/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.car;

import static android.content.pm.UserInfo.FLAG_EPHEMERAL;
import static android.os.UserHandle.USER_SYSTEM;
import static android.os.UserManager.USER_TYPE_FULL_GUEST;

import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;

import static com.google.common.truth.Truth.assertThat;

import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.notNull;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.when;

import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import android.annotation.Nullable;
import android.app.ActivityManager;
import android.car.hardware.power.CarPowerManager.CarPowerStateListener;
import android.car.hardware.power.ICarPowerStateListener;
import android.car.userlib.CarUserManagerHelper;
import android.content.Context;
import android.content.pm.UserInfo;
import android.content.res.Resources;
import android.hardware.automotive.vehicle.V2_0.VehicleApPowerStateReq;
import android.hardware.automotive.vehicle.V2_0.VehicleApPowerStateShutdownParam;
import android.os.RemoteException;
import android.os.UserManager;
import android.test.suitebuilder.annotation.SmallTest;
import android.util.Log;

import androidx.test.filters.FlakyTest;
import androidx.test.platform.app.InstrumentationRegistry;

import com.android.car.hal.PowerHalService;
import com.android.car.hal.PowerHalService.PowerState;
import com.android.car.systeminterface.DisplayInterface;
import com.android.car.systeminterface.IOInterface;
import com.android.car.systeminterface.SystemInterface;
import com.android.car.systeminterface.SystemStateInterface;
import com.android.car.systeminterface.WakeLockInterface;
import com.android.car.test.utils.TemporaryDirectory;

import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestRule;
import org.junit.rules.TestWatcher;
import org.junit.runner.Description;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoSession;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.junit.MockitoJUnitRunner;
import org.mockito.quality.Strictness;

import java.io.File;
import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import java.lang.reflect.Method;
import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;

@SmallTest
@RunWith(MockitoJUnitRunner.class)
public class CarPowerManagementServiceTest {
    private static final String TAG = CarPowerManagementServiceTest.class.getSimpleName();
    private static final long WAIT_TIMEOUT_MS = 2000;
    private static final long WAIT_TIMEOUT_LONG_MS = 5000;
    private static final int NO_USER_INFO_FLAGS = 0;
    private static final String NEW_GUEST_NAME = "NewestGuestInTheBlock";

    private final MockDisplayInterface mDisplayInterface = new MockDisplayInterface();
    private final MockSystemStateInterface mSystemStateInterface = new MockSystemStateInterface();
    private final MockWakeLockInterface mWakeLockInterface = new MockWakeLockInterface();
    private final MockIOInterface mIOInterface = new MockIOInterface();
    private final PowerSignalListener mPowerSignalListener = new PowerSignalListener();
    private final Context mContext = InstrumentationRegistry.getInstrumentation().getContext();

    private MockitoSession mSession;

    private MockedPowerHalService mPowerHal;
    private SystemInterface mSystemInterface;
    private CarPowerManagementService mService;
    private CompletableFuture<Void> mFuture;

    @Mock
    private CarUserManagerHelper mCarUserManagerHelper;
    @Mock
    private UserManager mUserManager;
    @Mock
    private Resources mResources;

    // Wakeup time for the test; it's automatically set based on @WakeupTime annotation
    private int mWakeupTime;

    // Value used to set config_disableUserSwitchDuringResume - must be defined before initTest();
    private boolean mDisableUserSwitchDuringResume;

    // Tracks Log.wtf() calls made during code execution / used on verifyWtfNeverLogged()
    // TODO: move mechanism to common code / custom Rule
    private final List<UnsupportedOperationException> mWtfs = new ArrayList<>();

    @Rule
    public final TestRule setWakeupTimeRule = new TestWatcher() {
        protected void starting(Description description) {
            final String testName = description.getMethodName();
            try {
                Method testMethod = CarPowerManagementServiceTest.class.getMethod(testName);
                WakeupTime wakeupAnnotation = testMethod.getAnnotation(WakeupTime.class);
                if (wakeupAnnotation != null) {
                    mWakeupTime = wakeupAnnotation.value();
                    Log.d(TAG, "Using annotated wakeup time: " + mWakeupTime);
                }
            } catch (Exception e) {
                Log.e(TAG, "Could not infer wakeupTime for " + testName, e);
            }
        }
    };

