1 /*
2  * Copyright (C) 2016 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.test.hal;
17 
18 import static com.android.car.internal.ExcludeFromCodeCoverageGeneratedReport.DEBUGGING_CODE;
19 
20 import static org.mockito.Mockito.mock;
21 import static org.mockito.Mockito.when;
22 
23 import android.car.feature.FeatureFlagsImpl;
24 import android.car.test.mocks.JavaMockitoHelper;
25 import android.content.Context;
26 import android.hardware.automotive.vehicle.VehicleApPowerStateReq;
27 import android.util.Log;
28 import android.util.SparseIntArray;
29 import android.view.Display;
30 
31 import com.android.car.CarServiceUtils;
32 import com.android.car.VehicleStub;
33 import com.android.car.hal.ClusterHalService;
34 import com.android.car.hal.DiagnosticHalService;
35 import com.android.car.hal.HalPropValueBuilder;
36 import com.android.car.hal.InputHalService;
37 import com.android.car.hal.PowerHalService;
38 import com.android.car.hal.PropertyHalService;
39 import com.android.car.hal.TimeHalService;
40 import com.android.car.hal.UserHalService;
41 import com.android.car.hal.VehicleHal;
42 import com.android.car.hal.VmsHalService;
43 import com.android.car.internal.ExcludeFromCodeCoverageGeneratedReport;
44 import com.android.car.systeminterface.DisplayHelperInterface;
45 import com.android.internal.annotations.GuardedBy;
46 
47 import java.util.LinkedList;
48 import java.util.concurrent.CountDownLatch;
49 import java.util.concurrent.TimeoutException;
50 
51 @ExcludeFromCodeCoverageGeneratedReport(reason = DEBUGGING_CODE)
52 public class MockedPowerHalService extends PowerHalService {
53     private static final String TAG = MockedPowerHalService.class.getSimpleName();
54 
55     private final boolean mIsPowerStateSupported;
56     private final boolean mIsTimedWakeupAllowed;
57 
58     private final Object mLock = new Object();
59     private final CountDownLatch mBrightnessSendLatch = new CountDownLatch(1);
60 
61     @GuardedBy("mLock")
62     private PowerState mCurrentPowerState = new PowerState(VehicleApPowerStateReq.ON, 0);
63 
64     @GuardedBy("mLock")
65     private PowerEventListener mListener;
66 
67     @GuardedBy("mLock")
68     private SignalListener mSignalListener;
69 
70     @GuardedBy("mLock")
71     private final LinkedList<int[]> mSentStates = new LinkedList<>();
72 
73     @GuardedBy("mLock")
74     private final SparseIntArray mDisplayBrightnessSet = new SparseIntArray();
75 
76     private boolean mIsDeepSleepAllowed;
77     private boolean mIsHibernationAllowed;
78     @PowerState.ShutdownType
79     private int mRequestedShutdownPowerState = PowerState.SHUTDOWN_TYPE_UNDEFINED;
80 
81     public interface SignalListener {
82         /**
83          * Sends signals
84          * @param signal The signal to send
85          */
sendingSignal(int signal)86         void sendingSignal(int signal);
87     }
88 
createVehicleHalWithMockedServices()89     private static VehicleHal createVehicleHalWithMockedServices() {
90         HalPropValueBuilder propValueBuilder = new HalPropValueBuilder(/*isAidl=*/true);
91         VehicleStub vehicleStub = mock(VehicleStub.class);
92         when(vehicleStub.getHalPropValueBuilder()).thenReturn(propValueBuilder);
93         VehicleHal mockedVehicleHal = new VehicleHal(
94                 mock(Context.class),
95                 mock(PowerHalService.class),
96                 mock(PropertyHalService.class),
97                 mock(InputHalService.class),
98                 mock(VmsHalService.class),
99                 mock(UserHalService.class),
100                 mock(DiagnosticHalService.class),
101                 mock(ClusterHalService.class),
102                 mock(TimeHalService.class),
103                 CarServiceUtils.getHandlerThread(VehicleHal.class.getSimpleName()),
104                 vehicleStub);
105 
106         return mockedVehicleHal;
107     }
108 
MockedPowerHalService(boolean isPowerStateSupported, boolean isDeepSleepAllowed, boolean isHibernationAllowed, boolean isTimedWakeupAllowed)109     public MockedPowerHalService(boolean isPowerStateSupported, boolean isDeepSleepAllowed,
110             boolean isHibernationAllowed, boolean isTimedWakeupAllowed) {
111         super(mock(Context.class), new FeatureFlagsImpl(),
112                 createVehicleHalWithMockedServices(), new DisplayHelperInterface.DefaultImpl());
113         mIsPowerStateSupported = isPowerStateSupported;
114         mIsDeepSleepAllowed = isDeepSleepAllowed;
115         mIsHibernationAllowed = isHibernationAllowed;
116         mIsTimedWakeupAllowed = isTimedWakeupAllowed;
117     }
118 
119     @Override
setListener(PowerEventListener listener)120     public void setListener(PowerEventListener listener) {
121         synchronized (mLock) {
122             mListener = listener;
123         }
124     }
125 
126     /**
127      * Sets the signalListener
128      * @param listener The listener to set
129      */
setSignalListener(SignalListener listener)130     public void setSignalListener(SignalListener listener) {
131         synchronized (mLock) {
132             mSignalListener = listener;
133         }
134     }
135 
136     @Override
sendOn()137     public void sendOn() {
138         Log.i(TAG, "sendOn");
139         doSendState(SET_ON, 0);
140     }
141 
142     @Override
sendWaitForVhal()143     public void sendWaitForVhal() {
144         Log.i(TAG, "sendWaitForVhal");
145         doSendState(SET_WAIT_FOR_VHAL, 0);
146     }
147 
148     @Override
sendSleepEntry(int wakeupTimeSec)149     public void sendSleepEntry(int wakeupTimeSec) {
150         Log.i(TAG, "sendSleepEntry");
151         doSendState(SET_DEEP_SLEEP_ENTRY, wakeupTimeSec);
152     }
153 
154     @Override
sendSleepExit()155     public void sendSleepExit() {
156         Log.i(TAG, "sendSleepExit");
157         doSendState(SET_DEEP_SLEEP_EXIT, 0);
158     }
159 
160     @Override
sendShutdownPostpone(int postponeTimeMs)161     public void sendShutdownPostpone(int postponeTimeMs) {
162         Log.i(TAG, "sendShutdownPostpone");
163         doSendState(SET_SHUTDOWN_POSTPONE, postponeTimeMs);
164     }
165 
166     @Override
sendShutdownStart(int wakeupTimeSec)167     public void sendShutdownStart(int wakeupTimeSec) {
168         Log.i(TAG, "sendShutdownStart");
169         doSendState(SET_SHUTDOWN_START, wakeupTimeSec);
170     }
171 
172     @Override
sendShutdownCancel()173     public void sendShutdownCancel() {
174         Log.i(TAG, "sendShutdownCancel");
175         doSendState(SET_SHUTDOWN_CANCELLED, 0);
176     }
177 
178     @Override
sendShutdownPrepare()179     public void sendShutdownPrepare() {
180         Log.i(TAG, "sendShutdownPrepare");
181         super.sendShutdownPrepare();
182     }
183 
184     @Override
sendHibernationEntry(int wakeupTimeSec)185     public void sendHibernationEntry(int wakeupTimeSec) {
186         Log.i(TAG, "sendHibernationEntry");
187         doSendState(SET_HIBERNATION_ENTRY, wakeupTimeSec);
188     }
189 
190     @Override
sendHibernationExit()191     public void sendHibernationExit() {
192         Log.i(TAG, "sendHibernationExit");
193         doSendState(SET_HIBERNATION_EXIT, 0);
194     }
195 
196     @Override
sendDisplayBrightnessLegacy(int brightness)197     public void sendDisplayBrightnessLegacy(int brightness) {
198         sendDisplayBrightness(Display.DEFAULT_DISPLAY, brightness);
199     }
200 
201     @Override
sendDisplayBrightness(int displayId, int brightness)202     public void sendDisplayBrightness(int displayId, int brightness) {
203         synchronized (mLock) {
204             mDisplayBrightnessSet.put(displayId, brightness);
205         }
206         mBrightnessSendLatch.countDown();
207     }
208 
209     /**
210      * Gets the display brightness
211      *
212      * @param displayId DisplayId to check brightness
213      * @return brightness of the displayId
214      */
getDisplayBrightness(int displayId)215     public int getDisplayBrightness(int displayId) {
216         synchronized (mLock) {
217             return mDisplayBrightnessSet.get(displayId, -1);
218         }
219     }
220 
221     /**
222      * Waits for the brightness to be sent
223      *
224      * @param displayId The displayId of the brightness
225      * @param brightness the brightness to set
226      * @param timeoutMs Amount of ms to wait before timeout.
227      * @throws Exception If the brightness is not sent by timeout.
228      */
waitForBrightnessSent(int displayId, int brightness, long timeoutMs)229     public void waitForBrightnessSent(int displayId, int brightness, long timeoutMs)
230             throws Exception {
231         if (getDisplayBrightness(displayId) == brightness) {
232             return;
233         }
234         JavaMockitoHelper.await(mBrightnessSendLatch, timeoutMs);
235     }
236 
237     @Override
requestShutdownAp(@owerState.ShutdownType int powerState, boolean runGarageMode)238     public void requestShutdownAp(@PowerState.ShutdownType int powerState, boolean runGarageMode) {
239         mRequestedShutdownPowerState = powerState;
240     }
241 
getRequestedShutdownPowerState()242     public int getRequestedShutdownPowerState() {
243         return mRequestedShutdownPowerState;
244     }
245 
246     /**
247      * Wait for sent events to be finished
248      *
249      * @param timeoutMs Timeout when events are not all sent by this time
250      * @return All the events that were sent
251      * @throws TimeoutException SentState is empty
252      */
waitForSend(long timeoutMs)253     public int[] waitForSend(long timeoutMs) throws Exception {
254         long now = System.currentTimeMillis();
255         long deadline = now + timeoutMs;
256         synchronized (mLock) {
257             while (mSentStates.isEmpty() && now < deadline) {
258                 mLock.wait(deadline - now);
259                 now = System.currentTimeMillis();
260             }
261             if (mSentStates.isEmpty()) {
262                 throw new TimeoutException("mSentStates is still empty "
263                         + "(monitor was not notified in " + timeoutMs + " ms)");
264             }
265             return mSentStates.removeFirst();
266         }
267     }
268 
doSendState(int state, int param)269     private void doSendState(int state, int param) {
270         int[] toSend = new int[] {state, param};
271         SignalListener listener;
272         synchronized (mLock) {
273             listener = mSignalListener;
274             mSentStates.addLast(toSend);
275             mLock.notifyAll();
276         }
277         if (listener != null) {
278             listener.sendingSignal(state);
279         }
280     }
281 
282     @Override
isPowerStateSupported()283     public boolean isPowerStateSupported() {
284         return mIsPowerStateSupported;
285     }
286 
287     @Override
isDeepSleepAllowed()288     public boolean isDeepSleepAllowed() {
289         return mIsDeepSleepAllowed;
290     }
291 
292     @Override
isHibernationAllowed()293     public boolean isHibernationAllowed() {
294         return mIsHibernationAllowed;
295     }
296 
297     @Override
isTimedWakeupAllowed()298     public boolean isTimedWakeupAllowed() {
299         return mIsTimedWakeupAllowed;
300     }
301 
302     @Override
getCurrentPowerState()303     public PowerState getCurrentPowerState() {
304         synchronized (mLock) {
305             return mCurrentPowerState;
306         }
307     }
308 
setDeepSleepEnabled(boolean enabled)309     public void setDeepSleepEnabled(boolean enabled) {
310         mIsDeepSleepAllowed = enabled;
311     }
312 
setHibernationEnabled(boolean enabled)313     public void setHibernationEnabled(boolean enabled) {
314         mIsHibernationAllowed = enabled;
315     }
316 
317     /**
318      * Sets the current power state to the state that is given.
319      * @param state The power state to set
320      */
setCurrentPowerState(PowerState state)321     public void setCurrentPowerState(PowerState state) {
322         setCurrentPowerState(state, true);
323     }
324 
325     /**
326      * Sets the current power state
327      * @param state The state to set
328      * @param notify If to notify listeners
329      */
setCurrentPowerState(PowerState state, boolean notify)330     public void setCurrentPowerState(PowerState state, boolean notify) {
331         PowerEventListener listener;
332         synchronized (mLock) {
333             mCurrentPowerState = state;
334             listener = mListener;
335         }
336         if (listener != null && notify) {
337             listener.onApPowerStateChange(state);
338         }
339     }
340 }
341