Format nav cluster, add segment text

Fix: 129501585
Fix: 129794376
Test: Manual

Change-Id: I663b8f8d68836d81ef044695cacf9c590a5c6b4c
(cherry picked from commit 91c656199dd8dfcab7693cd3eabf43415ff430e0)
diff --git a/tests/DirectRenderingClusterSample/res/layout/include_navigation_state.xml b/tests/DirectRenderingClusterSample/res/layout/include_navigation_state.xml
index 7f58e24..23b8ff3 100644
--- a/tests/DirectRenderingClusterSample/res/layout/include_navigation_state.xml
+++ b/tests/DirectRenderingClusterSample/res/layout/include_navigation_state.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-              android:layout_width="0dp"
+              android:layout_width="match_parent"
               android:layout_height="match_parent"
               android:orientation="horizontal">
 
@@ -12,38 +12,57 @@
         android:tint="@android:color/white"/>
 
     <LinearLayout
-        android:layout_width="@dimen/nav_state_width"
+        android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:orientation="vertical">
 
-        <TextView
-            android:id="@+id/distance"
-            android:layout_height="wrap_content"
+        <LinearLayout
             android:layout_width="wrap_content"
-            android:maxLines="1"
-            android:textSize="@dimen/distance_text_size"/>
+            android:layout_height="match_parent"
+            android:layout_weight="1.0">
+
+            <TextView
+                android:id="@+id/distance"
+                android:layout_width="@dimen/distance_width"
+                android:layout_height="wrap_content"
+                android:maxLines="1"
+                android:textSize="@dimen/distance_text_size"/>
+
+            <android.car.cluster.sample.LaneView
+                android:id="@+id/lane"
+                android:layout_width="wrap_content"
+                android:layout_height="@dimen/laneview_height"
+                android:layout_alignParentRight="true"/>
+        </LinearLayout>
+
         <android.car.cluster.sample.CueView
             android:id="@+id/cue"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:maxLines="1"
             android:textSize="@dimen/cue_text_size"/>
-        <TextView
-            android:id="@+id/eta"
+
+        <LinearLayout
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:maxLines="1"
-            android:textSize="@dimen/eta_text_size"/>
-    </LinearLayout>
+            android:orientation="horizontal">
 
-    <LinearLayout
-        android:layout_width="@dimen/nav_state_width"
-        android:layout_height="wrap_content"
-        android:orientation="vertical">
+            <TextView
+                android:id="@+id/eta"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center"
+                android:layout_marginRight="@dimen/eta_margin_right"
+                android:maxLines="1"
+                android:textSize="@dimen/eta_text_size"/>
 
-        <android.car.cluster.sample.LaneView
-            android:id="@+id/lane"
-            android:layout_width="wrap_content"
-            android:layout_height="@dimen/laneview_height"/>
+            <TextView
+                android:id="@+id/segment"
+                android:layout_height="wrap_content"
+                android:layout_width="wrap_content"
+                android:maxLines="1"
+                android:ellipsize="end"
+                android:textSize="@dimen/segment_text_size"/>
+        </LinearLayout>
     </LinearLayout>
 </LinearLayout>
\ No newline at end of file
diff --git a/tests/DirectRenderingClusterSample/res/values/dimens.xml b/tests/DirectRenderingClusterSample/res/values/dimens.xml
index 354836d..34a8a53 100644
--- a/tests/DirectRenderingClusterSample/res/values/dimens.xml
+++ b/tests/DirectRenderingClusterSample/res/values/dimens.xml
@@ -27,12 +27,14 @@
     <!-- Maneuver -->
     <dimen name="maneuver_width">60dp</dimen>
     <dimen name="maneuver_height">60dp</dimen>
-    <dimen name="maneuver_margin">10dp</dimen>
+    <dimen name="maneuver_margin">8dp</dimen>
     <!-- Distance -->
+    <dimen name="distance_width">125dp</dimen>
     <dimen name="distance_text_size">20sp</dimen>
     <!-- Segment -->
     <dimen name="segment_text_size">15sp</dimen>
     <!-- ETA -->
+    <dimen name="eta_margin_right">15dp</dimen>
     <dimen name="eta_text_size">15sp</dimen>
     <!-- Cue -->
     <dimen name="cue_text_size">15sp</dimen>
@@ -41,6 +43,8 @@
     <dimen name="lane_width">50dp</dimen>
     <dimen name="lane_height">50dp</dimen>
 
+    <dimen name="lane_icon_offset">12.5dp</dimen>
+
     <!--                                   -->
     <!-- Sensor value conversion constants -->
     <!--                                   -->
diff --git a/tests/DirectRenderingClusterSample/src/android/car/cluster/sample/LaneView.java b/tests/DirectRenderingClusterSample/src/android/car/cluster/sample/LaneView.java
index 6e86b92..ff021de 100644
--- a/tests/DirectRenderingClusterSample/src/android/car/cluster/sample/LaneView.java
+++ b/tests/DirectRenderingClusterSample/src/android/car/cluster/sample/LaneView.java
@@ -41,6 +41,13 @@
 
     private final int mWidth = (int) getResources().getDimension(R.dimen.lane_width);
     private final int mHeight = (int) getResources().getDimension(R.dimen.lane_height);
