Home | History | Annotate | Download | only in hal
      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