blob: 146dd95948c49bb8501f1ea99aacef6a6480168c [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;
Jordan Jozwiak39da9c82019-10-25 10:46:38 -070033import android.os.Handler;
34import android.os.HandlerThread;
Jordan Jozwiak05985a62020-02-27 10:58:11 -080035import android.os.RemoteCallbackList;
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -080036import android.os.RemoteException;
37import android.os.SystemClock;
Felipe Leme176a5fd2021-01-20 15:48:33 -080038import android.util.IndentingPrintWriter;
Eric Jeongbd5fb562020-12-21 13:49:40 -080039import android.util.Slog;
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -080040
Jordan Jozwiak05985a62020-02-27 10:58:11 -080041import com.android.internal.annotations.GuardedBy;
Jordan Jozwiak6e923002019-10-22 10:50:02 -070042import com.android.internal.annotations.VisibleForTesting;
43
Ram Periathiruvadi22c0d682018-05-10 17:50:48 -070044import java.util.LinkedList;
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -080045import java.util.List;
46
47/**
Steve Paik4d257022018-04-27 13:28:31 -070048 * A service that infers the current driving state of the vehicle. It computes the driving state
49 * from listening to relevant properties from {@link CarPropertyService}
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -080050 */
51public class CarDrivingStateService extends ICarDrivingState.Stub implements CarServiceBase {
Mayank Garg72c71d22021-02-03 23:54:45 -080052 private static final String TAG = CarLog.tagFor(CarDrivingStateService.class);
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -080053 private static final boolean DBG = false;
Ram Periathiruvadi22c0d682018-05-10 17:50:48 -070054 private static final int MAX_TRANSITION_LOG_SIZE = 20;
Steve Paik4d257022018-04-27 13:28:31 -070055 private static final int PROPERTY_UPDATE_RATE = 5; // Update rate in Hz
56 private static final int NOT_RECEIVED = -1;
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -080057 private final Context mContext;
Jordan Jozwiak05985a62020-02-27 10:58:11 -080058 private final CarPropertyService mPropertyService;
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -080059 // List of clients listening to driving state events.
Jordan Jozwiak05985a62020-02-27 10:58:11 -080060 private final RemoteCallbackList<ICarDrivingStateChangeListener> mDrivingStateClients =
61 new RemoteCallbackList<>();
Steve Paik4d257022018-04-27 13:28:31 -070062 // Array of properties that the service needs to listen to from CarPropertyService for deriving
Ram Periathiruvadif6381fb2018-06-05 18:44:19 -070063 // the driving state.
Steve Paik4d257022018-04-27 13:28:31 -070064 private static final int[] REQUIRED_PROPERTIES = {
65 VehicleProperty.PERF_VEHICLE_SPEED,
Ram Periathiruvadif6381fb2018-06-05 18:44:19 -070066 VehicleProperty.GEAR_SELECTION,
67 VehicleProperty.PARKING_BRAKE_ON};
Keun young Parkb241d022020-04-20 20:31:34 -070068 private final HandlerThread mClientDispatchThread = CarServiceUtils.getHandlerThread(
69 getClass().getSimpleName());
70 private final Handler mClientDispatchHandler = new Handler(mClientDispatchThread.getLooper());
Jordan Jozwiak05985a62020-02-27 10:58:11 -080071 private final Object mLock = new Object();
72
Ram Periathiruvadi22c0d682018-05-10 17:50:48 -070073 // For dumpsys logging
Jordan Jozwiak05985a62020-02-27 10:58:11 -080074 @GuardedBy("mLock")
Ram Periathiruvadi22c0d682018-05-10 17:50:48 -070075 private final LinkedList<Utils.TransitionLog> mTransitionLogs = new LinkedList<>();
Jordan Jozwiak05985a62020-02-27 10:58:11 -080076
77 @GuardedBy("mLock")
Steve Paik4d257022018-04-27 13:28:31 -070078 private int mLastGear;
Jordan Jozwiak05985a62020-02-27 10:58:11 -080079
80 @GuardedBy("mLock")
Steve Paik4d257022018-04-27 13:28:31 -070081 private long mLastGearTimestamp = NOT_RECEIVED;
Jordan Jozwiak05985a62020-02-27 10:58:11 -080082
83 @GuardedBy("mLock")
Steve Paik4d257022018-04-27 13:28:31 -070084 private float mLastSpeed;
Jordan Jozwiak05985a62020-02-27 10:58:11 -080085
86 @GuardedBy("mLock")
Steve Paik4d257022018-04-27 13:28:31 -070087 private long mLastSpeedTimestamp = NOT_RECEIVED;
Jordan Jozwiak05985a62020-02-27 10:58:11 -080088
89 @GuardedBy("mLock")
Ram Periathiruvadif6381fb2018-06-05 18:44:19 -070090 private boolean mLastParkingBrakeState;
Jordan Jozwiak05985a62020-02-27 10:58:11 -080091
92 @GuardedBy("mLock")
Ram Periathiruvadif6381fb2018-06-05 18:44:19 -070093 private long mLastParkingBrakeTimestamp = NOT_RECEIVED;
Jordan Jozwiak05985a62020-02-27 10:58:11 -080094
95 @GuardedBy("mLock")
Ram Periathiruvadif6381fb2018-06-05 18:44:19 -070096 private List<Integer> mSupportedGears;
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -080097
Jordan Jozwiak05985a62020-02-27 10:58:11 -080098 @GuardedBy("mLock")
99 private CarDrivingStateEvent mCurrentDrivingState;
100
Steve Paik4d257022018-04-27 13:28:31 -0700101 public CarDrivingStateService(Context context, CarPropertyService propertyService) {
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -0800102 mContext = context;
Steve Paik4d257022018-04-27 13:28:31 -0700103 mPropertyService = propertyService;
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -0800104 mCurrentDrivingState = createDrivingStateEvent(CarDrivingStateEvent.DRIVING_STATE_UNKNOWN);
105 }
106
107 @Override
Jordan Jozwiak05985a62020-02-27 10:58:11 -0800108 public void init() {
Steve Paik4d257022018-04-27 13:28:31 -0700109 if (!checkPropertySupport()) {
Eric Jeongbd5fb562020-12-21 13:49:40 -0800110 Slog.e(TAG, "init failure. Driving state will always be fully restrictive");
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -0800111 return;
112 }
Kai2cb9c472021-03-04 21:19:22 -0800113 // Gets the boot state first, before getting any events from car.
Jordan Jozwiak05985a62020-02-27 10:58:11 -0800114 synchronized (mLock) {
115 mCurrentDrivingState = createDrivingStateEvent(inferDrivingStateLocked());
116 addTransitionLogLocked(TAG + " Boot", CarDrivingStateEvent.DRIVING_STATE_UNKNOWN,
117 mCurrentDrivingState.eventValue, mCurrentDrivingState.timeStamp);
118 }
Kai2cb9c472021-03-04 21:19:22 -0800119 subscribeToProperties();
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -0800120 }
121
122 @Override
Jordan Jozwiak05985a62020-02-27 10:58:11 -0800123 public void release() {
Steve Paik4d257022018-04-27 13:28:31 -0700124 for (int property : REQUIRED_PROPERTIES) {
125 mPropertyService.unregisterListener(property, mICarPropertyEventListener);
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -0800126 }
Jordan Jozwiak05985a62020-02-27 10:58:11 -0800127 while (mDrivingStateClients.getRegisteredCallbackCount() > 0) {
128 for (int i = mDrivingStateClients.getRegisteredCallbackCount() - 1; i >= 0; i--) {
129 ICarDrivingStateChangeListener client =
130 mDrivingStateClients.getRegisteredCallbackItem(i);
131 if (client == null) {
132 continue;
133 }
134 mDrivingStateClients.unregister(client);
135 }
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -0800136 }
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -0800137 mCurrentDrivingState = createDrivingStateEvent(CarDrivingStateEvent.DRIVING_STATE_UNKNOWN);
138 }
139
140 /**
Steve Paik4d257022018-04-27 13:28:31 -0700141 * Checks if the {@link CarPropertyService} supports the required properties.
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -0800142 *
143 * @return {@code true} if supported, {@code false} if not
144 */
Jordan Jozwiak05985a62020-02-27 10:58:11 -0800145 private boolean checkPropertySupport() {
Kai2cb9c472021-03-04 21:19:22 -0800146 List<CarPropertyConfig> configs = mPropertyService
147 .getPropertyConfigList(REQUIRED_PROPERTIES);
Steve Paik4d257022018-04-27 13:28:31 -0700148 for (int propertyId : REQUIRED_PROPERTIES) {
149 boolean found = false;
150 for (CarPropertyConfig config : configs) {
151 if (config.getPropertyId() == propertyId) {
152 found = true;
153 break;
154 }
155 }
156 if (!found) {
Eric Jeongbd5fb562020-12-21 13:49:40 -0800157 Slog.e(TAG, "Required property not supported: " + propertyId);
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -0800158 return false;
159 }
160 }
161 return true;
162 }
163
164 /**
Steve Paik4d257022018-04-27 13:28:31 -0700165 * Subscribe to the {@link CarPropertyService} for required sensors.
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -0800166 */
Jordan Jozwiak05985a62020-02-27 10:58:11 -0800167 private void subscribeToProperties() {
Steve Paik4d257022018-04-27 13:28:31 -0700168 for (int propertyId : REQUIRED_PROPERTIES) {
169 mPropertyService.registerListener(propertyId, PROPERTY_UPDATE_RATE,
170 mICarPropertyEventListener);
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -0800171 }
172
173 }
174
175 // Binder methods
176
177 /**
178 * Register a {@link ICarDrivingStateChangeListener} to be notified for changes to the driving
179 * state.
180 *
181 * @param listener {@link ICarDrivingStateChangeListener}
182 */
183 @Override
Jordan Jozwiak05985a62020-02-27 10:58:11 -0800184 public void registerDrivingStateChangeListener(ICarDrivingStateChangeListener listener) {
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -0800185 if (listener == null) {
186 if (DBG) {
Eric Jeongbd5fb562020-12-21 13:49:40 -0800187 Slog.e(TAG, "registerDrivingStateChangeListener(): listener null");
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -0800188 }
189 throw new IllegalArgumentException("Listener is null");
190 }
Jordan Jozwiak05985a62020-02-27 10:58:11 -0800191 mDrivingStateClients.register(listener);
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -0800192 }
193
194 /**
195 * Unregister the given Driving State Change listener
196 *
197 * @param listener client to unregister
198 */
199 @Override
Jordan Jozwiak05985a62020-02-27 10:58:11 -0800200 public void unregisterDrivingStateChangeListener(ICarDrivingStateChangeListener listener) {
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -0800201 if (listener == null) {
Eric Jeongbd5fb562020-12-21 13:49:40 -0800202 Slog.e(TAG, "unregisterDrivingStateChangeListener(): listener null");
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -0800203 throw new IllegalArgumentException("Listener is null");
204 }
205
Jordan Jozwiak05985a62020-02-27 10:58:11 -0800206 mDrivingStateClients.unregister(listener);
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -0800207 }
208
209 /**
210 * Gets the current driving state
211 *
212 * @return {@link CarDrivingStateEvent} for the given event type
213 */
214 @Override
215 @Nullable
Jordan Jozwiak05985a62020-02-27 10:58:11 -0800216 public CarDrivingStateEvent getCurrentDrivingState() {
217 synchronized (mLock) {
218 return mCurrentDrivingState;
219 }
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -0800220 }
221
Yao, Yuxinge32b3f62019-05-22 12:36:24 -0700222 @Override
Yao, Yuxingba342ec2019-06-05 14:58:35 -0700223 public void injectDrivingState(CarDrivingStateEvent event) {
Yao, Yuxinge32b3f62019-05-22 12:36:24 -0700224 ICarImpl.assertPermission(mContext, Car.PERMISSION_CONTROL_APP_BLOCKING);
225
Jordan Jozwiak05985a62020-02-27 10:58:11 -0800226 dispatchEventToClients(event);
Yao, Yuxinge32b3f62019-05-22 12:36:24 -0700227 }
228
Jordan Jozwiak05985a62020-02-27 10:58:11 -0800229 private void dispatchEventToClients(CarDrivingStateEvent event) {
230 boolean success = mClientDispatchHandler.post(() -> {
231 int numClients = mDrivingStateClients.beginBroadcast();
232 for (int i = 0; i < numClients; i++) {
233 ICarDrivingStateChangeListener callback = mDrivingStateClients.getBroadcastItem(i);
234 try {
235 callback.onDrivingStateChanged(event);
236 } catch (RemoteException e) {
Eric Jeongbd5fb562020-12-21 13:49:40 -0800237 Slog.e(TAG,
Jordan Jozwiak05985a62020-02-27 10:58:11 -0800238 String.format("Dispatch to listener %s failed for event (%s)", callback,
239 event));
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -0800240 }
241 }
Jordan Jozwiak05985a62020-02-27 10:58:11 -0800242 mDrivingStateClients.finishBroadcast();
243 });
244
245 if (!success) {
Eric Jeongbd5fb562020-12-21 13:49:40 -0800246 Slog.e(TAG, "Unable to post (" + event + ") event to dispatch handler");
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -0800247 }
248 }
249
250 @Override
Felipe Leme176a5fd2021-01-20 15:48:33 -0800251 public void dump(IndentingPrintWriter writer) {
Jordan Jozwiak0aa05982019-06-17 15:14:39 -0700252 writer.println("*CarDrivingStateService*");
Jordan Jozwiak05985a62020-02-27 10:58:11 -0800253 mDrivingStateClients.dump(writer, "Driving State Clients ");
Ram Periathiruvadif6381fb2018-06-05 18:44:19 -0700254 writer.println("Driving state change log:");
Jordan Jozwiak05985a62020-02-27 10:58:11 -0800255 synchronized (mLock) {
256 for (Utils.TransitionLog tLog : mTransitionLogs) {
257 writer.println(tLog);
258 }
259 writer.println("Current Driving State: " + mCurrentDrivingState.eventValue);
260 if (mSupportedGears != null) {
261 writer.println("Supported gears:");
262 for (Integer gear : mSupportedGears) {
263 writer.print("Gear:" + gear);
264 }
Ram Periathiruvadif6381fb2018-06-05 18:44:19 -0700265 }
266 }
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -0800267 }
268
269 /**
Steve Paik4d257022018-04-27 13:28:31 -0700270 * {@link CarPropertyEvent} listener registered with the {@link CarPropertyService} for getting
271 * property change notifications.
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -0800272 */
Steve Paik4d257022018-04-27 13:28:31 -0700273 private final ICarPropertyEventListener mICarPropertyEventListener =
274 new ICarPropertyEventListener.Stub() {
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -0800275 @Override
Steve Paik4d257022018-04-27 13:28:31 -0700276 public void onEvent(List<CarPropertyEvent> events) throws RemoteException {
Jordan Jozwiak05985a62020-02-27 10:58:11 -0800277 synchronized (mLock) {
278 for (CarPropertyEvent event : events) {
279 handlePropertyEventLocked(event);
280 }
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -0800281 }
282 }
283 };
284
285 /**
Steve Paik4d257022018-04-27 13:28:31 -0700286 * Handle events coming from {@link CarPropertyService}. Compute the driving state, map it to
287 * the corresponding UX Restrictions and dispatch the events to the registered clients.
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -0800288 */
Jordan Jozwiak6e923002019-10-22 10:50:02 -0700289 @VisibleForTesting
Jordan Jozwiak05985a62020-02-27 10:58:11 -0800290 void handlePropertyEventLocked(CarPropertyEvent event) {
Yao, Yuxingba342ec2019-06-05 14:58:35 -0700291 if (event.getEventType() != CarPropertyEvent.PROPERTY_EVENT_PROPERTY_CHANGE) {
292 return;
293 }
294 CarPropertyValue value = event.getCarPropertyValue();
295 int propId = value.getPropertyId();
296 long curTimestamp = value.getTimestamp();
297 if (DBG) {
Eric Jeongbd5fb562020-12-21 13:49:40 -0800298 Slog.d(TAG, "Property Changed: propId=" + propId);
Yao, Yuxingba342ec2019-06-05 14:58:35 -0700299 }
300 switch (propId) {
301 case VehicleProperty.PERF_VEHICLE_SPEED:
302 float curSpeed = (Float) value.getValue();
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -0800303 if (DBG) {
Eric Jeongbd5fb562020-12-21 13:49:40 -0800304 Slog.d(TAG, "Speed: " + curSpeed + "@" + curTimestamp);
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -0800305 }
Yao, Yuxingba342ec2019-06-05 14:58:35 -0700306 if (curTimestamp > mLastSpeedTimestamp) {
307 mLastSpeedTimestamp = curTimestamp;
308 mLastSpeed = curSpeed;
309 } else if (DBG) {
Eric Jeongbd5fb562020-12-21 13:49:40 -0800310 Slog.d(TAG, "Ignoring speed with older timestamp:" + curTimestamp);
Yao, Yuxingba342ec2019-06-05 14:58:35 -0700311 }
312 break;
313 case VehicleProperty.GEAR_SELECTION:
314 if (mSupportedGears == null) {
315 mSupportedGears = getSupportedGears();
316 }
317 int curGear = (Integer) value.getValue();
318 if (DBG) {
Eric Jeongbd5fb562020-12-21 13:49:40 -0800319 Slog.d(TAG, "Gear: " + curGear + "@" + curTimestamp);
Yao, Yuxingba342ec2019-06-05 14:58:35 -0700320 }
321 if (curTimestamp > mLastGearTimestamp) {
322 mLastGearTimestamp = curTimestamp;
323 mLastGear = (Integer) value.getValue();
324 } else if (DBG) {
Eric Jeongbd5fb562020-12-21 13:49:40 -0800325 Slog.d(TAG, "Ignoring Gear with older timestamp:" + curTimestamp);
Yao, Yuxingba342ec2019-06-05 14:58:35 -0700326 }
327 break;
328 case VehicleProperty.PARKING_BRAKE_ON:
329 boolean curParkingBrake = (boolean) value.getValue();
330 if (DBG) {
Eric Jeongbd5fb562020-12-21 13:49:40 -0800331 Slog.d(TAG, "Parking Brake: " + curParkingBrake + "@" + curTimestamp);
Yao, Yuxingba342ec2019-06-05 14:58:35 -0700332 }
333 if (curTimestamp > mLastParkingBrakeTimestamp) {
334 mLastParkingBrakeTimestamp = curTimestamp;
335 mLastParkingBrakeState = curParkingBrake;
336 } else if (DBG) {
Eric Jeongbd5fb562020-12-21 13:49:40 -0800337 Slog.d(TAG, "Ignoring Parking Brake status with an older timestamp:"
Yao, Yuxingba342ec2019-06-05 14:58:35 -0700338 + curTimestamp);
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -0800339 }
340 break;
341 default:
Eric Jeongbd5fb562020-12-21 13:49:40 -0800342 Slog.e(TAG, "Received property event for unhandled propId=" + propId);
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -0800343 break;
344 }
Yao, Yuxingba342ec2019-06-05 14:58:35 -0700345
346 int drivingState = inferDrivingStateLocked();
347 // Check if the driving state has changed. If it has, update our records and
348 // dispatch the new events to the listeners.
349 if (DBG) {
Eric Jeongbd5fb562020-12-21 13:49:40 -0800350 Slog.d(TAG, "Driving state new->old " + drivingState + "->"
Yao, Yuxingba342ec2019-06-05 14:58:35 -0700351 + mCurrentDrivingState.eventValue);
352 }
353 if (drivingState != mCurrentDrivingState.eventValue) {
Jordan Jozwiak05985a62020-02-27 10:58:11 -0800354 addTransitionLogLocked(TAG, mCurrentDrivingState.eventValue, drivingState,
Yao, Yuxingba342ec2019-06-05 14:58:35 -0700355 System.currentTimeMillis());
356 // Update if there is a change in state.
357 mCurrentDrivingState = createDrivingStateEvent(drivingState);
358 if (DBG) {
Eric Jeongbd5fb562020-12-21 13:49:40 -0800359 Slog.d(TAG, "dispatching to " + mDrivingStateClients.getRegisteredCallbackCount()
Jordan Jozwiak05985a62020-02-27 10:58:11 -0800360 + " clients");
Yao, Yuxingba342ec2019-06-05 14:58:35 -0700361 }
Jordan Jozwiak39da9c82019-10-25 10:46:38 -0700362 // Dispatch to clients on a separate thread to prevent a deadlock
363 final CarDrivingStateEvent currentDrivingStateEvent = mCurrentDrivingState;
Jordan Jozwiak05985a62020-02-27 10:58:11 -0800364 dispatchEventToClients(currentDrivingStateEvent);
Yao, Yuxingba342ec2019-06-05 14:58:35 -0700365 }
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -0800366 }
367
Ram Periathiruvadif6381fb2018-06-05 18:44:19 -0700368 private List<Integer> getSupportedGears() {
Kai2cb9c472021-03-04 21:19:22 -0800369 List<CarPropertyConfig> propertyList = mPropertyService
370 .getPropertyConfigList(REQUIRED_PROPERTIES);
371 for (CarPropertyConfig p : propertyList) {
Ram Periathiruvadif6381fb2018-06-05 18:44:19 -0700372 if (p.getPropertyId() == VehicleProperty.GEAR_SELECTION) {
373 return p.getConfigArray();
374 }
375 }
376 return null;
377 }
378
Jordan Jozwiak05985a62020-02-27 10:58:11 -0800379 @GuardedBy("mLock")
380 private void addTransitionLogLocked(String name, int from, int to, long timestamp) {
Ram Periathiruvadi22c0d682018-05-10 17:50:48 -0700381 if (mTransitionLogs.size() >= MAX_TRANSITION_LOG_SIZE) {
382 mTransitionLogs.remove();
383 }
384
385 Utils.TransitionLog tLog = new Utils.TransitionLog(name, from, to, timestamp);
386 mTransitionLogs.add(tLog);
387 }
388
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -0800389 /**
390 * Infers the current driving state of the car from the other Car Sensor properties like
391 * Current Gear, Speed etc.
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -0800392 *
393 * @return Current driving state
394 */
Jordan Jozwiak05985a62020-02-27 10:58:11 -0800395 @GuardedBy("mLock")
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -0800396 @CarDrivingState
397 private int inferDrivingStateLocked() {
Jordan Jozwiak05985a62020-02-27 10:58:11 -0800398 updateVehiclePropertiesIfNeededLocked();
Steve Paik4d257022018-04-27 13:28:31 -0700399 if (DBG) {
Eric Jeongbd5fb562020-12-21 13:49:40 -0800400 Slog.d(TAG, "Last known Gear:" + mLastGear + " Last known speed:" + mLastSpeed);
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -0800401 }
Ram Periathiruvadif6381fb2018-06-05 18:44:19 -0700402
403 /*
404 Logic to start off deriving driving state:
405 1. If gear == parked, then Driving State is parked.
406 2. If gear != parked,
407 2a. if parking brake is applied, then Driving state is parked.
408 2b. if parking brake is not applied or unknown/unavailable, then driving state
409 is still unknown.
410 3. If driving state is unknown at the end of step 2,
411 3a. if speed == 0, then driving state is idling
412 3b. if speed != 0, then driving state is moving
413 3c. if speed unavailable, then driving state is unknown
414 */
415
Jordan Jozwiak05985a62020-02-27 10:58:11 -0800416 if (isVehicleKnownToBeParkedLocked()) {
Steve Paik4d257022018-04-27 13:28:31 -0700417 return CarDrivingStateEvent.DRIVING_STATE_PARKED;
418 }
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -0800419
Ram Periathiruvadif6381fb2018-06-05 18:44:19 -0700420 // We don't know if the vehicle is parked, let's look at the speed.
421 if (mLastSpeedTimestamp == NOT_RECEIVED || mLastSpeed < 0) {
Steve Paik4d257022018-04-27 13:28:31 -0700422 return CarDrivingStateEvent.DRIVING_STATE_UNKNOWN;
423 } else if (mLastSpeed == 0f) {
424 return CarDrivingStateEvent.DRIVING_STATE_IDLING;
425 } else {
426 return CarDrivingStateEvent.DRIVING_STATE_MOVING;
427 }
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -0800428 }
429
Ram Periathiruvadif6381fb2018-06-05 18:44:19 -0700430 /**
431 * Find if we have signals to know if the vehicle is parked
432 *
433 * @return true if we have enough information to say the vehicle is parked.
434 * false, if the vehicle is either not parked or if we don't have any information.
435 */
Jordan Jozwiak05985a62020-02-27 10:58:11 -0800436 @GuardedBy("mLock")
437 private boolean isVehicleKnownToBeParkedLocked() {
Ram Periathiruvadif6381fb2018-06-05 18:44:19 -0700438 // If we know the gear is in park, return true
439 if (mLastGearTimestamp != NOT_RECEIVED && mLastGear == VehicleGear.GEAR_PARK) {
440 return true;
441 } else if (mLastParkingBrakeTimestamp != NOT_RECEIVED) {
442 // if gear is not in park or unknown, look for status of parking brake if transmission
443 // type is manual.
Jordan Jozwiak05985a62020-02-27 10:58:11 -0800444 if (isCarManualTransmissionTypeLocked()) {
Ram Periathiruvadif6381fb2018-06-05 18:44:19 -0700445 return mLastParkingBrakeState;
446 }
447 }
448 // if neither information is available, return false to indicate we can't determine
449 // if the vehicle is parked.
450 return false;
451 }
452
453 /**
454 * If Supported gears information is available and GEAR_PARK is not one of the supported gears,
455 * transmission type is considered to be Manual. Automatic transmission is assumed otherwise.
456 */
Jordan Jozwiak05985a62020-02-27 10:58:11 -0800457 @GuardedBy("mLock")
458 private boolean isCarManualTransmissionTypeLocked() {
Ram Periathiruvadif6381fb2018-06-05 18:44:19 -0700459 if (mSupportedGears != null
460 && !mSupportedGears.isEmpty()
461 && !mSupportedGears.contains(VehicleGear.GEAR_PARK)) {
462 return true;
463 }
464 return false;
465 }
466
467 /**
468 * Try querying the gear selection and parking brake if we haven't received the event yet.
469 * This could happen if the gear change occurred before car service booted up like in the
470 * case of a HU restart in the middle of a drive. Since gear and parking brake are
471 * on-change only properties, we could be in this situation where we will have to query
472 * VHAL.
473 */
Jordan Jozwiak05985a62020-02-27 10:58:11 -0800474 @GuardedBy("mLock")
475 private void updateVehiclePropertiesIfNeededLocked() {
Ram Periathiruvadif6381fb2018-06-05 18:44:19 -0700476 if (mLastGearTimestamp == NOT_RECEIVED) {
Kai Wang301dd472021-05-18 06:09:44 +0000477 CarPropertyValue propertyValue = mPropertyService.getPropertySafe(
Ram Periathiruvadif6381fb2018-06-05 18:44:19 -0700478 VehicleProperty.GEAR_SELECTION,
479 VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL);
480 if (propertyValue != null) {
481 mLastGear = (Integer) propertyValue.getValue();
482 mLastGearTimestamp = propertyValue.getTimestamp();
483 if (DBG) {
Eric Jeongbd5fb562020-12-21 13:49:40 -0800484 Slog.d(TAG, "updateVehiclePropertiesIfNeeded: gear:" + mLastGear);
Ram Periathiruvadif6381fb2018-06-05 18:44:19 -0700485 }
486 }
487 }
488
489 if (mLastParkingBrakeTimestamp == NOT_RECEIVED) {
Kai Wang301dd472021-05-18 06:09:44 +0000490 CarPropertyValue propertyValue = mPropertyService.getPropertySafe(
Ram Periathiruvadif6381fb2018-06-05 18:44:19 -0700491 VehicleProperty.PARKING_BRAKE_ON,
492 VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL);
493 if (propertyValue != null) {
494 mLastParkingBrakeState = (boolean) propertyValue.getValue();
495 mLastParkingBrakeTimestamp = propertyValue.getTimestamp();
496 if (DBG) {
Eric Jeongbd5fb562020-12-21 13:49:40 -0800497 Slog.d(TAG, "updateVehiclePropertiesIfNeeded: brake:" + mLastParkingBrakeState);
Ram Periathiruvadif6381fb2018-06-05 18:44:19 -0700498 }
499 }
500 }
501
502 if (mLastSpeedTimestamp == NOT_RECEIVED) {
Kai Wang301dd472021-05-18 06:09:44 +0000503 CarPropertyValue propertyValue = mPropertyService.getPropertySafe(
Ram Periathiruvadif6381fb2018-06-05 18:44:19 -0700504 VehicleProperty.PERF_VEHICLE_SPEED,
505 VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL);
506 if (propertyValue != null) {
507 mLastSpeed = (float) propertyValue.getValue();
508 mLastSpeedTimestamp = propertyValue.getTimestamp();
509 if (DBG) {
Eric Jeongbd5fb562020-12-21 13:49:40 -0800510 Slog.d(TAG, "updateVehiclePropertiesIfNeeded: speed:" + mLastSpeed);
Ram Periathiruvadif6381fb2018-06-05 18:44:19 -0700511 }
512 }
513 }
514 }
515
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -0800516 private static CarDrivingStateEvent createDrivingStateEvent(int eventValue) {
517 return new CarDrivingStateEvent(eventValue, SystemClock.elapsedRealtimeNanos());
518 }
Ram Periathiruvadi22c0d682018-05-10 17:50:48 -0700519
Ram Periathiruvadi25c16f12017-11-17 16:48:37 -0800520}