CarEmulator.java revision 57787b006b4b4967bc1e390c672e34150a603e7a
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.google.android.car.kitchensink;
18
19import android.car.Car;
20import android.car.test.VehicleHalEmulator.VehicleHalPropertyHandler;
21import android.car.test.VehicleHalEmulator;
22import android.os.SystemClock;
23import android.util.SparseIntArray;
24import android.view.KeyEvent;
25
26import com.android.car.vehiclenetwork.VehicleNetworkConsts;
27import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleAudioFocusIndex;
28import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleAudioFocusRequest;
29import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleAudioFocusState;
30import com.android.car.vehiclenetwork.VehiclePropConfigUtil;
31import com.android.car.vehiclenetwork.VehiclePropValueUtil;
32import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehiclePermissionModel;
33import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehiclePropAccess;
34import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehiclePropChangeMode;
35import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType;
36import com.android.car.vehiclenetwork.VehicleNetworkProto.VehiclePropValue;
37
38import java.util.ArrayList;
39import java.util.List;
40
41public class CarEmulator {
42
43    private final Car mCar;
44    private final VehicleHalEmulator mHalEmulator;
45
46    private final AudioFocusPropertyHandler mAudioFocusPropertyHandler =
47            new AudioFocusPropertyHandler();
48    private final AudioStreamStatePropertyHandler mAudioStreamStatePropertyHandler =
49            new AudioStreamStatePropertyHandler();
50    private final AudioVolumeLimitPropertyHandler mAudioVolumeLimitPropertyHandler =
51            new AudioVolumeLimitPropertyHandler();
52    private final SingleChannelVolumeHandler mVolumeHandler;
53    private static final int STREAM_COUNT = 2;
54    private static final int[] STREAM_MAX_VOLUME = {30, 30};
55    private static final int[] STREAM_MIN_VOLUME = {0, 0};
56
57    public CarEmulator(Car car) {
58        mCar = car;
59        mHalEmulator = new VehicleHalEmulator(car);
60        List<Integer> maxVols = new ArrayList<>();
61        List<Integer> minVols = new ArrayList<>();
62        for(int i = 0; i < STREAM_COUNT; i++) {
63            maxVols.add(STREAM_MAX_VOLUME[i]);
64            minVols.add(STREAM_MIN_VOLUME[i]);
65        }
66        mVolumeHandler = new SingleChannelVolumeHandler(minVols, maxVols);
67        int zones = (1<<maxVols.size()) - 1;
68
69        mHalEmulator.addProperty(
70                VehiclePropConfigUtil.getBuilder(
71                        VehicleNetworkConsts.VEHICLE_PROPERTY_AUDIO_FOCUS,
72                        VehiclePropAccess.VEHICLE_PROP_ACCESS_READ_WRITE,
73                        VehiclePropChangeMode.VEHICLE_PROP_CHANGE_MODE_ON_CHANGE,
74                        VehicleValueType.VEHICLE_VALUE_TYPE_INT32_VEC4,
75                        VehiclePermissionModel.VEHICLE_PERMISSION_SYSTEM_APP_ONLY,
76                        0 /*configFlags*/, 0 /*sampleRateMax*/, 0 /*sampleRateMin*/).build(),
77                mAudioFocusPropertyHandler);
78        mHalEmulator.addProperty(
79                VehiclePropConfigUtil.getBuilder(
80                        VehicleNetworkConsts.VEHICLE_PROPERTY_INTERNAL_AUDIO_STREAM_STATE,
81                        VehiclePropAccess.VEHICLE_PROP_ACCESS_READ_WRITE,
82                        VehiclePropChangeMode.VEHICLE_PROP_CHANGE_MODE_ON_CHANGE,
83                        VehicleValueType.VEHICLE_VALUE_TYPE_INT32_VEC2,
84                        VehiclePermissionModel.VEHICLE_PERMISSION_SYSTEM_APP_ONLY,
85                        0 /*configFlags*/, 0 /*sampleRateMax*/, 0 /*sampleRateMin*/).build(),
86                        mAudioStreamStatePropertyHandler);
87        mHalEmulator.addProperty(
88                VehiclePropConfigUtil.getBuilder(VehicleNetworkConsts.VEHICLE_PROPERTY_AUDIO_VOLUME,
89                        VehiclePropAccess.VEHICLE_PROP_ACCESS_READ_WRITE,
90                        VehiclePropChangeMode.VEHICLE_PROP_CHANGE_MODE_ON_CHANGE,
91                        VehicleValueType.VEHICLE_VALUE_TYPE_INT32_VEC3,
92                        VehiclePermissionModel.VEHICLE_PERMISSION_SYSTEM_APP_ONLY,
93                        0 /*configFlags*/, 0 /*sampleRateMax*/, 0 /*sampleRateMin*/,
94                        maxVols, minVols).setZones(zones).build(),
95                mVolumeHandler);
96        mHalEmulator.addProperty(
97                VehiclePropConfigUtil.getBuilder(
98                        VehicleNetworkConsts.VEHICLE_PROPERTY_AUDIO_VOLUME_LIMIT,
99                        VehiclePropAccess.VEHICLE_PROP_ACCESS_READ_WRITE,
100                        VehiclePropChangeMode.VEHICLE_PROP_CHANGE_MODE_ON_CHANGE,
101                        VehicleValueType.VEHICLE_VALUE_TYPE_INT32_VEC2,
102                        VehiclePermissionModel.VEHICLE_PERMISSION_SYSTEM_APP_ONLY,
103                        0 /*configFlags*/, 0 /*sampleRateMax*/, 0 /*sampleRateMin*/).build(),
104                mAudioVolumeLimitPropertyHandler);
105
106        mHalEmulator.addProperty(
107                VehiclePropConfigUtil.getBuilder(
108                        VehicleNetworkConsts.VEHICLE_PROPERTY_HW_KEY_INPUT,
109                        VehiclePropAccess.VEHICLE_PROP_ACCESS_READ,
110                        VehiclePropChangeMode.VEHICLE_PROP_CHANGE_MODE_ON_CHANGE,
111                        VehicleValueType.VEHICLE_VALUE_TYPE_INT32_VEC4,
112                        VehiclePermissionModel.VEHICLE_PERMISSION_SYSTEM_APP_ONLY,
113                        0 /*configFlags*/, 0 /*sampleRateMax*/, 0 /*sampleRateMin*/).build(),
114                mHWKeyHandler);
115    }
116
117    public void start() {
118        mHalEmulator.start();
119    }
120
121    public void stop() {
122        mHalEmulator.stop();
123    }
124
125    public void setAudioFocusControl(boolean reject) {
126        mAudioFocusPropertyHandler.setAudioFocusControl(reject);
127    }
128
129    public void injectVolumeKey(boolean volUp) {
130        int[] values = {
131                VehicleNetworkConsts.VehicleHwKeyInputAction.VEHICLE_HW_KEY_INPUT_ACTION_DOWN,
132                volUp ? KeyEvent.KEYCODE_VOLUME_UP : KeyEvent.KEYCODE_VOLUME_DOWN, 0, 0 };
133
134        VehiclePropValue injectValue = VehiclePropValueUtil.createIntVectorValue(
135                VehicleNetworkConsts.VEHICLE_PROPERTY_HW_KEY_INPUT, values,
136                SystemClock.elapsedRealtimeNanos());
137
138        mHalEmulator.injectEvent(injectValue);
139
140        int[] upValues = {
141                VehicleNetworkConsts.VehicleHwKeyInputAction.VEHICLE_HW_KEY_INPUT_ACTION_UP,
142                volUp ? KeyEvent.KEYCODE_VOLUME_UP : KeyEvent.KEYCODE_VOLUME_DOWN, 0, 0 };
143
144        injectValue = VehiclePropValueUtil.createIntVectorValue(
145                VehicleNetworkConsts.VEHICLE_PROPERTY_HW_KEY_INPUT, upValues,
146                SystemClock.elapsedRealtimeNanos());
147
148        mHalEmulator.injectEvent(injectValue);
149    }
150
151    private final VehicleHalEmulator.VehicleHalPropertyHandler mHWKeyHandler =
152            new VehicleHalEmulator.VehicleHalPropertyHandler() {
153                @Override
154                public void onPropertySet(VehiclePropValue value) {
155                }
156
157                @Override
158                public VehiclePropValue onPropertyGet(VehiclePropValue value) {
159                    int[] values = {0, 0, 0, 0 };
160                    return VehiclePropValueUtil.createIntVectorValue(
161                            VehicleNetworkConsts.VEHICLE_PROPERTY_HW_KEY_INPUT, values,
162                            SystemClock.elapsedRealtimeNanos());
163                }
164
165                @Override
166                public void onPropertySubscribe(int property, float sampleRate, int zones) {
167                }
168
169                @Override
170                public void onPropertyUnsubscribe(int property) {
171                }
172            };
173
174    private class AudioFocusPropertyHandler implements VehicleHalPropertyHandler {
175        private boolean mRejectFocus;
176        private int mCurrentFocusState = VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_LOSS;
177        private int mCurrentFocusStreams = 0;
178        private int mCurrentFocusExtState = 0;
179
180        public void setAudioFocusControl(boolean reject) {
181            VehiclePropValue injectValue = null;
182            synchronized (this) {
183                if (reject) {
184                    if (!mRejectFocus) {
185                        mCurrentFocusState = VehicleAudioFocusState
186                                .VEHICLE_AUDIO_FOCUS_STATE_LOSS_TRANSIENT_EXLCUSIVE;
187                        mCurrentFocusStreams = 0;
188                        mCurrentFocusExtState = 0;
189                        mRejectFocus = true;
190                        int[] values = { mCurrentFocusState, mCurrentFocusStreams,
191                                mCurrentFocusExtState, 0};
192                        injectValue = VehiclePropValueUtil.createIntVectorValue(
193                                VehicleNetworkConsts.VEHICLE_PROPERTY_AUDIO_FOCUS, values,
194                                SystemClock.elapsedRealtimeNanos());
195                    }
196                } else {
197                    if (mRejectFocus) {
198                        mCurrentFocusState = VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_LOSS;
199                        mCurrentFocusStreams = 0;
200                        mCurrentFocusExtState = 0;
201                        int[] values = { mCurrentFocusState, mCurrentFocusStreams,
202                                mCurrentFocusExtState, 0};
203                        injectValue = VehiclePropValueUtil.createIntVectorValue(
204                                VehicleNetworkConsts.VEHICLE_PROPERTY_AUDIO_FOCUS, values,
205                                SystemClock.elapsedRealtimeNanos());
206                    }
207                    mRejectFocus = false;
208                }
209            }
210            if (injectValue != null) {
211                mHalEmulator.injectEvent(injectValue);
212            }
213        }
214
215        @Override
216        public void onPropertySet(VehiclePropValue value) {
217            VehiclePropValue injectValue = null;
218            synchronized (this) {
219                if (mRejectFocus) {
220                    int[] values = { mCurrentFocusState, mCurrentFocusStreams,
221                            mCurrentFocusExtState, 0};
222                    injectValue = VehiclePropValueUtil.createIntVectorValue(
223                            VehicleNetworkConsts.VEHICLE_PROPERTY_AUDIO_FOCUS, values,
224                            SystemClock.elapsedRealtimeNanos());
225                } else {
226                    int request = value.getInt32Values(
227                            VehicleAudioFocusIndex.VEHICLE_AUDIO_FOCUS_INDEX_FOCUS);
228                    int requestedStreams = value.getInt32Values(
229                            VehicleAudioFocusIndex.VEHICLE_AUDIO_FOCUS_INDEX_STREAMS);
230                    int requestedExtFocus = value.getInt32Values(
231                            VehicleAudioFocusIndex.VEHICLE_AUDIO_FOCUS_INDEX_EXTERNAL_FOCUS_STATE);
232                    int response = VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_LOSS;
233                    switch (request) {
234                        case VehicleAudioFocusRequest.VEHICLE_AUDIO_FOCUS_REQUEST_GAIN:
235                            response = VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_GAIN;
236                            break;
237                        case VehicleAudioFocusRequest.VEHICLE_AUDIO_FOCUS_REQUEST_GAIN_TRANSIENT:
238                        case VehicleAudioFocusRequest.VEHICLE_AUDIO_FOCUS_REQUEST_GAIN_TRANSIENT_MAY_DUCK:
239                            response =
240                                VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_GAIN_TRANSIENT;
241                            break;
242                        case VehicleAudioFocusRequest.VEHICLE_AUDIO_FOCUS_REQUEST_RELEASE:
243                            response = VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_LOSS;
244                            break;
245                    }
246                    mCurrentFocusState = response;
247                    mCurrentFocusStreams = requestedStreams;
248                    mCurrentFocusExtState = requestedExtFocus;
249                    int[] values = { mCurrentFocusState, mCurrentFocusStreams,
250                            mCurrentFocusExtState, 0};
251                    injectValue = VehiclePropValueUtil.createIntVectorValue(
252                            VehicleNetworkConsts.VEHICLE_PROPERTY_AUDIO_FOCUS, values,
253                            SystemClock.elapsedRealtimeNanos());
254                }
255            }
256            if (injectValue != null) {
257                mHalEmulator.injectEvent(injectValue);
258            }
259        }
260
261        @Override
262        public synchronized VehiclePropValue onPropertyGet(VehiclePropValue value) {
263            int[] values = { mCurrentFocusState, mCurrentFocusStreams,
264                    mCurrentFocusExtState, 0};
265            return VehiclePropValueUtil.createIntVectorValue(
266                    VehicleNetworkConsts.VEHICLE_PROPERTY_AUDIO_FOCUS, values,
267                    SystemClock.elapsedRealtimeNanos());
268        }
269
270        @Override
271        public void onPropertySubscribe(int property, float sampleRate, int zones) {
272        }
273
274        @Override
275        public void onPropertyUnsubscribe(int property) {
276        }
277    }
278
279    private class AudioStreamStatePropertyHandler implements VehicleHalPropertyHandler {
280        @Override
281        public void onPropertySet(VehiclePropValue value) {
282        }
283
284        @Override
285        public VehiclePropValue onPropertyGet(VehiclePropValue value) {
286            //ignore
287            return null;
288        }
289
290        @Override
291        public void onPropertySubscribe(int property, float sampleRate, int zones) {
292        }
293
294        @Override
295        public void onPropertyUnsubscribe(int property) {
296        }
297    }
298
299    private static class AudioVolumeLimitPropertyHandler implements VehicleHalPropertyHandler {
300        @Override
301        public void onPropertySet(VehiclePropValue value) {
302        }
303
304        @Override
305        public VehiclePropValue onPropertyGet(VehiclePropValue value) {
306            int stream = value.getInt32Values(
307                    VehicleNetworkConsts.VehicleAudioVolumeLimitIndex
308                            .VEHICLE_AUDIO_VOLUME_LIMIT_INDEX_STREAM);
309
310            int[] values = {stream, 20};
311            VehiclePropValue propValue = VehiclePropValueUtil.createIntVectorValue(
312                    VehicleNetworkConsts.VEHICLE_PROPERTY_AUDIO_VOLUME_LIMIT, values,
313                    SystemClock.elapsedRealtimeNanos());
314            return propValue;
315        }
316
317        @Override
318        public void onPropertySubscribe(int property, float sampleRate, int zones) {
319        }
320
321        @Override
322        public void onPropertyUnsubscribe(int property) {
323        }
324    }
325
326    private class SingleChannelVolumeHandler implements
327            VehicleHalEmulator.VehicleHalPropertyHandler {
328        private final List<Integer> mMins;
329        private final List<Integer> mMaxs;
330        private final SparseIntArray mCurrent;
331
332        public SingleChannelVolumeHandler(List<Integer> mins, List<Integer> maxs) {
333            mMins = mins;
334            mMaxs = maxs;
335            mCurrent = new SparseIntArray(mMins.size());
336            // initialize the vol to be the min volume.
337            for (int i = 0; i < mMins.size(); i++) {
338                mCurrent.put(i, mMins.get(i));
339            }
340        }
341
342        @Override
343        public void onPropertySet(VehiclePropValue value) {
344            int stream = value.getInt32Values(
345                    VehicleNetworkConsts.VehicleAudioVolumeIndex.VEHICLE_AUDIO_VOLUME_INDEX_STREAM);
346            int volume = value.getInt32Values(
347                    VehicleNetworkConsts.VehicleAudioVolumeIndex.VEHICLE_AUDIO_VOLUME_INDEX_VOLUME);
348            int state = value.getInt32Values(
349                    VehicleNetworkConsts.VehicleAudioVolumeIndex.VEHICLE_AUDIO_VOLUME_INDEX_STATE);
350
351            int[] values = {stream, volume, state};
352            VehiclePropValue injectValue = VehiclePropValueUtil.createIntVectorValue(
353                    VehicleNetworkConsts.VEHICLE_PROPERTY_AUDIO_VOLUME, values,
354                    SystemClock.elapsedRealtimeNanos());
355            mCurrent.put(stream, volume);
356            mHalEmulator.injectEvent(injectValue);
357        }
358
359        @Override
360        public VehiclePropValue onPropertyGet(VehiclePropValue value) {
361            int stream = value.getInt32Values(
362                    VehicleNetworkConsts.VehicleAudioVolumeIndex.VEHICLE_AUDIO_VOLUME_INDEX_STREAM);
363
364            int volume = mCurrent.get(stream);
365            int[] values = {stream, volume, 0};
366            VehiclePropValue propValue = VehiclePropValueUtil.createIntVectorValue(
367                    VehicleNetworkConsts.VEHICLE_PROPERTY_AUDIO_VOLUME, values,
368                    SystemClock.elapsedRealtimeNanos());
369            return propValue;
370        }
371
372        @Override
373        public void onPropertySubscribe(int property, float sampleRate, int zones) {
374        }
375
376        @Override
377        public void onPropertyUnsubscribe(int property) {
378        }
379    }
380}
381