1 /* 2 * Copyright (C) 2015 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.test; 17 18 import android.car.Car; 19 import android.car.hardware.radio.CarRadioEvent; 20 import android.car.hardware.radio.CarRadioManager; 21 import android.car.hardware.radio.CarRadioManager.CarRadioEventListener; 22 import android.car.hardware.radio.CarRadioPreset; 23 import android.hardware.radio.RadioManager; 24 import android.hardware.automotive.vehicle.V2_0.VehiclePropValue; 25 import android.hardware.automotive.vehicle.V2_0.VehicleProperty; 26 import android.os.SystemClock; 27 import android.test.suitebuilder.annotation.MediumTest; 28 import android.util.Log; 29 30 import com.google.android.collect.Lists; 31 32 import com.android.car.vehiclehal.VehiclePropValueBuilder; 33 import com.android.car.vehiclehal.test.MockedVehicleHal.VehicleHalPropertyHandler; 34 35 import java.util.HashMap; 36 import java.util.concurrent.Semaphore; 37 import java.util.concurrent.TimeUnit; 38 39 @MediumTest 40 public class CarRadioManagerTest extends MockedCarTestBase { 41 42 private static final String TAG = CarRadioManagerTest.class.getSimpleName(); 43 44 // Use this semaphore to block until the callback is heard of. 45 private Semaphore mAvailable; 46 47 private static final int NUM_PRESETS = 2; 48 private final HashMap<Integer, CarRadioPreset> mRadioPresets = new HashMap<>(); 49 50 private CarRadioManager mCarRadioManager; 51 52 private class RadioPresetPropertyHandler implements VehicleHalPropertyHandler { 53 public RadioPresetPropertyHandler() { } 54 55 @Override 56 public synchronized void onPropertySet(VehiclePropValue value) { 57 assertEquals(value.prop, VehicleProperty.RADIO_PRESET); 58 59 Integer[] valueList = new Integer[4]; 60 value.value.int32Values.toArray(valueList); 61 assertFalse( 62 "Index out of range: " + valueList[0] + " (0, " + NUM_PRESETS + ")", 63 valueList[0] < 1); 64 assertFalse( 65 "Index out of range: " + valueList[0] + " (0, " + NUM_PRESETS + ")", 66 valueList[0] > NUM_PRESETS); 67 68 CarRadioPreset preset = 69 new CarRadioPreset(valueList[0], valueList[1], valueList[2], valueList[3]); 70 mRadioPresets.put(valueList[0], preset); 71 72 // The test case must be waiting for the semaphore, if not we should throw exception. 73 if (mAvailable.availablePermits() != 0) { 74 Log.d(TAG, "Lock was free, should have been locked."); 75 } 76 mAvailable.release(); 77 } 78 79 @Override 80 public synchronized VehiclePropValue onPropertyGet(VehiclePropValue value) { 81 assertEquals(value.prop, VehicleProperty.RADIO_PRESET); 82 83 Integer[] valueList = new Integer[4]; 84 value.value.int32Values.toArray(valueList); 85 86 // Get the actual preset. 87 if (valueList[0] < 1 || valueList[0] > NUM_PRESETS) { 88 // VNS will call get method when subscribe is called, just return an empty 89 // value. 90 return value; 91 } 92 CarRadioPreset preset = mRadioPresets.get(valueList[0]); 93 return VehiclePropValueBuilder.newBuilder(VehicleProperty.RADIO_PRESET) 94 .setTimestamp(SystemClock.elapsedRealtimeNanos()) 95 .addIntValue( 96 preset.getPresetNumber(), 97 preset.getBand(), 98 preset.getChannel(), 99 preset.getSubChannel()) 100 .build(); 101 } 102 103 @Override 104 public synchronized void onPropertySubscribe(int property, int zones, float sampleRate) { 105 Log.d(TAG, "onPropertySubscribe property: " + property + " rate: " + sampleRate); 106 if (mAvailable.availablePermits() != 0) { 107 Log.d(TAG, "Lock was free, should have been locked."); 108 return; 109 } 110 mAvailable.release(); 111 } 112 113 @Override 114 public synchronized void onPropertyUnsubscribe(int property) { 115 } 116 } 117 118 private class EventListener implements CarRadioEventListener { 119 public EventListener() { } 120 121 @Override 122 public void onEvent(CarRadioEvent event) { 123 // Print the event and release the lock. 124 Log.d(TAG, event.toString()); 125 if (mAvailable.availablePermits() != 0) { 126 Log.e(TAG, "Lock should be taken."); 127 // Let the timeout fail the test here. 128 return; 129 } 130 mAvailable.release(); 131 } 132 } 133 134 @Override 135 protected synchronized void configureMockedHal() { 136 addProperty(VehicleProperty.RADIO_PRESET, new RadioPresetPropertyHandler()) 137 .setConfigArray(Lists.newArrayList(NUM_PRESETS)); 138 } 139 140 @Override 141 protected void setUp() throws Exception { 142 super.setUp(); 143 mAvailable = new Semaphore(0); 144 mCarRadioManager = (CarRadioManager) getCar().getCarManager(Car.RADIO_SERVICE); 145 } 146 147 public void testPresetCount() throws Exception { 148 int presetCount = mCarRadioManager.getPresetCount(); 149 assertEquals("Preset count not same.", NUM_PRESETS, presetCount); 150 } 151 152 public void testSetAndGetPreset() throws Exception { 153 // Create a preset. 154 CarRadioPreset preset = new CarRadioPreset(1, RadioManager.BAND_FM, 1234, -1); 155 assertEquals("Lock should be freed by now.", 0, mAvailable.availablePermits()); 156 // mAvailable.acquire(1); 157 mCarRadioManager.setPreset(preset); 158 159 // Wait for acquire to be available again, fail if timeout. 160 boolean success = mAvailable.tryAcquire(5L, TimeUnit.SECONDS); 161 assertEquals("Could not finish setting, timeout!", true, success); 162 163 // Test that get preset gives you the same element. 164 assertEquals(preset, mCarRadioManager.getPreset(1)); 165 } 166 167 public void testSubscribe() throws Exception { 168 EventListener listener = new EventListener(); 169 assertEquals("Lock should be freed by now.", 0, mAvailable.availablePermits()); 170 mCarRadioManager.registerListener(listener); 171 172 // Wait for acquire to be available again, fail if timeout. 173 boolean success = mAvailable.tryAcquire(5L, TimeUnit.SECONDS); 174 assertEquals("addListener timeout", true, success); 175 176 // Inject an event and wait for its callback in onPropertySet. 177 CarRadioPreset preset = new CarRadioPreset(2, RadioManager.BAND_AM, 4321, -1); 178 179 VehiclePropValue v = VehiclePropValueBuilder.newBuilder(VehicleProperty.RADIO_PRESET) 180 .setTimestamp(SystemClock.elapsedRealtimeNanos()) 181 .addIntValue( 182 preset.getPresetNumber(), 183 preset.getBand(), 184 preset.getChannel(), 185 preset.getSubChannel()) 186 .build(); 187 getMockedVehicleHal().injectEvent(v); 188 189 success = mAvailable.tryAcquire(5L, TimeUnit.SECONDS); 190 assertEquals("injectEvent, onEvent timeout!", true, success); 191 } 192 } 193