Home | History | Annotate | Download | only in navigation
      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.Bundle;
     26 import android.os.IBinder;
     27 import android.os.RemoteException;
     28 import android.util.Log;
     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     /**
    118      * Event type that holds information about next maneuver.
    119      * @hide
    120      */
    121     public static final int EVENT_TYPE_NEXT_MANEUVER_INFO = 1;
    122     /**
    123      * Event type that holds information regarding distance/time to the next maneuver.
    124      * @hide
    125      */
    126     public static final int EVENT_TYPE_NEXT_MANEUVER_COUNTDOWN = 2;
    127     /**
    128      * All custom (vendor-specific) event types should be equal or greater than this constant.
    129      * @hide
    130      */
    131     public static final int EVENT_TYPE_VENDOR_FIRST = 1024;
    132 
    133     /* Turn Side */
    134     /** Turn is on the left side of the vehicle. */
    135     public static final int TURN_SIDE_LEFT = 1;
    136     /** Turn is on the right side of the vehicle. */
    137     public static final int TURN_SIDE_RIGHT = 2;
    138     /** Turn side is unspecified. */
    139     public static final int TURN_SIDE_UNSPECIFIED = 3;
    140 
    141     /** @hide */
    142     @IntDef({
    143         TURN_SIDE_LEFT,
    144         TURN_SIDE_RIGHT,
    145         TURN_SIDE_UNSPECIFIED
    146     })
    147     public @interface TurnSide {}
    148 
    149     private static final int START = 1;
    150     private static final int STOP = 2;
    151 
    152     /**
    153      * Distance units for use in {@link #sendNavigationTurnDistanceEvent(int, int, int, int)}.
    154      */
    155     /** Distance is specified in meters. */
    156     public static final int DISTANCE_METERS = 1;
    157     /** Distance is specified in kilometers. */
    158     public static final int DISTANCE_KILOMETERS = 2;
    159     /** Distance is specified in miles. */
    160     public static final int DISTANCE_MILES = 3;
    161     /** Distance is specified in feet. */
    162     public static final int DISTANCE_FEET = 4;
    163     /** Distance is specified in yards. */
    164     public static final int DISTANCE_YARDS = 5;
    165 
    166     /** @hide */
    167     @IntDef({
    168         DISTANCE_METERS,
    169         DISTANCE_KILOMETERS,
    170         DISTANCE_MILES,
    171         DISTANCE_FEET,
    172         DISTANCE_YARDS
    173     })
    174     public @interface DistanceUnit {}
    175 
    176     private static final String TAG = CarLibLog.TAG_NAV;
    177 
    178     private final IInstrumentClusterNavigation mService;
    179 
    180 
    181     /**
    182      * Only for CarServiceLoader
    183      * @hide
    184      */
    185     public CarNavigationStatusManager(IBinder service) {
    186         mService = IInstrumentClusterNavigation.Stub.asInterface(service);
    187     }
    188 
    189     /**
    190      * @param status new instrument cluster navigation status.
    191      * @throws CarNotConnectedException if the connection to the car service has been lost.
    192      */
    193     public void sendNavigationStatus(@Status int status) throws CarNotConnectedException {
    194         try {
    195             if (status == STATUS_ACTIVE) {
    196                 mService.onStartNavigation();
    197             } else {
    198                 mService.onStopNavigation();
    199             }
    200         } catch (IllegalStateException e) {
    201             CarApiUtil.checkCarNotConnectedExceptionFromCarService(e);
    202         } catch (RemoteException e) {
    203             handleCarServiceRemoteExceptionAndThrow(e);
    204         }
    205     }
    206 
    207     /**
    208      * Sends a Navigation Next Step event to the car.
    209      * <p>
    210      * Note: For an example of a roundabout: if a roundabout has 4 exits, spaced evenly, then the
    211      * first exit will have turnNumber=1, turnAngle=90; the second will have turnNumber=2,
    212      * turnAngle=180; the third will have turnNumber=3, turnAngle=270.  turnNumber and turnAngle are
    213      * counted in the direction of travel around the roundabout (clockwise for roads where the car
    214      * drives on the left-hand side of the road, such as Australia; anti-clockwise for roads where
    215      * the car drives on the right, such as the USA).
    216      *
    217      * @param turnEvent turn event like ({@link #TURN_TURN}, {@link #TURN_U_TURN},
    218      *        {@link #TURN_ROUNDABOUT_ENTER_AND_EXIT}, etc).
    219      * @param eventName Name of the turn event like road name to turn. For example "Charleston road"
    220      *        in "Turn right to Charleston road"
    221      * @param turnAngle turn angle in degrees between the roundabout entry and exit (0..359).  Only
    222      *        used for event type {@link #TURN_ROUNDABOUT_ENTER_AND_EXIT}.  -1 if unused.
    223      * @param turnNumber turn number, counting around from the roundabout entry to the exit.  Only
    224      *        used for event type {@link #TURN_ROUNDABOUT_ENTER_AND_EXIT}.  -1 if unused.
    225      * @param image image to be shown in the instrument cluster.  Null if instrument
    226      *        cluster type doesn't support images.
    227      * @param turnSide turn side ({@link #TURN_SIDE_LEFT}, {@link #TURN_SIDE_RIGHT} or
    228      *        {@link #TURN_SIDE_UNSPECIFIED}).
    229      * @throws CarNotConnectedException if the connection to the car service has been lost.
    230      *
    231      * @deprecated Use {@link #sendEvent(int, Bundle)} instead.
    232      */
    233     public void sendNavigationTurnEvent(@TurnEvent int turnEvent, CharSequence eventName,
    234             int turnAngle, int turnNumber, Bitmap image, @TurnSide int turnSide)
    235                     throws CarNotConnectedException {
    236         try {
    237             mService.onNextManeuverChanged(turnEvent, eventName, turnAngle, turnNumber, image,
    238                     turnSide);
    239         } catch (IllegalStateException e) {
    240             CarApiUtil.checkCarNotConnectedExceptionFromCarService(e);
    241         } catch (RemoteException e) {
    242             handleCarServiceRemoteExceptionAndThrow(e);
    243         }
    244     }
    245 
    246     /**
    247      * Sends a Navigation Next Step Distance event to the car.
    248      *
    249      * @param distanceMeters Distance to next event in meters.
    250      * @param timeSeconds Time to next event in seconds.
    251      * @param displayDistanceMillis Distance to the next event. This is exactly the same distance
    252      * that navigation app is displaying. Use it when you want to display distance, it has
    253      * appropriate rounding function and units are in sync with navigation app. This parameter is
    254      * in {@code displayDistanceUnit * 1000}.
    255      * @param displayDistanceUnit units for {@param displayDistanceMillis} param.
    256      * See {@link DistanceUnit} for acceptable values.
    257      * @throws CarNotConnectedException if the connection to the car service has been lost.
    258      *
    259      * @deprecated Use {@link #sendEvent(int, Bundle)} instead.
    260      */
    261     public void sendNavigationTurnDistanceEvent(int distanceMeters, int timeSeconds,
    262             int displayDistanceMillis, @DistanceUnit int displayDistanceUnit)
    263             throws CarNotConnectedException {
    264         try {
    265             mService.onNextManeuverDistanceChanged(distanceMeters, timeSeconds,
    266                     displayDistanceMillis, displayDistanceUnit);
    267         } catch (IllegalStateException e) {
    268             CarApiUtil.checkCarNotConnectedExceptionFromCarService(e);
    269         } catch (RemoteException e) {
    270             handleCarServiceRemoteExceptionAndThrow(e);
    271         }
    272     }
    273 
    274     /**
    275      * Sends events from navigation app to instrument cluster.
    276      *
    277      * @param eventType event type
    278      * @param bundle object that holds data about the event
    279      * @throws CarNotConnectedException if the connection to the car service has been lost.
    280      *
    281      * @see #EVENT_TYPE_NEXT_MANEUVER_INFO
    282      * @see #EVENT_TYPE_NEXT_MANEUVER_COUNTDOWN
    283      *
    284      * @hide
    285      */
    286     public void sendEvent(int eventType, Bundle bundle) throws CarNotConnectedException {
    287         try {
    288             mService.onEvent(eventType, bundle);
    289         } catch (IllegalStateException e) {
    290             CarApiUtil.checkCarNotConnectedExceptionFromCarService(e);
    291         } catch (RemoteException e) {
    292             handleCarServiceRemoteExceptionAndThrow(e);
    293         }
    294     }
    295 
    296     @Override
    297     public void onCarDisconnected() {
    298         Log.d(TAG, "onCarDisconnected");
    299     }
    300 
    301     /** Returns navigation features of instrument cluster */
    302     public CarNavigationInstrumentCluster getInstrumentClusterInfo()
    303             throws CarNotConnectedException {
    304         try {
    305             return mService.getInstrumentClusterInfo();
    306         } catch (RemoteException e) {
    307             handleCarServiceRemoteExceptionAndThrow(e);
    308         }
    309         return null;
    310     }
    311 
    312     private void handleCarServiceRemoteExceptionAndThrow(RemoteException e)
    313             throws CarNotConnectedException {
    314         handleCarServiceRemoteException(e);
    315         throw new CarNotConnectedException();
    316     }
    317 
    318     private void handleCarServiceRemoteException(RemoteException e) {
    319         Log.w(TAG, "RemoteException from car service:" + e.getMessage());
    320         // nothing to do for now
    321     }
    322 }
    323