1 /* 2 * Copyright (C) 2019 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 package com.android.car; 17 18 import static org.junit.Assert.assertEquals; 19 import static org.junit.Assert.assertTrue; 20 21 import android.car.Car; 22 import android.car.VehicleAreaType; 23 import android.car.vms.VmsAvailableLayers; 24 import android.car.vms.VmsLayer; 25 import android.car.vms.VmsPublisherClientService; 26 import android.car.vms.VmsSubscriberManager; 27 import android.car.vms.VmsSubscriptionState; 28 import android.hardware.automotive.vehicle.VehiclePropValue; 29 import android.hardware.automotive.vehicle.VehicleProperty; 30 import android.hardware.automotive.vehicle.VehiclePropertyAccess; 31 import android.hardware.automotive.vehicle.VehiclePropertyChangeMode; 32 import android.hardware.automotive.vehicle.VmsAvailabilityStateIntegerValuesIndex; 33 import android.hardware.automotive.vehicle.VmsBaseMessageIntegerValuesIndex; 34 import android.hardware.automotive.vehicle.VmsMessageType; 35 import android.hardware.automotive.vehicle.VmsStartSessionMessageIntegerValuesIndex; 36 import android.util.Log; 37 import android.util.Pair; 38 39 import com.android.car.hal.test.AidlMockedVehicleHal; 40 import com.android.car.hal.test.AidlVehiclePropValueBuilder; 41 42 import org.junit.Before; 43 44 import java.util.concurrent.BlockingQueue; 45 import java.util.concurrent.CountDownLatch; 46 import java.util.concurrent.Executors; 47 import java.util.concurrent.LinkedBlockingQueue; 48 import java.util.concurrent.TimeUnit; 49 50 public class MockedVmsTestBase extends MockedCarTestBase { 51 public static final long PUBLISHER_CLIENT_TIMEOUT = 500L; 52 public static final long MESSAGE_RECEIVE_TIMEOUT = 500L; 53 private static final String TAG = "MockedVmsTestBase"; 54 55 private MockPublisherClient mPublisherClient; 56 private CountDownLatch mPublisherIsReady = new CountDownLatch(1); 57 private VmsSubscriberManager mVmsSubscriberManager; 58 private MockSubscriberClient mSubscriberClient; 59 private MockHalClient mHalClient; 60 61 @Override configureMockedHal()62 protected void configureMockedHal() { 63 mHalClient = new MockHalClient(); 64 addAidlProperty(VehicleProperty.VEHICLE_MAP_SERVICE, mHalClient) 65 .setChangeMode(VehiclePropertyChangeMode.ON_CHANGE) 66 .setAccess(VehiclePropertyAccess.READ_WRITE) 67 .addAreaConfig(VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, 0, 0); 68 } 69 70 @Before setUpVms()71 public void setUpVms() throws Exception { 72 mPublisherClient = new MockPublisherClient(); 73 mPublisherClient.setMockCar(getCar()); 74 mVmsSubscriberManager = (VmsSubscriberManager) getCar().getCarManager( 75 Car.VMS_SUBSCRIBER_SERVICE); 76 mSubscriberClient = new MockSubscriberClient(); 77 mVmsSubscriberManager.setVmsSubscriberClientCallback(Executors.newSingleThreadExecutor(), 78 mSubscriberClient); 79 80 assertTrue( 81 "Timeout while waiting for publisher client to be ready", 82 mPublisherIsReady.await(PUBLISHER_CLIENT_TIMEOUT, TimeUnit.MILLISECONDS)); 83 84 // Validate session handshake 85 int[] v = mHalClient.receiveMessage().value.int32Values; 86 assertEquals(VmsMessageType.START_SESSION, 87 v[VmsBaseMessageIntegerValuesIndex.MESSAGE_TYPE]); 88 int coreId = v[VmsStartSessionMessageIntegerValuesIndex.SERVICE_ID]; 89 assertTrue(coreId > 0); 90 assertEquals(-1, v[VmsStartSessionMessageIntegerValuesIndex.CLIENT_ID]); 91 92 // Send handshake acknowledgement 93 mHalClient.sendMessage( 94 VmsMessageType.START_SESSION, 95 coreId, 96 12345 // Client ID 97 ); 98 99 // Validate layer availability sent to HAL 100 v = mHalClient.receiveMessage().value.int32Values; 101 assertEquals(VmsMessageType.AVAILABILITY_CHANGE, 102 v[VmsAvailabilityStateIntegerValuesIndex.MESSAGE_TYPE]); 103 assertEquals(0, 104 v[VmsAvailabilityStateIntegerValuesIndex.SEQUENCE_NUMBER]); 105 assertEquals(0, 106 v[VmsAvailabilityStateIntegerValuesIndex.NUMBER_OF_ASSOCIATED_LAYERS]); 107 } 108 getSubscriberManager()109 VmsSubscriberManager getSubscriberManager() { 110 return mVmsSubscriberManager; 111 } 112 getMockPublisherClient()113 MockPublisherClient getMockPublisherClient() { 114 return mPublisherClient; 115 } 116 getMockSubscriberClient()117 MockSubscriberClient getMockSubscriberClient() { 118 return mSubscriberClient; 119 } 120 getMockHalClient()121 MockHalClient getMockHalClient() { 122 return mHalClient; 123 } 124 125 class MockPublisherClient extends VmsPublisherClientService { 126 private BlockingQueue<VmsSubscriptionState> mSubscriptionState = 127 new LinkedBlockingQueue<>(); 128 setMockCar(Car car)129 void setMockCar(Car car) { 130 onCarLifecycleChanged(car, true); 131 } 132 133 @Override onVmsPublisherServiceReady()134 protected void onVmsPublisherServiceReady() { 135 Log.d(TAG, "MockPublisherClient.onVmsPublisherServiceReady"); 136 mPublisherIsReady.countDown(); 137 } 138 139 @Override onVmsSubscriptionChange(VmsSubscriptionState subscriptionState)140 public void onVmsSubscriptionChange(VmsSubscriptionState subscriptionState) { 141 Log.d(TAG, "MockPublisherClient.onVmsSubscriptionChange: " 142 + subscriptionState.getSequenceNumber()); 143 mSubscriptionState.add(subscriptionState); 144 } 145 receiveSubscriptionState()146 VmsSubscriptionState receiveSubscriptionState() { 147 return receiveWithTimeout(mSubscriptionState); 148 } 149 } 150 151 class MockSubscriberClient implements VmsSubscriberManager.VmsSubscriberClientCallback { 152 private BlockingQueue<Pair<VmsLayer, byte[]>> mMessages = new LinkedBlockingQueue<>(); 153 private BlockingQueue<VmsAvailableLayers> mAvailableLayers = new LinkedBlockingQueue<>(); 154 155 @Override onVmsMessageReceived(VmsLayer layer, byte[] payload)156 public void onVmsMessageReceived(VmsLayer layer, byte[] payload) { 157 Log.d(TAG, "MockSubscriberClient.onVmsMessageReceived"); 158 mMessages.add(Pair.create(layer, payload)); 159 } 160 161 @Override onLayersAvailabilityChanged(VmsAvailableLayers availableLayers)162 public void onLayersAvailabilityChanged(VmsAvailableLayers availableLayers) { 163 Log.d(TAG, "MockSubscriberClient.onVmsMessageReceived"); 164 mAvailableLayers.add(availableLayers); 165 } 166 receiveMessage()167 Pair<VmsLayer, byte[]> receiveMessage() { 168 return receiveWithTimeout(mMessages); 169 } 170 receiveLayerAvailability()171 VmsAvailableLayers receiveLayerAvailability() { 172 return receiveWithTimeout(mAvailableLayers); 173 } 174 } 175 176 class MockHalClient implements AidlMockedVehicleHal.VehicleHalPropertyHandler { 177 private BlockingQueue<VehiclePropValue> mMessages = new LinkedBlockingQueue<>(); 178 179 @Override onPropertySet(VehiclePropValue value)180 public void onPropertySet(VehiclePropValue value) { 181 Log.d(TAG, "MockHalClient.onPropertySet"); 182 if (value.prop == VehicleProperty.VEHICLE_MAP_SERVICE) { 183 mMessages.add(value); 184 } 185 } 186 sendMessage(int... message)187 void sendMessage(int... message) { 188 getAidlMockedVehicleHal().injectEvent( 189 AidlVehiclePropValueBuilder.newBuilder(VehicleProperty.VEHICLE_MAP_SERVICE) 190 .addIntValues(message) 191 .build()); 192 } 193 sendMessage(int[] message, byte[] payload)194 void sendMessage(int[] message, byte[] payload) { 195 getAidlMockedVehicleHal().injectEvent( 196 AidlVehiclePropValueBuilder.newBuilder(VehicleProperty.VEHICLE_MAP_SERVICE) 197 .addIntValues(message) 198 .addByteValues(payload) 199 .build()); 200 } 201 receiveMessage()202 VehiclePropValue receiveMessage() { 203 return receiveWithTimeout(mMessages); 204 } 205 } 206 receiveWithTimeout(BlockingQueue<T> queue)207 private static <T> T receiveWithTimeout(BlockingQueue<T> queue) { 208 try { 209 return queue.poll(MESSAGE_RECEIVE_TIMEOUT, TimeUnit.MILLISECONDS); 210 } catch (InterruptedException e) { 211 throw new RuntimeException(e); 212 } 213 } 214 } 215