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