Merge "[gRPC] Add support for Multi-touch interaction." into emu-master-dev
diff --git a/android/android-emu/android/skin/qt/extended-pages/location-page-point.cpp b/android/android-emu/android/skin/qt/extended-pages/location-page-point.cpp
index ddb309a..aa310d3 100644
--- a/android/android-emu/android/skin/qt/extended-pages/location-page-point.cpp
+++ b/android/android-emu/android/skin/qt/extended-pages/location-page-point.cpp
@@ -525,8 +525,8 @@
             continue;
         }
 
-        // Get the HTML file (either 'index.html' or route.html')
-        QFile indexHtmlFile(isPoint ? ":/html/index.html" : ":/html/route.html");
+        // Get the HTML file (either 'location-point.html' or 'location-route.html')
+        QFile indexHtmlFile(isPoint ? ":/html/location-point.html" : ":/html/location-route.html");
 
         // Insert the Maps API key into the HTML and publish
         // that to QWebChannel
@@ -536,7 +536,7 @@
                 // Change the placeholder to the real Maps API key
                 htmlByteArray.replace("YOUR_API_KEY", mMapsApiKey.toUtf8());
                 // Publish it
-                webEnginePage->setHtml(htmlByteArray, QUrl(isPoint ? "qrc:/html/index.html" : "qrc:/html/route.html"));
+                webEnginePage->setHtml(htmlByteArray, QUrl(isPoint ? "qrc:/html/location-point.html" : "qrc:/html/location-route.html"));
             }
         }
     }
