/*
* Copyright (C) 2015 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.
*/
#define LOG_TAG "VehicleNetworkAudioHelperTest"
#include <unistd.h>
#include <gtest/gtest.h>
#include <binder/IServiceManager.h>
#include <binder/ProcessState.h>
#include <utils/threads.h>
#include <utils/KeyedVector.h>
#include <utils/String8.h>
#include <utils/SystemClock.h>
#include <vehicle-internal.h>
#include <VehicleNetwork.h>
#include <VehicleNetworkAudioHelper.h>
#include "TestProperties.h"
#include "VehicleHalMock.h"
#include "VehicleNetworkTestListener.h"
namespace android {
extern "C" {
vehicle_prop_config_t const * getTestPropertiesForAudio();
int getNumTestPropertiesForAudio();
};
class VehicleHalMockForAudioFocus : public VehicleHalMock {
public:
VehicleHalMockForAudioFocus(sp<VehicleNetwork>& vn)
: mVN(vn) {
mAudioProperties = new VehiclePropertiesHolder(false /* deleteConfigsInDestructor */);
vehicle_prop_config_t const * properties = getTestPropertiesForAudio();
for (int i = 0; i < getNumTestPropertiesForAudio(); i++) {
mAudioProperties->getList().push_back(properties + i);
}
mValueToGet.prop = VEHICLE_PROPERTY_AUDIO_FOCUS;
mValueToGet.value_type = VEHICLE_VALUE_TYPE_INT32_VEC4;
mValueToGet.value.int32_array[0] = 0;
mValueToGet.value.int32_array[1] = 0;
mValueToGet.value.int32_array[2] = 0;
mValueToGet.value.int32_array[3] = 0;
}
virtual ~VehicleHalMockForAudioFocus() {};
virtual sp<VehiclePropertiesHolder> onListProperties() {
ALOGI("onListProperties");
Mutex::Autolock autoLock(mLock);
return mAudioProperties;
};
virtual status_t onPropertySet(const vehicle_prop_value_t& value) {
ALOGI("onPropertySet 0x%x", value.prop);
return NO_ERROR;
};
virtual status_t onPropertyGet(vehicle_prop_value_t* value) {
ALOGI("onPropertyGet 0x%x", value->prop);
Mutex::Autolock autoLock(mLock);
if (value->prop == VEHICLE_PROPERTY_AUDIO_FOCUS) {
memcpy(value, &mValueToGet, sizeof(vehicle_prop_value_t));
}
return NO_ERROR;
};
virtual status_t onPropertySubscribe(int32_t property, float /*sampleRate*/,
int32_t /*zones*/) {
ALOGI("onPropertySubscribe 0x%x", property);
return NO_ERROR;
};
virtual void onPropertyUnsubscribe(int32_t property) {
ALOGI("onPropertySubscribe 0x%x", property);
};
void setFocusState(int32_t state, int32_t streams, int32_t extState) {
Mutex::Autolock autoLock(mLock);
mValueToGet.value.int32_array[VEHICLE_AUDIO_FOCUS_INDEX_FOCUS] = state;
mValueToGet.value.int32_array[VEHICLE_AUDIO_FOCUS_INDEX_STREAMS] = streams;
mValueToGet.value.int32_array[VEHICLE_AUDIO_FOCUS_INDEX_EXTERNAL_FOCUS_STATE] = extState;
mValueToGet.value.int32_array[VEHICLE_AUDIO_FOCUS_INDEX_AUDIO_CONTEXTS] = 0;
mValueToGet.timestamp = elapsedRealtimeNano();
mVN->injectEvent(mValueToGet);
}
const vehicle_prop_value_t& getCurrentFocus() {
Mutex::Autolock autoLock(mLock);
return mValueToGet;
}
private:
sp<VehicleNetwork> mVN;
mutable Mutex mLock;
sp<VehiclePropertiesHolder> mAudioProperties;
vehicle_prop_value_t mValueToGet;
};
class VehicleNetworkAudioHelperTest : public testing::Test {
public:
VehicleNetworkAudioHelperTest() :
mHalMock(NULL),
mVN(NULL),
mListener(new VehicleNetworkTestListener()) { }
~VehicleNetworkAudioHelperTest() {}
const nsecs_t WAIT_NS = 100000000;
protected:
virtual void SetUp() {
ASSERT_TRUE(mListener.get() != NULL);
sp<VehicleNetworkListener> listener(mListener.get());
mVN = VehicleNetwork::createVehicleNetwork(listener);
ASSERT_TRUE(mVN.get() != NULL);
mHalMock = new VehicleHalMockForAudioFocus(mVN);
sp<VehicleHalMock> halMock = mHalMock;
mVN->startMocking(halMock);
mAudioHelper = new VehicleNetworkAudioHelper();
ASSERT_EQ(NO_ERROR, mAudioHelper->init());
}
virtual void TearDown() {
mAudioHelper->release();
sp<VehicleHalMock> halMock = mHalMock;
mVN->stopMocking(halMock);
}
void changeFocusState(int32_t state, int32_t streams, int32_t extState) {
mHalMock->setFocusState(state, streams, extState);
mVN->injectEvent(mHalMock->getCurrentFocus());
}
protected:
sp<VehicleHalMockForAudioFocus> mHalMock;
sp<VehicleNetwork> mVN;
sp<VehicleNetworkTestListener> mListener;
sp<VehicleNetworkAudioHelper> mAudioHelper;
};
TEST_F(VehicleNetworkAudioHelperTest, streamStartStop) {
ASSERT_EQ(NO_ERROR, mVN->subscribe(VEHICLE_PROPERTY_INTERNAL_AUDIO_STREAM_STATE, 0));
int initialCount = mListener->getEventCount(VEHICLE_PROPERTY_INTERNAL_AUDIO_STREAM_STATE);
mAudioHelper->notifyStreamStarted(VEHICLE_NETWORK_AUDIO_HELPER_STREAM_0);
ASSERT_TRUE(mListener->waitForEvent(VEHICLE_PROPERTY_INTERNAL_AUDIO_STREAM_STATE, initialCount,
WAIT_NS));
const vehicle_prop_value& lastValue = mListener->getLastValue();
ASSERT_EQ(VEHICLE_AUDIO_STREAM_STATE_STARTED,
lastValue.value.int32_array[VEHICLE_AUDIO_STREAM_STATE_INDEX_STATE]);
ASSERT_EQ(0, lastValue.value.int32_array[VEHICLE_AUDIO_STREAM_STATE_INDEX_STREAM]);
initialCount = mListener->getEventCount(VEHICLE_PROPERTY_INTERNAL_AUDIO_STREAM_STATE);
mAudioHelper->notifyStreamStarted(VEHICLE_NETWORK_AUDIO_HELPER_STREAM_1);
ASSERT_TRUE(mListener->waitForEvent(VEHICLE_PROPERTY_INTERNAL_AUDIO_STREAM_STATE, initialCount,
WAIT_NS));
const vehicle_prop_value& lastValue1 = mListener->getLastValue();
ASSERT_EQ(VEHICLE_AUDIO_STREAM_STATE_STARTED,
lastValue1.value.int32_array[VEHICLE_AUDIO_STREAM_STATE_INDEX_STATE]);
ASSERT_EQ(1, lastValue1.value.int32_array[VEHICLE_AUDIO_STREAM_STATE_INDEX_STREAM]);
initialCount = mListener->getEventCount(VEHICLE_PROPERTY_INTERNAL_AUDIO_STREAM_STATE);
mAudioHelper->notifyStreamStopped(VEHICLE_NETWORK_AUDIO_HELPER_STREAM_0);
ASSERT_TRUE(mListener->waitForEvent(VEHICLE_PROPERTY_INTERNAL_AUDIO_STREAM_STATE, initialCount,
WAIT_NS));
const vehicle_prop_value& lastValue2 = mListener->getLastValue();
ASSERT_EQ(VEHICLE_AUDIO_STREAM_STATE_STOPPED,
lastValue2.value.int32_array[VEHICLE_AUDIO_STREAM_STATE_INDEX_STATE]);
ASSERT_EQ(0, lastValue2.value.int32_array[VEHICLE_AUDIO_STREAM_STATE_INDEX_STREAM]);
}
TEST_F(VehicleNetworkAudioHelperTest, testFocus) {
ASSERT_EQ(VEHICLE_NETWORK_AUDIO_HELPER_FOCUS_STATE_NO_FOCUS,
mAudioHelper->getStreamFocusState(VEHICLE_NETWORK_AUDIO_HELPER_STREAM_0));
ASSERT_EQ(VEHICLE_NETWORK_AUDIO_HELPER_FOCUS_STATE_NO_FOCUS,
mAudioHelper->getStreamFocusState(VEHICLE_NETWORK_AUDIO_HELPER_STREAM_1));
mHalMock->setFocusState(VEHICLE_AUDIO_FOCUS_REQUEST_GAIN, 0x1, 0);
// should wait for event first. Otherwise polling will fail as change is not delivered yet.
ASSERT_TRUE(mAudioHelper->waitForStreamFocus(VEHICLE_NETWORK_AUDIO_HELPER_STREAM_0,
WAIT_NS));
ASSERT_FALSE(mAudioHelper->waitForStreamFocus(VEHICLE_NETWORK_AUDIO_HELPER_STREAM_1,
WAIT_NS));
ASSERT_EQ(VEHICLE_NETWORK_AUDIO_HELPER_FOCUS_STATE_FOCUS,
mAudioHelper->getStreamFocusState(VEHICLE_NETWORK_AUDIO_HELPER_STREAM_0));
ASSERT_EQ(VEHICLE_NETWORK_AUDIO_HELPER_FOCUS_STATE_NO_FOCUS,
mAudioHelper->getStreamFocusState(VEHICLE_NETWORK_AUDIO_HELPER_STREAM_1));
mHalMock->setFocusState(VEHICLE_AUDIO_FOCUS_REQUEST_GAIN, 0x3, 0);
ASSERT_TRUE(mAudioHelper->waitForStreamFocus(VEHICLE_NETWORK_AUDIO_HELPER_STREAM_0,
WAIT_NS));
ASSERT_TRUE(mAudioHelper->waitForStreamFocus(VEHICLE_NETWORK_AUDIO_HELPER_STREAM_1,
WAIT_NS));
ASSERT_EQ(VEHICLE_NETWORK_AUDIO_HELPER_FOCUS_STATE_FOCUS,
mAudioHelper->getStreamFocusState(VEHICLE_NETWORK_AUDIO_HELPER_STREAM_0));
ASSERT_EQ(VEHICLE_NETWORK_AUDIO_HELPER_FOCUS_STATE_FOCUS,
mAudioHelper->getStreamFocusState(VEHICLE_NETWORK_AUDIO_HELPER_STREAM_1));
}
}; // namespace android