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 
17 package com.android.car;
18 
19 import android.car.hardware.CarSensorEvent;
20 import android.car.hardware.CarSensorManager;
21 import android.car.hardware.ICarSensorEventListener;
22 import android.content.Context;
23 import android.os.SystemClock;
24 import android.util.Log;
25 
26 import com.android.car.hal.SensorHalService.SensorListener;
27 import java.io.PrintWriter;
28 import java.util.List;
29 
30 
31 /**
32  * Logical sensor implementing driving state policy. This policy sets only two states:
33  * no restriction vs fully restrictive. To enter no restriction state, speed should be zero
34  * while either parking brake is applied or transmission gear is in P.
35  */
36 public class DrivingStatePolicy extends CarSensorService.LogicalSensor {
37 
38     private final Context mContext;
39     private CarSensorService mSensorService;
40     private int mDrivingState = CarSensorEvent.DRIVE_STATUS_FULLY_RESTRICTED;
41     private SensorListener mSensorListener;
42     private boolean mIsReady = false;
43     private boolean mStarted = false;
44 
45     private static final int[] SUPPORTED_SENSORS = { CarSensorManager.SENSOR_TYPE_DRIVING_STATUS };
46 
47     private final ICarSensorEventListener mICarSensorEventListener =
48             new ICarSensorEventListener.Stub() {
49         @Override
50         public void onSensorChanged(List<CarSensorEvent> events) {
51             for (CarSensorEvent event: events) {
52                 handleSensorEvent(event);
53             }
54         }
55     };
56 
DrivingStatePolicy(Context context, CarSensorService sensorService)57     public DrivingStatePolicy(Context context, CarSensorService sensorService) {
58         mContext = context;
59         mSensorService = sensorService;
60     }
61 
62     @Override
init()63     public void init() {
64         mIsReady = true;
65     }
66 
67     @Override
onSensorServiceReady()68     public synchronized void onSensorServiceReady() {
69         int sensorList[] = mSensorService.getSupportedSensors();
70         boolean hasSpeed = subscribeIfSupportedLocked(sensorList,
71                 CarSensorManager.SENSOR_TYPE_CAR_SPEED, CarSensorManager.SENSOR_RATE_FASTEST);
72         if (!hasSpeed) {
73             Log.w(CarLog.TAG_SENSOR,
74                     "No speed sensor from car. Driving state will be always fully restrictive");
75         }
76         boolean hasParkingBrake = subscribeIfSupportedLocked(sensorList,
77                 CarSensorManager.SENSOR_TYPE_PARKING_BRAKE, CarSensorManager.SENSOR_RATE_FASTEST);
78         boolean hasGear = subscribeIfSupportedLocked(sensorList, CarSensorManager.SENSOR_TYPE_GEAR,
79                 CarSensorManager.SENSOR_RATE_FASTEST);
80         if (!hasParkingBrake && !hasGear) {
81             Log.w(CarLog.TAG_SENSOR,
82                     "No brake info from car. Driving state will be always fully restrictive");
83         }
84     }
85 
86     @Override
release()87     public void release() {
88     }
89 
getDefaultValue(int sensorType)90     public static CarSensorEvent getDefaultValue(int sensorType) {
91         if (sensorType != CarSensorManager.SENSOR_TYPE_DRIVING_STATUS) {
92             Log.w(CarLog.TAG_SENSOR, "getDefaultValue to DrivingStatePolicy with sensorType:" +
93                     sensorType);
94             return null;
95         }
96         // There's a race condition and timestamp from vehicle HAL could be slightly less
97         // then current call to SystemClock.elapsedRealtimeNanos() will return.
98         // We want vehicle HAL value always override this default value so we set timestamp to 0.
99         return createEvent(CarSensorEvent.DRIVE_STATUS_FULLY_RESTRICTED, 0 /* timestamp */);
100     }
101 
registerSensorListener(SensorListener listener)102     public synchronized void registerSensorListener(SensorListener listener) {
103         mSensorListener = listener;
104     }
105 
106     @Override
isReady()107     public synchronized boolean isReady() {
108         return mIsReady;
109     }
110 
111     @Override
getSupportedSensors()112     public int[] getSupportedSensors() {
113         return SUPPORTED_SENSORS;
114     }
115 
116     @Override
requestSensorStart(int sensorType, int rate)117     public synchronized boolean requestSensorStart(int sensorType, int rate) {
118         mStarted = true;
119         dispatchCarSensorEvent(mSensorListener, createEvent(mDrivingState));
120         return true;
121     }
122 
123     @Override
requestSensorStop(int sensorType)124     public synchronized void requestSensorStop(int sensorType) {
125         mStarted = false;
126     }
127 
128     @Override
dump(PrintWriter writer)129     public void dump(PrintWriter writer) {
130     }
131 
subscribeIfSupportedLocked(int sensorList[], int sensorType, int rate)132     private boolean subscribeIfSupportedLocked(int sensorList[], int sensorType, int rate) {
133         if (!CarSensorManager.isSensorSupported(sensorList, sensorType)) {
134             Log.i(CarLog.TAG_SENSOR, "Sensor not supported:" + sensorType);
135             return false;
136         }
137         return mSensorService.registerOrUpdateSensorListener(sensorType, rate,
138                 mICarSensorEventListener);
139     }
140 
handleSensorEvent(CarSensorEvent event)141     private synchronized void handleSensorEvent(CarSensorEvent event) {
142         switch (event.sensorType) {
143             case CarSensorManager.SENSOR_TYPE_PARKING_BRAKE:
144             case CarSensorManager.SENSOR_TYPE_GEAR:
145             case CarSensorManager.SENSOR_TYPE_CAR_SPEED:
146                 int drivingState = recalcDrivingStateLocked();
147                 if (drivingState != mDrivingState && mSensorListener != null) {
148                     mDrivingState = drivingState;
149                     dispatchCarSensorEvent(mSensorListener, createEvent(mDrivingState));
150                 }
151                 break;
152             default:
153                 break;
154         }
155     }
156 
recalcDrivingStateLocked()157     private int recalcDrivingStateLocked() {
158         int drivingState = CarSensorEvent.DRIVE_STATUS_FULLY_RESTRICTED;
159         CarSensorEvent lastParkingBrake = mSensorService.getLatestSensorEvent(
160                 CarSensorManager.SENSOR_TYPE_PARKING_BRAKE);
161         CarSensorEvent lastGear = mSensorService.getLatestSensorEvent(
162                 CarSensorManager.SENSOR_TYPE_GEAR);
163         CarSensorEvent lastSpeed = mSensorService.getLatestSensorEvent(
164                 CarSensorManager.SENSOR_TYPE_CAR_SPEED);
165         if (lastSpeed != null && lastSpeed.floatValues[0] == 0f) { // stopped
166             if (lastParkingBrake == null && isParkingBrakeApplied(lastParkingBrake)) {
167                 if (lastGear != null && isGearInParkingOrNeutral(lastGear)) {
168                     drivingState = CarSensorEvent.DRIVE_STATUS_UNRESTRICTED;
169                 }
170             } else { // parking break not applied or not available
171                 if (lastGear != null && isGearInParking(lastGear)) { // gear in P
172                     drivingState = CarSensorEvent.DRIVE_STATUS_UNRESTRICTED;
173                 }
174             }
175         } // else moving, full restriction
176         return drivingState;
177     }
178 
isSpeedZero(CarSensorEvent event)179     private boolean isSpeedZero(CarSensorEvent event) {
180         return event.floatValues[0] == 0f;
181     }
182 
isParkingBrakeApplied(CarSensorEvent event)183     private boolean isParkingBrakeApplied(CarSensorEvent event) {
184         return event.intValues[0] == 1;
185     }
186 
isGearInParkingOrNeutral(CarSensorEvent event)187     private boolean isGearInParkingOrNeutral(CarSensorEvent event) {
188         int gear = event.intValues[0];
189         return (gear == CarSensorEvent.GEAR_NEUTRAL) ||
190                 (gear == CarSensorEvent.GEAR_PARK);
191     }
192 
isGearInParking(CarSensorEvent event)193     private boolean isGearInParking(CarSensorEvent event) {
194         int gear = event.intValues[0];
195         return gear == CarSensorEvent.GEAR_PARK;
196     }
197 
createEvent(int drivingState)198     private static CarSensorEvent createEvent(int drivingState) {
199         return createEvent(drivingState, SystemClock.elapsedRealtimeNanos());
200     }
201 
createEvent(int drivingState, long timestamp)202     private static CarSensorEvent createEvent(int drivingState, long timestamp) {
203         CarSensorEvent event = new CarSensorEvent(
204                 CarSensorManager.SENSOR_TYPE_DRIVING_STATUS,
205                 timestamp,
206                 0 /* float values */,
207                 1 /* int values */);
208         event.intValues[0] = drivingState;
209         return event;
210     }
211 }
212