1 /* 2 * Copyright (C) 2015 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.car.power; 18 19 import static android.car.hardware.power.CarPowerManager.STATE_PRE_SHUTDOWN_PREPARE; 20 import static android.car.hardware.power.CarPowerManager.STATE_SHUTDOWN_PREPARE; 21 import static android.car.hardware.power.PowerComponentUtil.FIRST_POWER_COMPONENT; 22 import static android.car.hardware.power.PowerComponentUtil.LAST_POWER_COMPONENT; 23 import static android.net.ConnectivityManager.TETHERING_WIFI; 24 25 import static com.android.car.hal.PowerHalService.BOOTUP_REASON_SYSTEM_ENTER_GARAGE_MODE; 26 import static com.android.car.internal.ExcludeFromCodeCoverageGeneratedReport.DUMP_INFO; 27 import static com.android.car.systeminterface.SystemInterface.SUSPEND_RESULT_ABORT; 28 import static com.android.car.systeminterface.SystemInterface.SUSPEND_RESULT_RETRY; 29 import static com.android.car.systeminterface.SystemInterface.SUSPEND_RESULT_SUCCESS; 30 31 import android.annotation.NonNull; 32 import android.annotation.Nullable; 33 import android.app.ActivityManager; 34 import android.automotive.power.internal.ICarPowerManagementDelegate; 35 import android.automotive.power.internal.ICarPowerManagementDelegateCallback; 36 import android.automotive.power.internal.PowerPolicyFailureReason; 37 import android.automotive.power.internal.PowerPolicyInitData; 38 import android.car.Car; 39 import android.car.CarOccupantZoneManager; 40 import android.car.ICarResultReceiver; 41 import android.car.builtin.app.ActivityManagerHelper; 42 import android.car.builtin.content.pm.PackageManagerHelper; 43 import android.car.builtin.os.BuildHelper; 44 import android.car.builtin.os.HandlerHelper; 45 import android.car.builtin.os.ServiceManagerHelper; 46 import android.car.builtin.os.SystemPropertiesHelper; 47 import android.car.builtin.os.TraceHelper; 48 import android.car.builtin.os.UserManagerHelper; 49 import android.car.builtin.util.EventLogHelper; 50 import android.car.builtin.util.Slogf; 51 import android.car.feature.FeatureFlags; 52 import android.car.feature.FeatureFlagsImpl; 53 import android.car.hardware.power.CarPowerManager; 54 import android.car.hardware.power.CarPowerPolicy; 55 import android.car.hardware.power.CarPowerPolicyFilter; 56 import android.car.hardware.power.ICarPower; 57 import android.car.hardware.power.ICarPowerPolicyListener; 58 import android.car.hardware.power.ICarPowerStateListener; 59 import android.car.hardware.power.PowerComponentUtil; 60 import android.car.remoteaccess.CarRemoteAccessManager; 61 import android.content.ComponentName; 62 import android.content.Context; 63 import android.content.Intent; 64 import android.content.res.Resources; 65 import android.frameworks.automotive.powerpolicy.internal.ICarPowerPolicySystemNotification; 66 import android.frameworks.automotive.powerpolicy.internal.PolicyState; 67 import android.hardware.automotive.vehicle.VehicleApPowerStateReport; 68 import android.hardware.automotive.vehicle.VehicleApPowerStateReq; 69 import android.hardware.automotive.vehicle.VehicleApPowerStateShutdownParam; 70 import android.hardware.display.DisplayManager; 71 import android.net.TetheringManager; 72 import android.net.TetheringManager.TetheringRequest; 73 import android.net.wifi.WifiManager; 74 import android.os.Binder; 75 import android.os.Handler; 76 import android.os.HandlerThread; 77 import android.os.IBinder; 78 import android.os.IInterface; 79 import android.os.Looper; 80 import android.os.Message; 81 import android.os.PowerManager; 82 import android.os.Process; 83 import android.os.RemoteCallbackList; 84 import android.os.RemoteException; 85 import android.os.SystemClock; 86 import android.os.SystemProperties; 87 import android.os.UserHandle; 88 import android.os.UserManager; 89 import android.util.ArraySet; 90 import android.util.AtomicFile; 91 import android.util.SparseArray; 92 import android.util.SparseBooleanArray; 93 import android.util.proto.ProtoOutputStream; 94 import android.view.Display; 95 96 import com.android.car.CarLocalServices; 97 import com.android.car.CarLog; 98 import com.android.car.CarOccupantZoneService; 99 import com.android.car.CarServiceBase; 100 import com.android.car.CarServiceUtils; 101 import com.android.car.CarStatsLogHelper; 102 import com.android.car.ICarImpl; 103 import com.android.car.R; 104 import com.android.car.hal.PowerHalService; 105 import com.android.car.hal.PowerHalService.BootupReason; 106 import com.android.car.hal.PowerHalService.PowerState; 107 import com.android.car.internal.ExcludeFromCodeCoverageGeneratedReport; 108 import com.android.car.internal.dep.Trace; 109 import com.android.car.internal.util.DebugUtils; 110 import com.android.car.internal.util.IndentingPrintWriter; 111 import com.android.car.internal.util.Lists; 112 import com.android.car.power.CarPowerDumpProto.CpmsStateProto; 113 import com.android.car.systeminterface.SystemInterface; 114 import com.android.car.user.CarUserNoticeService; 115 import com.android.car.user.CarUserService; 116 import com.android.car.user.UserHandleHelper; 117 import com.android.internal.annotations.GuardedBy; 118 import com.android.internal.annotations.VisibleForTesting; 119 import com.android.internal.util.Preconditions; 120 121 import org.xmlpull.v1.XmlPullParserException; 122 123 import java.io.BufferedReader; 124 import java.io.BufferedWriter; 125 import java.io.File; 126 import java.io.FileOutputStream; 127 import java.io.IOException; 128 import java.io.InputStream; 129 import java.io.InputStreamReader; 130 import java.io.OutputStreamWriter; 131 import java.lang.ref.WeakReference; 132 import java.nio.charset.StandardCharsets; 133 import java.util.ArrayList; 134 import java.util.Collection; 135 import java.util.LinkedList; 136 import java.util.List; 137 import java.util.Objects; 138 import java.util.Set; 139 import java.util.concurrent.CountDownLatch; 140 import java.util.concurrent.ExecutorService; 141 import java.util.concurrent.Executors; 142 import java.util.concurrent.Semaphore; 143 import java.util.concurrent.TimeUnit; 144 import java.util.concurrent.atomic.AtomicBoolean; 145 import java.util.concurrent.atomic.AtomicInteger; 146 import java.util.function.BiFunction; 147 import java.util.function.Consumer; 148 149 /** 150 * Power Management service class for cars. Controls the power states and interacts with other 151 * parts of the system to ensure its own state. 152 */ 153 public class CarPowerManagementService extends ICarPower.Stub implements 154 CarServiceBase, PowerHalService.PowerEventListener { 155 public static final String SILENT_MODE_FORCED_SILENT = 156 SilentModeHandler.SILENT_MODE_FORCED_SILENT; 157 public static final String SILENT_MODE_FORCED_NON_SILENT = 158 SilentModeHandler.SILENT_MODE_FORCED_NON_SILENT; 159 public static final String SILENT_MODE_NON_FORCED = SilentModeHandler.SILENT_MODE_NON_FORCED; 160 161 public static final long INVALID_TIMEOUT = -1L; 162 163 public static final int INVALID_NATIVE_LISTENER_CHANGE_ID = -1; 164 public static final int NO_WAKEUP_BY_TIMER = -1; 165 166 static final String TAG = CarLog.tagFor(CarPowerManagementService.class); 167 168 private static final String WIFI_STATE_FILENAME = "wifi_state"; 169 private static final String TETHERING_STATE_FILENAME = "tethering_state"; 170 private static final String COMPONENT_STATE_MODIFIED = "forcibly_disabled"; 171 private static final String COMPONENT_STATE_ORIGINAL = "original"; 172 private static final String KERNEL_BOOT_TIME_PROPERTY = "boot.car_kernel_boot_time"; 173 private static final String DEVICE_START_TIME_PROPERTY = "boot.car_device_start_time"; 174 // If Suspend to RAM fails, we retry with an exponential back-off: 175 // The wait interval will be 10 msec, 20 msec, 40 msec, ... 176 // Once the wait interval goes beyond 100 msec, it is fixed at 100 msec. 177 private static final long INITIAL_SUSPEND_RETRY_INTERVAL_MS = 10; 178 private static final long MAX_RETRY_INTERVAL_MS = 100; 179 // Minimum and maximum wait duration before the system goes into Suspend to RAM. 180 private static final long MIN_SUSPEND_WAIT_DURATION_MS = 0; 181 private static final long MAX_SUSPEND_WAIT_DURATION_MS = 3 * 60 * 1000; 182 183 private static final long CAR_POWER_MANAGEMENT_DAEMON_FIND_MARGINAL_TIME_MS = 300; 184 private static final long CAR_POWER_MANAGEMENT_DAEMON_BIND_RETRY_INTERVAL_MS = 500; 185 private static final int CAR_POWER_MANAGEMENT_DAEMON_BIND_MAX_RETRY = 10; 186 private static final long CAR_POWER_MANAGEMENT_DEFINITION_TIMEOUT_MS = 500; 187 // TODO(b/286303350): remove once power policy refactor complete, replace w/refactored version 188 private static final String CAR_POWER_POLICY_DAEMON_INTERFACE = 189 "android.frameworks.automotive.powerpolicy.internal.ICarPowerPolicySystemNotification/" 190 + "default"; 191 private static final String REFACTORED_CAR_POWER_MANAGEMENT_DAEMON_INTERFACE = 192 "android.automotive.power.internal.ICarPowerManagementDelegate/default"; 193 194 private static final int SHUTDOWN_POLLING_INTERVAL_DEFAULT_MS = 2000; 195 private static final int SHUTDOWN_POLLING_INTERVAL_MIN_MS = 1000; 196 private static final int SHUTDOWN_POLLING_INTERVAL_MAX_MS = 5000; 197 198 // maxGarageModeRunningDurationInSecs should be equal or greater than this. 15 min for now. 199 private static final int MIN_GARAGE_MODE_DURATION_MS = 15 * 60 * 1000; 200 201 // in secs 202 private static final String PROP_MAX_GARAGE_MODE_DURATION_OVERRIDE = 203 "android.car.garagemodeduration"; 204 // Constants for action on finish 205 private static final int ACTION_ON_FINISH_SHUTDOWN = 0; 206 private static final int ACTION_ON_FINISH_DEEP_SLEEP = 1; 207 private static final int ACTION_ON_FINISH_HIBERNATION = 2; 208 209 // Default timeout for listener completion during shutdown. 210 private static final int DEFAULT_COMPLETION_WAIT_TIMEOUT = 5_000; 211 212 // Default timeout for power policy change requests 213 private static final int DEFAULT_POWER_POLICY_REQUEST_TIMEOUT_MS = 5_000; 214 215 private static final int INDEX_WAIT_FOR_VHAL = 0; 216 private static final int INDEX_ON = 1; 217 218 private final Object mLock = new Object(); 219 private final Object mSimulationWaitObject = new Object(); 220 221 private final Context mContext; 222 private final PowerHalService mHal; 223 private final SystemInterface mSystemInterface; 224 private final HandlerThread mHandlerThread = CarServiceUtils.getHandlerThread( 225 getClass().getSimpleName()); 226 private final PowerHandler mHandler = new PowerHandler(mHandlerThread.getLooper(), this); 227 // TODO(b/409037873): replace a handler thread with a short-living thread. 228 private final PowerStateNotificationHandler mStateNotificationHandler = 229 new PowerStateNotificationHandler(CarServiceUtils.getHandlerThread( 230 PowerStateNotificationHandler.class.getSimpleName()).getLooper()); 231 private final HandlerThread mBroadcastHandlerThread = CarServiceUtils.getHandlerThread( 232 getClass().getSimpleName() + " broadcasts"); 233 private final Handler mBroadcastHandler = new Handler(mBroadcastHandlerThread.getLooper()); 234 // The listeners that complete simply by returning from onStateChanged() 235 private final PowerManagerCallbackList<ICarPowerStateListener> mPowerManagerListeners = 236 new PowerManagerCallbackList<>( 237 l -> CarPowerManagementService.this.doUnregisterListener(l)); 238 // The listeners that must indicate asynchronous completion by calling finished(). 239 private final PowerManagerCallbackList<ICarPowerStateListener> 240 mPowerManagerListenersWithCompletion = new PowerManagerCallbackList<>( 241 l -> CarPowerManagementService.this.doUnregisterListener(l)); 242 private final AtomicInteger mPowerChangeIdCounter = new AtomicInteger(0); 243 private final AtomicInteger mPolicyRequestIdCounter = new AtomicInteger(0); 244 // The internal listeners that must indicates asynchronous completion by calling 245 // completeStateChangeHandling(). Note that they are not binder objects. 246 @GuardedBy("mLock") 247 private final ArrayList<ICarPowerStateListener> mInternalPowerListeners = new ArrayList<>(); 248 249 @GuardedBy("mLock") 250 private final ArraySet<IBinder> mListenersWeAreWaitingFor = new ArraySet<>(); 251 @GuardedBy("mLock") 252 private final LinkedList<CpmsState> mPendingPowerStates = new LinkedList<>(); 253 @GuardedBy("mLock") 254 private final SparseArray<AsyncPolicyRequest> mRequestIdToPolicyRequest = new SparseArray<>(); 255 private final PolicyCallbackHelper mPolicyCallbackHelper = new PolicyCallbackHelper(); 256 private final UserManager mUserManager; 257 private final CarUserService mUserService; 258 private final WifiManager mWifiManager; 259 private final TetheringManager mTetheringManager; 260 private final AtomicFile mWifiStateFile; 261 private final AtomicFile mTetheringStateFile; 262 private final boolean mWifiAdjustmentForSuspend; 263 private boolean mShouldChangeSwap = true; 264 private long mCarServiceStartTimeAfterSuspend = 0; 265 266 // This is a temp work-around to reduce user switching delay after wake-up. 267 private final boolean mSwitchGuestUserBeforeSleep; 268 269 // CPMS tries to enter Suspend to RAM within the duration specified at 270 // mMaxSuspendWaitDurationMs. The default max duration is MAX_SUSPEND_WAIT_DRATION, and can be 271 // overridden by setting config_maxSuspendWaitDuration in an overrlay resource. 272 // The valid range is MIN_SUSPEND_WAIT_DRATION to MAX_SUSPEND_WAIT_DURATION. 273 private final long mMaxSuspendWaitDurationMs; 274 275 @GuardedBy("mSimulationWaitObject") 276 private boolean mWakeFromSimulatedSleep; 277 @GuardedBy("mSimulationWaitObject") 278 private boolean mInSimulatedDeepSleepMode; 279 @GuardedBy("mSimulationWaitObject") 280 private int mResumeDelayFromSimulatedSuspendSec = NO_WAKEUP_BY_TIMER; 281 @GuardedBy("mSimulationWaitObject") 282 private int mCancelDelayFromSimulatedSuspendSec = NO_WAKEUP_BY_TIMER; 283 @GuardedBy("mSimulationWaitObject") 284 private boolean mFreeMemoryBeforeSuspend; 285 286 @GuardedBy("mLock") 287 private CpmsState mCurrentState; 288 @GuardedBy("mLock") 289 private long mShutdownStartTime; 290 @GuardedBy("mLock") 291 private long mLastSleepEntryTime; 292 293 @GuardedBy("mLock") 294 private int mNextWakeupSec; 295 @GuardedBy("mLock") 296 private int mActionOnFinish; 297 @GuardedBy("mLock") 298 private boolean mShutdownOnNextSuspend; 299 @GuardedBy("mLock") 300 private boolean mShouldResumeUserService; 301 @GuardedBy("mLock") 302 private int mShutdownPrepareTimeMs = MIN_GARAGE_MODE_DURATION_MS; 303 @GuardedBy("mLock") 304 private int mShutdownPollingIntervalMs = SHUTDOWN_POLLING_INTERVAL_DEFAULT_MS; 305 @GuardedBy("mLock") 306 private boolean mRebootAfterGarageMode; 307 @GuardedBy("mLock") 308 private boolean mGarageModeShouldExitImmediately; 309 // TODO(b/286303350): remove once power policy refactor complete 310 @GuardedBy("mLock") 311 private ICarPowerPolicySystemNotification mCarPowerPolicyDaemon; 312 // TODO(b/286303350): rename "mCarPowerManagementDaemon" once power policy refactor complete 313 @GuardedBy("mLock") 314 private ICarPowerManagementDelegate mRefactoredCarPowerManagementDaemon; 315 @GuardedBy("mLock") 316 private boolean mConnectionInProgress; 317 private BinderHandler mBinderHandler; 318 private boolean mPowerPoliciesInitialized; 319 // TODO(b/286303350): remove after policy refactor, since daemon will be source of truth 320 @GuardedBy("mLock") 321 private String mCurrentPowerPolicyId; 322 // TODO(b/286303350): remove after policy refactor, since daemon will control power policy 323 @GuardedBy("mLock") 324 private String mPendingPowerPolicyId; 325 @GuardedBy("mLock") 326 private String mCurrentPowerPolicyGroupId; 327 @GuardedBy("mLock") 328 private boolean mIsPowerPolicyLocked; 329 // TODO(b/286303350): remove after policy refactor, since daemon will control power policy 330 @GuardedBy("mLock") 331 private boolean mHasControlOverDaemon; 332 private final CountDownLatch mPowerPolicyInitializationLatch = new CountDownLatch(1); 333 @GuardedBy("mLock") 334 private CarPowerPolicy mCurrentAccumulatedPowerPolicy = getInitialAccumulatedPowerPolicy(); 335 private final AtomicBoolean mIsListenerWaitingCancelled = new AtomicBoolean(false); 336 private final Semaphore mListenerCompletionSem = new Semaphore(/* permits= */ 0); 337 @GuardedBy("mLock") 338 private int mWaitingNativeListenerChangeId = INVALID_NATIVE_LISTENER_CHANGE_ID; 339 @GuardedBy("mLock") 340 @CarPowerManager.CarPowerState 341 private int mStateForCompletion = CarPowerManager.STATE_INVALID; 342 @GuardedBy("mLock") 343 @CarRemoteAccessManager.NextPowerState 344 private int mLastShutdownState = CarRemoteAccessManager.NEXT_POWER_STATE_OFF; 345 private final AtomicBoolean mIsReconnectionToPowerDaemon = new AtomicBoolean(false); 346 347 @GuardedBy("mLock") 348 @Nullable 349 private ICarResultReceiver mFactoryResetCallback; 350 @GuardedBy("mLock") 351 private boolean mIsEmergencyShutdown; 352 353 private final PowerManagerCallbackList<ICarPowerPolicyListener> mPowerPolicyListeners = 354 new PowerManagerCallbackList<>( 355 l -> CarPowerManagementService.this.mPowerPolicyListeners.unregister(l)); 356 357 private final PowerComponentHandler mPowerComponentHandler; 358 private final PolicyReader mPolicyReader = new PolicyReader(); 359 private final SilentModeHandler mSilentModeHandler; 360 private final ScreenOffHandler mScreenOffHandler; 361 362 // Allows for injecting feature flag values during testing 363 private FeatureFlags mFeatureFlags = new FeatureFlagsImpl(); 364 @GuardedBy("mSimulationWaitObject") 365 private boolean mBlockFromSimulatedCancelEvent; 366 367 @VisibleForTesting readPowerPolicyFromXml(InputStream inputStream)368 void readPowerPolicyFromXml(InputStream inputStream) 369 throws IOException, PolicyReader.PolicyXmlException, XmlPullParserException { 370 mPolicyReader.readPowerPolicyFromXml(inputStream); 371 Integer[] customComponents = 372 new Integer[mPolicyReader.getCustomComponents().values().size()]; 373 mPolicyReader.getCustomComponents().values().toArray(customComponents); 374 mPowerComponentHandler.registerCustomComponents(customComponents); 375 } 376 377 interface ActionOnDeath<T extends IInterface> { take(T listener)378 void take(T listener); 379 } 380 381 private static final class PowerManagerCallbackList<T extends IInterface> extends 382 RemoteCallbackList<T> { 383 private ActionOnDeath<T> mActionOnDeath; 384 PowerManagerCallbackList(ActionOnDeath<T> action)385 PowerManagerCallbackList(ActionOnDeath<T> action) { 386 mActionOnDeath = action; 387 } 388 389 /** 390 * Old version of {@link #onCallbackDied(E, Object)} that 391 * does not provide a cookie. 392 */ 393 @Override onCallbackDied(T listener)394 public void onCallbackDied(T listener) { 395 Slogf.i(TAG, "binderDied %s", listener.asBinder()); 396 mActionOnDeath.take(listener); 397 } 398 } 399 400 /** 401 * Builder for {@link android.car.power.CarPowerManagementService}. 402 */ 403 public static final class Builder { 404 private Context mContext; 405 private PowerHalService mPowerHalService; 406 private SystemInterface mSystemInterface; 407 private UserManager mUserManager; 408 private CarUserService mCarUserService; 409 private PowerComponentHandler mPowerComponentHandler; 410 private @Nullable IInterface mPowerManagementDaemon; 411 private @Nullable FeatureFlags mFeatureFlags; 412 private @Nullable ScreenOffHandler mScreenOffHandler; 413 private @Nullable String mSilentModeHwStatePath; 414 private @Nullable String mSilentModeKernelStatePath; 415 private @Nullable String mBootReason; 416 private Resources mResources; 417 private boolean mBuilt; 418 419 /** 420 * Sets the {@link Context}. 421 */ setContext(Context context)422 public Builder setContext(Context context) { 423 mContext = context; 424 return this; 425 } 426 427 /** 428 * Sets the {@link PowerHalService}. 429 */ setPowerHalService(PowerHalService powerHalService)430 public Builder setPowerHalService(PowerHalService powerHalService) { 431 mPowerHalService = powerHalService; 432 return this; 433 } 434 435 /** 436 * Sets the {@link SystemInterface}. 437 */ setSystemInterface(SystemInterface systemInterface)438 public Builder setSystemInterface(SystemInterface systemInterface) { 439 mSystemInterface = systemInterface; 440 return this; 441 } 442 443 /** 444 * Sets the {@link CarUserService}. 445 */ setCarUserService(CarUserService carUserService)446 public Builder setCarUserService(CarUserService carUserService) { 447 mCarUserService = carUserService; 448 return this; 449 } 450 451 /** 452 * Sets the {@link IInterface} for power management daemon. 453 */ setPowerManagementDaemon(@ullable IInterface powerManagementDaemon)454 public Builder setPowerManagementDaemon(@Nullable IInterface powerManagementDaemon) { 455 mPowerManagementDaemon = powerManagementDaemon; 456 return this; 457 } 458 459 /** 460 * Builds the object. 461 */ build()462 public CarPowerManagementService build() { 463 if (mBuilt) { 464 throw new IllegalStateException("Only allowed to be built once"); 465 } 466 mBuilt = true; 467 return new CarPowerManagementService(this); 468 } 469 470 /** 471 * Sets the {@link PowerComponentHandler}. 472 */ 473 @VisibleForTesting setPowerComponentHandler(PowerComponentHandler powerComponentHandler)474 public Builder setPowerComponentHandler(PowerComponentHandler powerComponentHandler) { 475 mPowerComponentHandler = powerComponentHandler; 476 return this; 477 } 478 479 /** 480 * Sets the {@link UserManager}. 481 */ 482 @VisibleForTesting setUserManager(UserManager userManager)483 public Builder setUserManager(UserManager userManager) { 484 mUserManager = userManager; 485 return this; 486 } 487 488 /** 489 * Sets the {@link FeatureFlags}. 490 */ 491 @VisibleForTesting setFeatureFlags(FeatureFlags featureFlags)492 public Builder setFeatureFlags(FeatureFlags featureFlags) { 493 mFeatureFlags = featureFlags; 494 return this; 495 } 496 497 /** 498 * Sets the {@link ScreenOffHandler}. 499 */ 500 @VisibleForTesting setScreenOffHandler(ScreenOffHandler screenOffHandler)501 public Builder setScreenOffHandler(ScreenOffHandler screenOffHandler) { 502 mScreenOffHandler = screenOffHandler; 503 return this; 504 } 505 506 /** 507 * Sets the silent mode hardware state path. 508 */ 509 @VisibleForTesting setSilentModeHwStatePath(String silentModeHwStatePath)510 public Builder setSilentModeHwStatePath(String silentModeHwStatePath) { 511 mSilentModeHwStatePath = silentModeHwStatePath; 512 return this; 513 } 514 515 /** 516 * Sets the silent mode kernel state path. 517 */ 518 @VisibleForTesting setSilentModeKernelStatePath(String silentModeKernelStatePath)519 public Builder setSilentModeKernelStatePath(String silentModeKernelStatePath) { 520 mSilentModeKernelStatePath = silentModeKernelStatePath; 521 return this; 522 } 523 524 /** 525 * Sets the boot reason. 526 */ 527 @VisibleForTesting setBootReason(String bootReason)528 public Builder setBootReason(String bootReason) { 529 mBootReason = bootReason; 530 return this; 531 } 532 533 /** 534 * Sets the {@link Resources}. 535 */ 536 @VisibleForTesting setResources(Resources resources)537 public Builder setResources(Resources resources) { 538 mResources = resources; 539 return this; 540 } 541 } 542 CarPowerManagementService(Context context, PowerHalService powerHalService, SystemInterface systemInterface, CarUserService carUserService, IInterface powerManagementDaemon)543 public CarPowerManagementService(Context context, PowerHalService powerHalService, 544 SystemInterface systemInterface, CarUserService carUserService, 545 IInterface powerManagementDaemon) { 546 this(new Builder().setContext(context).setPowerHalService(powerHalService) 547 .setSystemInterface(systemInterface).setCarUserService(carUserService) 548 .setPowerManagementDaemon(powerManagementDaemon)); 549 } 550 CarPowerManagementService(Builder builder)551 private CarPowerManagementService(Builder builder) { 552 mContext = Objects.requireNonNull(builder.mContext); 553 mHal = Objects.requireNonNull(builder.mPowerHalService); 554 mSystemInterface = Objects.requireNonNull(builder.mSystemInterface); 555 mUserManager = Objects.requireNonNullElseGet(builder.mUserManager, 556 () -> builder.mContext.getSystemService(UserManager.class)); 557 Resources resources = Objects.requireNonNullElseGet(builder.mResources, 558 () -> builder.mContext.getResources()); 559 mShutdownPrepareTimeMs = resources.getInteger( 560 R.integer.maxGarageModeRunningDurationInSecs) * 1000; 561 mShutdownPollingIntervalMs = 562 resources.getInteger(R.integer.config_shutdownPollingIntervalMs); 563 mSwitchGuestUserBeforeSleep = resources.getBoolean( 564 R.bool.config_switchGuestUserBeforeGoingSleep); 565 if (mShutdownPrepareTimeMs < MIN_GARAGE_MODE_DURATION_MS) { 566 Slogf.w(TAG, 567 "maxGarageModeRunningDurationInSecs smaller than minimum required, " 568 + "resource:%d(ms) while should exceed:%d(ms), Ignore resource.", 569 mShutdownPrepareTimeMs, MIN_GARAGE_MODE_DURATION_MS); 570 mShutdownPrepareTimeMs = MIN_GARAGE_MODE_DURATION_MS; 571 } 572 if (mShutdownPollingIntervalMs < SHUTDOWN_POLLING_INTERVAL_MIN_MS 573 || mShutdownPollingIntervalMs > SHUTDOWN_POLLING_INTERVAL_MAX_MS) { 574 Slogf.w(TAG, 575 "config_shutdownPollingIntervalMs(value = %d) is outside the valid range of %d " 576 + " to %d. Using the default value(%d).", 577 mShutdownPollingIntervalMs, SHUTDOWN_POLLING_INTERVAL_MIN_MS, 578 SHUTDOWN_POLLING_INTERVAL_MAX_MS, SHUTDOWN_POLLING_INTERVAL_DEFAULT_MS); 579 mShutdownPollingIntervalMs = SHUTDOWN_POLLING_INTERVAL_DEFAULT_MS; 580 } 581 mUserService = Objects.requireNonNull(builder.mCarUserService); 582 if (builder.mFeatureFlags != null) { 583 mFeatureFlags = builder.mFeatureFlags; 584 } 585 // In a real situation, this should be null. 586 IInterface powerManagementDaemon = builder.mPowerManagementDaemon; 587 if (mFeatureFlags.carPowerPolicyRefactoring()) { 588 mRefactoredCarPowerManagementDaemon = 589 (ICarPowerManagementDelegate) powerManagementDaemon; 590 mPowerPoliciesInitialized = false; 591 } else { 592 mCarPowerPolicyDaemon = (ICarPowerPolicySystemNotification) powerManagementDaemon; 593 if (powerManagementDaemon != null) { 594 // For testing purpose 595 mHasControlOverDaemon = true; 596 } 597 } 598 mWifiManager = mContext.getSystemService(WifiManager.class); 599 mTetheringManager = mContext.getSystemService(TetheringManager.class); 600 mWifiStateFile = new AtomicFile( 601 new File(mSystemInterface.getSystemCarDir(), WIFI_STATE_FILENAME)); 602 mTetheringStateFile = new AtomicFile( 603 new File(mSystemInterface.getSystemCarDir(), TETHERING_STATE_FILENAME)); 604 mWifiAdjustmentForSuspend = isWifiAdjustmentForSuspendConfig(); 605 mPowerComponentHandler = Objects.requireNonNullElseGet(builder.mPowerComponentHandler, 606 () -> new PowerComponentHandler(mContext, mSystemInterface)); 607 mSilentModeHandler = new SilentModeHandler(this, mFeatureFlags, 608 builder.mSilentModeHwStatePath, builder.mSilentModeKernelStatePath, 609 builder.mBootReason); 610 mMaxSuspendWaitDurationMs = Math.max(MIN_SUSPEND_WAIT_DURATION_MS, 611 Math.min(getMaxSuspendWaitDurationConfig(), MAX_SUSPEND_WAIT_DURATION_MS)); 612 mScreenOffHandler = Objects.requireNonNullElseGet(builder.mScreenOffHandler, () -> 613 new ScreenOffHandler(mContext, mSystemInterface, mHandler.getLooper())); 614 } 615 616 /** 617 * Overrides timers to keep testing time short. 618 * 619 * <p>Passing in {@code 0} resets the value to the default. 620 */ 621 @VisibleForTesting setShutdownTimersForTest(int pollingIntervalMs, int shutdownTimeoutMs)622 public void setShutdownTimersForTest(int pollingIntervalMs, int shutdownTimeoutMs) { 623 synchronized (mLock) { 624 mShutdownPollingIntervalMs = (pollingIntervalMs == 0) 625 ? SHUTDOWN_POLLING_INTERVAL_DEFAULT_MS : pollingIntervalMs; 626 mShutdownPrepareTimeMs = 627 (shutdownTimeoutMs == 0) ? MIN_GARAGE_MODE_DURATION_MS : shutdownTimeoutMs; 628 } 629 } 630 631 @VisibleForTesting getHandlerThread()632 protected HandlerThread getHandlerThread() { 633 return mHandlerThread; 634 } 635 636 @Override init()637 public void init() { 638 Trace.traceBegin(TraceHelper.TRACE_TAG_CAR_SERVICE, "init"); 639 mPolicyReader.init(mFeatureFlags); 640 mPowerComponentHandler.init(mPolicyReader.getCustomComponents()); 641 mHal.setListener(this); 642 mSystemInterface.init(this, mUserService); 643 mScreenOffHandler.init(); 644 if (mHal.isPowerStateSupported()) { 645 // Initialize CPMS in WAIT_FOR_VHAL state 646 onApPowerStateChange(CpmsState.WAIT_FOR_VHAL, CarPowerManager.STATE_WAIT_FOR_VHAL); 647 } else { 648 Slogf.w(TAG, "Vehicle hal does not support power state yet."); 649 onApPowerStateChange(CpmsState.ON, CarPowerManager.STATE_ON); 650 } 651 mSystemInterface.startDisplayStateMonitoring(); 652 connectToPowerManagementDaemon(); 653 Trace.traceEnd(TraceHelper.TRACE_TAG_CAR_SERVICE); 654 } 655 656 @Override release()657 public void release() { 658 if (mBinderHandler != null) { 659 mBinderHandler.unlinkToDeath(); 660 } 661 mPolicyCallbackHelper.setPolicyCallbackReady(false); 662 synchronized (mLock) { 663 clearWaitingForCompletion(/* clearQueue= */ false); 664 mCurrentState = null; 665 if (mFeatureFlags.carPowerPolicyRefactoring()) { 666 mRefactoredCarPowerManagementDaemon = null; 667 } else { 668 mCarPowerPolicyDaemon = null; 669 } 670 mHandler.cancelAll(); 671 mStateNotificationHandler.cancelAll(); 672 mListenersWeAreWaitingFor.clear(); 673 if (NativePowerNotificationsFlag.isFeatureSupported()) { 674 mWaitingNativeListenerChangeId = INVALID_NATIVE_LISTENER_CHANGE_ID; 675 } 676 } 677 // TODO(b/397787808): mIsReconnectionToPowerDaemon needs to be updated accordingly, or we 678 // should find a better way to handle crash recovery. 679 mSystemInterface.stopDisplayStateMonitoring(); 680 mPowerManagerListeners.kill(); 681 mPowerPolicyListeners.kill(); 682 forEachDisplay(mContext, mSystemInterface::releaseAllWakeLocks); 683 } 684 685 @Override 686 @ExcludeFromCodeCoverageGeneratedReport(reason = DUMP_INFO) dump(IndentingPrintWriter writer)687 public void dump(IndentingPrintWriter writer) { 688 synchronized (mLock) { 689 writer.println("*CarPowerManagementService*"); 690 writer.printf("mCurrentState: %s\n", mCurrentState); 691 writer.printf("mShutdownStartTime: %d\n", mShutdownStartTime); 692 writer.printf("mLastSleepEntryTime: %d\n", mLastSleepEntryTime); 693 writer.printf("mNextWakeupSec: %d\n", mNextWakeupSec); 694 writer.printf("mShutdownOnNextSuspend: %b\n", mShutdownOnNextSuspend); 695 writer.printf("mActionOnFinish: %s\n", actionOnFinishToString(mActionOnFinish)); 696 writer.printf("mShutdownPollingIntervalMs: %d\n", mShutdownPollingIntervalMs); 697 writer.printf("mShutdownPrepareTimeMs: %d\n", mShutdownPrepareTimeMs); 698 writer.printf("mRebootAfterGarageMode: %b\n", mRebootAfterGarageMode); 699 writer.printf("mSwitchGuestUserBeforeSleep: %b\n", mSwitchGuestUserBeforeSleep); 700 writer.printf("mCurrentPowerPolicyId: %s\n", mCurrentPowerPolicyId); 701 writer.printf("mPendingPowerPolicyId: %s\n", mPendingPowerPolicyId); 702 writer.printf("mCurrentPowerPolicyGroupId: %s\n", mCurrentPowerPolicyGroupId); 703 writer.printf("mIsPowerPolicyLocked: %b\n", mIsPowerPolicyLocked); 704 writer.printf("mMaxSuspendWaitDurationMs: %d\n", mMaxSuspendWaitDurationMs); 705 writer.printf("config_maxSuspendWaitDuration: %d\n", getMaxSuspendWaitDurationConfig()); 706 writer.printf("mWifiStateFile: %s\n", mWifiStateFile); 707 writer.printf("mTetheringStateFile: %s\n", mTetheringStateFile); 708 writer.printf("mWifiAdjustmentForSuspend: %b\n", mWifiAdjustmentForSuspend); 709 writer.printf("# of power policy change listener: %d\n", 710 mPowerPolicyListeners.getRegisteredCallbackCount()); 711 writer.printf("mFactoryResetCallback: %s\n", mFactoryResetCallback); 712 writer.printf("mIsListenerWaitingCancelled: %b\n", mIsListenerWaitingCancelled.get()); 713 writer.printf("kernel support S2R: %b\n", 714 mSystemInterface.isSystemSupportingDeepSleep()); 715 writer.printf("kernel support S2D: %b\n", 716 mSystemInterface.isSystemSupportingHibernation()); 717 writer.printf("mLastShutdownState: %d\n", mLastShutdownState); 718 writer.printf("Daemon ready for callback: %b\n", 719 mPolicyCallbackHelper.isPolicyCallbackReady()); 720 if (mFeatureFlags.stopProcessBeforeSuspendToDisk()) { 721 writer.printf("Suspend to disk importance level: %d\n", getS2dImportanceLevel()); 722 } 723 } 724 725 synchronized (mSimulationWaitObject) { 726 writer.printf("mWakeFromSimulatedSleep: %b\n", mWakeFromSimulatedSleep); 727 writer.printf("mInSimulatedDeepSleepMode: %b\n", mInSimulatedDeepSleepMode); 728 writer.printf("mResumeDelayFromSimulatedSuspendSec: %d\n", 729 mResumeDelayFromSimulatedSuspendSec); 730 writer.printf("mFreeMemoryBeforeSuspend: %b\n", mFreeMemoryBeforeSuspend); 731 } 732 writer.printf("Kernel boot time property: %d", SystemPropertiesHelper.getLong( 733 KERNEL_BOOT_TIME_PROPERTY, /* defaultVal= */0L)); 734 writer.printf("Device start time property: %d", SystemPropertiesHelper.getLong( 735 DEVICE_START_TIME_PROPERTY, /* defaultVal= */0L)); 736 737 mPolicyReader.dump(writer); 738 mPowerComponentHandler.dump(writer); 739 mSilentModeHandler.dump(writer); 740 mScreenOffHandler.dump(writer); 741 } 742 743 @Override 744 @ExcludeFromCodeCoverageGeneratedReport(reason = DUMP_INFO) dumpProto(ProtoOutputStream proto)745 public void dumpProto(ProtoOutputStream proto) { 746 synchronized (mLock) { 747 long currentStateToken = proto.start(CarPowerDumpProto.CURRENT_STATE); 748 proto.write(CpmsStateProto.CAN_POSTPONE, mCurrentState.mCanPostpone); 749 proto.write(CpmsStateProto.CAR_POWER_MANAGER_STATE, 750 mCurrentState.mCarPowerStateListenerState); 751 proto.write(CpmsStateProto.SHUTDOWN_TYPE, mCurrentState.mShutdownType); 752 proto.write(CpmsStateProto.STATE, mCurrentState.mState); 753 proto.write(CpmsStateProto.STATE_NAME, mCurrentState.stateToString()); 754 proto.end(currentStateToken); 755 proto.write(CarPowerDumpProto.SHUTDOWN_START_TIME, mShutdownStartTime); 756 proto.write(CarPowerDumpProto.LAST_SLEEP_ENTRY_TIME, mLastSleepEntryTime); 757 proto.write(CarPowerDumpProto.NEXT_WAKEUP_SEC, mNextWakeupSec); 758 proto.write(CarPowerDumpProto.SHUTDOWN_ON_NEXT_SUSPEND, mShutdownOnNextSuspend); 759 proto.write( 760 CarPowerDumpProto.ACTION_ON_FINISH, actionOnFinishToString(mActionOnFinish)); 761 proto.write(CarPowerDumpProto.SHUTDOWN_POLLING_INTERVAL_MS, mShutdownPollingIntervalMs); 762 proto.write(CarPowerDumpProto.SHUTDOWN_PREPARE_TIME_MS, mShutdownPrepareTimeMs); 763 proto.write(CarPowerDumpProto.REBOOT_AFTER_GARAGE_MODE, mRebootAfterGarageMode); 764 proto.write( 765 CarPowerDumpProto.SWITCH_GUEST_USER_BEFORE_SLEEP, mSwitchGuestUserBeforeSleep); 766 proto.write(CarPowerDumpProto.CURRENT_POWER_POLICY_ID, mCurrentPowerPolicyId); 767 proto.write(CarPowerDumpProto.PENDING_POWER_POLICY_ID, mPendingPowerPolicyId); 768 proto.write( 769 CarPowerDumpProto.CURRENT_POWER_POLICY_GROUP_ID, mCurrentPowerPolicyGroupId); 770 proto.write(CarPowerDumpProto.IS_POWER_POLICY_LOCKED, mIsPowerPolicyLocked); 771 proto.write(CarPowerDumpProto.MAX_SUSPEND_WAIT_DURATION_MS, mMaxSuspendWaitDurationMs); 772 proto.write(CarPowerDumpProto.MAX_SUSPEND_WAIT_DURATION_CONFIG, 773 getMaxSuspendWaitDurationConfig()); 774 proto.write(CarPowerDumpProto.WIFI_STATE_FILE, mWifiStateFile.toString()); 775 proto.write(CarPowerDumpProto.TETHERING_STATE_FILE, mTetheringStateFile.toString()); 776 proto.write(CarPowerDumpProto.WIFI_ADJUSTMENT_FOR_SUSPEND, mWifiAdjustmentForSuspend); 777 proto.write(CarPowerDumpProto.POWER_POLICY_LISTENERS, 778 mPowerPolicyListeners.getRegisteredCallbackCount()); 779 proto.write(CarPowerDumpProto.FACTORY_RESET_CALLBACK, 780 mFactoryResetCallback != null ? mFactoryResetCallback.toString() : ""); 781 proto.write(CarPowerDumpProto.IS_LISTENER_WAITING_CANCELLED, 782 mIsListenerWaitingCancelled.get()); 783 proto.write(CarPowerDumpProto.KERNEL_SUPPORTS_DEEP_SLEEP, 784 mSystemInterface.isSystemSupportingDeepSleep()); 785 proto.write(CarPowerDumpProto.KERNEL_SUPPORTS_HIBERNATION, 786 mSystemInterface.isSystemSupportingHibernation()); 787 } 788 789 synchronized (mSimulationWaitObject) { 790 proto.write(CarPowerDumpProto.WAKE_FROM_SIMULATED_SLEEP, mWakeFromSimulatedSleep); 791 proto.write(CarPowerDumpProto.IN_SIMULATED_DEEP_SLEEP_MODE, mInSimulatedDeepSleepMode); 792 proto.write(CarPowerDumpProto.RESUME_DELAY_FROM_SIMULATED_SUSPEND_SEC, 793 mResumeDelayFromSimulatedSuspendSec); 794 proto.write(CarPowerDumpProto.FREE_MEMORY_BEFORE_SUSPEND, mFreeMemoryBeforeSuspend); 795 } 796 797 mPolicyReader.dumpProto(proto); 798 mPowerComponentHandler.dumpProto(proto); 799 mSilentModeHandler.dumpProto(proto); 800 mScreenOffHandler.dumpProto(proto); 801 } 802 803 @Override onApPowerStateChange(PowerState state)804 public void onApPowerStateChange(PowerState state) { 805 Trace.traceBegin(TraceHelper.TRACE_TAG_CAR_SERVICE, "onApPowerStateChange"); 806 EventLogHelper.writeCarPowerManagerStateRequest(state.mState, state.mParam); 807 synchronized (mLock) { 808 mPendingPowerStates.addFirst(new CpmsState(state)); 809 mLock.notifyAll(); 810 } 811 mHandler.handlePowerStateChange(); 812 Trace.traceEnd(TraceHelper.TRACE_TAG_CAR_SERVICE); 813 } 814 815 @VisibleForTesting setStateForWakeUp()816 void setStateForWakeUp() { 817 mSilentModeHandler.init(); 818 synchronized (mLock) { 819 mShouldResumeUserService = true; 820 } 821 handleWaitForVhal(new CpmsState(CpmsState.WAIT_FOR_VHAL, 822 CarPowerManager.STATE_WAIT_FOR_VHAL, /* canPostpone= */ false)); 823 Slogf.d(TAG, 824 "setStateForTesting(): mShouldResumeUserService is set to false and power state " 825 + "is switched " 826 + "to Wait For Vhal"); 827 } 828 829 /** 830 * Initiate state change from CPMS directly. 831 */ onApPowerStateChange(int apState, @CarPowerManager.CarPowerState int carPowerStateListenerState)832 private void onApPowerStateChange(int apState, 833 @CarPowerManager.CarPowerState int carPowerStateListenerState) { 834 Trace.traceBegin(TraceHelper.TRACE_TAG_CAR_SERVICE, 835 "onApPowerStateChange_internally_triggered"); 836 CpmsState newState = new CpmsState(apState, carPowerStateListenerState, 837 /* canPostpone= */ false); 838 BiFunction<CpmsState, CpmsState, Boolean> eventFilter = null; 839 840 // We are ready to shut down. Suppress this transition if 841 // there is a request to cancel the shutdown (WAIT_FOR_VHAL). 842 // Completely ignore this WAIT_FOR_FINISH 843 if (newState.mState == CpmsState.WAIT_FOR_FINISH) { 844 eventFilter = (stateToAdd, pendingSate) -> 845 stateToAdd.mState == CpmsState.WAIT_FOR_FINISH 846 && pendingSate.mState == CpmsState.WAIT_FOR_VHAL; 847 } 848 849 // Check if there is another pending SHUTDOWN_PREPARE. 850 // This could happen, when another SHUTDOWN_PREPARE request is received from VHAL 851 // while notifying PRE_SHUTDOWN_PREPARE. 852 // If SHUTDOWN_PREPARE request already exist in the queue, and it skips Garage Mode, 853 // then newState is ignored . 854 if (newState.mState == CpmsState.SHUTDOWN_PREPARE) { 855 eventFilter = (stateToAdd, pendingState) -> 856 pendingState.mState == CpmsState.SHUTDOWN_PREPARE 857 && !pendingState.mCanPostpone 858 && pendingState.mCarPowerStateListenerState 859 == STATE_PRE_SHUTDOWN_PREPARE; 860 } 861 862 synchronized (mLock) { 863 // If eventFilter exists, lets check if event that satisfies filter is in queue. 864 if (eventFilter != null) { 865 for (int idx = 0; idx < mPendingPowerStates.size(); idx++) { 866 CpmsState pendingState = mPendingPowerStates.get(idx); 867 if (eventFilter.apply(newState, pendingState)) { 868 Trace.traceEnd(TraceHelper.TRACE_TAG_CAR_SERVICE); 869 return; 870 } 871 } 872 } 873 mPendingPowerStates.addFirst(newState); 874 mLock.notifyAll(); 875 } 876 mHandler.handlePowerStateChange(); 877 Trace.traceEnd(TraceHelper.TRACE_TAG_CAR_SERVICE); 878 } 879 doHandlePowerStateChange()880 private void doHandlePowerStateChange() { 881 CpmsState newState; 882 CpmsState prevState; 883 synchronized (mLock) { 884 prevState = mCurrentState; 885 newState = mPendingPowerStates.pollFirst(); 886 if (newState == null) { 887 Slogf.w(TAG, "No more power state to process"); 888 return; 889 } 890 Slogf.i(TAG, "doHandlePowerStateChange: newState=%s", newState.name()); 891 if (!needPowerStateChangeLocked(newState)) { 892 // We may need to process the pending power state request. 893 if (!mPendingPowerStates.isEmpty()) { 894 Slogf.i(TAG, "There is a pending power state change request. requesting the " 895 + "processing..."); 896 mHandler.handlePowerStateChange(); 897 } 898 return; 899 } 900 901 // now real power change happens. Whatever was queued before should be all cancelled. 902 mPendingPowerStates.clear(); 903 904 // Received updated SHUTDOWN_PREPARE there could be several reasons for that 905 // 1. CPMS is in SHUTDOWN_PREPARE, and received state change to perform transition 906 // from PRE_SHUTDOWN_PREPARE into SHUTDOWN_PREPARE 907 // 2. New SHUTDOWN_PREPARE request is received, and it is different from existing one. 908 if (newState.mState == CpmsState.SHUTDOWN_PREPARE && newState.mState == prevState.mState 909 && newState.mCarPowerStateListenerState == STATE_PRE_SHUTDOWN_PREPARE) { 910 // Nothing to do here, skipping clearing completion queue 911 } else { 912 clearWaitingForCompletion(/* clearQueue= */ false); 913 } 914 915 mCurrentState = newState; 916 } 917 mHandler.cancelProcessingComplete(); 918 if (mFeatureFlags.carPowerPolicyRefactoring()) { 919 mStateNotificationHandler.notifyPowerStateChange(newState.mCarPowerStateListenerState); 920 } 921 922 Slogf.i(TAG, "setCurrentState %s", newState); 923 CarStatsLogHelper.logPowerState(newState.mState); 924 EventLogHelper.writeCarPowerManagerStateChange(newState.mState); 925 switch (newState.mState) { 926 case CpmsState.WAIT_FOR_VHAL: 927 handleWaitForVhal(newState); 928 break; 929 case CpmsState.ON: 930 handleOn(); 931 break; 932 case CpmsState.SHUTDOWN_PREPARE: 933 handleShutdownPrepare(newState, prevState); 934 break; 935 case CpmsState.SIMULATE_SLEEP: 936 case CpmsState.SIMULATE_HIBERNATION: 937 simulateShutdownPrepare(newState, prevState); 938 break; 939 case CpmsState.WAIT_FOR_FINISH: 940 handleWaitForFinish(newState); 941 break; 942 case CpmsState.SUSPEND: 943 // Received FINISH from VHAL 944 handleFinish(); 945 break; 946 default: 947 // Illegal state 948 // TODO(b/202414427): Add handling of illegal state 949 break; 950 } 951 } 952 notifyPowerStateChangeToDaemon(@arPowerManager.CarPowerState int newState, long expirationTimeMs)953 private void notifyPowerStateChangeToDaemon(@CarPowerManager.CarPowerState int newState, 954 long expirationTimeMs) { 955 String powerStateName = powerStateToString(newState); 956 Slogf.i(TAG, "Notifying CPPD of power state (%s) with expiration duration of %d ms", 957 powerStateToString(newState), expirationTimeMs); 958 959 ICarPowerManagementDelegate daemon; 960 synchronized (mLock) { 961 daemon = mRefactoredCarPowerManagementDaemon; 962 } 963 if (daemon == null) { 964 Slogf.e(TAG, "Failed to notify car power management daemon of power state change " 965 + "to %s, daemon unavailable", powerStateName); 966 return; 967 } 968 int changeId = mPowerChangeIdCounter.getAndIncrement(); 969 if (isCompletionAllowed(newState) 970 && newState != CarPowerManager.STATE_SHUTDOWN_PREPARE) { 971 synchronized (mLock) { 972 mWaitingNativeListenerChangeId = changeId; 973 } 974 } 975 try { 976 daemon.notifyPowerStateChange(changeId, newState, expirationTimeMs); 977 } catch (IllegalArgumentException | SecurityException | RemoteException e) { 978 Slogf.e(TAG, e, "Failed to notify daemon of power state(%s)", powerStateName); 979 synchronized (mLock) { 980 // If an exception occurs, no reason to wait on native listener completion 981 mWaitingNativeListenerChangeId = INVALID_NATIVE_LISTENER_CHANGE_ID; 982 } 983 } 984 } 985 handleWaitForVhal(CpmsState state)986 private void handleWaitForVhal(CpmsState state) { 987 @CarPowerManager.CarPowerState int carPowerStateListenerState = 988 state.mCarPowerStateListenerState; 989 // TODO(b/177478420): Restore Wifi, Audio, Location, and Bluetooth, if they are artificially 990 // modified for S2R. 991 mSilentModeHandler.querySilentModeHwState(); 992 993 if (!mFeatureFlags.carPowerPolicyRefactoring()) { 994 applyDefaultPowerPolicyForState(CarPowerManager.STATE_WAIT_FOR_VHAL, 995 PolicyReader.POWER_POLICY_ID_INITIAL_ON); 996 if (!mSilentModeHandler.isSilentMode()) { 997 cancelPreemptivePowerPolicy(); 998 } 999 } 1000 1001 sendPowerManagerEvent(carPowerStateListenerState, INVALID_TIMEOUT); 1002 // Inspect CarPowerStateListenerState to decide which message to send via VHAL 1003 int lastShutdownState = CarRemoteAccessManager.NEXT_POWER_STATE_OFF; 1004 switch (carPowerStateListenerState) { 1005 case CarPowerManager.STATE_WAIT_FOR_VHAL: 1006 lastShutdownState = CarRemoteAccessManager.NEXT_POWER_STATE_OFF; 1007 mHal.sendWaitForVhal(); 1008 break; 1009 case CarPowerManager.STATE_SHUTDOWN_CANCELLED: 1010 synchronized (mLock) { 1011 mShutdownOnNextSuspend = false; // This cancels the "NextSuspend" 1012 mIsEmergencyShutdown = false; // TODO add cancel test 1013 } 1014 mHal.sendShutdownCancel(); 1015 Slogf.d(TAG, "reset mIsEmergencyShutdown"); 1016 break; 1017 case CarPowerManager.STATE_SUSPEND_EXIT: 1018 lastShutdownState = CarRemoteAccessManager.NEXT_POWER_STATE_SUSPEND_TO_RAM; 1019 mHal.sendSleepExit(); 1020 break; 1021 case CarPowerManager.STATE_HIBERNATION_EXIT: 1022 lastShutdownState = CarRemoteAccessManager.NEXT_POWER_STATE_SUSPEND_TO_DISK; 1023 mHal.sendHibernationExit(); 1024 break; 1025 default: 1026 Slogf.w(TAG, "Invalid action when handling wait for VHAL: %d", 1027 carPowerStateListenerState); 1028 break; 1029 } 1030 synchronized (mLock) { 1031 mLastShutdownState = lastShutdownState; 1032 } 1033 if (mWifiAdjustmentForSuspend) { 1034 restoreWifiFully(); 1035 } 1036 } 1037 updateCarUserNoticeServiceIfNecessary()1038 private void updateCarUserNoticeServiceIfNecessary() { 1039 try { 1040 int currentUserId = ActivityManager.getCurrentUser(); 1041 UserHandleHelper userHandleHelper = new UserHandleHelper(mContext, mUserManager); 1042 UserHandle currentUser = userHandleHelper.getExistingUserHandle(currentUserId); 1043 CarUserNoticeService carUserNoticeService = 1044 CarLocalServices.getService(CarUserNoticeService.class); 1045 if (currentUser != null && userHandleHelper.isGuestUser(currentUser) 1046 && carUserNoticeService != null) { 1047 Slogf.i(TAG, "Car user notice service will ignore all messages before user " 1048 + "switch."); 1049 Intent intent = new Intent(); 1050 intent.setComponent(ComponentName.unflattenFromString( 1051 mContext.getResources().getString(R.string.continuousBlankActivity))); 1052 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 1053 mContext.startActivityAsUser(intent, UserHandle.CURRENT); 1054 carUserNoticeService.ignoreUserNotice(currentUserId); 1055 } 1056 } catch (Exception e) { 1057 Slogf.w(TAG, e, "Cannot ignore user notice for current user"); 1058 } 1059 } 1060 1061 @VisibleForTesting handleOn()1062 void handleOn() { 1063 if (factoryResetIfNeeded()) return; 1064 1065 // If current user is a Guest User, we want to inform CarUserNoticeService not to show 1066 // notice for current user, and show user notice only for the target user. 1067 if (!mSwitchGuestUserBeforeSleep) { 1068 updateCarUserNoticeServiceIfNecessary(); 1069 } 1070 1071 if (!mFeatureFlags.carPowerPolicyRefactoring()) { 1072 if (!mSilentModeHandler.isSilentMode()) { 1073 cancelPreemptivePowerPolicy(); 1074 } 1075 applyDefaultPowerPolicyForState(VehicleApPowerStateReport.ON, 1076 PolicyReader.POWER_POLICY_ID_ALL_ON); 1077 } 1078 1079 sendPowerManagerEvent(CarPowerManager.STATE_ON, INVALID_TIMEOUT); 1080 1081 mHal.sendOn(); 1082 1083 synchronized (mLock) { 1084 if (!mShouldResumeUserService) { 1085 Slogf.d(TAG, "handleOn(): called on boot"); 1086 return; 1087 } else { 1088 mShouldResumeUserService = false; 1089 } 1090 } 1091 1092 try { 1093 mUserService.onResume(); 1094 } catch (Exception e) { 1095 Slogf.e(TAG, e, "Could not switch user on resume"); 1096 } 1097 } 1098 factoryResetIfNeeded()1099 private boolean factoryResetIfNeeded() { 1100 ICarResultReceiver callback; 1101 synchronized (mLock) { 1102 if (mFactoryResetCallback == null) return false; 1103 callback = mFactoryResetCallback; 1104 } 1105 1106 try { 1107 Slogf.i(TAG, "Factory resetting as it was delayed by user"); 1108 callback.send(/* resultCode= */ 0, /* resultData= */ null); 1109 return true; 1110 } catch (Exception e) { 1111 Slogf.wtf(TAG, e, "Should have factory reset, but failed"); 1112 return false; 1113 } 1114 } 1115 1116 // TODO(b/286303350): remove once power policy refactor is complete, CPPD will handle applying 1117 // default power policies according to state applyDefaultPowerPolicyForState(@arPowerManager.CarPowerState int state, @Nullable String fallbackPolicyId)1118 private void applyDefaultPowerPolicyForState(@CarPowerManager.CarPowerState int state, 1119 @Nullable String fallbackPolicyId) { 1120 Slogf.i(TAG, "Applying the default power policy for %s", powerStateToString(state)); 1121 CarPowerPolicy policy; 1122 synchronized (mLock) { 1123 policy = mPolicyReader 1124 .getDefaultPowerPolicyForState(mCurrentPowerPolicyGroupId, state); 1125 } 1126 if (policy == null && fallbackPolicyId == null) { 1127 Slogf.w(TAG, "No default power policy for %s is found", powerStateToString(state)); 1128 return; 1129 } 1130 String policyId = policy == null ? fallbackPolicyId : policy.getPolicyId(); 1131 applyPowerPolicy(policyId, /* delayNotification= */ false, /* upToDaemon= */ true, 1132 /* force= */ false); 1133 } 1134 1135 /** 1136 * Sets the callback used to factory reset the device on resume when the user delayed it. 1137 */ setFactoryResetCallback(ICarResultReceiver callback)1138 public void setFactoryResetCallback(ICarResultReceiver callback) { 1139 synchronized (mLock) { 1140 mFactoryResetCallback = callback; 1141 } 1142 } 1143 1144 /** 1145 * Tells Garage Mode if it should run normally, or just 1146 * exit immediately without indicating 'idle' 1147 * @return True if no idle jobs should be run 1148 * @hide 1149 */ garageModeShouldExitImmediately()1150 public boolean garageModeShouldExitImmediately() { 1151 synchronized (mLock) { 1152 return mGarageModeShouldExitImmediately; 1153 } 1154 } 1155 1156 /** 1157 * This method is required for testing 1158 * Gets {@code PolicyReader} that reads {@code power_policy.xml}. 1159 * @return {@link PolicyReader} 1160 */ 1161 @VisibleForTesting getPolicyReader()1162 public PolicyReader getPolicyReader() { 1163 return mPolicyReader; 1164 } 1165 handleShutdownPrepare(CpmsState currentState, CpmsState prevState)1166 private void handleShutdownPrepare(CpmsState currentState, CpmsState prevState) { 1167 switch (currentState.mCarPowerStateListenerState) { 1168 case CarPowerManager.STATE_PRE_SHUTDOWN_PREPARE: 1169 updateShutdownPrepareStatus(currentState); 1170 boolean isComplete = false; 1171 if (prevState.mCarPowerStateListenerState == STATE_SHUTDOWN_PREPARE) { 1172 // Received request to update SHUTDOWN target 1173 currentState = new CpmsState(currentState.mState, 1174 prevState.mCarPowerStateListenerState, 1175 prevState.mCanPostpone, currentState.mShutdownType); 1176 synchronized (mLock) { 1177 mCurrentState = currentState; 1178 isComplete = arePowerStateChangeListenersCompleteLocked(); 1179 } 1180 if (!isComplete) { 1181 if (garageModeShouldExitImmediately()) { 1182 Slogf.e(TAG, "Received 2nd shutdown request. Waiting for listeners is " 1183 + "not allowed. Clearing listeners."); 1184 clearWaitingForCompletion(/* clearQueue= */ true); 1185 } else { 1186 Slogf.e(TAG, "Received 2nd shutdown request. Waiting for listeners to " 1187 + "complete."); 1188 } 1189 } else { 1190 // new shutdown prepare request can interrupt completion of shutdown prepare 1191 // call handler to complete it - this may result in 2nd call 1192 // to finishShutdownPrepare() 1193 Slogf.e(TAG, 1194 "Received 2nd shutdown request after listeners were completed"); 1195 finishShutdownPrepare(); 1196 } 1197 } else if (prevState.mCarPowerStateListenerState == STATE_PRE_SHUTDOWN_PREPARE) { 1198 synchronized (mLock) { 1199 isComplete = arePowerStateChangeListenersCompleteLocked(); 1200 } 1201 // Update of state occurred while in PRE_SHUTDOWN_PREPARE 1202 if (isComplete) { 1203 handleCoreShutdownPrepare(); 1204 } else { 1205 // PRE_SHUTDOWN_PREPARE is still being processed, no actions required 1206 Slogf.e(TAG, 1207 "Received 2nd shutdown request. Waiting for listener" 1208 + " to complete"); 1209 return; 1210 } 1211 } else { 1212 handlePreShutdownPrepare(); 1213 } 1214 break; 1215 case CarPowerManager.STATE_SHUTDOWN_PREPARE: 1216 handleCoreShutdownPrepare(); 1217 break; 1218 default: 1219 Slogf.w(TAG, "Not supported listener state(%d)", 1220 currentState.mCarPowerStateListenerState); 1221 } 1222 } 1223 updateShutdownPrepareStatus(CpmsState newState)1224 private void updateShutdownPrepareStatus(CpmsState newState) { 1225 // Shutdown on finish if the system doesn't support deep sleep/hibernation 1226 // or doesn't allow it. 1227 synchronized (mLock) { 1228 if (mShutdownOnNextSuspend || ( 1229 newState.mShutdownType == PowerState.SHUTDOWN_TYPE_POWER_OFF 1230 || newState.mShutdownType == PowerState.SHUTDOWN_TYPE_EMERGENCY)) { 1231 mActionOnFinish = ACTION_ON_FINISH_SHUTDOWN; 1232 } else if (newState.mShutdownType == PowerState.SHUTDOWN_TYPE_DEEP_SLEEP) { 1233 boolean isDeepSleepOnFinish = 1234 isDeepSleepAvailable() || newState.mState == CpmsState.SIMULATE_SLEEP; 1235 mActionOnFinish = isDeepSleepOnFinish ? ACTION_ON_FINISH_DEEP_SLEEP 1236 : ACTION_ON_FINISH_SHUTDOWN; 1237 } else if (newState.mShutdownType == PowerState.SHUTDOWN_TYPE_HIBERNATION) { 1238 boolean isHibernationOnFinish = isHibernationAvailable() 1239 || newState.mState == CpmsState.SIMULATE_HIBERNATION; 1240 mActionOnFinish = isHibernationOnFinish ? ACTION_ON_FINISH_HIBERNATION 1241 : ACTION_ON_FINISH_SHUTDOWN; 1242 } else { 1243 Slogf.wtf(TAG, "handleShutdownPrepare - incorrect state " + newState); 1244 } 1245 mGarageModeShouldExitImmediately = !newState.mCanPostpone; 1246 if (!mIsEmergencyShutdown) { 1247 mIsEmergencyShutdown = newState.mShutdownType == PowerState.SHUTDOWN_TYPE_EMERGENCY; 1248 Slogf.d(TAG, "set mIsEmergencyShutdown to " + mIsEmergencyShutdown); 1249 } else { 1250 // Emergency shutdown can be cancelled only via SHUTDOWN_CANCEL request"); 1251 Slogf.d(TAG, "mIsEmergencyShutdown is already set"); 1252 } 1253 } 1254 } 1255 handlePreShutdownPrepare()1256 private void handlePreShutdownPrepare() { 1257 int intervalMs; 1258 long timeoutMs; 1259 synchronized (mLock) { 1260 intervalMs = mShutdownPollingIntervalMs; 1261 Slogf.i(TAG, mGarageModeShouldExitImmediately 1262 ? "starting shutdown prepare without Garage Mode" 1263 : "starting shutdown prepare with Garage Mode"); 1264 1265 // in case of emergency shutdown CPMS will not wait for 1266 timeoutMs = mIsEmergencyShutdown ? 0 : getPreShutdownPrepareTimeoutConfig(); 1267 } 1268 1269 int state = CarPowerManager.STATE_PRE_SHUTDOWN_PREPARE; 1270 sendPowerManagerEvent(state, timeoutMs); 1271 Runnable taskAtCompletion = () -> { 1272 // The next power state is still SHUTDOWN_PREPARE, and the listener state is 1273 // SHUTDOWN_PREPARE. 1274 Slogf.i(TAG, "All listeners completed (or timed out) for %s", 1275 powerStateToString(state)); 1276 onApPowerStateChange(CpmsState.SHUTDOWN_PREPARE, 1277 CarPowerManager.STATE_SHUTDOWN_PREPARE); 1278 }; 1279 1280 waitForCompletionWithShutdownPostpone(state, timeoutMs, taskAtCompletion, intervalMs); 1281 } 1282 handleCoreShutdownPrepare()1283 private void handleCoreShutdownPrepare() { 1284 Slogf.i(TAG, "Handling core part of shutdown prepare"); 1285 doShutdownPrepare(); 1286 } 1287 1288 // Simulates system shutdown to suspend simulateShutdownPrepare(CpmsState newState, CpmsState oldState)1289 private void simulateShutdownPrepare(CpmsState newState, CpmsState oldState) { 1290 Slogf.i(TAG, "Simulating shutdown prepare"); 1291 handleShutdownPrepare(newState, oldState); 1292 } 1293 doShutdownPrepare()1294 private void doShutdownPrepare() { 1295 long timeoutMs; 1296 int intervalMs; 1297 boolean isEmergencyShutdown; 1298 synchronized (mLock) { 1299 timeoutMs = mShutdownPrepareTimeMs; 1300 intervalMs = mShutdownPollingIntervalMs; 1301 mShutdownStartTime = SystemClock.elapsedRealtime(); 1302 isEmergencyShutdown = mIsEmergencyShutdown; 1303 } 1304 1305 if (isEmergencyShutdown) { 1306 timeoutMs = 0; // do not wait for listeners to complete during emergency shutdown 1307 } else if (BuildHelper.isUserDebugBuild() || BuildHelper.isEngBuild()) { 1308 int shutdownPrepareTimeOverrideInSecs = 1309 SystemProperties.getInt(PROP_MAX_GARAGE_MODE_DURATION_OVERRIDE, -1); 1310 if (shutdownPrepareTimeOverrideInSecs >= 0) { 1311 timeoutMs = shutdownPrepareTimeOverrideInSecs * 1000L; 1312 } 1313 } 1314 makeSureNoUserInteraction(); 1315 sendPowerManagerEvent(CarPowerManager.STATE_SHUTDOWN_PREPARE, timeoutMs); 1316 mHal.sendShutdownPrepare(); 1317 waitForShutdownPrepareListenersToComplete(timeoutMs, intervalMs); 1318 } 1319 forceSimulatedCancel()1320 private void forceSimulatedCancel() { 1321 synchronized (mLock) { 1322 mPendingPowerStates.addFirst(new CpmsState(CpmsState.WAIT_FOR_VHAL, 1323 CarPowerManager.STATE_SHUTDOWN_CANCELLED, 1324 /* canPostpone= */ false)); 1325 } 1326 mHandler.handlePowerStateChange(); 1327 synchronized (mSimulationWaitObject) { 1328 mBlockFromSimulatedCancelEvent = true; 1329 mSimulationWaitObject.notifyAll(); 1330 } 1331 } 1332 handleWaitForFinish(CpmsState state)1333 private void handleWaitForFinish(CpmsState state) { 1334 int timeoutMs = getShutdownEnterTimeoutConfig(); 1335 sendPowerManagerEvent(state.mCarPowerStateListenerState, timeoutMs); 1336 Runnable taskAtCompletion = () -> { 1337 Slogf.i(TAG, "All listeners completed (or timed out) for %s", 1338 powerStateToString(state.mCarPowerStateListenerState)); 1339 if (mFeatureFlags.carPowerCancelShellCommand()) { 1340 synchronized (mSimulationWaitObject) { 1341 if (mInSimulatedDeepSleepMode && mCancelDelayFromSimulatedSuspendSec >= 0) { 1342 // Cannot use mHandler here because it can cause deadlock. This code 1343 // can run on handler thread which relies on the results of 1344 // forceSimulatedCancel. If forceSimulatedCancel runs on the same handler, 1345 // it will cause deadlock. 1346 Handler handler = new Handler(Looper.getMainLooper()); 1347 handler.postDelayed(() -> forceSimulatedCancel(), 1348 mCancelDelayFromSimulatedSuspendSec * 1000L); 1349 while (!mBlockFromSimulatedCancelEvent) { 1350 try { 1351 mSimulationWaitObject.wait(); 1352 } catch (InterruptedException ignored) { 1353 Thread.currentThread().interrupt(); // Restore interrupted status 1354 } 1355 } 1356 mInSimulatedDeepSleepMode = false; 1357 return; 1358 } 1359 } 1360 } 1361 int wakeupSec; 1362 synchronized (mLock) { 1363 // If we're shutting down immediately, don't schedule a wakeup time. 1364 wakeupSec = mGarageModeShouldExitImmediately ? 0 : mNextWakeupSec; 1365 } 1366 switch (state.mCarPowerStateListenerState) { 1367 case CarPowerManager.STATE_SUSPEND_ENTER: 1368 mHal.sendSleepEntry(wakeupSec); 1369 break; 1370 case CarPowerManager.STATE_SHUTDOWN_ENTER: 1371 mHal.sendShutdownStart(wakeupSec); 1372 break; 1373 case CarPowerManager.STATE_HIBERNATION_ENTER: 1374 mHal.sendHibernationEntry(wakeupSec); 1375 break; 1376 default: 1377 Slogf.w(TAG, "Invalid action when handling wait for finish: %d", 1378 state.mCarPowerStateListenerState); 1379 break; 1380 } 1381 }; 1382 1383 int intervalMs; 1384 synchronized (mLock) { 1385 intervalMs = mShutdownPollingIntervalMs; 1386 } 1387 1388 waitForCompletionWithShutdownPostpone(state.mCarPowerStateListenerState, timeoutMs, 1389 taskAtCompletion, intervalMs); 1390 } 1391 handleFinish()1392 private void handleFinish() { 1393 int listenerState; 1394 synchronized (mLock) { 1395 switch (mActionOnFinish) { 1396 case ACTION_ON_FINISH_SHUTDOWN: 1397 listenerState = CarPowerManager.STATE_POST_SHUTDOWN_ENTER; 1398 break; 1399 case ACTION_ON_FINISH_DEEP_SLEEP: 1400 listenerState = CarPowerManager.STATE_POST_SUSPEND_ENTER; 1401 break; 1402 case ACTION_ON_FINISH_HIBERNATION: 1403 listenerState = CarPowerManager.STATE_POST_HIBERNATION_ENTER; 1404 break; 1405 default: 1406 Slogf.w(TAG, "Invalid action on finish: %d", mActionOnFinish); 1407 return; 1408 } 1409 } 1410 int timeoutMs = getPostShutdownEnterTimeoutConfig(); 1411 sendPowerManagerEvent(listenerState, timeoutMs); 1412 Runnable taskAtCompletion = () -> { 1413 Slogf.i(TAG, "All listeners completed (or timed out) for %s", 1414 powerStateToString(listenerState)); 1415 doHandleFinish(); 1416 }; 1417 Slogf.i(TAG, "Start waiting for listener completion for %s", 1418 powerStateToString(listenerState)); 1419 waitForCompletion(taskAtCompletion, /* taskAtInterval= */ null, timeoutMs, 1420 /* intervalMs= */ -1); 1421 } 1422 doHandleFinish()1423 private void doHandleFinish() { 1424 boolean simulatedMode; 1425 synchronized (mSimulationWaitObject) { 1426 simulatedMode = mInSimulatedDeepSleepMode; 1427 } 1428 boolean mustShutDown; 1429 boolean forceReboot; 1430 synchronized (mLock) { 1431 mustShutDown = (mActionOnFinish == ACTION_ON_FINISH_SHUTDOWN) && !simulatedMode; 1432 forceReboot = mRebootAfterGarageMode; 1433 mRebootAfterGarageMode = false; 1434 } 1435 if (forceReboot) { 1436 PowerManager powerManager = mContext.getSystemService(PowerManager.class); 1437 if (powerManager == null) { 1438 Slogf.wtf(TAG, "No PowerManager. Cannot reboot."); 1439 } else { 1440 Slogf.i(TAG, "GarageMode has completed. Forcing reboot."); 1441 powerManager.reboot("GarageModeReboot"); 1442 throw new AssertionError("Should not return from PowerManager.reboot()"); 1443 } 1444 } 1445 // To make Kernel implementation simpler when going into sleep. 1446 if (mWifiAdjustmentForSuspend) { 1447 disableWifiFully(); 1448 } 1449 1450 if (mustShutDown) { 1451 // shutdown HU 1452 mSystemInterface.shutdown(); 1453 } else { 1454 doHandleSuspend(simulatedMode); 1455 } 1456 synchronized (mLock) { 1457 mShutdownOnNextSuspend = false; 1458 } 1459 } 1460 disableWifiFully()1461 private void disableWifiFully() { 1462 disableWifi(); 1463 disableTethering(); 1464 } 1465 restoreWifiFully()1466 private void restoreWifiFully() { 1467 restoreTethering(); 1468 restoreWifi(); 1469 } 1470 restoreWifi()1471 private void restoreWifi() { 1472 boolean needToRestore = readWifiModifiedState(mWifiStateFile); 1473 if (!needToRestore) return; 1474 if (!mWifiManager.isWifiEnabled()) { 1475 Slogf.i(TAG, "Wifi has been enabled to restore the last setting"); 1476 mWifiManager.setWifiEnabled(true); 1477 } 1478 // Update the persistent data as wifi is not modified by car framework. 1479 saveWifiModifiedState(mWifiStateFile, /* forciblyDisabled= */ false); 1480 } 1481 disableWifi()1482 private void disableWifi() { 1483 boolean wifiEnabled = mWifiManager.isWifiEnabled(); 1484 boolean wifiModifiedState = readWifiModifiedState(mWifiStateFile); 1485 if (wifiEnabled != wifiModifiedState) { 1486 Slogf.i(TAG, "Saving the current Wifi state"); 1487 saveWifiModifiedState(mWifiStateFile, wifiEnabled); 1488 } 1489 1490 // In some devices, enabling a tether temporarily turns off Wifi. To make sure that Wifi is 1491 // disabled, we call this method in all cases. 1492 mWifiManager.setWifiEnabled(false); 1493 Slogf.i(TAG, "Wifi has been disabled and the last setting was saved"); 1494 } 1495 restoreTethering()1496 private void restoreTethering() { 1497 boolean needToRestore = readWifiModifiedState(mTetheringStateFile); 1498 if (!needToRestore) return; 1499 if (!mWifiManager.isWifiApEnabled()) { 1500 Slogf.i(TAG, "Tethering has been enabled to restore the last setting"); 1501 startTethering(); 1502 } 1503 // Update the persistent data as wifi is not modified by car framework. 1504 saveWifiModifiedState(mTetheringStateFile, /*forciblyDisabled= */ false); 1505 } 1506 disableTethering()1507 private void disableTethering() { 1508 boolean tetheringEnabled = mWifiManager.isWifiApEnabled(); 1509 boolean tetheringModifiedState = readWifiModifiedState(mTetheringStateFile); 1510 if (tetheringEnabled != tetheringModifiedState) { 1511 Slogf.i(TAG, "Saving the current tethering state: tetheringEnabled=%b", 1512 tetheringEnabled); 1513 saveWifiModifiedState(mTetheringStateFile, tetheringEnabled); 1514 } 1515 if (!tetheringEnabled) return; 1516 1517 mTetheringManager.stopTethering(TETHERING_WIFI); 1518 Slogf.i(TAG, "Tethering has been disabled and the last setting was saved"); 1519 } 1520 saveWifiModifiedState(AtomicFile file, boolean forciblyDisabled)1521 private void saveWifiModifiedState(AtomicFile file, boolean forciblyDisabled) { 1522 FileOutputStream fos; 1523 try { 1524 fos = file.startWrite(); 1525 } catch (IOException e) { 1526 Slogf.e(TAG, e, "Cannot create %s", file); 1527 return; 1528 } 1529 1530 try (BufferedWriter writer = new BufferedWriter( 1531 new OutputStreamWriter(fos, StandardCharsets.UTF_8))) { 1532 writer.write(forciblyDisabled ? COMPONENT_STATE_MODIFIED : COMPONENT_STATE_ORIGINAL); 1533 writer.newLine(); 1534 writer.flush(); 1535 file.finishWrite(fos); 1536 } catch (IOException e) { 1537 file.failWrite(fos); 1538 Slogf.e(TAG, e, "Writing %s failed", file); 1539 } 1540 } 1541 readWifiModifiedState(AtomicFile file)1542 private boolean readWifiModifiedState(AtomicFile file) { 1543 boolean needToRestore = false; 1544 boolean invalidState = false; 1545 1546 try (BufferedReader reader = new BufferedReader( 1547 new InputStreamReader(file.openRead(), StandardCharsets.UTF_8))) { 1548 String line = reader.readLine(); 1549 if (line == null) { 1550 needToRestore = false; 1551 invalidState = true; 1552 } else { 1553 line = line.trim(); 1554 needToRestore = COMPONENT_STATE_MODIFIED.equals(line); 1555 invalidState = !(needToRestore || COMPONENT_STATE_ORIGINAL.equals(line)); 1556 } 1557 } catch (IOException e) { 1558 // If a file named wifi_state doesn't exist, we will not modify Wifi at system start. 1559 Slogf.w(TAG, "Failed to read %s: %s", file, e); 1560 return false; 1561 } 1562 if (invalidState) { 1563 file.delete(); 1564 } 1565 1566 return needToRestore; 1567 } 1568 startTethering()1569 private void startTethering() { 1570 TetheringRequest request = new TetheringRequest.Builder(TETHERING_WIFI) 1571 .setShouldShowEntitlementUi(false).build(); 1572 mTetheringManager.startTethering(request, mContext.getMainExecutor(), 1573 new TetheringManager.StartTetheringCallback() { 1574 @Override 1575 public void onTetheringFailed(int error) { 1576 Slogf.w(TAG, "Starting tethering failed: %d", error); 1577 } 1578 }); 1579 } 1580 waitForShutdownPrepareListenersToComplete(long timeoutMs, int intervalMs)1581 private void waitForShutdownPrepareListenersToComplete(long timeoutMs, int intervalMs) { 1582 int state = CarPowerManager.STATE_SHUTDOWN_PREPARE; 1583 Runnable taskAtCompletion = () -> { 1584 finishShutdownPrepare(); 1585 Slogf.i(TAG, "All listeners completed (or timed out) for %s", 1586 powerStateToString(state)); 1587 }; 1588 1589 waitForCompletionWithShutdownPostpone(state, timeoutMs, taskAtCompletion, intervalMs); 1590 1591 // allowUserSwitch value doesn't matter for onSuspend = true 1592 mUserService.onSuspend(); 1593 synchronized (mLock) { 1594 mShouldResumeUserService = true; 1595 } 1596 } 1597 waitForCompletion(Runnable taskAtCompletion, Runnable taskAtInterval, long timeoutMs, int intervalMs)1598 private void waitForCompletion(Runnable taskAtCompletion, Runnable taskAtInterval, 1599 long timeoutMs, int intervalMs) { 1600 boolean isComplete = false; 1601 synchronized (mLock) { 1602 isComplete = arePowerStateChangeListenersCompleteLocked(); 1603 } 1604 if (isComplete) { 1605 taskAtCompletion.run(); 1606 } else { 1607 // Reset a flag to signal that waiting for completion is cancelled. 1608 mIsListenerWaitingCancelled.set(false); 1609 waitForCompletionAsync(taskAtCompletion, taskAtInterval, timeoutMs, intervalMs); 1610 } 1611 } 1612 1613 // Waits for listeners to complete. 1614 // If {@code intervalMs} is non-positive value, it is ignored and the method waits up to 1615 // {@code timeoutMs}. waitForCompletionAsync(Runnable taskAtCompletion, Runnable taskAtInterval, long timeoutMs, long intervalMs)1616 private void waitForCompletionAsync(Runnable taskAtCompletion, Runnable taskAtInterval, 1617 long timeoutMs, long intervalMs) { 1618 ExecutorService executor = Executors.newSingleThreadExecutor(); 1619 executor.submit(() -> { 1620 long startTimeMs = SystemClock.elapsedRealtime(); 1621 while (true) { 1622 try { 1623 long waitTimeMs = timeoutMs - (SystemClock.elapsedRealtime() - startTimeMs); 1624 boolean isLastWait = true; 1625 if (intervalMs > 0 && waitTimeMs > intervalMs) { 1626 isLastWait = false; 1627 waitTimeMs = intervalMs; 1628 } 1629 boolean isNotified = mListenerCompletionSem.tryAcquire(waitTimeMs, 1630 TimeUnit.MILLISECONDS); 1631 mListenerCompletionSem.drainPermits(); 1632 if (!isNotified) { 1633 if (isLastWait) { 1634 Slogf.w(TAG, "Waiting for listener completion has timed out(%d)", 1635 waitTimeMs); 1636 taskAtCompletion.run(); 1637 return; 1638 } else if (taskAtInterval != null) { 1639 taskAtInterval.run(); 1640 } 1641 } 1642 boolean isComplete = false; 1643 synchronized (mLock) { 1644 if (mIsListenerWaitingCancelled.get()) { 1645 Slogf.i(TAG, "Waiting for listener completion is cancelled"); 1646 mIsListenerWaitingCancelled.set(false); 1647 return; 1648 } 1649 isComplete = arePowerStateChangeListenersCompleteLocked(); 1650 } 1651 if (isComplete) { 1652 Slogf.i(TAG, "All listeners completed"); 1653 taskAtCompletion.run(); 1654 mIsListenerWaitingCancelled.set(false); 1655 return; 1656 } 1657 } catch (InterruptedException e) { 1658 Slogf.w(TAG, e, "Thread interrupted while waiting for listener completion"); 1659 Thread.currentThread().interrupt(); 1660 } 1661 } 1662 }); 1663 executor.shutdown(); 1664 } 1665 clearWaitingForCompletion(boolean clearQueue)1666 private void clearWaitingForCompletion(boolean clearQueue) { 1667 if (clearQueue) { 1668 synchronized (mLock) { 1669 mListenersWeAreWaitingFor.clear(); 1670 if (NativePowerNotificationsFlag.isFeatureSupported()) { 1671 mWaitingNativeListenerChangeId = INVALID_NATIVE_LISTENER_CHANGE_ID; 1672 } 1673 } 1674 } else { 1675 mIsListenerWaitingCancelled.set(true); 1676 } 1677 1678 mListenerCompletionSem.release(); 1679 } 1680 1681 @GuardedBy("mLock") arePowerStateChangeListenersCompleteLocked()1682 private boolean arePowerStateChangeListenersCompleteLocked() { 1683 boolean javaListenersComplete = mListenersWeAreWaitingFor.isEmpty(); 1684 if (NativePowerNotificationsFlag.isFeatureSupported()) { 1685 boolean nativeListenersComplete = 1686 mWaitingNativeListenerChangeId == INVALID_NATIVE_LISTENER_CHANGE_ID; 1687 return javaListenersComplete && nativeListenersComplete; 1688 } 1689 return javaListenersComplete; 1690 } 1691 sendPowerManagerEvent(@arPowerManager.CarPowerState int newState, long timeoutMs)1692 private void sendPowerManagerEvent(@CarPowerManager.CarPowerState int newState, 1693 long timeoutMs) { 1694 // Notify power daemon to notify native listeners 1695 if (NativePowerNotificationsFlag.isFeatureSupported()) { 1696 notifyPowerStateChangeToDaemon(newState, timeoutMs == INVALID_TIMEOUT ? 0 : timeoutMs); 1697 } 1698 1699 // Broadcasts to the listeners that do not signal completion. 1700 notifyListeners(mPowerManagerListeners, newState, INVALID_TIMEOUT); 1701 1702 boolean allowCompletion = isCompletionAllowed(newState); 1703 boolean isShutdownPrepare = newState == CarPowerManager.STATE_SHUTDOWN_PREPARE; 1704 long internalListenerExpirationTimeMs = INVALID_TIMEOUT; 1705 long binderListenerExpirationTimeMs = INVALID_TIMEOUT; 1706 1707 // Fully populates mListenersWeAreWaitingFor before calling any onStateChanged() 1708 // for the listeners that signal completion. 1709 // Otherwise, if the first listener calls finish() synchronously, we will 1710 // see the list go empty and we will think that we are done. 1711 PowerManagerCallbackList<ICarPowerStateListener> completingInternalListeners = 1712 new PowerManagerCallbackList(l -> { 1713 }); 1714 PowerManagerCallbackList<ICarPowerStateListener> completingBinderListeners = 1715 new PowerManagerCallbackList(l -> { 1716 }); 1717 synchronized (mLock) { 1718 if (allowCompletion) { 1719 if (timeoutMs < 0) { 1720 Slogf.wtf(TAG, "Completion timeout(%d) for state(%d) should be " 1721 + "non-negative", timeoutMs, newState); 1722 return; 1723 } 1724 mStateForCompletion = newState; 1725 internalListenerExpirationTimeMs = SystemClock.elapsedRealtime() + timeoutMs; 1726 binderListenerExpirationTimeMs = 1727 isShutdownPrepare ? INVALID_TIMEOUT : internalListenerExpirationTimeMs; 1728 } else { 1729 mStateForCompletion = CarPowerManager.STATE_INVALID; 1730 } 1731 1732 mListenersWeAreWaitingFor.clear(); 1733 for (int i = 0; i < mInternalPowerListeners.size(); i++) { 1734 ICarPowerStateListener listener = mInternalPowerListeners.get(i); 1735 completingInternalListeners.register(listener); 1736 if (allowCompletion) { 1737 mListenersWeAreWaitingFor.add(listener.asBinder()); 1738 } 1739 } 1740 mBroadcastHandler.post(() -> { 1741 int idx = mPowerManagerListenersWithCompletion.beginBroadcast(); 1742 while (idx-- > 0) { 1743 ICarPowerStateListener listener = 1744 mPowerManagerListenersWithCompletion.getBroadcastItem(idx); 1745 completingBinderListeners.register(listener); 1746 if (allowCompletion && !isShutdownPrepare) { 1747 synchronized (mLock) { 1748 mListenersWeAreWaitingFor.add(listener.asBinder()); 1749 } 1750 } 1751 } 1752 mPowerManagerListenersWithCompletion.finishBroadcast(); 1753 }); 1754 } 1755 // Resets the semaphore's available permits to 0. 1756 mListenerCompletionSem.drainPermits(); 1757 // Broadcasts to the listeners that DO signal completion. 1758 notifyListeners(completingInternalListeners, newState, internalListenerExpirationTimeMs); 1759 notifyListeners(completingBinderListeners, newState, binderListenerExpirationTimeMs); 1760 1761 // Call unlinkToDeath inside RemoteCallbackList 1762 completingInternalListeners.kill(); 1763 completingBinderListeners.kill(); 1764 } 1765 notifyListeners(PowerManagerCallbackList<ICarPowerStateListener> listenerList, @CarPowerManager.CarPowerState int newState, long expirationTimeMs)1766 private void notifyListeners(PowerManagerCallbackList<ICarPowerStateListener> listenerList, 1767 @CarPowerManager.CarPowerState int newState, long expirationTimeMs) { 1768 CountDownLatch listenerLatch = new CountDownLatch(1); 1769 mBroadcastHandler.post(() -> { 1770 int idx = listenerList.beginBroadcast(); 1771 while (idx-- > 0) { 1772 ICarPowerStateListener listener = listenerList.getBroadcastItem(idx); 1773 try { 1774 listener.onStateChanged(newState, expirationTimeMs); 1775 } catch (RemoteException e) { 1776 // It's likely the connection snapped. Let binder death handle the situation. 1777 Slogf.e(TAG, e, "onStateChanged() call failed"); 1778 } 1779 } 1780 listenerList.finishBroadcast(); 1781 listenerLatch.countDown(); 1782 }); 1783 try { 1784 listenerLatch.await(DEFAULT_COMPLETION_WAIT_TIMEOUT, TimeUnit.MILLISECONDS); 1785 } catch (InterruptedException e) { 1786 Slogf.w(TAG, e, "Wait for power state listener completion interrupted"); 1787 Thread.currentThread().interrupt(); 1788 } 1789 } 1790 doHandleSuspend(boolean simulatedMode)1791 private void doHandleSuspend(boolean simulatedMode) { 1792 int status; 1793 if (mFeatureFlags.carPowerPolicyRefactoring()) { 1794 status = applyPowerPolicy(PolicyReader.POWER_POLICY_ID_SUSPEND_PREP, 1795 /* delayNotification= */ false, /* upToDaemon= */ false, /* force= */ true); 1796 } else { 1797 status = applyPreemptivePowerPolicy(PolicyReader.POWER_POLICY_ID_SUSPEND_PREP); 1798 } 1799 if (status != PolicyOperationStatus.OK) { 1800 Slogf.w(TAG, PolicyOperationStatus.errorCodeToString(status)); 1801 } 1802 // Keeps holding partial wakelock to prevent entering sleep before enterDeepSleep/ 1803 // enterHibernation call. enterDeepSleep/enterHibernation should force sleep entry even if 1804 // wake lock is kept. 1805 forEachDisplay(mContext, mSystemInterface::switchToPartialWakeLock); 1806 mHandler.cancelProcessingComplete(); 1807 synchronized (mLock) { 1808 mLastSleepEntryTime = SystemClock.elapsedRealtime(); 1809 } 1810 if (simulatedMode) { 1811 simulateSleepByWaiting(); 1812 } else { 1813 boolean sleepSucceeded = suspendWithRetries(); 1814 if (!sleepSucceeded) { 1815 // Suspend failed and we shut down instead. 1816 // We either won't get here at all or we will power off very soon. 1817 return; 1818 } 1819 } 1820 @CarPowerManager.CarPowerState int nextListenerState; 1821 synchronized (mLock) { 1822 nextListenerState = (mActionOnFinish == ACTION_ON_FINISH_DEEP_SLEEP) 1823 ? CarPowerManager.STATE_SUSPEND_EXIT 1824 : CarPowerManager.STATE_HIBERNATION_EXIT; 1825 // Any wakeup time from before is no longer valid. 1826 mNextWakeupSec = 0; 1827 } 1828 Slogf.i(TAG, "Resuming after suspending"); 1829 forEachDisplay(mContext, mSystemInterface::refreshDisplayBrightness); 1830 // TODO(b/311063174): Verify boot.car_kernel_boot_time and boot.car_device_start time 1831 // format when LA.3.7.0 lands. 1832 if (!simulatedMode) { 1833 long userPerceivedStartTimeAfterSuspend = SystemClock.uptimeMillis(); 1834 String suspendTarget = getSuspendType(); 1835 long kernelStartTimeMillis = SystemPropertiesHelper.getLong( 1836 KERNEL_BOOT_TIME_PROPERTY, /* defaultVal= */ 0L); 1837 long deviceStartTimeMillis = SystemPropertiesHelper.getLong( 1838 DEVICE_START_TIME_PROPERTY, /* defaultVal= */ 0L); 1839 CarStatsLogHelper.logResumeFromSuspend(suspendTarget, kernelStartTimeMillis, 1840 mCarServiceStartTimeAfterSuspend, userPerceivedStartTimeAfterSuspend, 1841 deviceStartTimeMillis); 1842 } 1843 onApPowerStateChange(CpmsState.WAIT_FOR_VHAL, nextListenerState); 1844 } 1845 1846 @GuardedBy("mLock") needPowerStateChangeLocked(@onNull CpmsState newState)1847 private boolean needPowerStateChangeLocked(@NonNull CpmsState newState) { 1848 if (mCurrentState == null) { 1849 return true; 1850 } else if (mCurrentState.equals(newState)) { 1851 Slogf.d(TAG, "Requested state is already in effect: %s", newState.name()); 1852 return false; 1853 } 1854 1855 // The following switch/case enforces the allowed state transitions. 1856 boolean transitionAllowed = false; 1857 switch (mCurrentState.mState) { 1858 case CpmsState.WAIT_FOR_VHAL: 1859 transitionAllowed = (newState.mState == CpmsState.ON) 1860 || (newState.mState == CpmsState.SHUTDOWN_PREPARE); 1861 break; 1862 case CpmsState.SUSPEND: 1863 transitionAllowed = newState.mState == CpmsState.WAIT_FOR_VHAL; 1864 break; 1865 case CpmsState.ON: 1866 transitionAllowed = (newState.mState == CpmsState.SHUTDOWN_PREPARE) 1867 || (newState.mState == CpmsState.SIMULATE_SLEEP) 1868 || (newState.mState == CpmsState.SIMULATE_HIBERNATION); 1869 break; 1870 case CpmsState.SHUTDOWN_PREPARE: 1871 // If VHAL sends SHUTDOWN_IMMEDIATELY or SLEEP_IMMEDIATELY while in 1872 // SHUTDOWN_PREPARE state, do it. 1873 transitionAllowed = 1874 ((newState.mState == CpmsState.SHUTDOWN_PREPARE) && !newState.mCanPostpone) 1875 || (newState.mState == CpmsState.WAIT_FOR_FINISH) 1876 || (newState.mState == CpmsState.WAIT_FOR_VHAL); 1877 break; 1878 case CpmsState.SIMULATE_SLEEP: 1879 case CpmsState.SIMULATE_HIBERNATION: 1880 transitionAllowed = true; 1881 break; 1882 case CpmsState.WAIT_FOR_FINISH: 1883 transitionAllowed = (newState.mState == CpmsState.SUSPEND 1884 || newState.mState == CpmsState.WAIT_FOR_VHAL); 1885 break; 1886 default: 1887 Slogf.e(TAG, "Unexpected current state: currentState=%s, newState=%s", 1888 mCurrentState.name(), newState.name()); 1889 transitionAllowed = true; 1890 } 1891 if (!transitionAllowed) { 1892 Slogf.e(TAG, "Requested power transition is not allowed: %s --> %s", 1893 mCurrentState.name(), newState.name()); 1894 } 1895 return transitionAllowed; 1896 } 1897 doHandleProcessingComplete()1898 private void doHandleProcessingComplete() { 1899 int listenerState = CarPowerManager.STATE_SHUTDOWN_ENTER; 1900 synchronized (mLock) { 1901 clearWaitingForCompletion(/* clearQueue= */ false); 1902 boolean shutdownOnFinish = (mActionOnFinish == ACTION_ON_FINISH_SHUTDOWN); 1903 if (!shutdownOnFinish && mLastSleepEntryTime > mShutdownStartTime) { 1904 // entered sleep after processing start. So this could be duplicate request. 1905 Slogf.w(TAG, "Duplicate sleep entry request, ignore"); 1906 return; 1907 } 1908 if (shutdownOnFinish) { 1909 listenerState = CarPowerManager.STATE_SHUTDOWN_ENTER; 1910 } else if (mActionOnFinish == ACTION_ON_FINISH_DEEP_SLEEP) { 1911 listenerState = CarPowerManager.STATE_SUSPEND_ENTER; 1912 } else if (mActionOnFinish == ACTION_ON_FINISH_HIBERNATION) { 1913 listenerState = CarPowerManager.STATE_HIBERNATION_ENTER; 1914 } 1915 } 1916 1917 onApPowerStateChange(CpmsState.WAIT_FOR_FINISH, listenerState); 1918 } 1919 1920 @Override onDisplayBrightnessChange(int brightness)1921 public void onDisplayBrightnessChange(int brightness) { 1922 mHandler.handleDisplayBrightnessChange(Display.DEFAULT_DISPLAY, brightness); 1923 } 1924 1925 @Override onDisplayBrightnessChange(int displayId, int brightness)1926 public void onDisplayBrightnessChange(int displayId, int brightness) { 1927 mHandler.handleDisplayBrightnessChange(displayId, brightness); 1928 } 1929 doHandleDisplayBrightnessChange(int displayId, int brightness)1930 private void doHandleDisplayBrightnessChange(int displayId, int brightness) { 1931 mSystemInterface.onDisplayBrightnessChangeFromVhal(displayId, brightness); 1932 } 1933 doHandleDisplayStateChange(int displayId, boolean on)1934 private void doHandleDisplayStateChange(int displayId, boolean on) { 1935 mScreenOffHandler.handleDisplayStateChange(displayId, on); 1936 } 1937 doHandlePowerPolicyNotification(PowerPolicyChangeNotification notification)1938 private void doHandlePowerPolicyNotification(PowerPolicyChangeNotification notification) { 1939 // Sending notification of power policy change triggered through CarPowerManager API. 1940 if (notification.legacyNotification) { 1941 notifyPowerPolicyChange(notification, /* upToDaemon= */ true, /* force= */ false); 1942 } else { 1943 notifyPowerPolicyChange(notification); 1944 } 1945 } 1946 1947 /** 1948 * Handles when display changes. 1949 */ handleDisplayChanged(int displayId, boolean on)1950 public void handleDisplayChanged(int displayId, boolean on) { 1951 mHandler.handleDisplayStateChange(displayId, on); 1952 } 1953 1954 /** 1955 * Gets display display power mode to turn on display. 1956 * 1957 * @return {@code false}, if the display power mode is OFF. Otherwise, {@code true}. 1958 */ canTurnOnDisplay(int displayId)1959 public boolean canTurnOnDisplay(int displayId) { 1960 return mScreenOffHandler.canTurnOnDisplay(displayId); 1961 } 1962 1963 /** 1964 * Notifies that user activity has happened. 1965 */ notifyUserActivity(int displayId, long eventTime)1966 public void notifyUserActivity(int displayId, long eventTime) { 1967 mScreenOffHandler.updateUserActivity(displayId, eventTime); 1968 } 1969 1970 @Override notifyUserActivity(int displayId)1971 public void notifyUserActivity(int displayId) { 1972 CarServiceUtils.assertPermission(mContext, Car.PERMISSION_CAR_POWER); 1973 notifyUserActivity(displayId, SystemClock.uptimeMillis()); 1974 } 1975 1976 /** 1977 * Sends display brightness to VHAL. 1978 * @param brightness value 0-100% 1979 */ sendDisplayBrightnessLegacy(int brightness)1980 public void sendDisplayBrightnessLegacy(int brightness) { 1981 mHal.sendDisplayBrightnessLegacy(brightness); 1982 } 1983 1984 /** 1985 * Sends display brightness to VHAL. 1986 * @param displayId the target display 1987 * @param brightness value 0-100% 1988 */ sendDisplayBrightness(int displayId, int brightness)1989 public void sendDisplayBrightness(int displayId, int brightness) { 1990 mHal.sendDisplayBrightness(displayId, brightness); 1991 } 1992 1993 /** 1994 * Gets the PowerHandler that we use to change power states 1995 */ getHandler()1996 public Handler getHandler() { 1997 return mHandler; 1998 1999 } 2000 2001 /** 2002 * Registers power state change listeners running in CarService, which is not a binder 2003 * interfaces. 2004 */ registerInternalListener(ICarPowerStateListener listener)2005 public void registerInternalListener(ICarPowerStateListener listener) { 2006 CarServiceUtils.assertCallingFromSystemProcessOrSelf(); 2007 synchronized (mLock) { 2008 mInternalPowerListeners.add(listener); 2009 } 2010 } 2011 2012 /** 2013 * Unregisters power state change listeners running in CarService, which is not a binder 2014 * interface. 2015 */ unregisterInternalListener(ICarPowerStateListener listener)2016 public void unregisterInternalListener(ICarPowerStateListener listener) { 2017 CarServiceUtils.assertCallingFromSystemProcessOrSelf(); 2018 boolean found = false; 2019 synchronized (mLock) { 2020 found = mInternalPowerListeners.remove(listener); 2021 } 2022 if (found) { 2023 removeListenerFromWaitingList(listener.asBinder()); 2024 } 2025 } 2026 2027 /** 2028 * Tells {@link CarPowerManagementService} that the listener running in CarService completes 2029 * handling power state change. 2030 */ completeHandlingPowerStateChange(int state, ICarPowerStateListener listener)2031 public void completeHandlingPowerStateChange(int state, ICarPowerStateListener listener) { 2032 CarServiceUtils.assertCallingFromSystemProcessOrSelf(); 2033 handleListenerCompletion(state, listener, Set.of()); 2034 } 2035 2036 // Binder interface for general use. 2037 // The listener is not required (or allowed) to call finished(). 2038 @Override registerListener(ICarPowerStateListener listener)2039 public void registerListener(ICarPowerStateListener listener) { 2040 CarServiceUtils.assertPermission(mContext, Car.PERMISSION_CAR_POWER); 2041 mPowerManagerListeners.register(listener); 2042 } 2043 2044 // Binder interface for Car services only. 2045 // After the listener completes its processing, it must call finished(). 2046 @Override registerListenerWithCompletion(ICarPowerStateListener listener)2047 public void registerListenerWithCompletion(ICarPowerStateListener listener) { 2048 CarServiceUtils.assertPermission(mContext, Car.PERMISSION_CONTROL_SHUTDOWN_PROCESS); 2049 2050 mPowerManagerListenersWithCompletion.register(listener); 2051 // TODO: Need to send current state to newly registered listener? If so, need to handle 2052 // completion for SHUTDOWN_PREPARE state 2053 } 2054 2055 @Override unregisterListener(ICarPowerStateListener listener)2056 public void unregisterListener(ICarPowerStateListener listener) { 2057 CarServiceUtils.assertAnyPermission(mContext, Car.PERMISSION_CAR_POWER, 2058 Car.PERMISSION_CONTROL_SHUTDOWN_PROCESS); 2059 doUnregisterListener(listener); 2060 } 2061 2062 @Override requestShutdownOnNextSuspend()2063 public void requestShutdownOnNextSuspend() { 2064 CarServiceUtils.assertPermission(mContext, Car.PERMISSION_CAR_POWER); 2065 synchronized (mLock) { 2066 mShutdownOnNextSuspend = true; 2067 } 2068 } 2069 2070 @Override finished(int state, ICarPowerStateListener listener)2071 public void finished(int state, ICarPowerStateListener listener) { 2072 CarServiceUtils.assertPermission(mContext, Car.PERMISSION_CONTROL_SHUTDOWN_PROCESS); 2073 handleListenerCompletion(state, listener, Set.of(CarPowerManager.STATE_SHUTDOWN_PREPARE)); 2074 } 2075 2076 @Override scheduleNextWakeupTime(int seconds)2077 public void scheduleNextWakeupTime(int seconds) { 2078 CarServiceUtils.assertPermission(mContext, Car.PERMISSION_CAR_POWER); 2079 if (seconds < 0) { 2080 Slogf.w(TAG, "Next wake up time is negative. Ignoring!"); 2081 return; 2082 } 2083 boolean timedWakeupAllowed = mHal.isTimedWakeupAllowed(); 2084 synchronized (mLock) { 2085 if (!timedWakeupAllowed) { 2086 Slogf.w(TAG, "Setting timed wakeups are disabled in HAL. Skipping"); 2087 mNextWakeupSec = 0; 2088 return; 2089 } 2090 if (mNextWakeupSec == 0 || mNextWakeupSec > seconds) { 2091 // The new value is sooner than the old value. Take the new value. 2092 mNextWakeupSec = seconds; 2093 } else { 2094 Slogf.d(TAG, "Tried to schedule next wake up, but already had shorter " 2095 + "scheduled time"); 2096 } 2097 } 2098 } 2099 2100 @Override getPowerState()2101 public @CarPowerManager.CarPowerState int getPowerState() { 2102 CarServiceUtils.assertPermission(mContext, Car.PERMISSION_CAR_POWER); 2103 synchronized (mLock) { 2104 return (mCurrentState == null) ? CarPowerManager.STATE_INVALID 2105 : mCurrentState.mCarPowerStateListenerState; 2106 } 2107 } 2108 2109 /** 2110 * @see android.car.hardware.power.CarPowerManager#getCurrentPowerPolicy 2111 */ 2112 @Override getCurrentPowerPolicy()2113 public CarPowerPolicy getCurrentPowerPolicy() { 2114 CarServiceUtils.assertPermission(mContext, Car.PERMISSION_READ_CAR_POWER_POLICY); 2115 if (mFeatureFlags.carPowerPolicyRefactoring()) { 2116 synchronized (mLock) { 2117 return mCurrentAccumulatedPowerPolicy; 2118 } 2119 } else { 2120 return mPowerComponentHandler.getAccumulatedPolicy(); 2121 } 2122 } 2123 2124 /** 2125 * @see android.car.hardware.power.CarPowerManager#applyPowerPolicy 2126 */ 2127 @Override applyPowerPolicy(String policyId)2128 public void applyPowerPolicy(String policyId) { 2129 Slogf.i(TAG, "applyPowerPolicy(%s) from binder", policyId); 2130 CarServiceUtils.assertPermission(mContext, Car.PERMISSION_CONTROL_CAR_POWER_POLICY); 2131 Preconditions.checkArgument(policyId != null, "policyId cannot be null"); 2132 Preconditions.checkArgument(!policyId.startsWith(PolicyReader.SYSTEM_POWER_POLICY_PREFIX), 2133 "System power policy cannot be applied by apps"); 2134 // notify daemon of power policy change not needed after policy refactor 2135 boolean upToDaemon = !mFeatureFlags.carPowerPolicyRefactoring(); 2136 int status = applyPowerPolicy(policyId, /* delayNotification= */ true, upToDaemon, 2137 /* force= */ false); 2138 if (status != PolicyOperationStatus.OK) { 2139 throw new IllegalArgumentException(PolicyOperationStatus.errorCodeToString(status)); 2140 } 2141 } 2142 2143 /** 2144 * @see android.car.hardware.power.CarPowerManager#setPowerPolicyGroup 2145 */ 2146 @Override setPowerPolicyGroup(String policyGroupId)2147 public void setPowerPolicyGroup(String policyGroupId) throws RemoteException { 2148 Slogf.i(TAG, "setPowerPolicyGroup(%s)", policyGroupId); 2149 CarServiceUtils.assertPermission(mContext, Car.PERMISSION_CONTROL_CAR_POWER_POLICY); 2150 Preconditions.checkArgument(policyGroupId != null, "policyGroupId cannot be null"); 2151 if (mFeatureFlags.carPowerPolicyRefactoring()) { 2152 ICarPowerManagementDelegate daemon; 2153 synchronized (mLock) { 2154 daemon = mRefactoredCarPowerManagementDaemon; 2155 } 2156 try { 2157 daemon.setPowerPolicyGroup(policyGroupId); 2158 } catch (IllegalArgumentException e) { 2159 throw new IllegalArgumentException("Policy group ID is invalid"); 2160 } catch (SecurityException e) { 2161 Slogf.e(TAG, e, "Failed to set power policy group, insufficient permissions"); 2162 } 2163 synchronized (mLock) { 2164 mCurrentPowerPolicyGroupId = policyGroupId; 2165 } 2166 } else { 2167 int status = setCurrentPowerPolicyGroup(policyGroupId); 2168 if (status != PolicyOperationStatus.OK) { 2169 throw new IllegalArgumentException(PolicyOperationStatus.errorCodeToString(status)); 2170 } 2171 } 2172 } 2173 2174 @VisibleForTesting getCurrentPowerPolicyGroupId()2175 String getCurrentPowerPolicyGroupId() { 2176 synchronized (mLock) { 2177 return mCurrentPowerPolicyGroupId; 2178 } 2179 } 2180 2181 @VisibleForTesting getNumberOfCurrentPolicyRequests()2182 int getNumberOfCurrentPolicyRequests() { 2183 synchronized (mLock) { 2184 return mRequestIdToPolicyRequest.size(); 2185 } 2186 } 2187 2188 /** 2189 * @see android.car.hardware.power.CarPowerManager#addPowerPolicyListener 2190 */ 2191 @Override addPowerPolicyListener(CarPowerPolicyFilter filter, ICarPowerPolicyListener listener)2192 public void addPowerPolicyListener(CarPowerPolicyFilter filter, 2193 ICarPowerPolicyListener listener) { 2194 CarServiceUtils.assertPermission(mContext, Car.PERMISSION_READ_CAR_POWER_POLICY); 2195 mPowerPolicyListeners.register(listener, filter); 2196 } 2197 2198 /** 2199 * @see android.car.hardware.power.CarPowerManager#removePowerPolicyListener 2200 */ 2201 @Override removePowerPolicyListener(ICarPowerPolicyListener listener)2202 public void removePowerPolicyListener(ICarPowerPolicyListener listener) { 2203 CarServiceUtils.assertPermission(mContext, Car.PERMISSION_READ_CAR_POWER_POLICY); 2204 mPowerPolicyListeners.unregister(listener); 2205 } 2206 2207 /** 2208 * @see android.car.hardware.power.CarPowerManager#setDisplayPowerState 2209 */ 2210 @Override setDisplayPowerState(int displayId, boolean enable)2211 public void setDisplayPowerState(int displayId, boolean enable) { 2212 CarServiceUtils.assertPermission(mContext, Car.PERMISSION_CAR_POWER); 2213 boolean isNotSelf = Binder.getCallingUid() != Process.myUid(); 2214 CarOccupantZoneService occupantZoneService = 2215 CarLocalServices.getService(CarOccupantZoneService.class); 2216 long token = Binder.clearCallingIdentity(); 2217 try { 2218 int driverDisplayId = occupantZoneService.getDisplayIdForDriver( 2219 CarOccupantZoneManager.DISPLAY_TYPE_MAIN); 2220 if (displayId == driverDisplayId && isNotSelf) { 2221 throw new UnsupportedOperationException("Driver display control is not supported"); 2222 } 2223 } finally { 2224 Binder.restoreCallingIdentity(token); 2225 } 2226 mSystemInterface.setDisplayState(displayId, enable); 2227 } 2228 2229 // TODO(b/286303350): remove once power policy refactor complete; CPPD will handle power policy 2230 // change in response to silent mode status changes notifySilentModeChange(boolean silent)2231 void notifySilentModeChange(boolean silent) { 2232 Slogf.i(TAG, "Silent mode is set to %b", silent); 2233 if (silent) { 2234 applyPreemptivePowerPolicy(PolicyReader.POWER_POLICY_ID_NO_USER_INTERACTION); 2235 } else { 2236 cancelPreemptivePowerPolicy(); 2237 } 2238 } 2239 handleListenerCompletion(int state, ICarPowerStateListener listener, Set<Integer> notAllowedStates)2240 private void handleListenerCompletion(int state, ICarPowerStateListener listener, 2241 Set<Integer> notAllowedStates) { 2242 synchronized (mLock) { 2243 if (mStateForCompletion == CarPowerManager.STATE_INVALID) { 2244 Slogf.w(TAG, "The current state is invalid, listener completion not allowed"); 2245 return; 2246 } 2247 if (notAllowedStates.contains(mStateForCompletion)) { 2248 Slogf.w(TAG, "The current state(%d) doesn't allow listener completion", 2249 mStateForCompletion); 2250 return; 2251 } 2252 if (state != mStateForCompletion) { 2253 Slogf.w(TAG, "Given state(%d) doesn't match the current state(%d) for completion", 2254 state, mStateForCompletion); 2255 return; 2256 } 2257 } 2258 removeListenerFromWaitingList(listener.asBinder()); 2259 } 2260 2261 doUnregisterListener(ICarPowerStateListener listener)2262 private void doUnregisterListener(ICarPowerStateListener listener) { 2263 mPowerManagerListeners.unregister(listener); 2264 boolean found = mPowerManagerListenersWithCompletion.unregister(listener); 2265 if (found) { 2266 // Remove this from the completion list (if it's there) 2267 removeListenerFromWaitingList(listener.asBinder()); 2268 } 2269 } 2270 removeListenerFromWaitingList(IBinder binderListener)2271 private void removeListenerFromWaitingList(IBinder binderListener) { 2272 synchronized (mLock) { 2273 mListenersWeAreWaitingFor.remove(binderListener); 2274 } 2275 // Signals a thread to check if all listeners complete. 2276 mListenerCompletionSem.release(); 2277 } 2278 finishShutdownPrepare()2279 private void finishShutdownPrepare() { 2280 boolean shouldHandleProcessingComplete = false; 2281 synchronized (mLock) { 2282 if (mCurrentState != null 2283 && (mCurrentState.mState == CpmsState.SHUTDOWN_PREPARE 2284 || mCurrentState.mState == CpmsState.SIMULATE_SLEEP 2285 || mCurrentState.mState == CpmsState.SIMULATE_HIBERNATION)) { 2286 // All apps are ready to shutdown/suspend. 2287 if (mActionOnFinish != ACTION_ON_FINISH_SHUTDOWN) { 2288 if (mLastSleepEntryTime > mShutdownStartTime 2289 && mLastSleepEntryTime < SystemClock.elapsedRealtime()) { 2290 Slogf.d(TAG, "finishShutdownPrepare: Already slept!"); 2291 return; 2292 } 2293 } 2294 shouldHandleProcessingComplete = true; 2295 } 2296 } 2297 2298 if (shouldHandleProcessingComplete) { 2299 Slogf.i(TAG, "Apps are finished, call handleProcessingComplete()"); 2300 mHandler.handleProcessingComplete(); 2301 } 2302 } 2303 2304 /** 2305 * Converts a given power policy from power policy type returned by the car power policy daemon 2306 * to the one used within car service. 2307 * @param policy of type android.frameworks.automotive.powerpolicy.CarPowerPolicy 2308 * @return policy converted to type android.car.hardware.power.CarPowerPolicy 2309 */ convertPowerPolicyFromDaemon( android.frameworks.automotive.powerpolicy.CarPowerPolicy policy)2310 private CarPowerPolicy convertPowerPolicyFromDaemon( 2311 android.frameworks.automotive.powerpolicy.CarPowerPolicy policy) { 2312 return new CarPowerPolicy(policy.policyId, policy.enabledComponents, 2313 policy.disabledComponents); 2314 } 2315 2316 private final class PowerPolicyCallback extends ICarPowerManagementDelegateCallback.Stub { 2317 @Override updatePowerComponents( android.frameworks.automotive.powerpolicy.CarPowerPolicy policy)2318 public void updatePowerComponents( 2319 android.frameworks.automotive.powerpolicy.CarPowerPolicy policy) { 2320 mPowerComponentHandler.applyPowerPolicy(convertPowerPolicyFromDaemon(policy)); 2321 } 2322 2323 @Override onApplyPowerPolicySucceeded(int requestId, android.frameworks.automotive.powerpolicy.CarPowerPolicy accumulatedPolicy, boolean deferred)2324 public void onApplyPowerPolicySucceeded(int requestId, 2325 android.frameworks.automotive.powerpolicy.CarPowerPolicy accumulatedPolicy, 2326 boolean deferred) { 2327 Slogf.i(TAG, "onApplyPowerPolicySucceeded: requestId = %d, policyId = %s, " 2328 + "deferred = %b", requestId, accumulatedPolicy.policyId, deferred); 2329 AsyncPolicyRequest policyRequest; 2330 synchronized (mLock) { 2331 policyRequest = mRequestIdToPolicyRequest.get(requestId); 2332 } 2333 if (policyRequest == null) { 2334 Slogf.e(TAG, "No power policy request exists for request ID %d", requestId); 2335 return; 2336 } 2337 CarPowerPolicy accumulatedPowerPolicy = convertPowerPolicyFromDaemon(accumulatedPolicy); 2338 policyRequest.onPolicyRequestSucceeded(accumulatedPowerPolicy, deferred); 2339 } 2340 2341 @Override onApplyPowerPolicyFailed(int requestId, int reason)2342 public void onApplyPowerPolicyFailed(int requestId, int reason) { 2343 Slogf.i(TAG, "onApplyPowerPolicyFailed: requestId = %d, reason = %d", requestId, 2344 reason); 2345 AsyncPolicyRequest policyRequest; 2346 synchronized (mLock) { 2347 policyRequest = mRequestIdToPolicyRequest.get(requestId); 2348 } 2349 if (policyRequest == null) { 2350 Slogf.e(TAG, "No power policy request exists for request ID %d", requestId); 2351 return; 2352 } 2353 policyRequest.onPolicyRequestFailed(reason); 2354 } 2355 2356 @Override onPowerPolicyChanged( android.frameworks.automotive.powerpolicy.CarPowerPolicy accumulatedPolicy)2357 public void onPowerPolicyChanged( 2358 android.frameworks.automotive.powerpolicy.CarPowerPolicy accumulatedPolicy) { 2359 CarPowerPolicy currentAccumulatedPolicy = 2360 convertPowerPolicyFromDaemon(accumulatedPolicy); 2361 updateCurrentPowerPolicy(currentAccumulatedPolicy); 2362 String policyId = accumulatedPolicy.policyId; 2363 Slogf.i(TAG, "Queueing power policy notification (ID: %s) in the handler", policyId); 2364 mHandler.handlePowerPolicyNotification(new PowerPolicyChangeNotification( 2365 mPowerComponentHandler.getLastModifiedComponents(), 2366 currentAccumulatedPolicy, /* legacyNotification= */ false)); 2367 } 2368 2369 @Override onAllPowerStateChangeListenersComplete(int changeId)2370 public void onAllPowerStateChangeListenersComplete(int changeId) { 2371 synchronized (mLock) { 2372 if (changeId == mWaitingNativeListenerChangeId) { 2373 mWaitingNativeListenerChangeId = INVALID_NATIVE_LISTENER_CHANGE_ID; 2374 mListenerCompletionSem.release(); 2375 } else { 2376 Slogf.i(TAG, "Native power state change listeners completed for change " 2377 + "ID %d, but currently waiting for change ID %d to finish", 2378 changeId, mWaitingNativeListenerChangeId); 2379 } 2380 } 2381 } 2382 } 2383 getInitialAccumulatedPowerPolicy()2384 private static CarPowerPolicy getInitialAccumulatedPowerPolicy() { 2385 String initialPolicyId = ""; 2386 int[] enabledComponents = new int[0]; 2387 int[] disabledComponents = new int[LAST_POWER_COMPONENT - FIRST_POWER_COMPONENT + 1]; 2388 int disabledIndex = 0; 2389 for (int component = FIRST_POWER_COMPONENT; component <= LAST_POWER_COMPONENT; 2390 component++) { 2391 disabledComponents[disabledIndex++] = component; 2392 } 2393 return new CarPowerPolicy(initialPolicyId, enabledComponents, disabledComponents); 2394 } 2395 initializeRegisteredPowerPolicies( android.frameworks.automotive.powerpolicy.CarPowerPolicy[] policies)2396 private void initializeRegisteredPowerPolicies( 2397 android.frameworks.automotive.powerpolicy.CarPowerPolicy[] policies) { 2398 for (int i = 0; i < policies.length; i++) { 2399 CarPowerPolicy policy = convertPowerPolicyFromDaemon(policies[i]); 2400 List<String> enabledComponents = PowerComponentUtil.powerComponentsToStrings( 2401 Lists.asImmutableList(policy.getEnabledComponents())); 2402 List<String> disabledComponents = PowerComponentUtil.powerComponentsToStrings( 2403 Lists.asImmutableList(policy.getDisabledComponents())); 2404 mPolicyReader.definePowerPolicy(policy.getPolicyId(), 2405 enabledComponents.toArray(String[]::new), 2406 disabledComponents.toArray(String[]::new)); 2407 } 2408 mPowerPoliciesInitialized = true; 2409 mPowerPolicyInitializationLatch.countDown(); 2410 } 2411 2412 @VisibleForTesting initializePowerPolicy()2413 public void initializePowerPolicy() { 2414 if (mFeatureFlags.carPowerPolicyRefactoring()) { 2415 ICarPowerManagementDelegate daemon; 2416 synchronized (mLock) { 2417 daemon = mRefactoredCarPowerManagementDaemon; 2418 } 2419 PowerPolicyInitData powerPolicyInitData; 2420 if (daemon != null) { 2421 try { 2422 PowerPolicyCallback powerPolicyCallback = new PowerPolicyCallback(); 2423 powerPolicyInitData = daemon.notifyCarServiceReady(powerPolicyCallback); 2424 } catch (RemoteException e) { 2425 Slogf.e(TAG, e, "Failed to tell car power management daemon that " 2426 + "CarService is ready"); 2427 return; 2428 } 2429 } else { 2430 Slogf.w(TAG, "Failed to notify car service is ready, car power management " 2431 + "daemon is not available"); 2432 return; 2433 } 2434 mPolicyCallbackHelper.setPolicyCallbackReady(true); 2435 int[] registeredCustomComponents = powerPolicyInitData.registeredCustomComponents; 2436 Integer[] customComponents = new Integer[registeredCustomComponents.length]; 2437 for (int i = 0; i < customComponents.length; i++) { 2438 customComponents[i] = registeredCustomComponents[i]; 2439 } 2440 mPowerComponentHandler.registerCustomComponents(customComponents); 2441 initializeRegisteredPowerPolicies(powerPolicyInitData.registeredPolicies); 2442 CarPowerPolicy currentPolicy; 2443 synchronized (mLock) { 2444 currentPolicy = mCurrentAccumulatedPowerPolicy; 2445 } 2446 if (mIsReconnectionToPowerDaemon.get() && currentPolicy != null) { 2447 // If we've already connected to the power daemon and have reconnected, the daemon 2448 // most likely crashed and lost the power policy state, so use CPMS' current policy 2449 // instead. 2450 int status = applyPowerPolicy(currentPolicy.getPolicyId(), 2451 /* delayNotification= */ true, /* upToDaemon= */ false, /* force= */ false); 2452 if (status != PolicyOperationStatus.OK) { 2453 throw new IllegalArgumentException( 2454 PolicyOperationStatus.errorCodeToString(status)); 2455 } 2456 } else { 2457 CarPowerPolicy currentPowerPolicy = convertPowerPolicyFromDaemon( 2458 powerPolicyInitData.currentPowerPolicy); 2459 updateCurrentPowerPolicy(currentPowerPolicy); 2460 mPowerComponentHandler.applyPowerPolicy(currentPowerPolicy); 2461 notifyPowerPolicyChange(new PowerPolicyChangeNotification( 2462 mPowerComponentHandler.getLastModifiedComponents(), 2463 currentPowerPolicy, /* legacyNotification= */ false)); 2464 } 2465 // To cover the case where power state changed before connecting to CPPD. 2466 int currentPowerState = getPowerState(); 2467 if (currentPowerState != CarPowerManager.STATE_WAIT_FOR_VHAL 2468 && currentPowerState != CarPowerManager.STATE_ON) { 2469 Slogf.w(TAG, "Current power state is %s, doesn't correspond to wait for VHAL " 2470 + "or on state, skipping notification of power state to daemon.", 2471 powerStateToString(currentPowerState)); 2472 } else { 2473 mStateNotificationHandler.notifyPowerStateChange(currentPowerState); 2474 } 2475 } else { 2476 Slogf.i(TAG, "CPMS is taking control from carpowerpolicyd"); 2477 ICarPowerPolicySystemNotification daemon; 2478 synchronized (mLock) { 2479 daemon = mCarPowerPolicyDaemon; 2480 } 2481 PolicyState state; 2482 if (daemon != null) { 2483 try { 2484 state = daemon.notifyCarServiceReady(); 2485 } catch (RemoteException e) { 2486 Slogf.e(TAG, e, "Failed to tell car power management daemon that " 2487 + "CarService is ready"); 2488 return; 2489 } 2490 } else { 2491 Slogf.w(TAG, 2492 "Failed to notify car service is ready. car power management daemon " 2493 + "is not available"); 2494 return; 2495 } 2496 2497 String currentPowerPolicyId; 2498 String currentPolicyGroupId; 2499 synchronized (mLock) { 2500 mHasControlOverDaemon = true; 2501 currentPowerPolicyId = mCurrentPowerPolicyId; 2502 currentPolicyGroupId = mCurrentPowerPolicyGroupId; 2503 } 2504 // If the current power policy or the policy group has been modified by CPMS, we ignore 2505 // the power policy or the policy group passed from car power management daemon, and 2506 // notifies the current power policy to the daemon. 2507 if (currentPowerPolicyId == null || currentPowerPolicyId.isEmpty()) { 2508 Slogf.i(TAG, "Attempting to apply the power policy(%s) from the daemon", 2509 state.policyId); 2510 int status = applyPowerPolicy(state.policyId, /* delayNotification= */ false, 2511 /* upToDaemon= */ false, /* force= */ false); 2512 if (status != PolicyOperationStatus.OK) { 2513 Slogf.w(TAG, PolicyOperationStatus.errorCodeToString(status)); 2514 } 2515 } else { 2516 Slogf.i(TAG, 2517 "CPMS applied power policy(%s) before connecting to the daemon. Notifying " 2518 + "to the daemon...", currentPowerPolicyId); 2519 notifyPowerPolicyChangeToDaemon(currentPowerPolicyId, /* force= */ true); 2520 } 2521 if (currentPolicyGroupId == null || currentPolicyGroupId.isEmpty()) { 2522 int status = setCurrentPowerPolicyGroup(state.policyGroupId); 2523 if (status != PolicyOperationStatus.OK) { 2524 Slogf.w(TAG, PolicyOperationStatus.errorCodeToString(status)); 2525 } 2526 } 2527 } 2528 mSilentModeHandler.init(); 2529 } 2530 2531 @PolicyOperationStatus.ErrorCode setCurrentPowerPolicyGroup(String policyGroupId)2532 private int setCurrentPowerPolicyGroup(String policyGroupId) { 2533 if (!mPolicyReader.isPowerPolicyGroupAvailable(policyGroupId)) { 2534 int error = PolicyOperationStatus.ERROR_SET_POWER_POLICY_GROUP; 2535 Slogf.w(TAG, PolicyOperationStatus.errorCodeToString(error, 2536 policyGroupId + " is not registered")); 2537 return error; 2538 } 2539 synchronized (mLock) { 2540 mCurrentPowerPolicyGroupId = policyGroupId; 2541 } 2542 return PolicyOperationStatus.OK; 2543 } 2544 2545 private static final class AsyncPolicyRequest { 2546 private final Object mLock = new Object(); 2547 private final int mRequestId; 2548 private final long mTimeoutMs; 2549 private final CountDownLatch mPolicyRequestLatch = new CountDownLatch(1); 2550 @GuardedBy("mLock") 2551 private boolean mPolicyRequestSucceeded; 2552 @GuardedBy("mLock") 2553 @Nullable 2554 private CarPowerPolicy mAccumulatedPolicy; 2555 @GuardedBy("mLock") 2556 @PowerPolicyFailureReason 2557 private int mFailureReason; 2558 @GuardedBy("mLock") 2559 private boolean mIsDeferred; 2560 AsyncPolicyRequest(int requestId, long timeoutMs)2561 AsyncPolicyRequest(int requestId, long timeoutMs) { 2562 mRequestId = requestId; 2563 mTimeoutMs = timeoutMs; 2564 } 2565 getRequestId()2566 public int getRequestId() { 2567 return mRequestId; 2568 } 2569 isSuccessful()2570 public boolean isSuccessful() { 2571 synchronized (mLock) { 2572 return mPolicyRequestSucceeded; 2573 } 2574 } 2575 2576 @Nullable getAccumulatedPolicy()2577 public CarPowerPolicy getAccumulatedPolicy() { 2578 synchronized (mLock) { 2579 return mAccumulatedPolicy; 2580 } 2581 } 2582 2583 @PowerPolicyFailureReason getFailureReason()2584 public int getFailureReason() { 2585 synchronized (mLock) { 2586 return mFailureReason; 2587 } 2588 } 2589 isDeferred()2590 public boolean isDeferred() { 2591 synchronized (mLock) { 2592 return mIsDeferred; 2593 } 2594 } 2595 await()2596 public boolean await() throws InterruptedException { 2597 return mPolicyRequestLatch.await(mTimeoutMs, TimeUnit.MILLISECONDS); 2598 } 2599 onPolicyRequestSucceeded(CarPowerPolicy accumulatedPolicy, boolean deferred)2600 public void onPolicyRequestSucceeded(CarPowerPolicy accumulatedPolicy, boolean deferred) { 2601 synchronized (mLock) { 2602 mPolicyRequestSucceeded = true; 2603 if (!deferred) { 2604 mAccumulatedPolicy = accumulatedPolicy; 2605 } 2606 mIsDeferred = deferred; 2607 } 2608 mPolicyRequestLatch.countDown(); 2609 } 2610 onPolicyRequestFailed(@owerPolicyFailureReason int reason)2611 public void onPolicyRequestFailed(@PowerPolicyFailureReason int reason) { 2612 synchronized (mLock) { 2613 mFailureReason = reason; 2614 } 2615 mPolicyRequestLatch.countDown(); 2616 } 2617 } 2618 generateAsyncPolicyRequest(long timeoutMs)2619 private AsyncPolicyRequest generateAsyncPolicyRequest(long timeoutMs) { 2620 int requestId = mPolicyRequestIdCounter.getAndIncrement(); 2621 return new AsyncPolicyRequest(requestId, timeoutMs); 2622 } 2623 2624 @PolicyOperationStatus.ErrorCode getPolicyRequestError(int requestId, @PowerPolicyFailureReason int reason)2625 private int getPolicyRequestError(int requestId, @PowerPolicyFailureReason int reason) { 2626 switch(reason) { 2627 case PowerPolicyFailureReason.POWER_POLICY_FAILURE_UNKNOWN: 2628 Slogf.w(TAG, "Power policy request %d failed for unknown reason", 2629 requestId); 2630 return PolicyOperationStatus.ERROR_APPLY_POWER_POLICY; 2631 case PowerPolicyFailureReason.POWER_POLICY_FAILURE_NOT_REGISTERED_ID: 2632 Slogf.w(TAG, "Power policy request %d failed due to unregistered" 2633 + "power policy ID", requestId); 2634 return PolicyOperationStatus.ERROR_NOT_REGISTERED_POWER_POLICY_ID; 2635 case PowerPolicyFailureReason.POWER_POLICY_FAILURE_CANNOT_OVERRIDE: 2636 Slogf.w(TAG, "Power policy request %d failed because current non-" 2637 + "preemptive power policy cannot be overridden", requestId); 2638 return PolicyOperationStatus.ERROR_APPLY_POWER_POLICY; 2639 default: 2640 Slogf.w(TAG, "Reason for power policy request %d failing is " 2641 + "undefined", requestId); 2642 return PolicyOperationStatus.ERROR_APPLY_POWER_POLICY; 2643 } 2644 } 2645 2646 @PolicyOperationStatus.ErrorCode applyPowerPolicy(@ullable String policyId, boolean delayNotification, boolean upToDaemon, boolean force)2647 private int applyPowerPolicy(@Nullable String policyId, boolean delayNotification, 2648 boolean upToDaemon, boolean force) { 2649 if (mFeatureFlags.carPowerPolicyRefactoring()) { 2650 Trace.traceBegin(TraceHelper.TRACE_TAG_CAR_SERVICE, "applyPowerPolicy"); 2651 AsyncPolicyRequest request = generateAsyncPolicyRequest( 2652 DEFAULT_POWER_POLICY_REQUEST_TIMEOUT_MS); 2653 int requestId = request.getRequestId(); 2654 ICarPowerManagementDelegate daemon; 2655 synchronized (mLock) { 2656 daemon = mRefactoredCarPowerManagementDaemon; 2657 mRequestIdToPolicyRequest.put(requestId, request); 2658 } 2659 if (daemon == null) { 2660 Slogf.w(TAG, "Cannot call applyPowerPolicyAsync(requestId=%d, policyId=%s) to CPPD:" 2661 + " CPPD is not available", requestId, policyId); 2662 Trace.traceEnd(TraceHelper.TRACE_TAG_CAR_SERVICE); 2663 return PolicyOperationStatus.ERROR_APPLY_POWER_POLICY; 2664 } 2665 if (!mPolicyCallbackHelper.isPolicyCallbackReady()) { 2666 Slogf.w(TAG, "Cannot call applyPowerPolicyAsync(requestId=%d, policyId=%s) to CPPD:" 2667 + " not ready for calling to CPPD", requestId, policyId); 2668 Trace.traceEnd(TraceHelper.TRACE_TAG_CAR_SERVICE); 2669 return PolicyOperationStatus.ERROR_APPLY_POWER_POLICY; 2670 } 2671 try { 2672 Slogf.i(TAG, "Request(%d) of applying power policy(%s) to CPPD in async", requestId, 2673 policyId); 2674 daemon.applyPowerPolicyAsync(requestId, policyId, force); 2675 boolean policyRequestServed = request.await(); 2676 if (!policyRequestServed) { 2677 Slogf.w(TAG, "Power policy request (ID: %d) successful application timed out" 2678 + " after %d ms", requestId, DEFAULT_POWER_POLICY_REQUEST_TIMEOUT_MS); 2679 Trace.traceEnd(TraceHelper.TRACE_TAG_CAR_SERVICE); 2680 return PolicyOperationStatus.ERROR_APPLY_POWER_POLICY; 2681 } 2682 } catch (IllegalArgumentException e) { 2683 int error = PolicyOperationStatus.ERROR_INVALID_POWER_POLICY_ID; 2684 Slogf.w(TAG, PolicyOperationStatus.errorCodeToString(error, policyId)); 2685 Trace.traceEnd(TraceHelper.TRACE_TAG_CAR_SERVICE); 2686 return error; 2687 } catch (IllegalStateException e) { 2688 int error = PolicyOperationStatus.ERROR_APPLY_POWER_POLICY; 2689 Slogf.w(TAG, PolicyOperationStatus.errorCodeToString(error, policyId)); 2690 Trace.traceEnd(TraceHelper.TRACE_TAG_CAR_SERVICE); 2691 return error; 2692 } catch (SecurityException e) { 2693 Slogf.w(TAG, e, "Failed to apply power policy, insufficient permissions"); 2694 Trace.traceEnd(TraceHelper.TRACE_TAG_CAR_SERVICE); 2695 return PolicyOperationStatus.ERROR_APPLY_POWER_POLICY; 2696 } catch (InterruptedException e) { 2697 Slogf.w(TAG, e, "Wait for power policy change request interrupted"); 2698 Thread.currentThread().interrupt(); 2699 Trace.traceEnd(TraceHelper.TRACE_TAG_CAR_SERVICE); 2700 return PolicyOperationStatus.ERROR_APPLY_POWER_POLICY; 2701 } catch (RemoteException e) { 2702 Slogf.w(TAG, e, "Failed to apply power policy, connection issue"); 2703 Trace.traceEnd(TraceHelper.TRACE_TAG_CAR_SERVICE); 2704 return PolicyOperationStatus.ERROR_APPLY_POWER_POLICY; 2705 } finally { 2706 synchronized (mLock) { 2707 mRequestIdToPolicyRequest.remove(requestId); 2708 } 2709 } 2710 if (!request.isSuccessful()) { 2711 Slogf.w(TAG, "Failed to apply power policy, failure reason = %d", 2712 request.getFailureReason()); 2713 Trace.traceEnd(TraceHelper.TRACE_TAG_CAR_SERVICE); 2714 return getPolicyRequestError(requestId, request.getFailureReason()); 2715 } 2716 if (request.isDeferred()) { 2717 Slogf.i(TAG, "Applying power policy(%s) is deferred", policyId); 2718 Trace.traceEnd(TraceHelper.TRACE_TAG_CAR_SERVICE); 2719 return PolicyOperationStatus.OK; 2720 } 2721 CarPowerPolicy accumulatedPolicy = request.getAccumulatedPolicy(); 2722 updateCurrentPowerPolicy(accumulatedPolicy); 2723 PowerPolicyChangeNotification notification = new PowerPolicyChangeNotification(policyId, 2724 mPowerComponentHandler.getLastModifiedComponents(), 2725 mPowerComponentHandler.getAccumulatedPolicy(), /* legacyNotification= */ false); 2726 if (delayNotification) { 2727 Slogf.d(TAG, 2728 "Queueing power policy notification (id: %s) in the handler", policyId); 2729 mHandler.handlePowerPolicyNotification(notification); 2730 } else { 2731 notifyPowerPolicyChange(notification); 2732 } 2733 Trace.traceEnd(TraceHelper.TRACE_TAG_CAR_SERVICE); 2734 } else { 2735 CarPowerPolicy policy = mPolicyReader.getPowerPolicy(policyId); 2736 if (policy == null) { 2737 int error = PolicyOperationStatus.ERROR_NOT_REGISTERED_POWER_POLICY_ID; 2738 Slogf.w(TAG, PolicyOperationStatus.errorCodeToString(error, policyId)); 2739 return error; 2740 } 2741 synchronized (mLock) { 2742 if (mIsPowerPolicyLocked) { 2743 Slogf.i(TAG, "Power policy is locked. The request policy(%s) will be applied " 2744 + "when power policy becomes unlocked", policyId); 2745 mPendingPowerPolicyId = policyId; 2746 return PolicyOperationStatus.OK; 2747 } 2748 mCurrentPowerPolicyId = policyId; 2749 } 2750 mPowerComponentHandler.applyPowerPolicy(policy); 2751 PowerPolicyChangeNotification notification = new PowerPolicyChangeNotification( 2752 mPowerComponentHandler.getLastModifiedComponents(), 2753 policy, /* legacyNotification= */ true); 2754 if (delayNotification) { 2755 Slogf.d(TAG, 2756 "Queueing power policy notification (id: %s) in the handler", policyId); 2757 mHandler.handlePowerPolicyNotification(notification); 2758 } else { 2759 notifyPowerPolicyChange(notification, upToDaemon, force); 2760 } 2761 } 2762 Slogf.i(TAG, "The current power policy is %s", policyId); 2763 return PolicyOperationStatus.OK; 2764 } 2765 2766 @PolicyOperationStatus.ErrorCode applyPreemptivePowerPolicy(String policyId)2767 private int applyPreemptivePowerPolicy(String policyId) { 2768 CarPowerPolicy policy = mPolicyReader.getPreemptivePowerPolicy(policyId); 2769 if (policy == null) { 2770 int error = PolicyOperationStatus.ERROR_NOT_REGISTERED_POWER_POLICY_ID; 2771 Slogf.w(TAG, PolicyOperationStatus.errorCodeToString(error, policyId)); 2772 return error; 2773 } 2774 synchronized (mLock) { 2775 mIsPowerPolicyLocked = true; 2776 if (!mPolicyReader.isPreemptivePowerPolicy(mCurrentPowerPolicyId)) { 2777 mPendingPowerPolicyId = mCurrentPowerPolicyId; 2778 } 2779 mCurrentPowerPolicyId = policyId; 2780 } 2781 mPowerComponentHandler.applyPowerPolicy(policy); 2782 notifyPowerPolicyChange(new PowerPolicyChangeNotification(policyId, 2783 mPowerComponentHandler.getLastModifiedComponents(), 2784 mPowerComponentHandler.getAccumulatedPolicy(), 2785 /* legacyNotification= */ true), 2786 /* upToDaemon= */ true, /* force= */ true); 2787 Slogf.i(TAG, "The current power policy is %s", policyId); 2788 return PolicyOperationStatus.OK; 2789 } 2790 cancelPreemptivePowerPolicy()2791 private void cancelPreemptivePowerPolicy() { 2792 Slogf.i(TAG, "Canceling preemptive power policy"); 2793 String policyId; 2794 synchronized (mLock) { 2795 if (!mIsPowerPolicyLocked) { 2796 Slogf.w(TAG, "Failed to cancel system power policy: the current policy is not the " 2797 + "system power policy"); 2798 return; 2799 } 2800 mIsPowerPolicyLocked = false; 2801 policyId = mPendingPowerPolicyId; 2802 mPendingPowerPolicyId = null; 2803 } 2804 if (policyId != null) { // Pending policy exist 2805 int status = applyPowerPolicy(policyId, /* delayNotification= */ false, 2806 /* upToDaemon= */ true, /* force= */ true); 2807 if (status != PolicyOperationStatus.OK) { 2808 Slogf.w(TAG, "Failed to cancel system power policy: %s", 2809 PolicyOperationStatus.errorCodeToString(status)); 2810 } 2811 } else { 2812 Slogf.w(TAG, "cancelPreemptivePowerPolicy(), no pending power policy"); 2813 } 2814 } 2815 notifyPowerPolicyChangeToDaemon(String policyId, boolean force)2816 private void notifyPowerPolicyChangeToDaemon(String policyId, boolean force) { 2817 ICarPowerPolicySystemNotification daemon; 2818 synchronized (mLock) { 2819 daemon = mCarPowerPolicyDaemon; 2820 if (daemon == null) { 2821 Slogf.e(TAG, "Failed to notify car power management daemon: the daemon is not " 2822 + "ready"); 2823 return; 2824 } 2825 if (!mHasControlOverDaemon) { 2826 Slogf.w(TAG, "Notifying policy change is deferred: CPMS has not yet taken control"); 2827 return; 2828 } 2829 } 2830 try { 2831 daemon.notifyPowerPolicyChange(policyId, force); 2832 } catch (RemoteException | IllegalStateException e) { 2833 Slogf.e(TAG, e, "Failed to notify car power management daemon of a new power " 2834 + "policy(%s)", policyId); 2835 } 2836 } 2837 2838 // TODO(b/286303350): remove after power policy refactor is complete - will only use version 2839 // that takes 'accumulatedPowerPolicy' as input notifyPowerPolicyChange(PowerPolicyChangeNotification policyChangeNotification, boolean upToDaemon, boolean force)2840 private void notifyPowerPolicyChange(PowerPolicyChangeNotification policyChangeNotification, 2841 boolean upToDaemon, boolean force) { 2842 // Notify system clients 2843 String policyId = policyChangeNotification.policyId; 2844 if (upToDaemon) { 2845 notifyPowerPolicyChangeToDaemon(policyId, force); 2846 } 2847 // Notify Java clients 2848 CarPowerPolicy appliedPolicy = mPolicyReader.isPreemptivePowerPolicy(policyId) 2849 ? mPolicyReader.getPreemptivePowerPolicy(policyId) 2850 : mPolicyReader.getPowerPolicy(policyId); 2851 CarPowerPolicy accumulatedPolicy = mPowerComponentHandler.getAccumulatedPolicy(); 2852 notifyPowerPolicyChangeToListeners(policyChangeNotification, appliedPolicy); 2853 } 2854 2855 @Nullable getPowerPolicyDefinition(String policyId, long timeoutMs)2856 private CarPowerPolicy getPowerPolicyDefinition(String policyId, long timeoutMs) 2857 throws InterruptedException { 2858 if (!mPowerPoliciesInitialized) { 2859 boolean result = 2860 mPowerPolicyInitializationLatch.await(timeoutMs, TimeUnit.MILLISECONDS); 2861 if (!result) { 2862 Slogf.e(TAG, "Failed to get power policy initialization after waiting %d ms", 2863 timeoutMs); 2864 return null; 2865 } 2866 } 2867 return mPolicyReader.getPowerPolicy(policyId); 2868 } 2869 notifyPowerPolicyChange(PowerPolicyChangeNotification policyChangeNotification)2870 private void notifyPowerPolicyChange(PowerPolicyChangeNotification policyChangeNotification) { 2871 String policyId = policyChangeNotification.policyId; 2872 try { 2873 CarPowerPolicy appliedPolicy = 2874 getPowerPolicyDefinition(policyId, CAR_POWER_MANAGEMENT_DEFINITION_TIMEOUT_MS); 2875 if (appliedPolicy == null) { 2876 Slogf.wtf(TAG, "The new power policy(%s) should exist", policyId); 2877 return; 2878 } 2879 notifyPowerPolicyChangeToListeners(policyChangeNotification, appliedPolicy); 2880 } catch (InterruptedException e) { 2881 Slogf.e(TAG, e, "Failed to get power policy definition for policy ID %s", policyId); 2882 } 2883 } 2884 notifyPowerPolicyChangeToListeners( PowerPolicyChangeNotification policyChangeNotification, CarPowerPolicy appliedPolicy)2885 private void notifyPowerPolicyChangeToListeners( 2886 PowerPolicyChangeNotification policyChangeNotification, CarPowerPolicy appliedPolicy) { 2887 String policyId = policyChangeNotification.policyId; 2888 2889 SparseBooleanArray updatedComponents = policyChangeNotification.lastModifiedComponents; 2890 2891 EventLogHelper.writePowerPolicyChange(policyId); 2892 2893 if (appliedPolicy == null) { 2894 Slogf.wtf(TAG, "The new power policy(%s) should exist", policyId); 2895 } 2896 Slogf.i(TAG, "Power policy change to %s is notified to apps", policyId); 2897 mBroadcastHandler.post(() -> { 2898 Trace.traceBegin(TraceHelper.TRACE_TAG_CAR_SERVICE, "notifyPowerPolicyChange"); 2899 int idx = mPowerPolicyListeners.beginBroadcast(); 2900 2901 while (idx-- > 0) { 2902 ICarPowerPolicyListener listener = mPowerPolicyListeners.getBroadcastItem(idx); 2903 CarPowerPolicyFilter filter = 2904 (CarPowerPolicyFilter) mPowerPolicyListeners.getBroadcastCookie(idx); 2905 if (!PowerComponentHandler.isComponentChanged(updatedComponents, filter)) { 2906 continue; 2907 } 2908 try { 2909 listener.onPolicyChanged(appliedPolicy, 2910 policyChangeNotification.accumulatedPolicy); 2911 } catch (RemoteException e) { 2912 // It's likely the connection snapped. Let binder death handle the situation. 2913 Slogf.e(TAG, e, "onPolicyChanged() call failed: policyId = %s", policyId); 2914 } 2915 } 2916 mPowerPolicyListeners.finishBroadcast(); 2917 Trace.traceEnd(TraceHelper.TRACE_TAG_CAR_SERVICE); 2918 }); 2919 } 2920 makeSureNoUserInteraction()2921 private void makeSureNoUserInteraction() { 2922 mSilentModeHandler.updateKernelSilentMode(true); 2923 int status; 2924 if (mFeatureFlags.carPowerPolicyRefactoring()) { 2925 status = applyPowerPolicy(PolicyReader.POWER_POLICY_ID_NO_USER_INTERACTION, 2926 /* delayNotification= */ false, /* upToDaemon= */ false, /* force= */ true); 2927 } else { 2928 status = applyPreemptivePowerPolicy( 2929 PolicyReader.POWER_POLICY_ID_NO_USER_INTERACTION); 2930 } 2931 if (status != PolicyOperationStatus.OK) { 2932 Slogf.w(TAG, PolicyOperationStatus.errorCodeToString(status)); 2933 } 2934 } 2935 getPowerManagementDaemonLocked()2936 private android.os.IInterface getPowerManagementDaemonLocked() { 2937 if (mFeatureFlags.carPowerPolicyRefactoring()) { 2938 return mRefactoredCarPowerManagementDaemon; 2939 } else { 2940 return mCarPowerPolicyDaemon; 2941 } 2942 } 2943 connectToPowerManagementDaemon()2944 private void connectToPowerManagementDaemon() { 2945 Trace.asyncTraceBegin(TraceHelper.TRACE_TAG_CAR_SERVICE, 2946 "connectToPowerManagementDaemon", /* cookie= */ 0); 2947 synchronized (mLock) { 2948 android.os.IInterface powerManagementDaemon = getPowerManagementDaemonLocked(); 2949 if (powerManagementDaemon != null || mConnectionInProgress) { 2950 Trace.asyncTraceEnd(TraceHelper.TRACE_TAG_CAR_SERVICE, 2951 "connectToPowerManagementDaemon", /* cookie= */ 0); 2952 return; 2953 } 2954 mConnectionInProgress = true; 2955 } 2956 connectToDaemonHelper(CAR_POWER_MANAGEMENT_DAEMON_BIND_MAX_RETRY); 2957 } 2958 connectToDaemonHelper(int retryCount)2959 private void connectToDaemonHelper(int retryCount) { 2960 if (retryCount <= 0) { 2961 synchronized (mLock) { 2962 mConnectionInProgress = false; 2963 } 2964 Slogf.e(TAG, "Cannot reconnect to car power policyd daemon after retrying %d times", 2965 CAR_POWER_MANAGEMENT_DAEMON_BIND_MAX_RETRY); 2966 Trace.asyncTraceEnd(TraceHelper.TRACE_TAG_CAR_SERVICE, "connectToPowerManagementDaemon", 2967 /* cookie= */ 0); 2968 return; 2969 } 2970 if (makeBinderConnection()) { 2971 Slogf.i(TAG, "Connected to car power policy daemon"); 2972 initializePowerPolicy(); 2973 Trace.asyncTraceEnd(TraceHelper.TRACE_TAG_CAR_SERVICE, "connectToPowerManagementDaemon", 2974 /* cookie= */ 0); 2975 return; 2976 } 2977 final int numRetry = retryCount - 1; 2978 mHandler.postDelayed(() -> connectToDaemonHelper(numRetry), 2979 CAR_POWER_MANAGEMENT_DAEMON_BIND_RETRY_INTERVAL_MS); 2980 } 2981 makeBinderConnection()2982 private boolean makeBinderConnection() { 2983 long currentTimeMs = SystemClock.uptimeMillis(); 2984 IBinder binder; 2985 if (mFeatureFlags.carPowerPolicyRefactoring()) { 2986 binder = ServiceManagerHelper.getService( 2987 REFACTORED_CAR_POWER_MANAGEMENT_DAEMON_INTERFACE); 2988 } else { 2989 binder = ServiceManagerHelper.getService(CAR_POWER_POLICY_DAEMON_INTERFACE); 2990 } 2991 if (binder == null) { 2992 Slogf.w(TAG, "Finding car power management daemon failed. Power management is not " 2993 + "supported"); 2994 return false; 2995 } 2996 long elapsedTimeMs = SystemClock.uptimeMillis() - currentTimeMs; 2997 if (elapsedTimeMs > CAR_POWER_MANAGEMENT_DAEMON_FIND_MARGINAL_TIME_MS) { 2998 Slogf.wtf(TAG, "Finding car power Management daemon took too long(%dms)", 2999 elapsedTimeMs); 3000 } 3001 3002 if (mFeatureFlags.carPowerPolicyRefactoring()) { 3003 ICarPowerManagementDelegate daemon = 3004 ICarPowerManagementDelegate.Stub.asInterface(binder); 3005 if (daemon == null) { 3006 Slogf.w(TAG, "Getting car power management daemon interface failed. Power " 3007 + "management is not supported"); 3008 return false; 3009 } 3010 synchronized (mLock) { 3011 mRefactoredCarPowerManagementDaemon = daemon; 3012 mConnectionInProgress = false; 3013 } 3014 mBinderHandler = new BinderHandler(daemon); 3015 } else { 3016 ICarPowerPolicySystemNotification daemon = 3017 ICarPowerPolicySystemNotification.Stub.asInterface(binder); 3018 if (daemon == null) { 3019 Slogf.w(TAG, "Getting car power management daemon interface failed. Power " 3020 + "management is not supported"); 3021 return false; 3022 } 3023 synchronized (mLock) { 3024 mCarPowerPolicyDaemon = daemon; 3025 mConnectionInProgress = false; 3026 } 3027 mBinderHandler = new BinderHandler(daemon); 3028 } 3029 mBinderHandler.linkToDeath(); 3030 return true; 3031 } 3032 updateCurrentPowerPolicy(CarPowerPolicy accumulatedPolicy)3033 private void updateCurrentPowerPolicy(CarPowerPolicy accumulatedPolicy) { 3034 synchronized (mLock) { 3035 mCurrentPowerPolicyId = accumulatedPolicy.getPolicyId(); 3036 mCurrentAccumulatedPowerPolicy = accumulatedPolicy; 3037 } 3038 } 3039 3040 private static final class PolicyCallbackHelper { 3041 private static final long CAR_POWER_MANAGEMENT_DAEMON_CONNECTION_TIMEOUT_MS = 3042 CAR_POWER_MANAGEMENT_DAEMON_BIND_MAX_RETRY 3043 * CAR_POWER_MANAGEMENT_DAEMON_BIND_RETRY_INTERVAL_MS; 3044 private final Object mReadyLock = new Object(); 3045 @GuardedBy("mReadyLock") 3046 private boolean mCallbackReady; 3047 setPolicyCallbackReady(boolean ready)3048 public void setPolicyCallbackReady(boolean ready) { 3049 synchronized (mReadyLock) { 3050 mCallbackReady = ready; 3051 mReadyLock.notifyAll(); 3052 } 3053 } 3054 isPolicyCallbackReady()3055 public boolean isPolicyCallbackReady() { 3056 synchronized (mReadyLock) { 3057 return mCallbackReady; 3058 } 3059 } 3060 waitForPolicyCallbackReady()3061 public boolean waitForPolicyCallbackReady() throws InterruptedException { 3062 synchronized (mReadyLock) { 3063 long waitStartTime = SystemClock.uptimeMillis(); 3064 while (!mCallbackReady && (SystemClock.uptimeMillis() - waitStartTime) 3065 < CAR_POWER_MANAGEMENT_DAEMON_CONNECTION_TIMEOUT_MS) { 3066 mReadyLock.wait(CAR_POWER_MANAGEMENT_DAEMON_CONNECTION_TIMEOUT_MS); 3067 } 3068 return mCallbackReady; 3069 } 3070 } 3071 3072 // TODO(b/409798785): Create a cancelWait() method to notify and stop the wait for callback 3073 // to be ready, if currently waiting. To be called before handler thread is destroyed. 3074 } 3075 3076 private final class BinderHandler implements IBinder.DeathRecipient { 3077 // TODO(b/286303350): replace with refactored daemon once power policy refactor is complete 3078 private ICarPowerPolicySystemNotification mDaemon; 3079 private ICarPowerManagementDelegate mRefactoredDaemon; 3080 BinderHandler(ICarPowerPolicySystemNotification daemon)3081 private BinderHandler(ICarPowerPolicySystemNotification daemon) { 3082 mDaemon = daemon; 3083 } 3084 BinderHandler(ICarPowerManagementDelegate daemon)3085 private BinderHandler(ICarPowerManagementDelegate daemon) { 3086 mRefactoredDaemon = daemon; 3087 } 3088 3089 @Override binderDied()3090 public void binderDied() { 3091 Slogf.w(TAG, "Car power policy daemon died: reconnecting"); 3092 unlinkToDeath(); 3093 if (mFeatureFlags.carPowerPolicyRefactoring()) { 3094 mRefactoredDaemon = null; 3095 } else { 3096 mDaemon = null; 3097 } 3098 mPolicyCallbackHelper.setPolicyCallbackReady(false); 3099 synchronized (mLock) { 3100 if (mFeatureFlags.carPowerPolicyRefactoring()) { 3101 mRefactoredCarPowerManagementDaemon = null; 3102 } else { 3103 mCarPowerPolicyDaemon = null; 3104 mHasControlOverDaemon = false; 3105 } 3106 } 3107 mIsReconnectionToPowerDaemon.set(true); 3108 mHandler.postDelayed( 3109 () -> connectToDaemonHelper(CAR_POWER_MANAGEMENT_DAEMON_BIND_MAX_RETRY), 3110 CAR_POWER_MANAGEMENT_DAEMON_BIND_RETRY_INTERVAL_MS); 3111 } 3112 linkToDeath()3113 private void linkToDeath() { 3114 if (mFeatureFlags.carPowerPolicyRefactoring()) { 3115 if (mRefactoredDaemon == null) { 3116 return; 3117 } 3118 } else { 3119 if (mDaemon == null) { 3120 return; 3121 } 3122 } 3123 IBinder binder; 3124 if (mFeatureFlags.carPowerPolicyRefactoring()) { 3125 binder = mRefactoredDaemon.asBinder(); 3126 } else { 3127 binder = mDaemon.asBinder(); 3128 } 3129 if (binder == null) { 3130 Slogf.w(TAG, "Linking to binder death recipient skipped"); 3131 return; 3132 } 3133 try { 3134 binder.linkToDeath(this, 0); 3135 } catch (RemoteException e) { 3136 if (mFeatureFlags.carPowerPolicyRefactoring()) { 3137 mRefactoredDaemon = null; 3138 } else { 3139 mDaemon = null; 3140 } 3141 Slogf.w(TAG, e, "Linking to binder death recipient failed: %s"); 3142 } 3143 } 3144 unlinkToDeath()3145 private void unlinkToDeath() { 3146 if (mFeatureFlags.carPowerPolicyRefactoring()) { 3147 if (mRefactoredDaemon == null) { 3148 return; 3149 } 3150 } else { 3151 if (mDaemon == null) { 3152 return; 3153 } 3154 } 3155 IBinder binder; 3156 if (mFeatureFlags.carPowerPolicyRefactoring()) { 3157 binder = mRefactoredDaemon.asBinder(); 3158 } else { 3159 binder = mDaemon.asBinder(); 3160 } 3161 if (binder == null) { 3162 Slogf.w(TAG, "Unlinking from binder death recipient skipped"); 3163 return; 3164 } 3165 binder.unlinkToDeath(this, 0); 3166 } 3167 } 3168 3169 private final class PowerHandler extends Handler { 3170 private static final String TAG = PowerHandler.class.getSimpleName(); 3171 private static final int MSG_POWER_STATE_CHANGE = 0; 3172 private static final int MSG_DISPLAY_BRIGHTNESS_CHANGE = 1; 3173 private static final int MSG_DISPLAY_STATE_CHANGE = 2; 3174 private static final int MSG_PROCESSING_COMPLETE = 3; 3175 private static final int MSG_POWER_POLICY_NOTIFICATION = 4; 3176 3177 // Do not handle this immediately but with some delay as there can be a race between 3178 // display off due to rear view camera and delivery to here. 3179 private static final long MAIN_DISPLAY_EVENT_DELAY_MS = 500; 3180 3181 private final WeakReference<CarPowerManagementService> mService; 3182 PowerHandler(Looper looper, CarPowerManagementService service)3183 private PowerHandler(Looper looper, CarPowerManagementService service) { 3184 super(looper); 3185 mService = new WeakReference<CarPowerManagementService>(service); 3186 } 3187 handlePowerStateChange()3188 private void handlePowerStateChange() { 3189 Message msg = obtainMessage(MSG_POWER_STATE_CHANGE); 3190 sendMessage(msg); 3191 } 3192 handleDisplayBrightnessChange(int displayId, int brightness)3193 private void handleDisplayBrightnessChange(int displayId, int brightness) { 3194 Message msg = obtainMessage(MSG_DISPLAY_BRIGHTNESS_CHANGE, displayId, brightness); 3195 sendMessage(msg); 3196 } 3197 handleDisplayStateChange(int displayId, boolean on)3198 private void handleDisplayStateChange(int displayId, boolean on) { 3199 HandlerHelper.removeEqualMessages(this, MSG_DISPLAY_STATE_CHANGE, displayId); 3200 Message msg = obtainMessage(MSG_DISPLAY_STATE_CHANGE, displayId); 3201 msg.arg1 = on ? Display.STATE_ON : Display.STATE_OFF; 3202 sendMessageDelayed(msg, MAIN_DISPLAY_EVENT_DELAY_MS); 3203 } 3204 handleProcessingComplete()3205 private void handleProcessingComplete() { 3206 removeMessages(MSG_PROCESSING_COMPLETE); 3207 Message msg = obtainMessage(MSG_PROCESSING_COMPLETE); 3208 sendMessage(msg); 3209 } 3210 cancelProcessingComplete()3211 private void cancelProcessingComplete() { 3212 removeMessages(MSG_PROCESSING_COMPLETE); 3213 } 3214 3215 handlePowerPolicyNotification(PowerPolicyChangeNotification notification)3216 private void handlePowerPolicyNotification(PowerPolicyChangeNotification notification) { 3217 Message msg = obtainMessage(MSG_POWER_POLICY_NOTIFICATION, notification); 3218 sendMessage(msg); 3219 } 3220 cancelAll()3221 private void cancelAll() { 3222 removeMessages(MSG_POWER_STATE_CHANGE); 3223 removeMessages(MSG_DISPLAY_BRIGHTNESS_CHANGE); 3224 removeMessages(MSG_DISPLAY_STATE_CHANGE); 3225 removeMessages(MSG_PROCESSING_COMPLETE); 3226 removeMessages(MSG_POWER_POLICY_NOTIFICATION); 3227 } 3228 3229 @Override handleMessage(Message msg)3230 public void handleMessage(Message msg) { 3231 CarPowerManagementService service = mService.get(); 3232 if (service == null) { 3233 Slogf.i(TAG, "handleMessage null service"); 3234 return; 3235 } 3236 switch (msg.what) { 3237 case MSG_POWER_STATE_CHANGE: 3238 service.doHandlePowerStateChange(); 3239 break; 3240 case MSG_DISPLAY_BRIGHTNESS_CHANGE: 3241 service.doHandleDisplayBrightnessChange( 3242 /* displayId= */ msg.arg1, /* brightness= */ msg.arg2); 3243 break; 3244 case MSG_DISPLAY_STATE_CHANGE: 3245 int displayId = (Integer) msg.obj; 3246 boolean on = msg.arg1 == Display.STATE_ON; 3247 service.doHandleDisplayStateChange(displayId, on); 3248 break; 3249 case MSG_PROCESSING_COMPLETE: 3250 service.doHandleProcessingComplete(); 3251 break; 3252 case MSG_POWER_POLICY_NOTIFICATION: 3253 service.doHandlePowerPolicyNotification( 3254 (PowerPolicyChangeNotification) msg.obj); 3255 break; 3256 default: 3257 Slogf.w(TAG, "handleMessage invalid message type: %d", msg.what); 3258 break; 3259 } 3260 } 3261 } 3262 3263 private final class PowerStateNotificationHandler extends Handler { 3264 private static final String TAG = PowerStateNotificationHandler.class.getSimpleName(); 3265 private static final int MSG_POWER_STATE_CHANGE = 0; 3266 private static final List<Integer> WAIT_FOR_VHAL_LISTENER_STATES = List.of( 3267 CarPowerManager.STATE_WAIT_FOR_VHAL, CarPowerManager.STATE_SHUTDOWN_CANCELLED, 3268 CarPowerManager.STATE_HIBERNATION_EXIT, CarPowerManager.STATE_SUSPEND_EXIT); 3269 private final Object mHandlerLock = new Object(); 3270 @GuardedBy("mHandlerLock") 3271 private int mLastNotifiedState; PowerStateNotificationHandler(Looper looper)3272 private PowerStateNotificationHandler(Looper looper) { 3273 super(looper); 3274 } 3275 3276 /** 3277 * Notifies handler of a potential power state change. If the given power state has a 3278 * default power policy, queue a message to request the daemon to apply it. 3279 */ notifyPowerStateChange(@arPowerManager.CarPowerState int state)3280 private void notifyPowerStateChange(@CarPowerManager.CarPowerState int state) { 3281 synchronized (mHandlerLock) { 3282 if (mLastNotifiedState == state) { 3283 Slogf.i(TAG, "Power state change notification for %s already notified", 3284 powerStateToString(state)); 3285 return; 3286 } 3287 mLastNotifiedState = state; 3288 } 3289 if (state != CarPowerManager.STATE_ON 3290 && !WAIT_FOR_VHAL_LISTENER_STATES.contains(state)) { 3291 Slogf.d(TAG, "Power state does not have default power policy, skipping"); 3292 return; 3293 } 3294 Message msg = obtainMessage(MSG_POWER_STATE_CHANGE); 3295 msg.arg1 = state; 3296 sendMessage(msg); 3297 } 3298 cancelAll()3299 private void cancelAll() { 3300 removeMessages(MSG_POWER_STATE_CHANGE); 3301 } 3302 3303 // TODO(b/384052834): Move logic into car power daemon delegateDefaultPowerPolicyForStateToDaemon( @arPowerManager.CarPowerState int powerState)3304 private void delegateDefaultPowerPolicyForStateToDaemon( 3305 @CarPowerManager.CarPowerState int powerState) { 3306 String powerStateName = powerStateToString(powerState); 3307 Slogf.i(TAG, "Notifying CPPD of power state(%s)", powerStateToString(powerState)); 3308 3309 boolean callbackReady = false; 3310 try { 3311 callbackReady = mPolicyCallbackHelper.waitForPolicyCallbackReady(); 3312 } catch (InterruptedException ignored) { 3313 Thread.currentThread().interrupt(); 3314 } 3315 if (!callbackReady) { 3316 Slogf.w(TAG, "Cannot request car power management daemon apply default policy for " 3317 + "power state(%s): callback to CPMS from daemon not set", powerStateName); 3318 return; 3319 } 3320 ICarPowerManagementDelegate daemon; 3321 synchronized (mLock) { 3322 daemon = mRefactoredCarPowerManagementDaemon; 3323 } 3324 if (daemon == null) { 3325 Slogf.e(TAG, "Failed to notify car power management daemon of power state change, " 3326 + "to %s, daemon unavailable", powerStateName); 3327 return; 3328 } 3329 AsyncPolicyRequest request = generateAsyncPolicyRequest( 3330 DEFAULT_POWER_POLICY_REQUEST_TIMEOUT_MS); 3331 int requestId = request.getRequestId(); 3332 synchronized (mLock) { 3333 mRequestIdToPolicyRequest.put(requestId, request); 3334 } 3335 try { 3336 Slogf.i(TAG, "Request(%d) of applying power policy for power state(%s) to CPPD in " 3337 + "async", requestId, powerStateName); 3338 daemon.applyPowerPolicyPerPowerStateChangeAsync(requestId, (byte) powerState); 3339 boolean policyRequestServed = request.await(); 3340 if (!policyRequestServed) { 3341 Slogf.w(TAG, "Power policy request (ID: %d) for power state(%s) timed out after" 3342 + " %d ms", requestId, powerStateName, 3343 DEFAULT_POWER_POLICY_REQUEST_TIMEOUT_MS); 3344 return; 3345 } 3346 } catch (IllegalArgumentException e) { 3347 Slogf.w(TAG, e, "Failed to apply power policy for power state(%s)", powerStateName); 3348 return; 3349 } catch (InterruptedException e) { 3350 Slogf.w(TAG, e, "Wait for power policy change request for power state(%s) " 3351 + "interrupted", powerStateName); 3352 Thread.currentThread().interrupt(); 3353 return; 3354 } catch (RemoteException e) { 3355 Slogf.w(TAG, e, "Failed to apply power policy for power state(%s), connection " 3356 + "issue", powerStateName); 3357 return; 3358 } finally { 3359 synchronized (mLock) { 3360 mRequestIdToPolicyRequest.remove(requestId); 3361 } 3362 } 3363 if (!request.isSuccessful()) { 3364 Slogf.w(TAG, "Failed to apply power policy for power state(%s), " 3365 + "failure reason = %d", powerStateName, request.getFailureReason()); 3366 return; 3367 } 3368 if (request.isDeferred()) { 3369 Slogf.i(TAG, "Applying power policy for power state(%s) is deferred", 3370 powerStateName); 3371 return; 3372 } 3373 CarPowerPolicy accumulatedPolicy = request.getAccumulatedPolicy(); 3374 updateCurrentPowerPolicy(accumulatedPolicy); 3375 notifyPowerPolicyChange(new PowerPolicyChangeNotification( 3376 mPowerComponentHandler.getLastModifiedComponents(), 3377 accumulatedPolicy, /* legacyNotification= */ false)); 3378 } 3379 3380 @Override handleMessage(Message msg)3381 public void handleMessage(Message msg) { 3382 if (msg.what != MSG_POWER_STATE_CHANGE) { 3383 Slogf.w(TAG, "handleMessage invalid message type: %d", msg.what); 3384 return; 3385 } 3386 int state = msg.arg1; 3387 int stateToNotify; 3388 if (state == CarPowerManager.STATE_ON) { 3389 stateToNotify = state; 3390 } else if (WAIT_FOR_VHAL_LISTENER_STATES.contains(state)) { 3391 stateToNotify = CarPowerManager.STATE_WAIT_FOR_VHAL; 3392 } else { 3393 Slogf.d(TAG, "Power state does not have default power policy, skipping"); 3394 return; 3395 } 3396 delegateDefaultPowerPolicyForStateToDaemon(stateToNotify); 3397 } 3398 } 3399 getSuspendType()3400 private String getSuspendType() { 3401 synchronized (mLock) { 3402 return mActionOnFinish == ACTION_ON_FINISH_HIBERNATION ? "Suspend-to-Disk" 3403 : "Suspend-to-RAM"; 3404 } 3405 } 3406 3407 // Send the command to enter Suspend to RAM. 3408 // If the command is not successful, try again with an exponential back-off. 3409 // If it fails repeatedly, send the command to shut down. 3410 // If we decide to go to a different power state, abort this retry mechanism. 3411 // Returns true if we successfully suspended. suspendWithRetries()3412 private boolean suspendWithRetries() { 3413 String suspendTarget = getSuspendType(); 3414 boolean isSuspendToDisk = suspendTarget.equals("Suspend-to-Disk"); 3415 long retryIntervalMs = INITIAL_SUSPEND_RETRY_INTERVAL_MS; 3416 long totalWaitDurationMs = 0; 3417 while (true) { 3418 long suspendStartTime = SystemClock.elapsedRealtime(); 3419 Slogf.i(TAG, "Entering %s", suspendTarget); 3420 if (isSuspendToDisk) { 3421 freeMemory(); 3422 if (mFeatureFlags.changeSwapsDuringSuspendToDisk() && mShouldChangeSwap) { 3423 SystemPropertiesHelper.set("sys.hibernate", "1"); 3424 } 3425 } 3426 int suspendResult = isSuspendToDisk ? mSystemInterface.enterHibernation() 3427 : mSystemInterface.enterDeepSleep(); 3428 3429 switch (suspendResult) { 3430 case SUSPEND_RESULT_SUCCESS: 3431 mCarServiceStartTimeAfterSuspend = SystemClock.uptimeMillis(); 3432 if (isSuspendToDisk && mFeatureFlags.changeSwapsDuringSuspendToDisk() 3433 && mShouldChangeSwap) { 3434 SystemPropertiesHelper.set("sys.hibernate", "0"); 3435 } 3436 return true; 3437 case SUSPEND_RESULT_RETRY: 3438 break; 3439 case SUSPEND_RESULT_ABORT: 3440 Slogf.e(TAG, "Creating hibernation image failed. Shuttind down"); 3441 mSystemInterface.shutdown(); 3442 Slogf.wtf(TAG, "The system must be turned off"); 3443 return false; 3444 } 3445 if (totalWaitDurationMs >= mMaxSuspendWaitDurationMs) { 3446 break; 3447 } 3448 // We failed to suspend. Block the thread briefly and try again. 3449 synchronized (mLock) { 3450 if (!mPendingPowerStates.isEmpty()) { 3451 // Check for a new power state now, before going around the loop again. 3452 CpmsState state = mPendingPowerStates.peekFirst(); 3453 if (state != null && needPowerStateChangeLocked(state)) { 3454 Slogf.i(TAG, "Terminating the attempt to suspend target = %s," 3455 + " currentState = %s, pendingState = %s", suspendTarget, 3456 mCurrentState.stateToString(), state.stateToString()); 3457 return false; 3458 } 3459 } 3460 long suspendStopTime = SystemClock.elapsedRealtime(); 3461 Slogf.w(TAG, "Failed to Suspend; will retry after %dms", retryIntervalMs); 3462 try { 3463 mLock.wait(retryIntervalMs); 3464 } catch (InterruptedException ignored) { 3465 Thread.currentThread().interrupt(); 3466 } 3467 totalWaitDurationMs += retryIntervalMs; 3468 totalWaitDurationMs += (suspendStopTime - suspendStartTime); 3469 retryIntervalMs = Math.min(retryIntervalMs * 2, MAX_RETRY_INTERVAL_MS); 3470 } 3471 } 3472 // Too many failures trying to suspend. Shut down. 3473 Slogf.w(TAG, "Could not %s after %dms long trial. Shutting down.", suspendTarget, 3474 totalWaitDurationMs); 3475 mSystemInterface.shutdown(); 3476 Slogf.wtf(TAG, "The system must be turned off"); 3477 return false; 3478 } 3479 3480 private static final class CpmsState { 3481 // NOTE: When modifying states below, make sure to update CarPowerStateChanged.State in 3482 // frameworks/proto_logging/stats/atoms.proto also. 3483 public static final int WAIT_FOR_VHAL = 0; 3484 public static final int ON = 1; 3485 public static final int SHUTDOWN_PREPARE = 2; 3486 public static final int WAIT_FOR_FINISH = 3; 3487 public static final int SUSPEND = 4; 3488 public static final int SIMULATE_SLEEP = 5; 3489 public static final int SIMULATE_HIBERNATION = 6; 3490 3491 /* Config values from AP_POWER_STATE_REQ */ 3492 public final boolean mCanPostpone; 3493 3494 @PowerState.ShutdownType 3495 public final int mShutdownType; 3496 3497 /* Message sent to CarPowerStateListener in response to this state */ 3498 @CarPowerManager.CarPowerState 3499 public final int mCarPowerStateListenerState; 3500 /* One of the above state variables */ 3501 public final int mState; 3502 3503 /** 3504 * This constructor takes a PowerHalService.PowerState object and creates the corresponding 3505 * CPMS state from it. 3506 */ CpmsState(PowerState halPowerState)3507 CpmsState(PowerState halPowerState) { 3508 switch (halPowerState.mState) { 3509 case VehicleApPowerStateReq.ON: 3510 this.mCanPostpone = false; 3511 this.mShutdownType = PowerState.SHUTDOWN_TYPE_UNDEFINED; 3512 this.mCarPowerStateListenerState = cpmsStateToPowerStateListenerState(ON); 3513 this.mState = ON; 3514 break; 3515 case VehicleApPowerStateReq.SHUTDOWN_PREPARE: 3516 this.mCanPostpone = halPowerState.canPostponeShutdown(); 3517 this.mShutdownType = halPowerState.getShutdownType(); 3518 this.mCarPowerStateListenerState = cpmsStateToPowerStateListenerState( 3519 SHUTDOWN_PREPARE); 3520 this.mState = SHUTDOWN_PREPARE; 3521 break; 3522 case VehicleApPowerStateReq.CANCEL_SHUTDOWN: 3523 this.mCanPostpone = false; 3524 this.mShutdownType = PowerState.SHUTDOWN_TYPE_UNDEFINED; 3525 this.mCarPowerStateListenerState = CarPowerManager.STATE_SHUTDOWN_CANCELLED; 3526 this.mState = WAIT_FOR_VHAL; 3527 break; 3528 case VehicleApPowerStateReq.FINISHED: 3529 this.mCanPostpone = false; 3530 this.mShutdownType = PowerState.SHUTDOWN_TYPE_UNDEFINED; 3531 this.mCarPowerStateListenerState = cpmsStateToPowerStateListenerState(SUSPEND); 3532 this.mState = SUSPEND; 3533 break; 3534 default: 3535 // Illegal state from PowerState. Throw an exception? 3536 // TODO(b/202414427): Add handling of illegal state 3537 this.mCanPostpone = false; 3538 this.mShutdownType = PowerState.SHUTDOWN_TYPE_UNDEFINED; 3539 this.mCarPowerStateListenerState = 0; 3540 this.mState = 0; 3541 break; 3542 } 3543 } 3544 CpmsState(int state, int carPowerStateListenerState, boolean canPostpone)3545 CpmsState(int state, int carPowerStateListenerState, boolean canPostpone) { 3546 this.mCanPostpone = canPostpone; 3547 this.mCarPowerStateListenerState = carPowerStateListenerState; 3548 this.mState = state; 3549 this.mShutdownType = state == SIMULATE_SLEEP ? PowerState.SHUTDOWN_TYPE_DEEP_SLEEP : 3550 (state == SIMULATE_HIBERNATION ? PowerState.SHUTDOWN_TYPE_HIBERNATION 3551 : PowerState.SHUTDOWN_TYPE_POWER_OFF); 3552 } 3553 CpmsState(int state, int carPowerStateListenerState, boolean canPostpone, int shutdownType)3554 CpmsState(int state, int carPowerStateListenerState, boolean canPostpone, 3555 int shutdownType) { 3556 this.mCanPostpone = canPostpone; 3557 this.mCarPowerStateListenerState = carPowerStateListenerState; 3558 this.mState = state; 3559 this.mShutdownType = shutdownType; 3560 } 3561 name()3562 public String name() { 3563 return new StringBuilder() 3564 .append(stateToString()) 3565 .append('(') 3566 .append(mState) 3567 .append(')') 3568 .toString(); 3569 } 3570 stateToString()3571 private String stateToString() { 3572 String baseName; 3573 switch(mState) { 3574 case WAIT_FOR_VHAL: baseName = "WAIT_FOR_VHAL"; break; 3575 case ON: baseName = "ON"; break; 3576 case SHUTDOWN_PREPARE: baseName = "SHUTDOWN_PREPARE"; break; 3577 case WAIT_FOR_FINISH: baseName = "WAIT_FOR_FINISH"; break; 3578 case SUSPEND: baseName = "SUSPEND"; break; 3579 case SIMULATE_SLEEP: baseName = "SIMULATE_SLEEP"; break; 3580 case SIMULATE_HIBERNATION: baseName = "SIMULATE_HIBERNATION"; break; 3581 default: baseName = "<unknown>"; break; 3582 } 3583 return baseName; 3584 } 3585 cpmsStateToPowerStateListenerState(int state)3586 private static int cpmsStateToPowerStateListenerState(int state) { 3587 int powerStateListenerState = 0; 3588 3589 // Set the CarPowerStateListenerState based on current state 3590 switch (state) { 3591 case ON: 3592 powerStateListenerState = CarPowerManager.STATE_ON; 3593 break; 3594 case SHUTDOWN_PREPARE: 3595 powerStateListenerState = CarPowerManager.STATE_PRE_SHUTDOWN_PREPARE; 3596 break; 3597 case SUSPEND: 3598 powerStateListenerState = CarPowerManager.STATE_SUSPEND_ENTER; 3599 break; 3600 case WAIT_FOR_VHAL: 3601 case WAIT_FOR_FINISH: 3602 default: 3603 // Illegal state for this constructor. Throw an exception? 3604 break; 3605 } 3606 return powerStateListenerState; 3607 } 3608 3609 @Override equals(Object o)3610 public boolean equals(Object o) { 3611 if (this == o) { 3612 return true; 3613 } 3614 if (!(o instanceof CpmsState)) { 3615 return false; 3616 } 3617 CpmsState that = (CpmsState) o; 3618 return this.mState == that.mState 3619 && this.mShutdownType == that.mShutdownType 3620 && this.mCanPostpone == that.mCanPostpone 3621 && this.mCarPowerStateListenerState == that.mCarPowerStateListenerState; 3622 } 3623 3624 @Override hashCode()3625 public int hashCode() { 3626 return Objects.hash(mCanPostpone, mShutdownType, mCarPowerStateListenerState, mState); 3627 } 3628 3629 // PowerPolicyHostTest uses the dump output of {@code CarPowerManagementService}. If the 3630 // {@code CpmsState.toString} is modifed, PowerPolicyHostTest should be updated accordingly. 3631 // TODO(b/184862429): Remove the above comment once dump in proto buffer is done. 3632 @Override toString()3633 public String toString() { 3634 return "CpmsState canPostpone=" + mCanPostpone 3635 + ", carPowerStateListenerState=" + mCarPowerStateListenerState 3636 + ", mShutdownType=" + mShutdownType 3637 + ", CpmsState=" + name(); 3638 } 3639 } 3640 3641 /** 3642 * Resume after a manually-invoked suspend. 3643 * Invoked using "adb shell dumpsys cmd car_service resume". 3644 */ forceSimulatedResume()3645 public void forceSimulatedResume() { 3646 synchronized (mLock) { 3647 // Cancel Garage Mode in case it's running 3648 boolean isSuspendToDisk = mActionOnFinish == ACTION_ON_FINISH_HIBERNATION; 3649 mPendingPowerStates.addFirst(new CpmsState(CpmsState.WAIT_FOR_VHAL, 3650 isSuspendToDisk ? CarPowerManager.STATE_HIBERNATION_EXIT 3651 : CarPowerManager.STATE_SUSPEND_EXIT, /* canPostpone= */ false)); 3652 mLock.notifyAll(); 3653 } 3654 mHandler.handlePowerStateChange(); 3655 3656 synchronized (mSimulationWaitObject) { 3657 mWakeFromSimulatedSleep = true; 3658 mSimulationWaitObject.notifyAll(); 3659 } 3660 } 3661 3662 /** 3663 * Manually enters simulated suspend (deep sleep or hibernation) mode, trigging Garage mode. 3664 * 3665 * <p>If {@code shouldReboot} is 'true', reboots the system when Garage Mode completes. 3666 * 3667 * Can be invoked using 3668 * {@code "adb shell cmd car_service suspend --simulate"} or 3669 * {@code "adb shell cmd car_service hibernate --simulate"} or 3670 * {@code "adb shell cmd car_service garage-mode reboot"}. 3671 * 3672 * This is similar to {@code 'onApPowerStateChange()'} except that it needs to create a 3673 * {@code CpmsState} that is not directly derived from a {@code VehicleApPowerStateReq}. 3674 */ simulateSuspendAndMaybeReboot(@owerState.ShutdownType int shutdownType, boolean shouldReboot, boolean skipGarageMode, int wakeupAfter, boolean freeMemory)3675 public void simulateSuspendAndMaybeReboot(@PowerState.ShutdownType int shutdownType, 3676 boolean shouldReboot, boolean skipGarageMode, int wakeupAfter, boolean freeMemory) { 3677 simulateSuspendAndMaybeReboot(shutdownType, shouldReboot, skipGarageMode, wakeupAfter, 3678 CarPowerManagementService.NO_WAKEUP_BY_TIMER, freeMemory); 3679 } 3680 3681 /** 3682 * Manually enters simulated suspend (deep sleep or hibernation) mode, trigging Garage mode. 3683 * 3684 * <p>If {@code shouldReboot} is 'true', reboots the system when Garage Mode completes. 3685 * 3686 * Can be invoked using 3687 * {@code "adb shell cmd car_service suspend --simulate"} or 3688 * {@code "adb shell cmd car_service hibernate --simulate"} or 3689 * {@code "adb shell cmd car_service garage-mode reboot"}. 3690 * 3691 * This is similar to {@code 'onApPowerStateChange()'} except that it needs to create a 3692 * {@code CpmsState} that is not directly derived from a {@code VehicleApPowerStateReq}. 3693 */ 3694 // TODO(b/274895468): Add tests simulateSuspendAndMaybeReboot(@owerState.ShutdownType int shutdownType, boolean shouldReboot, boolean skipGarageMode, int wakeupAfter, int cancelAfter, boolean freeMemory)3695 public void simulateSuspendAndMaybeReboot(@PowerState.ShutdownType int shutdownType, 3696 boolean shouldReboot, boolean skipGarageMode, int wakeupAfter, int cancelAfter, 3697 boolean freeMemory) { 3698 boolean isDeepSleep = shutdownType == PowerState.SHUTDOWN_TYPE_DEEP_SLEEP; 3699 if (cancelAfter >= 0) { 3700 Slogf.i(TAG, "Cancel after is: %d", cancelAfter); 3701 } 3702 if (wakeupAfter >= 0) { 3703 Slogf.i(TAG, "Wakeup after is: %d", wakeupAfter); 3704 } 3705 synchronized (mSimulationWaitObject) { 3706 mInSimulatedDeepSleepMode = true; 3707 mWakeFromSimulatedSleep = false; 3708 mBlockFromSimulatedCancelEvent = false; 3709 mResumeDelayFromSimulatedSuspendSec = wakeupAfter; 3710 mCancelDelayFromSimulatedSuspendSec = cancelAfter; 3711 mFreeMemoryBeforeSuspend = freeMemory; 3712 } 3713 synchronized (mLock) { 3714 mRebootAfterGarageMode = shouldReboot; 3715 mPendingPowerStates.addFirst(new CpmsState(isDeepSleep ? CpmsState.SIMULATE_SLEEP 3716 : CpmsState.SIMULATE_HIBERNATION, 3717 CarPowerManager.STATE_PRE_SHUTDOWN_PREPARE, !skipGarageMode)); 3718 } 3719 mHandler.handlePowerStateChange(); 3720 } 3721 3722 /** 3723 * Manually defines a power policy. 3724 * 3725 * <p>If the given ID already exists or specified power components are invalid, it fails. 3726 * 3727 * @return {@code true}, if successful. Otherwise, {@code false}. 3728 */ definePowerPolicyFromCommand(String[] args, IndentingPrintWriter writer)3729 public boolean definePowerPolicyFromCommand(String[] args, IndentingPrintWriter writer) { 3730 if (args.length < 2) { 3731 writer.println("Too few arguments"); 3732 return false; 3733 } 3734 String powerPolicyId = args[1]; 3735 int index = 2; 3736 String[] enabledComponents = new String[0]; 3737 String[] disabledComponents = new String[0]; 3738 while (index < args.length) { 3739 switch (args[index]) { 3740 case "--enable": 3741 if (index == args.length - 1) { 3742 writer.println("No components for --enable"); 3743 return false; 3744 } 3745 enabledComponents = args[index + 1].split(","); 3746 break; 3747 case "--disable": 3748 if (index == args.length - 1) { 3749 writer.println("No components for --disabled"); 3750 return false; 3751 } 3752 disabledComponents = args[index + 1].split(","); 3753 break; 3754 default: 3755 writer.printf("Unrecognized argument: %s\n", args[index]); 3756 return false; 3757 } 3758 index += 2; 3759 } 3760 int status = definePowerPolicy(powerPolicyId, enabledComponents, disabledComponents); 3761 if (status != PolicyOperationStatus.OK) { 3762 writer.println(PolicyOperationStatus.errorCodeToString(status)); 3763 return false; 3764 } 3765 writer.printf("Power policy(%s) is successfully defined.\n", powerPolicyId); 3766 return true; 3767 } 3768 3769 /** 3770 * Defines a power policy with the given id and components. 3771 * 3772 * <p> A policy defined with this method is valid until the system is rebooted/restarted. 3773 */ 3774 @VisibleForTesting 3775 @PolicyOperationStatus.ErrorCode definePowerPolicy(String powerPolicyId, String[] enabledComponents, String[] disabledComponents)3776 public int definePowerPolicy(String powerPolicyId, String[] enabledComponents, 3777 String[] disabledComponents) { 3778 Preconditions.checkArgument(!powerPolicyId.startsWith( 3779 PolicyReader.SYSTEM_POWER_POLICY_PREFIX), 3780 "System power policy cannot be defined by apps"); 3781 int status = mPolicyReader.definePowerPolicy(powerPolicyId, 3782 enabledComponents, disabledComponents); 3783 if (status != PolicyOperationStatus.OK) { 3784 return status; 3785 } 3786 // Get custom power components and update components list in PowerComponentHandler 3787 Collection<Integer> customComponents = mPolicyReader.getCustomComponents().values(); 3788 if (customComponents.size() > 0) { 3789 mPowerComponentHandler.registerCustomComponents( 3790 customComponents.toArray(new Integer[customComponents.size()])); 3791 } 3792 if (mFeatureFlags.carPowerPolicyRefactoring()) { 3793 ICarPowerManagementDelegate daemon; 3794 synchronized (mLock) { 3795 daemon = mRefactoredCarPowerManagementDaemon; 3796 } 3797 try { 3798 daemon.notifyPowerPolicyDefinition(powerPolicyId, enabledComponents, 3799 disabledComponents); 3800 } catch (IllegalArgumentException e) { 3801 int policyError = PolicyOperationStatus.ERROR_INVALID_POWER_POLICY_ID; 3802 int componentError = PolicyOperationStatus.ERROR_INVALID_POWER_COMPONENT; 3803 Slogf.w(TAG, e, "%s and/or %s", 3804 PolicyOperationStatus.errorCodeToString(policyError), 3805 PolicyOperationStatus.errorCodeToString(componentError)); 3806 return policyError; 3807 } catch (IllegalStateException | RemoteException e) { 3808 int error = PolicyOperationStatus.ERROR_DEFINE_POWER_POLICY; 3809 Slogf.w(TAG, e, PolicyOperationStatus.errorCodeToString(error)); 3810 return error; 3811 } catch (SecurityException e) { 3812 int error = PolicyOperationStatus.ERROR_DEFINE_POWER_POLICY; 3813 Slogf.w(TAG, e, "%s; insufficient permissions", 3814 PolicyOperationStatus.errorCodeToString(error)); 3815 return error; 3816 } 3817 } else { 3818 ICarPowerPolicySystemNotification daemon; 3819 synchronized (mLock) { 3820 daemon = mCarPowerPolicyDaemon; 3821 } 3822 try { 3823 daemon.notifyPowerPolicyDefinition(powerPolicyId, enabledComponents, 3824 disabledComponents); 3825 } catch (RemoteException e) { 3826 int error = PolicyOperationStatus.ERROR_DEFINE_POWER_POLICY; 3827 Slogf.w(TAG, e, PolicyOperationStatus.errorCodeToString(error)); 3828 return error; 3829 } 3830 } 3831 return PolicyOperationStatus.OK; 3832 } 3833 3834 /** 3835 * Manually applies a power policy. 3836 * 3837 * <p>If the given ID is not defined, it fails. 3838 * 3839 * @return {@code true}, if successful. Otherwise, {@code false}. 3840 */ applyPowerPolicyFromCommand(String[] args, IndentingPrintWriter writer)3841 public boolean applyPowerPolicyFromCommand(String[] args, IndentingPrintWriter writer) { 3842 if (args.length != 2) { 3843 writer.println("Power policy ID should be given"); 3844 return false; 3845 } 3846 String powerPolicyId = args[1]; 3847 if (powerPolicyId == null) { 3848 writer.println("Policy ID cannot be null"); 3849 return false; 3850 } 3851 int status; 3852 Slogf.i(TAG, "Applying power policy(%s) from shell command", powerPolicyId); 3853 if (mFeatureFlags.carPowerPolicyRefactoring()) { 3854 status = applyPowerPolicy(powerPolicyId, /* delayNotification= */ false, 3855 /* upToDaemon= */ false, /* force= */ false); 3856 } else { 3857 boolean isPreemptive = mPolicyReader.isPreemptivePowerPolicy(powerPolicyId); 3858 status = isPreemptive ? applyPreemptivePowerPolicy(powerPolicyId) 3859 : applyPowerPolicy(powerPolicyId, /* delayNotification= */ false, 3860 /* upToDaemon= */ true, /* force= */ false); 3861 } 3862 if (status != PolicyOperationStatus.OK) { 3863 writer.println(PolicyOperationStatus.errorCodeToString(status)); 3864 return false; 3865 } 3866 writer.printf("Power policy(%s) is successfully applied.\n", powerPolicyId); 3867 return true; 3868 } 3869 3870 /** 3871 * Manually defines a power policy group. 3872 * 3873 * <p>If the given ID already exists, a wrong power state is given, or specified power policy ID 3874 * doesn't exist, it fails. 3875 * 3876 * @return {@code true}, if successful. Otherwise, {@code false}. 3877 */ definePowerPolicyGroupFromCommand(String[] args, IndentingPrintWriter writer)3878 public boolean definePowerPolicyGroupFromCommand(String[] args, IndentingPrintWriter writer) { 3879 if (args.length < 3 || args.length > 4) { 3880 writer.println("Invalid syntax"); 3881 return false; 3882 } 3883 String policyGroupId = args[1]; 3884 int index = 2; 3885 SparseArray<String> defaultPolicyPerState = new SparseArray<>(); 3886 String[] powerPolicyPerState = {"", ""}; 3887 while (index < args.length) { 3888 String[] tokens = args[index].split(":"); 3889 if (tokens.length != 2) { 3890 writer.println("Invalid syntax"); 3891 return false; 3892 } 3893 int state = PolicyReader.toPowerState(tokens[0]); 3894 if (state == PolicyReader.INVALID_POWER_STATE) { 3895 writer.printf("Invalid power state: %s\n", tokens[0]); 3896 return false; 3897 } 3898 defaultPolicyPerState.put(state, tokens[1]); 3899 switch (state) { 3900 case VehicleApPowerStateReport.WAIT_FOR_VHAL: 3901 powerPolicyPerState[INDEX_WAIT_FOR_VHAL] = tokens[1]; 3902 break; 3903 case VehicleApPowerStateReport.ON: 3904 powerPolicyPerState[INDEX_ON] = tokens[1]; 3905 break; 3906 } 3907 index++; 3908 } 3909 if (mFeatureFlags.carPowerPolicyRefactoring()) { 3910 ICarPowerManagementDelegate daemon; 3911 synchronized (mLock) { 3912 daemon = mRefactoredCarPowerManagementDaemon; 3913 } 3914 try { 3915 daemon.notifyPowerPolicyGroupDefinition(policyGroupId, powerPolicyPerState); 3916 } catch (IllegalArgumentException e) { 3917 Slogf.w(TAG, e, "The given policy group ID(%s) or mapping between power state and" 3918 + " policy is invalid", policyGroupId); 3919 return false; 3920 } catch (RemoteException e) { 3921 Slogf.w(TAG, e, "Calling ICarPowerManagementDelegate." 3922 + "notifyPowerPolicyGroupDefinition failed"); 3923 return false; 3924 } 3925 } 3926 int status = mPolicyReader.definePowerPolicyGroup(policyGroupId, 3927 defaultPolicyPerState); 3928 if (status != PolicyOperationStatus.OK) { 3929 writer.println(PolicyOperationStatus.errorCodeToString(status)); 3930 return false; 3931 } 3932 writer.printf("Power policy group(%s) is successfully defined.\n", policyGroupId); 3933 return true; 3934 } 3935 3936 /** 3937 * Manually sets a power policy group. 3938 * 3939 * <p>If the given ID is not defined, it fails. 3940 * 3941 * @return {@code true}, if successful. Otherwise, {@code false}. 3942 */ setPowerPolicyGroupFromCommand(String[] args, IndentingPrintWriter writer)3943 public boolean setPowerPolicyGroupFromCommand(String[] args, IndentingPrintWriter writer) { 3944 if (args.length != 2) { 3945 writer.println("Power policy group ID should be given"); 3946 return false; 3947 } 3948 String policyGroupId = args[1]; 3949 if (mFeatureFlags.carPowerPolicyRefactoring()) { 3950 try { 3951 setPowerPolicyGroup(policyGroupId); 3952 } catch (RemoteException e) { 3953 writer.println("RemoteException encountered when setting power policy group"); 3954 return false; 3955 } 3956 } else { 3957 int status = setCurrentPowerPolicyGroup(policyGroupId); 3958 if (status != PolicyOperationStatus.OK) { 3959 writer.println(PolicyOperationStatus.errorCodeToString(status)); 3960 return false; 3961 } 3962 } 3963 writer.printf("Setting power policy group(%s) is successful.\n", policyGroupId); 3964 return true; 3965 } 3966 3967 /** 3968 * Suspends the device. 3969 * 3970 * <p>According to the argument, the device is suspended to RAM or disk. 3971 */ suspendFromCommand(boolean isHibernation, boolean skipGarageMode)3972 public void suspendFromCommand(boolean isHibernation, boolean skipGarageMode) { 3973 CarServiceUtils.assertPermission(mContext, Car.PERMISSION_CAR_POWER); 3974 int param = 0; 3975 if (isHibernation) { 3976 if (!isHibernationAvailable()) { 3977 throw new IllegalStateException("The device doesn't support hibernation"); 3978 } 3979 param = skipGarageMode ? VehicleApPowerStateShutdownParam.HIBERNATE_IMMEDIATELY 3980 : VehicleApPowerStateShutdownParam.CAN_HIBERNATE; 3981 } else { 3982 if (!isDeepSleepAvailable()) { 3983 throw new IllegalStateException("The device doesn't support deep sleep"); 3984 } 3985 param = skipGarageMode ? VehicleApPowerStateShutdownParam.SLEEP_IMMEDIATELY 3986 : VehicleApPowerStateShutdownParam.CAN_SLEEP; 3987 } 3988 PowerState state = new PowerState(VehicleApPowerStateReq.SHUTDOWN_PREPARE, param); 3989 synchronized (mLock) { 3990 mRebootAfterGarageMode = false; 3991 mPendingPowerStates.addFirst(new CpmsState(state)); 3992 mLock.notifyAll(); 3993 } 3994 mHandler.handlePowerStateChange(); 3995 } 3996 3997 /** 3998 * Powers off the device. 3999 */ powerOffFromCommand(boolean skipGarageMode, boolean reboot)4000 public void powerOffFromCommand(boolean skipGarageMode, boolean reboot) { 4001 CarServiceUtils.assertPermission(mContext, Car.PERMISSION_CAR_POWER); 4002 Slogf.i(TAG, "%s %s Garage Mode", reboot ? "Rebooting" : "Powering off", 4003 skipGarageMode ? "with" : "without"); 4004 int param = skipGarageMode ? VehicleApPowerStateShutdownParam.SHUTDOWN_IMMEDIATELY 4005 : VehicleApPowerStateShutdownParam.SHUTDOWN_ONLY; 4006 PowerState state = new PowerState(VehicleApPowerStateReq.SHUTDOWN_PREPARE, param); 4007 synchronized (mLock) { 4008 mRebootAfterGarageMode = reboot; 4009 mPendingPowerStates.addFirst(new CpmsState(state)); 4010 mLock.notifyAll(); 4011 } 4012 mHandler.handlePowerStateChange(); 4013 } 4014 4015 /** 4016 * Returns the last shutdown state. 4017 */ getLastShutdownState()4018 public int getLastShutdownState() { 4019 synchronized (mLock) { 4020 return mLastShutdownState; 4021 } 4022 } 4023 4024 /** 4025 * Changes Silent Mode to the given mode. 4026 */ setSilentMode(String silentMode)4027 public void setSilentMode(String silentMode) { 4028 CarServiceUtils.assertPermission(mContext, Car.PERMISSION_CAR_POWER); 4029 mSilentModeHandler.setSilentMode(silentMode); 4030 if (mFeatureFlags.carPowerPolicyRefactoring()) { 4031 ICarPowerManagementDelegate daemon; 4032 synchronized (mLock) { 4033 daemon = mRefactoredCarPowerManagementDaemon; 4034 } 4035 if (daemon != null) { 4036 try { 4037 daemon.setSilentMode(silentMode); 4038 } catch (RemoteException e) { 4039 Slogf.e(TAG, e, "Failed to notify car power policy daemon of the new silent " 4040 + "mode(%s)", silentMode); 4041 return; 4042 } 4043 } else { 4044 Slogf.w(TAG, "Failed to notify the new silent mode, car power policy daemon" 4045 + " is not available"); 4046 return; 4047 } 4048 Slogf.i(TAG, "Set the new silent mode(%s) to CPPD", silentMode); 4049 } 4050 } 4051 4052 /** 4053 * Dumps the current Silent Mode. 4054 */ 4055 @ExcludeFromCodeCoverageGeneratedReport(reason = DUMP_INFO) dumpSilentMode(IndentingPrintWriter writer)4056 public void dumpSilentMode(IndentingPrintWriter writer) { 4057 mSilentModeHandler.dump(writer); 4058 } 4059 4060 /** 4061 * Returns whether a listener completion is allowed for the given state. 4062 * 4063 * <p>See {@link CarPowerManager.isCompletionAllowed} 4064 */ isCompletionAllowed(@arPowerManager.CarPowerState int state)4065 public static boolean isCompletionAllowed(@CarPowerManager.CarPowerState int state) { 4066 return CarPowerManager.isCompletionAllowed(state); 4067 } 4068 4069 /** 4070 * Returns a corresponding string of the given power state. 4071 */ powerStateToString(int state)4072 public static String powerStateToString(int state) { 4073 return DebugUtils.constantToString(CarPowerManager.class, "STATE_", state); 4074 } 4075 4076 /** 4077 * Requests VHAL to shutdown the head unit. 4078 * 4079 * @throws UnsupportedOperationException If the system doesn't not support 4080 * {@code nextPowerState}. 4081 */ requestShutdownAp(int nextPowerState, boolean runGarageMode)4082 public void requestShutdownAp(int nextPowerState, boolean runGarageMode) { 4083 int shutdownParam = PowerState.SHUTDOWN_TYPE_POWER_OFF; 4084 switch (nextPowerState) { 4085 case CarRemoteAccessManager.NEXT_POWER_STATE_ON: 4086 // Do nothing. 4087 return; 4088 case CarRemoteAccessManager.NEXT_POWER_STATE_OFF: 4089 shutdownParam = PowerState.SHUTDOWN_TYPE_POWER_OFF; 4090 break; 4091 case CarRemoteAccessManager.NEXT_POWER_STATE_SUSPEND_TO_RAM: 4092 if (!isDeepSleepAvailable()) { 4093 throw new UnsupportedOperationException("Suspend-to-RAM is not supported"); 4094 } 4095 shutdownParam = PowerState.SHUTDOWN_TYPE_DEEP_SLEEP; 4096 break; 4097 case CarRemoteAccessManager.NEXT_POWER_STATE_SUSPEND_TO_DISK: 4098 if (!isHibernationAvailable()) { 4099 throw new UnsupportedOperationException("Suspend-to-disk is not supported"); 4100 } 4101 shutdownParam = PowerState.SHUTDOWN_TYPE_HIBERNATION; 4102 break; 4103 default: 4104 Slogf.w(TAG, "Unknown power state(%d)", nextPowerState); 4105 return; 4106 } 4107 mHal.requestShutdownAp(shutdownParam, runGarageMode); 4108 } 4109 4110 /** 4111 * Returns whether suspend (deep sleep or hibernation) is available on the device. 4112 */ isSuspendAvailable(boolean isHibernation)4113 public boolean isSuspendAvailable(boolean isHibernation) { 4114 return isHibernation ? isHibernationAvailable() : isDeepSleepAvailable(); 4115 } 4116 4117 /** 4118 * Enters garage mode if the bootup reason is ENTER_GARAGE_MODE. 4119 */ 4120 @Override onInitComplete()4121 public void onInitComplete() { 4122 if (mFeatureFlags.serverlessRemoteAccess()) { 4123 maybeEnterGarageModeOnBoot(); 4124 } 4125 } 4126 4127 /** 4128 * Shutdown the device to run garage mode if the bootup reason is ENTER_GARAGE_MODE. 4129 */ maybeEnterGarageModeOnBoot()4130 private void maybeEnterGarageModeOnBoot() { 4131 @BootupReason int bootupReason = mHal.getVehicleApBootupReason(); 4132 Slogf.i(TAG, "Vehicle AP power bootup reason: " + bootupReason); 4133 if (bootupReason != BOOTUP_REASON_SYSTEM_ENTER_GARAGE_MODE) { 4134 return; 4135 } 4136 if (mHal.isVehicleInUse()) { 4137 Slogf.i(TAG, "Bootup reason is ENTER_GARAGE_MODE but vehicle is currently in use" 4138 + ", skip entering garage mode"); 4139 return; 4140 } 4141 try { 4142 requestShutdownAp(getLastShutdownState(), /* runGarageMode= */ true); 4143 } catch (Exception e) { 4144 Slogf.wtf(TAG, "Failed to call requestShutdownAp", e); 4145 } 4146 } 4147 isDeepSleepAvailable()4148 private boolean isDeepSleepAvailable() { 4149 return mHal.isDeepSleepAllowed() && mSystemInterface.isSystemSupportingDeepSleep(); 4150 } 4151 isHibernationAvailable()4152 private boolean isHibernationAvailable() { 4153 return mHal.isHibernationAllowed() && mSystemInterface.isSystemSupportingHibernation(); 4154 } 4155 4156 // In a real Deep Sleep, the hardware removes power from the CPU (but retains power 4157 // on the RAM). This puts the processor to sleep. Upon some external signal, power 4158 // is re-applied to the CPU, and processing resumes right where it left off. 4159 // We simulate this behavior by calling wait(). 4160 // We continue from wait() when forceSimulatedResume() is called. simulateSleepByWaiting()4161 private void simulateSleepByWaiting() { 4162 Slogf.i(TAG, "Starting to simulate Deep Sleep by waiting"); 4163 synchronized (mSimulationWaitObject) { 4164 if (mFreeMemoryBeforeSuspend) { 4165 freeMemory(); 4166 } 4167 if (mResumeDelayFromSimulatedSuspendSec >= 0) { 4168 Slogf.i(TAG, "Scheduling a wakeup after %d seconds", 4169 mResumeDelayFromSimulatedSuspendSec); 4170 Handler handler = new Handler(Looper.getMainLooper()); 4171 handler.postDelayed(() -> forceSimulatedResume(), 4172 mResumeDelayFromSimulatedSuspendSec * 1000L); 4173 } 4174 while (!mWakeFromSimulatedSleep) { 4175 try { 4176 mSimulationWaitObject.wait(); 4177 } catch (InterruptedException ignored) { 4178 Thread.currentThread().interrupt(); // Restore interrupted status 4179 } 4180 } 4181 mInSimulatedDeepSleepMode = false; 4182 } 4183 Slogf.i(TAG, "Exit Deep Sleep simulation"); 4184 } 4185 getMaxSuspendWaitDurationConfig()4186 private int getMaxSuspendWaitDurationConfig() { 4187 return mContext.getResources().getInteger(R.integer.config_maxSuspendWaitDuration); 4188 } 4189 isWifiAdjustmentForSuspendConfig()4190 private boolean isWifiAdjustmentForSuspendConfig() { 4191 return mContext.getResources().getBoolean(R.bool.config_wifiAdjustmentForSuspend); 4192 } 4193 getPreShutdownPrepareTimeoutConfig()4194 private int getPreShutdownPrepareTimeoutConfig() { 4195 return getCompletionWaitTimeoutConfig(R.integer.config_preShutdownPrepareTimeout); 4196 } 4197 getShutdownEnterTimeoutConfig()4198 private int getShutdownEnterTimeoutConfig() { 4199 return getCompletionWaitTimeoutConfig(R.integer.config_shutdownEnterTimeout); 4200 } 4201 getPostShutdownEnterTimeoutConfig()4202 private int getPostShutdownEnterTimeoutConfig() { 4203 return getCompletionWaitTimeoutConfig(R.integer.config_postShutdownEnterTimeout); 4204 } 4205 getS2dImportanceLevel()4206 private int getS2dImportanceLevel() { 4207 return convertMemorySuspendConfigToValue(mContext.getResources().getString( 4208 R.string.config_suspend_to_disk_memory_savings)); 4209 } 4210 getS2dAllowList()4211 private ArraySet<String> getS2dAllowList() { 4212 return new ArraySet<>(mContext.getResources().getStringArray( 4213 R.array.config_packages_not_to_stop_during_suspend)); 4214 } 4215 getCompletionWaitTimeoutConfig(int resourceId)4216 private int getCompletionWaitTimeoutConfig(int resourceId) { 4217 int timeout = mContext.getResources().getInteger(resourceId); 4218 return timeout >= 0 ? timeout : DEFAULT_COMPLETION_WAIT_TIMEOUT; 4219 } 4220 4221 @ExcludeFromCodeCoverageGeneratedReport(reason = DUMP_INFO) actionOnFinishToString(int actionOnFinish)4222 private static String actionOnFinishToString(int actionOnFinish) { 4223 switch (actionOnFinish) { 4224 case ACTION_ON_FINISH_SHUTDOWN: 4225 return "Shutdown"; 4226 case ACTION_ON_FINISH_DEEP_SLEEP: 4227 return "Deep sleep"; 4228 case ACTION_ON_FINISH_HIBERNATION: 4229 return "Hibernation"; 4230 default: 4231 return "Unknown"; 4232 } 4233 } 4234 waitForCompletionWithShutdownPostpone( @arPowerManager.CarPowerState int carPowerStateListenerState, long timeoutMs, Runnable taskAtCompletion, int intervalMs)4235 private void waitForCompletionWithShutdownPostpone( 4236 @CarPowerManager.CarPowerState int carPowerStateListenerState, long timeoutMs, 4237 Runnable taskAtCompletion, int intervalMs) { 4238 Runnable taskAtInterval = () -> { 4239 mHal.sendShutdownPostpone(intervalMs); 4240 }; 4241 4242 Slogf.i(TAG, "Start waiting for listener completion for %s", 4243 powerStateToString(carPowerStateListenerState)); 4244 4245 waitForCompletion(taskAtCompletion, taskAtInterval, timeoutMs, intervalMs); 4246 } 4247 4248 /** 4249 * Utility method to help with memory freeing before entering Suspend-To-Disk 4250 */ freeMemory()4251 private void freeMemory() { 4252 try { 4253 Trace.traceBegin(TraceHelper.TRACE_TAG_CAR_SERVICE, "freeMemory"); 4254 if (!mFeatureFlags.stopProcessBeforeSuspendToDisk()) { 4255 ActivityManagerHelper.killAllBackgroundProcesses(); 4256 Trace.traceEnd(TraceHelper.TRACE_TAG_CAR_SERVICE); 4257 return; 4258 } 4259 int suspendToDiskImportanceLevel = getS2dImportanceLevel(); 4260 switch (suspendToDiskImportanceLevel) { 4261 case ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE: 4262 return; 4263 case ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED: 4264 ActivityManagerHelper.killAllBackgroundProcesses(); 4265 return; 4266 } 4267 List<ActivityManager.RunningAppProcessInfo> allRunningAppProcesses = 4268 ActivityManagerHelper.getRunningAppProcesses(); 4269 ArraySet<Integer> safeUids = new ArraySet<>(); 4270 ArraySet<String> suspendToDiskAllowList = getS2dAllowList(); 4271 for (int i = 0; i < allRunningAppProcesses.size(); i++) { 4272 ActivityManager.RunningAppProcessInfo info = allRunningAppProcesses.get(i); 4273 boolean isCarServiceOrMyPid = ICarImpl.class.getPackage().getName() 4274 .equals(info.processName) 4275 || info.pid == android.os.Process.myPid(); 4276 boolean isSystemOrShellUid = info.uid == Process.SYSTEM_UID 4277 || info.uid == Process.SHELL_UID; 4278 boolean isProcessPersistent = (ActivityManagerHelper 4279 .getFlagsForRunningAppProcessInfo(info) 4280 & ActivityManagerHelper.PROCESS_INFO_PERSISTENT_FLAG) != 0; 4281 boolean isWithinConfig = suspendToDiskImportanceLevel > info.importance; 4282 boolean isProcessAllowListed = suspendToDiskAllowList.contains(info.processName); 4283 if (isCarServiceOrMyPid || isSystemOrShellUid || isProcessPersistent 4284 || isWithinConfig || isProcessAllowListed) { 4285 safeUids.add(info.uid); 4286 } 4287 } 4288 4289 for (int i = 0; i < allRunningAppProcesses.size(); i++) { 4290 ActivityManager.RunningAppProcessInfo info = allRunningAppProcesses.get(i); 4291 if (!safeUids.contains(info.uid)) { 4292 for (int j = 0; j < info.pkgList.length; j++) { 4293 String pkgToStop = info.pkgList[j]; 4294 PackageManagerHelper.forceStopPackageAsUser(mContext, pkgToStop, 4295 UserManagerHelper.USER_ALL); 4296 } 4297 } 4298 } 4299 } finally { 4300 Trace.traceEnd(TraceHelper.TRACE_TAG_CAR_SERVICE); 4301 } 4302 } 4303 4304 /** 4305 * Helper method to accept function with one displayId argument to run on all displays. 4306 */ forEachDisplay(@onNull Context context, @NonNull Consumer<Integer> consumer)4307 private static void forEachDisplay(@NonNull Context context, 4308 @NonNull Consumer<Integer> consumer) { 4309 DisplayManager displayManager = context.getSystemService(DisplayManager.class); 4310 for (Display display : displayManager.getDisplays()) { 4311 int displayId = display.getDisplayId(); 4312 consumer.accept(displayId); 4313 } 4314 } 4315 convertMemorySuspendConfigToValue(String configValue)4316 private int convertMemorySuspendConfigToValue(String configValue) { 4317 return switch (configValue) { 4318 case "low" -> ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED; 4319 case "medium" -> ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE; 4320 case "high" -> ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE; 4321 // none will fallthrough 4322 default -> ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE; 4323 }; 4324 } 4325 4326 @VisibleForTesting setSwapChangeEnabled(boolean enable)4327 void setSwapChangeEnabled(boolean enable) { 4328 mShouldChangeSwap = enable; 4329 } 4330 4331 // TODO (b/286303350): remove legacyNotification field after power policy refactor is complete PowerPolicyChangeNotification(String policyId, SparseBooleanArray lastModifiedComponents, CarPowerPolicy accumulatedPolicy, boolean legacyNotification)4332 private record PowerPolicyChangeNotification(String policyId, 4333 SparseBooleanArray lastModifiedComponents, 4334 CarPowerPolicy accumulatedPolicy, 4335 boolean legacyNotification) { 4336 PowerPolicyChangeNotification(SparseBooleanArray lastModifiedComponents, 4337 CarPowerPolicy accumulatedPolicy, boolean legacyNotification) { 4338 this(accumulatedPolicy.getPolicyId(), lastModifiedComponents, accumulatedPolicy, 4339 legacyNotification); 4340 } 4341 } 4342 } 4343