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