1/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16#define LOG_TAG "VehicleNetworkAudioHelperTest"
17
18#include <unistd.h>
19
20#include <gtest/gtest.h>
21#include <binder/IServiceManager.h>
22#include <binder/ProcessState.h>
23#include <utils/threads.h>
24#include <utils/KeyedVector.h>
25#include <utils/String8.h>
26#include <utils/SystemClock.h>
27#include <vehicle-internal.h>
28#include <VehicleNetwork.h>
29#include <VehicleNetworkAudioHelper.h>
30
31#include "TestProperties.h"
32#include "VehicleHalMock.h"
33#include "VehicleNetworkTestListener.h"
34
35namespace android {
36
37extern "C" {
38vehicle_prop_config_t const * getTestPropertiesForAudio();
39int getNumTestPropertiesForAudio();
40};
41
42class VehicleHalMockForAudioFocus : public VehicleHalMock {
43public:
44    VehicleHalMockForAudioFocus(sp<VehicleNetwork>& vn)
45        : mVN(vn) {
46        mAudioProperties = new VehiclePropertiesHolder(false /* deleteConfigsInDestructor */);
47        vehicle_prop_config_t const * properties = getTestPropertiesForAudio();
48        for (int i = 0; i < getNumTestPropertiesForAudio(); i++) {
49            mAudioProperties->getList().push_back(properties + i);
50        }
51        mValueToGet.prop = VEHICLE_PROPERTY_AUDIO_FOCUS;
52        mValueToGet.value_type = VEHICLE_VALUE_TYPE_INT32_VEC4;
53        mValueToGet.value.int32_array[0] = 0;
54        mValueToGet.value.int32_array[1] = 0;
55        mValueToGet.value.int32_array[2] = 0;
56        mValueToGet.value.int32_array[3] = 0;
57    }
58    virtual ~VehicleHalMockForAudioFocus() {};
59
60    virtual sp<VehiclePropertiesHolder> onListProperties() {
61        ALOGI("onListProperties");
62        Mutex::Autolock autoLock(mLock);
63        return mAudioProperties;
64    };
65
66    virtual status_t onPropertySet(const vehicle_prop_value_t& value) {
67        ALOGI("onPropertySet 0x%x", value.prop);
68        return NO_ERROR;
69    };
70
71    virtual status_t onPropertyGet(vehicle_prop_value_t* value) {
72        ALOGI("onPropertyGet 0x%x", value->prop);
73        Mutex::Autolock autoLock(mLock);
74        if (value->prop == VEHICLE_PROPERTY_AUDIO_FOCUS) {
75            memcpy(value, &mValueToGet, sizeof(vehicle_prop_value_t));
76        }
77        return NO_ERROR;
78    };
79
80    virtual status_t onPropertySubscribe(int32_t property, float /*sampleRate*/,
81            int32_t /*zones*/) {
82        ALOGI("onPropertySubscribe 0x%x", property);
83        return NO_ERROR;
84    };
85
86    virtual void onPropertyUnsubscribe(int32_t property) {
87        ALOGI("onPropertySubscribe 0x%x", property);
88    };
89
90    void setFocusState(int32_t state, int32_t streams, int32_t extState) {
91        Mutex::Autolock autoLock(mLock);
92        mValueToGet.value.int32_array[VEHICLE_AUDIO_FOCUS_INDEX_FOCUS] = state;
93        mValueToGet.value.int32_array[VEHICLE_AUDIO_FOCUS_INDEX_STREAMS] = streams;
94        mValueToGet.value.int32_array[VEHICLE_AUDIO_FOCUS_INDEX_EXTERNAL_FOCUS_STATE] = extState;
95        mValueToGet.value.int32_array[VEHICLE_AUDIO_FOCUS_INDEX_AUDIO_CONTEXTS] = 0;
96        mValueToGet.timestamp = elapsedRealtimeNano();
97        mVN->injectEvent(mValueToGet);
98    }
99
100    const vehicle_prop_value_t& getCurrentFocus() {
101        Mutex::Autolock autoLock(mLock);
102        return mValueToGet;
103    }
104
105private:
106    sp<VehicleNetwork> mVN;
107    mutable Mutex mLock;
108    sp<VehiclePropertiesHolder> mAudioProperties;
109    vehicle_prop_value_t mValueToGet;
110};
111
112class VehicleNetworkAudioHelperTest : public testing::Test {
113public:
114    VehicleNetworkAudioHelperTest() :
115        mHalMock(NULL),
116        mVN(NULL),
117        mListener(new VehicleNetworkTestListener()) { }
118
119    ~VehicleNetworkAudioHelperTest() {}
120
121    const nsecs_t WAIT_NS = 100000000;
122
123protected:
124    virtual void SetUp() {
125        ASSERT_TRUE(mListener.get() != NULL);
126        sp<VehicleNetworkListener> listener(mListener.get());
127        mVN = VehicleNetwork::createVehicleNetwork(listener);
128        ASSERT_TRUE(mVN.get() != NULL);
129        mHalMock = new VehicleHalMockForAudioFocus(mVN);
130        sp<VehicleHalMock> halMock = mHalMock;
131        mVN->startMocking(halMock);
132        mAudioHelper = new VehicleNetworkAudioHelper();
133        ASSERT_EQ(NO_ERROR, mAudioHelper->init());
134    }
135
136    virtual void TearDown() {
137        mAudioHelper->release();
138        sp<VehicleHalMock> halMock = mHalMock;
139        mVN->stopMocking(halMock);
140    }
141
142    void changeFocusState(int32_t state, int32_t streams, int32_t extState) {
143        mHalMock->setFocusState(state, streams, extState);
144        mVN->injectEvent(mHalMock->getCurrentFocus());
145    }
146
147protected:
148    sp<VehicleHalMockForAudioFocus> mHalMock;
149    sp<VehicleNetwork> mVN;
150    sp<VehicleNetworkTestListener> mListener;
151    sp<VehicleNetworkAudioHelper> mAudioHelper;
152};
153
154TEST_F(VehicleNetworkAudioHelperTest, streamStartStop) {
155    ASSERT_EQ(NO_ERROR, mVN->subscribe(VEHICLE_PROPERTY_INTERNAL_AUDIO_STREAM_STATE, 0));
156    int initialCount = mListener->getEventCount(VEHICLE_PROPERTY_INTERNAL_AUDIO_STREAM_STATE);
157    mAudioHelper->notifyStreamStarted(VEHICLE_NETWORK_AUDIO_HELPER_STREAM_0);
158    ASSERT_TRUE(mListener->waitForEvent(VEHICLE_PROPERTY_INTERNAL_AUDIO_STREAM_STATE, initialCount,
159            WAIT_NS));
160    const vehicle_prop_value& lastValue = mListener->getLastValue();
161    ASSERT_EQ(VEHICLE_AUDIO_STREAM_STATE_STARTED,
162            lastValue.value.int32_array[VEHICLE_AUDIO_STREAM_STATE_INDEX_STATE]);
163    ASSERT_EQ(0, lastValue.value.int32_array[VEHICLE_AUDIO_STREAM_STATE_INDEX_STREAM]);
164
165    initialCount = mListener->getEventCount(VEHICLE_PROPERTY_INTERNAL_AUDIO_STREAM_STATE);
166    mAudioHelper->notifyStreamStarted(VEHICLE_NETWORK_AUDIO_HELPER_STREAM_1);
167    ASSERT_TRUE(mListener->waitForEvent(VEHICLE_PROPERTY_INTERNAL_AUDIO_STREAM_STATE, initialCount,
168            WAIT_NS));
169    const vehicle_prop_value& lastValue1 = mListener->getLastValue();
170    ASSERT_EQ(VEHICLE_AUDIO_STREAM_STATE_STARTED,
171            lastValue1.value.int32_array[VEHICLE_AUDIO_STREAM_STATE_INDEX_STATE]);
172    ASSERT_EQ(1, lastValue1.value.int32_array[VEHICLE_AUDIO_STREAM_STATE_INDEX_STREAM]);
173
174    initialCount = mListener->getEventCount(VEHICLE_PROPERTY_INTERNAL_AUDIO_STREAM_STATE);
175    mAudioHelper->notifyStreamStopped(VEHICLE_NETWORK_AUDIO_HELPER_STREAM_0);
176    ASSERT_TRUE(mListener->waitForEvent(VEHICLE_PROPERTY_INTERNAL_AUDIO_STREAM_STATE, initialCount,
177            WAIT_NS));
178    const vehicle_prop_value& lastValue2 = mListener->getLastValue();
179    ASSERT_EQ(VEHICLE_AUDIO_STREAM_STATE_STOPPED,
180            lastValue2.value.int32_array[VEHICLE_AUDIO_STREAM_STATE_INDEX_STATE]);
181    ASSERT_EQ(0, lastValue2.value.int32_array[VEHICLE_AUDIO_STREAM_STATE_INDEX_STREAM]);
182}
183
184TEST_F(VehicleNetworkAudioHelperTest, testFocus) {
185    ASSERT_EQ(VEHICLE_NETWORK_AUDIO_HELPER_FOCUS_STATE_NO_FOCUS,
186            mAudioHelper->getStreamFocusState(VEHICLE_NETWORK_AUDIO_HELPER_STREAM_0));
187    ASSERT_EQ(VEHICLE_NETWORK_AUDIO_HELPER_FOCUS_STATE_NO_FOCUS,
188            mAudioHelper->getStreamFocusState(VEHICLE_NETWORK_AUDIO_HELPER_STREAM_1));
189    mHalMock->setFocusState(VEHICLE_AUDIO_FOCUS_REQUEST_GAIN, 0x1, 0);
190    // should wait for event first. Otherwise polling will fail as change is not delivered yet.
191    ASSERT_TRUE(mAudioHelper->waitForStreamFocus(VEHICLE_NETWORK_AUDIO_HELPER_STREAM_0,
192            WAIT_NS));
193    ASSERT_FALSE(mAudioHelper->waitForStreamFocus(VEHICLE_NETWORK_AUDIO_HELPER_STREAM_1,
194            WAIT_NS));
195    ASSERT_EQ(VEHICLE_NETWORK_AUDIO_HELPER_FOCUS_STATE_FOCUS,
196            mAudioHelper->getStreamFocusState(VEHICLE_NETWORK_AUDIO_HELPER_STREAM_0));
197    ASSERT_EQ(VEHICLE_NETWORK_AUDIO_HELPER_FOCUS_STATE_NO_FOCUS,
198            mAudioHelper->getStreamFocusState(VEHICLE_NETWORK_AUDIO_HELPER_STREAM_1));
199    mHalMock->setFocusState(VEHICLE_AUDIO_FOCUS_REQUEST_GAIN, 0x3, 0);
200    ASSERT_TRUE(mAudioHelper->waitForStreamFocus(VEHICLE_NETWORK_AUDIO_HELPER_STREAM_0,
201            WAIT_NS));
202    ASSERT_TRUE(mAudioHelper->waitForStreamFocus(VEHICLE_NETWORK_AUDIO_HELPER_STREAM_1,
203            WAIT_NS));
204    ASSERT_EQ(VEHICLE_NETWORK_AUDIO_HELPER_FOCUS_STATE_FOCUS,
205            mAudioHelper->getStreamFocusState(VEHICLE_NETWORK_AUDIO_HELPER_STREAM_0));
206    ASSERT_EQ(VEHICLE_NETWORK_AUDIO_HELPER_FOCUS_STATE_FOCUS,
207            mAudioHelper->getStreamFocusState(VEHICLE_NETWORK_AUDIO_HELPER_STREAM_1));
208}
209
210}; // namespace android
211