1fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park/*
2fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park * Copyright (C) 2016 The Android Open Source Project
3fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park *
4fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park * Licensed under the Apache License, Version 2.0 (the "License");
5fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park * you may not use this file except in compliance with the License.
6fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park * You may obtain a copy of the License at
7fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park *
8fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park *      http://www.apache.org/licenses/LICENSE-2.0
9fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park *
10fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park * Unless required by applicable law or agreed to in writing, software
11fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park * distributed under the License is distributed on an "AS IS" BASIS,
12fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park * See the License for the specific language governing permissions and
14fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park * limitations under the License.
15fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park */
16fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park
17ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsevpackage com.android.car;
18fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park
19fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Parkimport android.test.AndroidTestCase;
20a3b34bfdcbd88eab3353e4ef52c9d54ad5416cd4smaraaospimport android.test.suitebuilder.annotation.SmallTest;
21fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Parkimport android.util.Log;
22fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park
23fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Parkimport com.android.car.CarPowerManagementService.PowerEventProcessingHandler;
24fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Parkimport com.android.car.CarPowerManagementService.PowerServiceEventListener;
25fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Parkimport com.android.car.hal.PowerHalService;
26fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Parkimport com.android.car.hal.PowerHalService.PowerState;
27b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granataimport com.android.car.systeminterface.DisplayInterface;
28b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granataimport com.android.car.systeminterface.IOInterface;
29b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granataimport com.android.car.systeminterface.SystemInterface;
30b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granataimport com.android.car.systeminterface.SystemStateInterface;
31b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granataimport com.android.car.systeminterface.WakeLockInterface;
329c1f27227f843f10a2d286ded886464b60854e08Enrico Granataimport com.android.car.test.utils.TemporaryDirectory;
3387b36fdef99fec7fdba383adc48d7dd4671691feSteve Paik
349c1f27227f843f10a2d286ded886464b60854e08Enrico Granataimport java.io.File;
359c1f27227f843f10a2d286ded886464b60854e08Enrico Granataimport java.io.IOException;
36cf53fd7339fd2e4814230f2dae1b5baafc50298cEnrico Granataimport java.time.Duration;
37fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Parkimport java.util.concurrent.Semaphore;
38fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Parkimport java.util.concurrent.TimeUnit;
39fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park
40a3b34bfdcbd88eab3353e4ef52c9d54ad5416cd4smaraaosp@SmallTest
41fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Parkpublic class CarPowerManagementServiceTest extends AndroidTestCase {
42fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park    private static final String TAG = CarPowerManagementServiceTest.class.getSimpleName();
43fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park    private static final long WAIT_TIMEOUT_MS = 2000;
44fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park    private static final long WAIT_TIMEOUT_LONG_MS = 5000;
450d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
46b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata    private final MockDisplayInterface mDisplayInterface = new MockDisplayInterface();
47b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata    private final MockSystemStateInterface mSystemStateInterface = new MockSystemStateInterface();
48b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata    private final MockWakeLockInterface mWakeLockInterface = new MockWakeLockInterface();
49b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata    private final MockIOInterface mIOInterface = new MockIOInterface();
50b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata
51fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park    private MockedPowerHalService mPowerHal;
52b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata    private SystemInterface mSystemInterface;
53fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park    private CarPowerManagementService mService;
54fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park    private final PowerEventListener mPowerEventListener = new PowerEventListener();
55fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park    private PowerEventProcessingHandlerImpl mPowerEventProcessingHandler;
56fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park
57fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park    @Override
58fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park    protected void setUp() throws Exception {
59fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        super.setUp();
60fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        mPowerHal = new MockedPowerHalService(true /*isPowerStateSupported*/,
61fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park                true /*isDeepSleepAllowed*/, true /*isTimedWakeupAllowed*/);
62b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata        mSystemInterface = SystemInterface.Builder.defaultSystemInterface(getContext())
63b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata            .withDisplayInterface(mDisplayInterface)
64b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata            .withSystemStateInterface(mSystemStateInterface)
65b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata            .withWakeLockInterface(mWakeLockInterface)
66b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata            .withIOInterface(mIOInterface).build();
67fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park    }
68fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park
69fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park    @Override
70fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park    protected void tearDown() throws Exception {
71fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        super.tearDown();
72fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        if (mService != null) {
73fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            mService.release();
74fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        }
75b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata        mIOInterface.tearDown();
76fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park    }
77fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park
78388d77770e00eadde4e45df95678f1468ce6fbc8Steve Paik    /**
79388d77770e00eadde4e45df95678f1468ce6fbc8Steve Paik     * Helper method to create mService and initialize a test case
80388d77770e00eadde4e45df95678f1468ce6fbc8Steve Paik     */
81388d77770e00eadde4e45df95678f1468ce6fbc8Steve Paik    private void initTest(long processingTimeMs, int wakeupTime) throws Exception {
82388d77770e00eadde4e45df95678f1468ce6fbc8Steve Paik        mService = new CarPowerManagementService(getContext(), mPowerHal, mSystemInterface);
83fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        mService.init();
84fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        mService.registerPowerEventListener(mPowerEventListener);
85388d77770e00eadde4e45df95678f1468ce6fbc8Steve Paik        mPowerEventProcessingHandler = new PowerEventProcessingHandlerImpl(processingTimeMs,
86388d77770e00eadde4e45df95678f1468ce6fbc8Steve Paik                                                                           wakeupTime);
87fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        mService.registerPowerEventProcessingHandler(mPowerEventProcessingHandler);
88fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        assertStateReceived(MockedPowerHalService.SET_BOOT_COMPLETE, 0);
89fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        mPowerEventProcessingHandler.waitForPowerOn(WAIT_TIMEOUT_MS);
90fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park    }
91fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park
92388d77770e00eadde4e45df95678f1468ce6fbc8Steve Paik    public void testBootComplete() throws Exception {
93388d77770e00eadde4e45df95678f1468ce6fbc8Steve Paik        initTest(0, 0);
94388d77770e00eadde4e45df95678f1468ce6fbc8Steve Paik    }
95388d77770e00eadde4e45df95678f1468ce6fbc8Steve Paik
96fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park    public void testDisplayOff() throws Exception {
97388d77770e00eadde4e45df95678f1468ce6fbc8Steve Paik        initTest(0,0);
98fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        // it will call display on for initial state
99b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata        assertTrue(mDisplayInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
100fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        mPowerHal.setCurrentPowerState(new PowerState(PowerHalService.STATE_ON_DISP_OFF, 0));
101b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata        assertFalse(mDisplayInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
102fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park    }
103fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park
104fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park    public void testDisplayOn() throws Exception {
105fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        // start with display off
106fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        mSystemInterface.setDisplayState(false);
107b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata        mDisplayInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS);
108388d77770e00eadde4e45df95678f1468ce6fbc8Steve Paik        initTest(0,0);
109fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park
110fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        // display should be turned on as it started with off state.
111b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata        assertTrue(mDisplayInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
112fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park    }
113fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park
114fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park    public void testShutdown() throws Exception {
115fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        final int wakeupTime = 100;
116388d77770e00eadde4e45df95678f1468ce6fbc8Steve Paik        initTest(0, wakeupTime);
117b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata        assertTrue(mDisplayInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
118fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park
119fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        mPowerHal.setCurrentPowerState(new PowerState(PowerHalService.STATE_SHUTDOWN_PREPARE,
120110f95fab53232280d6c21ed433f5a40c9320e4eSteve Paik                PowerHalService.SHUTDOWN_IMMEDIATELY));
121fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        assertStateReceived(PowerHalService.SET_SHUTDOWN_START, wakeupTime);
122b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata        assertFalse(mDisplayInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
123fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        mPowerEventListener.waitForShutdown(WAIT_TIMEOUT_MS);
124b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata        mSystemStateInterface.waitForShutdown(WAIT_TIMEOUT_MS);
125fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park    }
126fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park
127fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park    public void testShutdownWithProcessing() throws Exception {
128fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        final long processingTimeMs = 3000;
129fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        final int wakeupTime = 100;
130388d77770e00eadde4e45df95678f1468ce6fbc8Steve Paik        initTest(processingTimeMs, wakeupTime);
131b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata        assertTrue(mDisplayInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
132fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park
133fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        mPowerHal.setCurrentPowerState(new PowerState(PowerHalService.STATE_SHUTDOWN_PREPARE, 0));
134fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        mPowerEventProcessingHandler.waitForPrepareShutdown(WAIT_TIMEOUT_MS);
135fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        assertStateReceivedForShutdownOrSleepWithPostpone(PowerHalService.SET_SHUTDOWN_START,
136fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park                WAIT_TIMEOUT_LONG_MS, wakeupTime);
137b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata        assertFalse(mDisplayInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
138fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        mPowerEventListener.waitForShutdown(WAIT_TIMEOUT_MS);
139b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata        mSystemStateInterface.waitForShutdown(WAIT_TIMEOUT_MS);
140fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park    }
141fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park
142fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park    public void testSleepEntryAndWakeup() throws Exception {
143fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        final int wakeupTime = 100;
144388d77770e00eadde4e45df95678f1468ce6fbc8Steve Paik        initTest(0, wakeupTime);
145b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata        assertTrue(mDisplayInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
146fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park
147fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        mPowerHal.setCurrentPowerState(new PowerState(PowerHalService.STATE_SHUTDOWN_PREPARE,
148110f95fab53232280d6c21ed433f5a40c9320e4eSteve Paik                PowerHalService.SHUTDOWN_CAN_SLEEP));
149b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata        assertFalse(mDisplayInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
150fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        assertStateReceived(PowerHalService.SET_DEEP_SLEEP_ENTRY, 0);
151fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        mPowerEventListener.waitForSleepEntry(WAIT_TIMEOUT_MS);
152b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata        int wakeupTimeReceived = mSystemStateInterface.waitForSleepEntryAndWakeup(WAIT_TIMEOUT_MS);
153fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        assertEquals(wakeupTime, wakeupTimeReceived);
154fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        assertStateReceived(PowerHalService.SET_DEEP_SLEEP_EXIT, 0);
155fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        mPowerEventListener.waitForSleepExit(WAIT_TIMEOUT_MS);
156fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park
157fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park    }
158fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park
159fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park    public void testSleepEntryAndPowerOnWithProcessing() throws Exception {
160fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        final long processingTimeMs = 3000;
161fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        final int wakeupTime = 100;
162388d77770e00eadde4e45df95678f1468ce6fbc8Steve Paik        initTest(processingTimeMs, wakeupTime);
163b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata        assertTrue(mDisplayInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
164fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park
165fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        mPowerHal.setCurrentPowerState(new PowerState(PowerHalService.STATE_SHUTDOWN_PREPARE,
166110f95fab53232280d6c21ed433f5a40c9320e4eSteve Paik                PowerHalService.SHUTDOWN_CAN_SLEEP));
167fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        mPowerEventProcessingHandler.waitForPrepareShutdown(WAIT_TIMEOUT_MS);
168b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata        assertFalse(mDisplayInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
169fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        assertStateReceivedForShutdownOrSleepWithPostpone(PowerHalService.SET_DEEP_SLEEP_ENTRY,
170fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park                WAIT_TIMEOUT_LONG_MS, 0);
171fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        mPowerEventListener.waitForSleepEntry(WAIT_TIMEOUT_MS);
172fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        // set power on here without notification. PowerManager should check the state after sleep
173fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        // exit
174fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        mPowerHal.setCurrentPowerState(new PowerState(PowerHalService.STATE_ON_DISP_OFF, 0), false);
175b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata        int wakeupTimeReceived = mSystemStateInterface.waitForSleepEntryAndWakeup(WAIT_TIMEOUT_MS);
176fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        assertEquals(wakeupTime, wakeupTimeReceived);
177fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        assertStateReceived(PowerHalService.SET_DEEP_SLEEP_EXIT, 0);
178fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        mPowerEventListener.waitForSleepExit(WAIT_TIMEOUT_MS);
179fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        mPowerEventProcessingHandler.waitForPowerOn(WAIT_TIMEOUT_MS);
180fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park    }
181fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park
182fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park    public void testSleepEntryAndWakeUpForProcessing() throws Exception {
183fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        final long processingTimeMs = 3000;
184fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        final int wakeupTime = 100;
185388d77770e00eadde4e45df95678f1468ce6fbc8Steve Paik        initTest(processingTimeMs, wakeupTime);
186b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata        assertTrue(mDisplayInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
187fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park
188fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        mPowerHal.setCurrentPowerState(new PowerState(PowerHalService.STATE_SHUTDOWN_PREPARE,
189110f95fab53232280d6c21ed433f5a40c9320e4eSteve Paik                PowerHalService.SHUTDOWN_CAN_SLEEP));
190fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        mPowerEventProcessingHandler.waitForPrepareShutdown(WAIT_TIMEOUT_MS);
191b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata        assertFalse(mDisplayInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
192fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        assertStateReceivedForShutdownOrSleepWithPostpone(PowerHalService.SET_DEEP_SLEEP_ENTRY,
193fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park                WAIT_TIMEOUT_LONG_MS, 0);
194fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        mPowerEventListener.waitForSleepEntry(WAIT_TIMEOUT_MS);
195b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata        mSystemStateInterface.setWakeupCausedByTimer(true);
196b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata        int wakeupTimeReceived = mSystemStateInterface.waitForSleepEntryAndWakeup(WAIT_TIMEOUT_MS);
197fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        assertEquals(wakeupTime, wakeupTimeReceived);
198fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        assertStateReceived(PowerHalService.SET_DEEP_SLEEP_EXIT, 0);
199fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        mPowerEventListener.waitForSleepExit(WAIT_TIMEOUT_MS);
200fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        // second processing after wakeup
201b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata        assertFalse(mDisplayInterface.getDisplayState());
202fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        mPowerEventProcessingHandler.waitForPrepareShutdown(WAIT_TIMEOUT_MS);
203fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        assertStateReceivedForShutdownOrSleepWithPostpone(PowerHalService.SET_DEEP_SLEEP_ENTRY,
204fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park                WAIT_TIMEOUT_LONG_MS, 0);
205fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        mPowerEventListener.waitForSleepEntry(WAIT_TIMEOUT_MS);
206fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        // PM will shutdown system as it was not woken-up due to timer and it is not power on.
207b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata        mSystemStateInterface.setWakeupCausedByTimer(false);
208b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata        wakeupTimeReceived = mSystemStateInterface.waitForSleepEntryAndWakeup(WAIT_TIMEOUT_MS);
209fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        assertEquals(wakeupTime, wakeupTimeReceived);
210fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        assertStateReceived(PowerHalService.SET_DEEP_SLEEP_EXIT, 0);
211fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        assertStateReceived(PowerHalService.SET_SHUTDOWN_START, wakeupTime);
212fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        mPowerEventListener.waitForShutdown(WAIT_TIMEOUT_MS);
213b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata        mSystemStateInterface.waitForShutdown(WAIT_TIMEOUT_MS);
214b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata        assertFalse(mDisplayInterface.getDisplayState());
215fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park    }
216fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park
217fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park    private void assertStateReceived(int expectedState, int expectedParam) throws Exception {
218fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        int[] state = mPowerHal.waitForSend(WAIT_TIMEOUT_MS);
219fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        assertEquals(expectedState, state[0]);
220fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        assertEquals(expectedParam, state[1]);
221fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park    }
222fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park
223fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park    private void assertStateReceivedForShutdownOrSleepWithPostpone(int lastState, long timeoutMs,
224fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            int expectedParamForShutdown) throws Exception {
225fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        while (true) {
226fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            int[] state = mPowerHal.waitForSend(timeoutMs);
227fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            if (state[0] == PowerHalService.SET_SHUTDOWN_POSTPONE) {
228fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park                continue;
229fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            }
230fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            if (state[0] == lastState) {
231fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park                assertEquals(expectedParamForShutdown, state[1]);
232fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park                return;
233fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            }
234fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        }
235fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park    }
236fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park
237fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park    private static void waitForSemaphore(Semaphore semaphore, long timeoutMs)
238fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            throws InterruptedException {
239fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        if (!semaphore.tryAcquire(timeoutMs, TimeUnit.MILLISECONDS)) {
240fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            throw new IllegalStateException("timeout");
241fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        }
242fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park    }
243fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park
244b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata    private static final class MockDisplayInterface implements DisplayInterface {
245fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        private boolean mDisplayOn = true;
246fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        private final Semaphore mDisplayStateWait = new Semaphore(0);
247fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park
248fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        @Override
24987b36fdef99fec7fdba383adc48d7dd4671691feSteve Paik        public void setDisplayBrightness(int brightness) {}
25087b36fdef99fec7fdba383adc48d7dd4671691feSteve Paik
25187b36fdef99fec7fdba383adc48d7dd4671691feSteve Paik        @Override
252fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        public synchronized void setDisplayState(boolean on) {
253fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            mDisplayOn = on;
254fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            mDisplayStateWait.release();
255fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        }
256fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park
257fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        public synchronized boolean getDisplayState() {
258fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            return mDisplayOn;
259fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        }
260fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park
261fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        public boolean waitForDisplayStateChange(long timeoutMs) throws Exception {
262fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            waitForSemaphore(mDisplayStateWait, timeoutMs);
263fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            return mDisplayOn;
264fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        }
265fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park
266fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        @Override
267b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata        public void startDisplayStateMonitoring(CarPowerManagementService service) {}
268b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata
269b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata        @Override
270b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata        public void stopDisplayStateMonitoring() {}
271b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata    }
272b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata
273b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata    private static final class MockSystemStateInterface implements SystemStateInterface {
274b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata        private final Semaphore mShutdownWait = new Semaphore(0);
275b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata        private final Semaphore mSleepWait = new Semaphore(0);
276b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata        private final Semaphore mSleepExitWait = new Semaphore(0);
277b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata        private int mWakeupTime;
278b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata        private boolean mWakeupCausedByTimer = false;
279fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park
280fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        @Override
281fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        public void shutdown() {
282fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            mShutdownWait.release();
283fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        }
284fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park
285fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        public void waitForShutdown(long timeoutMs) throws Exception {
286fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            waitForSemaphore(mShutdownWait, timeoutMs);
287fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        }
288fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park
289fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        @Override
2900f9fc00ffb03bc8e88c0a55e2e21b4ffdba19edfSteve Paik        public boolean enterDeepSleep(int wakeupTimeSec) {
291fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            mWakeupTime = wakeupTimeSec;
292fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            mSleepWait.release();
293fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            try {
294fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park                mSleepExitWait.acquire();
295fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            } catch (InterruptedException e) {
296fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            }
2970f9fc00ffb03bc8e88c0a55e2e21b4ffdba19edfSteve Paik            return true;
298fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        }
299fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park
300fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        public int waitForSleepEntryAndWakeup(long timeoutMs) throws Exception {
301fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            waitForSemaphore(mSleepWait, timeoutMs);
302fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            mSleepExitWait.release();
303fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            return mWakeupTime;
304fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        }
305fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park
306fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        @Override
307b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata        public void scheduleActionForBootCompleted(Runnable action, Duration delay) {}
308fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park
309fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        @Override
310b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata        public boolean isWakeupCausedByTimer() {
311b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata            Log.i(TAG, "isWakeupCausedByTimer:" + mWakeupCausedByTimer);
312b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata            return mWakeupCausedByTimer;
313fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        }
314fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park
315b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata        public synchronized void setWakeupCausedByTimer(boolean set) {
316b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata            mWakeupCausedByTimer = set;
317fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        }
318fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park
319fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        @Override
320b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata        public boolean isSystemSupportingDeepSleep() {
321b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata            return true;
322fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        }
323b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata    }
324b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata
325b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata    private static final class MockWakeLockInterface implements WakeLockInterface {
326fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park
327fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        @Override
328b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata        public void releaseAllWakeLocks() {}
329b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata
330b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata        @Override
331b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata        public void switchToPartialWakeLock() {}
332b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata
333b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata        @Override
334b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata        public void switchToFullWakeLock() {}
335b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata    }
336b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata
337b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata    private static final class MockIOInterface implements IOInterface {
338b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata        private TemporaryDirectory mFilesDir;
339fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park
340517a1e0666fc801dc38ee387013bb05ee965b1a6Enrico Granata        @Override
3419c1f27227f843f10a2d286ded886464b60854e08Enrico Granata        public File getFilesDir() {
3429c1f27227f843f10a2d286ded886464b60854e08Enrico Granata            if (mFilesDir == null) {
3439c1f27227f843f10a2d286ded886464b60854e08Enrico Granata                try {
3449c1f27227f843f10a2d286ded886464b60854e08Enrico Granata                    mFilesDir = new TemporaryDirectory(TAG);
3459c1f27227f843f10a2d286ded886464b60854e08Enrico Granata                } catch (IOException e) {
3469c1f27227f843f10a2d286ded886464b60854e08Enrico Granata                    Log.e(TAG, "failed to create temporary directory", e);
3479c1f27227f843f10a2d286ded886464b60854e08Enrico Granata                    fail("failed to create temporary directory. exception was: " + e);
3489c1f27227f843f10a2d286ded886464b60854e08Enrico Granata                }
3499c1f27227f843f10a2d286ded886464b60854e08Enrico Granata            }
3509c1f27227f843f10a2d286ded886464b60854e08Enrico Granata            return mFilesDir.getDirectory();
3519c1f27227f843f10a2d286ded886464b60854e08Enrico Granata        }
3529c1f27227f843f10a2d286ded886464b60854e08Enrico Granata
353b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata        public void tearDown() {
3549c1f27227f843f10a2d286ded886464b60854e08Enrico Granata            if (mFilesDir != null) {
3559c1f27227f843f10a2d286ded886464b60854e08Enrico Granata                try {
3569c1f27227f843f10a2d286ded886464b60854e08Enrico Granata                    mFilesDir.close();
3579c1f27227f843f10a2d286ded886464b60854e08Enrico Granata                } catch (Exception e) {
3589c1f27227f843f10a2d286ded886464b60854e08Enrico Granata                    Log.w(TAG, "could not remove temporary directory", e);
3599c1f27227f843f10a2d286ded886464b60854e08Enrico Granata                }
3609c1f27227f843f10a2d286ded886464b60854e08Enrico Granata            }
3619c1f27227f843f10a2d286ded886464b60854e08Enrico Granata        }
362fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park    }
363fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park
364fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park    private class PowerEventListener implements PowerServiceEventListener {
365fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        private final Semaphore mShutdownWait = new Semaphore(0);
366fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        private final Semaphore mSleepEntryWait = new Semaphore(0);
367fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        private final Semaphore mSleepExitWait = new Semaphore(0);
368fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park
369fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        @Override
370fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        public void onShutdown() {
371fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            mShutdownWait.release();
372fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        }
373fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park
374fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        public void waitForShutdown(long timeoutMs) throws Exception {
375fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            waitForSemaphore(mShutdownWait, timeoutMs);
376fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        }
377fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park
378fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        @Override
379fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        public void onSleepEntry() {
380fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            mSleepEntryWait.release();
381fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        }
382fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park
383fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        public void waitForSleepEntry(long timeoutMs) throws Exception {
384fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            waitForSemaphore(mSleepEntryWait, timeoutMs);
385fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        }
386fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park
387fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        @Override
388fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        public void onSleepExit() {
389fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            mSleepExitWait.release();
390fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        }
391fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park
392fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        public void waitForSleepExit(long timeoutMs) throws Exception {
393fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            waitForSemaphore(mSleepExitWait, timeoutMs);
394fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        }
395fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park    }
396fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park
397fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park    private class PowerEventProcessingHandlerImpl implements PowerEventProcessingHandler {
398fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        private final long mProcessingTime;
399fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        private final int mWakeupTime;
400fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        private final Semaphore mPrepareShutdownWait = new Semaphore(0);
401fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        private final Semaphore mOnPowerOnWait = new Semaphore(0);
402fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        private boolean mShuttingDown;
403fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        private boolean mDisplayOn;
404fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park
405fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        private PowerEventProcessingHandlerImpl(long processingTime, int wakeupTime) {
406fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            mProcessingTime = processingTime;
407fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            mWakeupTime = wakeupTime;
408fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        }
409fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park
410fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        @Override
411fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        public long onPrepareShutdown(boolean shuttingDown) {
412fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            mShuttingDown = shuttingDown;
413fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            mPrepareShutdownWait.release();
414fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            return mProcessingTime;
415fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        }
416fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        public boolean waitForPrepareShutdown(long timeoutMs) throws Exception {
417fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            waitForSemaphore(mPrepareShutdownWait, timeoutMs);
418fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            return mShuttingDown;
419fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        }
420fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park
421fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        @Override
422fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        public void onPowerOn(boolean displayOn) {
423fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            mDisplayOn = displayOn;
424fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            mOnPowerOnWait.release();
425fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        }
426fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park
427fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        public boolean waitForPowerOn(long timeoutMs) throws Exception {
428fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            waitForSemaphore(mOnPowerOnWait, timeoutMs);
429fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            return mDisplayOn;
430fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        }
431fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park
432fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        @Override
433fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        public int getWakeupTime() {
434fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            return mWakeupTime;
435fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        }
436fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park    }
437fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park}
438