+    private final int mOffset = (int) getResources().getDimension(R.dimen.lane_icon_offset);
+
+    private enum Shift {
+        LEFT,
+        RIGHT,
+        BOTH
+    }
 
     public LaneView(Context context) {
         super(context);
@@ -75,25 +82,28 @@
         Bitmap bitmap = Bitmap.createBitmap(mWidth, mHeight, Bitmap.Config.ARGB_8888);
         Canvas canvas = new Canvas(bitmap);
 
+        Shift shift = getShift(lane);
+
         for (LaneDirection laneDir : lane.getDirections()) {
             if (!laneDir.isHighlighted()) {
-                drawToCanvas(laneDir, canvas, false);
+                drawToCanvas(laneDir, canvas, false, shift);
             }
         }
 
         for (LaneDirection laneDir : lane.getDirections()) {
             if (laneDir.isHighlighted()) {
-                drawToCanvas(laneDir, canvas, true);
+                drawToCanvas(laneDir, canvas, true, shift);
             }
         }
 
         return bitmap;
     }
 
-
-    private void drawToCanvas(LaneDirection laneDir, Canvas canvas, boolean isHighlighted) {
+    private void drawToCanvas(LaneDirection laneDir, Canvas canvas, boolean isHighlighted,
+            Shift shift) {
+        int offset = getOffset(laneDir, shift);
         VectorDrawable icon = (VectorDrawable) getLaneIcon(laneDir);
-        icon.setBounds(0, 0, mWidth, mHeight);
+        icon.setBounds(offset, 0, mWidth + offset, mHeight);
         icon.setColorFilter(new PorterDuffColorFilter(isHighlighted
                 ? getContext().getColor(R.color.laneDirectionHighlighted)
                 : getContext().getColor(R.color.laneDirection),
@@ -101,6 +111,76 @@
         icon.draw(canvas);
     }
 
+    /**
+     * Determines the offset direction to line up overlapping lane directions.
+     */
+    private Shift getShift(Lane lane) {
+        boolean containsRight = false;
+        boolean containsLeft = false;
+        boolean containsStraight = false;
+
+        for (LaneDirection laneDir : lane.getDirections()) {
+            if (laneDir.getShape().equals(LaneDirection.Shape.NORMAL_RIGHT)
+                    || laneDir.getShape().equals(LaneDirection.Shape.SLIGHT_RIGHT)
+                    || laneDir.getShape().equals(LaneDirection.Shape.SHARP_RIGHT)
+                    || laneDir.getShape().equals(LaneDirection.Shape.U_TURN_RIGHT)) {
+                containsRight = true;
+            }
+            if (laneDir.getShape().equals(LaneDirection.Shape.NORMAL_LEFT)
+                    || laneDir.getShape().equals(LaneDirection.Shape.SLIGHT_LEFT)
+                    || laneDir.getShape().equals(LaneDirection.Shape.SHARP_LEFT)
+                    || laneDir.getShape().equals(LaneDirection.Shape.U_TURN_LEFT)) {
+                containsLeft = true;
+            }
+            if (laneDir.getShape().equals(LaneDirection.Shape.STRAIGHT)) {
+                containsStraight = true;
+            }
+        }
+
+        if (containsLeft && containsRight) {
+            //shift turns outwards
+            return Shift.BOTH;
+        } else if (containsStraight && containsRight) {
+            //shift straight lane dir to the left
+            return Shift.LEFT;
+        } else if (containsStraight && containsLeft) {
+            //shift straight lane dir to the right
+            return Shift.RIGHT;
+        }
+
+        return null;
+    }
+
+    /**
+     * Returns the offset value of the lane direction based on the given shift direction.
+     */
+    private int getOffset(LaneDirection laneDir, Shift shift) {
+        if (shift == Shift.BOTH) {
+            if (laneDir.getShape().equals(LaneDirection.Shape.NORMAL_LEFT)
+                    || laneDir.getShape().equals(LaneDirection.Shape.SLIGHT_LEFT)
+                    || laneDir.getShape().equals(LaneDirection.Shape.SHARP_LEFT)
+                    || laneDir.getShape().equals(LaneDirection.Shape.U_TURN_LEFT)) {
+                return -mOffset;
+            }
+            if (laneDir.getShape().equals(LaneDirection.Shape.NORMAL_RIGHT)
+                    || laneDir.getShape().equals(LaneDirection.Shape.SLIGHT_RIGHT)
+                    || laneDir.getShape().equals(LaneDirection.Shape.SHARP_RIGHT)
+                    || laneDir.getShape().equals(LaneDirection.Shape.U_TURN_RIGHT)) {
+                return mOffset;
+            }
+        } else if (shift == Shift.LEFT) {
+            if (laneDir.getShape().equals(LaneDirection.Shape.STRAIGHT)) {
+                return -mOffset;
+            }
+        } else if (shift == Shift.RIGHT) {
+            if (laneDir.getShape().equals(LaneDirection.Shape.STRAIGHT)) {
+                return mOffset;
+            }
+        }
+
+        return 0;
+    }
+
     private Drawable getLaneIcon(@Nullable LaneDirection laneDir) {
         if (laneDir == null) {
             return null;
diff --git a/tests/DirectRenderingClusterSample/src/android/car/cluster/sample/NavStateController.java b/tests/DirectRenderingClusterSample/src/android/car/cluster/sample/NavStateController.java
index 3ba31d7..1e4ba96 100644
--- a/tests/DirectRenderingClusterSample/src/android/car/cluster/sample/NavStateController.java
+++ b/tests/DirectRenderingClusterSample/src/android/car/cluster/sample/NavStateController.java
@@ -43,6 +43,7 @@
     private ImageView mManeuver;
     private LaneView mLane;
     private TextView mDistance;
+    private TextView mSegment;
     private TextView mEta;
     private CueView mCue;
     private Context mContext;
@@ -58,6 +59,7 @@
         mManeuver = container.findViewById(R.id.maneuver);
         mLane = container.findViewById(R.id.lane);
         mDistance = container.findViewById(R.id.distance);
+        mSegment = container.findViewById(R.id.segment);
         mEta = container.findViewById(R.id.eta);
         mCue = container.findViewById(R.id.cue);
 
@@ -85,6 +87,7 @@
         mEta.setTextColor(getTrafficColor(traffic));
         mManeuver.setImageDrawable(getManeuverIcon(step != null ? step.getManeuver() : null));
         mDistance.setText(formatDistance(step != null ? step.getDistance() : null));
+        mSegment.setText(state != null ? getSegmentString(state.getCurrentSegment()) : null);
         mCue.setRichText(step != null ? step.getCue() : null, mImageResolver);
 
         if (step != null && step.getLanes().size() > 0) {
@@ -256,7 +259,26 @@
         if (distance == null || distance.getDisplayUnit() == Distance.Unit.UNKNOWN) {
             return null;
         }
-        return String.format("In %s %s", distance.getDisplayValue(),
-                distance.getDisplayUnit().toString().toLowerCase());
+
+        String unit = "";
+
+        switch(distance.getDisplayUnit()){
+            case METERS:
+                unit = "m";
+                break;
+            case KILOMETERS:
+                unit = "km";
+                break;
+            case MILES:
+                unit = "mi";
+                break;
+            case YARDS:
+                unit = "yd";
+                break;
+            case FEET:
+                unit = "ft";
+                break;
+        }
+        return String.format("In %s %s", distance.getDisplayValue(), unit);
     }
 }
diff --git a/tests/EmbeddedKitchenSinkApp/res/raw/nav_state_data.json b/tests/EmbeddedKitchenSinkApp/res/raw/nav_state_data.json
index 99b28e6..d51a341 100644
--- a/tests/EmbeddedKitchenSinkApp/res/raw/nav_state_data.json
+++ b/tests/EmbeddedKitchenSinkApp/res/raw/nav_state_data.json
@@ -39,18 +39,58 @@
               {
                 "mShape": { "mValues": [ "STRAIGHT" ] },
                 "mHighlighted": false
+              }
+            ]
+          },
+          {
+            "mDirections": [
+              {
+                "mShape": { "mValues": [ "STRAIGHT" ] },
+                "mHighlighted": false
+              }
+            ]
+          },
+          {
+            "mDirections": [
+              {
+                "mShape": { "mValues": [ "STRAIGHT" ] },
+                "mHighlighted": false
+              }
+            ]
+          },
+          {
+            "mDirections": [
+              {
+                "mShape": { "mValues": [ "STRAIGHT" ] },
+                "mHighlighted": false
+              }
+            ]
+          },
+          {
+            "mDirections": [
+              {
+                "mShape": { "mValues": [ "STRAIGHT" ] },
+                "mHighlighted": false
               },
               {
                 "mShape": { "mValues": [ "SLIGHT_RIGHT" ] },
                 "mHighlighted": true
               }
             ]
+          },
+          {
+            "mDirections": [
+              {
+                "mShape": { "mValues": [ "SLIGHT_RIGHT" ] },
+                "mHighlighted": false
+              }
+            ]
           }
         ]
       }
     ],
     "mCurrentSegment": {
-      "mName": "On McCowan St"
+      "mName": "On Something Really Long St"
     },
     "mDestinations": [
       {
@@ -62,7 +102,7 @@
           "mDisplayUnit": { "mValues": [ "KILOMETERS" ] }
         },
         "mEta": {
-          "mSecondsSinceEpoch": 1551318762,
+          "mSecondsSinceEpoch": 1551314762,
           "mZoneId": "America/Los_Angeles"
         },
         "mTraffic": { "mValues": [ "MEDIUM" ] }