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
17package com.android.support.car.apitest;
18
19import android.os.Looper;
20import android.support.car.Car;
21import android.support.car.CarConnectionCallback;
22import android.support.car.hardware.CarSensorEvent;
23import android.support.car.hardware.CarSensorManager;
24import android.test.AndroidTestCase;
25import android.test.suitebuilder.annotation.MediumTest;
26
27import java.lang.reflect.Field;
28import java.util.HashMap;
29import java.util.LinkedList;
30import java.util.List;
31import java.util.Map;
32import java.util.concurrent.Semaphore;
33import java.util.concurrent.TimeUnit;
34
35@MediumTest
36public class CarSensorManagerTest extends AndroidTestCase {
37    private static final long DEFAULT_WAIT_TIMEOUT_MS = 3000;
38
39    private final Semaphore mConnectionWait = new Semaphore(0);
40
41    private Car mCar;
42    private CarSensorManager mCarSensorManager;
43
44    private final CarConnectionCallback mConnectionCallbacks =
45            new CarConnectionCallback() {
46        @Override
47        public void onDisconnected(Car car) {
48            assertMainThread();
49        }
50
51        @Override
52        public void onConnected(Car car) {
53            assertMainThread();
54            mConnectionWait.release();
55        }
56    };
57
58    private void assertMainThread() {
59        assertTrue(Looper.getMainLooper().isCurrentThread());
60    }
61    private void waitForConnection(long timeoutMs) throws InterruptedException {
62        mConnectionWait.tryAcquire(timeoutMs, TimeUnit.MILLISECONDS);
63    }
64
65    @Override
66    protected void setUp() throws Exception {
67        super.setUp();
68        mCar = Car.createCar(getContext(), mConnectionCallbacks);
69        mCar.connect();
70        waitForConnection(DEFAULT_WAIT_TIMEOUT_MS);
71        mCarSensorManager =
72                (CarSensorManager) mCar.getCarManager(Car.SENSOR_SERVICE);
73    }
74
75    @Override
76    protected void tearDown() throws Exception {
77        super.tearDown();
78        mCar.disconnect();
79    }
80
81    public void testDrivingPolicy() throws Exception {
82        int[] supportedSensors = mCarSensorManager.getSupportedSensors();
83        assertNotNull(supportedSensors);
84        boolean found = false;
85        for (int sensor: supportedSensors) {
86            if (sensor == CarSensorManager.SENSOR_TYPE_DRIVING_STATUS) {
87                found = true;
88                break;
89            }
90        }
91        assertTrue(found);
92        assertTrue(mCarSensorManager.isSensorSupported(
93                CarSensorManager.SENSOR_TYPE_DRIVING_STATUS));
94        CarSensorEvent lastEvent = mCarSensorManager.getLatestSensorEvent(
95                CarSensorManager.SENSOR_TYPE_DRIVING_STATUS);
96        assertNotNull(lastEvent);
97    }
98
99    public void testSensorType() throws Exception {
100        List<Field> androidCarAllIntMembers = TestUtil.getAllPublicStaticFinalMembers(
101                android.car.hardware.CarSensorManager.class, int.class);
102        List<Field> supportCarAllIntMembers = TestUtil.getAllPublicStaticFinalMembers(
103                android.support.car.hardware.CarSensorManager.class, int.class);
104        List<Field> androidCarSensorTypes = filterSensorTypes(androidCarAllIntMembers);
105        List<Field> supportCarSensorTypes = filterSensorTypes(supportCarAllIntMembers);
106        Map<Integer, Field> androidCarSensorTypeToField = new HashMap<>();
107        for (Field androidCarSensorType : androidCarSensorTypes) {
108            androidCarSensorTypeToField.put(androidCarSensorType.getInt(null),
109                    androidCarSensorType);
110        }
111        StringBuilder builder = new StringBuilder();
112        boolean failed = false;
113        for (Field supportCarSensorType : supportCarSensorTypes) {
114            Field androidCarSensorType = androidCarSensorTypeToField.get(
115                    supportCarSensorType.getInt(null));
116            assertNotNull("Sensor type:" + supportCarSensorType.getName() +
117                    " not defined in android.car", androidCarSensorType);
118            if (supportCarSensorType.getName().equals(androidCarSensorType.getName())) {
119                // match ok
120            } else if (androidCarSensorType.getName().startsWith("SENSOR_TYPE_RESERVED")) {
121                // not used in android.car, ok
122            } else if (supportCarSensorType.getName().startsWith("SENSOR_TYPE_RESERVED")) {
123                // used in android.car but reserved in support.car
124            } else {
125                failed = true;
126                builder.append("android.support sensor has name:" + supportCarSensorType.getName() +
127                        " while android.car sensor has name:" + androidCarSensorType.getName() +
128                        "\n");
129            }
130            androidCarSensorTypeToField.remove(supportCarSensorType.getInt(null));
131        }
132        assertFalse(builder.toString(), failed);
133        assertTrue("android Car sensor has additional types defined:" + androidCarSensorTypeToField,
134                androidCarSensorTypeToField.size() == 0);
135    }
136
137    public void testSensorRate() throws Exception {
138        List<Field> androidCarAllIntMembers = TestUtil.getAllPublicStaticFinalMembers(
139                android.car.hardware.CarSensorManager.class, int.class);
140        List<Field> supportCarAllIntMembers = TestUtil.getAllPublicStaticFinalMembers(
141                android.support.car.hardware.CarSensorManager.class, int.class);
142        List<Field> androidCarSensorRates = filterSensorRates(androidCarAllIntMembers);
143        List<Field> supportCarSensorRates = filterSensorRates(supportCarAllIntMembers);
144        Map<Integer, Field> androidCarSensorRateToField = new HashMap<>();
145        for (Field androidCarSensorRate : androidCarSensorRates) {
146            androidCarSensorRateToField.put(androidCarSensorRate.getInt(null),
147                    androidCarSensorRate);
148        }
149        StringBuilder builder = new StringBuilder();
150        boolean failed = false;
151        for (Field supprotCarSensorRate : supportCarSensorRates) {
152            Field androidCarSensorRate = androidCarSensorRateToField.get(
153                    supprotCarSensorRate.getInt(null));
154            assertNotNull("Sensor rate:" + supprotCarSensorRate.getName() +
155                    " not defined in android.car", androidCarSensorRate);
156            if (supprotCarSensorRate.getName().equals(androidCarSensorRate.getName())) {
157                // match ok
158            } else {
159                failed = true;
160                builder.append("android.support sensor rate has name:" +
161                        supprotCarSensorRate.getName() +
162                        " while android.car sensor rate has name:" +
163                        androidCarSensorRate.getName());
164            }
165            androidCarSensorRateToField.remove(supprotCarSensorRate.getInt(null));
166        }
167        assertFalse(builder.toString(), failed);
168        assertTrue("android Car sensor has additional rates defined:" + androidCarSensorRateToField,
169                androidCarSensorRateToField.size() == 0);
170    }
171
172    private List<Field> filterSensorTypes(List<Field> fields) {
173        return filterFields(fields, "SENSOR_TYPE_");
174    }
175
176    private List<Field> filterSensorRates(List<Field> fields) {
177        return filterFields(fields, "SENSOR_RATE_");
178    }
179
180    private List<Field> filterFields(List<Field> fields, String prefix) {
181        List<Field> result = new LinkedList<>();
182        for (Field f : fields) {
183            if (f.getName().startsWith(prefix)) {
184                result.add(f);
185            }
186        }
187        return result;
188    }
189}
190