diff --git a/android/android-emu/android/skin/qt/html/css/common.css b/android/android-emu/android/skin/qt/html/css/common.css
deleted file mode 100644
index b75dbed..0000000
--- a/android/android-emu/android/skin/qt/html/css/common.css
+++ /dev/null
@@ -1,438 +0,0 @@
-#pointInfoOverlay {
-    display: none;
-    position: fixed;
-    width: 100%;
-    justify-content: center;
-    flex-direction: column;
-    bottom: 0;
-    z-index: 2;
-    background-color: #5489ea;
-    padding-top: 12px;
-    padding-bottom: 12px;
-}
-#savePointOverlay {
-    display: none;
-    position: fixed;
-    width: 100%;
-    bottom: 0;
-    z-index: 2;
-}
-#startInfoOverlay {
-    display: none;
-    position: fixed;
-    width: 100%;
-    justify-content: center;
-    flex-direction: column;
-    bottom: 0;
-    z-index: 2;
-    background-color: #5489ea;
-    padding-top: 12px;
-    padding-bottom: 12px;
-}
-#routeCreatorOverlay {
-    display: none;
-    position: absolute;
-    z-index: 2;
-    top: 0;
-    width: 100%;
-    flex-direction: column;
-    background-color: #fff;
-}
-.close-icon {
-    content: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="%23ffffff"><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41z"/><path fill="none" d="M0 0h24v24H0V0z"/></svg>');
-}
-#upperbox {
-    background-color: #5489ea;
-    width: 100%;
-    display: flex;
-    justify-content: center;
-    flex-direction: column;
-    padding-top: 12px;
-    padding-bottom: 12px;
-}
-#lowerbox {
-    display: flex;
-    background-color: #3d69cf;
-    width: 100%;
-    height: 48px;
-    min-height: 48px;
-}
-#map {
-    height: 100%;
-}
-.title {
-    font-family: Roboto;
-    font-size: 20px;
-    font-weight: 400;
-    color: white;
-    margin-left: 24px;
-    padding-bottom: 6px;
-    margin-right: 24px;
-}
-#startInfoTitle {
-    /* we need more space to not overlap with startNavButton */
-    margin-right: 64px;
-}
-.subtitle {
-    font-family: Roboto;
-    font-size: 14px;
-    font-weight: 200;
-    color: white;
-    opacity: 0.6;
-    margin-left: 24px;
-}
-.common-button {
-    display: flex;
-    font-family: Roboto;
-    font-size: 16px;
-    font-weight: 200;
-    color: white;
-    height: 100%;
-    white-space: nowrap;
-    justify-content: center;
-    align-items: center;
-}
-.common-button[disabled='true'] {
-    opacity: 0;
-}
-
-html, body {
-    width: 100%;
-    height: 100%;
-    margin: 0px;
-    padding: 0px;
-}
-#description {
-    font-family: Roboto;
-    font-size: 15px;
-    font-weight: 300;
-}
-
-.pac-card {
-    margin: 10px 10px 0 0;
-    border-radius: 2px 0 0 2px;
-    box-sizing: border-box;
-    -moz-box-sizing: border-box;
-    outline: none;
-    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
-    background-color: #fff;
-    font-family: Roboto;
-}
-
-#pac-container {
-    padding-bottom: 12px;
-    margin-right: 12px;
-}
-
-.pac-controls {
-    display: inline-block;
-    padding: 5px 11px;
-}
-
-.pac-controls label {
-    font-family: Roboto;
-    font-size: 13px;
-    font-weight: 300;
-}
-#pac-input {
-    font-family: Roboto;
-    font-size: 15px;
-    font-weight: 300;
-    padding: 0 11px 0 13px;
-    text-overflow: ellipsis;
-    width: 100%;
-    height: 100%;
-    border: none;
-}
-
-#pac-input:focus {
-    border: none;
-}
-#pac-input:placeholder-shown ~ .search-icon {
-    content: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="24px" height="24px" viewBox="0 0 24 24" fill="%23757575"><path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/><path d="M0 0h24v24H0z" fill="none"/></svg>');
-}
-#pac-input ~ .search-icon {
-    content: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="%23757575"><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41z"/><path fill="none" d="M0 0h24v24H0V0z"/></svg>');
-}
-#search-container {
-    display: flex;
-    width: 85%;
-    height: 36px;
-    border-color: #dadce0;
-    border-style: solid;
-    border-width: 1px;
-    border-radius: 2px;
-    margin-top: 12px;
-}
-
-#search-icon {
-    text-align: center;
-    padding-left: 10px;
-    padding-right: 10px;
-    background-color: #fff;
-}
-#title {
-    color: #fff;
-    background-color: #4d90fe;
-    font-size: 25px;
-    font-weight: 500;
-    padding: 6px 12px;
-}
-#target {
-    width: 345px;
-}
-.loader-container {
-    background-color: #fff;
-    height: 36px;
-    padding-left: 10px;
-    padding-right: 10px;
-    display: flex;
-    justify-content: center;
-    flex-direction: column;
-}
-.loader {
-    border: 3px solid #fff; /* Light grey */
-    border-top: 3px solid #3498db; /* Blue */
-    border-radius: 50%;
-    animation: spin 1s linear infinite;
-    width: 16px;
-    height: 16px;
-}
-
-@keyframes spin {
-    0% { transform: rotate(0deg); }
-    100% { transform: rotate(360deg); }
-}
-
-.circular-button {
-    width: 48px;
-    height: 48px;
-    border-radius: 50%;
-    background-color: #fff;
-}
-.circular-button div {
-    width: 50%;
-    height: 50%;
-    padding: 25%;
-}
-.directions-icon {
-    content: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="24px" height="24px" viewBox="0 0 24 24" fill="%235489ea"><path d="M21.71 11.29l-9-9c-.39-.39-1.02-.39-1.41 0l-9 9c-.39.39-.39 1.02 0 1.41l9 9c.39.39 1.02.39 1.41 0l9-9c.39-.38.39-1.01 0-1.41zM14 14.5V12h-4v3H8v-4c0-.55.45-1 1-1h5V7.5l3.5 3.5-3.5 3.5z"/><path d="M0 0h24v24H0z" fill="none"/></svg>');
-}
-#startNavButton {
-    position: absolute;
-    top: -24px;
-    right: 12px;
-}
-
-#closeRouteCreatorButton {
-    width: 24px;
-    height: 24px;
-    margin-right: 24px;
-}
-
-/* Transport modes */
-.transport-mode-container {
-    display: block;
-    cursor: pointer;
-    -webkit-user-select: none;
-    -moz-user-select: none;
-    -ms-user-select: none;
-    user-select: none;
-    margin-right: 24px;
-    width: 24px;
-    height: 24px;
-}
-/* Hide the browser's default radio button */
-.transport-mode-container input {
-    position: absolute;
-    opacity: 0;
-    cursor: pointer;
-}
-.transport-mode-container div {
-    width: 24px;
-    height: 24px;
-    border-radius: 50%;
-    padding: 20%;
-}
-.transport-mode-container input ~ div img {
-    width: 24px;
-    height: 24px;
-}
-.transport-mode-container input:checked ~ div {
-    background-color: #3d69cf;
-}
-.transport-mode-container input ~ div > .transport-mode-car {
-    content: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="24px" height="24px" viewBox="0 0 24 24" fill="%23FFFFFF" opacity="0.6"><path d="M18.92 6.01C18.72 5.42 18.16 5 17.5 5h-11c-.66 0-1.21.42-1.42 1.01L3 12v8c0 .55.45 1 1 1h1c.55 0 1-.45 1-1v-1h12v1c0 .55.45 1 1 1h1c.55 0 1-.45 1-1v-8l-2.08-5.99zM6.5 16c-.83 0-1.5-.67-1.5-1.5S5.67 13 6.5 13s1.5.67 1.5 1.5S7.33 16 6.5 16zm11 0c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5zM5 11l1.5-4.5h11L19 11H5z"/><path d="m0 0h24v24h0z" fill="none"/></svg>');
-}
-.transport-mode-container input:checked ~ div > .transport-mode-car {
-    content: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="24px" height="24px" viewBox="0 0 24 24" fill="%23FFFFFF"><path d="M18.92 6.01C18.72 5.42 18.16 5 17.5 5h-11c-.66 0-1.21.42-1.42 1.01L3 12v8c0 .55.45 1 1 1h1c.55 0 1-.45 1-1v-1h12v1c0 .55.45 1 1 1h1c.55 0 1-.45 1-1v-8l-2.08-5.99zM6.5 16c-.83 0-1.5-.67-1.5-1.5S5.67 13 6.5 13s1.5.67 1.5 1.5S7.33 16 6.5 16zm11 0c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5zM5 11l1.5-4.5h11L19 11H5z"/><path d="m0 0h24v24h0z" fill="none"/></svg>');
-}
-.transport-mode-container input ~ div > .transport-mode-bike {
-    content: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="24px" height="24px" viewBox="0 0 24 24" fill="%23FFFFFF" opacity="0.6"><path fill="none" d="M0 0h24v24H0z"/><path d="M15.5 5.5c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zM5 12c-2.8 0-5 2.2-5 5s2.2 5 5 5 5-2.2 5-5-2.2-5-5-5zm0 8.5c-1.9 0-3.5-1.6-3.5-3.5s1.6-3.5 3.5-3.5 3.5 1.6 3.5 3.5-1.6 3.5-3.5 3.5zm5.8-10l2.4-2.4.8.8c1.3 1.3 3 2.1 5.1 2.1V9c-1.5 0-2.7-.6-3.6-1.5l-1.9-1.9c-.5-.4-1-.6-1.6-.6s-1.1.2-1.4.6L7.8 8.4c-.4.4-.6.9-.6 1.4 0 .6.2 1.1.6 1.4L11 14v5h2v-6.2l-2.2-2.3zM19 12c-2.8 0-5 2.2-5 5s2.2 5 5 5 5-2.2 5-5-2.2-5-5-5zm0 8.5c-1.9 0-3.5-1.6-3.5-3.5s1.6-3.5 3.5-3.5 3.5 1.6 3.5 3.5-1.6 3.5-3.5 3.5z"/></svg>');
-}
-.transport-mode-container input:checked ~ div > .transport-mode-bike {
-    content: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="24px" height="24px" viewBox="0 0 24 24" fill="%23FFFFFF"><path fill="none" d="M0 0h24v24H0z"/><path d="M15.5 5.5c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zM5 12c-2.8 0-5 2.2-5 5s2.2 5 5 5 5-2.2 5-5-2.2-5-5-5zm0 8.5c-1.9 0-3.5-1.6-3.5-3.5s1.6-3.5 3.5-3.5 3.5 1.6 3.5 3.5-1.6 3.5-3.5 3.5zm5.8-10l2.4-2.4.8.8c1.3 1.3 3 2.1 5.1 2.1V9c-1.5 0-2.7-.6-3.6-1.5l-1.9-1.9c-.5-.4-1-.6-1.6-.6s-1.1.2-1.4.6L7.8 8.4c-.4.4-.6.9-.6 1.4 0 .6.2 1.1.6 1.4L11 14v5h2v-6.2l-2.2-2.3zM19 12c-2.8 0-5 2.2-5 5s2.2 5 5 5 5-2.2 5-5-2.2-5-5-5zm0 8.5c-1.9 0-3.5-1.6-3.5-3.5s1.6-3.5 3.5-3.5 3.5 1.6 3.5 3.5-1.6 3.5-3.5 3.5z"/></svg>');
-}
-.transport-mode-container input ~ div > .transport-mode-walk {
-    content: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="24px" height="24px" viewBox="0 0 24 24" fill="%23FFFFFF" opacity="0.6"><path fill="none" d="M0 0h24v24H0z"/><path d="M13.5 5.5c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zM9.8 8.9L7 23h2.1l1.8-8 2.1 2v6h2v-7.5l-2.1-2 .6-3C14.8 12 16.8 13 19 13v-2c-1.9 0-3.5-1-4.3-2.4l-1-1.6c-.4-.6-1-1-1.7-1-.3 0-.5.1-.8.1L6 8.3V13h2V9.6l1.8-.7"/></svg>');
-}
-.transport-mode-container input:checked ~ div > .transport-mode-walk {
-    content: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="24px" height="24px" viewBox="0 0 24 24" fill="%23FFFFFF"><path fill="none" d="M0 0h24v24H0z"/><path d="M13.5 5.5c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zM9.8 8.9L7 23h2.1l1.8-8 2.1 2v6h2v-7.5l-2.1-2 .6-3C14.8 12 16.8 13 19 13v-2c-1.9 0-3.5-1-4.3-2.4l-1-1.6c-.4-.6-1-1-1.7-1-.3 0-.5.1-.8.1L6 8.3V13h2V9.6l1.8-.7"/></svg>');
-}
-.transport-mode-container input ~ div > .transport-mode-transit {
-    content: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="24px" height="24px" viewBox="0 0 24 24" fill="%23FFFFFF" opacity="0.6"><path d="M0 0h24v24H0z" fill="none"/><path d="M12 2c-4.42 0-8 .5-8 4v9.5C4 17.43 5.57 19 7.5 19L6 20.5v.5h12v-.5L16.5 19c1.93 0 3.5-1.57 3.5-3.5V6c0-3.5-3.58-4-8-4zM7.5 17c-.83 0-1.5-.67-1.5-1.5S6.67 14 7.5 14s1.5.67 1.5 1.5S8.33 17 7.5 17zm3.5-6H6V6h5v5zm5.5 6c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5zm1.5-6h-5V6h5v5z"/></svg>');
-}
-.transport-mode-container input:checked ~ div > .transport-mode-transit {
-    content: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="24px" height="24px" viewBox="0 0 24 24" fill="%23FFFFFF"><path d="M0 0h24v24H0z" fill="none"/><path d="M12 2c-4.42 0-8 .5-8 4v9.5C4 17.43 5.57 19 7.5 19L6 20.5v.5h12v-.5L16.5 19c1.93 0 3.5-1.57 3.5-3.5V6c0-3.5-3.58-4-8-4zM7.5 17c-.83 0-1.5-.67-1.5-1.5S6.67 14 7.5 14s1.5.67 1.5 1.5S8.33 17 7.5 17zm3.5-6H6V6h5v5zm5.5 6c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5zm1.5-6h-5V6h5v5z"/></svg>');
-}
-
-#waypoints-container {
-    display: flex;
-    margin-top: 24px;
-    margin-left: 12px;
-}
-#waypoints-icons-container {
-    display: flex;
-    flex-direction: column;
-}
-#waypoints-addrs-container {
-    display: flex;
-    flex-direction: column;
-    width: 100%;
-    padding-top: 2px;
-    margin-left: 12px;
-}
-.waypoint-addr-input {
-    color: white;
-    background-color: transparent;
-    margin-bottom: 20px;
-    font-family: Roboto;
-    font-size: 15px;
-    font-weight: 300;
-    width: 100%;
-    border: none;
-    border-bottom: 1px solid white;
-}
-.waypoint-addr-input::placeholder {
-    color: #fff;
-    opacity: 0.7;
-}
-.waypoint-addr-input:focus {
-    outline: none;
-}
-
-.widget-directions-icon {
-    background-size: 96px 240px;
-    background-image: url(https://maps.gstatic.com/tactile/directions/omnibox/directions-2x-20180521.png);
-    width: 24px;
-    height: 24px;
-}
-.start-dot-icon {
-    background-position: 0 -48px;
-    margin-bottom: -8px;
-}
-.waypoints-icon {
-    height: 32px;
-    background-position: -48px -24px;
-}
-.end-marker-icon {
-    background-position: -24px -48px;
-    margin-top: -6px;
-}
-.add-waypoint-icon {
-    background-position: -72px 0px;
-}
-
-#waypoints-reverse-container {
-    display: flex;
-    justify-content: center;
-    flex-direction: column;
-    margin-left: 36px;
-    margin-right: 36px;
-}
-.reverse-icon {
-    background-position: -24px -24px;
-}
-
-#routeCreatorOverlay #searchResultsOverlay {
-    width: 100%;
-    height: 100%;
-    background-color: #fff;
-    padding-top: 12px;
-    display: none;
-}
-
-.maps-sprite-suggest-place-pin {
-    background: no-repeat url(https://maps.gstatic.com/tactile/icons/suggest_hdpi-2bf63922a381545d9b758f76bc9e2943.png) 0 -200px;
-    background-size: 24px 649px;
-}
-.grey-marker-icon {
-    background-position: 0px -200px;
-}
-
-#searchResultsOverlay .search-item {
-    display: flex;
-    height: 36px;
-    align-items: center;
-    padding-left: 12px;
-    padding-right: 12px;
-}
-
-#searchResultsOverlay .search-item:hover {
-    background-color: #efefef;
-}
-
-#searchResultsOverlay .search-item-icon {
-    width: 24px;
-    min-width: 24px;
-    height: 24px;
-    margin-right: 12px;
-}
-
-#searchResultsOverlay .search-item-description {
-    display: flex;
-    height: 100%;
-    width: 100%;
-    flex-direction: column;
-    justify-content: center;
-}
-
-.search-item .name {
-    font-family: Roboto;
-    font-size: 14px;
-    font-weight: 100;
-    color: #333333;
-    display: inline-block;
-    white-space: nowrap;
-    overflow: hidden;
-    text-overflow: ellipsis;
-}
-.search-item .address {
-    font-family: Roboto;
-    font-size: 12px;
-    font-weight: 100;
-    color: #8c8c8c;
-}
-
-#startAddress:placeholder-shown #routeCreatorOverlay {
-    height: 100%;
-}
-#startAddress #routeCreatorOverlay {
-    height: auto;
-}
-#locationInfoOverlay {
-    display: none;
-    position: fixed;
-    width: auto;
-    justify-content: center;
-    flex-direction: column;
-    bottom: 0;
-    z-index: 2;
-    background-color: #fff;
-    padding: 6px;
-    margin-left: 6px;
-    margin-bottom: 6px;
-    -moz-box-shadow: 0 0 3px #ccc;
-    -webkit-box-shadow: 0 0 3px #ccc;
-    box-shadow: 0 0 3px #ccc;
-}
diff --git a/android/android-emu/android/skin/qt/html/css/location.css b/android/android-emu/android/skin/qt/html/css/location.css
index 27f95bb..a42b2d2 100644
--- a/android/android-emu/android/skin/qt/html/css/location.css
+++ b/android/android-emu/android/skin/qt/html/css/location.css
@@ -4,7 +4,7 @@
   padding: 0px;
 }
 
-.pointOverlaySlideIn, .pointOverlaySlideOut, .pointOverlayHideBottomPanel {
+.pointOverlaySlideIn, .pointOverlaySlideOut, .pointOverlayHideBottomPanel, .pointOverlayNoBottomPanel {
   display: flex;
   position: fixed;
   width: 100%;
@@ -26,10 +26,15 @@
   height: 90px;
 }
 
+.pointOverlayNoBottomPanel {
+  height: 100px;
+  overflow: visible;
+}
+
 .upperPointOverlayPanel {
   background-color: #5489ea;
   width: 100%;
-  height: 90px;
+  height: 100px;
   display: flex;
   justify-content: center;
   flex-direction: column;
@@ -42,6 +47,28 @@
   height: 38px;
 }
 
+.circular-button {
+  position: absolute;
+  top: -32px;
+  right: 12px;
+  width: 48px;
+  height: 48px;
+  border-radius: 50%;
+  background-color: #fff;
+  box-shadow: 0 10px 10px rgba(0, 0, 0, 0.3);
+  cursor: pointer;
+}
+
+.circular-button div {
+  width: 50%;
+  height: 50%;
+  padding: 25%;
+}
+
+.directions-icon {
+  content: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="24px" height="24px" viewBox="0 0 24 24" fill="%235489ea"><path d="M21.71 11.29l-9-9c-.39-.39-1.02-.39-1.41 0l-9 9c-.39.39-.39 1.02 0 1.41l9 9c.39.39 1.02.39 1.41 0l9-9c.39-.38.39-1.01 0-1.41zM14 14.5V12h-4v3H8v-4c0-.55.45-1 1-1h5V7.5l3.5 3.5-3.5 3.5z"/><path d="M0 0h24v24H0z" fill="none"/></svg>');
+}
+
 #map {
   height: 100%;
 }
