1ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung/*
2ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung * Copyright (C) 2015 The Android Open Source Project
3ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung *
4ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung * Licensed under the Apache License, Version 2.0 (the "License");
5ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung * you may not use this file except in compliance with the License.
6ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung * You may obtain a copy of the License at
7ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung *
8ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung *      http://www.apache.org/licenses/LICENSE-2.0
9ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung *
10ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung * Unless required by applicable law or agreed to in writing, software
11ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung * distributed under the License is distributed on an "AS IS" BASIS,
12ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung * See the License for the specific language governing permissions and
14ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung * limitations under the License.
15ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung */
16ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung
17e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Parkpackage android.car.hardware;
18ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung
19ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoungimport android.Manifest;
20af2cc99a2e8eea38a75b20b952ea5c0e7ebb4b1bKeun-young Parkimport android.annotation.IntDef;
21e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Parkimport android.annotation.RequiresPermission;
22e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Parkimport android.car.Car;
23e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Parkimport android.car.CarApiUtil;
24e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Parkimport android.car.CarLibLog;
25e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Parkimport android.car.CarManagerBase;
26e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Parkimport android.car.CarNotConnectedException;
27417631a1fb9a280d365aab6fb8d3b38ccd65e142Steve Paikimport android.car.VehiclePropertyType;
284d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paikimport android.car.hardware.property.CarPropertyManager;
29ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoungimport android.content.Context;
30a2819901c1b4f56e4950dd5cb6bf6c9e8042cf4cSteve Paikimport android.os.Bundle;
31ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoungimport android.os.Handler;
32e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Parkimport android.os.IBinder;
33ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoungimport android.os.RemoteException;
344d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paikimport android.util.ArraySet;
35ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoungimport android.util.Log;
360d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
37af2cc99a2e8eea38a75b20b952ea5c0e7ebb4b1bKeun-young Parkimport java.lang.annotation.Retention;
38af2cc99a2e8eea38a75b20b952ea5c0e7ebb4b1bKeun-young Parkimport java.lang.annotation.RetentionPolicy;
39ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoungimport java.lang.ref.WeakReference;
404d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paikimport java.util.Arrays;
414d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paikimport java.util.HashMap;
42cc449f7941456a0133ff8a4b2e49737f0936c1d0keunyoungimport java.util.List;
434d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik
44ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung
45ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung/**
46ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung *  API for monitoring car sensor data.
47ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung */
484cf6911619b9fe6ffeba7afeb05299aab165f184Keun-young Parkpublic final class CarSensorManager implements CarManagerBase {
494d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik    private static final  boolean DBG = false;
504d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik    private static final String TAG = "CarSensorManager";
514d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik    private final CarPropertyManager mCarPropertyMgr;
524afc6ee52690326316e2ed1b7bc354f466849426Keun-young Park    /** @hide */
53289ab99688d226518e47a7e47c9ffc20f221f0a6Steve Paik    public static final int SENSOR_TYPE_RESERVED1                   = 1;
54ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    /**
55ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * This sensor represents vehicle speed in m/s.
56ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * Sensor data in {@link CarSensorEvent} is a float which will be >= 0.
57ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * This requires {@link Car#PERMISSION_SPEED} permission.
58ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     */
594d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik    public static final int SENSOR_TYPE_CAR_SPEED                   = 0x11600207;
60ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    /**
61ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * Represents engine RPM of the car. Sensor data in {@link CarSensorEvent} is a float.
62ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     */
634d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik    public static final int SENSOR_TYPE_RPM                         = 0x11600305;
64ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    /**
65ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * Total travel distance of the car in Kilometer. Sensor data is a float.
66ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * This requires {@link Car#PERMISSION_MILEAGE} permission.
67ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     */
684d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik    public static final int SENSOR_TYPE_ODOMETER                    = 0x11600204;
69ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    /**
70ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * Indicates fuel level of the car.
71d0ebac2c18d1d226fcd2c92533846f23927d3ae3Steve Paik     * In {@link CarSensorEvent}, represents fuel level in milliliters.
7268ee16bde23d44fc4bafd30732bf50145a2fe9ffKai     * This requires {@link Car#PERMISSION_ENERGY} permission.
73ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     */
744d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik    public static final int SENSOR_TYPE_FUEL_LEVEL                  = 0x11600307;
75ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    /**
76ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * Represents the current status of parking brake. Sensor data in {@link CarSensorEvent} is an
77cc449f7941456a0133ff8a4b2e49737f0936c1d0keunyoung     * intValues[0]. Value of 1 represents parking brake applied while 0 means the other way
78d72b53500006e84b0c69e650878267c693c164a3Jason Tholstrup     * around. For this sensor, rate in {@link #registerListener(OnSensorChangedListener, int, int)}
79ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * will be ignored and all changes will be notified.
80ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     */
814d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik    public static final int SENSOR_TYPE_PARKING_BRAKE               = 0x11200402;
82ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    /**
83ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * This represents the current position of transmission gear. Sensor data in
84cc449f7941456a0133ff8a4b2e49737f0936c1d0keunyoung     * {@link CarSensorEvent} is an intValues[0]. For the meaning of the value, check
85ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * {@link CarSensorEvent#GEAR_NEUTRAL} and other GEAR_*.
86ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     */
874d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik    public static final int SENSOR_TYPE_GEAR                        = 0x11400400;
889eae32f8c09816d35ef28c14ed1f0c5fa39c21f1Jason Tholstrup    /** @hide */
89289ab99688d226518e47a7e47c9ffc20f221f0a6Steve Paik    public static final int SENSOR_TYPE_RESERVED8                   = 8;
90ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    /**
91cc449f7941456a0133ff8a4b2e49737f0936c1d0keunyoung     * Day/night sensor. Sensor data is intValues[0].
92ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     */
934d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik    public static final int SENSOR_TYPE_NIGHT                       = 0x11200407;
944afc6ee52690326316e2ed1b7bc354f466849426Keun-young Park    /** @hide */
95289ab99688d226518e47a7e47c9ffc20f221f0a6Steve Paik    public static final int SENSOR_TYPE_RESERVED10                  = 10;
969aa170f337045cbd2f216983ef1ac2ffa6faa336Ram Periathiruvadi    /** @hide */
979aa170f337045cbd2f216983ef1ac2ffa6faa336Ram Periathiruvadi    public static final int SENSOR_TYPE_RESERVED11                  = 11;
98ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    /**
99ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * Environment like temperature and pressure.
100ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     */
101289ab99688d226518e47a7e47c9ffc20f221f0a6Steve Paik    public static final int SENSOR_TYPE_ENVIRONMENT                 = 12;
102064ddd89fd57c6c20a98b9f95f9ea5123d11160bKeun-young Park    /** @hide */
103289ab99688d226518e47a7e47c9ffc20f221f0a6Steve Paik    public static final int SENSOR_TYPE_RESERVED13                  = 13;
104064ddd89fd57c6c20a98b9f95f9ea5123d11160bKeun-young Park    /** @hide */
105289ab99688d226518e47a7e47c9ffc20f221f0a6Steve Paik    public static final int SENSOR_TYPE_RESERVED14                  = 14;
1069eae32f8c09816d35ef28c14ed1f0c5fa39c21f1Jason Tholstrup    /** @hide */
107289ab99688d226518e47a7e47c9ffc20f221f0a6Steve Paik    public static final int SENSOR_TYPE_RESERVED15                  = 15;
1089eae32f8c09816d35ef28c14ed1f0c5fa39c21f1Jason Tholstrup    /** @hide */
109289ab99688d226518e47a7e47c9ffc20f221f0a6Steve Paik    public static final int SENSOR_TYPE_RESERVED16                  = 16;
1109eae32f8c09816d35ef28c14ed1f0c5fa39c21f1Jason Tholstrup    /** @hide */
111289ab99688d226518e47a7e47c9ffc20f221f0a6Steve Paik    public static final int SENSOR_TYPE_RESERVED17                  = 17;
1129eae32f8c09816d35ef28c14ed1f0c5fa39c21f1Jason Tholstrup    /** @hide */
113289ab99688d226518e47a7e47c9ffc20f221f0a6Steve Paik    public static final int SENSOR_TYPE_RESERVED18                  = 18;
1149eae32f8c09816d35ef28c14ed1f0c5fa39c21f1Jason Tholstrup    /** @hide */
115289ab99688d226518e47a7e47c9ffc20f221f0a6Steve Paik    public static final int SENSOR_TYPE_RESERVED19                  = 19;
1169eae32f8c09816d35ef28c14ed1f0c5fa39c21f1Jason Tholstrup    /** @hide */
117289ab99688d226518e47a7e47c9ffc20f221f0a6Steve Paik    public static final int SENSOR_TYPE_RESERVED20                  = 20;
1189eae32f8c09816d35ef28c14ed1f0c5fa39c21f1Jason Tholstrup    /** @hide */
119289ab99688d226518e47a7e47c9ffc20f221f0a6Steve Paik    public static final int SENSOR_TYPE_RESERVED21                  = 21;
120064ddd89fd57c6c20a98b9f95f9ea5123d11160bKeun-young Park    /**
1211e5a88bcaea73af4a140616b4e9ed5fcfa60d990Pavel Maltsev     * Represents ignition state. The value should be one of the constants that starts with
1221e5a88bcaea73af4a140616b4e9ed5fcfa60d990Pavel Maltsev     * IGNITION_STATE_* in {@link CarSensorEvent}.
1231e5a88bcaea73af4a140616b4e9ed5fcfa60d990Pavel Maltsev     */
1244d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik    public static final int SENSOR_TYPE_IGNITION_STATE              = 0x11400409;
125289ab99688d226518e47a7e47c9ffc20f221f0a6Steve Paik    /**
126289ab99688d226518e47a7e47c9ffc20f221f0a6Steve Paik     * Represents wheel distance in millimeters.  Some cars may not have individual sensors on each
127289ab99688d226518e47a7e47c9ffc20f221f0a6Steve Paik     * wheel.  If a value is not available, Long.MAX_VALUE will be reported.  The wheel distance
128289ab99688d226518e47a7e47c9ffc20f221f0a6Steve Paik     * accumulates over time.  It increments on forward movement, and decrements on reverse.  Wheel
129289ab99688d226518e47a7e47c9ffc20f221f0a6Steve Paik     * distance shall be reset to zero each time a vehicle is started by the user.
130289ab99688d226518e47a7e47c9ffc20f221f0a6Steve Paik     * This requires {@link Car#PERMISSION_SPEED} permission.
131289ab99688d226518e47a7e47c9ffc20f221f0a6Steve Paik     */
1324d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik    public static final int SENSOR_TYPE_WHEEL_TICK_DISTANCE         = 0x11510306;
133289ab99688d226518e47a7e47c9ffc20f221f0a6Steve Paik    /**
134289ab99688d226518e47a7e47c9ffc20f221f0a6Steve Paik     * Set to true when ABS is active.  This sensor is event driven.
13568ee16bde23d44fc4bafd30732bf50145a2fe9ffKai     * This requires {@link Car#PERMISSION_CAR_DYNAMICS_STATE} permission.
136289ab99688d226518e47a7e47c9ffc20f221f0a6Steve Paik     */
1374d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik    public static final int SENSOR_TYPE_ABS_ACTIVE                  = 0x1120040a;
138289ab99688d226518e47a7e47c9ffc20f221f0a6Steve Paik    /**
139289ab99688d226518e47a7e47c9ffc20f221f0a6Steve Paik     * Set to true when traction control is active.  This sensor is event driven.
14068ee16bde23d44fc4bafd30732bf50145a2fe9ffKai     * This requires {@link Car#PERMISSION_CAR_DYNAMICS_STATE} permission.
141289ab99688d226518e47a7e47c9ffc20f221f0a6Steve Paik     */
1424d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik    public static final int SENSOR_TYPE_TRACTION_CONTROL_ACTIVE     = 0x1120040b;
14320526258de542b521b630079513059d08c08efdbSteve Paik    /** @hide */
14420526258de542b521b630079513059d08c08efdbSteve Paik    public static final int SENSOR_TYPE_RESERVED26                  = 26;
145d0ebac2c18d1d226fcd2c92533846f23927d3ae3Steve Paik    /**
146d0ebac2c18d1d226fcd2c92533846f23927d3ae3Steve Paik     * Set to true if the fuel door is open.
147d0ebac2c18d1d226fcd2c92533846f23927d3ae3Steve Paik     */
1484d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik    public static final int SENSOR_TYPE_FUEL_DOOR_OPEN              = 0x11200308;
149d0ebac2c18d1d226fcd2c92533846f23927d3ae3Steve Paik
150d0ebac2c18d1d226fcd2c92533846f23927d3ae3Steve Paik    /**
151d0ebac2c18d1d226fcd2c92533846f23927d3ae3Steve Paik     * Indicates battery level of the car.
152d0ebac2c18d1d226fcd2c92533846f23927d3ae3Steve Paik     * In {@link CarSensorEvent}, represents battery level in WH.  floatValues[{@link
153d0ebac2c18d1d226fcd2c92533846f23927d3ae3Steve Paik     * CarSensorEvent#INDEX_EV_BATTERY_CAPACITY_ACTUAL}] represents the actual battery capacity in
154d0ebac2c18d1d226fcd2c92533846f23927d3ae3Steve Paik     * WH.  The battery degrades over time, so this value is expected to drop slowly over the life
155d0ebac2c18d1d226fcd2c92533846f23927d3ae3Steve Paik     * of the vehicle.
15668ee16bde23d44fc4bafd30732bf50145a2fe9ffKai     * This requires {@link Car#PERMISSION_ENERGY} permission.
157d0ebac2c18d1d226fcd2c92533846f23927d3ae3Steve Paik     */
1584d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik    public static final int SENSOR_TYPE_EV_BATTERY_LEVEL            = 0x11600309;
159d0ebac2c18d1d226fcd2c92533846f23927d3ae3Steve Paik    /**
160d0ebac2c18d1d226fcd2c92533846f23927d3ae3Steve Paik     * Set to true if EV charging port is open.
161d0ebac2c18d1d226fcd2c92533846f23927d3ae3Steve Paik     */
1624d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik    public static final int SENSOR_TYPE_EV_CHARGE_PORT_OPEN         = 0x1120030a;
163d0ebac2c18d1d226fcd2c92533846f23927d3ae3Steve Paik    /**
164d0ebac2c18d1d226fcd2c92533846f23927d3ae3Steve Paik     * Set to true if EV charging port is connected.
165d0ebac2c18d1d226fcd2c92533846f23927d3ae3Steve Paik     */
1664d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik    public static final int SENSOR_TYPE_EV_CHARGE_PORT_CONNECTED    = 0x1120030b;
167d0ebac2c18d1d226fcd2c92533846f23927d3ae3Steve Paik    /**
168d0ebac2c18d1d226fcd2c92533846f23927d3ae3Steve Paik     *  Indicates the instantaneous battery charging rate in mW.
16968ee16bde23d44fc4bafd30732bf50145a2fe9ffKai     *  This requires {@link Car#PERMISSION_ENERGY} permission.
170d0ebac2c18d1d226fcd2c92533846f23927d3ae3Steve Paik     */
1714d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik    public static final int SENSOR_TYPE_EV_BATTERY_CHARGE_RATE      = 0x1160030c;
17251f038eb441b7cbfe62407f89e06146214012850Steve Paik    /**
17351f038eb441b7cbfe62407f89e06146214012850Steve Paik     * Oil level sensor.
17425c0b8583d2328ec8e9f9d34587fb80d6bb38099Kai     * This requires {@link Car#PERMISSION_CAR_ENGINE_DETAILED} permission
17551f038eb441b7cbfe62407f89e06146214012850Steve Paik     * @hide
17651f038eb441b7cbfe62407f89e06146214012850Steve Paik     */
1774d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik    public static final int SENSOR_TYPE_ENGINE_OIL_LEVEL            = 0x11400303;
1781e5a88bcaea73af4a140616b4e9ed5fcfa60d990Pavel Maltsev
179064ddd89fd57c6c20a98b9f95f9ea5123d11160bKeun-young Park
180af2cc99a2e8eea38a75b20b952ea5c0e7ebb4b1bKeun-young Park    /** @hide */
181af2cc99a2e8eea38a75b20b952ea5c0e7ebb4b1bKeun-young Park    @IntDef({
1824d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik            SENSOR_TYPE_CAR_SPEED,
1834d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik            SENSOR_TYPE_RPM,
1844d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik            SENSOR_TYPE_ODOMETER,
1854d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik            SENSOR_TYPE_FUEL_LEVEL,
1864d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik            SENSOR_TYPE_PARKING_BRAKE,
1874d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik            SENSOR_TYPE_GEAR,
1884d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik            SENSOR_TYPE_NIGHT,
1894d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik            SENSOR_TYPE_ENVIRONMENT,
1904d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik            SENSOR_TYPE_IGNITION_STATE,
1914d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik            SENSOR_TYPE_WHEEL_TICK_DISTANCE,
1924d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik            SENSOR_TYPE_ABS_ACTIVE,
1934d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik            SENSOR_TYPE_TRACTION_CONTROL_ACTIVE,
1944d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik            SENSOR_TYPE_FUEL_DOOR_OPEN,
1954d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik            SENSOR_TYPE_EV_BATTERY_LEVEL,
1964d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik            SENSOR_TYPE_EV_CHARGE_PORT_OPEN,
1974d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik            SENSOR_TYPE_EV_CHARGE_PORT_CONNECTED,
1984d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik            SENSOR_TYPE_EV_BATTERY_CHARGE_RATE,
1994d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik            SENSOR_TYPE_ENGINE_OIL_LEVEL,
200af2cc99a2e8eea38a75b20b952ea5c0e7ebb4b1bKeun-young Park    })
201af2cc99a2e8eea38a75b20b952ea5c0e7ebb4b1bKeun-young Park    @Retention(RetentionPolicy.SOURCE)
202af2cc99a2e8eea38a75b20b952ea5c0e7ebb4b1bKeun-young Park    public @interface SensorType {}
203af2cc99a2e8eea38a75b20b952ea5c0e7ebb4b1bKeun-young Park
2044d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik    private final ArraySet<Integer> mSensorConfigIds = new ArraySet<>(Arrays.asList(new Integer[]{
2054d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik            SENSOR_TYPE_CAR_SPEED,
2064d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik            SENSOR_TYPE_RPM,
2074d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik            SENSOR_TYPE_ODOMETER,
2084d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik            SENSOR_TYPE_FUEL_LEVEL,
2094d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik            SENSOR_TYPE_PARKING_BRAKE,
2104d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik            SENSOR_TYPE_GEAR,
2114d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik            SENSOR_TYPE_NIGHT,
2124d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik            SENSOR_TYPE_ENVIRONMENT,
2134d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik            SENSOR_TYPE_IGNITION_STATE,
2144d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik            SENSOR_TYPE_WHEEL_TICK_DISTANCE,
2154d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik            SENSOR_TYPE_ABS_ACTIVE,
2164d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik            SENSOR_TYPE_TRACTION_CONTROL_ACTIVE,
2174d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik            SENSOR_TYPE_FUEL_DOOR_OPEN,
2184d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik            SENSOR_TYPE_EV_BATTERY_LEVEL,
2194d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik            SENSOR_TYPE_EV_CHARGE_PORT_OPEN,
2204d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik            SENSOR_TYPE_EV_CHARGE_PORT_CONNECTED,
2214d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik            SENSOR_TYPE_EV_BATTERY_CHARGE_RATE,
2224d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik            SENSOR_TYPE_ENGINE_OIL_LEVEL,
2234d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik    }));
2244d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik
225cc449f7941456a0133ff8a4b2e49737f0936c1d0keunyoung    /** Read sensor in default normal rate set for each sensors. This is default rate. */
2264d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik    public static final int SENSOR_RATE_NORMAL  = 1;
2274d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik    public static final int SENSOR_RATE_UI = 5;
2284d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik    public static final int SENSOR_RATE_FAST = 10;
229cc449f7941456a0133ff8a4b2e49737f0936c1d0keunyoung    /** Read sensor at the maximum rate. Actual rate will be different depending on the sensor. */
2304d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik    public static final int SENSOR_RATE_FASTEST = 100;
231ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung
232af2cc99a2e8eea38a75b20b952ea5c0e7ebb4b1bKeun-young Park    /** @hide */
233af2cc99a2e8eea38a75b20b952ea5c0e7ebb4b1bKeun-young Park    @IntDef({
2344d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik            SENSOR_RATE_NORMAL,
2354d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik            SENSOR_RATE_UI,
2364d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik            SENSOR_RATE_FAST,
2374d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik            SENSOR_RATE_FASTEST
238af2cc99a2e8eea38a75b20b952ea5c0e7ebb4b1bKeun-young Park    })
239af2cc99a2e8eea38a75b20b952ea5c0e7ebb4b1bKeun-young Park    @Retention(RetentionPolicy.SOURCE)
240af2cc99a2e8eea38a75b20b952ea5c0e7ebb4b1bKeun-young Park    public @interface SensorRate {}
241af2cc99a2e8eea38a75b20b952ea5c0e7ebb4b1bKeun-young Park
2424d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik    private CarPropertyEventListenerToBase mCarPropertyEventListener = null;
243ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung
244ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    /**
2454d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik     * To keep record of CarPropertyEventListenerToBase
246ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     */
2474d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik    private final HashMap<OnSensorChangedListener, CarPropertyEventListenerToBase> mListenerMap =
2484d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik            new HashMap<>();
2494d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik    /**
2504d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik     * Listener for car sensor data change.
2514d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik     * Callbacks are called in the Looper context.
2524d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik     */
2534d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik    public interface OnSensorChangedListener {
2544d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik        /**
2554d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik         * Called when there is a new sensor data from car.
2564d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik         * @param event Incoming sensor event for the given sensor type.
2574d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik         */
2584d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik        void onSensorChanged(CarSensorEvent event);
2594d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik    }
260ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung
2614d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik    private static class CarPropertyEventListenerToBase implements
2624d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik            CarPropertyManager.CarPropertyEventListener{
2634d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik        private final WeakReference<CarSensorManager> mManager;
2644d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik        private final OnSensorChangedListener mListener;
2654d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik        CarPropertyEventListenerToBase(CarSensorManager manager, OnSensorChangedListener listener) {
2664d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik            mManager = new WeakReference<>(manager);
2674d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik            mListener = listener;
2684d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik        }
269ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung
2704d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik        @Override
2714d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik        public void onChangeEvent(CarPropertyValue value) {
272da0eecb6294719791537bd8de5b881e35355bc86Kai            CarSensorManager manager = mManager.get();
273da0eecb6294719791537bd8de5b881e35355bc86Kai            if (manager != null) {
274da0eecb6294719791537bd8de5b881e35355bc86Kai                manager.handleOnChangeEvent(value, mListener);
2754d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik            }
2764d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik        }
277ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung
2784d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik        @Override
2794d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik        public void onErrorEvent(int propertyId, int zone) {
2804d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik
2814d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik        }
2824d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik    }
2834d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik
2844d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik    private void handleOnChangeEvent(CarPropertyValue value, OnSensorChangedListener listener) {
2854d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik        synchronized (mListenerMap) {
2864d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik            CarSensorEvent event = createCarSensorEvent(value);
2874d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik            listener.onSensorChanged(event);
2884d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik        }
2894d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik    }
2904d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik
2914d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik    private void handleOnErrorEvent(int propertyId, int zone) {
2924d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik
2934d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik    }
294ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    /** @hide */
2953ee334d8c220f631d2ea7fa225af148f41b43354Jason Tholstrup    public CarSensorManager(IBinder service, Context context, Handler handler) {
2964d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik        mCarPropertyMgr = new CarPropertyManager(service, handler, DBG, TAG);
297ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    }
298ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung
299ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    /** @hide */
300ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    @Override
301ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    public void onCarDisconnected() {
3024d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik        synchronized (mListenerMap) {
3034d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik            mListenerMap.clear();
304ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        }
3054d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik        mCarPropertyMgr.onCarDisconnected();
306ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    }
307ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung
308ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    /**
309ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * Give the list of CarSensors available in the connected car.
310ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * @return array of all sensor types supported.
311d72b53500006e84b0c69e650878267c693c164a3Jason Tholstrup     * @throws CarNotConnectedException if the connection to the car service has been lost.
312ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     */
313ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    public int[] getSupportedSensors() throws CarNotConnectedException {
314ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        try {
3154d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik            List<CarPropertyConfig> carPropertyConfigList = getPropertyList();
3164d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik            int[] supportedSensors = new int[carPropertyConfigList.size()];
3174d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik            for (int i = 0; i < supportedSensors.length; i++) {
3184d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik                supportedSensors[i] = carPropertyConfigList.get(i).getPropertyId();
3194d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik            }
3204d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik            return supportedSensors;
321ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        } catch (IllegalStateException e) {
322ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung            CarApiUtil.checkCarNotConnectedExceptionFromCarService(e);
323ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        }
324ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        return new int[0];
325ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    }
326ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung
3277e109f38b91024586e82b03f552de33360fc57b7Kai    /**
3287e109f38b91024586e82b03f552de33360fc57b7Kai     * Get list of properties represented by CarSensorManager for this car.
3297e109f38b91024586e82b03f552de33360fc57b7Kai     * @return List of CarPropertyConfig objects available via Car Cabin Manager.
3307e109f38b91024586e82b03f552de33360fc57b7Kai     * @throws CarNotConnectedException if the connection to the car service has been lost.
3317e109f38b91024586e82b03f552de33360fc57b7Kai     */
3327e109f38b91024586e82b03f552de33360fc57b7Kai    public List<CarPropertyConfig> getPropertyList() throws CarNotConnectedException {
3334d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik        return mCarPropertyMgr.getPropertyList(mSensorConfigIds);
3344d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik    }
3357e109f38b91024586e82b03f552de33360fc57b7Kai
336ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    /**
337ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * Tells if given sensor is supported or not.
338ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * @param sensorType
339ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * @return true if the sensor is supported.
340d72b53500006e84b0c69e650878267c693c164a3Jason Tholstrup     * @throws CarNotConnectedException if the connection to the car service has been lost.
341ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     */
342af2cc99a2e8eea38a75b20b952ea5c0e7ebb4b1bKeun-young Park    public boolean isSensorSupported(@SensorType int sensorType) throws CarNotConnectedException {
343ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        int[] sensors = getSupportedSensors();
344ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        for (int sensorSupported: sensors) {
345ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung            if (sensorType == sensorSupported) {
346ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung                return true;
347ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung            }
348ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        }
349ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        return false;
350ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    }
351ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung
352ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    /**
353ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * Check if given sensorList is including the sensorType.
354ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * @param sensorList
355ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * @param sensorType
356ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * @return
357ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     */
358af2cc99a2e8eea38a75b20b952ea5c0e7ebb4b1bKeun-young Park    public static boolean isSensorSupported(int[] sensorList, @SensorType int sensorType) {
359ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        for (int sensorSupported: sensorList) {
360ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung            if (sensorType == sensorSupported) {
361ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung                return true;
362ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung            }
363ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        }
364ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        return false;
365ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    }
366ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung
367ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    /**
368d72b53500006e84b0c69e650878267c693c164a3Jason Tholstrup     * Register {@link OnSensorChangedListener} to get repeated sensor updates. Multiple listeners
369ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * can be registered for a single sensor or the same listener can be used for different sensors.
370ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * If the same listener is registered again for the same sensor, it will be either ignored or
371ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * updated depending on the rate.
372ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * <p>
373289ab99688d226518e47a7e47c9ffc20f221f0a6Steve Paik     * Requires {@link Car#PERMISSION_SPEED} for {@link #SENSOR_TYPE_CAR_SPEED} and
374289ab99688d226518e47a7e47c9ffc20f221f0a6Steve Paik     *  {@link #SENSOR_TYPE_WHEEL_TICK_DISTANCE}, {@link Car#PERMISSION_MILEAGE} for
37568ee16bde23d44fc4bafd30732bf50145a2fe9ffKai     *  {@link #SENSOR_TYPE_ODOMETER}, {@link Car#PERMISSION_ENERGY} for
376d0ebac2c18d1d226fcd2c92533846f23927d3ae3Steve Paik     *  {@link #SENSOR_TYPE_FUEL_LEVEL} and (@link #SENSOR_TYPE_EV_BATTERY_LEVEL and
37768ee16bde23d44fc4bafd30732bf50145a2fe9ffKai     *  {@link #SENSOR_TYPE_EV_CHARGE_RATE}, {@link Car#PERMISSION_CAR_DYNAMICS_STATE} for
378289ab99688d226518e47a7e47c9ffc20f221f0a6Steve Paik     *  {@link #SENSOR_TYPE_ABS_ACTIVE} and {@link #SENSOR_TYPE_TRACTION_CONTROL_ACTIVE}
379ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     *
380ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * @param listener
381ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * @param sensorType sensor type to subscribe.
382ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * @param rate how fast the sensor events are delivered. It should be one of
38345e59a01ae0d00694743b49b6e3135ad97557e6fPavel Maltsev     *        {@link #SENSOR_RATE_FASTEST}, {@link #SENSOR_RATE_FAST}, {@link #SENSOR_RATE_UI},
38445e59a01ae0d00694743b49b6e3135ad97557e6fPavel Maltsev     *        {@link #SENSOR_RATE_NORMAL}. Rate may not be respected especially when the same sensor
38545e59a01ae0d00694743b49b6e3135ad97557e6fPavel Maltsev     *        is registered with different listener with different rates. Also, rate might be
38645e59a01ae0d00694743b49b6e3135ad97557e6fPavel Maltsev     *        ignored when vehicle property raises events only when the value is actually changed,
38745e59a01ae0d00694743b49b6e3135ad97557e6fPavel Maltsev     *        for example {@link #SENSOR_TYPE_PARKING_BRAKE} will raise an event only when parking
38845e59a01ae0d00694743b49b6e3135ad97557e6fPavel Maltsev     *        brake was engaged or disengaged.
389ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * @return if the sensor was successfully enabled.
390d72b53500006e84b0c69e650878267c693c164a3Jason Tholstrup     * @throws CarNotConnectedException if the connection to the car service has been lost.
391ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * @throws IllegalArgumentException for wrong argument like wrong rate
392ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * @throws SecurityException if missing the appropriate permission
393ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     */
394ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    @RequiresPermission(anyOf={Manifest.permission.ACCESS_FINE_LOCATION, Car.PERMISSION_SPEED,
39568ee16bde23d44fc4bafd30732bf50145a2fe9ffKai            Car.PERMISSION_MILEAGE, Car.PERMISSION_ENERGY, Car.PERMISSION_CAR_DYNAMICS_STATE},
396289ab99688d226518e47a7e47c9ffc20f221f0a6Steve Paik            conditional=true)
397af2cc99a2e8eea38a75b20b952ea5c0e7ebb4b1bKeun-young Park    public boolean registerListener(OnSensorChangedListener listener, @SensorType int sensorType,
398af2cc99a2e8eea38a75b20b952ea5c0e7ebb4b1bKeun-young Park            @SensorRate int rate) throws CarNotConnectedException, IllegalArgumentException {
39945e59a01ae0d00694743b49b6e3135ad97557e6fPavel Maltsev        if (rate != SENSOR_RATE_FASTEST && rate != SENSOR_RATE_NORMAL
40045e59a01ae0d00694743b49b6e3135ad97557e6fPavel Maltsev                && rate != SENSOR_RATE_UI && rate != SENSOR_RATE_FAST) {
401ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung            throw new IllegalArgumentException("wrong rate " + rate);
402ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        }
4034d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik        if (mListenerMap.get(listener) == null) {
4044d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik            mCarPropertyEventListener = new CarPropertyEventListenerToBase(this, listener);
4054d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik        } else {
4064d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik            mCarPropertyEventListener = mListenerMap.get(listener);
4074d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik        }
4084d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik        if (mCarPropertyMgr.registerListener(mCarPropertyEventListener, sensorType, rate)) {
4094d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik            mListenerMap.put(listener, mCarPropertyEventListener);
4104d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik            return true;
4114d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik        } else {
4124d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik            return false;
413ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        }
414ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    }
415ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung
416ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    /**
417ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * Stop getting sensor update for the given listener. If there are multiple registrations for
418ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * this listener, all listening will be stopped.
419ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * @param listener
420ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     */
421150d8de43e71a624106e90bcc04067414c42ef18Keun-young Park    public void unregisterListener(OnSensorChangedListener listener) {
422f9215209e0f425d2fc570bef37dad959c82d2e9eKeun-young Park        //TODO: removing listener should reset update rate, bug: 32060307
4234d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik        synchronized (mListenerMap) {
4244d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik            mCarPropertyEventListener = mListenerMap.get(listener);
4254d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik            mCarPropertyMgr.unregisterListener(mCarPropertyEventListener);
4264d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik            mListenerMap.remove(listener);
427ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        }
428ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    }
429ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung
430ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    /**
431ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * Stop getting sensor update for the given listener and sensor. If the same listener is used
432ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * for other sensors, those subscriptions will not be affected.
433ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * @param listener
434ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * @param sensorType
435ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     */
436150d8de43e71a624106e90bcc04067414c42ef18Keun-young Park    public void unregisterListener(OnSensorChangedListener listener, @SensorType int sensorType) {
4374d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik        synchronized (mListenerMap) {
4384d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik            mCarPropertyEventListener = mListenerMap.get(listener);
439ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        }
4404d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik        mCarPropertyMgr.unregisterListener(mCarPropertyEventListener, sensorType);
441ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    }
442ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung
443ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    /**
4444afc6ee52690326316e2ed1b7bc354f466849426Keun-young Park     * Get the most recent CarSensorEvent for the given type. Note that latest sensor data from car
4454afc6ee52690326316e2ed1b7bc354f466849426Keun-young Park     * will not be available if it was never subscribed before. This call will return immediately
4464afc6ee52690326316e2ed1b7bc354f466849426Keun-young Park     * with null if there is no data available.
447ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * @param type A sensor to request
448ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * @return null if there was no sensor update since connected to the car.
449d72b53500006e84b0c69e650878267c693c164a3Jason Tholstrup     * @throws CarNotConnectedException if the connection to the car service has been lost.
450ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     */
451af2cc99a2e8eea38a75b20b952ea5c0e7ebb4b1bKeun-young Park    public CarSensorEvent getLatestSensorEvent(@SensorType int type)
452af2cc99a2e8eea38a75b20b952ea5c0e7ebb4b1bKeun-young Park            throws CarNotConnectedException {
453ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        try {
4544d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik            CarPropertyValue propertyValue = mCarPropertyMgr.getProperty(type, 0);
4554d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik            return createCarSensorEvent(propertyValue);
456ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        } catch (IllegalStateException e) {
457ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung            CarApiUtil.checkCarNotConnectedExceptionFromCarService(e);
458ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        }
459ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        return null;
460ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    }
461ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung
462ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    private void handleCarServiceRemoteExceptionAndThrow(RemoteException e)
463ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung            throws CarNotConnectedException {
464ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        if (Log.isLoggable(CarLibLog.TAG_SENSOR, Log.INFO)) {
465ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung            Log.i(CarLibLog.TAG_SENSOR, "RemoteException from car service:" + e.getMessage());
466ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        }
467ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        throw new CarNotConnectedException();
468ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    }
469ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung
4704d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik    private CarSensorEvent createCarSensorEvent(CarPropertyValue propertyValue) {
4714d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik        CarSensorEvent event = null;
472417631a1fb9a280d365aab6fb8d3b38ccd65e142Steve Paik        switch (propertyValue.getPropertyId() & VehiclePropertyType.MASK) {
473417631a1fb9a280d365aab6fb8d3b38ccd65e142Steve Paik            case VehiclePropertyType.FLOAT:
474417631a1fb9a280d365aab6fb8d3b38ccd65e142Steve Paik                event = new CarSensorEvent(propertyValue.getPropertyId(),
475417631a1fb9a280d365aab6fb8d3b38ccd65e142Steve Paik                        propertyValue.getTimestamp(), 1, 0, 0);
476417631a1fb9a280d365aab6fb8d3b38ccd65e142Steve Paik                event.floatValues[0] = (float) propertyValue.getValue();
477417631a1fb9a280d365aab6fb8d3b38ccd65e142Steve Paik                break;
478417631a1fb9a280d365aab6fb8d3b38ccd65e142Steve Paik            case VehiclePropertyType.INT32:
479417631a1fb9a280d365aab6fb8d3b38ccd65e142Steve Paik                event = new CarSensorEvent(propertyValue.getPropertyId(),
480417631a1fb9a280d365aab6fb8d3b38ccd65e142Steve Paik                        propertyValue.getTimestamp(), 0, 1, 0);
481417631a1fb9a280d365aab6fb8d3b38ccd65e142Steve Paik                event.intValues[0] = (int) propertyValue.getValue();
482417631a1fb9a280d365aab6fb8d3b38ccd65e142Steve Paik                break;
483417631a1fb9a280d365aab6fb8d3b38ccd65e142Steve Paik            case VehiclePropertyType.BOOLEAN:
484417631a1fb9a280d365aab6fb8d3b38ccd65e142Steve Paik                event = new CarSensorEvent(propertyValue.getPropertyId(),
485417631a1fb9a280d365aab6fb8d3b38ccd65e142Steve Paik                        propertyValue.getTimestamp(), 0, 1, 0);
486417631a1fb9a280d365aab6fb8d3b38ccd65e142Steve Paik                event.intValues[0] = (boolean) propertyValue.getValue() ? 1 : 0;
487417631a1fb9a280d365aab6fb8d3b38ccd65e142Steve Paik                break;
488417631a1fb9a280d365aab6fb8d3b38ccd65e142Steve Paik            case VehiclePropertyType.INT64_VEC:
489417631a1fb9a280d365aab6fb8d3b38ccd65e142Steve Paik                Object[] value = (Object[]) propertyValue.getValue();
490417631a1fb9a280d365aab6fb8d3b38ccd65e142Steve Paik                event = new CarSensorEvent(propertyValue.getPropertyId(),
491417631a1fb9a280d365aab6fb8d3b38ccd65e142Steve Paik                        propertyValue.getTimestamp(), 0, 0, value.length);
492417631a1fb9a280d365aab6fb8d3b38ccd65e142Steve Paik                for (int i = 0; i < value.length; i++) {
493417631a1fb9a280d365aab6fb8d3b38ccd65e142Steve Paik                    event.longValues[i] = (Long) value[i];
494417631a1fb9a280d365aab6fb8d3b38ccd65e142Steve Paik                }
495417631a1fb9a280d365aab6fb8d3b38ccd65e142Steve Paik                break;
496417631a1fb9a280d365aab6fb8d3b38ccd65e142Steve Paik            default:
497417631a1fb9a280d365aab6fb8d3b38ccd65e142Steve Paik                Log.e(TAG, "unhandled VehiclePropertyType for propId="
498417631a1fb9a280d365aab6fb8d3b38ccd65e142Steve Paik                        + propertyValue.getPropertyId());
499417631a1fb9a280d365aab6fb8d3b38ccd65e142Steve Paik                break;
500ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        }
5014d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik        return event;
502ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    }
503a2819901c1b4f56e4950dd5cb6bf6c9e8042cf4cSteve Paik
504a2819901c1b4f56e4950dd5cb6bf6c9e8042cf4cSteve Paik    /**
505a2819901c1b4f56e4950dd5cb6bf6c9e8042cf4cSteve Paik     * Get the config data for the given type.
506a2819901c1b4f56e4950dd5cb6bf6c9e8042cf4cSteve Paik     *
507a2819901c1b4f56e4950dd5cb6bf6c9e8042cf4cSteve Paik     * A CarSensorConfig object is returned for every sensor type.  However, if there is no
508a2819901c1b4f56e4950dd5cb6bf6c9e8042cf4cSteve Paik     * config, the data will be empty.
509a2819901c1b4f56e4950dd5cb6bf6c9e8042cf4cSteve Paik     *
510a2819901c1b4f56e4950dd5cb6bf6c9e8042cf4cSteve Paik     * @param sensor type to request
511a2819901c1b4f56e4950dd5cb6bf6c9e8042cf4cSteve Paik     * @return CarSensorConfig object
512a2819901c1b4f56e4950dd5cb6bf6c9e8042cf4cSteve Paik     * @throws CarNotConnectedException if the connection to the car service has been lost.
513a2819901c1b4f56e4950dd5cb6bf6c9e8042cf4cSteve Paik     * @hide
514a2819901c1b4f56e4950dd5cb6bf6c9e8042cf4cSteve Paik     */
515a2819901c1b4f56e4950dd5cb6bf6c9e8042cf4cSteve Paik    public CarSensorConfig getSensorConfig(@SensorType int type)
5164d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik            throws CarNotConnectedException {
5174d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik        Bundle b = null;
5184d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik        switch (type) {
5194d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik            case SENSOR_TYPE_WHEEL_TICK_DISTANCE:
5204d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik                List<CarPropertyConfig> propertyConfigs = mCarPropertyMgr.getPropertyList();
5214d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik                for (CarPropertyConfig p : propertyConfigs) {
5224d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik                    if (p.getPropertyId() == type) {
5234d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik                        b = createWheelDistanceTickBundle(p.getConfigArray());
524da0eecb6294719791537bd8de5b881e35355bc86Kai                        break;
5254d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik                    }
5264d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik                }
5274d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik                break;
5284d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik            default:
5294d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik                b = Bundle.EMPTY;
5304d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik                break;
531a2819901c1b4f56e4950dd5cb6bf6c9e8042cf4cSteve Paik        }
5324d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik        return new CarSensorConfig(type, b);
5334d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik    }
5344d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik
5354d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik    private static final int INDEX_WHEEL_DISTANCE_ENABLE_FLAG = 0;
5364d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik    private static final int INDEX_WHEEL_DISTANCE_FRONT_LEFT = 1;
5374d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik    private static final int INDEX_WHEEL_DISTANCE_FRONT_RIGHT = 2;
5384d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik    private static final int INDEX_WHEEL_DISTANCE_REAR_RIGHT = 3;
5394d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik    private static final int INDEX_WHEEL_DISTANCE_REAR_LEFT = 4;
5404d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik    private static final int WHEEL_TICK_DISTANCE_BUNDLE_SIZE = 6;
5414d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik
5424d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik    private Bundle createWheelDistanceTickBundle(List<Integer> configArray) {
5434d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik        Bundle b = new Bundle(WHEEL_TICK_DISTANCE_BUNDLE_SIZE);
5444d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik        b.putInt(CarSensorConfig.WHEEL_TICK_DISTANCE_SUPPORTED_WHEELS,
5454d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik                configArray.get(INDEX_WHEEL_DISTANCE_ENABLE_FLAG));
5464d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik        b.putInt(CarSensorConfig.WHEEL_TICK_DISTANCE_FRONT_LEFT_UM_PER_TICK,
5474d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik                configArray.get(INDEX_WHEEL_DISTANCE_FRONT_LEFT));
5484d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik        b.putInt(CarSensorConfig.WHEEL_TICK_DISTANCE_FRONT_RIGHT_UM_PER_TICK,
5494d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik                configArray.get(INDEX_WHEEL_DISTANCE_FRONT_RIGHT));
5504d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik        b.putInt(CarSensorConfig.WHEEL_TICK_DISTANCE_REAR_RIGHT_UM_PER_TICK,
5514d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik                configArray.get(INDEX_WHEEL_DISTANCE_REAR_RIGHT));
5524d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik        b.putInt(CarSensorConfig.WHEEL_TICK_DISTANCE_REAR_LEFT_UM_PER_TICK,
5534d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik                configArray.get(INDEX_WHEEL_DISTANCE_REAR_LEFT));
5544d257023389c23b8836f10cda1bfa1ea136f56c9Steve Paik        return b;
555a2819901c1b4f56e4950dd5cb6bf6c9e8042cf4cSteve Paik    }
556ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung}
557