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 package com.android.car.hal; 17 18 import android.util.Log; 19 20 import com.android.car.CarLog; 21 import com.android.car.vehiclenetwork.VehicleNetworkConsts; 22 import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleApPowerSetState; 23 import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleApPowerState; 24 import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleApPowerStateConfigFlag; 25 import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleApPowerStateIndex; 26 import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleApPowerStateShutdownParam; 27 import com.android.car.vehiclenetwork.VehicleNetworkProto.VehiclePropConfig; 28 import com.android.car.vehiclenetwork.VehicleNetworkProto.VehiclePropValue; 29 import com.android.internal.annotations.VisibleForTesting; 30 31 import java.io.PrintWriter; 32 import java.util.HashMap; 33 import java.util.LinkedList; 34 import java.util.List; 35 36 public class PowerHalService extends HalServiceBase { 37 38 public static final int STATE_OFF = VehicleApPowerState.VEHICLE_AP_POWER_STATE_OFF; 39 public static final int STATE_DEEP_SLEEP = 40 VehicleApPowerState.VEHICLE_AP_POWER_STATE_DEEP_SLEEP; 41 public static final int STATE_ON_DISP_OFF = 42 VehicleApPowerState.VEHICLE_AP_POWER_STATE_ON_DISP_OFF; 43 public static final int STATE_ON_FULL = VehicleApPowerState.VEHICLE_AP_POWER_STATE_ON_FULL; 44 public static final int STATE_SHUTDOWN_PREPARE = 45 VehicleApPowerState.VEHICLE_AP_POWER_STATE_SHUTDOWN_PREPARE; 46 47 @VisibleForTesting 48 public static final int SET_BOOT_COMPLETE = 49 VehicleApPowerSetState.VEHICLE_AP_POWER_SET_BOOT_COMPLETE; 50 @VisibleForTesting 51 public static final int SET_DEEP_SLEEP_ENTRY = 52 VehicleApPowerSetState.VEHICLE_AP_POWER_SET_DEEP_SLEEP_ENTRY; 53 @VisibleForTesting 54 public static final int SET_DEEP_SLEEP_EXIT = 55 VehicleApPowerSetState.VEHICLE_AP_POWER_SET_DEEP_SLEEP_EXIT; 56 @VisibleForTesting 57 public static final int SET_SHUTDOWN_POSTPONE = 58 VehicleApPowerSetState.VEHICLE_AP_POWER_SET_SHUTDOWN_POSTPONE; 59 @VisibleForTesting 60 public static final int SET_SHUTDOWN_START = 61 VehicleApPowerSetState.VEHICLE_AP_POWER_SET_SHUTDOWN_START; 62 @VisibleForTesting 63 public static final int SET_DISPLAY_ON = VehicleApPowerSetState.VEHICLE_AP_POWER_SET_DISPLAY_ON; 64 @VisibleForTesting 65 public static final int SET_DISPLAY_OFF = 66 VehicleApPowerSetState.VEHICLE_AP_POWER_SET_DISPLAY_OFF; 67 68 @VisibleForTesting 69 public static final int FLAG_SHUTDOWN_PARAM_CAN_SLEEP = 70 VehicleApPowerStateShutdownParam.VEHICLE_AP_POWER_SHUTDOWN_PARAM_CAN_SLEEP; 71 @VisibleForTesting 72 public static final int FLAG_SHUTDOWN_IMMEDIATELY = 73 VehicleApPowerStateShutdownParam.VEHICLE_AP_POWER_SHUTDOWN_PARAM_SHUTDOWN_IMMEDIATELY; 74 75 public interface PowerEventListener { 76 /** 77 * Received power state change event. 78 * @param state One of STATE_* 79 * @param param 80 */ 81 void onApPowerStateChange(PowerState state); 82 /** 83 * Received display brightness change event. 84 * @param brightness in percentile. 100% full. 85 */ 86 void onDisplayBrightnessChange(int brightness); 87 } 88 89 public static final class PowerState { 90 /** 91 * One of STATE_* 92 */ 93 public final int state; 94 public final int param; 95 96 public PowerState(int state, int param) { 97 this.state = state; 98 this.param = param; 99 } 100 101 /** 102 * Whether the current PowerState allows deep sleep or not. Calling this for 103 * power state other than STATE_SHUTDOWN_PREPARE will trigger exception. 104 * @return 105 * @throws IllegalStateException 106 */ 107 public boolean canEnterDeepSleep() { 108 if (state != STATE_SHUTDOWN_PREPARE) { 109 throw new IllegalStateException("wrong state"); 110 } 111 return (param & 112 VehicleApPowerStateShutdownParam.VEHICLE_AP_POWER_SHUTDOWN_PARAM_CAN_SLEEP) != 113 0; 114 } 115 116 /** 117 * Whether the current PowerState allows postponing or not. Calling this for 118 * power state other than STATE_SHUTDOWN_PREPARE will trigger exception. 119 * @return 120 * @throws IllegalStateException 121 */ 122 public boolean canPostponeShutdown() { 123 if (state != STATE_SHUTDOWN_PREPARE) { 124 throw new IllegalStateException("wrong state"); 125 } 126 return (param & 127 VehicleApPowerStateShutdownParam.VEHICLE_AP_POWER_SHUTDOWN_PARAM_SHUTDOWN_IMMEDIATELY) 128 == 0; 129 } 130 131 @Override 132 public boolean equals(Object o) { 133 if (this == o) { 134 return true; 135 } 136 if (!(o instanceof PowerState)) { 137 return false; 138 } 139 PowerState that = (PowerState) o; 140 return this.state == that.state && this.param == that.param; 141 } 142 143 @Override 144 public String toString() { 145 return "PowerState state:" + state + ",param:" + param; 146 } 147 } 148 149 private final HashMap<Integer, VehiclePropConfig> mProperties = new HashMap<>(); 150 private final VehicleHal mHal; 151 private LinkedList<VehiclePropValue> mQueuedEvents; 152 private PowerEventListener mListener; 153 private int mMaxDisplayBrightness; 154 155 public PowerHalService(VehicleHal hal) { 156 mHal = hal; 157 } 158 159 public void setListener(PowerEventListener listener) { 160 LinkedList<VehiclePropValue> eventsToDispatch = null; 161 synchronized (this) { 162 mListener = listener; 163 if (mQueuedEvents != null && mQueuedEvents.size() > 0) { 164 eventsToDispatch = mQueuedEvents; 165 } 166 mQueuedEvents = null; 167 } 168 // do this outside lock 169 if (eventsToDispatch != null) { 170 dispatchEvents(eventsToDispatch, listener); 171 } 172 } 173 174 public void sendBootComplete() { 175 Log.i(CarLog.TAG_POWER, "send boot complete"); 176 int[] values = { VehicleApPowerSetState.VEHICLE_AP_POWER_SET_BOOT_COMPLETE, 0 }; 177 mHal.getVehicleNetwork().setIntVectorProperty( 178 VehicleNetworkConsts.VEHICLE_PROPERTY_AP_POWER_STATE, values); 179 } 180 181 public void sendSleepEntry() { 182 Log.i(CarLog.TAG_POWER, "send sleep entry"); 183 int[] values = { VehicleApPowerSetState.VEHICLE_AP_POWER_SET_DEEP_SLEEP_ENTRY, 0 }; 184 mHal.getVehicleNetwork().setIntVectorProperty( 185 VehicleNetworkConsts.VEHICLE_PROPERTY_AP_POWER_STATE, values); 186 } 187 188 public void sendSleepExit() { 189 Log.i(CarLog.TAG_POWER, "send sleep exit"); 190 int[] values = { VehicleApPowerSetState.VEHICLE_AP_POWER_SET_DEEP_SLEEP_EXIT, 0 }; 191 mHal.getVehicleNetwork().setIntVectorProperty( 192 VehicleNetworkConsts.VEHICLE_PROPERTY_AP_POWER_STATE, values); 193 } 194 195 public void sendShutdownPostpone(int postponeTimeMs) { 196 Log.i(CarLog.TAG_POWER, "send shutdown postpone, time:" + postponeTimeMs); 197 int[] values = { VehicleApPowerSetState.VEHICLE_AP_POWER_SET_SHUTDOWN_POSTPONE, 198 postponeTimeMs }; 199 mHal.getVehicleNetwork().setIntVectorProperty( 200 VehicleNetworkConsts.VEHICLE_PROPERTY_AP_POWER_STATE, values); 201 } 202 203 public void sendShutdownStart(int wakeupTimeSec) { 204 Log.i(CarLog.TAG_POWER, "send shutdown start"); 205 int[] values = { VehicleApPowerSetState.VEHICLE_AP_POWER_SET_SHUTDOWN_START, 0 }; 206 mHal.getVehicleNetwork().setIntVectorProperty( 207 VehicleNetworkConsts.VEHICLE_PROPERTY_AP_POWER_STATE, values); 208 } 209 210 public void sendDisplayOn() { 211 Log.i(CarLog.TAG_POWER, "send display on"); 212 int[] values = { VehicleApPowerSetState.VEHICLE_AP_POWER_SET_DISPLAY_ON, 0 }; 213 mHal.getVehicleNetwork().setIntVectorProperty( 214 VehicleNetworkConsts.VEHICLE_PROPERTY_AP_POWER_STATE, values); 215 } 216 217 public void sendDisplayOff() { 218 Log.i(CarLog.TAG_POWER, "send display off"); 219 int[] values = { VehicleApPowerSetState.VEHICLE_AP_POWER_SET_DISPLAY_OFF, 0 }; 220 mHal.getVehicleNetwork().setIntVectorProperty( 221 VehicleNetworkConsts.VEHICLE_PROPERTY_AP_POWER_STATE, values); 222 } 223 224 public PowerState getCurrentPowerState() { 225 int[] state = mHal.getVehicleNetwork().getIntVectorProperty( 226 VehicleNetworkConsts.VEHICLE_PROPERTY_AP_POWER_STATE); 227 return new PowerState(state[VehicleApPowerStateIndex.VEHICLE_AP_POWER_STATE_INDEX_STATE], 228 state[VehicleApPowerStateIndex.VEHICLE_AP_POWER_STATE_INDEX_ADDITIONAL]); 229 } 230 231 public synchronized boolean isPowerStateSupported() { 232 VehiclePropConfig config = mProperties.get( 233 VehicleNetworkConsts.VEHICLE_PROPERTY_AP_POWER_STATE); 234 return config != null; 235 } 236 237 public synchronized boolean isDeepSleepAllowed() { 238 VehiclePropConfig config = mProperties.get( 239 VehicleNetworkConsts.VEHICLE_PROPERTY_AP_POWER_STATE); 240 if (config == null) { 241 return false; 242 } 243 return (config.getConfigArray(0) & 244 VehicleApPowerStateConfigFlag.VEHICLE_AP_POWER_STATE_CONFIG_ENABLE_DEEP_SLEEP_FLAG) 245 != 0; 246 } 247 248 public synchronized boolean isTimedWakeupAllowed() { 249 VehiclePropConfig config = mProperties.get( 250 VehicleNetworkConsts.VEHICLE_PROPERTY_AP_POWER_STATE); 251 if (config == null) { 252 return false; 253 } 254 return (config.getConfigArray(0) & 255 VehicleApPowerStateConfigFlag.VEHICLE_AP_POWER_STATE_CONFIG_SUPPORT_TIMER_POWER_ON_FLAG) 256 != 0; 257 } 258 259 @Override 260 public synchronized void init() { 261 for (VehiclePropConfig config : mProperties.values()) { 262 if (VehicleHal.isPropertySubscribable(config)) { 263 mHal.subscribeProperty(this, config.getProp(), 0); 264 } 265 } 266 VehiclePropConfig brightnessProperty = mProperties.get( 267 VehicleNetworkConsts.VEHICLE_PROPERTY_DISPLAY_BRIGHTNESS); 268 if (brightnessProperty != null) { 269 mMaxDisplayBrightness = brightnessProperty.getInt32Maxs(0); 270 if (mMaxDisplayBrightness <= 0) { 271 Log.w(CarLog.TAG_POWER, "Max display brightness from vehicle HAL is invald:" + 272 mMaxDisplayBrightness); 273 mMaxDisplayBrightness = 1; 274 } 275 } 276 } 277 278 @Override 279 public synchronized void release() { 280 mProperties.clear(); 281 } 282 283 @Override 284 public List<VehiclePropConfig> takeSupportedProperties(List<VehiclePropConfig> allProperties) { 285 for (VehiclePropConfig config : allProperties) { 286 switch (config.getProp()) { 287 case VehicleNetworkConsts.VEHICLE_PROPERTY_AP_POWER_STATE: 288 case VehicleNetworkConsts.VEHICLE_PROPERTY_DISPLAY_BRIGHTNESS: 289 mProperties.put(config.getProp(), config); 290 break; 291 } 292 } 293 return new LinkedList<VehiclePropConfig>(mProperties.values()); 294 } 295 296 @Override 297 public void handleHalEvents(List<VehiclePropValue> values) { 298 PowerEventListener listener; 299 synchronized (this) { 300 if (mListener == null) { 301 if (mQueuedEvents == null) { 302 mQueuedEvents = new LinkedList<VehiclePropValue>(); 303 } 304 mQueuedEvents.addAll(values); 305 return; 306 } 307 listener = mListener; 308 } 309 dispatchEvents(values, listener); 310 } 311 312 private void dispatchEvents(List<VehiclePropValue> values, PowerEventListener listener) { 313 for (VehiclePropValue v : values) { 314 switch (v.getProp()) { 315 case VehicleNetworkConsts.VEHICLE_PROPERTY_AP_POWER_STATE: 316 listener.onApPowerStateChange(new PowerState( 317 v.getInt32Values( 318 VehicleApPowerStateIndex.VEHICLE_AP_POWER_STATE_INDEX_STATE), 319 v.getInt32Values( 320 VehicleApPowerStateIndex.VEHICLE_AP_POWER_STATE_INDEX_ADDITIONAL))); 321 break; 322 case VehicleNetworkConsts.VEHICLE_PROPERTY_DISPLAY_BRIGHTNESS: 323 int maxBrightness; 324 synchronized (this) { 325 maxBrightness = mMaxDisplayBrightness; 326 } 327 listener.onDisplayBrightnessChange(v.getInt32Values(0) * 100 / maxBrightness); 328 break; 329 } 330 } 331 } 332 333 @Override 334 public void dump(PrintWriter writer) { 335 writer.println("*Power HAL*"); 336 writer.println("isPowerStateSupported:" + isPowerStateSupported() + 337 ",isDeepSleepAllowed:" + isDeepSleepAllowed()); 338 } 339 } 340