@@ -93,7 +120,7 @@
 }
 
 .pac-container {
-  box-shadow: 0 -5px 5px -5px white, 0 3px 6px rgba(0, 0, 0, 0.16), 0 3px 6px rgba(0, 0, 0, 0.23);
+  box-shadow: 0 -5px 5px -5px white, 0 3px 6px rgba(0, 0, 0, 0.1), 0 3px 6px rgba(0, 0, 0, 0.16);
   border-top-left-radius: 0px;
   border-top-right-radius: 0px;
   border-bottom-left-radius: 4px;
@@ -125,27 +152,27 @@
 
 .search-container {
   display: flex;
-  width: 85%;
-  height: 42px;
+  width: 95%;
+  height: 38px;
   border-color: #dadce0;
   border-style: solid;
   border-width: 0px;
-  border-radius: 3px;
+  border-radius: 2px;
   margin-top: 12px;
-  box-shadow: 0 3px 6px rgba(0, 0, 0, 0.16), 0 3px 6px rgba(0, 0, 0, 0.23);
+  box-shadow: 0 3px 6px rgba(0, 0, 0, 0.1), 0 3px 6px rgba(0, 0, 0, 0.16);
 }
 
 .search-icon {
   text-align: center;
-  padding-top: 10px;
+  padding-top: 7px;
   padding-left: 10px;
   padding-right: 10px;
   background-color: #fff;
-  color: #aeaeae;
+  color: #b1b1b1;
   border-top-right-radius: 4px;
   border-bottom-right-radius: 4px;
-  position:absolute;
-  right:0;
+  position: absolute;
+  right: 0;
   cursor: pointer;
 }
 
@@ -163,7 +190,7 @@
 
 .spinner-container {
   background-color: #fff;
-  height: 42px;
+  height: 38px;
   padding-left: 10px;
   padding-right: 10px;
   display: flex;
@@ -190,4 +217,348 @@
   100% {
     transform: rotate(360deg);
   }
+}
+
+.routeCreatorOverlayHidden, .routeCreatorOverlay, .routeCreatorOverlayAutoCompleteVisible {
+  display: flex;
+  position: absolute;
+  z-index: 2;
+  top: 0;
+  width: 100%;
+  height: 0px;
+  flex-direction: column;
+  background-color: #fff;
+  transition: height 0.2s ease-in-out;
+  overflow: hidden;
+}
+
+.routeCreatorOverlay {
+  height: 204px;
+}
+
+.routeCreatorOverlayAutoCompleteVisible {
+  height: 100%;
+}
+
+#closeRouteCreatorButton {
+  width: 24px;
+  height: 24px;
+  margin-right: 24px;
+}
+
+/* Transport modes */
+
+.transport-mode-container {
+  display: block;
+  cursor: pointer;
+  -webkit-user-select: none;
+  -moz-user-select: none;
+  -ms-user-select: none;
+  user-select: none;
+  margin-right: 24px;
+  width: 24px;
+  height: 24px;
+}
+
+/* Hide the browser's default radio button */
+
+.transport-mode-container input {
+  position: absolute;
+  opacity: 0;
+  cursor: pointer;
+}
+
+.transport-mode-container div {
+  width: 24px;
+  height: 24px;
+  border-radius: 50%;
+  padding: 20%;
+}
+
+.transport-mode-container input~div img {
+  width: 24px;
+  height: 24px;
+}
+
+.transport-mode-container input:checked~div {
+  background-color: #3d69cf;
+}
+
+.transport-mode-container input~div>.transport-mode-car {
+  content: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="24px" height="24px" viewBox="0 0 24 24" fill="%23FFFFFF" opacity="0.6"><path d="M18.92 6.01C18.72 5.42 18.16 5 17.5 5h-11c-.66 0-1.21.42-1.42 1.01L3 12v8c0 .55.45 1 1 1h1c.55 0 1-.45 1-1v-1h12v1c0 .55.45 1 1 1h1c.55 0 1-.45 1-1v-8l-2.08-5.99zM6.5 16c-.83 0-1.5-.67-1.5-1.5S5.67 13 6.5 13s1.5.67 1.5 1.5S7.33 16 6.5 16zm11 0c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5zM5 11l1.5-4.5h11L19 11H5z"/><path d="m0 0h24v24h0z" fill="none"/></svg>');
+}
+
+.transport-mode-container input:checked~div>.transport-mode-car {
+  content: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="24px" height="24px" viewBox="0 0 24 24" fill="%23FFFFFF"><path d="M18.92 6.01C18.72 5.42 18.16 5 17.5 5h-11c-.66 0-1.21.42-1.42 1.01L3 12v8c0 .55.45 1 1 1h1c.55 0 1-.45 1-1v-1h12v1c0 .55.45 1 1 1h1c.55 0 1-.45 1-1v-8l-2.08-5.99zM6.5 16c-.83 0-1.5-.67-1.5-1.5S5.67 13 6.5 13s1.5.67 1.5 1.5S7.33 16 6.5 16zm11 0c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5zM5 11l1.5-4.5h11L19 11H5z"/><path d="m0 0h24v24h0z" fill="none"/></svg>');
+}
+
+.transport-mode-container input~div>.transport-mode-bike {
+  content: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="24px" height="24px" viewBox="0 0 24 24" fill="%23FFFFFF" opacity="0.6"><path fill="none" d="M0 0h24v24H0z"/><path d="M15.5 5.5c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zM5 12c-2.8 0-5 2.2-5 5s2.2 5 5 5 5-2.2 5-5-2.2-5-5-5zm0 8.5c-1.9 0-3.5-1.6-3.5-3.5s1.6-3.5 3.5-3.5 3.5 1.6 3.5 3.5-1.6 3.5-3.5 3.5zm5.8-10l2.4-2.4.8.8c1.3 1.3 3 2.1 5.1 2.1V9c-1.5 0-2.7-.6-3.6-1.5l-1.9-1.9c-.5-.4-1-.6-1.6-.6s-1.1.2-1.4.6L7.8 8.4c-.4.4-.6.9-.6 1.4 0 .6.2 1.1.6 1.4L11 14v5h2v-6.2l-2.2-2.3zM19 12c-2.8 0-5 2.2-5 5s2.2 5 5 5 5-2.2 5-5-2.2-5-5-5zm0 8.5c-1.9 0-3.5-1.6-3.5-3.5s1.6-3.5 3.5-3.5 3.5 1.6 3.5 3.5-1.6 3.5-3.5 3.5z"/></svg>');
+}
+
+.transport-mode-container input:checked~div>.transport-mode-bike {
+  content: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="24px" height="24px" viewBox="0 0 24 24" fill="%23FFFFFF"><path fill="none" d="M0 0h24v24H0z"/><path d="M15.5 5.5c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zM5 12c-2.8 0-5 2.2-5 5s2.2 5 5 5 5-2.2 5-5-2.2-5-5-5zm0 8.5c-1.9 0-3.5-1.6-3.5-3.5s1.6-3.5 3.5-3.5 3.5 1.6 3.5 3.5-1.6 3.5-3.5 3.5zm5.8-10l2.4-2.4.8.8c1.3 1.3 3 2.1 5.1 2.1V9c-1.5 0-2.7-.6-3.6-1.5l-1.9-1.9c-.5-.4-1-.6-1.6-.6s-1.1.2-1.4.6L7.8 8.4c-.4.4-.6.9-.6 1.4 0 .6.2 1.1.6 1.4L11 14v5h2v-6.2l-2.2-2.3zM19 12c-2.8 0-5 2.2-5 5s2.2 5 5 5 5-2.2 5-5-2.2-5-5-5zm0 8.5c-1.9 0-3.5-1.6-3.5-3.5s1.6-3.5 3.5-3.5 3.5 1.6 3.5 3.5-1.6 3.5-3.5 3.5z"/></svg>');
+}
+
+.transport-mode-container input~div>.transport-mode-walk {
+  content: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="24px" height="24px" viewBox="0 0 24 24" fill="%23FFFFFF" opacity="0.6"><path fill="none" d="M0 0h24v24H0z"/><path d="M13.5 5.5c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zM9.8 8.9L7 23h2.1l1.8-8 2.1 2v6h2v-7.5l-2.1-2 .6-3C14.8 12 16.8 13 19 13v-2c-1.9 0-3.5-1-4.3-2.4l-1-1.6c-.4-.6-1-1-1.7-1-.3 0-.5.1-.8.1L6 8.3V13h2V9.6l1.8-.7"/></svg>');
+}
+
+.transport-mode-container input:checked~div>.transport-mode-walk {
+  content: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="24px" height="24px" viewBox="0 0 24 24" fill="%23FFFFFF"><path fill="none" d="M0 0h24v24H0z"/><path d="M13.5 5.5c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zM9.8 8.9L7 23h2.1l1.8-8 2.1 2v6h2v-7.5l-2.1-2 .6-3C14.8 12 16.8 13 19 13v-2c-1.9 0-3.5-1-4.3-2.4l-1-1.6c-.4-.6-1-1-1.7-1-.3 0-.5.1-.8.1L6 8.3V13h2V9.6l1.8-.7"/></svg>');
+}
+
+.transport-mode-container input~div>.transport-mode-transit {
+  content: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="24px" height="24px" viewBox="0 0 24 24" fill="%23FFFFFF" opacity="0.6"><path d="M0 0h24v24H0z" fill="none"/><path d="M12 2c-4.42 0-8 .5-8 4v9.5C4 17.43 5.57 19 7.5 19L6 20.5v.5h12v-.5L16.5 19c1.93 0 3.5-1.57 3.5-3.5V6c0-3.5-3.58-4-8-4zM7.5 17c-.83 0-1.5-.67-1.5-1.5S6.67 14 7.5 14s1.5.67 1.5 1.5S8.33 17 7.5 17zm3.5-6H6V6h5v5zm5.5 6c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5zm1.5-6h-5V6h5v5z"/></svg>');
+}
+
+.transport-mode-container input:checked~div>.transport-mode-transit {
+  content: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="24px" height="24px" viewBox="0 0 24 24" fill="%23FFFFFF"><path d="M0 0h24v24H0z" fill="none"/><path d="M12 2c-4.42 0-8 .5-8 4v9.5C4 17.43 5.57 19 7.5 19L6 20.5v.5h12v-.5L16.5 19c1.93 0 3.5-1.57 3.5-3.5V6c0-3.5-3.58-4-8-4zM7.5 17c-.83 0-1.5-.67-1.5-1.5S6.67 14 7.5 14s1.5.67 1.5 1.5S8.33 17 7.5 17zm3.5-6H6V6h5v5zm5.5 6c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5zm1.5-6h-5V6h5v5z"/></svg>');
+}
+
+#waypoints-container {
+  display: flex;
+  margin-top: 24px;
+  margin-left: 12px;
+}
+
+#waypoints-icons-container {
+  display: flex;
+  flex-direction: column;
+}
+
+#waypoints-addrs-container {
+  display: flex;
+  flex-direction: column;
+  width: 100%;
+  padding-top: 2px;
+  margin-left: 12px;
+}
+
+.waypoint-addr-input {
+  color: white;
+  background-color: transparent;
+  margin-bottom: 20px;
+  font-family: Roboto;
+  font-size: 15px;
+  font-weight: 300;
+  width: 100%;
+  border: none;
+  border-bottom: 1px solid white;
+}
+
+.waypoint-addr-input::placeholder {
+  color: #fff;
+  opacity: 0.7;
+}
+
+.waypoint-addr-input:focus {
+  outline: none;
+}
+
+.widget-directions-icon {
+  background-size: 96px 240px;
+  background-image: url(https://maps.gstatic.com/tactile/directions/omnibox/directions-2x-20180521.png);
+  width: 24px;
+  height: 24px;
+}
+
+.start-dot-icon {
+  background-position: 0 -48px;
+  margin-bottom: -8px;
+}
+
+.waypoints-icon {
+  height: 32px;
+  background-position: -48px -24px;
+}
+
+.end-marker-icon {
+  background-position: -24px -48px;
+  margin-top: -6px;
+}
+
+.add-waypoint-icon {
+  background-position: -72px 0px;
+}
+
+#waypoints-reverse-container {
+  display: flex;
+  justify-content: center;
+  flex-direction: column;
+  margin-left: 36px;
+  margin-right: 36px;
+}
+
+.reverse-icon {
+  background-position: -24px -24px;
+}
+
+#routeCreatorOverlay #searchResultsOverlay {
+  width: 100%;
+  height: 100%;
+  background-color: #fff;
+  padding-top: 12px;
+  display: none;
+}
+
+#searchResultsOverlay .search-item {
+  display: flex;
+  height: 36px;
+  align-items: center;
+  padding-left: 12px;
+  padding-right: 12px;
+  border-bottom-width: 1px;
+  border-bottom-color: #eeeeee;
+  border-bottom-style: solid;
+  cursor: pointer;
+}
+
+#searchResultsOverlay .search-item:hover {
+  background-color: #efefef;
+}
+
+#searchResultsOverlay .search-item:hover .search-item-icon {
+  color: #d9503f;
+}
+
+#searchResultsOverlay .search-item-icon {
+  color: grey;
+  width: 24px;
+  min-width: 24px;
+  height: 24px;
+  margin-right: 12px;
+}
+
+#searchResultsOverlay .search-item-description {
+  display: flex;
+  height: 100%;
+  width: 100%;
+  flex-direction: column;
+  justify-content: center;
+}
+
+.search-item .name {
+  font-family: Roboto;
+  font-size: 14px;
+  font-weight: 100;
+  color: #333333;
+  display: inline-block;
+  white-space: nowrap;
+  overflow: hidden;
+  text-overflow: ellipsis;
+}
+
+.search-item .address {
+  font-family: Roboto;
+  font-size: 12px;
+  font-weight: 100;
+  color: #8c8c8c;
+}
+
+#startAddress:placeholder-shown #routeCreatorOverlay {
+  height: 100%;
+}
+
+#startAddress #routeCreatorOverlay {
+  height: auto;
+}
+
+#locationInfoOverlay {
+  display: none;
+  position: fixed;
+  width: auto;
+  justify-content: center;
+  flex-direction: column;
+  bottom: 0;
+  z-index: 2;
+  background-color: #fff;
+  padding: 6px;
+  margin-left: 6px;
+  margin-bottom: 6px;
+  -moz-box-shadow: 0 0 3px #ccc;
+  -webkit-box-shadow: 0 0 3px #ccc;
+  box-shadow: 0 0 3px #ccc;
+}
+
+#upperbox {
+  background-color: #5489ea;
+  width: 100%;
+  display: flex;
+  justify-content: center;
+  flex-direction: column;
+  padding-top: 12px;
+  padding-bottom: 12px;
+}
+
+#lowerbox {
+  display: flex;
+  background-color: #3d69cf;
+  width: 100%;
+  height: 48px;
+  min-height: 48px;
+}
+
+.location-icons {
+  color: white;
+}
+
+.close-icon {
+  content: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="%23ffffff"><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41z"/><path fill="none" d="M0 0h24v24H0V0z"/></svg>');
+}
+
+.loader, .loader:after {
+  border-radius: 50%;
+  width: 48px;
+  height: 48px;
+}
+
+.loader {
+  margin: auto;
+  font-size: 10px;
+  text-indent: -9999em;
+  border-top: 1.1em solid rgba(255, 255, 255, 0.2);
+  border-right: 1.1em solid rgba(255, 255, 255, 0.2);
+  border-bottom: 1.1em solid rgba(255, 255, 255, 0.2);
+  border-left: 1.1em solid #ffffff;
+  -webkit-transform: translateZ(0);
+  -ms-transform: translateZ(0);
+  transform: translateZ(0);
+  -webkit-animation: load8 1.1s infinite linear;
+  animation: load8 1.1s infinite linear;
+}
+
+@-webkit-keyframes load8 {
+  0% {
+    -webkit-transform: rotate(0deg);
+    transform: rotate(0deg);
+  }
+  100% {
+    -webkit-transform: rotate(360deg);
+    transform: rotate(360deg);
+  }
+}
+
+@keyframes load8 {
+  0% {
+    -webkit-transform: rotate(0deg);
+    transform: rotate(0deg);
+  }
+  100% {
+    -webkit-transform: rotate(360deg);
+    transform: rotate(360deg);
+  }
+}
+
+#loadingDiv {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  background-color: #5489ea;
+  overflow: hidden;
+  display: flex;
+  justify-content: center;
+  align-items: center;
 }
