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