1 /* 2 * Copyright (C) 2016 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 package android.car.navigation; 17 18 import android.annotation.IntDef; 19 import android.car.CarApiUtil; 20 import android.car.CarLibLog; 21 import android.car.CarManagerBase; 22 import android.car.CarNotConnectedException; 23 import android.car.cluster.renderer.IInstrumentClusterNavigation; 24 import android.graphics.Bitmap; 25 import android.os.IBinder; 26 import android.os.RemoteException; 27 import android.util.Log; 28 29 import java.lang.annotation.Retention; 30 import java.lang.annotation.RetentionPolicy; 31 32 /** 33 * API for providing navigation status for instrument cluster. 34 * @hide 35 */ 36 public final class CarNavigationStatusManager implements CarManagerBase { 37 38 /** Navigation status */ 39 public static final int STATUS_UNAVAILABLE = 0; 40 public static final int STATUS_ACTIVE = 1; 41 public static final int STATUS_INACTIVE = 2; 42 43 /** @hide */ 44 @IntDef({ 45 STATUS_UNAVAILABLE, 46 STATUS_ACTIVE, 47 STATUS_INACTIVE 48 }) 49 @Retention(RetentionPolicy.SOURCE) 50 public @interface Status {} 51 52 /* Turn Types */ 53 /** Turn is of an unknown type.*/ 54 public static final int TURN_UNKNOWN = 0; 55 /** Starting point of the navigation. */ 56 public static final int TURN_DEPART = 1; 57 /** No turn, but the street name changes. */ 58 public static final int TURN_NAME_CHANGE = 2; 59 /** Slight turn. */ 60 public static final int TURN_SLIGHT_TURN = 3; 61 /** Regular turn. */ 62 public static final int TURN_TURN = 4; 63 /** Sharp turn. */ 64 public static final int TURN_SHARP_TURN = 5; 65 /** U-turn. */ 66 public static final int TURN_U_TURN = 6; 67 /** On ramp. */ 68 public static final int TURN_ON_RAMP = 7; 69 /** Off ramp. */ 70 public static final int TURN_OFF_RAMP = 8; 71 /** Road forks (diverges). */ 72 public static final int TURN_FORK = 9; 73 /** Road merges. */ 74 public static final int TURN_MERGE = 10; 75 /** Roundabout entrance on which the route ends. Instruction says "Enter roundabout". */ 76 public static final int TURN_ROUNDABOUT_ENTER = 11; 77 /** Roundabout exit. */ 78 public static final int TURN_ROUNDABOUT_EXIT = 12; 79 /** 80 * Roundabout entrance and exit. For example, "At the roundabout, take Nth exit." Be sure to 81 * specify the "turnNumber" parameter when using this type. 82 */ 83 public static final int TURN_ROUNDABOUT_ENTER_AND_EXIT = 13; 84 /** Potentially confusing intersection where the user should steer straight. */ 85 public static final int TURN_STRAIGHT = 14; 86 /** You're on a boat! */ 87 public static final int TURN_FERRY_BOAT = 16; 88 /** Train ferries for vehicles. */ 89 public static final int TURN_FERRY_TRAIN = 17; 90 /** You have arrived. */ 91 public static final int TURN_DESTINATION = 19; 92 93 /** @hide */ 94 @IntDef({ 95 TURN_UNKNOWN, 96 TURN_DEPART, 97 TURN_NAME_CHANGE, 98 TURN_SLIGHT_TURN, 99 TURN_TURN, 100 TURN_SHARP_TURN, 101 TURN_U_TURN, 102 TURN_ON_RAMP, 103 TURN_OFF_RAMP, 104 TURN_FORK, 105 TURN_MERGE, 106 TURN_ROUNDABOUT_ENTER, 107 TURN_ROUNDABOUT_EXIT, 108 TURN_ROUNDABOUT_ENTER_AND_EXIT, 109 TURN_STRAIGHT, 110 TURN_FERRY_BOAT, 111 TURN_FERRY_TRAIN, 112 TURN_DESTINATION 113 }) 114 @Retention(RetentionPolicy.SOURCE) 115 public @interface TurnEvent {} 116 117 /* Turn Side */ 118 /** Turn is on the left side of the vehicle. */ 119 public static final int TURN_SIDE_LEFT = 1; 120 /** Turn is on the right side of the vehicle. */ 121 public static final int TURN_SIDE_RIGHT = 2; 122 /** Turn side is unspecified. */ 123 public static final int TURN_SIDE_UNSPECIFIED = 3; 124 125 /** @hide */ 126 @IntDef({ 127 TURN_SIDE_LEFT, 128 TURN_SIDE_RIGHT, 129 TURN_SIDE_UNSPECIFIED 130 }) 131 public @interface TurnSide {} 132 133 private static final int START = 1; 134 private static final int STOP = 2; 135 136 /** 137 * Distance units for use in {@link #sendNavigationTurnDistanceEvent(int, int, int, int)}. 138 */ 139 /** Distance is specified in meters. */ 140 public static final int DISTANCE_METERS = 1; 141 /** Distance is specified in kilometers. */ 142 public static final int DISTANCE_KILOMETERS = 2; 143 /** Distance is specified in miles. */ 144 public static final int DISTANCE_MILES = 3; 145 /** Distance is specified in feet. */ 146 public static final int DISTANCE_FEET = 4; 147 /** Distance is specified in yards. */ 148 public static final int DISTANCE_YARDS = 5; 149 150 /** @hide */ 151 @IntDef({ 152 DISTANCE_METERS, 153 DISTANCE_KILOMETERS, 154 DISTANCE_MILES, 155 DISTANCE_FEET, 156 DISTANCE_YARDS 157 }) 158 public @interface DistanceUnit {} 159 160 private static final String TAG = CarLibLog.TAG_NAV; 161 162 private final IInstrumentClusterNavigation mService; 163 164 165 /** 166 * Only for CarServiceLoader 167 * @hide 168 */ CarNavigationStatusManager(IBinder service)169 public CarNavigationStatusManager(IBinder service) { 170 mService = IInstrumentClusterNavigation.Stub.asInterface(service); 171 } 172 173 /** 174 * @param status new instrument cluster navigation status. 175 * @throws CarNotConnectedException if the connection to the car service has been lost. 176 */ sendNavigationStatus(@tatus int status)177 public void sendNavigationStatus(@Status int status) throws CarNotConnectedException { 178 try { 179 if (status == STATUS_ACTIVE) { 180 mService.onStartNavigation(); 181 } else { 182 mService.onStopNavigation(); 183 } 184 } catch (IllegalStateException e) { 185 CarApiUtil.checkCarNotConnectedExceptionFromCarService(e); 186 } catch (RemoteException e) { 187 handleCarServiceRemoteExceptionAndThrow(e); 188 } 189 } 190 191 /** 192 * Sends a Navigation Next Step event to the car. 193 * <p> 194 * Note: For an example of a roundabout: if a roundabout has 4 exits, spaced evenly, then the 195 * first exit will have turnNumber=1, turnAngle=90; the second will have turnNumber=2, 196 * turnAngle=180; the third will have turnNumber=3, turnAngle=270. turnNumber and turnAngle are 197 * counted in the direction of travel around the roundabout (clockwise for roads where the car 198 * drives on the left-hand side of the road, such as Australia; anti-clockwise for roads where 199 * the car drives on the right, such as the USA). 200 * 201 * @param event event type ({@link #TURN_TURN}, {@link #TURN_U_TURN}, 202 * {@link #TURN_ROUNDABOUT_ENTER_AND_EXIT}, etc). 203 * @param eventName Name of the turn event like road name to turn. For example "Charleston road" 204 * in "Turn right to Charleston road" 205 * @param turnAngle turn angle in degrees between the roundabout entry and exit (0..359). Only 206 * used for event type {@link #TURN_ROUNDABOUT_ENTER_AND_EXIT}. -1 if unused. 207 * @param turnNumber turn number, counting around from the roundabout entry to the exit. Only 208 * used for event type {@link #TURN_ROUNDABOUT_ENTER_AND_EXIT}. -1 if unused. 209 * @param image image to be shown in the instrument cluster. Null if instrument 210 * cluster type doesn't support images. 211 * @param turnSide turn side ({@link #TURN_SIDE_LEFT}, {@link #TURN_SIDE_RIGHT} or 212 * {@link #TURN_SIDE_UNSPECIFIED}). 213 * @throws CarNotConnectedException if the connection to the car service has been lost. 214 * 215 */ sendNavigationTurnEvent(@urnEvent int turnEvent, CharSequence eventName, int turnAngle, int turnNumber, Bitmap image, @TurnSide int turnSide)216 public void sendNavigationTurnEvent(@TurnEvent int turnEvent, CharSequence eventName, 217 int turnAngle, int turnNumber, Bitmap image, @TurnSide int turnSide) 218 throws CarNotConnectedException { 219 try { 220 mService.onNextManeuverChanged(turnEvent, eventName, turnAngle, turnNumber, image, 221 turnSide); 222 } catch (IllegalStateException e) { 223 CarApiUtil.checkCarNotConnectedExceptionFromCarService(e); 224 } catch (RemoteException e) { 225 handleCarServiceRemoteExceptionAndThrow(e); 226 } 227 } 228 229 /** 230 * Sends a Navigation Next Step Distance event to the car. 231 * 232 * @param distanceMeters Distance to next event in meters. 233 * @param timeSeconds Time to next event in seconds. 234 * @param displayDistanceMillis Distance to the next event. This is exactly the same distance 235 * that navigation app is displaying. Use it when you want to display distance, it has 236 * appropriate rounding function and units are in sync with navigation app. This parameter is 237 * in {@code displayDistanceUnit * 1000}. 238 * @param displayDistanceUnit units for {@param displayDistanceMillis} param. 239 * See {@link DistanceUnit} for acceptable values. 240 * @throws CarNotConnectedException if the connection to the car service has been lost. 241 */ sendNavigationTurnDistanceEvent(int distanceMeters, int timeSeconds, int displayDistanceMillis, @DistanceUnit int displayDistanceUnit)242 public void sendNavigationTurnDistanceEvent(int distanceMeters, int timeSeconds, 243 int displayDistanceMillis, @DistanceUnit int displayDistanceUnit) 244 throws CarNotConnectedException { 245 try { 246 mService.onNextManeuverDistanceChanged(distanceMeters, timeSeconds, 247 displayDistanceMillis, displayDistanceUnit); 248 } catch (IllegalStateException e) { 249 CarApiUtil.checkCarNotConnectedExceptionFromCarService(e); 250 } catch (RemoteException e) { 251 handleCarServiceRemoteExceptionAndThrow(e); 252 } 253 } 254 255 @Override onCarDisconnected()256 public void onCarDisconnected() { 257 Log.d(TAG, "onCarDisconnected"); 258 } 259 260 /** Returns navigation features of instrument cluster */ getInstrumentClusterInfo()261 public CarNavigationInstrumentCluster getInstrumentClusterInfo() 262 throws CarNotConnectedException { 263 try { 264 return mService.getInstrumentClusterInfo(); 265 } catch (RemoteException e) { 266 handleCarServiceRemoteExceptionAndThrow(e); 267 } 268 return null; 269 } 270 handleCarServiceRemoteExceptionAndThrow(RemoteException e)271 private void handleCarServiceRemoteExceptionAndThrow(RemoteException e) 272 throws CarNotConnectedException { 273 handleCarServiceRemoteException(e); 274 throw new CarNotConnectedException(); 275 } 276 handleCarServiceRemoteException(RemoteException e)277 private void handleCarServiceRemoteException(RemoteException e) { 278 Log.w(TAG, "RemoteException from car service:" + e.getMessage()); 279 // nothing to do for now 280 } 281 } 282