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.vehiclenetwork.libtest; 17 18 import android.os.HandlerThread; 19 import android.os.SystemClock; 20 import android.test.AndroidTestCase; 21 import android.test.suitebuilder.annotation.MediumTest; 22 import android.util.ArraySet; 23 import android.util.Log; 24 25 import com.android.car.vehiclenetwork.VehicleNetwork; 26 import com.android.car.vehiclenetwork.VehicleNetwork.VehicleNetworkListener; 27 import com.android.car.vehiclenetwork.VehicleNetworkConsts; 28 import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehiclePropAccess; 29 import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehiclePropChangeMode; 30 import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType; 31 import com.android.car.vehiclenetwork.VehicleNetworkProto.VehiclePropConfig; 32 import com.android.car.vehiclenetwork.VehicleNetworkProto.VehiclePropConfigs; 33 import com.android.car.vehiclenetwork.VehicleNetworkProto.VehiclePropValue; 34 import com.android.car.vehiclenetwork.VehicleNetworkProto.VehiclePropValues; 35 import com.android.car.vehiclenetwork.VehicleNetworkProtoUtil; 36 37 import java.util.LinkedList; 38 39 @MediumTest 40 public class VehicleNetworkTest extends AndroidTestCase { 41 private static final String TAG = VehicleNetworkTest.class.getSimpleName(); 42 private static final long TIMEOUT_MS = 2000; 43 44 private final HandlerThread mHandlerThread = new HandlerThread( 45 VehicleNetworkTest.class.getSimpleName()); 46 private VehicleNetwork mVehicleNetwork; 47 private final TestListener mListener = new TestListener(); 48 49 @Override 50 protected void setUp() throws Exception { 51 super.setUp(); 52 mHandlerThread.start(); 53 mVehicleNetwork = VehicleNetwork.createVehicleNetwork(mListener, 54 mHandlerThread.getLooper()); 55 } 56 57 @Override 58 protected void tearDown() throws Exception { 59 super.tearDown(); 60 mHandlerThread.quit(); 61 } 62 63 public void testListProperties() { 64 VehiclePropConfigs configs = mVehicleNetwork.listProperties(); 65 assertNotNull(configs); 66 assertTrue(configs.getConfigsCount() > 0); 67 Log.i(TAG, "got configs:" + configs.getConfigsCount()); 68 for (VehiclePropConfig config : configs.getConfigsList()) { 69 Log.i(TAG, VehicleNetworkProtoUtil.VehiclePropConfigToString(config)); 70 } 71 72 int oneProperty = configs.getConfigs(0).getProp(); 73 VehiclePropConfigs configs2 = mVehicleNetwork.listProperties(oneProperty); 74 assertEquals(1, configs2.getConfigsCount()); 75 assertTrue(VehicleNetworkProtoUtil.VehiclePropConfigEquals( 76 configs.getConfigs(0), configs2.getConfigs(0))); 77 78 VehiclePropConfigs configs3 = mVehicleNetwork.listProperties(-1); 79 assertNull(configs3); 80 } 81 82 public void testGetProperty() { 83 try { 84 VehiclePropValue value = mVehicleNetwork.getProperty(-1); 85 fail(); 86 } catch (IllegalArgumentException e) { 87 // expected 88 } 89 VehiclePropConfigs configs = mVehicleNetwork.listProperties(); 90 assertNotNull(configs); 91 assertTrue(configs.getConfigsCount() > 0); 92 Log.i(TAG, "got configs:" + configs.getConfigsCount()); 93 for (VehiclePropConfig config : configs.getConfigsList()) { 94 if ((config.getAccess() & VehiclePropAccess.VEHICLE_PROP_ACCESS_READ) != 0) { 95 if (config.getProp() == VehicleNetworkConsts.VEHICLE_PROPERTY_RADIO_PRESET) { 96 continue; 97 } 98 if (config.getProp() >= VehicleNetworkConsts.VEHICLE_PROPERTY_INTERNAL_START && 99 config.getProp() <= VehicleNetworkConsts.VEHICLE_PROPERTY_INTERNAL_END) { 100 // internal property requires write to read 101 VehiclePropValue v = VehicleNetworkTestUtil.createDummyValue(config.getProp(), 102 config.getValueType()); 103 mVehicleNetwork.setProperty(v); 104 } 105 VehiclePropValue value = mVehicleNetwork.getProperty(config.getProp()); 106 assertEquals(config.getProp(), value.getProp()); 107 assertEquals(config.getValueType(), value.getValueType()); 108 Log.i(TAG, " got property:" + 109 VehicleNetworkProtoUtil.VehiclePropValueToString(value)); 110 } 111 } 112 } 113 114 public void testSetProperty() { 115 try { 116 VehiclePropValue value = VehiclePropValue.newBuilder(). 117 setProp(-1). 118 setValueType(VehicleValueType.VEHICLE_VALUE_TYPE_INT32). 119 addInt32Values(0). 120 build(); 121 mVehicleNetwork.setProperty(value); 122 fail(); 123 } catch (SecurityException e) { 124 // expected 125 } 126 VehiclePropConfigs configs = mVehicleNetwork.listProperties(); 127 assertNotNull(configs); 128 assertTrue(configs.getConfigsCount() > 0); 129 Log.i(TAG, "got configs:" + configs.getConfigsCount()); 130 for (VehiclePropConfig config : configs.getConfigsList()) { 131 if ((config.getAccess() & VehiclePropAccess.VEHICLE_PROP_ACCESS_WRITE) != 0) { 132 if (config.getValueType() == VehicleValueType.VEHICLE_VALUE_TYPE_INT32) { 133 VehiclePropValue value = VehiclePropValue.newBuilder(). 134 setProp(config.getProp()). 135 setValueType(config.getValueType()). 136 addInt32Values(0). 137 build(); 138 mVehicleNetwork.setProperty(value); 139 } 140 } else { 141 try { 142 VehiclePropValue value = VehiclePropValue.newBuilder(). 143 setProp(config.getProp()). 144 setValueType(config.getValueType()). 145 build(); 146 mVehicleNetwork.setProperty(value); 147 fail(); 148 } catch (IllegalArgumentException e) { 149 // expected 150 } 151 } 152 } 153 } 154 155 public void testSubscribe() throws Exception { 156 try { 157 mVehicleNetwork.subscribe(-1, 0); 158 fail(); 159 } catch (SecurityException e) { 160 //expected 161 } 162 VehiclePropConfigs configs = mVehicleNetwork.listProperties(); 163 assertNotNull(configs); 164 assertTrue(configs.getConfigsCount() > 0); 165 Log.i(TAG, "got configs:" + configs.getConfigsCount()); 166 LinkedList<Integer> subscribedProperties = new LinkedList<Integer>(); 167 for (VehiclePropConfig config : configs.getConfigsList()) { 168 if (config.getChangeMode() == VehiclePropChangeMode.VEHICLE_PROP_CHANGE_MODE_STATIC) { 169 // cannot subscribe 170 try { 171 mVehicleNetwork.subscribe(config.getProp(), config.getSampleRateMin()); 172 fail(); 173 } catch (IllegalArgumentException e) { 174 //expected 175 } 176 } else if ((config.getAccess() & VehiclePropAccess.VEHICLE_PROP_ACCESS_READ) != 0){ 177 mVehicleNetwork.subscribe(config.getProp(), config.getSampleRateMin()); 178 subscribedProperties.add(config.getProp()); 179 if (config.getProp() >= VehicleNetworkConsts.VEHICLE_PROPERTY_INTERNAL_START && 180 config.getProp() <= VehicleNetworkConsts.VEHICLE_PROPERTY_INTERNAL_END) { 181 // internal property requires write to get notification 182 VehiclePropValue v = VehicleNetworkTestUtil.createDummyValue(config.getProp(), 183 config.getValueType()); 184 mVehicleNetwork.setProperty(v); 185 } 186 } 187 } 188 // now confirm event 189 for (Integer prop : subscribedProperties) { 190 mListener.waitForEvent(prop, TIMEOUT_MS); 191 mVehicleNetwork.unsubscribe(prop); 192 } 193 // wait for already patched events to go away. 194 Thread.sleep(1000); 195 mListener.resetEventRecord(); 196 Thread.sleep(2000); 197 assertEquals(0, mListener.getActiveEventsCount()); 198 } 199 200 private class TestListener implements VehicleNetworkListener { 201 private final ArraySet<Integer> mEventRecord = new ArraySet<Integer>(); 202 203 @Override 204 public void onVehicleNetworkEvents(VehiclePropValues values) { 205 for (VehiclePropValue value : values.getValuesList()) { 206 Log.i(TAG, "event " + VehicleNetworkProtoUtil.VehiclePropValueToString(value)); 207 synchronized (this) { 208 mEventRecord.add(value.getProp()); 209 notifyAll(); 210 } 211 } 212 } 213 214 @Override 215 public void onHalError(int errorCode, int property, int operation) { 216 // TODO Auto-generated method stub 217 } 218 219 @Override 220 public void onHalRestart(boolean inMocking) { 221 // TODO Auto-generated method stub 222 } 223 224 private synchronized boolean waitForEvent(Integer prop, long timeoutMs) 225 throws InterruptedException { 226 long now = SystemClock.elapsedRealtime(); 227 long end = now + timeoutMs; 228 long timeToWait = end - now; 229 while (timeToWait > 0 && !mEventRecord.contains(prop)) { 230 wait(timeToWait); 231 timeToWait = end - SystemClock.elapsedRealtime(); 232 } 233 return mEventRecord.contains(prop); 234 } 235 236 private synchronized void resetEventRecord() { 237 mEventRecord.clear(); 238 } 239 240 private synchronized int getActiveEventsCount() { 241 return mEventRecord.size(); 242 } 243 } 244 } 245