\ No newline at end of file
diff --git a/android/android-emu/android/skin/qt/html/js/common.js b/android/android-emu/android/skin/qt/html/js/common.js
deleted file mode 100644
index 755d42d..0000000
--- a/android/android-emu/android/skin/qt/html/js/common.js
+++ /dev/null
@@ -1,43 +0,0 @@
-class MockEmuLocationServer {
-    constructor() {
-        console.log("Running outside emulator. Creating fake emulocationserver.");
-        this.lat = 0.0;
-        this.lng = 0.0;
-        this.addr = "";
-    }
-
-    map_savePoint() {
-        console.log("map_savePoint() faked");
-        showPendingLocation(this.lat, this.lng, this.addr);
-    }
-
-    sendLocation(lat, lng, addr) {
-        console.log("sendLocation(" + lat + ", " + lng + ", " + addr + ") faked");
-        this.lat = lat;
-        this.lng = lng;
-        this.addr = addr;
-    }
-
-    sendFullRouteToEmu(numPoints, totalDuration, fullResult, mode) {
-        console.log("sendFullRouteToEmu(" + numPoints + ", " + totalDuration + ", " + fullResult + ", " + mode + ") faked");
-    }
-
-    saveRoute() {
-        console.log("saveRoute() called");
-    }
-}
-class MockObjects {
-    constructor() {
-        this.emulocationserver = new MockEmuLocationServer();
-    }
-}
-class MockChannel {
-    constructor() {
-        this.objects = new MockObjects();
-    }
-}    
-// |channel| is only defined if running inside QtWebEngine.
-if (typeof(channel) === 'undefined') {
-   channel = new MockChannel(); 
-}
-
diff --git a/android/android-emu/android/skin/qt/html/js/location-loader.js b/android/android-emu/android/skin/qt/html/js/location-loader.js
new file mode 100644
index 0000000..f3afe0f
--- /dev/null
+++ b/android/android-emu/android/skin/qt/html/js/location-loader.js
@@ -0,0 +1,10 @@
+$('body').append('<div style="" id="loadingDiv"><div class="loader">Loading...</div></div>');
+$(window).on('load', function () {
+    setTimeout(removeLoader, 2000); // wait for page load PLUS 2 seconds.
+});
+function removeLoader() {
+    $("#loadingDiv").fadeOut(500, function () {
+        // fadeOut complete. Remove the loading div
+        $("#loadingDiv").remove();
+    });
+}
diff --git a/android/android-emu/android/skin/qt/html/js/location-point.js b/android/android-emu/android/skin/qt/html/js/location-point.js
index 3f93d9f..18ebfb8 100644
--- a/android/android-emu/android/skin/qt/html/js/location-point.js
+++ b/android/android-emu/android/skin/qt/html/js/location-point.js
@@ -8,10 +8,6 @@
 var gSearchResultMarkers = [];
 var gPointOverlay = new LocationPointOverlay();
 
-document.addEventListener('DOMContentLoaded', function () {
-
-}, false);
-
 function savePoint() {
     // The emulator should have the point of interest already, from the
     // sendAddress() call.
@@ -30,17 +26,31 @@
         zoom: 10,
         zoomControl: true,
         disableDefaultUI: true,
-        controlSize: 24
+        controlSize: 20
     });
     gGeocoder = new google.maps.Geocoder;
 
     gSearchBox = new LocationSearchBox();
