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