• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
17 package android.car.drivingstate;
18 
19 import android.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.annotation.SystemApi;
22 import android.annotation.TestApi;
23 import android.car.Car;
24 import android.car.CarManagerBase;
25 import android.car.annotation.AddedInOrBefore;
26 import android.os.Handler;
27 import android.os.IBinder;
28 import android.os.Looper;
29 import android.os.Message;
30 import android.os.RemoteException;
31 import android.os.SystemClock;
32 import android.util.Log;
33 
34 import java.lang.ref.WeakReference;
35 
36 /**
37  * API to register and get driving state related information in a car.
38  *
39  * @hide
40  */
41 @SystemApi
42 @TestApi
43 public final class CarDrivingStateManager extends CarManagerBase {
44     private static final String TAG = "CarDrivingStateMgr";
45     private static final boolean DBG = false;
46     private static final boolean VDBG = false;
47     private static final int MSG_HANDLE_DRIVING_STATE_CHANGE = 0;
48 
49     private final ICarDrivingState mDrivingService;
50     private final EventCallbackHandler mEventCallbackHandler;
51     private CarDrivingStateEventListener mDrvStateEventListener;
52     private CarDrivingStateChangeListenerToService mListenerToService;
53 
54 
55     /** @hide */
CarDrivingStateManager(Car car, IBinder service)56     public CarDrivingStateManager(Car car, IBinder service) {
57         super(car);
58         mDrivingService = ICarDrivingState.Stub.asInterface(service);
59         mEventCallbackHandler = new EventCallbackHandler(this, getEventHandler().getLooper());
60     }
61 
62     /** @hide */
63     @Override
64     @AddedInOrBefore(majorVersion = 33)
onCarDisconnected()65     public synchronized void onCarDisconnected() {
66         mListenerToService = null;
67         mDrvStateEventListener = null;
68     }
69 
70     /**
71      * Listener Interface for clients to implement to get updated on driving state changes.
72      *
73      * @hide
74      */
75     @SystemApi
76     public interface CarDrivingStateEventListener {
77         /**
78          * Called when the car's driving state changes.
79          * @param event Car's driving state.
80          */
81         @AddedInOrBefore(majorVersion = 33)
onDrivingStateChanged(CarDrivingStateEvent event)82         void onDrivingStateChanged(CarDrivingStateEvent event);
83     }
84 
85     /**
86      * Register a {@link CarDrivingStateEventListener} to listen for driving state changes.
87      *
88      * @param listener  {@link CarDrivingStateEventListener}
89      *
90      * @hide
91      */
92     @SystemApi
93     @AddedInOrBefore(majorVersion = 33)
registerListener(@onNull CarDrivingStateEventListener listener)94     public synchronized void registerListener(@NonNull CarDrivingStateEventListener listener) {
95         if (listener == null) {
96             if (VDBG) {
97                 Log.v(TAG, "registerCarDrivingStateEventListener(): null listener");
98             }
99             throw new IllegalArgumentException("Listener is null");
100         }
101         // Check if the listener has been already registered for this event type
102         if (mDrvStateEventListener != null) {
103             if (DBG) {
104                 Log.d(TAG, "Listener already registered");
105             }
106             return;
107         }
108         mDrvStateEventListener = listener;
109         try {
110             if (mListenerToService == null) {
111                 mListenerToService = new CarDrivingStateChangeListenerToService(this);
112             }
113             // register to the Service for getting notified
114             mDrivingService.registerDrivingStateChangeListener(mListenerToService);
115         } catch (RemoteException e) {
116             handleRemoteExceptionFromCarService(e);
117         }
118     }
119 
120     /**
121      * Unregister the registered {@link CarDrivingStateEventListener} for the given driving event
122      * type.
123      *
124      * @hide
125      */
126     @SystemApi
127     @AddedInOrBefore(majorVersion = 33)
unregisterListener()128     public synchronized void unregisterListener() {
129         if (mDrvStateEventListener == null) {
130             if (DBG) {
131                 Log.d(TAG, "Listener was not previously registered");
132             }
133             return;
134         }
135         try {
136             mDrivingService.unregisterDrivingStateChangeListener(mListenerToService);
137             mDrvStateEventListener = null;
138             mListenerToService = null;
139         } catch (RemoteException e) {
140             handleRemoteExceptionFromCarService(e);
141         }
142     }
143 
144     /**
145      * Get the current value of the car's driving state.
146      *
147      * @return {@link CarDrivingStateEvent} corresponding to the given eventType
148      *
149      * @hide
150      */
151     @Nullable
152     @SystemApi
153     @AddedInOrBefore(majorVersion = 33)
getCurrentCarDrivingState()154     public CarDrivingStateEvent getCurrentCarDrivingState() {
155         try {
156             return mDrivingService.getCurrentDrivingState();
157         } catch (RemoteException e) {
158             return handleRemoteExceptionFromCarService(e, null);
159         }
160     }
161 
162     /**
163      * Notify registered driving state change listener about injected event.
164      *
165      * @param drivingState Value in {@link CarDrivingStateEvent.CarDrivingState}.
166      *
167      * Requires Permission:
168      * {@link Car#PERMISSION_CONTROL_APP_BLOCKING}
169      *
170      * @hide
171      */
172     @TestApi
173     @AddedInOrBefore(majorVersion = 33)
injectDrivingState(int drivingState)174     public void injectDrivingState(int drivingState) {
175         CarDrivingStateEvent event = new CarDrivingStateEvent(
176                 drivingState, SystemClock.elapsedRealtimeNanos());
177         try {
178             mDrivingService.injectDrivingState(event);
179         } catch (RemoteException e) {
180             handleRemoteExceptionFromCarService(e);
181         }
182     }
183 
184     /**
185      * Class that implements the listener interface and gets called back from the
186      * {@link com.android.car.CarDrivingStateService} across the binder interface.
187      */
188     private static class CarDrivingStateChangeListenerToService extends
189             ICarDrivingStateChangeListener.Stub {
190         private final WeakReference<CarDrivingStateManager> mDrvStateMgr;
191 
CarDrivingStateChangeListenerToService(CarDrivingStateManager manager)192         CarDrivingStateChangeListenerToService(CarDrivingStateManager manager) {
193             mDrvStateMgr = new WeakReference<>(manager);
194         }
195 
196         @Override
onDrivingStateChanged(CarDrivingStateEvent event)197         public void onDrivingStateChanged(CarDrivingStateEvent event) {
198             CarDrivingStateManager manager = mDrvStateMgr.get();
199             if (manager != null) {
200                 manager.handleDrivingStateChanged(event);
201             }
202         }
203     }
204 
205     /**
206      * Gets the {@link CarDrivingStateEvent} from the service listener
207      * {@link CarDrivingStateChangeListenerToService} and dispatches it to a handler provided
208      * to the manager
209      *
210      * @param event  {@link CarDrivingStateEvent} that has been registered to listen on
211      */
handleDrivingStateChanged(CarDrivingStateEvent event)212     private void handleDrivingStateChanged(CarDrivingStateEvent event) {
213         // send a message to the handler
214         mEventCallbackHandler.sendMessage(
215                 mEventCallbackHandler.obtainMessage(MSG_HANDLE_DRIVING_STATE_CHANGE, event));
216 
217     }
218 
219     /**
220      * Callback Handler to handle dispatching the driving state changes to the corresponding
221      * listeners
222      */
223     private static final class EventCallbackHandler extends Handler {
224         private final WeakReference<CarDrivingStateManager> mDrvStateMgr;
225 
EventCallbackHandler(CarDrivingStateManager manager, Looper looper)226         EventCallbackHandler(CarDrivingStateManager manager, Looper looper) {
227             super(looper);
228             mDrvStateMgr = new WeakReference<>(manager);
229         }
230 
231         @Override
handleMessage(Message msg)232         public void handleMessage(Message msg) {
233             CarDrivingStateManager mgr = mDrvStateMgr.get();
234             if (mgr != null) {
235                 mgr.dispatchDrivingStateChangeToClient((CarDrivingStateEvent) msg.obj);
236             }
237         }
238 
239     }
240 
241     /**
242      * Checks for the listener to {@link CarDrivingStateEvent} and calls it back
243      * in the callback handler thread
244      *
245      * @param event  {@link CarDrivingStateEvent}
246      */
dispatchDrivingStateChangeToClient(CarDrivingStateEvent event)247     private void dispatchDrivingStateChangeToClient(CarDrivingStateEvent event) {
248         if (event == null) {
249             return;
250         }
251         CarDrivingStateEventListener listener;
252         synchronized (this) {
253             listener = mDrvStateEventListener;
254         }
255         if (listener != null) {
256             listener.onDrivingStateChanged(event);
257         }
258     }
259 
260 }
261