-    gSearchBox.init(gMap);
+    gSearchBox.init(gMap,
+        gSearchResultMarkers,
+        (lastLatLng) => {
+            // Clear the red pin and any existing search markers
+            if (gPendingMarker != null) {
+                gPendingMarker.setMap(null);
+            }
+            showPendingLocation(lastLatLng.lat(), lastLatLng.lng());
+            sendAddress(lastLatLng);
+        },
+        () => {
+            gPointOverlay.hide()
+            if (gPendingMarker != null) {
+                gPendingMarker.setMap(null);
+            }
+        });
 
     // Register a listener that sets a new marker wherever the
     // user clicks on the map.
     google.maps.event.addListener(gMap, 'click', function (event) {
-        // TODO: add spinner here
         gSearchBox.showSpinner();
 
         showPin(event.latLng);
@@ -58,12 +68,14 @@
     showPin(latLng);
     // TODO: no support for elevation yet.
     gPointOverlay.show(addr, latLng, null, true);
+    gSearchBox.update(addr);
+    gMap.panTo(latLng);
 }
 
 function setDeviceLocation(lat, lng) {
     // Called from Qt code to show the blue marker to display the emulator location on the map.
     // Code to set location marker on the map. Move this to a signal event handler.
-
+    console.log('setDeviceLocation', lat, lng);
     // Clear any existing blue dot and red pin
     if (gCurrentMarker != null) {
         gCurrentMarker.setMap(null);
@@ -133,6 +145,7 @@
             elevation = results[0].elevation;
         }
         gPointOverlay.show(address, latLng, elevation);
+        gMap.panTo(latLng);
         channel.objects.emulocationserver
             .sendLocation(latLng.lat(), latLng.lng(), address);
         console.log("addr=" + address);
diff --git a/android/android-emu/android/skin/qt/html/js/routes.js b/android/android-emu/android/skin/qt/html/js/location-routes.js
similarity index 74%
rename from android/android-emu/android/skin/qt/html/js/routes.js
rename to android/android-emu/android/skin/qt/html/js/location-routes.js
index 1d220c3..8f2cba5 100644
--- a/android/android-emu/android/skin/qt/html/js/routes.js
+++ b/android/android-emu/android/skin/qt/html/js/location-routes.js
@@ -1,6 +1,7 @@
 // Googleplex!
-var lastLatLng = {lat: 37.4220919, lng: -122.0826088};
+var lastLatLng = { lat: 37.4220919, lng: -122.0826088 };
 var gMap;
+var gSearchBox;
 var gFirstPoint;
 // TODO: replace the gstart and gend with WaypointInfo classes
 var gStartLatLng;
@@ -10,7 +11,7 @@
 var gFocusedWaypoint;
 // TODO: add intermediate waypoints
 var gHaveActiveRoute;
-var gMarkers = [];
+var gSearchResultMarkers = [];
 var gDirectionsService;
 var gDirectionsDisplay;
 var gEndMarker;
@@ -59,19 +60,9 @@
     }
 }
 
