1#!/usr/bin/env python 2# 3# Copyright (C) 2018 The Android Open Source Project 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16# 17 18import logging 19import random 20 21from vts.runners.host import asserts 22from vts.runners.host import base_test 23from vts.runners.host import const 24from vts.runners.host import test_runner 25from vts.proto import ComponentSpecificationMessage_pb2 as CompSpecMsg 26 27 28class VtsCodelabHidlMemoryTest(base_test.BaseTestClass): 29 """Test hidl_memory APIs from host side to target side and HAL server. 30 31 This class tests APIs to operate on memory object from host side. 32 It also tests sending memory objects (including argument and return values) 33 in HAL servers. 34 We use a test HAL service IMemoryTest.hal in this script. 35 36 Attributes: 37 MAX_RETRY: int, maximum times to check if HAL server has started. 38 If server is still not started after MAX_RETRY times, 39 stop the testcase. 40 SERVICE_NAME: string, script to start the memory test HAL server. 41 COMMAND_32: string, command to start the HAL server in a 32-bit device. 42 COMMAND_64: string, command to start the HAL server in a 64-bit device. 43 CHECK_COMMAND: string, command to check if memory HAL service 44 has started. 45 MEM_VAL: int, data to fill the memory with. 46 MEM_SIZE: int, size of the memory region allocated on the target side. 47 _mem_obj: memory mirror object that users can use to read from or 48 write into. 49 _tests_memory: HAL server instance that users can directly call API on. 50 """ 51 # Some constants. 52 MAX_RETRY = 3 53 SERVICE_NAME = "hidl_test_servers" 54 COMMAND_32 = "/data/nativetest/" + SERVICE_NAME + "/" + SERVICE_NAME + " &" 55 COMMAND_64 = "/data/nativetest64/" + SERVICE_NAME + "/" + SERVICE_NAME + " &" 56 CHECK_COMMAND = "lshal --types=b | grep \"android.hardware.tests.memory@1.0\"" 57 MEM_SIZE = 1024 58 59 def setUpClass(self): 60 """Do necessary setup including starting the HAL service. 61 62 This method starts the HAL service and loads it in the target-side 63 driver. It also initializes a memory object on the target side, and 64 users can use it for reading and writing. 65 """ 66 self.dut = self.android_devices[0] 67 # Send command to start the HAL server. 68 if int(self.abi_bitness) == 64: 69 self.dut.shell.Execute(self.COMMAND_64) 70 else: 71 self.dut.shell.Execute(self.COMMAND_32) 72 73 # Wait until service is started. 74 # Retry at most three times. 75 start_hal_success = False 76 for _ in range(self.MAX_RETRY): 77 result = self.dut.shell.Execute(self.CHECK_COMMAND) 78 if result[const.STDOUT][0] != "": 79 start_hal_success = True # setup successful 80 break 81 time.sleep(1) # wait one second. 82 # memory HAL service is still not started after waiting for 83 # self.MAX_RETRY times, stop the testcase. 84 if not start_hal_success: 85 logging.error("Failed to start hidl_memory HAL service.") 86 return False 87 88 # Load a hidl_memory test hal driver. 89 self.dut.hal.InitHidlHal( 90 target_type="tests_memory", 91 target_basepaths=self.dut.libPaths, 92 target_version_major=1, 93 target_version_minor=0, 94 target_package="android.hardware.tests.memory", 95 target_component_name="IMemoryTest", 96 hw_binder_service_name="memory", 97 bits=int(self.abi_bitness), 98 is_test_hal=True) 99 # Create a shortcut for HAL server. 100 self._tests_memory = self.dut.hal.tests_memory 101 102 # Create a memory object on the client side. 103 self._mem_obj = self.dut.resource.InitHidlMemory( 104 mem_size=self.MEM_SIZE, 105 client=self.dut.hal.GetTcpClient("tests_memory")) 106 107 # Do necessary super class setup. 108 super(VtsCodelabHidlMemoryTest, self).setUpClass() 109 110 def testGetSize(self): 111 """Test getting memory size correctness. """ 112 asserts.assertEqual(self.MEM_SIZE, self._mem_obj.getSize()) 113 114 def testSimpleWriteRead(self): 115 """Test writing to the memory and reading the same data back. """ 116 write_data = "abcdef" 117 # Write data into memory. 118 self._mem_obj.update() 119 self._mem_obj.updateBytes(write_data, len(write_data)) 120 self._mem_obj.commit() 121 122 # Read data from memory. 123 self._mem_obj.read() 124 read_data = self._mem_obj.readBytes(len(write_data)) 125 asserts.assertEqual(write_data, read_data) 126 127 def testLargeWriteRead(self): 128 """Test consecutive writes and reads using integers. 129 130 For each of the 5 iterations, write 5 integers into 131 different chunks of memory, and read them back. 132 """ 133 for i in range(5): 134 # Writes five integers. 135 write_data = [random.randint(0, 100) for j in range(10)] 136 write_data_str = str(bytearray(write_data)) 137 # Start writing at offset i * 5. 138 self._mem_obj.updateRange(i * 5, len(write_data_str)) 139 self._mem_obj.updateBytes(write_data_str, len(write_data_str), 140 i * 5) 141 self._mem_obj.commit() 142 143 # Reads data back. 144 self._mem_obj.readRange(i * 5, len(write_data_str)) 145 read_data_str = self._mem_obj.readBytes(len(write_data_str), i * 5) 146 read_data = list(bytearray(read_data_str)) 147 # Check if read data is correct. 148 asserts.assertEqual(write_data, read_data) 149 150 def testWriteTwoRegionsInOneBuffer(self): 151 """Test writing into different regions in one memory buffer. 152 153 Writer requests the beginning of the first half and 154 the beginning of the second half of the buffer. 155 It writes to the second half, commits, and reads the data back. 156 Then it writes to the first half, commits, and reads the data back. 157 """ 158 write_data1 = "abcdef" 159 write_data2 = "ghijklmno" 160 161 # Reserve both regions. 162 self._mem_obj.updateRange(0, len(write_data1)) 163 self._mem_obj.updateRange(self.MEM_SIZE / 2, len(write_data2)) 164 # Write to the second region. 165 self._mem_obj.updateBytes(write_data2, len(write_data2), 166 self.MEM_SIZE / 2) 167 self._mem_obj.commit() 168 169 # Read from the second region. 170 self._mem_obj.read() 171 read_data2 = self._mem_obj.readBytes( 172 len(write_data2), self.MEM_SIZE / 2) 173 self._mem_obj.commit() 174 # Check if read data is correct. 175 asserts.assertEqual(read_data2, write_data2) 176 177 # Write to the first region. 178 self._mem_obj.updateBytes(write_data1, len(write_data1)) 179 self._mem_obj.commit() 180 181 # Read from the first region. 182 self._mem_obj.read() 183 read_data1 = self._mem_obj.readBytes(len(write_data1)) 184 self._mem_obj.commit() 185 # Check if read data is correct. 186 asserts.assertEqual(write_data1, read_data1) 187 188 def testSharedMemory(self): 189 """Test HAL server API fillMemory(), which takes in hidl_memory. 190 191 The memory filled out by the HAL server should be seen by the client. 192 """ 193 # Zero out memory. 194 self._mem_obj.update() 195 self._mem_obj.updateBytes("\0" * self.MEM_SIZE, self.MEM_SIZE) 196 self._mem_obj.commit() 197 198 # Tell HAL server to fill the memory, should be seen by the client, 199 # because they use shared memory. 200 var_msg = self.prepareHidlMemoryArgument(self._mem_obj.memId) 201 # Fill the memory with each byte be integer value 42. 202 self._tests_memory.fillMemory(var_msg, 42) 203 self._mem_obj.read() 204 read_data = self._mem_obj.readBytes(self.MEM_SIZE) 205 self._mem_obj.commit() 206 207 # Convert read_data to a list of chars, and convert them back to int8_t. 208 read_data = list(read_data) 209 read_data = map(lambda i: ord(i), read_data) 210 211 # Check read data. 212 asserts.assertEqual(read_data, [42] * self.MEM_SIZE) 213 214 def testSameMemoryDifferentId(self): 215 """Test HAL server API haveSomeMemory(), which returns hidl_memory. 216 217 haveSomeMemory() returns input memory directly. 218 We pass the client memory object to this API, and the return value 219 of this API should be registered in our target-side drivers as well. 220 The returned memory object is basically identical to the first memory 221 object held by the client. 222 They have different id, but they share the same memory region. 223 """ 224 # Prepare a hidl_memory argument. 225 var_msg = self.prepareHidlMemoryArgument(self._mem_obj.memId) 226 227 # memory_client2 is identical to self._mem_obj because 228 # haveSomeMemory() API in the server just returns the input 229 # hidl_memory reference directly. 230 memory_client2 = self._tests_memory.haveSomeMemory(var_msg) 231 asserts.assertNotEqual(memory_client2, None) 232 asserts.assertNotEqual(memory_client2.memId, -1) 233 # Check these two clients are stored as different objects. 234 asserts.assertNotEqual(memory_client2.memId, 235 self._mem_obj.memId) 236 237 # Fill the memory with each byte being integer value 50. 238 self._tests_memory.fillMemory(var_msg, 50) 239 240 # Both clients read. 241 self._mem_obj.read() 242 read_data1 = self._mem_obj.readBytes(self.MEM_SIZE) 243 self._mem_obj.commit() 244 memory_client2.read() 245 read_data2 = memory_client2.readBytes(self.MEM_SIZE) 246 memory_client2.commit() 247 248 # Convert read_data to a list of chars, and convert them back to int8_t. 249 read_data1 = list(read_data1) 250 read_data1 = map(lambda i: ord(i), read_data1) 251 read_data2 = list(read_data2) 252 read_data2 = map(lambda i: ord(i), read_data2) 253 254 # Check read data. 255 asserts.assertEqual(read_data1, [50] * self.MEM_SIZE) 256 asserts.assertEqual(read_data2, [50] * self.MEM_SIZE) 257 258 @staticmethod 259 def prepareHidlMemoryArgument(mem_id): 260 """Prepare VariableSpecificationMessage containing hidl_memory argument. 261 262 Args: 263 mem_id: int, identifies the memory object. 264 265 Returns: 266 VariableSpecificationMessage, specifies the memory id. 267 """ 268 var_msg = CompSpecMsg.VariableSpecificationMessage() 269 var_msg.type = CompSpecMsg.TYPE_HIDL_MEMORY 270 var_msg.hidl_memory_value.mem_id = mem_id 271 return var_msg 272 273 274if __name__ == "__main__": 275 test_runner.main() 276