blob: 48840b784dc923338d30bbce4897bbce3edee121 [file] [log] [blame]
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -08001/*
2 * Copyright (C) 2018 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.car;
18
19import android.annotation.Nullable;
Yao, Yuxinge32b3f62019-05-22 12:36:24 -070020import android.car.Car;
Ram Periathiruvadif6381fb2018-06-05 18:44:19 -070021import android.car.VehicleAreaType;
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -080022import android.car.drivingstate.CarDrivingStateEvent;
23import android.car.drivingstate.CarDrivingStateEvent.CarDrivingState;
24import android.car.drivingstate.ICarDrivingState;
25import android.car.drivingstate.ICarDrivingStateChangeListener;
Steve Paik4d257022018-04-27 13:28:31 -070026import android.car.hardware.CarPropertyConfig;
27import android.car.hardware.CarPropertyValue;
28import android.car.hardware.property.CarPropertyEvent;
29import android.car.hardware.property.ICarPropertyEventListener;
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -080030import android.content.Context;
Steve Paik4d257022018-04-27 13:28:31 -070031import android.hardware.automotive.vehicle.V2_0.VehicleGear;
32import android.hardware.automotive.vehicle.V2_0.VehicleProperty;
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -080033import android.os.IBinder;
34import android.os.RemoteException;
35import android.os.SystemClock;
36import android.util.Log;
37
38import java.io.PrintWriter;
39import java.util.ArrayList;
Ram Periathiruvadi22c0d682018-05-10 17:50:48 -070040import java.util.LinkedList;
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -080041import java.util.List;
42
43/**
Steve Paik4d257022018-04-27 13:28:31 -070044 * A service that infers the current driving state of the vehicle. It computes the driving state
45 * from listening to relevant properties from {@link CarPropertyService}
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -080046 */
47public class CarDrivingStateService extends ICarDrivingState.Stub implements CarServiceBase {
48 private static final String TAG = "CarDrivingState";
49 private static final boolean DBG = false;
Ram Periathiruvadi22c0d682018-05-10 17:50:48 -070050 private static final int MAX_TRANSITION_LOG_SIZE = 20;
Steve Paik4d257022018-04-27 13:28:31 -070051 private static final int PROPERTY_UPDATE_RATE = 5; // Update rate in Hz
52 private static final int NOT_RECEIVED = -1;
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -080053 private final Context mContext;
Steve Paik4d257022018-04-27 13:28:31 -070054 private CarPropertyService mPropertyService;
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -080055 // List of clients listening to driving state events.
Steve Paik4d257022018-04-27 13:28:31 -070056 private final List<DrivingStateClient> mDrivingStateClients = new ArrayList<>();
57 // Array of properties that the service needs to listen to from CarPropertyService for deriving
Ram Periathiruvadif6381fb2018-06-05 18:44:19 -070058 // the driving state.
Steve Paik4d257022018-04-27 13:28:31 -070059 private static final int[] REQUIRED_PROPERTIES = {
60 VehicleProperty.PERF_VEHICLE_SPEED,
Ram Periathiruvadif6381fb2018-06-05 18:44:19 -070061 VehicleProperty.GEAR_SELECTION,
62 VehicleProperty.PARKING_BRAKE_ON};
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -080063 private CarDrivingStateEvent mCurrentDrivingState;
Ram Periathiruvadi22c0d682018-05-10 17:50:48 -070064 // For dumpsys logging
65 private final LinkedList<Utils.TransitionLog> mTransitionLogs = new LinkedList<>();
Steve Paik4d257022018-04-27 13:28:31 -070066 private int mLastGear;
67 private long mLastGearTimestamp = NOT_RECEIVED;
68 private float mLastSpeed;
69 private long mLastSpeedTimestamp = NOT_RECEIVED;
Ram Periathiruvadif6381fb2018-06-05 18:44:19 -070070 private boolean mLastParkingBrakeState;
71 private long mLastParkingBrakeTimestamp = NOT_RECEIVED;
72 private List<Integer> mSupportedGears;
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -080073
Steve Paik4d257022018-04-27 13:28:31 -070074 public CarDrivingStateService(Context context, CarPropertyService propertyService) {
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -080075 mContext = context;
Steve Paik4d257022018-04-27 13:28:31 -070076 mPropertyService = propertyService;
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -080077 mCurrentDrivingState = createDrivingStateEvent(CarDrivingStateEvent.DRIVING_STATE_UNKNOWN);
78 }
79
80 @Override
Ram Periathiruvadif6381fb2018-06-05 18:44:19 -070081 public synchronized void init() {
Steve Paik4d257022018-04-27 13:28:31 -070082 if (!checkPropertySupport()) {
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -080083 Log.e(TAG, "init failure. Driving state will always be fully restrictive");
84 return;
85 }
Steve Paik4d257022018-04-27 13:28:31 -070086 subscribeToProperties();
Ram Periathiruvadif6381fb2018-06-05 18:44:19 -070087 mCurrentDrivingState = createDrivingStateEvent(inferDrivingStateLocked());
88 addTransitionLog(TAG + " Boot", CarDrivingStateEvent.DRIVING_STATE_UNKNOWN,
89 mCurrentDrivingState.eventValue, mCurrentDrivingState.timeStamp);
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -080090 }
91
92 @Override
93 public synchronized void release() {
Steve Paik4d257022018-04-27 13:28:31 -070094 for (int property : REQUIRED_PROPERTIES) {
95 mPropertyService.unregisterListener(property, mICarPropertyEventListener);
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -080096 }
Steve Paik4d257022018-04-27 13:28:31 -070097 for (DrivingStateClient client : mDrivingStateClients) {
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -080098 client.listenerBinder.unlinkToDeath(client, 0);
99 }
Steve Paik4d257022018-04-27 13:28:31 -0700100 mDrivingStateClients.clear();
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -0800101 mCurrentDrivingState = createDrivingStateEvent(CarDrivingStateEvent.DRIVING_STATE_UNKNOWN);
102 }
103
104 /**
Steve Paik4d257022018-04-27 13:28:31 -0700105 * Checks if the {@link CarPropertyService} supports the required properties.
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -0800106 *
107 * @return {@code true} if supported, {@code false} if not
108 */
Steve Paik4d257022018-04-27 13:28:31 -0700109 private synchronized boolean checkPropertySupport() {
110 List<CarPropertyConfig> configs = mPropertyService.getPropertyList();
111 for (int propertyId : REQUIRED_PROPERTIES) {
112 boolean found = false;
113 for (CarPropertyConfig config : configs) {
114 if (config.getPropertyId() == propertyId) {
115 found = true;
116 break;
117 }
118 }
119 if (!found) {
120 Log.e(TAG, "Required property not supported: " + propertyId);
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -0800121 return false;
122 }
123 }
124 return true;
125 }
126
127 /**
Steve Paik4d257022018-04-27 13:28:31 -0700128 * Subscribe to the {@link CarPropertyService} for required sensors.
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -0800129 */
Steve Paik4d257022018-04-27 13:28:31 -0700130 private synchronized void subscribeToProperties() {
131 for (int propertyId : REQUIRED_PROPERTIES) {
132 mPropertyService.registerListener(propertyId, PROPERTY_UPDATE_RATE,
133 mICarPropertyEventListener);
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -0800134 }
135
136 }
137
138 // Binder methods
139
140 /**
141 * Register a {@link ICarDrivingStateChangeListener} to be notified for changes to the driving
142 * state.
143 *
144 * @param listener {@link ICarDrivingStateChangeListener}
145 */
146 @Override
147 public synchronized void registerDrivingStateChangeListener(
148 ICarDrivingStateChangeListener listener) {
149 if (listener == null) {
150 if (DBG) {
151 Log.e(TAG, "registerDrivingStateChangeListener(): listener null");
152 }
153 throw new IllegalArgumentException("Listener is null");
154 }
155 // If a new client is registering, create a new DrivingStateClient and add it to the list
156 // of listening clients.
157 DrivingStateClient client = findDrivingStateClientLocked(listener);
158 if (client == null) {
159 client = new DrivingStateClient(listener);
160 try {
161 listener.asBinder().linkToDeath(client, 0);
162 } catch (RemoteException e) {
163 Log.e(TAG, "Cannot link death recipient to binder " + e);
164 return;
165 }
Steve Paik4d257022018-04-27 13:28:31 -0700166 mDrivingStateClients.add(client);
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -0800167 }
168 }
169
170 /**
171 * Iterates through the list of registered Driving State Change clients -
172 * {@link DrivingStateClient} and finds if the given client is already registered.
173 *
174 * @param listener Listener to look for.
175 * @return the {@link DrivingStateClient} if found, null if not
176 */
177 @Nullable
178 private DrivingStateClient findDrivingStateClientLocked(
179 ICarDrivingStateChangeListener listener) {
180 IBinder binder = listener.asBinder();
181 // Find the listener by comparing the binder object they host.
Steve Paik4d257022018-04-27 13:28:31 -0700182 for (DrivingStateClient client : mDrivingStateClients) {
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -0800183 if (client.isHoldingBinder(binder)) {
184 return client;
185 }
186 }
187 return null;
188 }
189
190 /**
191 * Unregister the given Driving State Change listener
192 *
193 * @param listener client to unregister
194 */
195 @Override
196 public synchronized void unregisterDrivingStateChangeListener(
197 ICarDrivingStateChangeListener listener) {
198 if (listener == null) {
199 Log.e(TAG, "unregisterDrivingStateChangeListener(): listener null");
200 throw new IllegalArgumentException("Listener is null");
201 }
202
203 DrivingStateClient client = findDrivingStateClientLocked(listener);
204 if (client == null) {
205 Log.e(TAG, "unregisterDrivingStateChangeListener(): listener was not previously "
206 + "registered");
207 return;
208 }
209 listener.asBinder().unlinkToDeath(client, 0);
Steve Paik4d257022018-04-27 13:28:31 -0700210 mDrivingStateClients.remove(client);
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -0800211 }
212
213 /**
214 * Gets the current driving state
215 *
216 * @return {@link CarDrivingStateEvent} for the given event type
217 */
218 @Override
219 @Nullable
220 public synchronized CarDrivingStateEvent getCurrentDrivingState() {
221 return mCurrentDrivingState;
222 }
223
Yao, Yuxinge32b3f62019-05-22 12:36:24 -0700224 @Override
225 public synchronized void injectDrivingState(CarDrivingStateEvent event) {
226 ICarImpl.assertPermission(mContext, Car.PERMISSION_CONTROL_APP_BLOCKING);
227
228 for (DrivingStateClient client : mDrivingStateClients) {
229 client.dispatchEventToClients(event);
230 }
231 }
232
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -0800233 /**
234 * Class that holds onto client related information - listener interface, process that hosts the
235 * binder object etc.
236 * <p>
237 * It also registers for death notifications of the host.
238 */
239 private class DrivingStateClient implements IBinder.DeathRecipient {
240 private final IBinder listenerBinder;
241 private final ICarDrivingStateChangeListener listener;
242
243 public DrivingStateClient(ICarDrivingStateChangeListener l) {
244 listener = l;
245 listenerBinder = l.asBinder();
246 }
247
248 @Override
249 public void binderDied() {
250 if (DBG) {
251 Log.d(TAG, "Binder died " + listenerBinder);
252 }
253 listenerBinder.unlinkToDeath(this, 0);
254 synchronized (CarDrivingStateService.this) {
Steve Paik4d257022018-04-27 13:28:31 -0700255 mDrivingStateClients.remove(this);
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -0800256 }
257 }
258
259 /**
260 * Returns if the given binder object matches to what this client info holds.
261 * Used to check if the listener asking to be registered is already registered.
262 *
263 * @return true if matches, false if not
264 */
265 public boolean isHoldingBinder(IBinder binder) {
266 return listenerBinder == binder;
267 }
268
269 /**
270 * Dispatch the events to the listener
271 *
272 * @param event {@link CarDrivingStateEvent}.
273 */
274 public void dispatchEventToClients(CarDrivingStateEvent event) {
275 if (event == null) {
276 return;
277 }
278 try {
279 listener.onDrivingStateChanged(event);
280 } catch (RemoteException e) {
281 if (DBG) {
282 Log.d(TAG, "Dispatch to listener failed");
283 }
284 }
285 }
286 }
287
288 @Override
289 public void dump(PrintWriter writer) {
Ram Periathiruvadif6381fb2018-06-05 18:44:19 -0700290 writer.println("Driving state change log:");
Ram Periathiruvadi22c0d682018-05-10 17:50:48 -0700291 for (Utils.TransitionLog tLog : mTransitionLogs) {
292 writer.println(tLog);
293 }
294 writer.println("Current Driving State: " + mCurrentDrivingState.eventValue);
Ram Periathiruvadif6381fb2018-06-05 18:44:19 -0700295 if (mSupportedGears != null) {
296 writer.println("Supported gears:");
297 for (Integer gear : mSupportedGears) {
298 writer.print("Gear:" + gear);
299 }
300 }
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -0800301 }
302
303 /**
Steve Paik4d257022018-04-27 13:28:31 -0700304 * {@link CarPropertyEvent} listener registered with the {@link CarPropertyService} for getting
305 * property change notifications.
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -0800306 */
Steve Paik4d257022018-04-27 13:28:31 -0700307 private final ICarPropertyEventListener mICarPropertyEventListener =
308 new ICarPropertyEventListener.Stub() {
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -0800309 @Override
Steve Paik4d257022018-04-27 13:28:31 -0700310 public void onEvent(List<CarPropertyEvent> events) throws RemoteException {
311 for (CarPropertyEvent event : events) {
312 handlePropertyEvent(event);
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -0800313 }
314 }
315 };
316
317 /**
Steve Paik4d257022018-04-27 13:28:31 -0700318 * Handle events coming from {@link CarPropertyService}. Compute the driving state, map it to
319 * the corresponding UX Restrictions and dispatch the events to the registered clients.
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -0800320 */
Steve Paik4d257022018-04-27 13:28:31 -0700321 private synchronized void handlePropertyEvent(CarPropertyEvent event) {
322 switch (event.getEventType()) {
323 case CarPropertyEvent.PROPERTY_EVENT_PROPERTY_CHANGE:
324 CarPropertyValue value = event.getCarPropertyValue();
325 int propId = value.getPropertyId();
326 long curTimestamp = value.getTimestamp();
327 Log.d(TAG, "Property Changed: propId=" + propId);
328 switch (propId) {
329 case VehicleProperty.PERF_VEHICLE_SPEED:
330 float curSpeed = (Float) value.getValue();
331 if (DBG) {
332 Log.d(TAG, "Speed: " + curSpeed + "@" + curTimestamp);
333 }
334 if (curTimestamp > mLastSpeedTimestamp) {
335 mLastSpeedTimestamp = curTimestamp;
336 mLastSpeed = curSpeed;
337 } else if (DBG) {
338 Log.d(TAG, "Ignoring speed with older timestamp:" + curTimestamp);
339 }
340 break;
341 case VehicleProperty.GEAR_SELECTION:
Ram Periathiruvadif6381fb2018-06-05 18:44:19 -0700342 if (mSupportedGears == null) {
343 mSupportedGears = getSupportedGears();
344 }
Steve Paik4d257022018-04-27 13:28:31 -0700345 int curGear = (Integer) value.getValue();
346 if (DBG) {
347 Log.d(TAG, "Gear: " + curGear + "@" + curTimestamp);
348 }
349 if (curTimestamp > mLastGearTimestamp) {
350 mLastGearTimestamp = curTimestamp;
351 mLastGear = (Integer) value.getValue();
352 } else if (DBG) {
353 Log.d(TAG, "Ignoring Gear with older timestamp:" + curTimestamp);
354 }
355 break;
Ram Periathiruvadif6381fb2018-06-05 18:44:19 -0700356 case VehicleProperty.PARKING_BRAKE_ON:
357 boolean curParkingBrake = (boolean) value.getValue();
358 if (DBG) {
359 Log.d(TAG, "Parking Brake: " + curParkingBrake + "@" + curTimestamp);
360 }
361 if (curTimestamp > mLastParkingBrakeTimestamp) {
362 mLastParkingBrakeTimestamp = curTimestamp;
363 mLastParkingBrakeState = curParkingBrake;
364 } else if (DBG) {
365 Log.d(TAG, "Ignoring Parking Brake status with an older timestamp:"
366 + curTimestamp);
367 }
368 break;
Steve Paik4d257022018-04-27 13:28:31 -0700369 default:
370 Log.e(TAG, "Received property event for unhandled propId=" + propId);
371 break;
372 }
373
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -0800374 int drivingState = inferDrivingStateLocked();
375 // Check if the driving state has changed. If it has, update our records and
376 // dispatch the new events to the listeners.
377 if (DBG) {
378 Log.d(TAG, "Driving state new->old " + drivingState + "->"
379 + mCurrentDrivingState.eventValue);
380 }
Steve Paik4d257022018-04-27 13:28:31 -0700381 if (drivingState != mCurrentDrivingState.eventValue) {
382 addTransitionLog(TAG, mCurrentDrivingState.eventValue, drivingState,
383 System.currentTimeMillis());
384 // Update if there is a change in state.
385 mCurrentDrivingState = createDrivingStateEvent(drivingState);
386 if (DBG) {
387 Log.d(TAG, "dispatching to " + mDrivingStateClients.size() + " clients");
388 }
389 for (DrivingStateClient client : mDrivingStateClients) {
390 client.dispatchEventToClients(mCurrentDrivingState);
391 }
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -0800392 }
393 break;
394 default:
Steve Paik4d257022018-04-27 13:28:31 -0700395 // Unhandled event
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -0800396 break;
397 }
398 }
399
Ram Periathiruvadif6381fb2018-06-05 18:44:19 -0700400 private List<Integer> getSupportedGears() {
401 List<CarPropertyConfig> properyList = mPropertyService.getPropertyList();
402 for (CarPropertyConfig p : properyList) {
403 if (p.getPropertyId() == VehicleProperty.GEAR_SELECTION) {
404 return p.getConfigArray();
405 }
406 }
407 return null;
408 }
409
Ram Periathiruvadi22c0d682018-05-10 17:50:48 -0700410 private void addTransitionLog(String name, int from, int to, long timestamp) {
411 if (mTransitionLogs.size() >= MAX_TRANSITION_LOG_SIZE) {
412 mTransitionLogs.remove();
413 }
414
415 Utils.TransitionLog tLog = new Utils.TransitionLog(name, from, to, timestamp);
416 mTransitionLogs.add(tLog);
417 }
418
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -0800419 /**
420 * Infers the current driving state of the car from the other Car Sensor properties like
421 * Current Gear, Speed etc.
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -0800422 *
423 * @return Current driving state
424 */
425 @CarDrivingState
426 private int inferDrivingStateLocked() {
Ram Periathiruvadif6381fb2018-06-05 18:44:19 -0700427 updateVehiclePropertiesIfNeeded();
Steve Paik4d257022018-04-27 13:28:31 -0700428 if (DBG) {
429 Log.d(TAG, "Last known Gear:" + mLastGear + " Last known speed:" + mLastSpeed);
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -0800430 }
Ram Periathiruvadif6381fb2018-06-05 18:44:19 -0700431
432 /*
433 Logic to start off deriving driving state:
434 1. If gear == parked, then Driving State is parked.
435 2. If gear != parked,
436 2a. if parking brake is applied, then Driving state is parked.
437 2b. if parking brake is not applied or unknown/unavailable, then driving state
438 is still unknown.
439 3. If driving state is unknown at the end of step 2,
440 3a. if speed == 0, then driving state is idling
441 3b. if speed != 0, then driving state is moving
442 3c. if speed unavailable, then driving state is unknown
443 */
444
445 if (isVehicleKnownToBeParked()) {
Steve Paik4d257022018-04-27 13:28:31 -0700446 return CarDrivingStateEvent.DRIVING_STATE_PARKED;
447 }
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -0800448
Ram Periathiruvadif6381fb2018-06-05 18:44:19 -0700449 // We don't know if the vehicle is parked, let's look at the speed.
450 if (mLastSpeedTimestamp == NOT_RECEIVED || mLastSpeed < 0) {
Steve Paik4d257022018-04-27 13:28:31 -0700451 return CarDrivingStateEvent.DRIVING_STATE_UNKNOWN;
452 } else if (mLastSpeed == 0f) {
453 return CarDrivingStateEvent.DRIVING_STATE_IDLING;
454 } else {
455 return CarDrivingStateEvent.DRIVING_STATE_MOVING;
456 }
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -0800457 }
458
Ram Periathiruvadif6381fb2018-06-05 18:44:19 -0700459 /**
460 * Find if we have signals to know if the vehicle is parked
461 *
462 * @return true if we have enough information to say the vehicle is parked.
463 * false, if the vehicle is either not parked or if we don't have any information.
464 */
465 private boolean isVehicleKnownToBeParked() {
466 // If we know the gear is in park, return true
467 if (mLastGearTimestamp != NOT_RECEIVED && mLastGear == VehicleGear.GEAR_PARK) {
468 return true;
469 } else if (mLastParkingBrakeTimestamp != NOT_RECEIVED) {
470 // if gear is not in park or unknown, look for status of parking brake if transmission
471 // type is manual.
472 if (isCarManualTransmissionType()) {
473 return mLastParkingBrakeState;
474 }
475 }
476 // if neither information is available, return false to indicate we can't determine
477 // if the vehicle is parked.
478 return false;
479 }
480
481 /**
482 * If Supported gears information is available and GEAR_PARK is not one of the supported gears,
483 * transmission type is considered to be Manual. Automatic transmission is assumed otherwise.
484 */
485 private boolean isCarManualTransmissionType() {
486 if (mSupportedGears != null
487 && !mSupportedGears.isEmpty()
488 && !mSupportedGears.contains(VehicleGear.GEAR_PARK)) {
489 return true;
490 }
491 return false;
492 }
493
494 /**
495 * Try querying the gear selection and parking brake if we haven't received the event yet.
496 * This could happen if the gear change occurred before car service booted up like in the
497 * case of a HU restart in the middle of a drive. Since gear and parking brake are
498 * on-change only properties, we could be in this situation where we will have to query
499 * VHAL.
500 */
501 private void updateVehiclePropertiesIfNeeded() {
502 if (mLastGearTimestamp == NOT_RECEIVED) {
503 CarPropertyValue propertyValue = mPropertyService.getProperty(
504 VehicleProperty.GEAR_SELECTION,
505 VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL);
506 if (propertyValue != null) {
507 mLastGear = (Integer) propertyValue.getValue();
508 mLastGearTimestamp = propertyValue.getTimestamp();
509 if (DBG) {
510 Log.d(TAG, "updateVehiclePropertiesIfNeeded: gear:" + mLastGear);
511 }
512 }
513 }
514
515 if (mLastParkingBrakeTimestamp == NOT_RECEIVED) {
516 CarPropertyValue propertyValue = mPropertyService.getProperty(
517 VehicleProperty.PARKING_BRAKE_ON,
518 VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL);
519 if (propertyValue != null) {
520 mLastParkingBrakeState = (boolean) propertyValue.getValue();
521 mLastParkingBrakeTimestamp = propertyValue.getTimestamp();
522 if (DBG) {
523 Log.d(TAG, "updateVehiclePropertiesIfNeeded: brake:" + mLastParkingBrakeState);
524 }
525 }
526 }
527
528 if (mLastSpeedTimestamp == NOT_RECEIVED) {
529 CarPropertyValue propertyValue = mPropertyService.getProperty(
530 VehicleProperty.PERF_VEHICLE_SPEED,
531 VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL);
532 if (propertyValue != null) {
533 mLastSpeed = (float) propertyValue.getValue();
534 mLastSpeedTimestamp = propertyValue.getTimestamp();
535 if (DBG) {
536 Log.d(TAG, "updateVehiclePropertiesIfNeeded: speed:" + mLastSpeed);
537 }
538 }
539 }
540 }
541
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -0800542 private static CarDrivingStateEvent createDrivingStateEvent(int eventValue) {
543 return new CarDrivingStateEvent(eventValue, SystemClock.elapsedRealtimeNanos());
544 }
Ram Periathiruvadi22c0d682018-05-10 17:50:48 -0700545
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -0800546}