    @Before
    public void setUp() throws Exception {
        mSession = mockitoSession()
                .strictness(Strictness.LENIENT)
                .spyStatic(ActivityManager.class)
                .spyStatic(Log.class)
                .startMocking();
        mPowerHal = new MockedPowerHalService(true /*isPowerStateSupported*/,
                true /*isDeepSleepAllowed*/, true /*isTimedWakeupAllowed*/);
        mSystemInterface = SystemInterface.Builder.defaultSystemInterface(mContext)
            .withDisplayInterface(mDisplayInterface)
            .withSystemStateInterface(mSystemStateInterface)
            .withWakeLockInterface(mWakeLockInterface)
            .withIOInterface(mIOInterface).build();
        doAnswer((invocation) -> {
            return addWtf(invocation);
        }).when(() -> Log.wtf(anyString(), anyString()));
        doAnswer((invocation) -> {
            return addWtf(invocation);
        }).when(() -> Log.wtf(anyString(), anyString(), notNull()));
    }

    @After
    public void tearDown() throws Exception {
        if (mService != null) {
            mService.release();
        }
        mIOInterface.tearDown();
        mSession.finishMocking();
    }


    private Object addWtf(InvocationOnMock invocation) {
        String message = "Called " + invocation;
        Log.d(TAG, message); // Log always, as some test expect it
        mWtfs.add(new UnsupportedOperationException(message));
        return null;
    }

    /**
     * Helper method to create mService and initialize a test case
     */
    private void initTest() throws Exception {
        when(mResources.getInteger(R.integer.maxGarageModeRunningDurationInSecs))
                .thenReturn(900);
        when(mResources.getBoolean(R.bool.config_disableUserSwitchDuringResume))
                .thenReturn(mDisableUserSwitchDuringResume);

        Log.i(TAG, "initTest(): overridden overlay properties: "
                + "config_disableUserSwitchDuringResume="
                + mResources.getBoolean(R.bool.config_disableUserSwitchDuringResume)
                + ", maxGarageModeRunningDurationInSecs="
                + mResources.getInteger(R.integer.maxGarageModeRunningDurationInSecs));
        mService = new CarPowerManagementService(mContext, mResources, mPowerHal,
                mSystemInterface, mCarUserManagerHelper, mUserManager, NEW_GUEST_NAME);
        mService.init();
        mService.setShutdownTimersForTest(0, 0);
        mPowerHal.setSignalListener(mPowerSignalListener);
        if (mWakeupTime > 0) {
            registerListenerToService();
            mService.scheduleNextWakeupTime(mWakeupTime);
        }
        assertStateReceived(MockedPowerHalService.SET_WAIT_FOR_VHAL, 0);
    }

    /**
     * Same as {@link #initTest()}, but it also assumes the current and initial users are user 10.
     */
    private void initTestForUser10() throws Exception {
        initTest();
        setUserInfo(10, NO_USER_INFO_FLAGS);
        setCurrentUser(10);
        setInitialUser(10);
    }

    @Test
    public void testBootComplete() throws Exception {
        initTest();

        verifyWtfNeverLogged();
    }

    @Test
    public void testDisplayOn() throws Exception {
        // start with display off
        mSystemInterface.setDisplayState(false);
        mDisplayInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS);
        initTest();
        // Transition to ON state
        mPowerHal.setCurrentPowerState(new PowerState(VehicleApPowerStateReq.ON, 0));

