1 /* 2 * Copyright (C) 2017 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 package com.android.car; 18 19 import static org.junit.Assert.assertEquals; 20 import static org.junit.Assert.assertTrue; 21 22 import android.car.Car; 23 import android.car.VehicleAreaType; 24 import android.car.vms.VmsAssociatedLayer; 25 import android.car.vms.VmsAvailableLayers; 26 import android.car.vms.VmsLayer; 27 import android.car.vms.VmsSubscriberManager; 28 import android.hardware.automotive.vehicle.V2_0.VehicleProperty; 29 import android.hardware.automotive.vehicle.V2_0.VehiclePropertyAccess; 30 import android.hardware.automotive.vehicle.V2_0.VehiclePropertyChangeMode; 31 import android.support.test.filters.MediumTest; 32 import android.support.test.runner.AndroidJUnit4; 33 34 import com.android.car.vehiclehal.test.MockedVehicleHal; 35 36 import org.junit.Test; 37 import org.junit.runner.RunWith; 38 39 import java.util.ArrayList; 40 import java.util.Arrays; 41 import java.util.HashSet; 42 import java.util.List; 43 import java.util.Set; 44 import java.util.concurrent.Executor; 45 import java.util.concurrent.Semaphore; 46 import java.util.concurrent.TimeUnit; 47 48 @RunWith(AndroidJUnit4.class) 49 @MediumTest 50 public class VmsPublisherSubscriberTest extends MockedCarTestBase { 51 private static final int LAYER_ID = 88; 52 private static final int LAYER_VERSION = 19; 53 private static final int LAYER_SUBTYPE = 55; 54 private static final String TAG = "VmsPubSubTest"; 55 56 // The expected publisher ID is 0 since it the expected assigned ID from the VMS core. 57 public static final int EXPECTED_PUBLISHER_ID = 0; 58 public static final VmsLayer LAYER = new VmsLayer(LAYER_ID, LAYER_SUBTYPE, LAYER_VERSION); 59 public static final VmsAssociatedLayer ASSOCIATED_LAYER = 60 new VmsAssociatedLayer(LAYER, new HashSet<>(Arrays.asList(EXPECTED_PUBLISHER_ID))); 61 public static final byte[] PAYLOAD = new byte[]{2, 3, 5, 7, 11, 13, 17}; 62 63 private static final List<VmsAssociatedLayer> AVAILABLE_ASSOCIATED_LAYERS = 64 new ArrayList<>(Arrays.asList(ASSOCIATED_LAYER)); 65 private static final VmsAvailableLayers AVAILABLE_LAYERS_WITH_SEQ = 66 new VmsAvailableLayers( 67 new HashSet(AVAILABLE_ASSOCIATED_LAYERS), 1); 68 69 70 private static final int SUBSCRIBED_LAYER_ID = 89; 71 public static final VmsLayer SUBSCRIBED_LAYER = 72 new VmsLayer(SUBSCRIBED_LAYER_ID, LAYER_SUBTYPE, LAYER_VERSION); 73 public static final VmsAssociatedLayer ASSOCIATED_SUBSCRIBED_LAYER = 74 new VmsAssociatedLayer(SUBSCRIBED_LAYER, 75 new HashSet<>(Arrays.asList(EXPECTED_PUBLISHER_ID))); 76 private static final List<VmsAssociatedLayer> 77 AVAILABLE_ASSOCIATED_LAYERS_WITH_SUBSCRIBED_LAYER = 78 new ArrayList<>(Arrays.asList(ASSOCIATED_LAYER, ASSOCIATED_SUBSCRIBED_LAYER)); 79 private static final VmsAvailableLayers AVAILABLE_LAYERS_WITH_SUBSCRIBED_LAYER_WITH_SEQ = 80 new VmsAvailableLayers( 81 new HashSet(AVAILABLE_ASSOCIATED_LAYERS_WITH_SUBSCRIBED_LAYER), 1); 82 VmsSubscriberManager mVmsSubscriberManager; 83 TestClientCallback mClientCallback; 84 private HalHandler mHalHandler; 85 // Used to block until a value is propagated to the TestClientCallback.onVmsMessageReceived. 86 private Semaphore mSubscriberSemaphore; 87 private Semaphore mAvailabilitySemaphore; 88 private Executor mExecutor; 89 90 private class ThreadPerTaskExecutor implements Executor { execute(Runnable r)91 public void execute(Runnable r) { 92 new Thread(r).start(); 93 } 94 } 95 96 97 @Override configureMockedHal()98 protected synchronized void configureMockedHal() { 99 mHalHandler = new HalHandler(); 100 addProperty(VehicleProperty.VEHICLE_MAP_SERVICE, mHalHandler) 101 .setChangeMode(VehiclePropertyChangeMode.ON_CHANGE) 102 .setAccess(VehiclePropertyAccess.READ_WRITE) 103 .addAreaConfig(VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, 0, 0); 104 } 105 106 @Override configureResourceOverrides(MockResources resources)107 protected synchronized void configureResourceOverrides(MockResources resources) { 108 resources.overrideResource(com.android.car.R.array.vmsPublisherClients, 109 new String[]{getFlattenComponent(VmsPublisherClientMockService.class)}); 110 } 111 112 /* 113 * The method setUp initializes all the Car services, including the VmsPublisherService. 114 * The VmsPublisherService will start and configure its list of clients. This list was 115 * overridden in the method getCarServiceContext. Therefore, only VmsPublisherClientMockService 116 * will be started. Method setUp() subscribes to a layer and triggers 117 * VmsPublisherClientMockService.onVmsSubscriptionChange. 118 * There is a race condition between publisher and subscriber starting time. 119 * So we wanted to make sure that the tests start only after the publisher is up. We achieve 120 * this by subscribing in setUp() and waiting on the semaphore at the beginning of each test 121 * case. 122 */ 123 124 @Override setUp()125 public void setUp() throws Exception { 126 mExecutor = new ThreadPerTaskExecutor(); 127 super.setUp(); 128 mSubscriberSemaphore = new Semaphore(0); 129 mAvailabilitySemaphore = new Semaphore(0); 130 131 mVmsSubscriberManager = (VmsSubscriberManager) getCar().getCarManager( 132 Car.VMS_SUBSCRIBER_SERVICE); 133 mClientCallback = new TestClientCallback(); 134 mVmsSubscriberManager.setVmsSubscriberClientCallback(mExecutor, mClientCallback); 135 mVmsSubscriberManager.subscribe(LAYER); 136 } 137 postSetup()138 public void postSetup() throws Exception { 139 assertTrue(mAvailabilitySemaphore.tryAcquire(2L, TimeUnit.SECONDS)); 140 } 141 142 /* 143 * This test method subscribes to a layer and triggers 144 * VmsPublisherClientMockService.onVmsSubscriptionChange. In turn, the mock service will publish 145 * a message, which is validated in this test. 146 */ 147 148 @Test testPublisherToSubscriber()149 public void testPublisherToSubscriber() throws Exception { 150 postSetup(); 151 assertEquals(LAYER, mClientCallback.getLayer()); 152 assertTrue(Arrays.equals(PAYLOAD, mClientCallback.getPayload())); 153 } 154 155 /** 156 * The Mock service will get a publisher ID by sending its information when it will get 157 * ServiceReady as well as on SubscriptionChange. Since clients are not notified when 158 * publishers are assigned IDs, this test waits until the availability is changed which 159 * indicates 160 * that the Mock service has gotten its ServiceReady and publisherId. 161 */ 162 163 164 @Test testPublisherInfo()165 public void testPublisherInfo() throws Exception { 166 postSetup(); 167 168 // Inject a value and wait for its callback in TestClientCallback.onVmsMessageReceived. 169 byte[] info = mVmsSubscriberManager.getPublisherInfo(EXPECTED_PUBLISHER_ID); 170 assertTrue(Arrays.equals(PAYLOAD, info)); 171 } 172 173 /* 174 * The Mock service offers all the subscribed layers as available layers. 175 * In this test the client subscribes to a layer and verifies that it gets the 176 * notification that it is available. 177 */ 178 179 @Test testAvailabilityWithSubscription()180 public void testAvailabilityWithSubscription() throws Exception { 181 postSetup(); 182 mVmsSubscriberManager.subscribe(SUBSCRIBED_LAYER); 183 assertTrue(mAvailabilitySemaphore.tryAcquire(2L, TimeUnit.SECONDS)); 184 185 final Set<VmsAssociatedLayer> associatedLayers = 186 AVAILABLE_LAYERS_WITH_SUBSCRIBED_LAYER_WITH_SEQ.getAssociatedLayers(); 187 assertEquals(associatedLayers, mClientCallback.getAvailableLayers().getAssociatedLayers()); 188 assertEquals(associatedLayers, 189 mVmsSubscriberManager.getAvailableLayers().getAssociatedLayers()); 190 } 191 192 private class HalHandler implements MockedVehicleHal.VehicleHalPropertyHandler { 193 } 194 195 private class TestClientCallback implements VmsSubscriberManager.VmsSubscriberClientCallback { 196 private VmsLayer mLayer; 197 private byte[] mPayload; 198 private VmsAvailableLayers mAvailableLayers; 199 200 @Override onVmsMessageReceived(VmsLayer layer, byte[] payload)201 public void onVmsMessageReceived(VmsLayer layer, byte[] payload) { 202 assertEquals(LAYER, layer); 203 assertTrue(Arrays.equals(PAYLOAD, payload)); 204 mLayer = layer; 205 mPayload = payload; 206 mSubscriberSemaphore.release(); 207 } 208 209 @Override onLayersAvailabilityChanged(VmsAvailableLayers availableLayers)210 public void onLayersAvailabilityChanged(VmsAvailableLayers availableLayers) { 211 mAvailableLayers = availableLayers; 212 mAvailabilitySemaphore.release(); 213 } 214 getLayer()215 public VmsLayer getLayer() { 216 return mLayer; 217 } 218 getPayload()219 public byte[] getPayload() { 220 return mPayload; 221 } 222 getAvailableLayers()223 public VmsAvailableLayers getAvailableLayers() { 224 return mAvailableLayers; 225 } 226 } 227 } 228