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