-function showSearchSpinner(visible) {
-    if (visible) {
-        document.getElementById('search-icon').style.display = 'none';
-        document.getElementById('search-spinner').style.display = 'flex';
-    } else {
-        document.getElementById('search-icon').style.display = 'block';
-        document.getElementById('search-spinner').style.display = 'none';
-    }
-}
-
 function hideAllOverlays() {
-    document.getElementById("startInfoOverlay").style.display = "none";
-    document.getElementById("routeCreatorOverlay").style.display = "none";
+    document.getElementById("startInfoOverlay").className = "pointOverlaySlideOut";
+    document.getElementById("routeCreatorOverlay").className = "routeCreatorOverlayHidden";
 }
 
 function showStartInfoOverlay(address, latLng, elevation) {
@@ -82,19 +73,19 @@
     var lng = latLng.lng().toFixed(4);
     subtitle = lat + ", " + lng + (elevation != null ? ", " + elevation.toFixed(4) : "");
     document.getElementById("startInfoSubtitle").innerHTML = subtitle;
-    document.getElementById("startInfoOverlay").style.display = "flex";
+    document.getElementById("startInfoOverlay").className = "pointOverlayNoBottomPanel"
 }
 
 function showRouteCreatorOverlay(isSavedRoute) {
-    document.getElementById("routeCreatorOverlay").style.display = "flex";
+    document.getElementById("routeCreatorOverlay").className = "routeCreatorOverlay";
     if (isSavedRoute) {
         setTransportMode(gTravelModeString);
     }
 }
 
 function inRouteCreatorMode() {
-    let disp = document.getElementById('routeCreatorOverlay').style.display;
-    return (disp.length > 0 && disp !== "none");
+    let className = document.getElementById('routeCreatorOverlay').className;
+    return (className === "routeCreatorOverlay");
 }
 
 function getTransportMode() {
@@ -115,7 +106,7 @@
     setTransportMode("DRIVING");
     document.getElementById('startAddress').value = '';
     document.getElementById('endAddress').value = '';
-    document.getElementById('routeCreatorOverlay').style.height = 'auto';
+    document.getElementById('routeCreatorOverlay').className = "routeCreatorOverlayHidden"
     document.getElementById('searchResultsOverlay').style.display = 'none';
     gStartWaypoint.invalidate();
     gEndWaypoint.invalidate();
@@ -133,10 +124,10 @@
     var searchItem = document.createElement('div');
     searchItem.classList.add("search-item");
 
-    var icon = document.createElement('div');
+    var icon = document.createElement('i');
     icon.classList.add("search-item-icon");
-    icon.classList.add("maps-sprite-suggest-place-pin");
-    icon.classList.add("grey-marker-icon");
+    icon.classList.add("material-icons");
+    icon.innerText = "place";
     searchItem.appendChild(icon);
 
     var nameSpan = document.createElement('span');
@@ -153,20 +144,20 @@
     searchContainer.appendChild(searchItem);
 
     searchItem.setAttribute("data-place-id", placeId);
-    searchItem.addEventListener('click', function() {
+    searchItem.addEventListener('click', function () {
         var placeid = this.getAttribute("data-place-id");
         var address = this.getAttribute("data-address");
         if (placeid != null) {
-            gGeocoder.geocode({ 'placeId': placeid }, function(results, status) {
+            gGeocoder.geocode({ 'placeId': placeid }, function (results, status) {
                 if (status !== 'OK' || !results[0]) {
                     return;
                 }
                 document.getElementById('searchResultsOverlay').style.display = 'none';
                 clearSearchResults();
-                document.getElementById('routeCreatorOverlay').style.height = 'auto';
+                document.getElementById('routeCreatorOverlay').className = "routeCreatorOverlay";
                 console.log("latlng=" + results[0].geometry.location);
                 if (setWaypointForActiveAddressBox(results[0].geometry.location,
-                                                   results[0].formatted_address)) {
+                    results[0].formatted_address)) {
                     calcRoute();
                 }
             });
@@ -187,7 +178,7 @@
 
 function setWaypointForActiveAddressBox(latLng, address) {
     var focusedWaypoint;
-    if (typeof(gLastFocusedAddrBox) === "undefined") {
+    if (typeof (gLastFocusedAddrBox) === "undefined") {
         console.log("addr box null");
         return false;
     }
@@ -244,12 +235,12 @@
     gFocusedWaypoint.invalidate();
 
     gFocusedWaypoint.setLatLng(latLng);
-    gGeocoder.geocode({ 'location': latLng }, function(results, status) {
+    gGeocoder.geocode({ 'location': latLng }, function (results, status) {
         var address = "";
         var elevation = 0.0;
         if (status === 'OK' && results[0]) {
-          address = results[0].formatted_address;
-          elevation = results[0].elevation;
+            address = results[0].formatted_address;
+            elevation = results[0].elevation;
         }
         gFocusedWaypoint.setAddress(address);
         gFocusedWaypoint.inputDiv.value = address;
@@ -303,12 +294,12 @@
         hideAllOverlays();
         google.maps.event.removeListener(gMapClickedListener);
         gMapClickedListener = null;
-        gMap.setOptions({zoomControl: false});
+        gMap.setOptions({ zoomControl: false });
         document.getElementById('locationInfoOverlay').style.display = 'flex';
         gSearchContainer = gMap.controls[google.maps.ControlPosition.TOP_CENTER].pop();
     } else {
         showRouteCreatorOverlay(true);
-        gMap.setOptions({zoomControl: true});
+        gMap.setOptions({ zoomControl: true });
         document.getElementById('locationInfoOverlay').style.display = 'none';
         gMapClickedListener = google.maps.event.addListener(gMap, 'click', mapClickedEvent);
         gMap.controls[google.maps.ControlPosition.TOP_CENTER].push(gSearchContainer);
@@ -326,7 +317,7 @@
 }
 
 function showDestinationPoint(latLng) {
-    showSearchSpinner(true);
+    gSearchBox.showSpinner();
     gEndLatLng = latLng;
 
     // Clear current pin
@@ -348,17 +339,16 @@
     // got something new under way.
     channel.objects.emulocationserver.sendFullRouteToEmu(0, 0.0, null, null);
 
-    gGeocoder.geocode({ 'location': latLng }, function(results, status) {
+    gGeocoder.geocode({ 'location': latLng }, function (results, status) {
         var address = "";
         var elevation = 0.0;
         if (status === 'OK' && results[0]) {
-          address = results[0].formatted_address;
-          elevation = results[0].elevation;
+            address = results[0].formatted_address;
+            elevation = results[0].elevation;
         }
         gEndWaypoint.setAddress(address);
         showStartInfoOverlay(address, latLng, elevation);
-        document.getElementById('pac-input').value = address;
-        showSearchSpinner(false);
+        gSearchBox.update(address);
     });
 }
 
@@ -369,31 +359,32 @@
         center: lastLatLng,
         zoom: 10,
         zoomControl: true,
-        controlSize: 18,
+        controlSize: 20,
         disableDefaultUI: true
     });
 
     gGeocoder = new google.maps.Geocoder;
     gFirstPoint = true;
     clearDirections();
+    hideAllOverlays();
 
     gStartWaypoint = new WaypointInfo;
     gStartWaypoint.setInputDiv(document.getElementById('startAddress'));
     gEndWaypoint = new WaypointInfo;
     gEndWaypoint.setInputDiv(document.getElementById('endAddress'));
 
-    gBlueMarker = new google.maps.Marker({map: null, position: lastLatLng});
+    gBlueMarker = new google.maps.Marker({ map: null, position: lastLatLng });
 
     // Register a listener that sets a new marker wherever user clicks
     // on the map.
     gMapClickedListener = google.maps.event.addListener(gMap, 'click', mapClickedEvent);
 
-    setDeviceLocation = function(lat, lng) {
+    setDeviceLocation = function (lat, lng) {
         // Called from Qt code to show the blue marker to display the emulator location on the map.
 
         var latLng = new google.maps.LatLng(lat, lng);
         gBlueMarker.setMap(null); // Remove the old marker
-        gBlueMarker = new google.maps.Marker({map: gMap, position: latLng});
+        gBlueMarker = new google.maps.Marker({ map: gMap, position: latLng });
 
         var blueDot = 'data:image/svg+xml, \
                 <svg xmlns="http://www.w3.org/2000/svg" width="24px" height="24px" \
@@ -403,11 +394,11 @@
                         fill="%234286f5" /> \
                 </svg>';
         var image = {
-          url: blueDot,
-          size: new google.maps.Size(24, 24),
-          origin: new google.maps.Point(0, 0),
-          anchor: new google.maps.Point(12, 12),
-          scaledSize: new google.maps.Size(25, 25)
+            url: blueDot,
+            size: new google.maps.Size(24, 24),
+            origin: new google.maps.Point(0, 0),
+            anchor: new google.maps.Point(12, 12),
+            scaledSize: new google.maps.Size(25, 25)
         };
         gBlueMarker.setIcon(image);
         gMap.setCenter(latLng);
@@ -415,7 +406,7 @@
     }
 
     // Receive the selected route from the host
-    setRouteOnMap = function(routeJson) {
+    setRouteOnMap = function (routeJson) {
         if (routeJson.length > 0) {
             hideAllOverlays();
             resetRouteCreatorOverlay();
@@ -437,76 +428,40 @@
             document.getElementById('endAddress').value = theRoute.routes[0].legs[0].end_address;
             showRouteCreatorOverlay(true);
         }
-        gInputBox['value'] = '';
+        gSearchBox.update('');
     }
 
     // Add Google search box
     // Create the search box and link it to the UI element.
-    var searchContainer = document.getElementById('search-container');
-    var gInputBox = /** @type {HTMLInputElement} */ (
-            document.getElementById('pac-input'));
-    gMap.controls[google.maps.ControlPosition.TOP_CENTER].push(searchContainer);
-
-    var autocomplete = new google.maps.places.Autocomplete(
-            /** @type {HTMLInputElement} */
-            (gInputBox));
-    autocomplete.bindTo('bounds', gMap);
+    gSearchBox = new LocationSearchBox();
+    gSearchBox.init(gMap,
+        gSearchResultMarkers,
+        (lastLatLng) => { showDestinationPoint(lastLatLng); },
+        () => { hideAllOverlays(); }
+    );
 
     // For the route creator
     gAutocompleteService = new google.maps.places.AutocompleteService();
 
-    // Listen for the event fired when the user selects an item from the
-    // pick list.
-    autocomplete.addListener('place_changed', function() {
-        // Clear any existing markers
-        for (var i = 0, marker; marker = gMarkers[i]; i++) {
-            marker.setMap(null);
-        }
-        gMarkers = [];
-
-        var place = autocomplete.getPlace();
-        if (!place.geometry) {
-            // User entered the name of a Place that was not suggested and
-            // pressed the Enter key, or the Place Details request failed.
-            // Just ignore it.
-            return;
-        }
-
-        // If the place has a geometry, then present it on a map.
-        if (place.geometry.viewport) {
-            gMap.fitBounds(place.geometry.viewport);
-        } else {
-            gMap.setCenter(place.geometry.location);
-            gMap.setZoom(17);  // Why 17? Because it looks good.
-        }
-
-        showDestinationPoint(place.geometry.location);
-    });
-
-    document.getElementById('search-icon').addEventListener('click', function() {
-        if (gInputBox.value.length > 0) {
-            gInputBox.value = "";
-            hideAllOverlays();
-        }
-    });
-    document.getElementById('closeRouteCreatorButton').addEventListener('click', function() {
+    document.getElementById('closeRouteCreatorButton').addEventListener('click', function () {
         if (gDirectionsDisplay != null) {
             gDirectionsDisplay.setMap(null);
             gDirectionsDisplay = null;
         }
-        document.getElementById("routeCreatorOverlay").style.display = "none";
-        document.getElementById("startInfoOverlay").style.display = "flex";
+        document.getElementById("routeCreatorOverlay").className = "routeCreatorOverlayHidden";
+        document.getElementById("startInfoOverlay").className = "pointOverlayNoBottomPanel";
         resetRouteCreatorOverlay();
     });
 
-    document.getElementById('startNavButton').addEventListener('click', function() {
+    document.getElementById('startNavButton').style.position = 'absolute';
+    document.getElementById('startNavButton').addEventListener('click', function () {
         hideAllOverlays();
         document.getElementById('endAddress').value = gEndWaypoint.address;
         document.getElementById('startAddress').value = "";
         showRouteCreatorOverlay(false);
     });
 
-    var displaySuggestions = function(predictions, status) {
+    var displaySuggestions = function (predictions, status) {
         if (status != google.maps.places.PlacesServiceStatus.OK) {
             return;
         }
@@ -515,67 +470,67 @@
         var numResults = predictions.length > 5 ? kMaxSearchResults : predictions.length;
         for (var i = 0; i < numResults; ++i) {
             addSearchResultItem(predictions[i].structured_formatting.main_text,
-                                predictions[i].structured_formatting.secondary_text,
-                                predictions[i].place_id);
+                predictions[i].structured_formatting.secondary_text,
+                predictions[i].place_id);
         }
     };
 
-    document.getElementById('startAddress').addEventListener('input', function() {
+    document.getElementById('startAddress').addEventListener('input', function () {
         var overlay = document.getElementById('routeCreatorOverlay');
         clearSearchResults();
         clearDirections();
         gStartWaypoint.invalidate();
         if (this.value === "") {
             document.getElementById('searchResultsOverlay').style.display = 'none';
-            overlay.style.height = "auto";
+            overlay.className = "routeCreatorOverlay"
         } else {
-            overlay.style.height = "100%";
+            overlay.className = "routeCreatorOverlayAutoCompleteVisible";
             document.getElementById('searchResultsOverlay').style.display = 'block';
             gLastFocusedAddrBox = this;
-            gAutocompleteService.getPlacePredictions({input: this.value}, displaySuggestions);
+            gAutocompleteService.getPlacePredictions({ input: this.value }, displaySuggestions);
         }
     });
 
-    document.getElementById('startAddress').addEventListener('focusin', function() {
+    document.getElementById('startAddress').addEventListener('focusin', function () {
         this.select();
         var overlay = document.getElementById('routeCreatorOverlay');
         clearSearchResults();
         document.getElementById('searchResultsOverlay').style.display = 'none';
-        overlay.style.height = "auto";
+        overlay.className = "routeCreatorOverlay"
     });
 
-    document.getElementById('endAddress').addEventListener('focusin', function() {
+    document.getElementById('endAddress').addEventListener('focusin', function () {
         this.select();
         var overlay = document.getElementById('routeCreatorOverlay');
         clearSearchResults();
         document.getElementById('searchResultsOverlay').style.display = 'none';
-        overlay.style.height = "auto";
+        overlay.className = "routeCreatorOverlay"
     });
 
-    document.getElementById('endAddress').addEventListener('input', function() {
+    document.getElementById('endAddress').addEventListener('input', function () {
         var overlay = document.getElementById('routeCreatorOverlay');
         clearSearchResults();
         clearDirections();
         gEndWaypoint.invalidate();
         if (this.value === "") {
             document.getElementById('searchResultsOverlay').style.display = 'none';
-            overlay.style.height = "auto";
+            overlay.className = "routeCreatorOverlay"
         } else {
             gLastFocusedAddrBox = this;
-            overlay.style.height = "100%";
+            overlay.className = "routeCreatorOverlayAutoCompleteVisible"
             document.getElementById('searchResultsOverlay').style.display = 'block';
-            gAutocompleteService.getQueryPredictions({input: this.value}, displaySuggestions);
+            gAutocompleteService.getQueryPredictions({ input: this.value }, displaySuggestions);
         }
     });
 
     var modes = document.getElementsByName('transportMode');
     for (var i = 0; i < modes.length; ++i) {
-        modes[i].addEventListener('change', function() {
-           if (this.checked) {
-               console.log("Setting transport mode to " + this.value);
-               gTravelModeString = this.value;
-               calcRoute();
-           }
+        modes[i].addEventListener('change', function () {
+            if (this.checked) {
+                console.log("Setting transport mode to " + this.value);
+                gTravelModeString = this.value;
+                calcRoute();
+            }
         });
     }
 
@@ -597,7 +552,7 @@
     };
     gDirectionsDisplay = new google.maps.DirectionsRenderer();
     gDirectionsDisplay.setMap(gMap);
-    gDirectionsService.route(request, function(result, status) {
+    gDirectionsService.route(request, function (result, status) {
         if (status != 'OK') {
             return;
         }
@@ -608,9 +563,8 @@
         var numPoints = 0;
         var totalDuration = 0.0;
         for (var legIdx = 0;
-             legIdx < result.routes[0].legs.length;
-             legIdx++)
-        {
+            legIdx < result.routes[0].legs.length;
+            legIdx++) {
             totalDuration += result.routes[0].legs[legIdx].duration.value;
 
             var numSteps = result.routes[0].legs[legIdx].steps.length;
diff --git a/android/android-emu/android/skin/qt/html/js/location-search-box.js b/android/android-emu/android/skin/qt/html/js/location-search-box.js
index 52b2ce6..587ac6b 100644
--- a/android/android-emu/android/skin/qt/html/js/location-search-box.js
+++ b/android/android-emu/android/skin/qt/html/js/location-search-box.js
@@ -1,7 +1,8 @@
 class LocationSearchBox {
-    init(map) {
+    init(map, searchResultsMarkers, placeChangedHandler, clearSearchResultsHandler) {
         // Add Google search box
         // Create the search box and link it to the UI element.
+        var self = this;
         var searchContainer = document.getElementById('search-container');
         var input = /** @type {HTMLInputElement} */ (
             document.getElementById('search-input'));
@@ -14,18 +15,13 @@
         // Set the data fields to return when the user selects a place.
         autocomplete.setFields(
             ['address_components', 'geometry', 'icon', 'name']);
-
         // Listen for the event fired when the user selects an item from the
         // pick list.
         autocomplete.addListener('place_changed', function () {
-            // Clear the red pin and any existing search markers
-            if (gPendingMarker != null) {
-                gPendingMarker.setMap(null);
-            }
-            for (marker in gSearchResultMarkers) {
+            for (marker in searchResultsMarkers) {
                 marker.setMap(null);
             }
-            gSearchResultMarkers = [];
+            searchResultsMarkers = [];
 
             var place = autocomplete.getPlace();
             if (!place.geometry) {
@@ -36,8 +32,7 @@
             }
 
             lastLatLng = place.geometry.location;
-            showPendingLocation(lastLatLng.lat(), lastLatLng.lng());
-            sendAddress(lastLatLng);
+            placeChangedHandler(lastLatLng);
 
             // If the place has a geometry, then present it on a map.
             if (place.geometry.viewport) {
@@ -51,28 +46,24 @@
         document.getElementById('search-icon').addEventListener('click', function () {
             if (input.value.length > 0) {
                 input.value = "";
-                this.innerText = "search";
-                gPointOverlay.hide()
-                if (gPendingMarker != null) {
-                    gPendingMarker.setMap(null);
-                }
+                self._showSearchIcon();
+                clearSearchResultsHandler();
             }
         });
         input.addEventListener('input', function () {
-            var searchIcon = $('#search-icon');
             if (input.value.length > 0) {
-                searchIcon.text("close");
+                self._showCloseIcon();
             } else {
-                searchIcon.text("search");
+                self._showSearchIcon();
             }
         });
     }
 
     update(address) {
         $('#search-input').val(address);
-        $('#search-icon').text("close");
         $('#search-icon').css("display", "block");
         $('#search-spinner').css("display", "none");
+        this._showCloseIcon();
     }
 
     showSpinner() {
@@ -80,7 +71,22 @@
         $('#search-spinner').css('display', 'flex');
     }
 
+    hideSpinner() {
+        $('#search-icon').css('display', 'block');
+        $('#search-spinner').css('display', 'none');
+    }
+
     clear() {
+        this._showSearchIcon();
+    }
+
+    _showSearchIcon() {
         $('#search-icon').text("search");
+        $('#search-icon').css("color", "#b1b1b1");
+    }
+
+    _showCloseIcon() {
+        $('#search-icon').text("close");
+        $('#search-icon').css("color", "#555555");
     }
 }
diff --git a/android/android-emu/android/skin/qt/html/js/points.js b/android/android-emu/android/skin/qt/html/js/points.js
deleted file mode 100644
index 04e6a9d..0000000
--- a/android/android-emu/android/skin/qt/html/js/points.js
+++ /dev/null
@@ -1,217 +0,0 @@
-// Googleplex!
-var lastLatLng = {lat: 37.4220919, lng: -122.0826088};
-var sevDeviceLocation;
-var gMap;
-var gGeocoder;
-var gCurrentMarker; // The blue dot
-var gPendingMarker; // The red "pin"
-var gSearchResultMarkers = [];
-
-function savePoint() {
-    // The emulator should have the point of interest already, from the
-    // sendAddress() call.
-    channel.objects.emulocationserver.map_savePoint();
-}
-
-function hideAllOverlays() {
-    document.getElementById("savePointOverlay").style.display = "none";
-    document.getElementById("pointInfoOverlay").style.display = "none";
-}
-
-function resetPointsMap() {
-    hideAllOverlays();
-}
-
-function showPointInfoOverlay(address, latLng, elevation) {
-    hideAllOverlays();
-    document.getElementById("pointInfoTitle").innerHTML = address;
-    var lat = latLng.lat().toFixed(4);
-    var lng = latLng.lng().toFixed(4);
-    subtitle = lat + ", " + lng + (elevation != null ? ", " + elevation.toFixed(4) : "");
-    document.getElementById("pointInfoSubtitle").innerHTML = subtitle;
-    document.getElementById("pointInfoOverlay").style.display = "flex";
-}
-
-// Callback function for Maps API
-function initMap() {
-    // Create a map object and specify the DOM element for display.
-    gMap = new google.maps.Map(document.getElementById('map'), {
-        center: lastLatLng,
-        zoom: 10,
-        zoomControl: true,
-        controlSize: 18,
-        disableDefaultUI: true
-    });
-    gGeocoder = new google.maps.Geocoder;
-
-    function showPin(latLng) {
-        // Clear current pin
-        if (gPendingMarker != null) {
-            gPendingMarker.setMap(null);
-        }
-        // Clear all current search markers
-        for (var i = 0, marker; marker = gSearchResultMarkers[i]; i++) {
-            marker.setMap(null);
-        }
-        gSearchResultMarkers = [];
-
-        // Create a new pin at this location
-        gPendingMarker = new google.maps.Marker({
-            map: gMap,
-            position: latLng
-        });
-        var bounds = gMap.getBounds();
-        if (bounds == null || !bounds.contains(latLng)) {
-            gMap.setCenter(latLng);
-        }
-    }
-    function showSavePointOverlay(address, latLng, elevation) {
-        hideAllOverlays();
-        document.getElementById("savePointTitle").innerHTML = address;
-        var lat = latLng.lat().toFixed(4);
-        var lng = latLng.lng().toFixed(4);
-        subtitle = lat + ", " + lng + (elevation != null ? ", " + elevation.toFixed(4) : "");
-        document.getElementById("savePointSubtitle").innerHTML = subtitle;
-        document.getElementById("savePointOverlay").style.display = "block";
-    }
-    function sendAddress(latLng) {
-        gGeocoder.geocode({ 'location': latLng }, function(results, status) {
-            var address = "";
-            var elevation = 0.0;
-            if (status === 'OK' && results[0]) {
-              address = results[0].formatted_address;
-              elevation = results[0].elevation;
-            }
-            showSavePointOverlay(address, latLng, elevation);
-            channel.objects.emulocationserver
-                .sendLocation(latLng.lat(), latLng.lng(), address);
-            console.log("addr=" + address);
-            document.getElementById('pac-input').value = address;
-            document.getElementById('search-icon').style.display = 'block';
-            document.getElementById('search-spinner').style.display = 'none';
-        });
-    }
-
-    // Register a listener that sets a new marker wherever the
-    // user clicks on the map.
-    google.maps.event.addListener(gMap, 'click', function(event) {
-        // TODO: add spinner here
-        document.getElementById('search-icon').style.display = 'none';
-        document.getElementById('search-spinner').style.display = 'flex';
-        showPin(event.latLng);
-
-        // Send the location coordinates to the emulator
-        lastLatLng = event.latLng;
-        sendAddress(lastLatLng);
-    });
-
-    showPendingLocation = function(lat, lng, addr) {
-        // Called from Qt code to show a pending location on the UI map.
-        // This point has NOT been sent to the AVD.
-        var latLng = new google.maps.LatLng(lat, lng);
-        showPin(latLng);
-        // TODO: no support for elevation yet.
-        showPointInfoOverlay(addr, latLng, null);
-    }
-
-    setDeviceLocation = function(lat, lng) {
-        // Called from Qt code to show the blue marker to display the emulator location on the map.
-        // Code to set location marker on the map. Move this to a signal event handler.
-
-        // Clear any existing blue dot and red pin
-        if (gCurrentMarker != null) {
-            gCurrentMarker.setMap(null);
-        }
-        if (gPendingMarker != null) {
-            gPendingMarker.setMap(null);
-        }
-
-        var latLng = new google.maps.LatLng(lat, lng);
-        gCurrentMarker = new google.maps.Marker({ map: gMap, position: latLng});
-
-        var blueDot = 'data:image/svg+xml, \
-                <svg xmlns="http://www.w3.org/2000/svg" width="24px" height="24px" \
-                        viewBox="0 0 24 24" fill="%23000000"> \
-                    <circle cx="12" cy="12" r="10" fill="black" opacity=".1" /> \
-                    <circle cx="12" cy="12" r="8" stroke="white" stroke-width="2" \
-                        fill="%234286f5" /> \
-                </svg>';
-        var image = {
-          url: blueDot,
-          size: new google.maps.Size(24, 24),
-          origin: new google.maps.Point(0, 0),
-          anchor: new google.maps.Point(12, 12),
-          scaledSize: new google.maps.Size(25, 25)
-        };
-        var bounds = gMap.getBounds();
-        if (bounds == null || !bounds.contains(latLng)) {
-            gMap.setCenter(latLng);
-        }
-        gCurrentMarker.setIcon(image);
-    }
-
-    function markerListener(event) {
-        lastLatLng = event.latLng;
-        showPin(lastLatLng);
-        sendAddress(lastLatLng);
-    }
-
-    // Add Google search box
-    // Create the search box and link it to the UI element.
-    var searchContainer = document.getElementById('search-container');
-    var input = /** @type {HTMLInputElement} */ (
-            document.getElementById('pac-input'));
-    gMap.controls[google.maps.ControlPosition.TOP_CENTER].push(searchContainer);
-
-    var autocomplete = new google.maps.places.Autocomplete(
-            /** @type {HTMLInputElement} */
-            (input));
-    autocomplete.bindTo('bounds', gMap);
-    // Set the data fields to return when the user selects a place.
-    autocomplete.setFields(
-        ['address_components', 'geometry', 'icon', 'name']);
-
-    // Listen for the event fired when the user selects an item from the
-    // pick list.
-    autocomplete.addListener('place_changed', function() {
-        // Clear the red pin and any existing search markers
-        if (gPendingMarker != null) {
-            gPendingMarker.setMap(null);
-        }
-        for (var i = 0, marker; marker = gSearchResultMarkers[i]; i++) {
-            marker.setMap(null);
-        }
-        gSearchResultMarkers = [];
-
-        var place = autocomplete.getPlace();
-        if (!place.geometry) {
-            // User entered the name of a Place that was not suggested and
-            // pressed the Enter key, or the Place Details request failed.
-            // Just ignore it.
-            return;
-        }
-
-        lastLatLng = place.geometry.location;
-        showPendingLocation(lastLatLng.lat(), lastLatLng.lng());
-        sendAddress(lastLatLng);
-
-        // If the place has a geometry, then present it on a map.
-        if (place.geometry.viewport) {
-            gMap.fitBounds(place.geometry.viewport);
-        } else {
-            gMap.setCenter(place.geometry.location);
-            gMap.setZoom(17);  // Why 17? Because it looks good.
-        }
-    });
-
-    document.getElementById('search-icon').addEventListener('click', function() {
-        if (input.value.length > 0) {
-            input.value = "";
-            hideAllOverlays();
-            if (gPendingMarker != null) {
-                gPendingMarker.setMap(null);
-            }
-        }
-    });
-}
-
diff --git a/android/android-emu/android/skin/qt/html/index.html b/android/android-emu/android/skin/qt/html/location-point.html
similarity index 97%
rename from android/android-emu/android/skin/qt/html/index.html
rename to android/android-emu/android/skin/qt/html/location-point.html
index ed6456a..8ebd1b6 100644
--- a/android/android-emu/android/skin/qt/html/index.html
+++ b/android/android-emu/android/skin/qt/html/location-point.html
@@ -40,6 +40,7 @@
   </div>
   <script src="https://maps.googleapis.com/maps/api/js?libraries=places&key=YOUR_API_KEY&callback=initMap" async
     defer></script>
+  <script src="js/location-loader.js"></script>
 </body>
 
 </html>
\ No newline at end of file
diff --git a/android/android-emu/android/skin/qt/html/location-route.html b/android/android-emu/android/skin/qt/html/location-route.html
new file mode 100644
index 0000000..dc078cf
--- /dev/null
+++ b/android/android-emu/android/skin/qt/html/location-route.html
@@ -0,0 +1,101 @@
+<!doctype html>
+<html lang="en">
+
+<head>
+    <title>Android Emulator Location Picker</title>
+    <meta name="viewport" content="initial-scale=1.0">
+    <meta charset="utf-8">
+    <link rel="stylesheet" href="css/location.css">
+    <link rel="stylesheet" href="https://unpkg.com/material-components-web@latest/dist/material-components-web.min.css">
+    <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
+    <script src="https://unpkg.com/material-components-web@latest/dist/material-components-web.min.js"></script>
+    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
+    <script src="js/location-mock-web-channel.js"></script>
+    <script src="js/location-point-overlay.js"></script>
+    <script src="js/location-search-box.js"></script>
+    <script src="js/location-routes.js"></script>
+</head>
+
+<body>
+    <div id="search-container" class="search-container mdc-ripple-surface">
+        <input id="search-input" class="search-input" type="text" placeholder="Search">
+        <div id="search-spinner" class="spinner-container">
+            <div class="spinner"></div>
+        </div>
+        <div id="search-icon" class="search-icon material-icons">search</div>
+    </div>
+    <div id="map"></div>
+    <div id="startInfoOverlay" class="pointOverlaySlideOut">
+        <div id="startNavButton" class="circular-button mdc-ripple-surface">
+            <div class="directions-icon"></div>
+        </div>
+        <div id="startInfoTitle" class="title">Port Authority Bus Terminal, NY</div>
+        <div id="startInfoSubtitle" class="subtitle">40.134832, -74.832453, 14.34</div>
+    </div>
+    <div id="locationInfoOverlay">
+    </div>
+    <div id="routeCreatorOverlay" class="routeCreatorOverlayHidden">
+        <div id="upperbox">
+            <div style="display: flex; width: 100%;">
+                <div style="display: flex; width: 100%; padding-left: 48px;">
+                    <label class="transport-mode-container">
+                        <input id="transportModeCar" type="radio" checked="checked" name="transportMode"
+                            value="DRIVING">
+                        <div>
+                            <img class="transport-mode-car"></img>
+                        </div>
+                    </label>
+                    <label class="transport-mode-container">
+                        <input id="transportModeTransit" type="radio" name="transportMode" value="TRANSIT">
+                        <div>
+                            <img class="transport-mode-transit"></img>
+                        </div>
+                    </label>
+                    <label class="transport-mode-container">
+                        <input id="transportModeBike" type="radio" name="transportMode" value="BICYCLING">
+                        <div>
+                            <img class="transport-mode-bike"></img>
+                        </div>
+                    </label>
+                    <label class="transport-mode-container">
+                        <input id="transportModeWalk" type="radio" name="transportMode" value="WALKING">
+                        <div>
+                            <img class="transport-mode-walk"></img>
+                        </div>
+                    </label>
+                </div>
+                <div id="closeRouteCreatorButton" class="close-icon"></div>
+            </div>
+            <div id="waypoints-container">
+                <div id="waypoints-icons-container">
+                    <div class="widget-directions-icon start-dot-icon"></div>
+                    <div class="widget-directions-icon waypoints-icon"></div>
+                    <div class="widget-directions-icon end-marker-icon"></div>
+                </div>
+                <div id="waypoints-addrs-container">
+                    <input id="startAddress" name="waypoints" class="waypoint-addr-input" type="text"
+                        placeholder="Choose starting point, or click on the map..." />
+                    <input id="endAddress" name="waypoints" class="waypoint-addr-input" type="text"
+                        placeholder="The destination" />
+                </div>
+                <div id="waypoints-reverse-container">
+                    <div class="widget-directions-icon reverse-icon" onclick="onReverseButtonClicked()"></div>
+                </div>
+            </div>
+        </div>
+        <div id="lowerbox" style="justify-content: space-between">
+            <div
+                style="height: 100%; display: flex; flex-direction: column; justify-content: center; margin-left: 12px;">
+                <div class="location-icons material-icons">add_circle_outline</div>
+            </div>
+            <div id="saveRouteButton" class="common-button" onclick="saveRouteButton_clicked()">
+                SAVE ROUTE
+            </div>
+        </div>
+        <div id="searchResultsOverlay"></div>
+        <script src="https://maps.googleapis.com/maps/api/js?libraries=places&key=YOUR_API_KEY&callback=initMap" async
+            defer></script>
+        <script src="js/location-loader.js"></script>
+</body>
+
+</html>
\ No newline at end of file
diff --git a/android/android-emu/android/skin/qt/html/route.html b/android/android-emu/android/skin/qt/html/route.html
deleted file mode 100644
index 5209ce4..0000000
--- a/android/android-emu/android/skin/qt/html/route.html
+++ /dev/null
@@ -1,92 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-    <title>Android Emulator Location Picker</title>
-    <meta name="viewport" content="initial-scale=1.0">
-    <meta charset="utf-8">
-    <link rel="stylesheet" href="css/common.css">
-    <script src="js/common.js"></script>
-    <script src="js/routes.js"></script>
-    <script src="https://maps.googleapis.com/maps/api/js?libraries=places&key=YOUR_API_KEY&callback=initMap" async defer></script>
-</head>
-<body>
-    <div id="search-container">
-     <input id="pac-input" class="controls" type="text" placeholder="Search">
-     <div id="search-spinner" class="loader-container" style="display: none">
-      <div class="loader"></div>
-     </div>
-     <div id="search-icon" class="search-icon"></div>
-    </div>
-    <div id="map"></div>
-    <div id="startInfoOverlay">
-      <div id="startNavButton" class="circular-button">
-       <div class="directions-icon"></div>
-      </div>
-      <div id="startInfoTitle" class="title">Port Authority Bus Terminal, NY</div>
-      <div id="startInfoSubtitle" class="subtitle">40.134832, -74.832453, 14.34</div>
-    </div>
-    <div id="locationInfoOverlay">
-    </div>
-    <div id="routeCreatorOverlay">
-     <div id="upperbox">
-      <div style="display: flex; width: 100%;">
-       <div style="display: flex; width: 100%; padding-left: 48px;">
-        <label class="transport-mode-container">
-         <input id="transportModeCar" type="radio" checked="checked" name="transportMode" value="DRIVING">
-         <div>
-          <img class="transport-mode-car"></img>
-         </div>
-        </label>
-        <label class="transport-mode-container">
-         <input id="transportModeTransit" type="radio" name="transportMode" value="TRANSIT">
-         <div>
-          <img class="transport-mode-transit"></img>
-         </div>
-        </label>
-        <label class="transport-mode-container">
-         <input id="transportModeBike" type="radio" name="transportMode" value="BICYCLING">
-         <div>
-          <img class="transport-mode-bike"></img>
-         </div>
-        </label>
-        <label class="transport-mode-container">
-         <input id="transportModeWalk" type="radio" name="transportMode" value="WALKING">
-         <div>
-          <img class="transport-mode-walk"></img>
-         </div>
-        </label>
-       </div>
-       <div id="closeRouteCreatorButton" class="close-icon"></div>
-      </div>
-      <div id="waypoints-container">
-       <div id="waypoints-icons-container">
-        <div class="widget-directions-icon start-dot-icon"></div>
-        <div class="widget-directions-icon waypoints-icon"></div>
-        <div class="widget-directions-icon end-marker-icon"></div>
-       </div>
-       <div id="waypoints-addrs-container">
-        <input id="startAddress" name="waypoints" class="waypoint-addr-input" type="text" placeholder="Choose starting point, or click on the map..." />
-        <input id="endAddress" name="waypoints" class="waypoint-addr-input" type="text" placeholder="The destination" />
-       </div>
-       <div id="waypoints-reverse-container">
-        <div class="widget-directions-icon reverse-icon" onclick="onReverseButtonClicked()"></div>
-       </div>
-      </div>
-     </div>
-     <div id="lowerbox" style="justify-content: space-between">
-      <div style="height=100%; display: flex; flex-direction: column; justify-content: center; margin-left: 12px;">
-       <!-- TODO: NOT IMPLEMENTED -->
-       <div class="widget-directions-icon add-waypoint-icon" style="display: none"></div>
-      </div>
-      <div id="saveRouteButton" class="common-button" style="margin-right: 24px;" onclick="saveRouteButton_clicked()">
-       SAVE ROUTE
-      </div>
-     </div>
-     <div id="searchResultsOverlay">
-      <div class="search-item">
-        <div class="search-item-icon maps-sprite-suggest-place-pin grey-marker-icon"></div>
-        <span class="name">Dazzling Hair Salon <span class="address">fiewnwnifn feiwenf iowef South Bascom Avenue, Campbell, CA</span></span>
-     </div>
-    </div>
-</body>
-</html>
diff --git a/android/android-emu/android/skin/qt/resources.qrc b/android/android-emu/android/skin/qt/resources.qrc
index 3b3414f..b9b1976 100644
--- a/android/android-emu/android/skin/qt/resources.qrc
+++ b/android/android-emu/android/skin/qt/resources.qrc
@@ -13,18 +13,16 @@
     <qresource prefix="/">
         <file alias="styles/stylesheet_template.css">styles/stylesheet_template.css</file>
         <file alias="styles/fonts_stylesheet_template.css">styles/fonts_stylesheet_template.css</file>
-        <file alias="html/index.html">html/index.html</file>
-        <file alias="html/route.html">html/route.html</file>
+        <file alias="html/location-point.html">html/location-point.html</file>
+        <file alias="html/location-route.html">html/location-route.html</file>
         <file alias="html/js/qwebchannel.js">../../../html/js/qwebchannel.js</file>
-        <file alias="html/css/common.css">html/css/common.css</file>
         <file alias="html/css/location.css">html/css/location.css</file>
-        <file alias="html/js/common.js">html/js/common.js</file>
-        <file alias="html/js/points.js">html/js/points.js</file>
+        <file alias="html/js/location-loader.js">html/js/location-loader.js</file>
         <file alias="html/js/location-mock-web-channel.js">html/js/location-mock-web-channel.js</file>
         <file alias="html/js/location-point-overlay.js">html/js/location-point-overlay.js</file>
         <file alias="html/js/location-point.js">html/js/location-point.js</file>
+        <file alias="html/js/location-routes.js">html/js/location-routes.js</file>
         <file alias="html/js/location-search-box.js">html/js/location-search-box.js</file>
-        <file alias="html/js/routes.js">html/js/routes.js</file>
     </qresource>
     <qresource prefix="/lib/fonts">
          <!-- The names 'Roboto*' are used to load the fonts in