/*
 * Copyright (C) 2020 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.hal;

import static android.car.VehiclePropertyIds.CURRENT_GEAR;
import static android.car.VehiclePropertyIds.INITIAL_USER_INFO;
import static android.car.VehiclePropertyIds.SWITCH_USER;
import static android.car.VehiclePropertyIds.USER_IDENTIFICATION_ASSOCIATION;
import static android.car.test.mocks.CarArgumentMatchers.isProperty;
import static android.car.test.mocks.CarArgumentMatchers.isPropertyWithValues;
import static android.car.test.util.VehicleHalTestingHelper.newConfig;
import static android.car.test.util.VehicleHalTestingHelper.newSubscribableConfig;
import static android.hardware.automotive.vehicle.V2_0.InitialUserInfoRequestType.COLD_BOOT;
import static android.hardware.automotive.vehicle.V2_0.UserIdentificationAssociationType.CUSTOM_1;
import static android.hardware.automotive.vehicle.V2_0.UserIdentificationAssociationType.KEY_FOB;
import static android.hardware.automotive.vehicle.V2_0.UserIdentificationAssociationValue.ASSOCIATED_CURRENT_USER;

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

import static org.junit.Assert.fail;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.testng.Assert.assertThrows;

import android.car.hardware.property.VehicleHalStatusCode;
import android.car.userlib.HalCallback;
import android.car.userlib.UserHalHelper;
import android.hardware.automotive.vehicle.V2_0.InitialUserInfoResponse;
import android.hardware.automotive.vehicle.V2_0.InitialUserInfoResponseAction;
import android.hardware.automotive.vehicle.V2_0.SwitchUserMessageType;
import android.hardware.automotive.vehicle.V2_0.SwitchUserResponse;
import android.hardware.automotive.vehicle.V2_0.SwitchUserStatus;
import android.hardware.automotive.vehicle.V2_0.UserFlags;
import android.hardware.automotive.vehicle.V2_0.UserIdentificationAssociation;
import android.hardware.automotive.vehicle.V2_0.UserIdentificationGetRequest;
import android.hardware.automotive.vehicle.V2_0.UserIdentificationResponse;
import android.hardware.automotive.vehicle.V2_0.UserInfo;
import android.hardware.automotive.vehicle.V2_0.UsersInfo;
import android.hardware.automotive.vehicle.V2_0.VehiclePropConfig;
import android.hardware.automotive.vehicle.V2_0.VehiclePropValue;
import android.os.ServiceSpecificException;
import android.os.SystemClock;
import android.os.UserHandle;
import android.util.Log;
import android.util.Pair;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;

@RunWith(MockitoJUnitRunner.class)
public final class UserHalServiceTest {

    private static final String TAG = UserHalServiceTest.class.getSimpleName();

    /**
     * Timeout passed to {@link UserHalService} methods
     */
    private static final int TIMEOUT_MS = 50;

    /**
     * Timeout for {@link GenericHalCallback#assertCalled()} for tests where the HAL is supposed to
     * return something - it's a short time so it doesn't impact the test duration.
     */
    private static final int CALLBACK_TIMEOUT_SUCCESS = TIMEOUT_MS + 50;

    /**
     * Timeout for {@link GenericHalCallback#assertCalled()} for tests where the HAL is not supposed
     * to return anything - it's a slightly longer to make sure the test doesn't fail prematurely.
     */
    private static final int CALLBACK_TIMEOUT_TIMEOUT = TIMEOUT_MS + 450;

    // Used when crafting a request property - the real value will be set by the mock.
    private static final int REQUEST_ID_PLACE_HOLDER = 42;

    private static final int INITIAL_USER_INFO_RESPONSE_ACTION = 108;

    @Mock
    private VehicleHal mVehicleHal;

    private final UserInfo mUser0 = new UserInfo();
    private final UserInfo mUser10 = new UserInfo();

    private final UsersInfo mUsersInfo = new UsersInfo();

    private UserHalService mUserHalService;

    @Before
    public void setFixtures() {
        mUserHalService = new UserHalService(mVehicleHal);
        mUserHalService.takeProperties(Arrays.asList(
                newSubscribableConfig(INITIAL_USER_INFO),
                newSubscribableConfig(SWITCH_USER)));

        mUser0.userId = 0;
        mUser0.flags = 100;
        mUser10.userId = 10;
        mUser10.flags = 110;

        mUsersInfo.currentUser = mUser0;
        mUsersInfo.numberUsers = 2;
        mUsersInfo.existingUsers = new ArrayList<>(2);
        mUsersInfo.existingUsers.add(mUser0);
        mUsersInfo.existingUsers.add(mUser10);
    }

    @Test
    public void testTakeSupportedProperties_unsupportedOnly() {
        // Cannot use mUserHalService because it's already set with supported properties
        UserHalService myHalService = new UserHalService(mVehicleHal);

        myHalService.takeProperties(Collections.EMPTY_LIST);
        assertThat(myHalService.isSupported()).isFalse();
    }

    @Test
    public void testTakeSupportedPropertiesAndInit() {
        // Cannot use mUserHalService because it's already set with supported properties
        UserHalService myHalService = new UserHalService(mVehicleHal);

        VehiclePropConfig unsupportedConfig = newConfig(CURRENT_GEAR);
        VehiclePropConfig userInfoConfig = newSubscribableConfig(INITIAL_USER_INFO);
        List<VehiclePropConfig> input = Arrays.asList(unsupportedConfig, userInfoConfig);
        myHalService.takeProperties(input);
        assertThat(mUserHalService.isSupported()).isTrue();

        // Ideally there should be 2 test methods (one for takeSupportedProperties() and one for
        // init()), but on "real life" VehicleHal calls these 2 methods in sequence, and the latter
        // depends on the properties set by the former, so it's ok to test both here...
        myHalService.init();
        verify(mVehicleHal).subscribeProperty(myHalService, INITIAL_USER_INFO);
    }

    @Test
    public void testSupportedProperties() {
        assertThat(mUserHalService.getAllSupportedProperties()).asList().containsAllOf(
                INITIAL_USER_INFO,
                SWITCH_USER,
                USER_IDENTIFICATION_ASSOCIATION);
    }

    @Test
    public void testGetUserInfo_invalidTimeout() {
        assertThrows(IllegalArgumentException.class,
                () -> mUserHalService.getInitialUserInfo(COLD_BOOT, 0, mUsersInfo, (i, r) -> {
                }));
        assertThrows(IllegalArgumentException.class,
                () -> mUserHalService.getInitialUserInfo(COLD_BOOT, -1, mUsersInfo, (i, r) -> {
                }));
    }

    @Test
    public void testGetUserInfo_noUsersInfo() {
        assertThrows(NullPointerException.class,
                () -> mUserHalService.getInitialUserInfo(COLD_BOOT, TIMEOUT_MS, null,
                        (i, r) -> {
                        }));
    }

    @Test
    public void testGetUserInfo_noCallback() {
        assertThrows(NullPointerException.class,
                () -> mUserHalService.getInitialUserInfo(COLD_BOOT, TIMEOUT_MS,
                        mUsersInfo, null));
    }

    @Test
    public void testGetUserInfo_halSetTimedOut() throws Exception {
        replySetPropertyWithTimeoutException(INITIAL_USER_INFO);

        GenericHalCallback<InitialUserInfoResponse> callback = new GenericHalCallback<>(
                CALLBACK_TIMEOUT_TIMEOUT);
        mUserHalService.getInitialUserInfo(COLD_BOOT, TIMEOUT_MS, mUsersInfo,
                callback);

        callback.assertCalled();
        assertCallbackStatus(callback, HalCallback.STATUS_HAL_SET_TIMEOUT);
        assertThat(callback.response).isNull();

        // Make sure the pending request was removed
        SystemClock.sleep(CALLBACK_TIMEOUT_TIMEOUT);
        callback.assertNotCalledAgain();
    }

    @Test
    public void testGetUserInfo_halDidNotReply() throws Exception {
        GenericHalCallback<InitialUserInfoResponse> callback = new GenericHalCallback<>(
                CALLBACK_TIMEOUT_TIMEOUT);
        mUserHalService.getInitialUserInfo(COLD_BOOT, TIMEOUT_MS, mUsersInfo,
                callback);

        callback.assertCalled();
        assertCallbackStatus(callback, HalCallback.STATUS_HAL_RESPONSE_TIMEOUT);
        assertThat(callback.response).isNull();
    }

    @Test
    public void testGetUserInfo_secondCallFailWhilePending() throws Exception {
        GenericHalCallback<InitialUserInfoResponse> callback1 = new GenericHalCallback<>(
                CALLBACK_TIMEOUT_TIMEOUT);
        GenericHalCallback<InitialUserInfoResponse> callback2 = new GenericHalCallback<>(
                CALLBACK_TIMEOUT_TIMEOUT);
        mUserHalService.getInitialUserInfo(COLD_BOOT, TIMEOUT_MS, mUsersInfo,
                callback1);
        mUserHalService.getInitialUserInfo(COLD_BOOT, TIMEOUT_MS, mUsersInfo,
                callback2);

        callback1.assertCalled();
        assertCallbackStatus(callback1, HalCallback.STATUS_HAL_RESPONSE_TIMEOUT);
        assertThat(callback1.response).isNull();

        callback2.assertCalled();
        assertCallbackStatus(callback2, HalCallback.STATUS_CONCURRENT_OPERATION);
        assertThat(callback1.response).isNull();
    }

    @Test
    public void testGetUserInfo_halReplyWithWrongRequestId() throws Exception {
        VehiclePropValue propResponse = UserHalHelper.createPropRequest(REQUEST_ID_PLACE_HOLDER,
                    INITIAL_USER_INFO_RESPONSE_ACTION, INITIAL_USER_INFO);

        replySetPropertyWithOnChangeEvent(INITIAL_USER_INFO, propResponse,
                /* rightRequestId= */ false);

        GenericHalCallback<InitialUserInfoResponse> callback = new GenericHalCallback<>(
                CALLBACK_TIMEOUT_TIMEOUT);
        mUserHalService.getInitialUserInfo(COLD_BOOT, TIMEOUT_MS, mUsersInfo,
                callback);

        callback.assertCalled();
        assertCallbackStatus(callback, HalCallback.STATUS_HAL_RESPONSE_TIMEOUT);
        assertThat(callback.response).isNull();
    }

    @Test
    public void testGetUserInfo_halReturnedInvalidAction() throws Exception {
        VehiclePropValue propResponse = UserHalHelper.createPropRequest(REQUEST_ID_PLACE_HOLDER,
                    INITIAL_USER_INFO_RESPONSE_ACTION, INITIAL_USER_INFO);

        AtomicReference<VehiclePropValue> reqCaptor = replySetPropertyWithOnChangeEvent(
                INITIAL_USER_INFO, propResponse, /* rightRequestId= */ true);

        GenericHalCallback<InitialUserInfoResponse> callback = new GenericHalCallback<>(
                CALLBACK_TIMEOUT_SUCCESS);
        mUserHalService.getInitialUserInfo(COLD_BOOT, TIMEOUT_MS, mUsersInfo,
                callback);

        callback.assertCalled();

        // Make sure the arguments were properly converted
        assertInitialUserInfoSetRequest(reqCaptor.get(), COLD_BOOT);

        // Assert response
        assertCallbackStatus(callback, HalCallback.STATUS_WRONG_HAL_RESPONSE);
        assertThat(callback.response).isNull();
    }

    @Test
    public void testGetUserInfo_successDefault() throws Exception {
        VehiclePropValue propResponse = UserHalHelper.createPropRequest(REQUEST_ID_PLACE_HOLDER,
                    InitialUserInfoResponseAction.DEFAULT, INITIAL_USER_INFO);

        AtomicReference<VehiclePropValue> reqCaptor = replySetPropertyWithOnChangeEvent(
                INITIAL_USER_INFO, propResponse, /* rightRequestId= */ true);

        GenericHalCallback<InitialUserInfoResponse> callback = new GenericHalCallback<>(
                CALLBACK_TIMEOUT_SUCCESS);
        mUserHalService.getInitialUserInfo(COLD_BOOT, TIMEOUT_MS, mUsersInfo,
                callback);

        callback.assertCalled();

        // Make sure the arguments were properly converted
        assertInitialUserInfoSetRequest(reqCaptor.get(), COLD_BOOT);

        // Assert response
        assertCallbackStatus(callback, HalCallback.STATUS_OK);
        InitialUserInfoResponse actualResponse = callback.response;
        assertThat(actualResponse.action).isEqualTo(InitialUserInfoResponseAction.DEFAULT);
        assertThat(actualResponse.userNameToCreate).isEmpty();
        assertThat(actualResponse.userToSwitchOrCreate).isNotNull();
        assertThat(actualResponse.userToSwitchOrCreate.userId).isEqualTo(UserHandle.USER_NULL);
        assertThat(actualResponse.userToSwitchOrCreate.flags).isEqualTo(UserFlags.NONE);
    }

    @Test
    public void testGetUserInfo_successSwitchUser() throws Exception {
        int userIdToSwitch = 42;
        VehiclePropValue propResponse = UserHalHelper.createPropRequest(REQUEST_ID_PLACE_HOLDER,
                    InitialUserInfoResponseAction.SWITCH, INITIAL_USER_INFO);
        propResponse.value.int32Values.add(userIdToSwitch);

        AtomicReference<VehiclePropValue> reqCaptor = replySetPropertyWithOnChangeEvent(
                INITIAL_USER_INFO, propResponse, /* rightRequestId= */ true);

        GenericHalCallback<InitialUserInfoResponse> callback = new GenericHalCallback<>(
                CALLBACK_TIMEOUT_SUCCESS);
        mUserHalService.getInitialUserInfo(COLD_BOOT, TIMEOUT_MS, mUsersInfo,
                callback);

        callback.assertCalled();

        // Make sure the arguments were properly converted
        assertInitialUserInfoSetRequest(reqCaptor.get(), COLD_BOOT);

        assertCallbackStatus(callback, HalCallback.STATUS_OK);
        InitialUserInfoResponse actualResponse = callback.response;
        assertThat(actualResponse.action).isEqualTo(InitialUserInfoResponseAction.SWITCH);
        assertThat(actualResponse.userNameToCreate).isEmpty();
        UserInfo userToSwitch = actualResponse.userToSwitchOrCreate;
        assertThat(userToSwitch).isNotNull();
        assertThat(userToSwitch.userId).isEqualTo(userIdToSwitch);
        assertThat(userToSwitch.flags).isEqualTo(UserFlags.NONE);
    }

    @Test
    public void testGetUserInfo_successCreateUser() throws Exception {
        int newUserFlags = 108;
        String newUserName = "Groot";
        VehiclePropValue propResponse = UserHalHelper.createPropRequest(REQUEST_ID_PLACE_HOLDER,
                    InitialUserInfoResponseAction.CREATE, INITIAL_USER_INFO);
        propResponse.value.int32Values.add(newUserFlags);
        propResponse.value.stringValue = newUserName;

        AtomicReference<VehiclePropValue> reqCaptor = replySetPropertyWithOnChangeEvent(
                INITIAL_USER_INFO, propResponse, /* rightRequestId= */ true);

        GenericHalCallback<InitialUserInfoResponse> callback = new GenericHalCallback<>(
                CALLBACK_TIMEOUT_SUCCESS);
        mUserHalService.getInitialUserInfo(COLD_BOOT, TIMEOUT_MS, mUsersInfo,
                callback);

        callback.assertCalled();

        // Make sure the arguments were properly converted
        assertInitialUserInfoSetRequest(reqCaptor.get(), COLD_BOOT);

        assertCallbackStatus(callback, HalCallback.STATUS_OK);
        assertThat(callback.status).isEqualTo(HalCallback.STATUS_OK);
        InitialUserInfoResponse actualResponse = callback.response;
        assertThat(actualResponse.action).isEqualTo(InitialUserInfoResponseAction.CREATE);
        assertThat(actualResponse.userNameToCreate).isEqualTo(newUserName);
        UserInfo newUser = actualResponse.userToSwitchOrCreate;
        assertThat(newUser).isNotNull();
        assertThat(newUser.userId).isEqualTo(UserHandle.USER_NULL);
        assertThat(newUser.flags).isEqualTo(newUserFlags);
    }

    @Test
    public void testGetUserInfo_twoSuccessfulCalls() throws Exception {
        testGetUserInfo_successDefault();
        testGetUserInfo_successDefault();
    }

    @Test
    public void testSwitchUser_invalidTimeout() {
        assertThrows(IllegalArgumentException.class,
                () -> mUserHalService.switchUser(mUser10, 0, mUsersInfo, (i, r) -> {
                }));
        assertThrows(IllegalArgumentException.class,
                () -> mUserHalService.switchUser(mUser10, -1, mUsersInfo, (i, r) -> {
                }));
    }

    @Test
    public void testSwitchUser_noUsersInfo() {
        assertThrows(NullPointerException.class,
                () -> mUserHalService.switchUser(mUser10, TIMEOUT_MS, null,
                        (i, r) -> {
                        }));
    }

    @Test
    public void testSwitchUser_noCallback() {
        assertThrows(NullPointerException.class,
                () -> mUserHalService.switchUser(mUser10, TIMEOUT_MS,
                        mUsersInfo, null));
    }

    @Test
    public void testSwitchUser_halSetTimedOut() throws Exception {
        replySetPropertyWithTimeoutException(SWITCH_USER);

        GenericHalCallback<SwitchUserResponse> callback = new GenericHalCallback<>(
                CALLBACK_TIMEOUT_TIMEOUT);
        mUserHalService.switchUser(mUser10, TIMEOUT_MS, mUsersInfo, callback);

        callback.assertCalled();
        assertCallbackStatus(callback, HalCallback.STATUS_HAL_SET_TIMEOUT);
        assertThat(callback.response).isNull();

        // Make sure the pending request was removed
        SystemClock.sleep(CALLBACK_TIMEOUT_TIMEOUT);
        callback.assertNotCalledAgain();
    }

    @Test
    public void testSwitchUser_halDidNotReply() throws Exception {
        GenericHalCallback<SwitchUserResponse> callback = new GenericHalCallback<>(
                CALLBACK_TIMEOUT_TIMEOUT);
        mUserHalService.switchUser(mUser10, TIMEOUT_MS, mUsersInfo, callback);

        callback.assertCalled();
        assertCallbackStatus(callback, HalCallback.STATUS_HAL_RESPONSE_TIMEOUT);
        assertThat(callback.response).isNull();
    }

    @Test
    public void testSwitchUser_halReplyWithWrongRequestId() throws Exception {
        VehiclePropValue propResponse = UserHalHelper.createPropRequest(REQUEST_ID_PLACE_HOLDER,
                    InitialUserInfoResponseAction.SWITCH, SWITCH_USER);

        replySetPropertyWithOnChangeEvent(SWITCH_USER, propResponse,
                /* rightRequestId= */ false);

        GenericHalCallback<SwitchUserResponse> callback = new GenericHalCallback<>(
                CALLBACK_TIMEOUT_TIMEOUT);
        mUserHalService.switchUser(mUser10, TIMEOUT_MS, mUsersInfo, callback);

        callback.assertCalled();
        assertCallbackStatus(callback, HalCallback.STATUS_HAL_RESPONSE_TIMEOUT);
        assertThat(callback.response).isNull();
    }

    @Test
    public void testSwitchUser_halReturnedInvalidMessageType() throws Exception {
        VehiclePropValue propResponse = UserHalHelper.createPropRequest(REQUEST_ID_PLACE_HOLDER,
                    SwitchUserMessageType.VEHICLE_REQUEST, SWITCH_USER);
        propResponse.value.int32Values.add(SwitchUserStatus.SUCCESS);

        AtomicReference<VehiclePropValue> reqCaptor = replySetPropertyWithOnChangeEvent(
                SWITCH_USER, propResponse, /* rightRequestId= */ true);

        GenericHalCallback<SwitchUserResponse> callback = new GenericHalCallback<>(
                CALLBACK_TIMEOUT_SUCCESS);
        mUserHalService.switchUser(mUser10, TIMEOUT_MS, mUsersInfo, callback);

        callback.assertCalled();

        // Make sure the arguments were properly converted
        assertSwitchUserSetRequest(reqCaptor.get(), SwitchUserMessageType.ANDROID_SWITCH, mUser10);

        // Assert response
        assertCallbackStatus(callback, HalCallback.STATUS_WRONG_HAL_RESPONSE);
        assertThat(callback.response).isNull();
    }

    @Test
    public void testUserSwitch_success() throws Exception {
        VehiclePropValue propResponse = UserHalHelper.createPropRequest(REQUEST_ID_PLACE_HOLDER,
                    SwitchUserMessageType.VEHICLE_RESPONSE, SWITCH_USER);
        propResponse.value.int32Values.add(SwitchUserStatus.SUCCESS);

        AtomicReference<VehiclePropValue> reqCaptor = replySetPropertyWithOnChangeEvent(
                SWITCH_USER, propResponse, /* rightRequestId= */ true);

        GenericHalCallback<SwitchUserResponse> callback = new GenericHalCallback<>(
                CALLBACK_TIMEOUT_SUCCESS);
        mUserHalService.switchUser(mUser10, TIMEOUT_MS, mUsersInfo, callback);

        callback.assertCalled();

        // Make sure the arguments were properly converted
        assertSwitchUserSetRequest(reqCaptor.get(), SwitchUserMessageType.ANDROID_SWITCH, mUser10);

        // Assert response
        assertCallbackStatus(callback, HalCallback.STATUS_OK);
        SwitchUserResponse actualResponse = callback.response;
        assertThat(actualResponse.status).isEqualTo(SwitchUserStatus.SUCCESS);
        assertThat(actualResponse.messageType).isEqualTo(SwitchUserMessageType.VEHICLE_RESPONSE);
    }

    @Test
    public void testUserSwitch_failure() throws Exception {
        VehiclePropValue propResponse = UserHalHelper.createPropRequest(REQUEST_ID_PLACE_HOLDER,
                    SwitchUserMessageType.VEHICLE_RESPONSE, SWITCH_USER);
        propResponse.value.int32Values.add(SwitchUserStatus.FAILURE);

        AtomicReference<VehiclePropValue> reqCaptor = replySetPropertyWithOnChangeEvent(
                SWITCH_USER, propResponse, /* rightRequestId= */ true);

        GenericHalCallback<SwitchUserResponse> callback = new GenericHalCallback<>(
                CALLBACK_TIMEOUT_SUCCESS);
        mUserHalService.switchUser(mUser10, TIMEOUT_MS, mUsersInfo, callback);

        callback.assertCalled();

        // Make sure the arguments were properly converted
        assertSwitchUserSetRequest(reqCaptor.get(), SwitchUserMessageType.ANDROID_SWITCH, mUser10);

        // Assert response
        assertCallbackStatus(callback, HalCallback.STATUS_OK);
        SwitchUserResponse actualResponse = callback.response;
        assertThat(actualResponse.status).isEqualTo(SwitchUserStatus.FAILURE);
        assertThat(actualResponse.messageType).isEqualTo(SwitchUserMessageType.VEHICLE_RESPONSE);
    }

    @Test
    public void testSwitchUser_secondCallFailWhilePending() throws Exception {
        GenericHalCallback<SwitchUserResponse> callback1 = new GenericHalCallback<>(
                CALLBACK_TIMEOUT_TIMEOUT);
        GenericHalCallback<SwitchUserResponse> callback2 = new GenericHalCallback<>(
                CALLBACK_TIMEOUT_TIMEOUT);
        mUserHalService.switchUser(mUser10, TIMEOUT_MS, mUsersInfo, callback1);
        mUserHalService.switchUser(mUser10, TIMEOUT_MS, mUsersInfo, callback2);

        callback1.assertCalled();
        assertCallbackStatus(callback1, HalCallback.STATUS_HAL_RESPONSE_TIMEOUT);
        assertThat(callback1.response).isNull();

        callback2.assertCalled();
        assertCallbackStatus(callback2, HalCallback.STATUS_CONCURRENT_OPERATION);
        assertThat(callback1.response).isNull();
    }

    @Test
    public void testSwitchUser_halReturnedInvalidStatus() throws Exception {
        VehiclePropValue propResponse = UserHalHelper.createPropRequest(REQUEST_ID_PLACE_HOLDER,
                    SwitchUserMessageType.VEHICLE_RESPONSE, SWITCH_USER);
        propResponse.value.int32Values.add(/*status =*/ 110); // an invalid status

        AtomicReference<VehiclePropValue> reqCaptor = replySetPropertyWithOnChangeEvent(
                SWITCH_USER, propResponse, /* rightRequestId= */ true);

        GenericHalCallback<SwitchUserResponse> callback = new GenericHalCallback<>(
                CALLBACK_TIMEOUT_SUCCESS);
        mUserHalService.switchUser(mUser10, TIMEOUT_MS, mUsersInfo, callback);

        callback.assertCalled();

        // Make sure the arguments were properly converted
        assertSwitchUserSetRequest(reqCaptor.get(), SwitchUserMessageType.ANDROID_SWITCH, mUser10);

        // Assert response
        assertCallbackStatus(callback, HalCallback.STATUS_WRONG_HAL_RESPONSE);
        assertThat(callback.response).isNull();
    }

    @Test
    public void testPostSwitchResponse_noUsersInfo() {
        assertThrows(NullPointerException.class,
                () -> mUserHalService.postSwitchResponse(42, mUser10, null));
    }

    @Test
    public void testPostSwitchResponse_HalCalledWithCorrectProp() {
        mUserHalService.postSwitchResponse(42, mUser10, mUsersInfo);
        ArgumentCaptor<VehiclePropValue> propCaptor =
                ArgumentCaptor.forClass(VehiclePropValue.class);
        verify(mVehicleHal).set(propCaptor.capture());
        VehiclePropValue prop = propCaptor.getValue();
        assertPostSwitchResponseSetRequest(prop, SwitchUserMessageType.ANDROID_POST_SWITCH,
                mUser10);
    }

    @Test
    public void testGetUserAssociation_nullRequest() {
        assertThrows(NullPointerException.class, () -> mUserHalService.getUserAssociation(null));
    }

    @Test
    public void testGetUserAssociation_requestWithDuplicatedTypes() {
        UserIdentificationGetRequest request = new UserIdentificationGetRequest();
        request.numberAssociationTypes = 2;
        request.associationTypes.add(KEY_FOB);
        request.associationTypes.add(KEY_FOB);

        assertThrows(IllegalArgumentException.class,
                () -> mUserHalService.getUserAssociation(request));
    }

    @Test
    public void testGetUserAssociation_invalidResponse() {
        VehiclePropValue mockedResponse = new VehiclePropValue();
        mockedResponse.prop = USER_IDENTIFICATION_ASSOCIATION;
        mockedResponse.value.int32Values.add(1); // 1 associations
        mockedResponse.value.int32Values.add(KEY_FOB); // type only, it's missing value
        when(mVehicleHal.get(
                isPropertyWithValues(USER_IDENTIFICATION_ASSOCIATION, 42, 108, 1, KEY_FOB)))
                        .thenReturn(mockedResponse);

        UserIdentificationGetRequest request = new UserIdentificationGetRequest();
        request.userInfo.userId = 42;
        request.userInfo.flags = 108;
        request.numberAssociationTypes = 1;
        request.associationTypes.add(KEY_FOB);

        assertThat(mUserHalService.getUserAssociation(request)).isNull();
    }

    @Test
    public void testGetUserAssociation_nullResponse() {
        VehiclePropValue mockedResponse = new VehiclePropValue();
        mockedResponse.prop = USER_IDENTIFICATION_ASSOCIATION;
        mockedResponse.value.int32Values.add(1); // 1 association
        mockedResponse.value.int32Values.add(KEY_FOB);
        mockedResponse.value.int32Values.add(ASSOCIATED_CURRENT_USER);
        when(mVehicleHal.get(
                isPropertyWithValues(USER_IDENTIFICATION_ASSOCIATION, 42, 108, 1, KEY_FOB)))
                        .thenReturn(null);

        UserIdentificationGetRequest request = new UserIdentificationGetRequest();
        request.userInfo.userId = 42;
        request.userInfo.flags = 108;
        request.numberAssociationTypes = 1;
        request.associationTypes.add(KEY_FOB);

        assertThat(mUserHalService.getUserAssociation(request)).isNull();
    }

    @Test
    public void testGetUserAssociation_wrongNumberOfAssociationsOnResponse() {
        VehiclePropValue mockedResponse = new VehiclePropValue();
        mockedResponse.prop = USER_IDENTIFICATION_ASSOCIATION;
        mockedResponse.value.int32Values.add(2); // 2 associations
        mockedResponse.value.int32Values.add(KEY_FOB);
        mockedResponse.value.int32Values.add(ASSOCIATED_CURRENT_USER);
        mockedResponse.value.int32Values.add(CUSTOM_1);
        mockedResponse.value.int32Values.add(ASSOCIATED_CURRENT_USER);
        when(mVehicleHal.get(
                isPropertyWithValues(USER_IDENTIFICATION_ASSOCIATION, 42, 108, 1, KEY_FOB)))
                        .thenReturn(mockedResponse);

        UserIdentificationGetRequest request = new UserIdentificationGetRequest();
        request.userInfo.userId = 42;
        request.userInfo.flags = 108;
        request.numberAssociationTypes = 1;
        request.associationTypes.add(KEY_FOB);

        assertThat(mUserHalService.getUserAssociation(request)).isNull();
    }

    @Test
    public void testGetUserAssociation_typesOnResponseMismatchTypesOnRequest() {
        VehiclePropValue mockedResponse = new VehiclePropValue();
        mockedResponse.prop = USER_IDENTIFICATION_ASSOCIATION;
        mockedResponse.value.int32Values.add(1);
        mockedResponse.value.int32Values.add(CUSTOM_1);
        mockedResponse.value.int32Values.add(ASSOCIATED_CURRENT_USER);
        when(mVehicleHal.get(
                isPropertyWithValues(USER_IDENTIFICATION_ASSOCIATION, 42, 108, 1, KEY_FOB)))
                        .thenReturn(mockedResponse);

        UserIdentificationGetRequest request = new UserIdentificationGetRequest();
        request.userInfo.userId = 42;
        request.userInfo.flags = 108;
        request.numberAssociationTypes = 1;
        request.associationTypes.add(KEY_FOB);

        assertThat(mUserHalService.getUserAssociation(request)).isNull();
    }

    @Test
    public void testGetUserAssociation_ok() {
        VehiclePropValue mockedResponse = new VehiclePropValue();
        mockedResponse.prop = USER_IDENTIFICATION_ASSOCIATION;
        mockedResponse.value.int32Values.add(1); // 1 association
        mockedResponse.value.int32Values.add(KEY_FOB);
        mockedResponse.value.int32Values.add(ASSOCIATED_CURRENT_USER);
        when(mVehicleHal.get(
                isPropertyWithValues(USER_IDENTIFICATION_ASSOCIATION, 42, 108, 1, KEY_FOB)))
                        .thenReturn(mockedResponse);

        UserIdentificationGetRequest request = new UserIdentificationGetRequest();
        request.userInfo.userId = 42;
        request.userInfo.flags = 108;
        request.numberAssociationTypes = 1;
        request.associationTypes.add(KEY_FOB);

        UserIdentificationResponse actualResponse = mUserHalService.getUserAssociation(request);

        assertThat(actualResponse.numberAssociation).isEqualTo(1);
        assertThat(actualResponse.associations).hasSize(1);
        UserIdentificationAssociation actualAssociation = actualResponse.associations.get(0);
        assertThat(actualAssociation.type).isEqualTo(KEY_FOB);
        assertThat(actualAssociation.value).isEqualTo(ASSOCIATED_CURRENT_USER);
    }

    /**
     * Asserts the given {@link UsersInfo} is properly represented in the {@link VehiclePropValue}.
     *
     * @param value property containing the info
     * @param info info to be checked
     * @param initialIndex first index of the info values in the property's {@code int32Values}
     */
    private void assertUsersInfo(VehiclePropValue value, UsersInfo info, int initialIndex) {
        // TODO: consider using UserHalHelper to convert the property into a specific request,
        // and compare the request's UsersInfo.
        // But such method is not needed in production code yet.
        ArrayList<Integer> values = value.value.int32Values;
        assertWithMessage("wrong values size").that(values)
                .hasSize(initialIndex + 3 + info.numberUsers * 2);

        int i = initialIndex;
        assertWithMessage("currentUser.id mismatch at index %s", i).that(values.get(i))
                .isEqualTo(info.currentUser.userId);
        i++;
        assertWithMessage("currentUser.flags mismatch at index %s", i).that(values.get(i))
            .isEqualTo(info.currentUser.flags);
        i++;
        assertWithMessage("numberUsers mismatch at index %s", i).that(values.get(i))
            .isEqualTo(info.numberUsers);
        i++;

        for (int j = 0; j < info.numberUsers; j++) {
            int actualUserId = values.get(i++);
            int actualUserFlags = values.get(i++);
            UserInfo expectedUser = info.existingUsers.get(j);
            assertWithMessage("wrong id for existing user#%s at index %s", j, i)
                .that(actualUserId).isEqualTo(expectedUser.userId);
            assertWithMessage("wrong flags for existing user#%s at index %s", j, i)
                .that(actualUserFlags).isEqualTo(expectedUser.flags);
        }
    }

    /**
     * Sets the VHAL mock to emulate a property change event upon a call to set a property.
     *
     * @param prop prop to be set
     * @param response response to be set on event
     * @param rightRequestId whether the response id should match the request
     * @return
     *
     * @return reference to the value passed to {@code set()}.
     */
    private AtomicReference<VehiclePropValue> replySetPropertyWithOnChangeEvent(int prop,
            VehiclePropValue response, boolean rightRequestId) throws Exception {
        AtomicReference<VehiclePropValue> ref = new AtomicReference<>();
        doAnswer((inv) -> {
            VehiclePropValue request = inv.getArgument(0);
            ref.set(request);
            int requestId = request.value.int32Values.get(0);
            int responseId = rightRequestId ? requestId : requestId + 1000;
            response.value.int32Values.set(0, responseId);
            Log.d(TAG, "mockSetPropertyWithOnChange(): resp=" + response + " for req=" + request);
            mUserHalService.onHalEvents(Arrays.asList(response));
            return null;
        }).when(mVehicleHal).set(isProperty(prop));
        return ref;
    }

    /**
     * Sets the VHAL mock to emulate a property timeout exception upon a call to set a property.
     */
    private void replySetPropertyWithTimeoutException(int prop) throws Exception {
        doThrow(new ServiceSpecificException(VehicleHalStatusCode.STATUS_TRY_AGAIN,
                "PropId: 0x" + Integer.toHexString(prop))).when(mVehicleHal).set(isProperty(prop));
    }

    private void assertInitialUserInfoSetRequest(VehiclePropValue req, int requestType) {
        assertThat(req.value.int32Values.get(1)).isEqualTo(requestType);
        assertUsersInfo(req, mUsersInfo, 2);
    }

    private void assertSwitchUserSetRequest(VehiclePropValue req, int messageType,
            UserInfo targetUserInfo) {
        assertThat(req.value.int32Values.get(1)).isEqualTo(messageType);
        assertWithMessage("targetuser.id mismatch").that(req.value.int32Values.get(2))
                .isEqualTo(targetUserInfo.userId);
        assertWithMessage("targetuser.flags mismatch").that(req.value.int32Values.get(3))
                .isEqualTo(targetUserInfo.flags);
        assertUsersInfo(req, mUsersInfo, 4);
    }

    private void assertPostSwitchResponseSetRequest(VehiclePropValue req, int messageType,
            UserInfo targetUserInfo) {
        assertThat(req.value.int32Values.get(1)).isEqualTo(messageType);
        assertWithMessage("targetuser.id mismatch").that(req.value.int32Values.get(2))
                .isEqualTo(targetUserInfo.userId);
        assertWithMessage("targetuser.flags mismatch").that(req.value.int32Values.get(3))
                .isEqualTo(targetUserInfo.flags);
        assertUsersInfo(req, mUsersInfo, 4);
    }

    private void assertCallbackStatus(GenericHalCallback callback,
            int expectedStatus) {
        int actualStatus = callback.status;
        if (actualStatus == expectedStatus) return;

        fail("Wrong callback status; expected "
                + UserHalHelper.halCallbackStatusToString(expectedStatus) + ", got "
                + UserHalHelper.halCallbackStatusToString(actualStatus));
    }

    private final class GenericHalCallback<R> implements HalCallback<R> {

        private final CountDownLatch mLatch = new CountDownLatch(1);
        private final int mTimeout;
        private final List<Pair<Integer, R>> mExtraCalls = new ArrayList<>();

        public int status;
        public R response;

        GenericHalCallback(int timeout) {
            this.mTimeout = timeout;
        }

        @Override
        public void onResponse(int status, R response) {
            Log.d(TAG, "onResponse(): status=" + status + ", response=" +  response);
            this.status = status;
            this.response = response;
            if (mLatch.getCount() == 0) {
                Log.e(TAG, "Already responded");
                mExtraCalls.add(new Pair<>(status, response));
                return;
            }
            mLatch.countDown();
        }

        /**
         * Asserts that the callback was called, or fail if it timed out.
         */
        public void assertCalled() throws InterruptedException {
            Log.d(TAG, "assertCalled(): waiting " + mTimeout + "ms");
            if (!mLatch.await(mTimeout, TimeUnit.MILLISECONDS)) {
                throw new AssertionError("callback not called in " + mTimeout + "ms");
            }
        }

        /**
         * Asserts that the callback was not called more than once.
         */
        public void assertNotCalledAgain() {
            if (mExtraCalls.isEmpty()) return;
            throw new AssertionError("Called " + mExtraCalls.size() + " times more than expected: "
                    + mExtraCalls);
        }
    }
}
