• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 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 
17 // Unit tests for AAudio Marshalling of RingBuffer information.
18 
19 #include <stdlib.h>
20 #include <math.h>
21 
22 #include <android-base/unique_fd.h>
23 #include <binder/Parcel.h>
24 #include <binder/Parcelable.h>
25 #include <cutils/ashmem.h>
26 #include <gtest/gtest.h>
27 #include <sys/mman.h>
28 
29 #include <aaudio/AAudio.h>
30 #include <binding/AudioEndpointParcelable.h>
31 
32 using android::base::unique_fd;
33 using namespace android;
34 using namespace aaudio;
35 
36 template<typename T>
copy(const T & object)37 T copy(const T& object) {
38     return T(object);
39 }
40 
41 template<>
copy(const SharedMemoryParcelable & object)42 SharedMemoryParcelable copy<SharedMemoryParcelable>(const SharedMemoryParcelable& object) {
43     return object.dup();
44 }
45 
46 template<typename T>
writeToParcel(const T & object,Parcel * parcel)47 void writeToParcel(const T& object, Parcel* parcel) {
48     copy(object).parcelable().writeToParcel(parcel);
49 }
50 
51 template<typename T>
readFromParcel(const Parcel & parcel)52 T readFromParcel(const Parcel& parcel) {
53     using ParcelType = std::decay_t<decltype(std::declval<T>().parcelable())>;
54     ParcelType parcelable;
55     parcelable.readFromParcel(&parcel);
56     return T(std::move(parcelable));
57 }
58 
59 // Test adding one value.
TEST(test_marshalling,aaudio_one_read_write)60 TEST(test_marshalling, aaudio_one_read_write) {
61     Parcel parcel;
62     size_t pos = parcel.dataPosition();
63     const int arbitraryValue = 235;
64     parcel.writeInt32(arbitraryValue);
65     parcel.setDataPosition(pos);
66     int32_t y;
67     parcel.readInt32(&y);
68     EXPECT_EQ(arbitraryValue, y);
69 }
70 
71 // Test SharedMemoryParcel.
TEST(test_marshalling,aaudio_shared_memory)72 TEST(test_marshalling, aaudio_shared_memory) {
73     SharedMemoryParcelable sharedMemoryA;
74     const size_t memSizeBytes = 840;
75     unique_fd fd(ashmem_create_region("TestMarshalling", memSizeBytes));
76     ASSERT_LE(0, fd);
77     sharedMemoryA.setup(fd, memSizeBytes);
78     void *region1;
79     EXPECT_EQ(AAUDIO_OK, sharedMemoryA.resolve(0, 16, &region1)); // fits in region
80     EXPECT_NE(AAUDIO_OK, sharedMemoryA.resolve(-2, 16, &region1)); // offset is negative
81     EXPECT_NE(AAUDIO_OK, sharedMemoryA.resolve(0, memSizeBytes + 8, &region1)); // size too big
82     EXPECT_NE(AAUDIO_OK, sharedMemoryA.resolve(memSizeBytes - 8, 16, &region1)); // goes past the end
83     int32_t *buffer1 = (int32_t *)region1;
84     buffer1[0] = 98735; // arbitrary value
85 
86     Parcel parcel;
87     size_t pos = parcel.dataPosition();
88     writeToParcel(sharedMemoryA, &parcel);
89 
90     parcel.setDataPosition(pos);
91     SharedMemoryParcelable sharedMemoryB = readFromParcel<SharedMemoryParcelable>(parcel);
92     EXPECT_EQ(sharedMemoryA.getSizeInBytes(), sharedMemoryB.getSizeInBytes());
93 
94     // should see same value at two different addresses
95     void *region2;
96     EXPECT_EQ(AAUDIO_OK, sharedMemoryB.resolve(0, 16, &region2));
97     int32_t *buffer2 = (int32_t *)region2;
98     EXPECT_NE(buffer1, buffer2);
99     EXPECT_EQ(buffer1[0], buffer2[0]);
100 }
101 
102 // Test SharedRegionParcel.
TEST(test_marshalling,aaudio_shared_region)103 TEST(test_marshalling, aaudio_shared_region) {
104     SharedMemoryParcelable sharedMemories[2];
105     SharedRegionParcelable sharedRegionA;
106     const size_t memSizeBytes = 840;
107     unique_fd fd(ashmem_create_region("TestMarshalling", memSizeBytes));
108     ASSERT_LE(0, fd);
109     sharedMemories[0].setup(fd, memSizeBytes);
110     int32_t regionOffset1 = 32;
111     int32_t regionSize1 = 16;
112     sharedRegionA.setup(0, regionOffset1, regionSize1);
113 
114     void *region1;
115     EXPECT_EQ(AAUDIO_OK, sharedRegionA.resolve(sharedMemories, &region1));
116     int32_t *buffer1 = (int32_t *)region1;
117     buffer1[0] = 336677; // arbitrary value
118 
119     Parcel parcel;
120     size_t pos = parcel.dataPosition();
121     writeToParcel(sharedRegionA, &parcel);
122 
123     parcel.setDataPosition(pos);
124     SharedRegionParcelable sharedRegionB = readFromParcel<SharedRegionParcelable>(parcel);
125 
126     // should see same value
127     void *region2;
128     EXPECT_EQ(AAUDIO_OK, sharedRegionB.resolve(sharedMemories, &region2));
129     int32_t *buffer2 = (int32_t *)region2;
130     EXPECT_EQ(buffer1[0], buffer2[0]);
131 }
132 
133 // Test RingBufferParcelable.
TEST(test_marshalling,aaudio_ring_buffer_parcelable)134 TEST(test_marshalling, aaudio_ring_buffer_parcelable) {
135     SharedMemoryParcelable sharedMemories[2];
136     RingBufferParcelable ringBufferA;
137 
138     const size_t bytesPerFrame = 8;
139     const size_t framesPerBurst = 32;
140     const size_t dataSizeBytes = 2048;
141     const int32_t counterSizeBytes = sizeof(int64_t);
142     const size_t memSizeBytes = dataSizeBytes + (2 * counterSizeBytes);
143 
144     unique_fd fd(ashmem_create_region("TestMarshalling Z", memSizeBytes));
145     ASSERT_LE(0, fd);
146     sharedMemories[0].setup(fd, memSizeBytes);
147 
148     int32_t sharedMemoryIndex = 0;
149     // arrange indices and data in the shared memory
150     int32_t readOffset = 0;
151     int32_t writeOffset = readOffset + counterSizeBytes;
152     int32_t dataOffset = writeOffset + counterSizeBytes;
153     ringBufferA.setupMemory(sharedMemoryIndex, dataOffset, dataSizeBytes,
154         readOffset, writeOffset, counterSizeBytes);
155     ringBufferA.setFramesPerBurst(framesPerBurst);
156     ringBufferA.setBytesPerFrame(bytesPerFrame);
157     ringBufferA.setCapacityInFrames(dataSizeBytes / bytesPerFrame);
158 
159     // setup A
160     RingBufferDescriptor descriptorA;
161     EXPECT_EQ(AAUDIO_OK, ringBufferA.resolve(sharedMemories, &descriptorA));
162     descriptorA.dataAddress[0] = 95;
163     descriptorA.dataAddress[1] = 57;
164     descriptorA.readCounterAddress[0] = 17;
165     descriptorA.writeCounterAddress[0] = 39;
166 
167     // write A to parcel
168     Parcel parcel;
169     size_t pos = parcel.dataPosition();
170     writeToParcel(ringBufferA, &parcel);
171 
172     // read B from parcel
173     parcel.setDataPosition(pos);
174     RingBufferParcelable ringBufferB = readFromParcel<RingBufferParcelable>(parcel);
175 
176     RingBufferDescriptor descriptorB;
177     EXPECT_EQ(AAUDIO_OK, ringBufferB.resolve(sharedMemories, &descriptorB));
178 
179     // A and B should match
180     EXPECT_EQ(descriptorA.dataAddress[0], descriptorB.dataAddress[0]);
181     EXPECT_EQ(descriptorA.dataAddress[1], descriptorB.dataAddress[1]);
182     EXPECT_EQ(descriptorA.readCounterAddress[0], descriptorB.readCounterAddress[0]);
183     EXPECT_EQ(descriptorA.writeCounterAddress[0], descriptorB.writeCounterAddress[0]);
184 
185     EXPECT_EQ(ringBufferA.getFramesPerBurst(), ringBufferB.getFramesPerBurst());
186     EXPECT_EQ(ringBufferA.getBytesPerFrame(), ringBufferB.getBytesPerFrame());
187     EXPECT_EQ(ringBufferA.getCapacityInFrames(), ringBufferB.getCapacityInFrames());
188 }
189