        // display should be turned on as it started with off state.
        assertThat(mDisplayInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS)).isTrue();

        verifyWtfNeverLogged();
    }

    @Test
    public void testShutdown() throws Exception {
        initTestForUser10();

        // Transition to ON state
        mPowerHal.setCurrentPowerState(new PowerState(VehicleApPowerStateReq.ON, 0));
        assertThat(mDisplayInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS)).isTrue();

        mPowerHal.setCurrentPowerState(
                new PowerState(
                        VehicleApPowerStateReq.SHUTDOWN_PREPARE,
                        VehicleApPowerStateShutdownParam.SHUTDOWN_IMMEDIATELY));
        // Since modules have to manually schedule next wakeup, we should not schedule next wakeup
        // To test module behavior, we need to actually implement mock listener module.
        assertStateReceived(PowerHalService.SET_SHUTDOWN_START, 0);
        assertThat(mDisplayInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS)).isFalse();
        mPowerSignalListener.waitForShutdown(WAIT_TIMEOUT_MS);
        mSystemStateInterface.waitForShutdown(WAIT_TIMEOUT_MS);

        verifyWtfNeverLogged();
    }

    @Test
    public void testSuspend() throws Exception {
        initTestForUser10();

        // Start in the ON state
        mPowerHal.setCurrentPowerState(new PowerState(VehicleApPowerStateReq.ON, 0));
        assertThat(mDisplayInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS)).isTrue();
        // Request suspend
        mPowerHal.setCurrentPowerState(
                new PowerState(
                        VehicleApPowerStateReq.SHUTDOWN_PREPARE,
                        VehicleApPowerStateShutdownParam.CAN_SLEEP));
        // Verify suspend
        assertStateReceivedForShutdownOrSleepWithPostpone(
                PowerHalService.SET_DEEP_SLEEP_ENTRY, WAIT_TIMEOUT_LONG_MS, mWakeupTime);

        verifyWtfNeverLogged();
    }

    @Test
    public void testShutdownOnSuspend() throws Exception {
        initTestForUser10();

        // Start in the ON state
        mPowerHal.setCurrentPowerState(new PowerState(VehicleApPowerStateReq.ON, 0));
        assertThat(mDisplayInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS)).isTrue();
        // Tell it to shutdown
        mService.requestShutdownOnNextSuspend();
        // Request suspend
        mPowerHal.setCurrentPowerState(
                new PowerState(
                        VehicleApPowerStateReq.SHUTDOWN_PREPARE,
                        VehicleApPowerStateShutdownParam.CAN_SLEEP));
        // Verify shutdown
        assertStateReceivedForShutdownOrSleepWithPostpone(
                PowerHalService.SET_SHUTDOWN_START, WAIT_TIMEOUT_LONG_MS, mWakeupTime);
        mPowerSignalListener.waitForShutdown(WAIT_TIMEOUT_MS);
        // Send the finished signal
        mPowerHal.setCurrentPowerState(new PowerState(VehicleApPowerStateReq.FINISHED, 0));
        mSystemStateInterface.waitForShutdown(WAIT_TIMEOUT_MS);
        // Cancel the shutdown
        mPowerHal.setCurrentPowerState(new PowerState(VehicleApPowerStateReq.CANCEL_SHUTDOWN, 0));
        assertStateReceivedForShutdownOrSleepWithPostpone(
                PowerHalService.SET_SHUTDOWN_CANCELLED, WAIT_TIMEOUT_LONG_MS, 0);

        // Request suspend again
        mPowerHal.setCurrentPowerState(
                new PowerState(
                        VehicleApPowerStateReq.SHUTDOWN_PREPARE,
                        VehicleApPowerStateShutdownParam.CAN_SLEEP));
        // Verify suspend
        assertStateReceivedForShutdownOrSleepWithPostpone(
                PowerHalService.SET_DEEP_SLEEP_ENTRY, WAIT_TIMEOUT_LONG_MS, mWakeupTime);
        verifyWtfNeverLogged();
    }

    @Test
    public void testShutdownCancel() throws Exception {
        initTestForUser10();

        // Start in the ON state
        mPowerHal.setCurrentPowerState(new PowerState(VehicleApPowerStateReq.ON, 0));
        assertThat(mDisplayInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS)).isTrue();
        // Start shutting down
        mPowerHal.setCurrentPowerState(
                new PowerState(
                        VehicleApPowerStateReq.SHUTDOWN_PREPARE,
                        VehicleApPowerStateShutdownParam.SHUTDOWN_IMMEDIATELY));
        assertStateReceivedForShutdownOrSleepWithPostpone(
                PowerHalService.SET_SHUTDOWN_START, WAIT_TIMEOUT_LONG_MS, 0);
        // Cancel the shutdown
        mPowerHal.setCurrentPowerState(new PowerState(VehicleApPowerStateReq.CANCEL_SHUTDOWN, 0));
        assertStateReceivedForShutdownOrSleepWithPostpone(
                PowerHalService.SET_SHUTDOWN_CANCELLED, WAIT_TIMEOUT_LONG_MS, 0);
        // Go to suspend
        mPowerHal.setCurrentPowerState(
                new PowerState(
                        VehicleApPowerStateReq.SHUTDOWN_PREPARE,
                        VehicleApPowerStateShutdownParam.CAN_SLEEP));
        assertStateReceivedForShutdownOrSleepWithPostpone(
                PowerHalService.SET_DEEP_SLEEP_ENTRY, WAIT_TIMEOUT_LONG_MS, mWakeupTime);
        verifyWtfNeverLogged();
    }

    @Test
    public void testSleepImmediately() throws Exception {
        initTestForUser10();

        // Transition to ON state
        mPowerHal.setCurrentPowerState(new PowerState(VehicleApPowerStateReq.ON, 0));
        assertThat(mDisplayInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS)).isTrue();

        mPowerHal.setCurrentPowerState(
                new PowerState(
                        VehicleApPowerStateReq.SHUTDOWN_PREPARE,
                        VehicleApPowerStateShutdownParam.SLEEP_IMMEDIATELY));
        // Since modules have to manually schedule next wakeup, we should not schedule next wakeup
        // To test module behavior, we need to actually implement mock listener module.
        assertStateReceived(PowerHalService.SET_SHUTDOWN_START, 0);
        assertThat(mDisplayInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS)).isFalse();
        mPowerSignalListener.waitForShutdown(WAIT_TIMEOUT_MS);
        mSystemStateInterface.waitForShutdown(WAIT_TIMEOUT_MS);
        verifyWtfNeverLogged();
    }

    @Test
    @WakeupTime(100)
    @FlakyTest
    public void testShutdownWithProcessing() throws Exception {
        initTestForUser10();
        mPowerHal.setCurrentPowerState(new PowerState(VehicleApPowerStateReq.SHUTDOWN_PREPARE, 0));
        assertStateReceivedForShutdownOrSleepWithPostpone(
                PowerHalService.SET_SHUTDOWN_START, WAIT_TIMEOUT_LONG_MS, mWakeupTime);
        mPowerSignalListener.waitForShutdown(WAIT_TIMEOUT_MS);
        // Send the finished signal
        mPowerHal.setCurrentPowerState(new PowerState(VehicleApPowerStateReq.FINISHED, 0));
        mSystemStateInterface.waitForShutdown(WAIT_TIMEOUT_MS);
        verifyWtfNeverLogged();
    }

    @Test
    @WakeupTime(100)
    public void testSleepEntryAndWakeup() throws Exception {
        initTest();
        mPowerHal.setCurrentPowerState(new PowerState(VehicleApPowerStateReq.SHUTDOWN_PREPARE,
                VehicleApPowerStateShutdownParam.CAN_SLEEP));
        assertStateReceivedForShutdownOrSleepWithPostpone(
                PowerHalService.SET_DEEP_SLEEP_ENTRY, WAIT_TIMEOUT_LONG_MS, mWakeupTime);
        mPowerSignalListener.waitForSleepEntry(WAIT_TIMEOUT_MS);
        // Send the finished signal from HAL to CPMS
        mPowerHal.setCurrentPowerState(new PowerState(VehicleApPowerStateReq.FINISHED, 0));
        mSystemStateInterface.waitForSleepEntryAndWakeup(WAIT_TIMEOUT_MS);
        assertStateReceived(PowerHalService.SET_DEEP_SLEEP_EXIT, 0);
        mPowerSignalListener.waitForSleepExit(WAIT_TIMEOUT_MS);
        verifyWtfNeverLogged();
    }

    @Test
    @FlakyTest
    public void testUserSwitchingOnResume_differentUser() throws Exception {
        initTest();
        setUserInfo(10, NO_USER_INFO_FLAGS);
        setUserInfo(11, NO_USER_INFO_FLAGS);
        setCurrentUser(10);
        setInitialUser(11);

        suspendAndResumeForUserSwitchingTests();

        verifyUserSwitched(11);
        verifyWtfNeverLogged();
    }

    @Test
    public void testUserSwitchingOnResume_sameUser() throws Exception {
        initTest();
        setUserInfo(10, NO_USER_INFO_FLAGS);
        setInitialUser(10);
        setCurrentUser(10);

        suspendAndResumeForUserSwitchingTests();

        verifyUserNotSwitched();
        verifyWtfNeverLogged();
    }

    @Test
    public void testUserSwitchingOnResume_differentEphemeralUser() throws Exception {
        initTest();
        setUserInfo(10, NO_USER_INFO_FLAGS);
        setUserInfo(11, FLAG_EPHEMERAL);
        setCurrentUser(10);
        setInitialUser(11);

        suspendAndResumeForUserSwitchingTests();

        verifyUserSwitched(11);
        verifyWtfNeverLogged();
    }

    @Test
    public void testUserSwitchingOnResume_sameGuest() throws Exception {
        initTest();
        setUserInfo(10, "ElGuesto", USER_TYPE_FULL_GUEST, FLAG_EPHEMERAL);
        setInitialUser(10);
        setCurrentUser(10);
        expectGuestMarkedForDeletionOk(10);
        expectNewGuestCreated(11);

        suspendAndResumeForUserSwitchingTests();

        verifyUserRemoved(10);
        verifyUserSwitched(11);
        verifyWtfNeverLogged();
    }

    @Test
    public void testUserSwitchingOnResume_differentGuest() throws Exception {
        initTest();
        setUserInfo(11, "ElGuesto", USER_TYPE_FULL_GUEST, FLAG_EPHEMERAL);
        setInitialUser(11);
        setCurrentUser(10);
        expectGuestMarkedForDeletionOk(11);
        expectNewGuestCreated(12);

        suspendAndResumeForUserSwitchingTests();

        verifyUserRemoved(11);
        verifyUserSwitched(12);
        verifyWtfNeverLogged();
    }

    @Test
    public void testUserSwitchingOnResume_guestCreationFailed() throws Exception {
        initTest();
        setUserInfo(10, "ElGuesto", USER_TYPE_FULL_GUEST, FLAG_EPHEMERAL);
        setInitialUser(10);
        setCurrentUser(10);
        expectGuestMarkedForDeletionOk(10);
        expectNewGuestCreationFailed("ElGuesto");

        suspendAndResumeForUserSwitchingTests();

        verifyUserNotSwitched();
        verifyUserNotRemoved(10);
        // expects WTF
    }

    @Test
    public void testUserSwitchingOnResume_differentPersistentGuest() throws Exception {
        initTest();
        setUserInfo(11, "ElGuesto", USER_TYPE_FULL_GUEST, NO_USER_INFO_FLAGS);
        setInitialUser(11);
        setCurrentUser(10);
        expectGuestMarkedForDeletionOk(11);
        expectNewGuestCreated(12);

        suspendAndResumeForUserSwitchingTests();

        verifyUserRemoved(11);
        verifyUserSwitched(12);
        verifyWtfNeverLogged();
    }

    @Test
    public void testUserSwitchingOnResume_preDeleteGuestFail() throws Exception {
        initTest();
        setUserInfo(10, "ElGuesto", USER_TYPE_FULL_GUEST, FLAG_EPHEMERAL);
        setInitialUser(10);
        setCurrentUser(10);
        expectGuestMarkedForDeletionFail(10);

        suspendAndResumeForUserSwitchingTests();

        verifyUserNotSwitched();
        verifyNoGuestCreated();
        verifyWtfNeverLogged();
    }

    @Test
    public void testUserSwitchingOnResume_systemUser() throws Exception {
        initTest();
        setInitialUser(USER_SYSTEM);
        setCurrentUser(10);

        suspendAndResumeForUserSwitchingTests();

        verifyUserNotSwitched();
        // expects WTF
    }

    @Test
    public void testUserSwitchingOnResume_disabledByOEM_differentUser() throws Exception {
        disableUserSwitchingDuringResume();
        initTest();
        setUserInfo(10, NO_USER_INFO_FLAGS);
        setUserInfo(11, NO_USER_INFO_FLAGS);
        setCurrentUser(10);
        setInitialUser(11);

        suspendAndResumeForUserSwitchingTests();

        verifyUserNotSwitched();
        verifyWtfNeverLogged();
    }

    @Test
    public void testUserSwitchingOnResume_disabledByOEM_sameUser() throws Exception {
        disableUserSwitchingDuringResume();
        initTest();
        setUserInfo(10, NO_USER_INFO_FLAGS);
        setInitialUser(10);
        setCurrentUser(10);

        suspendAndResumeForUserSwitchingTests();

        verifyUserNotSwitched();
        verifyWtfNeverLogged();
    }

    @Test
    public void testUserSwitchingOnResume_disabledByOEM_differentEphemeralUser() throws Exception {
        disableUserSwitchingDuringResume();
        initTest();
        setUserInfo(10, NO_USER_INFO_FLAGS);
        setUserInfo(11, FLAG_EPHEMERAL);
        setCurrentUser(10);
        setInitialUser(11);

        suspendAndResumeForUserSwitchingTests();

        verifyUserNotSwitched();
        verifyWtfNeverLogged();
    }

    @Test
    public void testUserSwitchingOnResume_disabledByOEM_sameGuest() throws Exception {
        disableUserSwitchingDuringResume();
        initTest();
        setUserInfo(10, "ElGuesto", USER_TYPE_FULL_GUEST, FLAG_EPHEMERAL);
        setInitialUser(10);
        setCurrentUser(10);
        expectGuestMarkedForDeletionOk(10);
        expectNewGuestCreated(11);

        suspendAndResumeForUserSwitchingTests();

        verifyUserRemoved(10);
        verifyUserSwitched(11);
        verifyWtfNeverLogged();
    }

    @Test
    public void testUserSwitchingOnResume_disabledByOEM_differentGuest() throws Exception {
        disableUserSwitchingDuringResume();
        initTest();
        setUserInfo(11, "ElGuesto", USER_TYPE_FULL_GUEST, FLAG_EPHEMERAL);
        setInitialUser(11);
        setCurrentUser(10);
        expectGuestMarkedForDeletionOk(11);
        expectNewGuestCreated(12);

        suspendAndResumeForUserSwitchingTests();

        verifyUserRemoved(11);
        verifyUserSwitched(12);
        verifyWtfNeverLogged();
    }

    @Test
    public void testUserSwitchingOnResume_disabledByOEM_guestCreationFailed() throws Exception {
        disableUserSwitchingDuringResume();
        initTest();
        setUserInfo(10, "ElGuesto", USER_TYPE_FULL_GUEST, FLAG_EPHEMERAL);
        setInitialUser(10);
        setCurrentUser(10);
        expectGuestMarkedForDeletionOk(10);
        expectNewGuestCreationFailed("ElGuesto");

        suspendAndResumeForUserSwitchingTests();

        verifyUserNotSwitched();
        verifyUserNotRemoved(10);
        // expects WTF
    }

    @Test
    public void testUserSwitchingOnResume_disabledByOEM_differentPersistentGuest()
            throws Exception {
        disableUserSwitchingDuringResume();
        initTest();
        setUserInfo(11, "ElGuesto", USER_TYPE_FULL_GUEST, NO_USER_INFO_FLAGS);
        setInitialUser(11);
        setCurrentUser(10);
        expectGuestMarkedForDeletionOk(11);
        expectNewGuestCreated(12);

        suspendAndResumeForUserSwitchingTests();

        verifyUserRemoved(11);
        verifyUserSwitched(12);
        verifyWtfNeverLogged();
    }

    @Test
    public void testUserSwitchingOnResume_disabledByOEM_preDeleteGuestFail() throws Exception {
        disableUserSwitchingDuringResume();
        initTest();
        setUserInfo(10, "ElGuesto", USER_TYPE_FULL_GUEST, FLAG_EPHEMERAL);
        setInitialUser(10);
        setCurrentUser(10);
        expectGuestMarkedForDeletionFail(10);

        suspendAndResumeForUserSwitchingTests();

        verifyUserNotSwitched();
        verifyNoGuestCreated();
        verifyWtfNeverLogged();
    }

    @Test
    public void testUserSwitchingOnResume_disabledByOEM_systemUser() throws Exception {
        disableUserSwitchingDuringResume();
        initTest();
        setInitialUser(USER_SYSTEM);
        setCurrentUser(10);

        suspendAndResumeForUserSwitchingTests();

        verifyUserNotSwitched();
        // expects WTF
    }

    private void suspendAndResumeForUserSwitchingTests() throws Exception {
        Log.d(TAG, "suspend()");
        mPowerHal.setCurrentPowerState(new PowerState(VehicleApPowerStateReq.SHUTDOWN_PREPARE,
                VehicleApPowerStateShutdownParam.CAN_SLEEP));
        assertThat(mDisplayInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS)).isFalse();
        assertStateReceivedForShutdownOrSleepWithPostpone(
                PowerHalService.SET_DEEP_SLEEP_ENTRY, WAIT_TIMEOUT_LONG_MS, mWakeupTime);
        mPowerSignalListener.waitForSleepEntry(WAIT_TIMEOUT_MS);

        // Send the finished signal
        Log.d(TAG, "resume()");
        mPowerHal.setCurrentPowerState(new PowerState(VehicleApPowerStateReq.FINISHED, 0));
        mSystemStateInterface.setWakeupCausedByTimer(true);
        mSystemStateInterface.waitForSleepEntryAndWakeup(WAIT_TIMEOUT_MS);
        assertStateReceived(PowerHalService.SET_DEEP_SLEEP_EXIT, 0);
        mPowerSignalListener.waitForSleepExit(WAIT_TIMEOUT_MS);
        mService.scheduleNextWakeupTime(mWakeupTime);
        // second processing after wakeup
        assertThat(mDisplayInterface.getDisplayState()).isFalse();

        mService.setStateForTesting(/* isBooting= */ false, /* isResuming= */ true);

        mPowerHal.setCurrentPowerState(new PowerState(VehicleApPowerStateReq.ON, 0));
        assertThat(mDisplayInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS)).isTrue();
        // Should wait until Handler has finished ON processing.
        CarServiceUtils.runOnLooperSync(mService.getHandlerThread().getLooper(), () -> { });
        mPowerHal.setCurrentPowerState(new PowerState(VehicleApPowerStateReq.SHUTDOWN_PREPARE,
                VehicleApPowerStateShutdownParam.CAN_SLEEP));
        assertStateReceivedForShutdownOrSleepWithPostpone(
                PowerHalService.SET_DEEP_SLEEP_ENTRY, WAIT_TIMEOUT_LONG_MS, mWakeupTime);
        mPowerSignalListener.waitForSleepEntry(WAIT_TIMEOUT_MS);
        mPowerHal.setCurrentPowerState(new PowerState(VehicleApPowerStateReq.FINISHED, 0));
        // PM will shutdown system as it was not woken-up due timer and it is not power on.
        mSystemStateInterface.setWakeupCausedByTimer(false);
        mSystemStateInterface.waitForSleepEntryAndWakeup(WAIT_TIMEOUT_MS);
        // Since we just woke up from shutdown, wake up time will be 0
        assertStateReceived(PowerHalService.SET_DEEP_SLEEP_EXIT, 0);
        assertThat(mDisplayInterface.getDisplayState()).isFalse();
    }

    private void registerListenerToService() {
        ICarPowerStateListener listenerToService = new ICarPowerStateListener.Stub() {
            @Override
            public void onStateChanged(int state) throws RemoteException {
                if (state == CarPowerStateListener.SHUTDOWN_ENTER
                        || state == CarPowerStateListener.SUSPEND_ENTER) {
                    mFuture = new CompletableFuture<>();
                    mFuture.whenComplete((res, ex) -> {
                        if (ex == null) {
                            mService.finished(this);
                        }
                    });
                } else {
                    mFuture = null;
                }
            }
        };
        mService.registerListener(listenerToService);
    }

    private void assertStateReceived(int expectedState, int expectedParam) throws Exception {
        int[] state = mPowerHal.waitForSend(WAIT_TIMEOUT_MS);
        assertThat(state[0]).isEqualTo(expectedState);
        assertThat(state[1]).isEqualTo(expectedParam);
    }

    private void assertStateReceivedForShutdownOrSleepWithPostpone(
            int lastState, long timeoutMs, int expectedParamForShutdownOrSuspend) throws Exception {
        while (true) {
            if (mFuture != null && !mFuture.isDone()) {
                mFuture.complete(null);
            }
            int[] state = mPowerHal.waitForSend(timeoutMs);
            if (state[0] == PowerHalService.SET_SHUTDOWN_POSTPONE) {
                continue;
            }
            if (state[0] == lastState) {
                assertThat(state[1]).isEqualTo(expectedParamForShutdownOrSuspend);
                return;
            }
        }
    }

    // TODO: should be part of @After, but then it would hide the real test failure (if any). We'd
    // need a custom rule (like CTS's SafeCleaner) for it...
    private void verifyWtfNeverLogged() {
        int size = mWtfs.size();

        switch (size) {
            case 0:
                return;
            case 1:
                throw mWtfs.get(0);
            default:
                StringBuilder msg = new StringBuilder("wtf called ").append(size).append(" times")
                        .append(": ").append(mWtfs);
                fail(msg.toString());
        }
    }

    private static void waitForSemaphore(Semaphore semaphore, long timeoutMs)
            throws InterruptedException {
        if (!semaphore.tryAcquire(timeoutMs, TimeUnit.MILLISECONDS)) {
            throw new IllegalStateException("timeout");
        }
    }

    private void setInitialUser(int userId) {
        when(mCarUserManagerHelper.getInitialUser()).thenReturn(userId);
    }

    private void setCurrentUser(int userId) {
        when(ActivityManager.getCurrentUser()).thenReturn(userId);
    }

    private void setUserInfo(int userId, int flags) {
        setUserInfo(userId, /* name= */ null, /* userType= */ null, flags);
    }

    private void setUserInfo(int userId, @Nullable String name, @Nullable String userType,
            int flags) {
        final UserInfo userInfo = new UserInfo();
        userInfo.id = userId;
        userInfo.name = name;
        userInfo.flags = flags;
        if (userType != null) {
            userInfo.userType = userType;
        }
        Log.v(TAG, "UM.getUserInfo("  + userId + ") will return " + userInfo.toFullString());
        when(mUserManager.getUserInfo(userId)).thenReturn(userInfo);
    }

    private void verifyUserNotSwitched() {
        verify(mCarUserManagerHelper, never()).switchToUserId(anyInt());
    }

    private void verifyUserSwitched(int userId) {
        verify(mCarUserManagerHelper, times(1)).switchToUserId(userId);
    }

    private void verifyNoGuestCreated() {
        verify(mUserManager, never()).createGuest(notNull(), anyString());
    }

    private void expectGuestMarkedForDeletionOk(int userId) {
        when(mUserManager.markGuestForDeletion(userId)).thenReturn(true);
    }

    private void expectGuestMarkedForDeletionFail(int userId) {
        when(mUserManager.markGuestForDeletion(userId)).thenReturn(false);
    }

    private void expectNewGuestCreated(int userId) {
        final UserInfo userInfo = new UserInfo();
        userInfo.id = userId;
        userInfo.name = NEW_GUEST_NAME;
        when(mUserManager.createGuest(notNull(), eq(NEW_GUEST_NAME))).thenReturn(userInfo);
    }

    private void expectNewGuestCreationFailed(String name) {
        when(mUserManager.createGuest(notNull(), eq(name))).thenReturn(null);
    }

    private void verifyUserRemoved(int userId) {
        verify(mUserManager, times(1)).removeUser(userId);
    }

    private void verifyUserNotRemoved(int userId) {
        verify(mUserManager, never()).removeUser(userId);
    }

    private void disableUserSwitchingDuringResume() {
        mDisableUserSwitchDuringResume = true;
    }

    private static final class MockDisplayInterface implements DisplayInterface {
        private boolean mDisplayOn = true;
        private final Semaphore mDisplayStateWait = new Semaphore(0);

        @Override
        public void setDisplayBrightness(int brightness) {}

        @Override
        public synchronized void setDisplayState(boolean on) {
            mDisplayOn = on;
            mDisplayStateWait.release();
        }

        public synchronized boolean getDisplayState() {
            return mDisplayOn;
        }

        public boolean waitForDisplayStateChange(long timeoutMs) throws Exception {
            waitForSemaphore(mDisplayStateWait, timeoutMs);
            return mDisplayOn;
        }

        @Override
        public void startDisplayStateMonitoring(CarPowerManagementService service) {}

        @Override
        public void stopDisplayStateMonitoring() {}

        @Override
        public void refreshDisplayBrightness() {}
    }

    private static final class MockSystemStateInterface implements SystemStateInterface {
        private final Semaphore mShutdownWait = new Semaphore(0);
        private final Semaphore mSleepWait = new Semaphore(0);
        private final Semaphore mSleepExitWait = new Semaphore(0);
        private boolean mWakeupCausedByTimer = false;

        @Override
        public void shutdown() {
            mShutdownWait.release();
        }

        public void waitForShutdown(long timeoutMs) throws Exception {
            waitForSemaphore(mShutdownWait, timeoutMs);
        }

        @Override
        public boolean enterDeepSleep() {
            mSleepWait.release();
            try {
                mSleepExitWait.acquire();
            } catch (InterruptedException e) {
            }
            return true;
        }

        public void waitForSleepEntryAndWakeup(long timeoutMs) throws Exception {
            waitForSemaphore(mSleepWait, timeoutMs);
            mSleepExitWait.release();
        }

        @Override
        public void scheduleActionForBootCompleted(Runnable action, Duration delay) {}

        @Override
        public boolean isWakeupCausedByTimer() {
            Log.i(TAG, "isWakeupCausedByTimer:" + mWakeupCausedByTimer);
            return mWakeupCausedByTimer;
        }

        public synchronized void setWakeupCausedByTimer(boolean set) {
            mWakeupCausedByTimer = set;
        }

        @Override
        public boolean isSystemSupportingDeepSleep() {
            return true;
        }
    }

    private static final class MockWakeLockInterface implements WakeLockInterface {

        @Override
        public void releaseAllWakeLocks() {}

        @Override
        public void switchToPartialWakeLock() {}

        @Override
        public void switchToFullWakeLock() {}
    }

    private static final class MockIOInterface implements IOInterface {
        private TemporaryDirectory mFilesDir;

        @Override
        public File getSystemCarDir() {
            if (mFilesDir == null) {
                try {
                    mFilesDir = new TemporaryDirectory(TAG);
                } catch (IOException e) {
                    Log.e(TAG, "failed to create temporary directory", e);
                    fail("failed to create temporary directory. exception was: " + e);
                }
            }
            return mFilesDir.getDirectory();
        }

        public void tearDown() {
            if (mFilesDir != null) {
                try {
                    mFilesDir.close();
                } catch (Exception e) {
                    Log.w(TAG, "could not remove temporary directory", e);
                }
            }
        }
    }

    private class PowerSignalListener implements MockedPowerHalService.SignalListener {
        private final Semaphore mShutdownWait = new Semaphore(0);
        private final Semaphore mSleepEntryWait = new Semaphore(0);
        private final Semaphore mSleepExitWait = new Semaphore(0);

        public void waitForSleepExit(long timeoutMs) throws Exception {
            waitForSemaphore(mSleepExitWait, timeoutMs);
        }

        public void waitForShutdown(long timeoutMs) throws Exception {
            waitForSemaphore(mShutdownWait, timeoutMs);
        }

        public void waitForSleepEntry(long timeoutMs) throws Exception {
            waitForSemaphore(mSleepEntryWait, timeoutMs);
        }

        @Override
        public void sendingSignal(int signal) {
            if (signal == PowerHalService.SET_SHUTDOWN_START) {
                mShutdownWait.release();
                return;
            }
            if (signal == PowerHalService.SET_DEEP_SLEEP_ENTRY) {
                mSleepEntryWait.release();
                return;
            }
            if (signal == PowerHalService.SET_DEEP_SLEEP_EXIT) {
                mSleepExitWait.release();
                return;
            }
        }
    }

    @Retention(RUNTIME)
    @Target({METHOD})
    public static @interface WakeupTime {
        int value();
    }
}
