[automerger skipped] Import translations. DO NOT MERGE am: ffc2bff725 -s ours

am skip reason: subject contains skip directive

Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/apps/Car/libs/+/12082226

Change-Id: I593110f68c22121b6c8684f13f07b226bf4415cc
diff --git a/EncryptionRunner/Android.bp b/EncryptionRunner/Android.bp
deleted file mode 100644
index 54316ff..0000000
--- a/EncryptionRunner/Android.bp
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright (C) 2019 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-android_library {
-    name: "EncryptionRunner-lib",
-    min_sdk_version: "23",
-    product_variables: {
-        pdk: {
-            enabled: false,
-        },
-    },
-    static_libs: [
-      "ukey2",
-    ],
-    srcs: [
-        "src/**/*.java",
-    ],
-    installable: true,
-}
-
diff --git a/EncryptionRunner/AndroidManifest.xml b/EncryptionRunner/AndroidManifest.xml
deleted file mode 100644
index 3ebdf42..0000000
--- a/EncryptionRunner/AndroidManifest.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2019 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-        xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
-        package="android.car.encryptionrunner" >
-    <uses-sdk android:minSdkVersion="23" android:targetSdkVersion="23" />
-</manifest>
diff --git a/EncryptionRunner/src/android/car/encryptionrunner/DummyEncryptionRunner.java b/EncryptionRunner/src/android/car/encryptionrunner/DummyEncryptionRunner.java
deleted file mode 100644
index 5b63dbc..0000000
--- a/EncryptionRunner/src/android/car/encryptionrunner/DummyEncryptionRunner.java
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.car.encryptionrunner;
-
-import android.annotation.IntDef;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * An encryption runner that doesn't actually do encryption. Useful for debugging. Do not use in
- * production environments.
- */
-@VisibleForTesting
-public class DummyEncryptionRunner implements EncryptionRunner {
-
-    private static final String KEY = "key";
-    private static final byte[] DUMMY_MESSAGE = "Dummy Message".getBytes();
-    @VisibleForTesting
-    public static final String INIT = "init";
-    @VisibleForTesting
-    public static final String INIT_RESPONSE = "initResponse";
-    @VisibleForTesting
-    public static final String CLIENT_RESPONSE = "clientResponse";
-    public static final String VERIFICATION_CODE = "1234";
-
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef({Mode.UNKNOWN, Mode.CLIENT, Mode.SERVER})
-    private @interface Mode {
-
-        int UNKNOWN = 0;
-        int CLIENT = 1;
-        int SERVER = 2;
-    }
-
-    private boolean mIsReconnect;
-    private boolean mInitReconnectVerification;
-    private Key mCurrentDummyKey;
-    @Mode
-    private int mMode;
-    @HandshakeMessage.HandshakeState
-    private int mState;
-
-    @Override
-    public HandshakeMessage initHandshake() {
-        checkRunnerIsNew();
-        mMode = Mode.CLIENT;
-        mState = HandshakeMessage.HandshakeState.IN_PROGRESS;
-        return HandshakeMessage.newBuilder()
-                .setHandshakeState(mState)
-                .setNextMessage(INIT.getBytes())
-                .build();
-    }
-
-    @Override
-    public HandshakeMessage respondToInitRequest(byte[] initializationRequest)
-            throws HandshakeException {
-        checkRunnerIsNew();
-        mMode = Mode.SERVER;
-        if (!new String(initializationRequest).equals(INIT)) {
-            throw new HandshakeException("Unexpected initialization request");
-        }
-        mState = HandshakeMessage.HandshakeState.IN_PROGRESS;
-        return HandshakeMessage.newBuilder()
-                .setHandshakeState(HandshakeMessage.HandshakeState.IN_PROGRESS)
-                .setNextMessage(INIT_RESPONSE.getBytes())
-                .build();
-    }
-
-    private void checkRunnerIsNew() {
-        if (mState != HandshakeMessage.HandshakeState.UNKNOWN) {
-            throw new IllegalStateException("runner already initialized.");
-        }
-    }
-
-    @Override
-    public HandshakeMessage continueHandshake(byte[] response) throws HandshakeException {
-        if (mState != HandshakeMessage.HandshakeState.IN_PROGRESS) {
-            throw new HandshakeException("not waiting for response but got one");
-        }
-        switch (mMode) {
-            case Mode.SERVER:
-                if (!CLIENT_RESPONSE.equals(new String(response))) {
-                    throw new HandshakeException("unexpected response: " + new String(response));
-                }
-                mState = HandshakeMessage.HandshakeState.VERIFICATION_NEEDED;
-                if (mIsReconnect) {
-                    verifyPin();
-                    mState = HandshakeMessage.HandshakeState.RESUMING_SESSION;
-                }
-                return HandshakeMessage.newBuilder()
-                        .setVerificationCode(VERIFICATION_CODE)
-                        .setHandshakeState(mState)
-                        .build();
-            case Mode.CLIENT:
-                if (!INIT_RESPONSE.equals(new String(response))) {
-                    throw new HandshakeException("unexpected response: " + new String(response));
-                }
-                mState = HandshakeMessage.HandshakeState.VERIFICATION_NEEDED;
-                if (mIsReconnect) {
-                    verifyPin();
-                    mState = HandshakeMessage.HandshakeState.RESUMING_SESSION;
-                }
-                return HandshakeMessage.newBuilder()
-                        .setHandshakeState(mState)
-                        .setNextMessage(CLIENT_RESPONSE.getBytes())
-                        .setVerificationCode(VERIFICATION_CODE)
-                        .build();
-            default:
-                throw new IllegalStateException("unexpected role: " + mMode);
-        }
-    }
-
-    @Override
-    public HandshakeMessage authenticateReconnection(byte[] message, byte[] previousKey)
-            throws HandshakeException {
-        mCurrentDummyKey = new DummyKey();
-        // Blindly verify the reconnection because this is a dummy encryption runner.
-        return HandshakeMessage.newBuilder()
-                .setHandshakeState(HandshakeMessage.HandshakeState.FINISHED)
-                .setKey(mCurrentDummyKey)
-                .setNextMessage(mInitReconnectVerification ? null : DUMMY_MESSAGE)
-                .build();
-    }
-
-    @Override
-    public HandshakeMessage initReconnectAuthentication(byte[] previousKey)
-            throws HandshakeException {
-        mInitReconnectVerification = true;
-        mState = HandshakeMessage.HandshakeState.RESUMING_SESSION;
-        return HandshakeMessage.newBuilder()
-                .setHandshakeState(mState)
-                .setNextMessage(DUMMY_MESSAGE)
-                .build();
-    }
-
-    @Override
-    public Key keyOf(byte[] serialized) {
-        return new DummyKey();
-    }
-
-    @Override
-    public HandshakeMessage verifyPin() throws HandshakeException {
-        if (mState != HandshakeMessage.HandshakeState.VERIFICATION_NEEDED) {
-            throw new IllegalStateException("asking to verify pin, state = " + mState);
-        }
-        mState = HandshakeMessage.HandshakeState.FINISHED;
-        return HandshakeMessage.newBuilder().setKey(new DummyKey()).setHandshakeState(
-                mState).build();
-    }
-
-    @Override
-    public void invalidPin() {
-        mState = HandshakeMessage.HandshakeState.INVALID;
-    }
-
-    @Override
-    public void setIsReconnect(boolean isReconnect) {
-        mIsReconnect = isReconnect;
-    }
-
-    private class DummyKey implements Key {
-        @Override
-        public byte[] asBytes() {
-            return KEY.getBytes();
-        }
-
-        @Override
-        public byte[] encryptData(byte[] data) {
-            return data;
-        }
-
-        @Override
-        public byte[] decryptData(byte[] encryptedData) {
-            return encryptedData;
-        }
-
-        @Override
-        public byte[] getUniqueSession() {
-            return KEY.getBytes();
-        }
-    }
-}
diff --git a/EncryptionRunner/src/android/car/encryptionrunner/EncryptionRunner.java b/EncryptionRunner/src/android/car/encryptionrunner/EncryptionRunner.java
deleted file mode 100644
index f0a34b2..0000000
--- a/EncryptionRunner/src/android/car/encryptionrunner/EncryptionRunner.java
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.car.encryptionrunner;
-
-import android.annotation.NonNull;
-
-/**
- * A generalized interface that allows for generating shared secrets as well as encrypting
- * messages.
- *
- * To use this interface:
- *
- * <p>1. As a client.
- *
- * {@code
- * HandshakeMessage initialClientMessage = clientRunner.initHandshake();
- * sendToServer(initialClientMessage.getNextMessage());
- * byte message = getServerResponse();
- * HandshakeMessage message = clientRunner.continueHandshake(message);
- * }
- *
- * <p>If it is a first-time connection,
- *
- * {@code message.getHandshakeState()} should be VERIFICATION_NEEDED, show user the verification
- * code and ask to verify.
- * After user confirmed, {@code HandshakeMessage lastMessage = clientRunner.verifyPin();} otherwise
- * {@code clientRunner.invalidPin(); }
- *
- * Use {@code lastMessage.getKey()} to get the key for encryption.
- *
- * <p>If it is a reconnection,
- *
- * {@code message.getHandshakeState()} should be RESUMING_SESSION, PIN has been verified blindly,
- * send the authentication message over to server, then authenticate the message from server.
- *
- * {@code
- * clientMessage = clientRunner.initReconnectAuthentication(previousKey)
- * sendToServer(clientMessage.getNextMessage());
- * HandshakeMessage lastMessage = clientRunner.authenticateReconnection(previousKey, message)
- * }
- *
- * {@code lastMessage.getHandshakeState()} should be FINISHED if reconnection handshake is done.
- *
- * <p>2. As a server.
- *
- * {@code
- * byte[] initialMessage = getClientMessageBytes();
- * HandshakeMessage message = serverRunner.respondToInitRequest(initialMessage);
- * sendToClient(message.getNextMessage());
- * byte[] clientMessage = getClientResponse();
- * HandshakeMessage message = serverRunner.continueHandshake(clientMessage);}
- *
- * <p>if it is a first-time connection,
- *
- * {@code message.getHandshakeState()} should be VERIFICATION_NEEDED, show user the verification
- * code and ask to verify.
- * After PIN is confirmed, {@code HandshakeMessage lastMessage = serverRunner.verifyPin}, otherwise
- * {@code clientRunner.invalidPin(); }
- * Use {@code lastMessage.getKey()} to get the key for encryption.
- *
- * <p>If it is a reconnection,
- *
- * {@code message.getHandshakeState()} should be RESUMING_SESSION,PIN has been verified blindly,
- * waiting for client message.
- * After client message been received,
- * {@code serverMessage = serverRunner.authenticateReconnection(previousKey, message);
- * sendToClient(serverMessage.getNextMessage());}
- * {@code serverMessage.getHandshakeState()} should be FINISHED if reconnection handshake is done.
- *
- * Also see {@link EncryptionRunnerTest} for examples.
- */
-public interface EncryptionRunner {
-
-    String TAG = "EncryptionRunner";
-
-    /**
-     * Starts an encryption handshake.
-     *
-     * @return A handshake message with information about the handshake that is started.
-     */
-    @NonNull
-    HandshakeMessage initHandshake();
-
-    /**
-     * Starts an encryption handshake where the device that is being communicated with already
-     * initiated the request.
-     *
-     * @param initializationRequest the bytes that the other device sent over.
-     * @return a handshake message with information about the handshake.
-     * @throws HandshakeException if initialization request is invalid.
-     */
-    @NonNull
-    HandshakeMessage respondToInitRequest(@NonNull byte[] initializationRequest)
-            throws HandshakeException;
-
-    /**
-     * Continues a handshake after receiving another response from the connected device.
-     *
-     * @param response the response from the other device.
-     * @return a message that can be used to continue the handshake.
-     * @throws HandshakeException if unexpected bytes in response.
-     */
-    @NonNull
-    HandshakeMessage continueHandshake(@NonNull byte[] response) throws HandshakeException;
-
-    /**
-     * Verifies the pin shown to the user. The result is the next handshake message and will
-     * typically contain an encryption key.
-     *
-     * @throws HandshakeException if not in state to verify pin.
-     */
-    @NonNull
-    HandshakeMessage verifyPin() throws HandshakeException;
-
-    /**
-     * Notifies the encryption runner that the user failed to validate the pin. After calling this
-     * method the runner should not be used, and will throw exceptions.
-     */
-    void invalidPin();
-
-    /**
-     * Verifies the reconnection message.
-     *
-     * <p>The message passed to this method should have been generated by
-     * {@link #initReconnectAuthentication(byte[] previousKey)}.
-     *
-     * <p>If the message is valid, then a {@link HandshakeMessage} will be returned that contains
-     * the encryption key and a handshake message which can be used to verify the other side of the
-     * connection.
-     *
-     * @param previousKey previously stored key.
-     * @param message     message from the client
-     * @return a handshake message with an encryption key if verification succeed.
-     * @throws HandshakeException if the message does not match.
-     */
-    @NonNull
-    HandshakeMessage authenticateReconnection(@NonNull byte[] message, @NonNull byte[] previousKey)
-            throws HandshakeException;
-
-    /**
-     * Initiates the reconnection verification by generating a message that should be sent to the
-     * device that is being reconnected to.
-     *
-     * @param previousKey previously stored key.
-     * @return a handshake message with client's message which will be sent to server.
-     * @throws HandshakeException when get encryption key's unique session fail.
-     */
-    @NonNull
-    HandshakeMessage initReconnectAuthentication(@NonNull byte[] previousKey)
-            throws HandshakeException;
-
-    /**
-     * De-serializes a previously serialized key generated by an instance of this encryption runner.
-     *
-     * @param serialized the serialized bytes of the key.
-     * @return the Key object used for encryption.
-     */
-    @NonNull
-    Key keyOf(@NonNull byte[] serialized);
-
-    /**
-     * Set the signal if it is a reconnection process.
-     *
-     * @param isReconnect {@code true} if it is a reconnect.
-     */
-    void setIsReconnect(boolean isReconnect);
-}
diff --git a/EncryptionRunner/src/android/car/encryptionrunner/EncryptionRunnerFactory.java b/EncryptionRunner/src/android/car/encryptionrunner/EncryptionRunnerFactory.java
deleted file mode 100644
index 156abd8..0000000
--- a/EncryptionRunner/src/android/car/encryptionrunner/EncryptionRunnerFactory.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.car.encryptionrunner;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-/**
- * Factory that creates encryption runner.
- */
-public class EncryptionRunnerFactory {
-
-    private EncryptionRunnerFactory() {
-        // prevent instantiation.
-    }
-
-    /**
-     * Creates a new {@link EncryptionRunner}.
-     */
-    public static EncryptionRunner newRunner() {
-        return new Ukey2EncryptionRunner();
-    }
-
-    /**
-     * Creates a new {@link EncryptionRunner} one that doesn't actually do encryption but is useful
-     * for testing.
-     */
-    @VisibleForTesting
-    public static EncryptionRunner newDummyRunner() {
-        return new DummyEncryptionRunner();
-    }
-}
diff --git a/EncryptionRunner/src/android/car/encryptionrunner/HandshakeException.java b/EncryptionRunner/src/android/car/encryptionrunner/HandshakeException.java
deleted file mode 100644
index 185a21c..0000000
--- a/EncryptionRunner/src/android/car/encryptionrunner/HandshakeException.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.car.encryptionrunner;
-
-/**
- * Exception indicating an error during a Handshake of EncryptionRunner.
- */
-public class HandshakeException extends Exception {
-
-    HandshakeException(String message) {
-        super(message);
-    }
-
-    HandshakeException(Exception e) {
-        super(e);
-    }
-}
diff --git a/EncryptionRunner/src/android/car/encryptionrunner/HandshakeMessage.java b/EncryptionRunner/src/android/car/encryptionrunner/HandshakeMessage.java
deleted file mode 100644
index fa6705d..0000000
--- a/EncryptionRunner/src/android/car/encryptionrunner/HandshakeMessage.java
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.car.encryptionrunner;
-
-import android.annotation.IntDef;
-import android.annotation.Nullable;
-import android.text.TextUtils;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * During an {@link EncryptionRunner} handshake process, these are the messages returned as part
- * of each step.
- */
-public class HandshakeMessage {
-
-    /**
-     * States for handshake progress.
-     */
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef({HandshakeState.UNKNOWN, HandshakeState.IN_PROGRESS, HandshakeState.VERIFICATION_NEEDED,
-            HandshakeState.FINISHED, HandshakeState.INVALID, HandshakeState.RESUMING_SESSION,})
-    public @interface HandshakeState {
-        /**
-         * The initial state, this value is not expected to be returned.
-         */
-        int UNKNOWN = 0;
-        /**
-         * The handshake is in progress.
-         */
-        int IN_PROGRESS = 1;
-        /**
-         * The handshake is complete, but verification of the code is needed.
-         */
-        int VERIFICATION_NEEDED = 2;
-        /**
-         * The handshake is complete.
-         */
-        int FINISHED = 3;
-        /**
-         * The handshake is complete and not successful.
-         */
-        int INVALID = 4;
-        /**
-         * The handshake is complete, but extra verification is needed.
-         */
-        int RESUMING_SESSION = 5;
-    }
-
-    @HandshakeState
-    private final int mHandshakeState;
-    private final Key mKey;
-    private final byte[] mNextMessage;
-    private final String mVerificationCode;
-
-    /**
-     * @return Returns a builder for {@link HandshakeMessage}.
-     */
-    public static Builder newBuilder() {
-        return new Builder();
-    }
-
-    /**
-     * Use the builder;
-     */
-    private HandshakeMessage(
-            @HandshakeState int handshakeState,
-            @Nullable Key key,
-            @Nullable byte[] nextMessage,
-            @Nullable String verificationCode) {
-        mHandshakeState = handshakeState;
-        mKey = key;
-        mNextMessage = nextMessage;
-        mVerificationCode = verificationCode;
-    }
-
-    /**
-     * Returns the next message to send in a handshake.
-     */
-    @Nullable
-    public byte[] getNextMessage() {
-        return mNextMessage == null ? null : mNextMessage.clone();
-    }
-
-    /**
-     * Returns the state of the handshake.
-     */
-    @HandshakeState
-    public int getHandshakeState() {
-        return mHandshakeState;
-    }
-
-    /**
-     * Returns the encryption key that can be used to encrypt data.
-     */
-    @Nullable
-    public Key getKey() {
-        return mKey;
-    }
-
-    /**
-     * Returns a verification code to show to the user.
-     */
-    @Nullable
-    public String getVerificationCode() {
-        return mVerificationCode;
-    }
-
-    static class Builder {
-        @HandshakeState
-        int mHandshakeState;
-        Key mKey;
-        byte[] mNextMessage;
-        String mVerificationCode;
-
-        Builder setHandshakeState(@HandshakeState int handshakeState) {
-            mHandshakeState = handshakeState;
-            return this;
-        }
-
-        Builder setKey(@Nullable Key key) {
-            mKey = key;
-            return this;
-        }
-
-        Builder setNextMessage(@Nullable byte[] nextMessage) {
-            mNextMessage = nextMessage == null ? null : nextMessage.clone();
-            return this;
-        }
-
-        Builder setVerificationCode(@Nullable String verificationCode) {
-            mVerificationCode = verificationCode;
-            return this;
-        }
-
-        HandshakeMessage build() {
-            if (mHandshakeState == HandshakeState.UNKNOWN) {
-                throw new IllegalStateException("must set handshake state before calling build");
-            }
-            if (mHandshakeState == HandshakeState.VERIFICATION_NEEDED
-                    && TextUtils.isEmpty(mVerificationCode)) {
-                throw new IllegalStateException(
-                        "if state is verification needed, must have verification code");
-            }
-            return new HandshakeMessage(mHandshakeState, mKey, mNextMessage, mVerificationCode);
-        }
-
-    }
-}
diff --git a/EncryptionRunner/src/android/car/encryptionrunner/Key.java b/EncryptionRunner/src/android/car/encryptionrunner/Key.java
deleted file mode 100644
index 2e32858..0000000
--- a/EncryptionRunner/src/android/car/encryptionrunner/Key.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.car.encryptionrunner;
-
-import android.annotation.NonNull;
-
-import java.security.NoSuchAlgorithmException;
-import java.security.SignatureException;
-
-/**
- * Represents a serializable encryption key.
- */
-public interface Key {
-    /**
-     * Returns a serialized encryption key.
-     */
-    @NonNull
-    byte[] asBytes();
-
-    /**
-     * Encrypts data using this key.
-     *
-     * @param data the data to be encrypted
-     * @return the encrypted data.
-     */
-    @NonNull
-    byte[] encryptData(@NonNull byte[] data);
-
-    /**
-     * Decrypts data using this key.
-     *
-     * @param encryptedData The encrypted data.
-     * @return decrypted data.
-     * @throws SignatureException if encrypted data is not properly signed.
-     */
-    @NonNull
-    byte[] decryptData(@NonNull byte[] encryptedData) throws SignatureException;
-
-    /**
-     * Returns a cryptographic digest of the key.
-     *
-     * @throws NoSuchAlgorithmException when a unique session can not be created.
-     */
-    @NonNull
-    byte[] getUniqueSession() throws NoSuchAlgorithmException;
-}
diff --git a/EncryptionRunner/src/android/car/encryptionrunner/Ukey2EncryptionRunner.java b/EncryptionRunner/src/android/car/encryptionrunner/Ukey2EncryptionRunner.java
deleted file mode 100644
index 904d5c2..0000000
--- a/EncryptionRunner/src/android/car/encryptionrunner/Ukey2EncryptionRunner.java
+++ /dev/null
@@ -1,397 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.car.encryptionrunner;
-
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.util.Log;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-import com.google.security.cryptauth.lib.securegcm.D2DConnectionContext;
-import com.google.security.cryptauth.lib.securegcm.Ukey2Handshake;
-import com.google.security.cryptauth.lib.securemessage.CryptoOps;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.security.InvalidKeyException;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.security.SignatureException;
-
-import javax.crypto.spec.SecretKeySpec;
-
-/**
- * An {@link EncryptionRunner} that uses Ukey2 as the underlying implementation.
- */
-public class Ukey2EncryptionRunner implements EncryptionRunner {
-
-    private static final Ukey2Handshake.HandshakeCipher CIPHER =
-            Ukey2Handshake.HandshakeCipher.P256_SHA512;
-    private static final int RESUME_HMAC_LENGTH = 32;
-    private static final byte[] RESUME = "RESUME".getBytes();
-    private static final byte[] SERVER = "SERVER".getBytes();
-    private static final byte[] CLIENT = "CLIENT".getBytes();
-    private static final int AUTH_STRING_LENGTH = 6;
-
-    @IntDef({Mode.UNKNOWN, Mode.CLIENT, Mode.SERVER})
-    private @interface Mode {
-        int UNKNOWN = 0;
-        int CLIENT = 1;
-        int SERVER = 2;
-    }
-
-    private Ukey2Handshake mUkey2client;
-    private boolean mRunnerIsInvalid;
-    private Key mCurrentKey;
-    private byte[] mCurrentUniqueSesion;
-    private byte[] mPrevUniqueSesion;
-    private boolean mIsReconnect;
-    private boolean mInitReconnectionVerification;
-    @Mode
-    private int mMode = Mode.UNKNOWN;
-
-    @Override
-    public HandshakeMessage initHandshake() {
-        checkRunnerIsNew();
-        mMode = Mode.CLIENT;
-        try {
-            mUkey2client = Ukey2Handshake.forInitiator(CIPHER);
-            return HandshakeMessage.newBuilder()
-                    .setHandshakeState(getHandshakeState())
-                    .setNextMessage(mUkey2client.getNextHandshakeMessage())
-                    .build();
-        } catch (com.google.security.cryptauth.lib.securegcm.HandshakeException e) {
-            Log.e(TAG, "unexpected exception", e);
-            throw new RuntimeException(e);
-        }
-
-    }
-
-    @Override
-    public void setIsReconnect(boolean isReconnect) {
-        mIsReconnect = isReconnect;
-    }
-
-    @Override
-    public HandshakeMessage respondToInitRequest(byte[] initializationRequest)
-            throws HandshakeException {
-        checkRunnerIsNew();
-        mMode = Mode.SERVER;
-        try {
-            if (mUkey2client != null) {
-                throw new IllegalStateException("Cannot reuse encryption runners, "
-                        + "this one is already initialized");
-            }
-            mUkey2client = Ukey2Handshake.forResponder(CIPHER);
-            mUkey2client.parseHandshakeMessage(initializationRequest);
-            return HandshakeMessage.newBuilder()
-                    .setHandshakeState(getHandshakeState())
-                    .setNextMessage(mUkey2client.getNextHandshakeMessage())
-                    .build();
-
-        } catch (com.google.security.cryptauth.lib.securegcm.HandshakeException
-                | Ukey2Handshake.AlertException e) {
-            throw new HandshakeException(e);
-        }
-    }
-
-    private void checkRunnerIsNew() {
-        if (mUkey2client != null) {
-            throw new IllegalStateException("This runner is already initialized.");
-        }
-    }
-
-
-    @Override
-    public HandshakeMessage continueHandshake(byte[] response) throws HandshakeException {
-        checkInitialized();
-        try {
-            if (mUkey2client.getHandshakeState() != Ukey2Handshake.State.IN_PROGRESS) {
-                throw new IllegalStateException("handshake is not in progress, state ="
-                        + mUkey2client.getHandshakeState());
-            }
-            mUkey2client.parseHandshakeMessage(response);
-
-            // Not obvious from ukey2 api, but getting the next message can change the state.
-            // calling getNext message might go from in progress to verification needed, on
-            // the assumption that we already send this message to the peer.
-            byte[] nextMessage = null;
-            if (mUkey2client.getHandshakeState() == Ukey2Handshake.State.IN_PROGRESS) {
-                nextMessage = mUkey2client.getNextHandshakeMessage();
-            }
-            String verificationCode = null;
-            if (mUkey2client.getHandshakeState() == Ukey2Handshake.State.VERIFICATION_NEEDED) {
-                // getVerificationString() needs to be called before verifyPin().
-                verificationCode = generateReadablePairingCode(
-                        mUkey2client.getVerificationString(AUTH_STRING_LENGTH));
-                if (mIsReconnect) {
-                    HandshakeMessage handshakeMessage = verifyPin();
-                    return HandshakeMessage.newBuilder()
-                            .setHandshakeState(handshakeMessage.getHandshakeState())
-                            .setNextMessage(nextMessage)
-                            .build();
-                }
-            }
-            return HandshakeMessage.newBuilder()
-                    .setHandshakeState(getHandshakeState())
-                    .setNextMessage(nextMessage)
-                    .setVerificationCode(verificationCode)
-                    .build();
-        } catch (com.google.security.cryptauth.lib.securegcm.HandshakeException
-                | Ukey2Handshake.AlertException e) {
-            throw new HandshakeException(e);
-        }
-    }
-
-    /**
-     * Returns a human-readable pairing code string generated from the verification bytes. Converts
-     * each byte into a digit with a simple modulo.
-     *
-     * <p>This should match the implementation in the iOS and Android client libraries.
-     */
-    @VisibleForTesting
-    String generateReadablePairingCode(byte[] verificationCode) {
-        StringBuilder outString = new StringBuilder();
-        for (byte b : verificationCode) {
-            int unsignedInt = Byte.toUnsignedInt(b);
-            int digit = unsignedInt % 10;
-            outString.append(digit);
-        }
-
-        return outString.toString();
-    }
-
-    private static class UKey2Key implements Key {
-
-        private final D2DConnectionContext mConnectionContext;
-
-        UKey2Key(@NonNull D2DConnectionContext connectionContext) {
-            this.mConnectionContext = connectionContext;
-        }
-
-        @Override
-        public byte[] asBytes() {
-            return mConnectionContext.saveSession();
-        }
-
-        @Override
-        public byte[] encryptData(byte[] data) {
-            return mConnectionContext.encodeMessageToPeer(data);
-        }
-
-        @Override
-        public byte[] decryptData(byte[] encryptedData) throws SignatureException {
-            return mConnectionContext.decodeMessageFromPeer(encryptedData);
-        }
-
-        @Override
-        public byte[] getUniqueSession() throws NoSuchAlgorithmException {
-            return mConnectionContext.getSessionUnique();
-        }
-    }
-
-    @Override
-    public HandshakeMessage verifyPin() throws HandshakeException {
-        checkInitialized();
-        mUkey2client.verifyHandshake();
-        int state = getHandshakeState();
-        try {
-            mCurrentKey = new UKey2Key(mUkey2client.toConnectionContext());
-        } catch (com.google.security.cryptauth.lib.securegcm.HandshakeException e) {
-            throw new HandshakeException(e);
-        }
-        return HandshakeMessage.newBuilder()
-                .setHandshakeState(state)
-                .setKey(mCurrentKey)
-                .build();
-    }
-
-    /**
-     * <p>After getting message from the other device, authenticate the message with the previous
-     * stored key.
-     *
-     * If current device inits the reconnection authentication by calling {@code
-     * initReconnectAuthentication} and sends the message to the other device, the other device
-     * will call {@code authenticateReconnection()} with the received message and send its own
-     * message back to the init device. The init device will call {@code
-     * authenticateReconnection()} on the received message, but do not need to set the next
-     * message.
-     */
-    @Override
-    public HandshakeMessage authenticateReconnection(byte[] message, byte[] previousKey)
-            throws HandshakeException {
-        if (!mIsReconnect) {
-            throw new HandshakeException(
-                    "Reconnection authentication requires setIsReconnect(true)");
-        }
-        if (mCurrentKey == null) {
-            throw new HandshakeException("Current key is null, make sure verifyPin() is called.");
-        }
-        if (message.length != RESUME_HMAC_LENGTH) {
-            mRunnerIsInvalid = true;
-            throw new HandshakeException("Failing because (message.length =" + message.length
-                    + ") is not equal to " + RESUME_HMAC_LENGTH);
-        }
-        try {
-            mCurrentUniqueSesion = mCurrentKey.getUniqueSession();
-            mPrevUniqueSesion = keyOf(previousKey).getUniqueSession();
-        } catch (NoSuchAlgorithmException e) {
-            throw new HandshakeException(e);
-        }
-        switch (mMode) {
-            case Mode.SERVER:
-                if (!MessageDigest.isEqual(
-                        message, computeMAC(mPrevUniqueSesion, mCurrentUniqueSesion, CLIENT))) {
-                    mRunnerIsInvalid = true;
-                    throw new HandshakeException("Reconnection authentication failed.");
-                }
-                return HandshakeMessage.newBuilder()
-                        .setHandshakeState(HandshakeMessage.HandshakeState.FINISHED)
-                        .setKey(mCurrentKey)
-                        .setNextMessage(mInitReconnectionVerification ? null
-                                : computeMAC(mPrevUniqueSesion, mCurrentUniqueSesion, SERVER))
-                        .build();
-            case Mode.CLIENT:
-                if (!MessageDigest.isEqual(
-                        message, computeMAC(mPrevUniqueSesion, mCurrentUniqueSesion, SERVER))) {
-                    mRunnerIsInvalid = true;
-                    throw new HandshakeException("Reconnection authentication failed.");
-                }
-                return HandshakeMessage.newBuilder()
-                        .setHandshakeState(HandshakeMessage.HandshakeState.FINISHED)
-                        .setKey(mCurrentKey)
-                        .setNextMessage(mInitReconnectionVerification ? null
-                                : computeMAC(mPrevUniqueSesion, mCurrentUniqueSesion, CLIENT))
-                        .build();
-            default:
-                throw new IllegalStateException(
-                        "Encountered unexpected role during authenticateReconnection: " + mMode);
-        }
-    }
-
-    /**
-     * Both client and server can call this method to send authentication message to the other
-     * device.
-     */
-    @Override
-    public HandshakeMessage initReconnectAuthentication(byte[] previousKey)
-            throws HandshakeException {
-        if (!mIsReconnect) {
-            throw new HandshakeException(
-                    "Reconnection authentication requires setIsReconnect(true).");
-        }
-        if (mCurrentKey == null) {
-            throw new HandshakeException("Current key is null, make sure verifyPin() is called.");
-        }
-        mInitReconnectionVerification = true;
-        try {
-            mCurrentUniqueSesion = mCurrentKey.getUniqueSession();
-            mPrevUniqueSesion = keyOf(previousKey).getUniqueSession();
-        } catch (NoSuchAlgorithmException e) {
-            throw new HandshakeException(e);
-        }
-        switch (mMode) {
-            case Mode.SERVER:
-                return HandshakeMessage.newBuilder()
-                        .setHandshakeState(HandshakeMessage.HandshakeState.RESUMING_SESSION)
-                        .setNextMessage(computeMAC(mPrevUniqueSesion, mCurrentUniqueSesion, SERVER))
-                        .build();
-            case Mode.CLIENT:
-                return HandshakeMessage.newBuilder()
-                        .setHandshakeState(HandshakeMessage.HandshakeState.RESUMING_SESSION)
-                        .setNextMessage(computeMAC(mPrevUniqueSesion, mCurrentUniqueSesion, CLIENT))
-                        .build();
-            default:
-                throw new IllegalStateException(
-                        "Encountered unexpected role during authenticateReconnection: " + mMode);
-        }
-    }
-
-    @HandshakeMessage.HandshakeState
-    private int getHandshakeState() {
-        checkInitialized();
-        switch (mUkey2client.getHandshakeState()) {
-            case ALREADY_USED:
-            case ERROR:
-                throw new IllegalStateException("unexpected error state");
-            case FINISHED:
-                if (mIsReconnect) {
-                    return HandshakeMessage.HandshakeState.RESUMING_SESSION;
-                }
-                return HandshakeMessage.HandshakeState.FINISHED;
-            case IN_PROGRESS:
-                return HandshakeMessage.HandshakeState.IN_PROGRESS;
-            case VERIFICATION_IN_PROGRESS:
-            case VERIFICATION_NEEDED:
-                return HandshakeMessage.HandshakeState.VERIFICATION_NEEDED;
-            default:
-                throw new IllegalStateException("unexpected handshake state");
-        }
-    }
-
-    @Override
-    public Key keyOf(byte[] serialized) {
-        return new UKey2Key(D2DConnectionContext.fromSavedSession(serialized));
-    }
-
-    @Override
-    public void invalidPin() {
-        mRunnerIsInvalid = true;
-    }
-
-    private UKey2Key checkIsUkey2Key(Key key) {
-        if (!(key instanceof UKey2Key)) {
-            throw new IllegalArgumentException("wrong key type");
-        }
-        return (UKey2Key) key;
-    }
-
-    private void checkInitialized() {
-        if (mUkey2client == null) {
-            throw new IllegalStateException("runner not initialized");
-        }
-        if (mRunnerIsInvalid) {
-            throw new IllegalStateException("runner has been invalidated");
-        }
-    }
-
-    @Nullable
-    private byte[] computeMAC(byte[] previous, byte[] next, byte[] info) {
-        try {
-            SecretKeySpec inputKeyMaterial = new SecretKeySpec(
-                    concatByteArrays(previous, next), "" /* key type is just plain raw bytes */);
-            return CryptoOps.hkdf(inputKeyMaterial, RESUME, info);
-        } catch (NoSuchAlgorithmException | InvalidKeyException e) {
-            // Does not happen in practice
-            Log.e(TAG, "Compute MAC failed");
-            return null;
-        }
-    }
-
-    private static byte[] concatByteArrays(@NonNull byte[] a, @NonNull byte[] b) {
-        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
-        try {
-            outputStream.write(a);
-            outputStream.write(b);
-        } catch (IOException e) {
-            return new byte[0];
-        }
-        return outputStream.toByteArray();
-    }
-}
diff --git a/OWNERS b/OWNERS
index c1e7ec6..15d29ad 100644
--- a/OWNERS
+++ b/OWNERS
@@ -6,6 +6,7 @@
 [email protected]
 [email protected]
 [email protected]
[email protected]
 
 # TLMs
 [email protected]
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index a810f8e..e438129 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -3,6 +3,8 @@
 ktlint_hook = ${REPO_ROOT}/prebuilts/ktlint/ktlint.py -f ${PREUPLOAD_FILES}
 chassis_current_hook = car-ui-lib/tests/apitest/auto-generate-resources.py --sha ${PREUPLOAD_COMMIT} --compare
 chassis_findviewbyid_check = car-ui-lib/findviewbyid-preupload-hook.sh
+chassis_trailing_blank_line_check = car-ui-lib/trailing-blank-line-hook.sh
+
 [Builtin Hooks]
 commit_msg_changeid_field = true
 commit_msg_test_field = true
diff --git a/android-car-lib/Android.mk b/android-car-lib/Android.mk
deleted file mode 100644
index a7cd0b3..0000000
--- a/android-car-lib/Android.mk
+++ /dev/null
@@ -1,25 +0,0 @@
-# Copyright (C) 2015 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-#
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_AAPT2_ONLY := true
-
-LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := \
-        android-car:android-car.aar
-
-include $(BUILD_MULTI_PREBUILT)
diff --git a/android-car-lib/android-car-lib.mk b/android-car-lib/android-car-lib.mk
deleted file mode 100644
index 419daab..0000000
--- a/android-car-lib/android-car-lib.mk
+++ /dev/null
@@ -1,53 +0,0 @@
-#
-# Include this make file to build your application with car ui.
-# This only applied to app which is not CarActivity based but wants to use car-ui.
-#
-# Make sure to include it after you've set all your desired LOCAL variables.
-# Note that you must explicitly set your LOCAL_RESOURCE_DIR before including this file.
-#
-# For example:
-#
-#   LOCAL_RESOURCE_DIR := \
-#        $(LOCAL_PATH)/res
-#
-#   In your .mk file, include the items in the following order, to ensure the prebuilt
-#   static libraries are included in the correct order.
-#
-#   include vendor/auto/embedded/prebuilts/android-car-lib/car-lib.mk
-#   include $(BUILD_PACKAGE)
-#   include vendor/auto/embedded/prebuilts/android-car-lib/Android.mk
-
-# Check that LOCAL_RESOURCE_DIR is defined
-ifeq (,$(LOCAL_RESOURCE_DIR))
-$(error LOCAL_RESOURCE_DIR must be defined)
-endif
-
-LOCAL_STATIC_JAVA_AAR_LIBRARIES += android-car
-
-# Work around limitations of AAR prebuilts
-LOCAL_RESOURCE_DIR += packages/apps/Car/libs/android-car-lib/res
-
-# Include support-v7-appcompat, if not already included
-ifeq (,$(findstring android-support-v7-appcompat,$(LOCAL_STATIC_JAVA_LIBRARIES)))
-LOCAL_STATIC_ANDROID_LIBRARIES += android-support-v7-appcompat
-endif
-
-# Include support-v7-recyclerview, if not already included
-ifeq (,$(findstring android-support-v7-recyclerview,$(LOCAL_STATIC_JAVA_LIBRARIES)))
-LOCAL_STATIC_ANDROID_LIBRARIES += android-support-v7-recyclerview
-endif
-
-# Include support-v7-cardview, if not already included
-ifeq (,$(findstring android-support-v7-cardview,$(LOCAL_STATIC_JAVA_LIBRARIES)))
-LOCAL_STATIC_ANDROID_LIBRARIES += android-support-v7-cardview
-endif
-
-# Include support-design, if not already included
-ifeq (,$(findstring android-support-design,$(LOCAL_STATIC_JAVA_LIBRARIES)))
-LOCAL_STATIC_ANDROID_LIBRARIES += android-support-design
-endif
-
-# Include support-v4, if not already included
-ifeq (,$(findstring android-support-v4,$(LOCAL_STATIC_JAVA_LIBRARIES)))
-LOCAL_STATIC_ANDROID_LIBRARIES += android-support-v4
-endif
diff --git a/android-car-lib/android-car.aar b/android-car-lib/android-car.aar
deleted file mode 100644
index ff03a9c..0000000
--- a/android-car-lib/android-car.aar
+++ /dev/null
Binary files differ
diff --git a/android-car-lib/car-release.aar b/android-car-lib/car-release.aar
deleted file mode 100644
index ff03a9c..0000000
--- a/android-car-lib/car-release.aar
+++ /dev/null
Binary files differ
diff --git a/android-car-lib/res/anim/fade_in_trans_left.xml b/android-car-lib/res/anim/fade_in_trans_left.xml
deleted file mode 100644
index 2d6bab5..0000000
--- a/android-car-lib/res/anim/fade_in_trans_left.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<set xmlns:android="http://schemas.android.com/apk/res/android"
-     android:duration="@android:integer/config_shortAnimTime">
-    <translate
-        android:interpolator="@android:interpolator/decelerate_quint"
-        android:fromXDelta="-10%p"
-        android:toXDelta="0" />
-
-    <alpha
-        android:fromAlpha="0.2"
-        android:toAlpha="1"
-        android:interpolator="@android:interpolator/decelerate_quint" />
-</set>
diff --git a/android-car-lib/res/anim/fade_in_trans_left_layout_anim.xml b/android-car-lib/res/anim/fade_in_trans_left_layout_anim.xml
deleted file mode 100644
index e7660db..0000000
--- a/android-car-lib/res/anim/fade_in_trans_left_layout_anim.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<layoutAnimation
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:animation="@anim/fade_in_trans_left"
-    android:delay="0%"
-    android:animationOrder="normal" />
diff --git a/android-car-lib/res/anim/fade_in_trans_right.xml b/android-car-lib/res/anim/fade_in_trans_right.xml
deleted file mode 100644
index 5cbeb59..0000000
--- a/android-car-lib/res/anim/fade_in_trans_right.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<set xmlns:android="http://schemas.android.com/apk/res/android"
-     android:duration="@android:integer/config_shortAnimTime">
-    <translate
-        android:interpolator="@android:interpolator/decelerate_quint"
-        android:fromXDelta="10%p"
-        android:toXDelta="0" />
-
-    <alpha
-        android:fromAlpha="0.2"
-        android:toAlpha="1"
-        android:interpolator="@android:interpolator/decelerate_quint" />
-</set>
diff --git a/android-car-lib/res/anim/fade_in_trans_right_layout_anim.xml b/android-car-lib/res/anim/fade_in_trans_right_layout_anim.xml
deleted file mode 100644
index b76de23..0000000
--- a/android-car-lib/res/anim/fade_in_trans_right_layout_anim.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<layoutAnimation
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:animation="@anim/fade_in_trans_right"
-    android:delay="0%"
-    android:animationOrder="normal" />
diff --git a/android-car-lib/res/anim/lock_out_message_bar.xml b/android-car-lib/res/anim/lock_out_message_bar.xml
deleted file mode 100644
index e70a4ef..0000000
--- a/android-car-lib/res/anim/lock_out_message_bar.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2018 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<set
-    xmlns:android="http://schemas.android.com/apk/res/android" >
-    <objectAnimator
-        android:duration="@integer/speed_bump_lock_out_duration_ms"
-        android:propertyName="pathData"
-        android:valueFrom="M 96.5,48.5 c 0.0,26.5096740723 -21.4903259277,48.0 -48.0,48.0 c 0.0,0.0 -384.0,0.0 -384.0,0.0 c -26.5096740723,0.0 -48.0,-21.4903259277 -48.0,-48.0 c 0.0,-26.5096740723 21.4903259277,-48.0 48.0,-48.0 c 0.0,0.0 384.0,0.0 384.0,0.0 c 26.5096740723,0.0 48.0,21.4903411865 48.0,48.0 Z"
-        android:valueTo="M 480.5,48.5 c 0.0,26.5096740723 -21.4903259277,48.0 -48.0,48.0 c 0.0,0.0 -384.0,0.0 -384.0,0.0 c -26.5096740723,0.0 -48.0,-21.4903259277 -48.0,-48.0 c 0.0,-26.5096740723 21.4903259277,-48.0 48.0,-48.0 c 0.0,0.0 384.0,0.0 384.0,0.0 c 26.5096740723,0.0 48.0,21.4903259277 48.0,48.0 Z"
-        android:valueType="pathType"
-        android:interpolator="@interpolator/speed_bump_interpolator" />
-</set>
diff --git a/android-car-lib/res/anim/lock_out_message_bg_color_change.xml b/android-car-lib/res/anim/lock_out_message_bg_color_change.xml
deleted file mode 100644
index 6d56ff4..0000000
--- a/android-car-lib/res/anim/lock_out_message_bg_color_change.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2018 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<set
-    xmlns:android="http://schemas.android.com/apk/res/android" >
-    <objectAnimator
-        android:startOffset="@integer/speed_bump_lock_out_color_change_start_delay_ms"
-        android:duration="@integer/speed_bump_lock_out_color_change_ms"
-        android:propertyName="fillColor"
-        android:valueFrom="#FF029AE5"
-        android:valueTo="#FF26994B"
-        android:interpolator="@android:interpolator/linear" />
-</set>
diff --git a/android-car-lib/res/anim/lock_out_message_in.xml b/android-car-lib/res/anim/lock_out_message_in.xml
deleted file mode 100644
index aae3d17..0000000
--- a/android-car-lib/res/anim/lock_out_message_in.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2018 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<set xmlns:android="http://schemas.android.com/apk/res/android">
-    <alpha
-        android:fromAlpha="0"
-        android:toAlpha="1.0"
-        android:fillEnabled="true"
-        android:fillBefore="true"
-        android:fillAfter="true"
-        android:interpolator="@android:interpolator/accelerate_quint"
-        android:duration="@integer/speed_bump_fade_duration_ms"/>
-    <translate
-        android:fromYDelta="100%"
-        android:toYDelta="0%"
-        android:fillEnabled="true"
-        android:fillBefore="true"
-        android:fillAfter="true"
-        android:interpolator="@android:interpolator/linear_out_slow_in"
-        android:duration="@integer/speed_bump_translate_y_duration_ms"/>
-</set>
diff --git a/android-car-lib/res/anim/lock_out_message_out.xml b/android-car-lib/res/anim/lock_out_message_out.xml
deleted file mode 100644
index 3044d0a..0000000
--- a/android-car-lib/res/anim/lock_out_message_out.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<!-- Copyright (C) 2018 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<set xmlns:android="http://schemas.android.com/apk/res/android">
-    <alpha
-        android:fromAlpha="1.0"
-        android:toAlpha="0"
-        android:fillEnabled="true"
-        android:fillBefore="true"
-        android:fillAfter="true"
-        android:interpolator="@android:interpolator/accelerate_quint"
-        android:duration="@integer/speed_bump_fade_duration_ms"/>
-</set>
diff --git a/android-car-lib/res/drawable/car_action_button_activated_ring_foreground.xml b/android-car-lib/res/drawable/car_action_button_activated_ring_foreground.xml
deleted file mode 100644
index cf9570b..0000000
--- a/android-car-lib/res/drawable/car_action_button_activated_ring_foreground.xml
+++ /dev/null
@@ -1,48 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2018 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<selector
-    xmlns:android="http://schemas.android.com/apk/res/android">
-  <item
-      android:state_activated="true">
-    <shape
-        xmlns:android="http://schemas.android.com/apk/res/android"
-        android:shape="oval">
-      <stroke
-          android:color="@color/car_tint"
-          android:width="@dimen/car_action_bar_activation_ring_stroke_width">
-      </stroke>
-      <size
-          android:height="@dimen/car_action_bar_activation_ring_radius"
-          android:width="@dimen/car_action_bar_activation_ring_radius"/>
-    </shape>
-  </item>
-  <!--Yes, this is a load-bearing invisible circle.-->
-  <!--Android doesn't remeasure foregrounds when state_activated changes, -->
-  <!--so we need a default drawable with the same size as the one we actually want to draw-->
-  <item>
-    <shape
-        xmlns:android="http://schemas.android.com/apk/res/android"
-        android:shape="oval">
-      <stroke
-          android:color="#00000000"
-          android:width="@dimen/car_action_bar_activation_ring_stroke_width">
-      </stroke>
-      <size
-          android:height="@dimen/car_action_bar_activation_ring_radius"
-          android:width="@dimen/car_action_bar_activation_ring_radius"/>
-    </shape>
-  </item>
-</selector>
diff --git a/android-car-lib/res/drawable/car_action_button_background.xml b/android-car-lib/res/drawable/car_action_button_background.xml
deleted file mode 100644
index 27e97e3..0000000
--- a/android-car-lib/res/drawable/car_action_button_background.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2018 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<inset xmlns:android="http://schemas.android.com/apk/res/android"
-    android:inset="@dimen/car_action_button_ripple_inset" >
-    <ripple android:color="@color/car_card_ripple_background" />
-</inset>
diff --git a/android-car-lib/res/drawable/car_borderless_button_text_color.xml b/android-car-lib/res/drawable/car_borderless_button_text_color.xml
deleted file mode 100644
index 27f79f0..0000000
--- a/android-car-lib/res/drawable/car_borderless_button_text_color.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-    Copyright (C) 2017 The Android Open Source Project
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-      http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
--->
-<!-- Default text colors for car buttons when enabled/disabled. -->
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:color="@color/car_grey_700" android:state_enabled="false"/>
-    <item android:color="?android:attr/colorButtonNormal"/>
-</selector>
diff --git a/android-car-lib/res/drawable/car_button_background.xml b/android-car-lib/res/drawable/car_button_background.xml
deleted file mode 100644
index 58aa739..0000000
--- a/android-car-lib/res/drawable/car_button_background.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-    Copyright (C) 2017 The Android Open Source Project
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-      http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
--->
-<!-- Default background styles for car buttons when enabled/disabled. -->
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_enabled="false">
-        <shape android:shape="rectangle">
-            <corners android:radius="@dimen/car_button_radius"/>
-            <solid android:color="@color/car_grey_300"/>
-        </shape>
-    </item>
-    <item>
-        <shape android:shape="rectangle">
-            <corners android:radius="@dimen/car_button_radius"/>
-            <solid android:color="?android:attr/colorButtonNormal"/>
-        </shape>
-    </item>
-</selector>
diff --git a/android-car-lib/res/drawable/car_button_text_color.xml b/android-car-lib/res/drawable/car_button_text_color.xml
deleted file mode 100644
index bb8c681..0000000
--- a/android-car-lib/res/drawable/car_button_text_color.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-    Copyright (C) 2017 The Android Open Source Project
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-      http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
--->
-<!-- Default text colors for car buttons when enabled/disabled. -->
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:color="@color/car_grey_700" android:state_enabled="false"/>
-    <item android:color="@color/car_action1"/>
-</selector>
diff --git a/android-car-lib/res/drawable/car_card_background.xml b/android-car-lib/res/drawable/car_card_background.xml
deleted file mode 100644
index 7caa2ff..0000000
--- a/android-car-lib/res/drawable/car_card_background.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2017 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
-    <solid android:color="@color/car_card"/>
-</shape>
\ No newline at end of file
diff --git a/android-car-lib/res/drawable/car_card_ripple_background.xml b/android-car-lib/res/drawable/car_card_ripple_background.xml
deleted file mode 100644
index ca20e0f..0000000
--- a/android-car-lib/res/drawable/car_card_ripple_background.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2017 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-<ripple
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:color="@color/car_card_ripple_background">
-    <item
-        android:id="@android:id/mask"
-        android:drawable="@android:color/white" />
-</ripple>
diff --git a/android-car-lib/res/drawable/car_card_ripple_background_day.xml b/android-car-lib/res/drawable/car_card_ripple_background_day.xml
deleted file mode 100644
index 880ff7a..0000000
--- a/android-car-lib/res/drawable/car_card_ripple_background_day.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2017 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-<ripple
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:color="@color/car_card_ripple_background_dark">
-    <item
-        android:id="@android:id/mask"
-        android:drawable="@android:color/white" />
-</ripple>
diff --git a/android-car-lib/res/drawable/car_card_ripple_background_inverse.xml b/android-car-lib/res/drawable/car_card_ripple_background_inverse.xml
deleted file mode 100644
index e063e2c..0000000
--- a/android-car-lib/res/drawable/car_card_ripple_background_inverse.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2017 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-<ripple
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:color="@color/car_card_ripple_background_inverse" >
-    <item
-        android:id="@android:id/mask"
-        android:drawable="@android:color/white" />
-</ripple>
diff --git a/android-car-lib/res/drawable/car_card_ripple_background_night.xml b/android-car-lib/res/drawable/car_card_ripple_background_night.xml
deleted file mode 100644
index 5d4f2c6..0000000
--- a/android-car-lib/res/drawable/car_card_ripple_background_night.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2017 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-<ripple
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:color="@color/car_card_ripple_background_light">
-    <item
-        android:id="@android:id/mask"
-        android:drawable="@android:color/white" />
-</ripple>
diff --git a/android-car-lib/res/drawable/car_card_rounded_background.xml b/android-car-lib/res/drawable/car_card_rounded_background.xml
deleted file mode 100644
index 594705b..0000000
--- a/android-car-lib/res/drawable/car_card_rounded_background.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2017 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
-    <solid android:color="@color/car_card"/>
-    <corners
-        android:radius="@dimen/car_radius_3"/>
-</shape>
\ No newline at end of file
diff --git a/android-car-lib/res/drawable/car_card_rounded_bottom_background.xml b/android-car-lib/res/drawable/car_card_rounded_bottom_background.xml
deleted file mode 100644
index 35dba13..0000000
--- a/android-car-lib/res/drawable/car_card_rounded_bottom_background.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2017 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
-    <solid android:color="@color/car_card"/>
-    <corners
-        android:bottomRightRadius="@dimen/car_radius_3"
-        android:bottomLeftRadius="@dimen/car_radius_3"/>
-</shape>
\ No newline at end of file
diff --git a/android-car-lib/res/drawable/car_card_rounded_top_background.xml b/android-car-lib/res/drawable/car_card_rounded_top_background.xml
deleted file mode 100644
index dfb5622..0000000
--- a/android-car-lib/res/drawable/car_card_rounded_top_background.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2017 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
-    <solid android:color="@color/car_card"/>
-    <corners
-        android:topRightRadius="@dimen/car_radius_3"
-        android:topLeftRadius="@dimen/car_radius_3"/>
-</shape>
\ No newline at end of file
diff --git a/android-car-lib/res/drawable/car_drawer_list_item_background.xml b/android-car-lib/res/drawable/car_drawer_list_item_background.xml
deleted file mode 100644
index c5fc36b..0000000
--- a/android-car-lib/res/drawable/car_drawer_list_item_background.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2017 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-<ripple xmlns:android="http://schemas.android.com/apk/res/android"
-    android:color="@color/car_card_ripple_background">
-    <item android:id="@android:id/mask">
-        <color android:color="#ffffffff" />
-    </item>
-</ripple>
diff --git a/android-car-lib/res/drawable/car_list_divider.xml b/android-car-lib/res/drawable/car_list_divider.xml
deleted file mode 100644
index 14a5ce1..0000000
--- a/android-car-lib/res/drawable/car_list_divider.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<!-- Drawable of dividers used in lists -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
-    <size android:height="@dimen/car_list_divider_height"/>
-    <solid android:color="@color/car_list_divider"/>
-</shape>
\ No newline at end of file
diff --git a/android-car-lib/res/drawable/car_list_divider_dark.xml b/android-car-lib/res/drawable/car_list_divider_dark.xml
deleted file mode 100644
index 4760623..0000000
--- a/android-car-lib/res/drawable/car_list_divider_dark.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2018 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<!-- Drawable of dividers used in lists -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
-  <size android:height="@dimen/car_list_divider_height"/>
-  <solid android:color="@color/car_list_divider_dark"/>
-</shape>
diff --git a/android-car-lib/res/drawable/car_list_divider_light.xml b/android-car-lib/res/drawable/car_list_divider_light.xml
deleted file mode 100644
index 07b52dd..0000000
--- a/android-car-lib/res/drawable/car_list_divider_light.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2018 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<!-- Drawable of dividers used in lists -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
-  <size android:height="@dimen/car_list_divider_height"/>
-  <solid android:color="@color/car_list_divider_light"/>
-</shape>
diff --git a/android-car-lib/res/drawable/car_scrollbar_thumb.xml b/android-car-lib/res/drawable/car_scrollbar_thumb.xml
deleted file mode 100644
index 42aaebf..0000000
--- a/android-car-lib/res/drawable/car_scrollbar_thumb.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2018 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License
-  -->
-
-<shape
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:shape="rectangle">
-    <solid android:color="@color/car_scrollbar_thumb" />
-    <corners android:radius="@dimen/car_radius_5"/>
-</shape>
diff --git a/android-car-lib/res/drawable/car_seekbar_thumb.xml b/android-car-lib/res/drawable/car_seekbar_thumb.xml
deleted file mode 100644
index a5c4910..0000000
--- a/android-car-lib/res/drawable/car_seekbar_thumb.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2018 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License
-  -->
-
-<shape
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:shape="oval">
-    <solid android:color="@color/car_accent" />
-    <size
-        android:width="@dimen/car_seekbar_thumb_size"
-        android:height="@dimen/car_seekbar_thumb_size" />
-</shape>
\ No newline at end of file
diff --git a/android-car-lib/res/drawable/car_seekbar_track.xml b/android-car-lib/res/drawable/car_seekbar_track.xml
deleted file mode 100644
index 05700c2..0000000
--- a/android-car-lib/res/drawable/car_seekbar_track.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2018 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License
-  -->
-
-<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:id="@android:id/background">
-        <shape android:shape="line">
-            <stroke
-                android:width="@dimen/car_seekbar_height"
-                android:color="@color/car_seekbar_track_background" />
-        </shape>
-    </item>
-    <item android:id="@android:id/progress">
-        <clip>
-            <shape android:shape="line">
-                <stroke
-                    android:width="@dimen/car_seekbar_height"
-                    android:color="@color/car_accent" />
-            </shape>
-        </clip>
-    </item>
-</layer-list>
\ No newline at end of file
diff --git a/android-car-lib/res/drawable/ic_down.xml b/android-car-lib/res/drawable/ic_down.xml
deleted file mode 100644
index cd486c1..0000000
--- a/android-car-lib/res/drawable/ic_down.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2018 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="76dp"
-        android:height="76dp"
-        android:viewportWidth="76.0"
-        android:viewportHeight="76.0">
-    <path
-        android:pathData="M38,0.96C17.01,0.96 0,17.75 0,38.47C0,59.18 17.01,75.97 38,75.97C58.99,75.97 76,59.18 76,38.47C76,17.75 58.99,0.96 38,0.96M38,3.3C57.64,3.3 73.62,19.08 73.62,38.47C73.62,57.85 57.64,73.63 38,73.63C18.36,73.63 2.38,57.86 2.38,38.47C2.38,19.08 18.36,3.3 38,3.3"
-        android:strokeColor="#00000000"
-        android:fillColor="#212121"
-        android:strokeWidth="1"/>
-    <path
-        android:pathData="M26.63,31.09l11.37,11.08l11.37,-11.08l3.5,3.42l-14.87,14.5l-14.87,-14.5z"
-        android:strokeColor="#00000000"
-        android:fillColor="#212121"
-        android:strokeWidth="1"/>
-</vector>
diff --git a/android-car-lib/res/drawable/ic_list_view_disable.xml b/android-car-lib/res/drawable/ic_list_view_disable.xml
deleted file mode 100644
index 8649423..0000000
--- a/android-car-lib/res/drawable/ic_list_view_disable.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="176dp"
-        android:height="176dp"
-        android:viewportWidth="176.0"
-        android:viewportHeight="176.0">
-    <path
-        android:pathData="M88.99,55.55l15.71,15.71l46.13,0l0,-15.71z"
-        android:fillColor="#212121"/>
-    <path
-        android:pathData="M25.19,119.06h66.5v15.71h-66.5z"
-        android:fillColor="#212121"/>
-    <path
-        android:pathData="M114.58,103.35l-15.71,-15.71l-0.12,0l-16.38,-16.38l0.12,0l-15.71,-15.71l-0.12,0l-30.29,-30.29l-11.11,11.11l19.19,19.18l-19.28,0l0,15.71l34.98,0l16.39,16.38l-51.37,0l0,15.71l67.08,0l47.38,47.39l11.11,-11.11l-36.28,-36.28z"
-        android:fillColor="#212121"/>
-    <path
-        android:pathData="M136.79,103.35l14.04,0l0,-15.71l-29.74,0z"
-        android:fillColor="#212121"/>
-</vector>
diff --git a/android-car-lib/res/drawable/ic_overflow.xml b/android-car-lib/res/drawable/ic_overflow.xml
deleted file mode 100644
index eda306c..0000000
--- a/android-car-lib/res/drawable/ic_overflow.xml
+++ /dev/null
@@ -1,45 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2018 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="56dp"
-    android:height="56dp"
-    android:viewportWidth="24"
-    android:viewportHeight="24">
-
-    <group
-            android:translateX="-0.750000"
-            android:translateY="-0.750000">
-        <path
-            android:strokeWidth="1"
-            android:pathData="M 0.75 24.75 L 24.75 24.75 L 24.75 0.75 L 0.75 0.75 Z" />
-        <path
-            android:fillColor="#000000"
-            android:strokeWidth="1"
-            android:pathData="M12.75,10.1666667 C13.4604167,10.1666667 14.0416667,9.58541667 14.0416667,8.875
-C14.0416667,8.16458333 13.4604167,7.58333333 12.75,7.58333333
-C12.0395833,7.58333333 11.4583333,8.16458333 11.4583333,8.875
-C11.4583333,9.58541667 12.0395833,10.1666667 12.75,10.1666667 L12.75,10.1666667
-Z M12.75,11.4583333 C12.0395833,11.4583333 11.4583333,12.0395833
-11.4583333,12.75 C11.4583333,13.4604167 12.0395833,14.0416667 12.75,14.0416667
-C13.4604167,14.0416667 14.0416667,13.4604167 14.0416667,12.75
-C14.0416667,12.0395833 13.4604167,11.4583333 12.75,11.4583333 L12.75,11.4583333
-Z M12.75,15.3333333 C12.0395833,15.3333333 11.4583333,15.9145833
-11.4583333,16.625 C11.4583333,17.3354167 12.0395833,17.9166667 12.75,17.9166667
-C13.4604167,17.9166667 14.0416667,17.3354167 14.0416667,16.625
-C14.0416667,15.9145833 13.4604167,15.3333333 12.75,15.3333333 L12.75,15.3333333
-Z" />
-    </group>
-</vector>
diff --git a/android-car-lib/res/drawable/ic_up.xml b/android-car-lib/res/drawable/ic_up.xml
deleted file mode 100644
index ec18410..0000000
--- a/android-car-lib/res/drawable/ic_up.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2018 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="76dp"
-        android:height="76dp"
-        android:viewportWidth="76.0"
-        android:viewportHeight="76.0">
-    <path
-        android:pathData="M38,75.04C58.99,75.04 76,58.27 76,37.57C76,16.88 58.99,0.11 38,0.11C17.01,0.11 0,16.88 0,37.57C0,58.27 17.01,75.04 38,75.04M38,72.7C18.36,72.7 2.38,56.94 2.38,37.57C2.38,18.21 18.36,2.45 38,2.45C57.64,2.45 73.62,18.21 73.62,37.57C73.62,56.94 57.64,72.7 38,72.7"
-        android:strokeColor="#00000000"
-        android:fillColor="#212121"
-        android:strokeWidth="1"/>
-    <path
-        android:pathData="M49.37,44.9l-11.37,-11.08l-11.37,11.08l-3.5,-3.42l14.87,-14.5l14.87,14.5z"
-        android:strokeColor="#00000000"
-        android:fillColor="#212121"
-        android:strokeWidth="1"/>
-</vector>
diff --git a/android-car-lib/res/drawable/lock_out_message_animation.xml b/android-car-lib/res/drawable/lock_out_message_animation.xml
deleted file mode 100644
index 42cea41..0000000
--- a/android-car-lib/res/drawable/lock_out_message_animation.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2018 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<animated-vector
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:drawable="@drawable/lock_out_message_background" >
-    <target
-        android:name="bar_mask"
-        android:animation="@anim/lock_out_message_bar" />
-    <target
-        android:name="bar_path"
-        android:animation="@anim/lock_out_message_bg_color_change" />
-</animated-vector>
diff --git a/android-car-lib/res/drawable/lock_out_message_background.xml b/android-car-lib/res/drawable/lock_out_message_background.xml
deleted file mode 100644
index 26b559b..0000000
--- a/android-car-lib/res/drawable/lock_out_message_background.xml
+++ /dev/null
@@ -1,62 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2018 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<vector
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="480dp"
-    android:viewportWidth="480"
-    android:height="96dp"
-    android:viewportHeight="96" >
-    <group
-        android:name="base"
-        android:translateX="240"
-        android:translateY="48"
-        android:scaleX="0.994"
-        android:scaleY="0.994" >
-        <group
-            android:name="base_pivot"
-            android:translateX="-240"
-            android:translateY="-47" >
-            <group
-                android:name="base"
-                android:scaleY="0.99" >
-                <path
-                    android:name="base_path"
-                    android:pathData="M 480.0,48.0 c 0.0,26.5096740723 -21.4903259277,48.0 -48.0,48.0 c 0.0,0.0 -384.0,0.0 -384.0,0.0 c -26.5096740723,0.0 -48.0,-21.4903259277 -48.0,-48.0 c 0.0,-26.5096740723 21.4903259277,-48.0 48.0,-48.0 c 0.0,0.0 384.0,0.0 384.0,0.0 c 26.5096740723,0.0 48.0,21.4903259277 48.0,48.0 Z"
-                    android:fillColor="@color/speed_bump_background" />
-            </group>
-        </group>
-    </group>
-    <group
-        android:name="bar"
-        android:translateX="240"
-        android:translateY="48" >
-        <group
-            android:name="bar_pivot"
-            android:translateX="-240"
-            android:translateY="-48" >
-            <clip-path
-                android:name="bar_mask"
-                android:pathData="M 96.5,48.5 c 0.0,26.5096740723 -21.4903259277,48.0 -48.0,48.0 c 0.0,0.0 -384.0,0.0 -384.0,0.0 c -26.5096740723,0.0 -48.0,-21.4903259277 -48.0,-48.0 c 0.0,-26.5096740723 21.4903259277,-48.0 48.0,-48.0 c 0.0,0.0 384.0,0.0 384.0,0.0 c 26.5096740723,0.0 48.0,21.4903411865 48.0,48.0 Z" />
-            <group
-                android:name="base" >
-                <path
-                    android:name="bar_path"
-                    android:pathData="M 480.0,48.0 c 0.0,26.5096740723 -21.4903259277,48.0 -48.0,48.0 c 0.0,0.0 -384.0,0.0 -384.0,0.0 c -26.5096740723,0.0 -48.0,-21.4903259277 -48.0,-48.0 c 0.0,-26.5096740723 21.4903259277,-48.0 48.0,-48.0 c 0.0,0.0 384.0,0.0 384.0,0.0 c 26.5096740723,0.0 48.0,21.4903259277 48.0,48.0 Z"
-                    android:fillColor="#FF029AE5" />
-            </group>
-        </group>
-    </group>
-</vector>
diff --git a/android-car-lib/res/drawable/speed_bump_scrim.xml b/android-car-lib/res/drawable/speed_bump_scrim.xml
deleted file mode 100644
index aacea49..0000000
--- a/android-car-lib/res/drawable/speed_bump_scrim.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2018 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
-       android:shape="rectangle" >
-    <gradient
-        android:type="linear"
-        android:startColor="@android:color/transparent"
-        android:endColor="#8d000000"
-        android:angle="270"/>
-</shape>
diff --git a/android-car-lib/res/interpolator/speed_bump_interpolator.xml b/android-car-lib/res/interpolator/speed_bump_interpolator.xml
deleted file mode 100644
index ec7e694..0000000
--- a/android-car-lib/res/interpolator/speed_bump_interpolator.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2018 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<pathInterpolator
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:pathData="M 0.0,0.0 c 1.0,0.535553908162 0.961348094524,0.999999995867 1.0,1.0" />
diff --git a/android-car-lib/res/layout/action_bar.xml b/android-car-lib/res/layout/action_bar.xml
deleted file mode 100644
index 431a2a8..0000000
--- a/android-car-lib/res/layout/action_bar.xml
+++ /dev/null
@@ -1,49 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2018 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<androidx.cardview.widget.CardView
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    android:id="@+id/action_bar_wrapper"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:elevation="@dimen/car_action_bar_elevation"
-    app:cardCornerRadius="@dimen/car_radius_3">
-
-    <LinearLayout
-        android:id="@+id/rows_container"
-        android:orientation="vertical"
-        android:animateLayoutChanges="true"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content">
-
-        <LinearLayout
-            android:orientation="horizontal"
-            android:visibility="gone"
-            android:clipChildren="false"
-            android:layout_width="match_parent"
-            android:layout_height="@dimen/car_action_bar_height">
-        </LinearLayout>
-
-        <LinearLayout
-            android:orientation="horizontal"
-            android:clipChildren="false"
-            android:layout_width="match_parent"
-            android:layout_height="@dimen/car_action_bar_height">
-        </LinearLayout>
-
-    </LinearLayout>
-
-</androidx.cardview.widget.CardView>
\ No newline at end of file
diff --git a/android-car-lib/res/layout/action_bar_button.xml b/android-car-lib/res/layout/action_bar_button.xml
deleted file mode 100644
index e9d2370..0000000
--- a/android-car-lib/res/layout/action_bar_button.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2018 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<ImageButton style="@style/Widget.Car.Button.ActionBar" />
diff --git a/android-car-lib/res/layout/action_bar_slot.xml b/android-car-lib/res/layout/action_bar_slot.xml
deleted file mode 100644
index 804e356..0000000
--- a/android-car-lib/res/layout/action_bar_slot.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2018 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<FrameLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="0dp"
-    android:layout_height="@dimen/car_action_bar_button_height"
-    android:layout_weight="1"
-    android:visibility="visible"
-    android:foregroundGravity="center"
-    android:clipChildren="false"
-    android:foreground="@drawable/car_action_button_activated_ring_foreground">
-</FrameLayout>
\ No newline at end of file
diff --git a/android-car-lib/res/layout/car_alert_dialog.xml b/android-car-lib/res/layout/car_alert_dialog.xml
deleted file mode 100644
index d9b52a5..0000000
--- a/android-car-lib/res/layout/car_alert_dialog.xml
+++ /dev/null
@@ -1,83 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2018 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<!-- Note: the width is 0dp because ColumnCardView will automatically set a width based
-     on the number of columns it should take up. See ColumnCardView for more details. -->
-<androidx.car.widget.ColumnCardView
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    android:layout_gravity="center"
-    android:layout_width="0dp"
-    android:layout_height="wrap_content"
-    android:elevation="@dimen/car_dialog_elevation"
-    app:cardBackgroundColor="?attr/dialogBackgroundColor"
-    app:cardCornerRadius="@dimen/car_radius_3">
-
-    <LinearLayout
-        android:id="@+id/content_view"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginStart="@dimen/car_keyline_1"
-        android:layout_marginEnd="@dimen/car_keyline_1"
-        android:paddingTop="@dimen/car_padding_4"
-        android:paddingBottom="@dimen/car_padding_4"
-        android:orientation="vertical">
-
-        <TextView
-            android:id="@+id/title"
-            android:layout_width="wrap_content"
-            android:layout_height="@dimen/car_dialog_header_height"
-            android:gravity="center_vertical|start"
-            android:visibility="gone"
-            style="?attr/dialogTitleStyle" />
-
-        <TextView
-            android:id="@+id/body"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:visibility="gone"
-            style="?attr/dialogBodyStyle" />
-
-        <LinearLayout
-            android:id="@+id/button_panel"
-            android:layout_width="match_parent"
-            android:layout_height="@dimen/car_dialog_action_bar_height"
-            android:layout_marginTop="@dimen/car_padding_2"
-            android:gravity="center_vertical"
-            android:orientation="horizontal"
-            android:visibility="gone">
-
-            <Button
-                android:id="@+id/positive_button"
-                android:layout_marginEnd="@dimen/car_padding_4"
-                android:layout_width="wrap_content"
-                android:minWidth="0dp"
-                android:padding="0dp"
-                android:textColor="@color/car_accent"
-                android:visibility="gone"
-                style="?attr/dialogButtonStyle" />
-
-            <Button
-                android:id="@+id/negative_button"
-                android:layout_width="wrap_content"
-                android:minWidth="0dp"
-                android:padding="0dp"
-                android:textColor="@color/car_accent"
-                android:visibility="gone"
-                style="?attr/dialogButtonStyle" />
-        </LinearLayout>
-    </LinearLayout>
-</androidx.car.widget.ColumnCardView>
diff --git a/android-car-lib/res/layout/car_drawer.xml b/android-car-lib/res/layout/car_drawer.xml
deleted file mode 100644
index 0629862..0000000
--- a/android-car-lib/res/layout/car_drawer.xml
+++ /dev/null
@@ -1,41 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<androidx.car.moderator.SpeedBumpView
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    android:id="@+id/drawer_content"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:layout_marginEnd="@dimen/car_drawer_margin_end"
-    android:background="?attr/drawerBackgroundColor"
-    android:paddingTop="@dimen/car_app_bar_height" >
-
-  <androidx.car.widget.PagedListView
-      android:id="@+id/drawer_list"
-      android:layout_width="match_parent"
-      android:layout_height="match_parent"
-      app:listEndMargin="@dimen/car_drawer_margin_end"
-      app:gutter="start"
-      style="?attr/drawerListStyle" />
-
-  <ProgressBar
-      android:id="@+id/drawer_progress"
-      android:layout_width="@dimen/car_drawer_progress_bar_size"
-      android:layout_height="@dimen/car_drawer_progress_bar_size"
-      android:layout_gravity="center"
-      android:indeterminate="true"
-      android:visibility="gone" />
-</androidx.car.moderator.SpeedBumpView>
diff --git a/android-car-lib/res/layout/car_drawer_activity.xml b/android-car-lib/res/layout/car_drawer_activity.xml
deleted file mode 100644
index 1648d09..0000000
--- a/android-car-lib/res/layout/car_drawer_activity.xml
+++ /dev/null
@@ -1,56 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<androidx.coordinatorlayout.widget.CoordinatorLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent">
-
-    <androidx.drawerlayout.widget.DrawerLayout
-        android:id="@+id/drawer_layout"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent">
-
-        <!-- The main content view. Fragments will be added here. -->
-      <androidx.car.moderator.SpeedBumpView
-            android:id="@+id/content_frame"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            app:layout_behavior="@string/appbar_scrolling_view_behavior" />
-
-        <include
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:layout_gravity="start"
-            layout="@layout/car_drawer" />
-    </androidx.drawerlayout.widget.DrawerLayout>
-
-    <android.support.design.widget.AppBarLayout
-        android:id="@+id/appbar"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:fitsSystemWindows="true">
-        <!-- The min height of the Toolbar needs to be set to ensure that the icons in it
-             are vertically centered. -->
-        <androidx.car.widget.ClickThroughToolbar
-            android:id="@+id/car_toolbar"
-            android:layout_width="match_parent"
-            android:layout_height="@dimen/car_app_bar_height"
-            android:layout_gravity="center_vertical"
-            android:minHeight="@dimen/car_app_bar_height"
-            style="@style/Widget.Car.Toolbar" />
-    </android.support.design.widget.AppBarLayout>
-</androidx.coordinatorlayout.widget.CoordinatorLayout>
diff --git a/android-car-lib/res/layout/car_drawer_list_item_empty.xml b/android-car-lib/res/layout/car_drawer_list_item_empty.xml
deleted file mode 100644
index d078a32..0000000
--- a/android-car-lib/res/layout/car_drawer_list_item_empty.xml
+++ /dev/null
@@ -1,45 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<LinearLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/container"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:layout_marginStart="16dp"
-    android:focusable="false"
-    android:orientation="vertical"
-    android:background="@drawable/car_drawer_list_item_background" >
-    <FrameLayout
-        android:id="@+id/icon_container"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:visibility="visible">
-        <ImageView
-            android:id="@+id/icon"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_gravity="center_horizontal"
-            android:layout_marginTop="48dp"
-            android:layout_marginBottom="22dp" />
-    </FrameLayout>
-    <TextView
-        android:id="@+id/title"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_marginEnd="16dp"
-        android:gravity="center"
-        android:textAppearance="?attr/drawerItemTitleTextAppearance" />
-</LinearLayout>
diff --git a/android-car-lib/res/layout/car_drawer_list_item_normal.xml b/android-car-lib/res/layout/car_drawer_list_item_normal.xml
deleted file mode 100644
index a400c5a..0000000
--- a/android-car-lib/res/layout/car_drawer_list_item_normal.xml
+++ /dev/null
@@ -1,59 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<LinearLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="@dimen/car_double_line_list_item_height"
-    android:focusable="true"
-    android:orientation="horizontal"
-    android:background="@drawable/car_drawer_list_item_background" >
-    <ImageView
-        android:id="@+id/icon"
-        android:layout_width="@dimen/car_drawer_list_item_icon_size"
-        android:layout_height="@dimen/car_drawer_list_item_icon_size"
-        android:layout_marginEnd="@dimen/car_drawer_list_item_icon_end_margin"
-        android:layout_gravity="center_vertical"
-        android:scaleType="centerCrop" />
-    <LinearLayout
-        android:id="@+id/text_container"
-        android:layout_width="0dp"
-        android:layout_height="wrap_content"
-        android:layout_weight="1"
-        android:layout_gravity="center_vertical"
-        android:orientation="vertical" >
-        <TextView
-            android:id="@+id/title"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_marginBottom="@dimen/car_text_vertical_margin"
-            android:maxLines="1"
-            android:textAppearance="?attr/drawerItemTitleTextAppearance" />
-        <TextView
-            android:id="@+id/text"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:ellipsize="end"
-            android:maxLines="1"
-            android:textAppearance="?attr/drawerItemBodyTextAppearance" />
-    </LinearLayout>
-    <ImageView
-        android:id="@+id/end_icon"
-        android:layout_width="@dimen/car_drawer_list_item_end_icon_size"
-        android:layout_height="@dimen/car_drawer_list_item_end_icon_size"
-        android:scaleType="fitCenter"
-        android:layout_marginEnd="@dimen/car_drawer_list_item_end_margin"
-        android:layout_gravity="center_vertical" />
-</LinearLayout>
diff --git a/android-car-lib/res/layout/car_drawer_list_item_small.xml b/android-car-lib/res/layout/car_drawer_list_item_small.xml
deleted file mode 100644
index 7ccf72b..0000000
--- a/android-car-lib/res/layout/car_drawer_list_item_small.xml
+++ /dev/null
@@ -1,46 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<LinearLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="@dimen/car_single_line_list_item_height"
-    android:focusable="true"
-    android:orientation="horizontal"
-    android:background="@drawable/car_drawer_list_item_background" >
-    <ImageView
-        android:id="@+id/icon"
-        android:layout_width="@dimen/car_drawer_list_item_small_icon_size"
-        android:layout_height="@dimen/car_drawer_list_item_small_icon_size"
-        android:layout_marginEnd="@dimen/car_drawer_list_item_icon_end_margin"
-        android:layout_gravity="center_vertical"
-        android:scaleType="centerCrop" />
-    <TextView
-        android:id="@+id/title"
-        android:layout_width="0dp"
-        android:layout_height="wrap_content"
-        android:layout_weight="1"
-        android:layout_gravity="center_vertical"
-        android:layout_marginBottom="@dimen/car_text_vertical_margin"
-        android:maxLines="1"
-        android:textAppearance="?attr/drawerItemTitleTextAppearance" />
-    <ImageView
-        android:id="@+id/end_icon"
-        android:layout_width="@dimen/car_drawer_list_item_end_icon_size"
-        android:layout_height="@dimen/car_drawer_list_item_end_icon_size"
-        android:scaleType="fitCenter"
-        android:layout_marginEnd="@dimen/car_drawer_list_item_end_margin"
-        android:layout_gravity="center_vertical"/>
-</LinearLayout>
diff --git a/android-car-lib/res/layout/car_list_dialog.xml b/android-car-lib/res/layout/car_list_dialog.xml
deleted file mode 100644
index c3ff1bf..0000000
--- a/android-car-lib/res/layout/car_list_dialog.xml
+++ /dev/null
@@ -1,62 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2018 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<FrameLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    android:id="@+id/container"
-    android:background="@android:color/transparent"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent" >
-
-    <!-- Note: the width is 0dp because ColumnCardView will automatically set a width based
-         on the number of columns it should take up. See ColumnCardView for more details. -->
-    <androidx.car.widget.ColumnCardView
-        android:layout_gravity="center"
-        android:layout_width="0dp"
-        android:layout_height="wrap_content"
-        android:layout_marginTop="@dimen/car_padding_4"
-        android:layout_marginBottom="@dimen/car_padding_4"
-        android:elevation="@dimen/car_dialog_elevation"
-        app:cardBackgroundColor="?attr/dialogBackgroundColor"
-        app:cardCornerRadius="@dimen/car_radius_3">
-
-        <!-- Hide the scrollbar for this PagedListView because it will be implemented by
-             @id/scrollbar. -->
-        <androidx.car.widget.PagedListView
-            android:id="@+id/list"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:theme="?attr/dialogListTheme"
-            app:gutter="none"
-            app:dividerStartMargin="@dimen/car_keyline_1"
-            app:dividerEndMargin="@dimen/car_keyline_1"
-            app:showPagedListViewDivider="true"
-            app:scrollBarEnabled="false" />
-    </androidx.car.widget.ColumnCardView>
-
-    <!-- Putting this as the last child for highest z-index. It is also clickable to reduce
-         the chance of clicks on the buttons accidentally dismissing the dialog. -->
-    <androidx.car.widget.PagedScrollBarView
-        android:id="@+id/scrollbar"
-        android:layout_width="@dimen/car_margin"
-        android:layout_height="match_parent"
-        android:layout_marginTop="@dimen/car_padding_4"
-        android:layout_marginBottom="@dimen/car_padding_4"
-        android:layout_gravity="start|top"
-        android:clickable="true"
-        android:visibility="invisible" />
-</FrameLayout>
diff --git a/android-car-lib/res/layout/car_list_item_seekbar_content.xml b/android-car-lib/res/layout/car_list_item_seekbar_content.xml
deleted file mode 100644
index 2e3b165..0000000
--- a/android-car-lib/res/layout/car_list_item_seekbar_content.xml
+++ /dev/null
@@ -1,61 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2018 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-<RelativeLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/container"
-    android:layout_width="wrap_content"
-    android:layout_height="match_parent">
-
-    <!-- This layout should only be used by class SeekbarListItem, as it requires layout params
-         being set programmatically depending on item data/view configuration. -->
-
-    <!-- Primary Action. -->
-    <ImageView
-        android:id="@+id/primary_icon"
-        android:layout_width="@dimen/car_single_line_list_item_height"
-        android:layout_height="@dimen/car_single_line_list_item_height"/>
-
-    <!-- Slider and text. -->
-    <LinearLayout
-        android:id="@+id/seek_bar_container"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:orientation="vertical">
-        <TextView
-            android:id="@+id/text"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"/>
-        <SeekBar
-            android:id="@+id/seek_bar"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:splitTrack="false"
-            style="@style/Widget.Car.SeekBar"/>
-    </LinearLayout>
-
-    <!-- Supplemental action. -->
-    <ImageView
-        android:id="@+id/supplemental_icon"
-        android:layout_width="@dimen/car_primary_icon_size"
-        android:layout_height="@dimen/car_primary_icon_size"
-        android:scaleType="fitCenter"/>
-    <View
-        android:id="@+id/supplemental_icon_divider"
-        android:layout_width="@dimen/car_vertical_line_divider_width"
-        android:layout_height="@dimen/car_vertical_line_divider_height"
-        android:background="@color/car_list_divider"/>
-</RelativeLayout>
diff --git a/android-car-lib/res/layout/car_list_item_text_content.xml b/android-car-lib/res/layout/car_list_item_text_content.xml
deleted file mode 100644
index a85a31e..0000000
--- a/android-car-lib/res/layout/car_list_item_text_content.xml
+++ /dev/null
@@ -1,113 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2017 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-<RelativeLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/container"
-    android:layout_width="wrap_content"
-    android:layout_height="match_parent"
-    android:foreground="@drawable/car_card_ripple_background">
-    <!-- Primary Action. -->
-    <ImageView
-        android:id="@+id/primary_icon"
-        android:layout_width="@dimen/car_single_line_list_item_height"
-        android:layout_height="@dimen/car_single_line_list_item_height"/>
-
-    <!-- Text. -->
-    <TextView
-        android:id="@+id/title"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:singleLine="true"
-        android:ellipsize="end"/>
-    <TextView
-        android:id="@+id/body"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"/>
-
-    <!-- Supplemental action(s) - only one of the following groups should be visible. -->
-    <!-- End icon with divider. -->
-    <View
-        android:id="@+id/supplemental_icon_divider"
-        android:layout_centerVertical="true"
-        android:layout_toStartOf="@id/supplemental_icon"
-        android:layout_marginEnd="@dimen/car_padding_4"
-        style="@style/CarListVerticalDivider"/>
-    <ImageView
-        android:id="@+id/supplemental_icon"
-        android:layout_centerVertical="true"
-        android:layout_width="@dimen/car_primary_icon_size"
-        android:layout_height="@dimen/car_primary_icon_size"
-        android:layout_alignParentEnd="true"
-        android:layout_marginEnd="@dimen/car_keyline_1"
-        android:scaleType="fitCenter"/>
-
-    <!-- Switch with divider. -->
-    <View
-        android:id="@+id/switch_divider"
-        android:layout_centerVertical="true"
-        android:layout_toStartOf="@id/switch_widget"
-        android:layout_marginEnd="@dimen/car_padding_4"
-        style="@style/CarListVerticalDivider"/>
-    <Switch
-        android:id="@+id/switch_widget"
-        android:layout_centerVertical="true"
-        android:layout_width="@dimen/car_primary_icon_size"
-        android:layout_height="@dimen/car_primary_icon_size"
-        android:layout_alignParentEnd="true"
-        android:layout_marginEnd="@dimen/car_keyline_1"
-        style="@android:style/Widget.Material.CompoundButton.Switch"/>
-
-    <!-- Up to 2 action buttons with dividers. -->
-    <View
-        android:id="@+id/action2_divider"
-        android:layout_centerVertical="true"
-        android:layout_toStartOf="@id/action2"
-        android:layout_marginEnd="@dimen/car_padding_4"
-        style="@style/CarListVerticalDivider"/>
-    <Button
-        android:id="@+id/action2"
-        android:layout_centerVertical="true"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_toStartOf="@id/action1_divider"
-        android:layout_marginEnd="@dimen/car_padding_4"
-        android:ellipsize="end"
-        android:maxLength="@integer/car_borderless_button_text_length_limit"
-        android:maxLines="1"
-        android:background="@color/car_card"
-        android:foreground="@drawable/car_card_ripple_background"
-        style="?android:attr/borderlessButtonStyle"/>
-    <View
-        android:id="@+id/action1_divider"
-        android:layout_centerVertical="true"
-        android:layout_toStartOf="@id/action1"
-        android:layout_marginEnd="@dimen/car_padding_4"
-        style="@style/CarListVerticalDivider"/>
-    <Button
-        android:id="@+id/action1"
-        android:layout_centerVertical="true"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_alignParentEnd="true"
-        android:layout_marginEnd="@dimen/car_keyline_1"
-        android:ellipsize="end"
-        android:maxLength="@integer/car_borderless_button_text_length_limit"
-        android:maxLines="1"
-        android:background="@color/car_card"
-        android:foreground="@drawable/car_card_ripple_background"
-        style="?android:attr/borderlessButtonStyle"/>
-</RelativeLayout>
diff --git a/android-car-lib/res/layout/car_paged_recycler_view.xml b/android-car-lib/res/layout/car_paged_recycler_view.xml
deleted file mode 100644
index 360d9a2..0000000
--- a/android-car-lib/res/layout/car_paged_recycler_view.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2017 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-<FrameLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent">
-
-    <androidx.recyclerview.widget.RecyclerView
-        android:id="@+id/recycler_view"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent" />
-
-    <!-- Putting this as the last child so that it can intercept any touch events on the
-         scroll buttons. -->
-    <androidx.car.widget.PagedScrollBarView
-        android:id="@+id/paged_scroll_view"
-        android:layout_width="@dimen/car_margin"
-        android:layout_height="match_parent"
-        android:paddingBottom="@dimen/car_padding_4"
-        android:paddingTop="@dimen/car_padding_4"
-        android:visibility="invisible" />
-</FrameLayout>
diff --git a/android-car-lib/res/layout/car_paged_scrollbar_buttons.xml b/android-car-lib/res/layout/car_paged_scrollbar_buttons.xml
deleted file mode 100644
index b126b48..0000000
--- a/android-car-lib/res/layout/car_paged_scrollbar_buttons.xml
+++ /dev/null
@@ -1,58 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2017 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-<LinearLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:layout_gravity="center"
-    android:gravity="center"
-    android:orientation="vertical">
-
-    <ImageView
-        android:id="@+id/page_up"
-        android:layout_width="@dimen/car_scroll_bar_button_size"
-        android:layout_height="@dimen/car_scroll_bar_button_size"
-        android:background="@drawable/car_card_ripple_background"
-        android:focusable="false"
-        android:hapticFeedbackEnabled="false"
-        android:src="@drawable/ic_up" />
-
-    <FrameLayout
-        android:id="@+id/filler"
-        android:layout_width="match_parent"
-        android:layout_height="0dp"
-        android:layout_weight="1"
-        android:layout_marginBottom="@dimen/car_padding_2"
-        android:layout_marginTop="@dimen/car_padding_2" >
-
-        <View
-            android:id="@+id/scrollbar_thumb"
-            android:layout_width="@dimen/car_scroll_bar_thumb_width"
-            android:layout_height="0dp"
-            android:layout_gravity="center_horizontal"
-            android:background="@drawable/car_scrollbar_thumb" />
-    </FrameLayout>
-
-    <ImageView
-        android:id="@+id/page_down"
-        android:layout_width="@dimen/car_scroll_bar_button_size"
-        android:layout_height="@dimen/car_scroll_bar_button_size"
-        android:background="@drawable/car_card_ripple_background"
-        android:focusable="false"
-        android:hapticFeedbackEnabled="false"
-        android:src="@drawable/ic_down" />
-</LinearLayout>
diff --git a/android-car-lib/res/layout/car_toolbar.xml b/android-car-lib/res/layout/car_toolbar.xml
deleted file mode 100644
index 3926896..0000000
--- a/android-car-lib/res/layout/car_toolbar.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<FrameLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="@dimen/car_app_bar_height">
-    <androidx.appcompat.widget.Toolbar
-        android:id="@+id/car_toolbar"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_gravity="center_vertical"
-        style="@style/Widget.Car.Toolbar" />
-</FrameLayout>
diff --git a/android-car-lib/res/layout/lock_out_message.xml b/android-car-lib/res/layout/lock_out_message.xml
deleted file mode 100644
index 220e1f3..0000000
--- a/android-car-lib/res/layout/lock_out_message.xml
+++ /dev/null
@@ -1,48 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2018 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<RelativeLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/lock_out_message_container"
-    android:background="@drawable/speed_bump_scrim"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:layout_gravity="bottom"
-    android:visibility="gone">
-
-    <ImageView
-        android:id="@+id/lock_out_drawable"
-        android:layout_width="wrap_content"
-        android:layout_height="@dimen/speed_bump_lock_out_message_height"
-        android:layout_gravity="center"
-        android:layout_marginBottom="@dimen/speed_bump_lock_out_drawable_margin_bottom"
-        android:layout_alignParentBottom="true"
-        android:layout_centerHorizontal="true"
-        android:src="@drawable/lock_out_message_animation"/>
-
-    <!-- Align this TextView against the lock_out_drawable to ensure that the latter will wrap
-         this TextView. -->
-    <TextView
-        android:id="@+id/lock_out_text"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:textAppearance="@style/TextAppearance.Car.Body1"
-        android:layout_alignStart="@id/lock_out_drawable"
-        android:layout_alignEnd="@id/lock_out_drawable"
-        android:layout_alignTop="@id/lock_out_drawable"
-        android:layout_alignBottom="@id/lock_out_drawable"
-        android:gravity="center"
-        android:text="@string/speed_bump_lockout_message"/>
-</RelativeLayout>
diff --git a/android-car-lib/res/values-af/values-af.xml b/android-car-lib/res/values-af/values-af.xml
deleted file mode 100644
index ed25d1d..0000000
--- a/android-car-lib/res/values-af/values-af.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Konsentreer op die pad"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-af/values.xml b/android-car-lib/res/values-af/values.xml
deleted file mode 100644
index 7990a8e..0000000
--- a/android-car-lib/res/values-af/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Vou knoppie in/uit"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Konsentreer op die pad"</string>
-</resources>
diff --git a/android-car-lib/res/values-am/values-am.xml b/android-car-lib/res/values-am/values-am.xml
deleted file mode 100644
index 529a04e..0000000
--- a/android-car-lib/res/values-am/values-am.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"መንገዱ ላይ ያተኩሩ"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-am/values.xml b/android-car-lib/res/values-am/values.xml
deleted file mode 100644
index 8bd9ce9..0000000
--- a/android-car-lib/res/values-am/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"አዝራርን ዘርጋ/ሰብስብ"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"መንገዱ ላይ ያተኩሩ"</string>
-</resources>
diff --git a/android-car-lib/res/values-ar/values-ar.xml b/android-car-lib/res/values-ar/values-ar.xml
deleted file mode 100644
index 3d64213..0000000
--- a/android-car-lib/res/values-ar/values-ar.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"ركِّز في الطريق"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-ar/values.xml b/android-car-lib/res/values-ar/values.xml
deleted file mode 100644
index a05692c..0000000
--- a/android-car-lib/res/values-ar/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"زر التوسيع/التصغير"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"ركِّز في الطريق."</string>
-</resources>
diff --git a/android-car-lib/res/values-as/values.xml b/android-car-lib/res/values-as/values.xml
deleted file mode 100644
index db2bb2f..0000000
--- a/android-car-lib/res/values-as/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"সম্প্ৰসাৰণ/সংকোচন বুটাম"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"মনোযোগেৰে গাড়ী চলাওক"</string>
-</resources>
diff --git a/android-car-lib/res/values-az/values-az.xml b/android-car-lib/res/values-az/values-az.xml
deleted file mode 100644
index b5b0f12..0000000
--- a/android-car-lib/res/values-az/values-az.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Diqqətinizi yola yönəldin"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-az/values.xml b/android-car-lib/res/values-az/values.xml
deleted file mode 100644
index 822f446..0000000
--- a/android-car-lib/res/values-az/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Düyməni genişləndirin/yığcamlaşdırın"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Diqqətinizi yola yönəldin"</string>
-</resources>
diff --git a/android-car-lib/res/values-b+sr+Latn/values-b+sr+Latn.xml b/android-car-lib/res/values-b+sr+Latn/values-b+sr+Latn.xml
deleted file mode 100644
index 97332eb..0000000
--- a/android-car-lib/res/values-b+sr+Latn/values-b+sr+Latn.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Fokusirajte se na put"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-b+sr+Latn/values.xml b/android-car-lib/res/values-b+sr+Latn/values.xml
deleted file mode 100644
index 1da562a..0000000
--- a/android-car-lib/res/values-b+sr+Latn/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Dugme Proširi/skupi"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Fokusirajte se na put"</string>
-</resources>
diff --git a/android-car-lib/res/values-be/values-be.xml b/android-car-lib/res/values-be/values-be.xml
deleted file mode 100644
index cd54ef9..0000000
--- a/android-car-lib/res/values-be/values-be.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Увага на дарогу"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-be/values.xml b/android-car-lib/res/values-be/values.xml
deleted file mode 100644
index a33ac9b..0000000
--- a/android-car-lib/res/values-be/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Кнопка \"Разгарнуць/згарнуць\""</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Увага на дарогу"</string>
-</resources>
diff --git a/android-car-lib/res/values-bg/values-bg.xml b/android-car-lib/res/values-bg/values-bg.xml
deleted file mode 100644
index 90f73ad..0000000
--- a/android-car-lib/res/values-bg/values-bg.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Съсредоточете се върху пътя"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-bg/values.xml b/android-car-lib/res/values-bg/values.xml
deleted file mode 100644
index 18a283d..0000000
--- a/android-car-lib/res/values-bg/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Бутон за разгъване/свиване"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Съсредоточете се върху пътя"</string>
-</resources>
diff --git a/android-car-lib/res/values-bn/values-bn.xml b/android-car-lib/res/values-bn/values-bn.xml
deleted file mode 100644
index 8a7d235..0000000
--- a/android-car-lib/res/values-bn/values-bn.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"মনোযোগ দিয়ে গাড়ি চালান"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-bn/values.xml b/android-car-lib/res/values-bn/values.xml
deleted file mode 100644
index ad4f5a0..0000000
--- a/android-car-lib/res/values-bn/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"বোতামটি বড় করুন/আড়াল করুন"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"মনোযোগ দিয়ে গাড়ি চালান"</string>
-</resources>
diff --git a/android-car-lib/res/values-bs/values-bs.xml b/android-car-lib/res/values-bs/values-bs.xml
deleted file mode 100644
index 5cb1759..0000000
--- a/android-car-lib/res/values-bs/values-bs.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Fokusirajte se na cestu"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-bs/values.xml b/android-car-lib/res/values-bs/values.xml
deleted file mode 100644
index f9b4431..0000000
--- a/android-car-lib/res/values-bs/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Dugme proširi/suzi"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Fokusirajte se na cestu"</string>
-</resources>
diff --git a/android-car-lib/res/values-ca/values-ca.xml b/android-car-lib/res/values-ca/values-ca.xml
deleted file mode 100644
index 2c1c31a..0000000
--- a/android-car-lib/res/values-ca/values-ca.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Concentra\'t en la carretera"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-ca/values.xml b/android-car-lib/res/values-ca/values.xml
deleted file mode 100644
index c9133a5..0000000
--- a/android-car-lib/res/values-ca/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Botó per desplegar o replegar"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Concentra\'t en la carretera"</string>
-</resources>
diff --git a/android-car-lib/res/values-cs/values-cs.xml b/android-car-lib/res/values-cs/values-cs.xml
deleted file mode 100644
index 7bd877c..0000000
--- a/android-car-lib/res/values-cs/values-cs.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Soustřeďte se na silnici"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-cs/values.xml b/android-car-lib/res/values-cs/values.xml
deleted file mode 100644
index aad6789..0000000
--- a/android-car-lib/res/values-cs/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Tlačítko rozbalení/sbalení"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Soustřeďte se na silnici"</string>
-</resources>
diff --git a/android-car-lib/res/values-da/values-da.xml b/android-car-lib/res/values-da/values-da.xml
deleted file mode 100644
index 54f7632..0000000
--- a/android-car-lib/res/values-da/values-da.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Hold øjnene på vejen"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-da/values.xml b/android-car-lib/res/values-da/values.xml
deleted file mode 100644
index fb82413..0000000
--- a/android-car-lib/res/values-da/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Knappen Udvid/skjul"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Hold øjnene på vejen"</string>
-</resources>
diff --git a/android-car-lib/res/values-de/values-de.xml b/android-car-lib/res/values-de/values-de.xml
deleted file mode 100644
index d0a35b5..0000000
--- a/android-car-lib/res/values-de/values-de.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Achte auf den Verkehr"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-de/values.xml b/android-car-lib/res/values-de/values.xml
deleted file mode 100644
index fb8e1c5..0000000
--- a/android-car-lib/res/values-de/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Schaltfläche zum Maximieren/Minimieren"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Achte auf den Verkehr"</string>
-</resources>
diff --git a/android-car-lib/res/values-el/values-el.xml b/android-car-lib/res/values-el/values-el.xml
deleted file mode 100644
index 52758b1..0000000
--- a/android-car-lib/res/values-el/values-el.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Επικεντρωθείτε στον δρόμο"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-el/values.xml b/android-car-lib/res/values-el/values.xml
deleted file mode 100644
index e17e8f4..0000000
--- a/android-car-lib/res/values-el/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Κουμπί ανάπτυξης/σύμπτυξης"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Επικεντρωθείτε στον δρόμο"</string>
-</resources>
diff --git a/android-car-lib/res/values-en-rAU/values-en-rAU.xml b/android-car-lib/res/values-en-rAU/values-en-rAU.xml
deleted file mode 100644
index 14ebe5f..0000000
--- a/android-car-lib/res/values-en-rAU/values-en-rAU.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Focus on the road"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-en-rAU/values.xml b/android-car-lib/res/values-en-rAU/values.xml
deleted file mode 100644
index b950788..0000000
--- a/android-car-lib/res/values-en-rAU/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Expand/collapse button"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Focus on the road"</string>
-</resources>
diff --git a/android-car-lib/res/values-en-rCA/values-en-rCA.xml b/android-car-lib/res/values-en-rCA/values-en-rCA.xml
deleted file mode 100644
index 14ebe5f..0000000
--- a/android-car-lib/res/values-en-rCA/values-en-rCA.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Focus on the road"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-en-rCA/values.xml b/android-car-lib/res/values-en-rCA/values.xml
deleted file mode 100644
index b950788..0000000
--- a/android-car-lib/res/values-en-rCA/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Expand/collapse button"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Focus on the road"</string>
-</resources>
diff --git a/android-car-lib/res/values-en-rGB/values-en-rGB.xml b/android-car-lib/res/values-en-rGB/values-en-rGB.xml
deleted file mode 100644
index 14ebe5f..0000000
--- a/android-car-lib/res/values-en-rGB/values-en-rGB.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Focus on the road"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-en-rGB/values.xml b/android-car-lib/res/values-en-rGB/values.xml
deleted file mode 100644
index b950788..0000000
--- a/android-car-lib/res/values-en-rGB/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Expand/collapse button"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Focus on the road"</string>
-</resources>
diff --git a/android-car-lib/res/values-en-rIN/values-en-rIN.xml b/android-car-lib/res/values-en-rIN/values-en-rIN.xml
deleted file mode 100644
index 14ebe5f..0000000
--- a/android-car-lib/res/values-en-rIN/values-en-rIN.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Focus on the road"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-en-rIN/values.xml b/android-car-lib/res/values-en-rIN/values.xml
deleted file mode 100644
index b950788..0000000
--- a/android-car-lib/res/values-en-rIN/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Expand/collapse button"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Focus on the road"</string>
-</resources>
diff --git a/android-car-lib/res/values-en-rXC/values-en-rXC.xml b/android-car-lib/res/values-en-rXC/values-en-rXC.xml
deleted file mode 100644
index 2644d8a..0000000
--- a/android-car-lib/res/values-en-rXC/values-en-rXC.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‏‏‎‎‎‎‎‏‎‎‏‏‏‎‎‏‎‏‎‏‏‏‏‏‎‎‎‏‎‏‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‎‏‎‏‎‎‏‏‏‏‎Focus on the road‎‏‎‎‏‎"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-en-rXC/values.xml b/android-car-lib/res/values-en-rXC/values.xml
deleted file mode 100644
index 1d1d116..0000000
--- a/android-car-lib/res/values-en-rXC/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‏‎‏‎‏‎‎‎‎‏‎‎‎‏‎‎‏‏‏‎‏‏‎‎‏‏‏‏‏‎‎‎‎‏‏‏‎‏‎‏‏‎‏‏‏‎‎‏‎‏‎‏‏‎‎‎‏‏‎‏‎‎‎‎‎Expand/collapse button‎‏‎‎‏‎"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‎‎‎‎‎‏‏‎‏‎‎‏‏‏‏‎‏‏‏‏‏‏‏‏‏‏‏‎‎‎‏‏‏‏‏‎‎‏‏‏‎‏‏‏‎‏‏‎‎‏‏‎‎‎‎‏‏‏‎‎Focus on the road‎‏‎‎‏‎"</string>
-</resources>
diff --git a/android-car-lib/res/values-es-rUS/values-es-rUS.xml b/android-car-lib/res/values-es-rUS/values-es-rUS.xml
deleted file mode 100644
index e5ecf44..0000000
--- a/android-car-lib/res/values-es-rUS/values-es-rUS.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Concéntrate en el camino"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-es-rUS/values.xml b/android-car-lib/res/values-es-rUS/values.xml
deleted file mode 100644
index 0a3e9a8..0000000
--- a/android-car-lib/res/values-es-rUS/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Botón Expandir/contraer"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Concéntrate en el camino"</string>
-</resources>
diff --git a/android-car-lib/res/values-es/values-es.xml b/android-car-lib/res/values-es/values-es.xml
deleted file mode 100644
index 2af260c..0000000
--- a/android-car-lib/res/values-es/values-es.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Céntrate en la carretera"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-es/values.xml b/android-car-lib/res/values-es/values.xml
deleted file mode 100644
index a175812..0000000
--- a/android-car-lib/res/values-es/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Botón para mostrar u ocultar"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Céntrate en la carretera"</string>
-</resources>
diff --git a/android-car-lib/res/values-et/values-et.xml b/android-car-lib/res/values-et/values-et.xml
deleted file mode 100644
index 30fce07..0000000
--- a/android-car-lib/res/values-et/values-et.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Keskenduge teele"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-et/values.xml b/android-car-lib/res/values-et/values.xml
deleted file mode 100644
index 18e9283..0000000
--- a/android-car-lib/res/values-et/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Nupp Laienda/Ahenda"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Keskenduge teele"</string>
-</resources>
diff --git a/android-car-lib/res/values-eu/values-eu.xml b/android-car-lib/res/values-eu/values-eu.xml
deleted file mode 100644
index 65513d4..0000000
--- a/android-car-lib/res/values-eu/values-eu.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Jarri arreta errepidean"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-eu/values.xml b/android-car-lib/res/values-eu/values.xml
deleted file mode 100644
index 4e2c741..0000000
--- a/android-car-lib/res/values-eu/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Zabaltzeko/Tolesteko botoia"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Jarri arreta errepidean"</string>
-</resources>
diff --git a/android-car-lib/res/values-fa/values-fa.xml b/android-car-lib/res/values-fa/values-fa.xml
deleted file mode 100644
index f683363..0000000
--- a/android-car-lib/res/values-fa/values-fa.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"روی جاده تمرکز داشته باشید"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-fa/values.xml b/android-car-lib/res/values-fa/values.xml
deleted file mode 100644
index 319b857..0000000
--- a/android-car-lib/res/values-fa/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"دکمه بزرگ کردن/کوچک کردن"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"روی جاده تمرکز داشته باشید"</string>
-</resources>
diff --git a/android-car-lib/res/values-fi/values-fi.xml b/android-car-lib/res/values-fi/values-fi.xml
deleted file mode 100644
index b7223be..0000000
--- a/android-car-lib/res/values-fi/values-fi.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Pidä katse tiessä"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-fi/values.xml b/android-car-lib/res/values-fi/values.xml
deleted file mode 100644
index 7e917d2..0000000
--- a/android-car-lib/res/values-fi/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Laajennus- ja tiivistyspainike"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Pidä katse tiessä"</string>
-</resources>
diff --git a/android-car-lib/res/values-fr-rCA/values-fr-rCA.xml b/android-car-lib/res/values-fr-rCA/values-fr-rCA.xml
deleted file mode 100644
index 79e44c5..0000000
--- a/android-car-lib/res/values-fr-rCA/values-fr-rCA.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Concentrez-vous sur la route"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-fr-rCA/values.xml b/android-car-lib/res/values-fr-rCA/values.xml
deleted file mode 100644
index e44d8cb..0000000
--- a/android-car-lib/res/values-fr-rCA/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Bouton Développer/Réduire"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Concentrez-vous sur la route"</string>
-</resources>
diff --git a/android-car-lib/res/values-fr/values-fr.xml b/android-car-lib/res/values-fr/values-fr.xml
deleted file mode 100644
index 79e44c5..0000000
--- a/android-car-lib/res/values-fr/values-fr.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Concentrez-vous sur la route"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-fr/values.xml b/android-car-lib/res/values-fr/values.xml
deleted file mode 100644
index e44d8cb..0000000
--- a/android-car-lib/res/values-fr/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Bouton Développer/Réduire"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Concentrez-vous sur la route"</string>
-</resources>
diff --git a/android-car-lib/res/values-gl/values-gl.xml b/android-car-lib/res/values-gl/values-gl.xml
deleted file mode 100644
index d024b93..0000000
--- a/android-car-lib/res/values-gl/values-gl.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Céntrate na estrada"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-gl/values.xml b/android-car-lib/res/values-gl/values.xml
deleted file mode 100644
index 9b09422..0000000
--- a/android-car-lib/res/values-gl/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Botón despregar/contraer"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Céntrate na estrada"</string>
-</resources>
diff --git a/android-car-lib/res/values-gu/values-gu.xml b/android-car-lib/res/values-gu/values-gu.xml
deleted file mode 100644
index 6b0f8d5..0000000
--- a/android-car-lib/res/values-gu/values-gu.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"રસ્તા પર ફોકસ કરો"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-gu/values.xml b/android-car-lib/res/values-gu/values.xml
deleted file mode 100644
index 8735563..0000000
--- a/android-car-lib/res/values-gu/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"વિસ્તાર કરો/સંકુચિત કરો બટન"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"રસ્તા પર ફોકસ કરો"</string>
-</resources>
diff --git a/android-car-lib/res/values-h1752dp-v13/values-h1752dp-v13.xml b/android-car-lib/res/values-h1752dp-v13/values-h1752dp-v13.xml
deleted file mode 100644
index 9eb87ed..0000000
--- a/android-car-lib/res/values-h1752dp-v13/values-h1752dp-v13.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <dimen name="car_action1_size">32sp</dimen>
-    <dimen name="car_app_bar_height">112dp</dimen>
-    <dimen name="car_avatar_size">96dp</dimen>
-    <dimen name="car_body1_size">40sp</dimen>
-    <dimen name="car_body2_size">32sp</dimen>
-    <dimen name="car_card_action_bar_height">96dp</dimen>
-    <dimen name="car_card_header_height">96dp</dimen>
-    <dimen name="car_headline1_size">56sp</dimen>
-    <dimen name="car_headline2_size">50sp</dimen>
-    <dimen name="car_label1_size">32sp</dimen>
-    <dimen name="car_primary_icon_size">56dp</dimen>
-    <dimen name="car_secondary_icon_size">36dp</dimen>
-    <dimen name="car_single_line_list_item_height">128dp</dimen>
-    <dimen name="car_slide_up_menu_initial_height">128dp</dimen>
-    <dimen name="car_sub_header_height">96dp</dimen>
-    <dimen name="car_title2_size">40sp</dimen>
-    <dimen name="car_touch_target_size">96dp</dimen>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-h668dp-v13/values-h668dp-v13.xml b/android-car-lib/res/values-h668dp-v13/values-h668dp-v13.xml
deleted file mode 100644
index 127e094..0000000
--- a/android-car-lib/res/values-h668dp-v13/values-h668dp-v13.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <dimen name="car_app_bar_height">96dp</dimen>
-    <dimen name="car_drawer_list_item_end_icon_size">56dp</dimen>
-    <dimen name="car_drawer_list_item_icon_size">108dp</dimen>
-    <dimen name="car_drawer_list_item_small_icon_size">56dp</dimen>
-    <dimen name="car_headline2_size">36sp</dimen>
-    <dimen name="car_padding_2">16dp</dimen>
-    <dimen name="car_padding_3">28dp</dimen>
-    <dimen name="car_padding_4">32dp</dimen>
-    <dimen name="car_padding_5">64dp</dimen>
-    <dimen name="car_padding_6">96dp</dimen>
-    <dimen name="car_scroll_bar_button_size">76dp</dimen>
-    <dimen name="car_single_line_list_item_height">116dp</dimen>
-    <dimen name="car_slide_up_menu_initial_height">116dp</dimen>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-hi/values-hi.xml b/android-car-lib/res/values-hi/values-hi.xml
deleted file mode 100644
index 5430f04..0000000
--- a/android-car-lib/res/values-hi/values-hi.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"सड़क पर ध्यान दें"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-hi/values.xml b/android-car-lib/res/values-hi/values.xml
deleted file mode 100644
index d2cb5f8..0000000
--- a/android-car-lib/res/values-hi/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"बड़ा/छोटा करने वाला बटन"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"सड़क पर ध्यान दें"</string>
-</resources>
diff --git a/android-car-lib/res/values-hr/values-hr.xml b/android-car-lib/res/values-hr/values-hr.xml
deleted file mode 100644
index dc7be15..0000000
--- a/android-car-lib/res/values-hr/values-hr.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Usredotočite se na cestu"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-hr/values.xml b/android-car-lib/res/values-hr/values.xml
deleted file mode 100644
index d279d04..0000000
--- a/android-car-lib/res/values-hr/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Gumb za proširivanje/sažimanje"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Usredotočite se na cestu"</string>
-</resources>
diff --git a/android-car-lib/res/values-hu/values-hu.xml b/android-car-lib/res/values-hu/values-hu.xml
deleted file mode 100644
index 1e7ff2c..0000000
--- a/android-car-lib/res/values-hu/values-hu.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Figyeljen az útra"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-hu/values.xml b/android-car-lib/res/values-hu/values.xml
deleted file mode 100644
index e009ab8..0000000
--- a/android-car-lib/res/values-hu/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Gomb kibontása/összecsukása"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Figyeljen az útra"</string>
-</resources>
diff --git a/android-car-lib/res/values-hy/values-hy.xml b/android-car-lib/res/values-hy/values-hy.xml
deleted file mode 100644
index 54ba33e..0000000
--- a/android-car-lib/res/values-hy/values-hy.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Հետևեք ճանապարհին"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-hy/values.xml b/android-car-lib/res/values-hy/values.xml
deleted file mode 100644
index 05a225d..0000000
--- a/android-car-lib/res/values-hy/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"«Ընդարձակել/ծալել» կոճակ"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Հետևեք ճանապարհին"</string>
-</resources>
diff --git a/android-car-lib/res/values-in/values-in.xml b/android-car-lib/res/values-in/values-in.xml
deleted file mode 100644
index 25b10ed..0000000
--- a/android-car-lib/res/values-in/values-in.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Konsentrasi saat mengemudi"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-in/values.xml b/android-car-lib/res/values-in/values.xml
deleted file mode 100644
index 33e98c8..0000000
--- a/android-car-lib/res/values-in/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Tombol luaskan/ciutkan"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Konsentrasi saat mengemudi"</string>
-</resources>
diff --git a/android-car-lib/res/values-is/values-is.xml b/android-car-lib/res/values-is/values-is.xml
deleted file mode 100644
index c48d73b..0000000
--- a/android-car-lib/res/values-is/values-is.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Einbeittu þér að akstrinum"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-is/values.xml b/android-car-lib/res/values-is/values.xml
deleted file mode 100644
index 8db74e8..0000000
--- a/android-car-lib/res/values-is/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Hnappur til að stækka/minnka"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Einbeittu þér að akstrinum"</string>
-</resources>
diff --git a/android-car-lib/res/values-it/values-it.xml b/android-car-lib/res/values-it/values-it.xml
deleted file mode 100644
index 64780ad..0000000
--- a/android-car-lib/res/values-it/values-it.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Concentrati sulla strada"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-it/values.xml b/android-car-lib/res/values-it/values.xml
deleted file mode 100644
index 42e9fb6..0000000
--- a/android-car-lib/res/values-it/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Pulsante Espandi/Comprimi"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Concentrati sulla strada"</string>
-</resources>
diff --git a/android-car-lib/res/values-iw/values-iw.xml b/android-car-lib/res/values-iw/values-iw.xml
deleted file mode 100644
index 3af92b7..0000000
--- a/android-car-lib/res/values-iw/values-iw.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"עליך להתמקד בכביש"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-iw/values.xml b/android-car-lib/res/values-iw/values.xml
deleted file mode 100644
index 9a5d0d9..0000000
--- a/android-car-lib/res/values-iw/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"לחצן הרחבה וכיווץ"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"עליך להתמקד בכביש"</string>
-</resources>
diff --git a/android-car-lib/res/values-ja/values-ja.xml b/android-car-lib/res/values-ja/values-ja.xml
deleted file mode 100644
index 598f61f..0000000
--- a/android-car-lib/res/values-ja/values-ja.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"運転に集中してください"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-ja/values.xml b/android-car-lib/res/values-ja/values.xml
deleted file mode 100644
index 004bc89..0000000
--- a/android-car-lib/res/values-ja/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"展開 / 折りたたみボタン"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"運転に集中してください"</string>
-</resources>
diff --git a/android-car-lib/res/values-ka/values-ka.xml b/android-car-lib/res/values-ka/values-ka.xml
deleted file mode 100644
index 0e5a161..0000000
--- a/android-car-lib/res/values-ka/values-ka.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"კონცენტრირდით გზაზე"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-ka/values.xml b/android-car-lib/res/values-ka/values.xml
deleted file mode 100644
index fa26c0c..0000000
--- a/android-car-lib/res/values-ka/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"ღილაკის გაშლა/ჩაკეცვა"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"კონცენტრირდით გზაზე"</string>
-</resources>
diff --git a/android-car-lib/res/values-kk/values-kk.xml b/android-car-lib/res/values-kk/values-kk.xml
deleted file mode 100644
index b70f1db..0000000
--- a/android-car-lib/res/values-kk/values-kk.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Жолға назар аударыңыз"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-kk/values.xml b/android-car-lib/res/values-kk/values.xml
deleted file mode 100644
index a90524b..0000000
--- a/android-car-lib/res/values-kk/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"\"Жаю/Жию\" түймесі"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Жолға назар аударыңыз"</string>
-</resources>
diff --git a/android-car-lib/res/values-km/values-km.xml b/android-car-lib/res/values-km/values-km.xml
deleted file mode 100644
index b550049..0000000
--- a/android-car-lib/res/values-km/values-km.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"ផ្តោតលើ​ការបើកបរ"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-km/values.xml b/android-car-lib/res/values-km/values.xml
deleted file mode 100644
index 8fc71c6..0000000
--- a/android-car-lib/res/values-km/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"ប៊ូតុង​ពង្រីក/បង្រួម"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"ផ្តោតលើ​ការបើកបរ"</string>
-</resources>
diff --git a/android-car-lib/res/values-kn/values-kn.xml b/android-car-lib/res/values-kn/values-kn.xml
deleted file mode 100644
index cf77bf0..0000000
--- a/android-car-lib/res/values-kn/values-kn.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"ರಸ್ತೆಯ ಮೇಲೆ ಗಮನಹರಿಸಿ"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-kn/values.xml b/android-car-lib/res/values-kn/values.xml
deleted file mode 100644
index dea965f..0000000
--- a/android-car-lib/res/values-kn/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"ವಿಸ್ತರಿಸಿ/ಕುಗ್ಗಿಸಿ ಬಟನ್"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"ರಸ್ತೆಯ ಮೇಲೆ ಗಮನಹರಿಸಿ"</string>
-</resources>
diff --git a/android-car-lib/res/values-ko/values-ko.xml b/android-car-lib/res/values-ko/values-ko.xml
deleted file mode 100644
index 5564a12..0000000
--- a/android-car-lib/res/values-ko/values-ko.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"도로 상황에 집중하세요."</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-ko/values.xml b/android-car-lib/res/values-ko/values.xml
deleted file mode 100644
index 62f39d1..0000000
--- a/android-car-lib/res/values-ko/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"펼치기/접기 버튼"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"도로 상황에 집중하세요."</string>
-</resources>
diff --git a/android-car-lib/res/values-ky/values-ky.xml b/android-car-lib/res/values-ky/values-ky.xml
deleted file mode 100644
index eb5b9dc..0000000
--- a/android-car-lib/res/values-ky/values-ky.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Жолго көңүл буруңуз"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-ky/values.xml b/android-car-lib/res/values-ky/values.xml
deleted file mode 100644
index 5a48f45..0000000
--- a/android-car-lib/res/values-ky/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Жайып көрсөтүү/жыйыштыруу баскычы"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Жолго көңүл буруңуз"</string>
-</resources>
diff --git a/android-car-lib/res/values-lo/values-lo.xml b/android-car-lib/res/values-lo/values-lo.xml
deleted file mode 100644
index 332f827..0000000
--- a/android-car-lib/res/values-lo/values-lo.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"ຕັ້ງໃຈຂັບລົດ"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-lo/values.xml b/android-car-lib/res/values-lo/values.xml
deleted file mode 100644
index 96a8c09..0000000
--- a/android-car-lib/res/values-lo/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"ປຸ່ມຂະຫຍາຍ/ຫຍໍ້ລົງ"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"ຕັ້ງໃຈຂັບລົດ"</string>
-</resources>
diff --git a/android-car-lib/res/values-lt/values-lt.xml b/android-car-lib/res/values-lt/values-lt.xml
deleted file mode 100644
index cad45a9..0000000
--- a/android-car-lib/res/values-lt/values-lt.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Sutelkite dėmesį į kelią"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-lt/values.xml b/android-car-lib/res/values-lt/values.xml
deleted file mode 100644
index d77e8b0..0000000
--- a/android-car-lib/res/values-lt/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Mygtukas „Išskleisti / sutraukti“"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Sutelkite dėmesį į kelią"</string>
-</resources>
diff --git a/android-car-lib/res/values-lv/values-lv.xml b/android-car-lib/res/values-lv/values-lv.xml
deleted file mode 100644
index fa8b02b..0000000
--- a/android-car-lib/res/values-lv/values-lv.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Pievērsieties autovadīšanai"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-lv/values.xml b/android-car-lib/res/values-lv/values.xml
deleted file mode 100644
index a29444b..0000000
--- a/android-car-lib/res/values-lv/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Izvēršanas/sakļaušanas poga"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Pievērsieties ceļam"</string>
-</resources>
diff --git a/android-car-lib/res/values-mk/values-mk.xml b/android-car-lib/res/values-mk/values-mk.xml
deleted file mode 100644
index a1fec3e..0000000
--- a/android-car-lib/res/values-mk/values-mk.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Фокусирајте се на патот"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-mk/values.xml b/android-car-lib/res/values-mk/values.xml
deleted file mode 100644
index ae4ceb5..0000000
--- a/android-car-lib/res/values-mk/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Копче за проширување/собирање"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Фокусирајте се на патот"</string>
-</resources>
diff --git a/android-car-lib/res/values-ml/values-ml.xml b/android-car-lib/res/values-ml/values-ml.xml
deleted file mode 100644
index 0301e61..0000000
--- a/android-car-lib/res/values-ml/values-ml.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"റോഡിൽ ശ്രദ്ധിക്കുക"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-ml/values.xml b/android-car-lib/res/values-ml/values.xml
deleted file mode 100644
index 5399293..0000000
--- a/android-car-lib/res/values-ml/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"വികസിപ്പിക്കുക/ചുരുക്കുക ബട്ടൺ"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"റോഡിൽ ശ്രദ്ധിക്കുക"</string>
-</resources>
diff --git a/android-car-lib/res/values-mn/values-mn.xml b/android-car-lib/res/values-mn/values-mn.xml
deleted file mode 100644
index 3d2a53f..0000000
--- a/android-car-lib/res/values-mn/values-mn.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Зам дээр төвлөрөх"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-mn/values.xml b/android-car-lib/res/values-mn/values.xml
deleted file mode 100644
index abe78f1..0000000
--- a/android-car-lib/res/values-mn/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Дэлгэх/буулгах товчлуур"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Зам дээр анхаарлаа төвлөрүүлэх"</string>
-</resources>
diff --git a/android-car-lib/res/values-mr/values-mr.xml b/android-car-lib/res/values-mr/values-mr.xml
deleted file mode 100644
index 9f9dfa7..0000000
--- a/android-car-lib/res/values-mr/values-mr.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"रस्त्यावर फोकस करा"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-mr/values.xml b/android-car-lib/res/values-mr/values.xml
deleted file mode 100644
index 77e890f..0000000
--- a/android-car-lib/res/values-mr/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"बटण विस्‍तृत करा/कोलॅप्‍स करा"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"रस्त्यावर फोकस करा"</string>
-</resources>
diff --git a/android-car-lib/res/values-ms/values-ms.xml b/android-car-lib/res/values-ms/values-ms.xml
deleted file mode 100644
index f5e24b5..0000000
--- a/android-car-lib/res/values-ms/values-ms.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Beri tumpuan pada jalan raya"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-ms/values.xml b/android-car-lib/res/values-ms/values.xml
deleted file mode 100644
index d04485b..0000000
--- a/android-car-lib/res/values-ms/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Butang kembangkan/runtuhkan"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Beri tumpuan pada jalan raya"</string>
-</resources>
diff --git a/android-car-lib/res/values-my/values-my.xml b/android-car-lib/res/values-my/values-my.xml
deleted file mode 100644
index 617468e..0000000
--- a/android-car-lib/res/values-my/values-my.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"လမ်းကို အာရုံစိုက်ရန်"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-my/values.xml b/android-car-lib/res/values-my/values.xml
deleted file mode 100644
index be8c9fc..0000000
--- a/android-car-lib/res/values-my/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"ချဲ့ရန်/လျှော့ပြရန် ခလုတ်"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"လမ်းပေါ်တွင် အာရုံစိုက်ပါ"</string>
-</resources>
diff --git a/android-car-lib/res/values-nb/values-nb.xml b/android-car-lib/res/values-nb/values-nb.xml
deleted file mode 100644
index 7f50f78..0000000
--- a/android-car-lib/res/values-nb/values-nb.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Fokuser på veien"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-nb/values.xml b/android-car-lib/res/values-nb/values.xml
deleted file mode 100644
index 5575a1a..0000000
--- a/android-car-lib/res/values-nb/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Vis/skjul-knapp"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Fokuser på veien"</string>
-</resources>
diff --git a/android-car-lib/res/values-ne/values-ne.xml b/android-car-lib/res/values-ne/values-ne.xml
deleted file mode 100644
index 91acb81..0000000
--- a/android-car-lib/res/values-ne/values-ne.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"सडकमा ध्यान केन्द्रित गर्नु…"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-ne/values.xml b/android-car-lib/res/values-ne/values.xml
deleted file mode 100644
index b366be2..0000000
--- a/android-car-lib/res/values-ne/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"विस्तृत/संक्षिप्त गर्ने बटन"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"सडकमा ध्यान केन्द्रित गर्नुहोस्"</string>
-</resources>
diff --git a/android-car-lib/res/values-night-v8/values-night-v8.xml b/android-car-lib/res/values-night-v8/values-night-v8.xml
deleted file mode 100644
index e9a243a..0000000
--- a/android-car-lib/res/values-night-v8/values-night-v8.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <color name="car_accent">@color/car_accent_light</color>
-    <color name="car_action1">@color/car_action1_light</color>
-    <color name="car_body1">@color/car_body1_light</color>
-    <color name="car_body2">@color/car_body2_light</color>
-    <color name="car_body3">@color/car_body3_light</color>
-    <color name="car_body4">@color/car_body4_light</color>
-    <color name="car_card">@color/car_card_dark</color>
-    <color name="car_card_inverse">@color/car_card_light</color>
-    <color name="car_card_ripple_background">@color/car_card_ripple_background_light</color>
-    <color name="car_card_ripple_background_inverse">@color/car_card_ripple_background_dark</color>
-    <color name="car_headline1">@color/car_headline1_light</color>
-    <color name="car_headline2">@color/car_headline2_light</color>
-    <color name="car_headline3">@color/car_headline3_light</color>
-    <color name="car_headline4">@color/car_headline4_light</color>
-    <color name="car_label1">@color/car_label1_light</color>
-    <color name="car_list_divider">@color/car_list_divider_light</color>
-    <color name="car_list_divider_inverse">@color/car_list_divider_dark</color>
-    <color name="car_scrollbar_thumb">@color/car_scrollbar_thumb_light</color>
-    <color name="car_scrollbar_thumb_inverse">@color/car_scrollbar_thumb_dark</color>
-    <color name="car_tint">@color/car_tint_light</color>
-    <color name="car_tint_inverse">@color/car_tint_dark</color>
-    <color name="car_title">@color/car_title_light</color>
-    <color name="car_title2">@color/car_title2_light</color>
-    <color name="speed_bump_background">#FF4C4C4C</color>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-nl/values-nl.xml b/android-car-lib/res/values-nl/values-nl.xml
deleted file mode 100644
index 756b53d..0000000
--- a/android-car-lib/res/values-nl/values-nl.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Houd je aandacht op de weg"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-nl/values.xml b/android-car-lib/res/values-nl/values.xml
deleted file mode 100644
index de8f173..0000000
--- a/android-car-lib/res/values-nl/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Knop voor uitvouwen/samenvouwen"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Houd je aandacht op de weg"</string>
-</resources>
diff --git a/android-car-lib/res/values-or/values.xml b/android-car-lib/res/values-or/values.xml
deleted file mode 100644
index 1836305..0000000
--- a/android-car-lib/res/values-or/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"ବିସ୍ତାର/ସଂକୋଚନ ବଟନ୍"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"ରାସ୍ତା ଉପରେ ଧ୍ୟାନରଖନ୍ତୁ"</string>
-</resources>
diff --git a/android-car-lib/res/values-pa/values-pa.xml b/android-car-lib/res/values-pa/values-pa.xml
deleted file mode 100644
index 8aec306..0000000
--- a/android-car-lib/res/values-pa/values-pa.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"ਸੜਕ \'ਤੇ ਧਿਆਨ ਦਿਓ"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-pa/values.xml b/android-car-lib/res/values-pa/values.xml
deleted file mode 100644
index c4369d3..0000000
--- a/android-car-lib/res/values-pa/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"ਵਿਸਤਾਰ ਕਰੋ ਜਾਂ ਸਮੇਟੋ ਬਟਨ"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"ਸੜਕ \'ਤੇ ਧਿਆਨ ਦਿਓ"</string>
-</resources>
diff --git a/android-car-lib/res/values-pl/values-pl.xml b/android-car-lib/res/values-pl/values-pl.xml
deleted file mode 100644
index 32a3af6..0000000
--- a/android-car-lib/res/values-pl/values-pl.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Skup się na drodze"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-pl/values.xml b/android-car-lib/res/values-pl/values.xml
deleted file mode 100644
index 0373349..0000000
--- a/android-car-lib/res/values-pl/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Przycisk zwijania/rozwijania"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Skup się na drodze"</string>
-</resources>
diff --git a/android-car-lib/res/values-pt-rBR/values-pt-rBR.xml b/android-car-lib/res/values-pt-rBR/values-pt-rBR.xml
deleted file mode 100644
index 01c5f31..0000000
--- a/android-car-lib/res/values-pt-rBR/values-pt-rBR.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Foco na estrada"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-pt-rPT/values-pt-rPT.xml b/android-car-lib/res/values-pt-rPT/values-pt-rPT.xml
deleted file mode 100644
index 9cc59bc..0000000
--- a/android-car-lib/res/values-pt-rPT/values-pt-rPT.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Concentre-se na estrada."</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-pt-rPT/values.xml b/android-car-lib/res/values-pt-rPT/values.xml
deleted file mode 100644
index 85c248a..0000000
--- a/android-car-lib/res/values-pt-rPT/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Botão Expandir/reduzir"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Concentre-se na estrada"</string>
-</resources>
diff --git a/android-car-lib/res/values-pt/values-pt.xml b/android-car-lib/res/values-pt/values-pt.xml
deleted file mode 100644
index 01c5f31..0000000
--- a/android-car-lib/res/values-pt/values-pt.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Foco na estrada"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-pt/values.xml b/android-car-lib/res/values-pt/values.xml
deleted file mode 100644
index 8d7071d..0000000
--- a/android-car-lib/res/values-pt/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Botão \"Expandir/Recolher\""</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Foco na estrada"</string>
-</resources>
diff --git a/android-car-lib/res/values-ro/values-ro.xml b/android-car-lib/res/values-ro/values-ro.xml
deleted file mode 100644
index 72b3ef7..0000000
--- a/android-car-lib/res/values-ro/values-ro.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Concentrați-vă asupra drumului"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-ro/values.xml b/android-car-lib/res/values-ro/values.xml
deleted file mode 100644
index 4a40973..0000000
--- a/android-car-lib/res/values-ro/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Butonul de extindere/restrângere"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Concentrați-vă asupra drumului"</string>
-</resources>
diff --git a/android-car-lib/res/values-ru/values-ru.xml b/android-car-lib/res/values-ru/values-ru.xml
deleted file mode 100644
index 96f1b8f..0000000
--- a/android-car-lib/res/values-ru/values-ru.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Следите за дорогой"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-ru/values.xml b/android-car-lib/res/values-ru/values.xml
deleted file mode 100644
index 82def43..0000000
--- a/android-car-lib/res/values-ru/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Кнопка \"Развернуть/свернуть\""</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Следите за дорогой"</string>
-</resources>
diff --git a/android-car-lib/res/values-si/values-si.xml b/android-car-lib/res/values-si/values-si.xml
deleted file mode 100644
index 53aeba6..0000000
--- a/android-car-lib/res/values-si/values-si.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"මාර්ගයට අවධානය යොමු කරන්න"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-si/values.xml b/android-car-lib/res/values-si/values.xml
deleted file mode 100644
index d841b61..0000000
--- a/android-car-lib/res/values-si/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"දිග හැරීමේ/හැකිළීමේ බොත්තම"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"මාර්ගයට අවධානය යොමු කරන්න"</string>
-</resources>
diff --git a/android-car-lib/res/values-sk/values-sk.xml b/android-car-lib/res/values-sk/values-sk.xml
deleted file mode 100644
index 20634da..0000000
--- a/android-car-lib/res/values-sk/values-sk.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Sústreďte sa na cestu"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-sk/values.xml b/android-car-lib/res/values-sk/values.xml
deleted file mode 100644
index cd78105..0000000
--- a/android-car-lib/res/values-sk/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Tlačidlo rozbalenia/zbalenia"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Sústreďte sa na cestu"</string>
-</resources>
diff --git a/android-car-lib/res/values-sl/values-sl.xml b/android-car-lib/res/values-sl/values-sl.xml
deleted file mode 100644
index 6a8dd70..0000000
--- a/android-car-lib/res/values-sl/values-sl.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Glejte na cesto"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-sl/values.xml b/android-car-lib/res/values-sl/values.xml
deleted file mode 100644
index db5e068..0000000
--- a/android-car-lib/res/values-sl/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Gumb za razširitev/strnitev"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Glejte na cesto"</string>
-</resources>
diff --git a/android-car-lib/res/values-sq/values-sq.xml b/android-car-lib/res/values-sq/values-sq.xml
deleted file mode 100644
index 2079f47..0000000
--- a/android-car-lib/res/values-sq/values-sq.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Përqendrohu te rruga"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-sq/values.xml b/android-car-lib/res/values-sq/values.xml
deleted file mode 100644
index e72a586..0000000
--- a/android-car-lib/res/values-sq/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Butoni i zgjerimit/palosjes"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Përqendrohu te rruga"</string>
-</resources>
diff --git a/android-car-lib/res/values-sr/values-sr.xml b/android-car-lib/res/values-sr/values-sr.xml
deleted file mode 100644
index 428dcc6..0000000
--- a/android-car-lib/res/values-sr/values-sr.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Фокусирајте се на пут"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-sr/values.xml b/android-car-lib/res/values-sr/values.xml
deleted file mode 100644
index 2c6b1ea..0000000
--- a/android-car-lib/res/values-sr/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Дугме Прошири/скупи"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Фокусирајте се на пут"</string>
-</resources>
diff --git a/android-car-lib/res/values-sv/values-sv.xml b/android-car-lib/res/values-sv/values-sv.xml
deleted file mode 100644
index b63afe6..0000000
--- a/android-car-lib/res/values-sv/values-sv.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Fokusera på körningen"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-sv/values.xml b/android-car-lib/res/values-sv/values.xml
deleted file mode 100644
index d7a7ca4..0000000
--- a/android-car-lib/res/values-sv/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Knappen Utöka/komprimera"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Fokusera på körningen"</string>
-</resources>
diff --git a/android-car-lib/res/values-sw/values-sw.xml b/android-car-lib/res/values-sw/values-sw.xml
deleted file mode 100644
index 4b3d68a..0000000
--- a/android-car-lib/res/values-sw/values-sw.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Tia makini barabarani"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-sw/values.xml b/android-car-lib/res/values-sw/values.xml
deleted file mode 100644
index dfb951c..0000000
--- a/android-car-lib/res/values-sw/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Kitufe cha kupanua/kukunja"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Makinika barabarani"</string>
-</resources>
diff --git a/android-car-lib/res/values-ta/values-ta.xml b/android-car-lib/res/values-ta/values-ta.xml
deleted file mode 100644
index 0718f29..0000000
--- a/android-car-lib/res/values-ta/values-ta.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"வாகனம் ஓட்டும்போது கவனம் தேவை"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-ta/values.xml b/android-car-lib/res/values-ta/values.xml
deleted file mode 100644
index 2a7bf98..0000000
--- a/android-car-lib/res/values-ta/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"விரிவாக்குவதற்கான/சுருக்குவதற்கான பட்டன்"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"வாகனம் ஓட்டும்போது கவனம் தேவை"</string>
-</resources>
diff --git a/android-car-lib/res/values-te/values-te.xml b/android-car-lib/res/values-te/values-te.xml
deleted file mode 100644
index c4d7d3e..0000000
--- a/android-car-lib/res/values-te/values-te.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"రహదారిపై దృష్టి ఉంచండి"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-te/values.xml b/android-car-lib/res/values-te/values.xml
deleted file mode 100644
index 082ee94..0000000
--- a/android-car-lib/res/values-te/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"విస్తరించు/కుదించు బటన్"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"రహదారిపై దృష్టి ఉంచండి"</string>
-</resources>
diff --git a/android-car-lib/res/values-th/values-th.xml b/android-car-lib/res/values-th/values-th.xml
deleted file mode 100644
index e3fb94f..0000000
--- a/android-car-lib/res/values-th/values-th.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"จดจ่อกับถนน"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-th/values.xml b/android-car-lib/res/values-th/values.xml
deleted file mode 100644
index 4c7f8ce..0000000
--- a/android-car-lib/res/values-th/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"ปุ่มขยาย/ยุบ"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"จดจ่อกับถนน"</string>
-</resources>
diff --git a/android-car-lib/res/values-tl/values-tl.xml b/android-car-lib/res/values-tl/values-tl.xml
deleted file mode 100644
index 332c15c..0000000
--- a/android-car-lib/res/values-tl/values-tl.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Tumuon sa kalsada"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-tl/values.xml b/android-car-lib/res/values-tl/values.xml
deleted file mode 100644
index 674ffb1..0000000
--- a/android-car-lib/res/values-tl/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Button na i-expand/i-collapse"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Tumuon sa kalsada"</string>
-</resources>
diff --git a/android-car-lib/res/values-tr/values-tr.xml b/android-car-lib/res/values-tr/values-tr.xml
deleted file mode 100644
index 5f66ef3..0000000
--- a/android-car-lib/res/values-tr/values-tr.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Dikkatinizi yola verin"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-tr/values.xml b/android-car-lib/res/values-tr/values.xml
deleted file mode 100644
index dde5e18..0000000
--- a/android-car-lib/res/values-tr/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Genişlet/daralt düğmesi"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Dikkatinizi yola verin"</string>
-</resources>
diff --git a/android-car-lib/res/values-uk/values-uk.xml b/android-car-lib/res/values-uk/values-uk.xml
deleted file mode 100644
index 472d178..0000000
--- a/android-car-lib/res/values-uk/values-uk.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Зосередьтеся на дорозі"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-uk/values.xml b/android-car-lib/res/values-uk/values.xml
deleted file mode 100644
index e277cc5..0000000
--- a/android-car-lib/res/values-uk/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Кнопка \"Розгорнути або згорнути\""</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Зосередьтеся на дорозі"</string>
-</resources>
diff --git a/android-car-lib/res/values-ur/values-ur.xml b/android-car-lib/res/values-ur/values-ur.xml
deleted file mode 100644
index 6f13ae2..0000000
--- a/android-car-lib/res/values-ur/values-ur.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"سڑک پر توجہ مرکوز کریں"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-ur/values.xml b/android-car-lib/res/values-ur/values.xml
deleted file mode 100644
index 70659bf..0000000
--- a/android-car-lib/res/values-ur/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"پھیلائیں/سکیڑیں بٹن"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"سڑک پر توجہ مرکوز کریں"</string>
-</resources>
diff --git a/android-car-lib/res/values-uz/values-uz.xml b/android-car-lib/res/values-uz/values-uz.xml
deleted file mode 100644
index cb5f3aa..0000000
--- a/android-car-lib/res/values-uz/values-uz.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Diqqatingizni yo‘lga qarating"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-uz/values.xml b/android-car-lib/res/values-uz/values.xml
deleted file mode 100644
index e9c7755..0000000
--- a/android-car-lib/res/values-uz/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Yoyish/yig‘ish tugmasi"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Diqqatingizni yo‘lga qarating"</string>
-</resources>
diff --git a/android-car-lib/res/values-vi/values-vi.xml b/android-car-lib/res/values-vi/values-vi.xml
deleted file mode 100644
index cecbeac..0000000
--- a/android-car-lib/res/values-vi/values-vi.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Tập trung vào đường đi"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-vi/values.xml b/android-car-lib/res/values-vi/values.xml
deleted file mode 100644
index 070849e..0000000
--- a/android-car-lib/res/values-vi/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Nút mở rộng/thu gọn"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Tập trung vào đường đi"</string>
-</resources>
diff --git a/android-car-lib/res/values-w1280dp-v13/values-w1280dp-v13.xml b/android-car-lib/res/values-w1280dp-v13/values-w1280dp-v13.xml
deleted file mode 100644
index e5d29e6..0000000
--- a/android-car-lib/res/values-w1280dp-v13/values-w1280dp-v13.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <dimen name="car_keyline_4">182dp</dimen>
-    <dimen name="car_keyline_4_neg">-182dp</dimen>
-    <dimen name="car_margin">148dp</dimen>
-    <integer name="car_dialog_column_number">8</integer>
-    <integer name="column_card_default_column_span">8</integer>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-w1920dp-v13/values-w1920dp-v13.xml b/android-car-lib/res/values-w1920dp-v13/values-w1920dp-v13.xml
deleted file mode 100644
index bcffcfa..0000000
--- a/android-car-lib/res/values-w1920dp-v13/values-w1920dp-v13.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <dimen name="car_gutter_size">32dp</dimen>
-    <dimen name="car_keyline_1">48dp</dimen>
-    <dimen name="car_keyline_1_keyline_3_diff">104dp</dimen>
-    <dimen name="car_keyline_1_neg">-48dp</dimen>
-    <dimen name="car_keyline_3">152dp</dimen>
-    <dimen name="car_keyline_3_neg">-152dp</dimen>
-    <dimen name="car_margin">192dp</dimen>
-    <integer name="car_column_number">16</integer>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-w690dp-v13/values-w690dp-v13.xml b/android-car-lib/res/values-w690dp-v13/values-w690dp-v13.xml
deleted file mode 100644
index 19864c5..0000000
--- a/android-car-lib/res/values-w690dp-v13/values-w690dp-v13.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <dimen name="car_margin">112dp</dimen>
-    <integer name="car_column_number">12</integer>
-    <integer name="car_dialog_column_number">10</integer>
-    <integer name="car_slide_up_menu_column_number">12</integer>
-    <integer name="column_card_default_column_span">12</integer>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-w930dp-v13/values-w930dp-v13.xml b/android-car-lib/res/values-w930dp-v13/values-w930dp-v13.xml
deleted file mode 100644
index 363170c..0000000
--- a/android-car-lib/res/values-w930dp-v13/values-w930dp-v13.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <dimen name="car_gutter_size">24dp</dimen>
-    <dimen name="car_keyline_1">32dp</dimen>
-    <dimen name="car_keyline_1_keyline_3_diff">96dp</dimen>
-    <dimen name="car_keyline_1_neg">-32dp</dimen>
-    <dimen name="car_keyline_2">108dp</dimen>
-    <dimen name="car_keyline_2_neg">-108dp</dimen>
-    <dimen name="car_keyline_3">128dp</dimen>
-    <dimen name="car_keyline_3_neg">-128dp</dimen>
-    <dimen name="car_keyline_4">168dp</dimen>
-    <dimen name="car_keyline_4_neg">-168dp</dimen>
-    <integer name="car_dialog_column_number">10</integer>
-    <integer name="column_card_default_column_span">10</integer>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-zh-rCN/values-zh-rCN.xml b/android-car-lib/res/values-zh-rCN/values-zh-rCN.xml
deleted file mode 100644
index e3ac7a1..0000000
--- a/android-car-lib/res/values-zh-rCN/values-zh-rCN.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"请专心驾驶"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-zh-rCN/values.xml b/android-car-lib/res/values-zh-rCN/values.xml
deleted file mode 100644
index 5347850..0000000
--- a/android-car-lib/res/values-zh-rCN/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"“展开”/“收起”按钮"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"请专心驾驶"</string>
-</resources>
diff --git a/android-car-lib/res/values-zh-rHK/values-zh-rHK.xml b/android-car-lib/res/values-zh-rHK/values-zh-rHK.xml
deleted file mode 100644
index 37107e1..0000000
--- a/android-car-lib/res/values-zh-rHK/values-zh-rHK.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"請專心駕駛"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-zh-rHK/values.xml b/android-car-lib/res/values-zh-rHK/values.xml
deleted file mode 100644
index b190714..0000000
--- a/android-car-lib/res/values-zh-rHK/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"展開/收合按鈕"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"請專心駕駛"</string>
-</resources>
diff --git a/android-car-lib/res/values-zh-rTW/values-zh-rTW.xml b/android-car-lib/res/values-zh-rTW/values-zh-rTW.xml
deleted file mode 100644
index 37107e1..0000000
--- a/android-car-lib/res/values-zh-rTW/values-zh-rTW.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"請專心駕駛"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-zh-rTW/values.xml b/android-car-lib/res/values-zh-rTW/values.xml
deleted file mode 100644
index b190714..0000000
--- a/android-car-lib/res/values-zh-rTW/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"展開/收合按鈕"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"請專心駕駛"</string>
-</resources>
diff --git a/android-car-lib/res/values-zu/values-zu.xml b/android-car-lib/res/values-zu/values-zu.xml
deleted file mode 100644
index 1f93364..0000000
--- a/android-car-lib/res/values-zu/values-zu.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Gxila emgwaqweni"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-zu/values.xml b/android-car-lib/res/values-zu/values.xml
deleted file mode 100644
index 0646429..0000000
--- a/android-car-lib/res/values-zu/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Inkinobho yokunweba/ukugoqa"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Gxila emgwaqeni"</string>
-</resources>
diff --git a/android-car-lib/res/values/values.xml b/android-car-lib/res/values/values.xml
deleted file mode 100644
index 0ae2c80..0000000
--- a/android-car-lib/res/values/values.xml
+++ /dev/null
@@ -1,546 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <color name="car_accent">@color/car_accent_dark</color>
-    <color name="car_accent_dark">@color/car_teal_700</color>
-    <color name="car_accent_light">@color/car_teal_200</color>
-    <color name="car_action1">@color/car_action1_dark</color>
-    <color name="car_action1_dark">@color/car_grey_50</color>
-    <color name="car_action1_light">@color/car_grey_900</color>
-    <color name="car_blue_300">#ff91a7ff</color>
-    <color name="car_blue_500">#ff5677fc</color>
-    <color name="car_blue_grey_800">#ff37474F</color>
-    <color name="car_blue_grey_900">#ff263238</color>
-    <color name="car_body1">@color/car_body1_dark</color>
-    <color name="car_body1_dark">@color/car_grey_900</color>
-    <color name="car_body1_light">@color/car_grey_100</color>
-    <color name="car_body2">@color/car_body2_dark</color>
-    <color name="car_body2_dark">@color/car_grey_650</color>
-    <color name="car_body2_light">@color/car_grey_300</color>
-    <color name="car_body3">@color/car_body3_dark</color>
-    <color name="car_body3_dark">@android:color/black</color>
-    <color name="car_body3_light">@android:color/white</color>
-    <color name="car_body4">@color/car_body4_dark</color>
-    <color name="car_body4_dark">@android:color/black</color>
-    <color name="car_body4_light">@android:color/white</color>
-    <color name="car_card">@color/car_card_light</color>
-    <color name="car_card_dark">@color/car_dark_blue_grey_700</color>
-    <color name="car_card_inverse">@color/car_card_dark</color>
-    <color name="car_card_light">@color/car_grey_50</color>
-    <color name="car_card_ripple_background">@color/car_card_ripple_background_dark</color>
-    <color name="car_card_ripple_background_dark">#8F000000</color>
-    <color name="car_card_ripple_background_inverse">@color/car_card_ripple_background_light</color>
-    <color name="car_card_ripple_background_light">#27ffffff</color>
-    <color name="car_dark_blue_grey_1000">#ff090c0f</color>
-    <color name="car_dark_blue_grey_600">#ff1d272d</color>
-    <color name="car_dark_blue_grey_700">#ff172026</color>
-    <color name="car_dark_blue_grey_800">#ff11181d</color>
-    <color name="car_dark_blue_grey_900">#ff0c1013</color>
-    <color name="car_green_500">#ff0f9d58</color>
-    <color name="car_green_700">#ff0b8043</color>
-    <color name="car_grey_100">#fff5f5f5</color>
-    <color name="car_grey_1000">#cc000000</color>
-    <color name="car_grey_200">#ffeeeeee</color>
-    <color name="car_grey_300">#ffe0e0e0</color>
-    <color name="car_grey_400">#ffbdbdbd</color>
-    <color name="car_grey_50">#fffafafa</color>
-    <color name="car_grey_500">#ff9e9e9e</color>
-    <color name="car_grey_600">#ff757575</color>
-    <color name="car_grey_650">#ff6B6B6B</color>
-    <color name="car_grey_700">#ff616161</color>
-    <color name="car_grey_800">#ff424242</color>
-    <color name="car_grey_900">#ff212121</color>
-    <color name="car_headline1">@color/car_headline1_dark</color>
-    <color name="car_headline1_dark">@color/car_grey_800</color>
-    <color name="car_headline1_light">@color/car_grey_100</color>
-    <color name="car_headline2">@color/car_headline2_dark</color>
-    <color name="car_headline2_dark">@color/car_grey_900</color>
-    <color name="car_headline2_light">@color/car_grey_100</color>
-    <color name="car_headline3">@color/car_headline3_dark</color>
-    <color name="car_headline3_dark">@color/car_grey_900</color>
-    <color name="car_headline3_light">@android:color/white</color>
-    <color name="car_headline4">@color/car_headline4_dark</color>
-    <color name="car_headline4_dark">@android:color/black</color>
-    <color name="car_headline4_light">@android:color/white</color>
-    <color name="car_highlight">@color/car_highlight_light</color>
-    <color name="car_highlight_dark">@color/car_teal_200</color>
-    <color name="car_highlight_light">@color/car_teal_700</color>
-    <color name="car_indigo_800">#ff283593</color>
-    <color name="car_label1">@color/car_label1_dark</color>
-    <color name="car_label1_dark">@color/car_grey_900</color>
-    <color name="car_label1_light">@color/car_grey_50</color>
-    <color name="car_light_blue_300">#ff4fc3f7</color>
-    <color name="car_light_blue_500">#ff03A9F4</color>
-    <color name="car_light_blue_600">#ff039be5</color>
-    <color name="car_light_blue_700">#ff0288d1</color>
-    <color name="car_light_blue_800">#ff0277bd</color>
-    <color name="car_light_blue_900">#ff01579b</color>
-    <color name="car_list_divider">@color/car_list_divider_dark</color>
-    <color name="car_list_divider_dark">#1f000000</color>
-    <color name="car_list_divider_inverse">@color/car_list_divider_light</color>
-    <color name="car_list_divider_light">#1fffffff</color>
-    <color name="car_list_header">@color/car_blue_500</color>
-    <color name="car_red_400">#ffe06055</color>
-    <color name="car_red_500">#ffdb4437</color>
-    <color name="car_red_500a">#ffd50000</color>
-    <color name="car_red_700">#ffc53929</color>
-    <color name="car_scrollbar_thumb">@color/car_scrollbar_thumb_dark</color>
-    <color name="car_scrollbar_thumb_dark">#7f0b0f12</color>
-    <color name="car_scrollbar_thumb_inverse">@color/car_scrollbar_thumb_light</color>
-    <color name="car_scrollbar_thumb_light">#99ffffff</color>
-    <color name="car_seekbar_track_background">@color/car_seekbar_track_background_dark</color>
-    <color name="car_seekbar_track_background_dark">@color/car_grey_700</color>
-    <color name="car_seekbar_track_background_inverse"> @color/car_seekbar_track_background_light
-    </color>
-    <color name="car_seekbar_track_background_light">@color/car_grey_400</color>
-    <color name="car_teal_200">#ff80cbc4</color>
-    <color name="car_teal_700">#ff00796b</color>
-    <color name="car_tint">@color/car_tint_dark</color>
-    <color name="car_tint_dark">@color/car_grey_900</color>
-    <color name="car_tint_inverse">@color/car_tint_light</color>
-    <color name="car_tint_light">@color/car_grey_50</color>
-    <color name="car_title">@color/car_title_dark</color>
-    <color name="car_title2">@color/car_title2_dark</color>
-    <color name="car_title2_dark">@color/car_grey_900</color>
-    <color name="car_title2_light">@color/car_grey_100</color>
-    <color name="car_title_dark">@color/car_grey_900</color>
-    <color name="car_title_light">@color/car_grey_100</color>
-    <color name="car_white_1000">#1effffff</color>
-    <color name="car_yellow_500">#fff4b400</color>
-    <color name="car_yellow_800">#ffee8100</color>
-    <color name="speed_bump_background">#FFD0D0D0</color>
-    <declare-styleable name="ActionBar"><attr format="integer" name="columns"/></declare-styleable>
-    <declare-styleable name="CarTheme"><attr format="reference" name="carDialogTheme"/><attr format="reference" name="pagedListViewStyle"/><attr format="reference" name="listItemStyle"/><attr format="color" name="dialogBackgroundColor"/><attr format="reference" name="dialogTitleStyle"/><attr format="reference" name="dialogBodyStyle"/><attr format="reference" name="dialogButtonStyle"/><attr format="reference" name="dialogListTheme"/><attr format="color" name="drawerBackgroundColor"/><attr format="color" name="drawerOpenHeaderColor"/><attr format="color" name="drawerClosedHeaderColor"/><attr format="reference" name="drawerItemTitleTextAppearance"/><attr format="reference" name="drawerItemBodyTextAppearance"/><attr format="reference" name="drawerListStyle"/></declare-styleable>
-    <declare-styleable name="ClickThroughToolbar"><attr format="boolean" name="clickThrough"/></declare-styleable>
-    <declare-styleable name="ColumnCardView"><attr format="integer" name="columnSpan"/></declare-styleable>
-    <declare-styleable name="DrawerArrowDrawable"><attr format="color" name="carArrowColor"/><attr format="boolean" name="carArrowAnimate"/><attr format="dimension" name="carArrowSize"/><attr format="dimension" name="carArrowHeadLength"/><attr format="dimension" name="carArrowShaftLength"/><attr format="dimension" name="carArrowThickness"/><attr format="dimension" name="carMenuBarSpacing"/><attr format="dimension" name="carMenuBarThickness"/></declare-styleable>
-    <declare-styleable name="ListItem"><attr format="color" name="listItemBackgroundColor"/><attr format="reference" name="listItemTitleTextAppearance"/><attr format="reference" name="listItemBodyTextAppearance"/></declare-styleable>
-    <declare-styleable name="PagedListView"><attr format="boolean" name="offsetScrollBar"/><attr format="enum" name="gutter">
-            
-            <enum name="none" value="0"/>
-            
-            <enum name="start" value="1"/>
-            
-            <enum name="end" value="2"/>
-            
-            <enum name="both" value="3"/>
-        </attr><attr format="dimension" name="gutterSize"/><attr format="boolean" name="scrollBarEnabled"/><attr format="dimension" name="scrollBarTopMargin"/><attr format="dimension" name="scrollBarContainerWidth"/><attr format="boolean" name="showPagedListViewDivider"/><attr format="reference" name="alignDividerStartTo"/><attr format="reference" name="alignDividerEndTo"/><attr format="dimension" name="dividerStartMargin"/><attr format="dimension" name="dividerEndMargin"/><attr format="color" name="listDividerColor"/><attr format="dimension" name="listEndMargin"/><attr format="dimension" name="itemSpacing"/><attr format="reference" name="upButtonIcon"/><attr format="reference" name="downButtonIcon"/><attr format="reference" name="listContentTopOffset"/><attr format="enum" name="dayNightStyle">
-            
-            <enum name="auto" value="0"/>
-            
-            <enum name="auto_inverse" value="1"/>
-            
-            <enum name="force_night" value="2"/>
-            
-            <enum name="force_day" value="3"/>
-        </attr></declare-styleable>
-    <dimen name="app_header_height">96dp</dimen>
-    <dimen name="car_action1_size">26sp</dimen>
-    <dimen name="car_action_bar_activation_ring_radius">64dp</dimen>
-    <dimen name="car_action_bar_activation_ring_stroke_width">3dp</dimen>
-    <dimen name="car_action_bar_button_height">128dp</dimen>
-    <dimen name="car_action_bar_button_ripple_radius">48dp</dimen>
-    <dimen name="car_action_bar_button_width">128dp</dimen>
-    <dimen name="car_action_bar_buttons_space">@dimen/car_padding_4</dimen>
-    <dimen name="car_action_bar_elevation">2dp</dimen>
-    <dimen name="car_action_bar_height">128dp</dimen>
-    <dimen name="car_action_bar_touch_ripple_size">38dp</dimen>
-    <dimen name="car_action_button_icon_inset">24dp</dimen>
-    <dimen name="car_action_button_ripple_inset">16dp</dimen>
-    <dimen name="car_alpha_jump_button_size">@dimen/car_scroll_bar_button_size</dimen>
-    <dimen name="car_app_bar_default_elevation">8dp</dimen>
-    <dimen name="car_app_bar_height">80dp</dimen>
-    <dimen name="car_arrow_head_length">18dp</dimen>
-    <dimen name="car_arrow_shaft_length">34dp</dimen>
-    <dimen name="car_arrow_size">96dp</dimen>
-    <dimen name="car_arrow_thickness">3dp</dimen>
-    <dimen name="car_avatar_size">56dp</dimen>
-    <dimen name="car_body1_size">32sp</dimen>
-    <dimen name="car_body2_size">26sp</dimen>
-    <dimen name="car_body3_size">16sp</dimen>
-    <dimen name="car_body4_size">14sp</dimen>
-    <dimen name="car_body5_size">18sp</dimen>
-    <dimen name="car_borderless_button_horizontal_padding">0dp</dimen>
-    <dimen name="car_button_height">56dp</dimen>
-    <dimen name="car_button_horizontal_padding">@dimen/car_padding_4</dimen>
-    <dimen name="car_button_min_width">158dp</dimen>
-    <dimen name="car_button_radius">@dimen/car_radius_1</dimen>
-    <dimen name="car_card_action_bar_height">76dp</dimen>
-    <dimen name="car_card_header_height">76dp</dimen>
-    <dimen name="car_dialog_action_bar_height">@dimen/car_card_action_bar_height</dimen>
-    <dimen name="car_dialog_elevation">16dp</dimen>
-    <dimen name="car_dialog_header_height">@dimen/car_card_header_height</dimen>
-    <dimen name="car_double_line_list_item_height">@dimen/car_single_line_list_item_height</dimen>
-    <dimen name="car_drawer_list_item_end_icon_size">56dp</dimen>
-    <dimen name="car_drawer_list_item_end_margin">32dp</dimen>
-    <dimen name="car_drawer_list_item_icon_end_margin">32dp</dimen>
-    <dimen name="car_drawer_list_item_icon_size">64dp</dimen>
-    <dimen name="car_drawer_list_item_small_icon_size">56dp</dimen>
-    <dimen name="car_drawer_margin_end">96dp</dimen>
-    <dimen name="car_drawer_progress_bar_size">48dp</dimen>
-    <dimen name="car_gutter_size">16dp</dimen>
-    <dimen name="car_headline1_size">45sp</dimen>
-    <dimen name="car_headline2_size">32sp</dimen>
-    <dimen name="car_headline3_size">24sp</dimen>
-    <dimen name="car_headline4_size">20sp</dimen>
-    <dimen name="car_keyline_1">24dp</dimen>
-    <dimen name="car_keyline_1_keyline_3_diff">88dp</dimen>
-    <dimen name="car_keyline_1_neg">-24dp</dimen>
-    <dimen name="car_keyline_2">96dp</dimen>
-    <dimen name="car_keyline_2_neg">-96dp</dimen>
-    <dimen name="car_keyline_3">112dp</dimen>
-    <dimen name="car_keyline_3_neg">-112dp</dimen>
-    <dimen name="car_keyline_4">148dp</dimen>
-    <dimen name="car_keyline_4_neg">-148dp</dimen>
-    <dimen name="car_label1_size">26sp</dimen>
-    <dimen name="car_last_card_peek_amount">16dp</dimen>
-    <dimen name="car_list_divider_height">1dp</dimen>
-    <dimen name="car_margin">20dp</dimen>
-    <dimen name="car_menu_bar_length">40dp</dimen>
-    <dimen name="car_menu_bar_spacing">6dp</dimen>
-    <dimen name="car_padding_0">4dp</dimen>
-    <dimen name="car_padding_1">10dp</dimen>
-    <dimen name="car_padding_2">12dp</dimen>
-    <dimen name="car_padding_3">16dp</dimen>
-    <dimen name="car_padding_4">20dp</dimen>
-    <dimen name="car_padding_5">40dp</dimen>
-    <dimen name="car_padding_6">64dp</dimen>
-    <dimen name="car_primary_icon_size">44dp</dimen>
-    <dimen name="car_progress_bar_height">@dimen/car_seekbar_height</dimen>
-    <dimen name="car_radius_1">4dp</dimen>
-    <dimen name="car_radius_2">8dp</dimen>
-    <dimen name="car_radius_3">16dp</dimen>
-    <dimen name="car_radius_5">100dp</dimen>
-    <dimen name="car_sample_row_height">128dp</dimen>
-    <dimen name="car_scroll_bar_button_size">56dp</dimen>
-    <dimen name="car_scroll_bar_thumb_width">6dp</dimen>
-    <dimen name="car_secondary_icon_size">24dp</dimen>
-    <dimen name="car_seekbar_height">6dp</dimen>
-    <dimen name="car_seekbar_thumb_size">20dp</dimen>
-    <dimen name="car_seekbar_thumb_stroke">1dp</dimen>
-    <dimen name="car_single_line_list_item_height">96dp</dimen>
-    <dimen name="car_slide_down_menu_initial_height">@dimen/car_slide_up_menu_initial_height</dimen>
-    <dimen name="car_slide_up_menu_initial_height">76dp</dimen>
-    <dimen name="car_sub_header_height">76dp</dimen>
-    <dimen name="car_text_input_line_height">2dp</dimen>
-    <dimen name="car_text_vertical_margin">2dp</dimen>
-    <dimen name="car_title2_size">32sp</dimen>
-    <dimen name="car_title_size">32sp</dimen>
-    <dimen name="car_touch_target_size">76dp</dimen>
-    <dimen name="car_vertical_line_divider_height">60dp</dimen>
-    <dimen name="car_vertical_line_divider_width">1dp</dimen>
-    <dimen name="speed_bump_lock_out_drawable_margin_bottom">8dp</dimen>
-    <dimen name="speed_bump_lock_out_message_height">96dp</dimen>
-    <integer name="car_action_bar_collapse_anim_duration">233</integer>
-    <integer name="car_action_bar_expand_anim_duration">333</integer>
-    <integer name="car_borderless_button_text_length_limit">20</integer>
-    <integer name="car_column_number">4</integer>
-    <integer name="car_dialog_column_number">10</integer>
-    <integer name="car_list_item_text_length_limit">120</integer>
-    <integer name="car_slide_up_menu_column_number">4</integer>
-    <integer name="column_card_default_column_span">4</integer>
-    <integer name="speed_bump_fade_duration_ms">167</integer>
-    <integer name="speed_bump_lock_out_color_change_ms">500</integer>
-    <integer name="speed_bump_lock_out_color_change_start_delay_ms">5433</integer>
-    <integer name="speed_bump_lock_out_duration_ms">5933</integer>
-    <integer name="speed_bump_translate_y_duration_ms">300</integer>
-    <string name="action_bar_expand_collapse_button">Expand/collapse button</string>
-    <string name="car_drawer_close" translatable="false">Close drawer</string>
-    <string name="car_drawer_open" translatable="false">Open drawer</string>
-    <string name="ellipsis" translatable="false">…</string>
-    <string name="speed_bump_lockout_message">Focus on the road</string>
-    <style name="CarListVerticalDivider">
-        <item name="android:layout_width">@dimen/car_vertical_line_divider_width</item>
-        <item name="android:layout_height">@dimen/car_vertical_line_divider_height</item>
-        <item name="android:layout_marginStart">@dimen/car_padding_4</item>
-        <item name="android:background">@color/car_list_divider</item>
-    </style>
-    <style name="TextAppearance.Car" parent="TextAppearance.AppCompat"/>
-    <style name="TextAppearance.Car.Body1">
-        <item name="android:textStyle">normal</item>
-        <item name="android:textSize">@dimen/car_body1_size</item>
-        <item name="android:textColor">@color/car_body1</item>
-    </style>
-    <style name="TextAppearance.Car.Body1.Dark">
-        <item name="android:textColor">@color/car_body2_dark</item>
-    </style>
-    <style name="TextAppearance.Car.Body1.Light">
-        <item name="android:textColor">@color/car_body1_light</item>
-    </style>
-    <style name="TextAppearance.Car.Body2">
-        <item name="android:textStyle">normal</item>
-        <item name="android:textSize">@dimen/car_body2_size</item>
-        <item name="android:textColor">@color/car_body2</item>
-    </style>
-    <style name="TextAppearance.Car.Body2.Dark">
-        <item name="android:textColor">@color/car_body2_dark</item>
-    </style>
-    <style name="TextAppearance.Car.Body2.Light">
-        <item name="android:textColor">@color/car_body2_light</item>
-    </style>
-    <style name="TextAppearance.Car.Body3">
-        <item name="android:textStyle">normal</item>
-        <item name="android:textSize">@dimen/car_body3_size</item>
-        <item name="android:textColor">@color/car_body3</item>
-    </style>
-    <style name="TextAppearance.Car.Body4">
-        <item name="android:textStyle">normal</item>
-        <item name="android:textSize">@dimen/car_body4_size</item>
-        <item name="android:textColor">@color/car_body4</item>
-    </style>
-    <style name="TextAppearance.Car.Headline1">
-        <item name="android:textStyle">normal</item>
-        <item name="android:textSize">@dimen/car_headline1_size</item>
-        <item name="android:textColor">@color/car_headline1</item>
-    </style>
-    <style name="TextAppearance.Car.Headline1.Dark">
-        <item name="android:textColor">@color/car_headline1_dark</item>
-    </style>
-    <style name="TextAppearance.Car.Headline1.Light">
-        <item name="android:textColor">@color/car_headline1_light</item>
-    </style>
-    <style name="TextAppearance.Car.Headline2">
-        <item name="android:textStyle">normal</item>
-        <item name="android:textSize">@dimen/car_headline2_size</item>
-        <item name="android:textColor">@color/car_headline2</item>
-    </style>
-    <style name="TextAppearance.Car.Headline3">
-        <item name="android:textStyle">normal</item>
-        <item name="android:textSize">@dimen/car_headline3_size</item>
-        <item name="android:textColor">@color/car_headline3</item>
-    </style>
-    <style name="TextAppearance.Car.Headline4">
-        <item name="android:textStyle">normal</item>
-        <item name="android:textSize">@dimen/car_headline4_size</item>
-        <item name="android:textColor">@color/car_headline4</item>
-    </style>
-    <style name="TextAppearance.Car.Hint" parent="TextAppearance.Car.Body2"/>
-    <style name="TextAppearance.Car.Label1">
-        <item name="android:textStyle">normal</item>
-        <item name="android:textSize">@dimen/car_label1_size</item>
-        <item name="android:textColor">@color/car_label1</item>
-    </style>
-    <style name="TextAppearance.Car.Title">
-        <item name="android:fontFamily">sans-serif-medium</item>
-        <item name="android:textStyle">normal</item>
-        <item name="android:textSize">@dimen/car_title_size</item>
-        <item name="android:textColor">@color/car_title</item>
-    </style>
-    <style name="TextAppearance.Car.Title.Dark">
-        <item name="android:textColor">@color/car_title_dark</item>
-    </style>
-    <style name="TextAppearance.Car.Title.Light">
-        <item name="android:textColor">@color/car_title_light</item>
-    </style>
-    <style name="TextAppearance.Car.Title2">
-        <item name="android:fontFamily">sans-serif-medium</item>
-        <item name="android:textStyle">normal</item>
-        <item name="android:textSize">@dimen/car_title2_size</item>
-        <item name="android:textColor">@color/car_title2</item>
-    </style>
-    <style name="TextAppearance.Car.Title2.Dark">
-        <item name="android:textColor">@color/car_title2_dark</item>
-    </style>
-    <style name="TextAppearance.Car.Title2.Light">
-        <item name="android:textColor">@color/car_title2_light</item>
-    </style>
-    <style name="Theme.Car.Dark.Dialog" parent="Theme.Car.Dialog">
-        <item name="dialogButtonStyle">@style/Widget.Car.Button.Borderless.Colored</item>
-        <item name="dialogBackgroundColor">@color/car_card_dark</item>
-        <item name="dialogListTheme">@style/Theme.Car.Light.List.DarkItems</item>
-        <item name="dialogTitleStyle">@style/Widget.Car.Dialog.Title.Light</item>
-        <item name="dialogBodyStyle">@style/Widget.Car.Dialog.Body.Light</item>
-    </style>
-    <style name="Theme.Car.Dark.Dialog.Alert" parent="Theme.Car.Dialog.Alert">
-        <item name="android:background">@color/car_card_dark</item>
-        <item name="android:listDividerAlertDialog">@drawable/car_list_divider_light</item>
-        <item name="android:textColorPrimary">@color/car_body2_light</item>
-        <item name="android:windowTitleStyle">@style/Widget.Car.Dialog.Title.Light</item>
-    </style>
-    <style name="Theme.Car.Dark.NoActionBar" parent="Theme.Car.NoActionBar">
-        <item name="android:alertDialogTheme">@style/Theme.Car.Dark.Dialog.Alert</item>
-        <item name="alertDialogTheme">@style/Theme.Car.Dark.Dialog.Alert</item>
-        <item name="carDialogTheme">@style/Theme.Car.Dark.Dialog</item>
-        <item name="pagedListViewStyle">@style/Widget.Car.Light.List.LightDivider</item>
-        <item name="listItemStyle">@style/Widget.Car.ListItem.Dark</item>
-    </style>
-    <style name="Theme.Car.Dark.NoActionBar.Drawer">
-        <item name="drawerArrowStyle">@style/Widget.Car.DrawerArrowToggle</item>
-        <item name="drawerBackgroundColor">@color/car_card_dark</item>
-        <item name="drawerOpenHeaderColor">@color/car_title2_light</item>
-        <item name="drawerClosedHeaderColor">@color/car_title2_light</item>
-        <item name="drawerItemTitleTextAppearance">@style/TextAppearance.Car.Body1.Light</item>
-        <item name="drawerItemBodyTextAppearance">@style/TextAppearance.Car.Body2.Light</item>
-        <item name="drawerListStyle">@style/Widget.Car.Light.List.LightDivider</item>
-    </style>
-    <style name="Theme.Car.Dialog" parent="Theme.AppCompat.Dialog">
-        <item name="android:windowIsTranslucent">true</item>
-        <item name="android:windowBackground">@android:color/transparent</item>
-        <item name="dialogButtonStyle">@style/Widget.Car.Button.Borderless.Colored</item>
-        <item name="dialogBackgroundColor">@color/car_card</item>
-        <item name="dialogListTheme">@style/Theme.Car.List</item>
-        <item name="dialogTitleStyle">@style/Widget.Car.Dialog.Title</item>
-        <item name="dialogBodyStyle">@style/Widget.Car.Dialog.Body</item>
-    </style>
-    <style name="Theme.Car.Dialog.Alert" parent="Theme.AppCompat.Dialog.Alert">
-        <item name="android:background">@color/car_card</item>
-        <item name="android:borderlessButtonStyle">@style/Widget.Car.Button.Borderless.Colored</item>
-        <item name="android:colorButtonNormal">@color/car_accent</item>
-        <item name="android:listDividerAlertDialog">@drawable/car_list_divider</item>
-        <item name="android:textColorPrimary">@color/car_body2</item>
-        <item name="android:windowTitleStyle">@style/Widget.Car.Dialog.Title</item>
-        <item name="buttonBarNeutralButtonStyle">@style/Widget.Car.Button.Borderless.Colored</item>
-        <item name="buttonBarNegativeButtonStyle">@style/Widget.Car.Button.Borderless.Colored</item>
-        <item name="buttonBarPositiveButtonStyle">@style/Widget.Car.Button.Borderless.Colored</item>
-    </style>
-    <style name="Theme.Car.Light.Dialog.Alert" parent="Theme.Car.Dialog.Alert">
-        <item name="android:background">@color/car_card_light</item>
-        <item name="android:listDividerAlertDialog">@drawable/car_list_divider_dark</item>
-        <item name="android:textColorPrimary">@color/car_body2_dark</item>
-        <item name="android:windowTitleStyle">@style/Widget.Car.Dialog.Title.Dark</item>
-    </style>
-    <style name="Theme.Car.Light.List" parent="Theme.Car.List">
-        <item name="pagedListViewStyle">@style/Widget.Car.Light.List.LightDivider</item>
-    </style>
-    <style name="Theme.Car.Light.List.DarkItems">
-        <item name="listItemStyle">@style/Widget.Car.ListItem.Dark</item>
-    </style>
-    <style name="Theme.Car.Light.NoActionBar" parent="Theme.Car.NoActionBar"/>
-    <style name="Theme.Car.Light.NoActionBar.Drawer" parent="Theme.Car.NoActionBar.Drawer"/>
-    <style name="Theme.Car.List" parent="android:Theme">
-        <item name="pagedListViewStyle">@style/Widget.Car.List</item>
-        <item name="listItemStyle">@style/Widget.Car.ListItem</item>
-    </style>
-    <style name="Theme.Car.NoActionBar" parent="Theme.AppCompat.NoActionBar">
-        <item name="android:colorAccent">@color/car_accent</item>
-        <item name="android:colorButtonNormal">@color/car_accent</item>
-        <item name="android:buttonStyle">@style/Widget.Car.Button</item>
-        <item name="android:borderlessButtonStyle">@style/Widget.Car.Button.Borderless.Colored</item>
-        <item name="android:progressBarStyleHorizontal">@style/Widget.Car.ProgressBar.Horizontal</item>
-        <item name="android:textColorHint">@color/car_body2</item>
-        <item name="android:editTextStyle">@style/Widget.Car.EditText</item>
-        <item name="android:editTextColor">@color/car_body1</item>
-        <item name="android:colorControlNormal">@color/car_body2</item>
-        <item name="carDialogTheme">@style/Theme.Car.Dialog</item>
-        <item name="pagedListViewStyle">@style/Widget.Car.List</item>
-        <item name="listItemStyle">@style/Widget.Car.ListItem</item>
-    </style>
-    <style name="Theme.Car.NoActionBar.Drawer">
-        <item name="drawerArrowStyle">@style/Widget.Car.DrawerArrowToggle</item>
-        <item name="drawerBackgroundColor">@color/car_card</item>
-        <item name="drawerOpenHeaderColor">@color/car_title2</item>
-        <item name="drawerClosedHeaderColor">@color/car_title2_light</item>
-        <item name="drawerItemTitleTextAppearance">@style/TextAppearance.Car.Body1</item>
-        <item name="drawerItemBodyTextAppearance">@style/TextAppearance.Car.Body2</item>
-        <item name="drawerListStyle">@style/Widget.Car.List</item>
-    </style>
-    <style name="Widget.Car.Button" parent="Widget.AppCompat.Button">
-        <item name="android:fontFamily">sans-serif-medium</item>
-        <item name="android:layout_height">@dimen/car_button_height</item>
-        <item name="android:minWidth">@dimen/car_button_min_width</item>
-        <item name="android:paddingStart">@dimen/car_button_horizontal_padding</item>
-        <item name="android:paddingEnd">@dimen/car_button_horizontal_padding</item>
-        <item name="android:textSize">@dimen/car_action1_size</item>
-        <item name="android:background">@drawable/car_button_background</item>
-        <item name="android:textColor">@drawable/car_button_text_color</item>
-    </style>
-    <style name="Widget.Car.Button.ActionBar">
-        <item name="android:scaleType">fitCenter</item>
-        <item name="android:padding">@dimen/car_action_button_icon_inset</item>
-        <item name="android:background">@drawable/car_action_button_background</item>
-        <item name="android:tint">@color/car_tint</item>
-    </style>
-    <style name="Widget.Car.Button.Borderless.Colored" parent="Widget.AppCompat.Button.Borderless.Colored">
-        <item name="android:fontFamily">sans-serif-medium</item>
-        <item name="android:layout_height">@dimen/car_button_height</item>
-        <item name="android:minWidth">@dimen/car_button_min_width</item>
-        <item name="android:paddingStart">@dimen/car_borderless_button_horizontal_padding</item>
-        <item name="android:paddingEnd">@dimen/car_borderless_button_horizontal_padding</item>
-        <item name="android:textSize">@dimen/car_action1_size</item>
-        <item name="android:textColor">@drawable/car_borderless_button_text_color</item>
-    </style>
-    <style name="Widget.Car.Button.Borderless.Colored.Dark">
-        <item name="android:textColor">@drawable/car_borderless_button_text_color</item>
-    </style>
-    <style name="Widget.Car.Button.Borderless.Colored.Light">
-        <item name="android:textColor">@drawable/car_borderless_button_text_color</item>
-    </style>
-    <style name="Widget.Car.Dark.List" parent="Widget.Car.List">
-        <item name="dayNightStyle">force_day</item>
-    </style>
-    <style name="Widget.Car.Dark.List.LightDivider">
-        <item name="listDividerColor">@color/car_list_divider_light</item>
-    </style>
-    <style name="Widget.Car.Dialog" parent="android:Widget"/>
-    <style name="Widget.Car.Dialog.Body">
-        <item name="android:textAppearance">@style/TextAppearance.Car.Body2</item>
-    </style>
-    <style name="Widget.Car.Dialog.Body.Dark">
-        <item name="android:textAppearance">@style/TextAppearance.Car.Body2.Dark</item>
-    </style>
-    <style name="Widget.Car.Dialog.Body.Light">
-        <item name="android:textAppearance">@style/TextAppearance.Car.Body2.Light</item>
-    </style>
-    <style name="Widget.Car.Dialog.Title">
-        <item name="android:maxLines">1</item>
-        <item name="android:textAppearance">@style/TextAppearance.Car.Title2</item>
-        <item name="android:ellipsize">end</item>
-        <item name="android:textAlignment">viewStart</item>
-    </style>
-    <style name="Widget.Car.Dialog.Title.Dark">
-        <item name="android:textAppearance">@style/TextAppearance.Car.Title2.Dark</item>
-    </style>
-    <style name="Widget.Car.Dialog.Title.Light">
-        <item name="android:textAppearance">@style/TextAppearance.Car.Title2.Light</item>
-    </style>
-    <style name="Widget.Car.DrawerArrowToggle" parent="Widget.AppCompat.DrawerArrowToggle">
-        <item name="color">@color/car_title_light</item>
-        <item name="spinBars">true</item>
-        <item name="barLength">@dimen/car_menu_bar_length</item>
-        <item name="thickness">@dimen/car_arrow_thickness</item>
-        <item name="gapBetweenBars">@dimen/car_menu_bar_spacing</item>
-        <item name="arrowShaftLength">@dimen/car_arrow_shaft_length</item>
-        <item name="arrowHeadLength">@dimen/car_arrow_head_length</item>
-        <item name="drawableSize">@dimen/car_arrow_size</item>
-    </style>
-    <style name="Widget.Car.EditText" parent="Widget.AppCompat.EditText">
-        <item name="android:textColor">?attr/editTextColor</item>
-        <item name="android:textAppearance">@style/TextAppearance.Car.Body1</item>
-    </style>
-    <style name="Widget.Car.Light.List" parent="Widget.Car.List">
-        <item name="dayNightStyle">force_night</item>
-    </style>
-    <style name="Widget.Car.Light.List.LightDivider">
-        <item name="listDividerColor">@color/car_list_divider_light</item>
-    </style>
-    <style name="Widget.Car.List" parent="android:Widget">
-        <item name="dayNightStyle">auto</item>
-        <item name="listDividerColor">@color/car_list_divider</item>
-    </style>
-    <style name="Widget.Car.List.Inverse">
-        <item name="dayNightStyle">auto_inverse</item>
-        <item name="listDividerColor">@color/car_list_divider_inverse</item>
-    </style>
-    <style name="Widget.Car.ListItem" parent="android:Widget">
-        <item name="listItemBackgroundColor">@color/car_card</item>
-        <item name="listItemTitleTextAppearance">@style/TextAppearance.Car.Body1</item>
-        <item name="listItemBodyTextAppearance">@style/TextAppearance.Car.Body2</item>
-    </style>
-    <style name="Widget.Car.ListItem.Dark">
-        <item name="listItemBackgroundColor">@color/car_card_dark</item>
-        <item name="listItemTitleTextAppearance">@style/TextAppearance.Car.Body1.Light</item>
-        <item name="listItemBodyTextAppearance">@style/TextAppearance.Car.Body2.Light</item>
-    </style>
-    <style name="Widget.Car.ProgressBar.Horizontal" parent="Widget.AppCompat.ProgressBar.Horizontal">
-        <item name="android:minHeight">@dimen/car_progress_bar_height</item>
-        <item name="android:maxHeight">@dimen/car_progress_bar_height</item>
-    </style>
-    <style name="Widget.Car.SeekBar" parent="Widget.AppCompat.SeekBar">
-        <item name="android:progressDrawable">@drawable/car_seekbar_track</item>
-        <item name="android:thumb">@drawable/car_seekbar_thumb</item>
-    </style>
-    <style name="Widget.Car.Toolbar" parent="Widget.AppCompat.Toolbar">
-        <item name="titleTextAppearance">@style/TextAppearance.Car.Title.Light</item>
-        <item name="contentInsetStart">@dimen/car_keyline_1</item>
-        <item name="contentInsetEnd">@dimen/car_keyline_1</item>
-    </style>
-</resources>
\ No newline at end of file
diff --git a/androidx-car/Android.bp b/androidx-car/Android.bp
new file mode 100644
index 0000000..8d1eee6
--- /dev/null
+++ b/androidx-car/Android.bp
@@ -0,0 +1,46 @@
+//
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+android_library_import {
+    name: "androidx.car_car-resources-partially-dejetified-nodeps",
+    aars: ["androidx-car-resources.aar"],
+    sdk_version: "current",
+    static_libs: [
+        "com.google.android.material_material",
+        "androidx.appcompat_appcompat",
+        "androidx.cardview_cardview",
+        "androidx.recyclerview_recyclerview",
+        "androidx.gridlayout_gridlayout",
+        "androidx.preference_preference",
+        "androidx-constraintlayout_constraintlayout",
+    ],
+}
+android_library {
+    name: "androidx.car_car-resources-partially-dejetified",
+    sdk_version: "current",
+    min_sdk_version: "21",
+    manifest: "AndroidManifest.xml",
+    static_libs: [
+        "androidx.car_car-resources-partially-dejetified-nodeps",
+        "com.google.android.material_material",
+        "androidx.appcompat_appcompat",
+        "androidx.cardview_cardview",
+        "androidx.recyclerview_recyclerview",
+        "androidx.gridlayout_gridlayout",
+        "androidx.preference_preference",
+        "androidx-constraintlayout_constraintlayout",
+    ],
+    java_version: "1.7",
+}
diff --git a/androidx-car/AndroidManifest.xml b/androidx-car/AndroidManifest.xml
new file mode 100644
index 0000000..87ef2c9
--- /dev/null
+++ b/androidx-car/AndroidManifest.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="androidx.car" >
+
+    <uses-sdk
+        android:minSdkVersion="21"
+        android:targetSdkVersion="28" />
+
+</manifest>
diff --git a/androidx-car/androidx-car-resources.aar b/androidx-car/androidx-car-resources.aar
new file mode 100755
index 0000000..8f8aeaf
--- /dev/null
+++ b/androidx-car/androidx-car-resources.aar
Binary files differ
diff --git a/androidx-room/Android.bp b/androidx-room/Android.bp
deleted file mode 100644
index f9ac357..0000000
--- a/androidx-room/Android.bp
+++ /dev/null
@@ -1,56 +0,0 @@
-//
-// Copyright (C) 2019 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-java_plugin {
-    name: "car-androidx-room-compiler",
-    static_libs: [
-        "car-androidx-annotation-nodeps-bp",
-        "car-androidx-room-common-nodeps-bp",
-        "car-androidx-room-compiler-nodeps-bp",
-        "car-androidx-room-compiler-tools-common-m2-deps",
-        "car-androidx-room-migration-nodeps-bp",
-        "kotlin-stdlib",
-    ],
-    processor_class: "androidx.room.RoomProcessor",
-    generates_api: true,
-}
-
-android_library_import {
-    name: "car-androidx-room-runtime-nodeps-bp",
-    aars: ["androidx.room/room-runtime-2.0.0-alpha1.aar"],
-    sdk_version: "current",
-}
-
-java_import {
-    name: "car-androidx-room-common-nodeps-bp",
-    jars: ["androidx.room/room-common-2.0.0-alpha1.jar"],
-    host_supported: true,
-}
-
-java_import_host {
-    name: "car-androidx-room-compiler-nodeps-bp",
-    jars: ["androidx.room/room-compiler-2.0.0-alpha1.jar"],
-}
-
-java_import_host {
-    name: "car-androidx-room-migration-nodeps-bp",
-    jars: ["androidx.room/room-migration-2.0.0-alpha1.jar"],
-}
-
-java_import_host {
-    name: "car-androidx-annotation-nodeps-bp",
-    jars: ["annotation-1.0.0-alpha1.jar"],
-}
diff --git a/androidx-room/Android.mk b/androidx-room/Android.mk
deleted file mode 100644
index 675dac8..0000000
--- a/androidx-room/Android.mk
+++ /dev/null
@@ -1,43 +0,0 @@
-#
-# Copyright (C) 2019 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := \
-    car-androidx-room-runtime-nodeps:androidx.room/room-runtime-2.0.0-alpha1.aar \
-    car-androidx-room-common-nodeps:androidx.room/room-common-2.0.0-alpha1.jar
-
-include $(BUILD_MULTI_PREBUILT)
-
-include $(CLEAR_VARS)
-
-COMMON_LIBS_PATH := ../../../../../prebuilts/tools/common/m2/repository
-
-LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := \
-    car-androidx-room-common-nodeps:androidx.room/room-common-2.0.0-alpha1.jar \
-    car-androidx-room-compiler-nodeps:androidx.room/room-compiler-2.0.0-alpha1.jar \
-    car-androidx-room-migration-nodeps:androidx.room/room-migration-2.0.0-alpha1.jar \
-    car-androidx-annotation-nodeps:annotation-1.0.0-alpha1.jar \
-    car-antlr4-nodeps:$(COMMON_LIBS_PATH)/org/antlr/antlr4/4.5.3/antlr4-4.5.3.jar \
-    car-apache-commons-codec-nodeps:$(COMMON_LIBS_PATH)/org/eclipse/tycho/tycho-bundles-external/0.18.1/eclipse/plugins/org.apache.commons.codec_1.4.0.v201209201156.jar \
-    car-auto-common-nodeps:$(COMMON_LIBS_PATH)/com/google/auto/auto-common/0.9/auto-common-0.9.jar \
-    car-javapoet-nodeps:$(COMMON_LIBS_PATH)/com/squareup/javapoet/1.8.0/javapoet-1.8.0.jar \
-    car-jetbrains-annotations-nodeps:$(COMMON_LIBS_PATH)/org/jetbrains/annotations/13.0/annotations-13.0.jar \
-    car-kotlin-metadata-nodeps:$(COMMON_LIBS_PATH)/me/eugeniomarletti/kotlin-metadata/1.2.1/kotlin-metadata-1.2.1.jar \
-    car-sqlite-jdbc-nodeps:$(COMMON_LIBS_PATH)/org/xerial/sqlite-jdbc/3.20.1/sqlite-jdbc-3.20.1.jar
-
-include $(BUILD_HOST_PREBUILT)
diff --git a/androidx-room/androidx.room/room-common-2.0.0-alpha1.jar b/androidx-room/androidx.room/room-common-2.0.0-alpha1.jar
deleted file mode 100644
index 2c09fdf..0000000
--- a/androidx-room/androidx.room/room-common-2.0.0-alpha1.jar
+++ /dev/null
Binary files differ
diff --git a/androidx-room/androidx.room/room-compiler-2.0.0-alpha1.jar b/androidx-room/androidx.room/room-compiler-2.0.0-alpha1.jar
deleted file mode 100644
index a95872d..0000000
--- a/androidx-room/androidx.room/room-compiler-2.0.0-alpha1.jar
+++ /dev/null
Binary files differ
diff --git a/androidx-room/androidx.room/room-migration-2.0.0-alpha1.jar b/androidx-room/androidx.room/room-migration-2.0.0-alpha1.jar
deleted file mode 100644
index 4851df9..0000000
--- a/androidx-room/androidx.room/room-migration-2.0.0-alpha1.jar
+++ /dev/null
Binary files differ
diff --git a/androidx-room/androidx.room/room-runtime-2.0.0-alpha1.aar b/androidx-room/androidx.room/room-runtime-2.0.0-alpha1.aar
deleted file mode 100644
index ca797dd..0000000
--- a/androidx-room/androidx.room/room-runtime-2.0.0-alpha1.aar
+++ /dev/null
Binary files differ
diff --git a/androidx-room/annotation-1.0.0-alpha1.jar b/androidx-room/annotation-1.0.0-alpha1.jar
deleted file mode 100644
index 3bfd348..0000000
--- a/androidx-room/annotation-1.0.0-alpha1.jar
+++ /dev/null
Binary files differ
diff --git a/car-apps-common/Android.bp b/car-apps-common/Android.bp
index 8c52089..ef94de8 100644
--- a/car-apps-common/Android.bp
+++ b/car-apps-common/Android.bp
@@ -13,8 +13,9 @@
 // limitations under the License.
 //
 
+// Unbundled target (should stay that way).
 android_library {
-    name: "car-apps-common-bp",
+    name: "car-apps-common",
 
     srcs: ["src/**/*.java"],
 
@@ -24,7 +25,8 @@
         enabled: false,
     },
 
-    libs: ["android.car"],
+    libs: ["android.car-stubs"],
+    sdk_version: "system_current",
 
     static_libs: [
         "androidx.annotation_annotation",
@@ -35,5 +37,6 @@
         "androidx-constraintlayout_constraintlayout",
         "androidx.recyclerview_recyclerview",
         "androidx-constraintlayout_constraintlayout-solver",
+        "car-ui-lib",
     ],
 }
diff --git a/car-apps-common/Android.mk b/car-apps-common/Android.mk
deleted file mode 100644
index ce96f11..0000000
--- a/car-apps-common/Android.mk
+++ /dev/null
@@ -1,55 +0,0 @@
-#
-# Copyright (C) 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-
-LOCAL_MODULE := car-apps-common
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_PRIVILEGED_MODULE := true
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-LOCAL_USE_AAPT2 := true
-
-LOCAL_JAVA_LIBRARIES += android.car
-
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-
-LOCAL_STATIC_ANDROID_LIBRARIES += \
-    androidx.annotation_annotation \
-    androidx.cardview_cardview \
-    androidx.interpolator_interpolator \
-    androidx.lifecycle_lifecycle-common-java8 \
-    androidx.lifecycle_lifecycle-extensions \
-    androidx-constraintlayout_constraintlayout \
-    androidx.recyclerview_recyclerview
-
-LOCAL_STATIC_JAVA_LIBRARIES += \
-    androidx-constraintlayout_constraintlayout-solver
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
-ifeq (,$(ONE_SHOT_MAKEFILE))
-    include $(call all-makefiles-under,$(LOCAL_PATH))
-endif
diff --git a/car-apps-common/res/drawable-hdpi/ic_contact.png b/car-apps-common/res/drawable-hdpi/ic_contact.png
deleted file mode 100644
index c34e844..0000000
--- a/car-apps-common/res/drawable-hdpi/ic_contact.png
+++ /dev/null
Binary files differ
diff --git a/car-apps-common/res/drawable-ldrtl/background_image_scrim.xml b/car-apps-common/res/drawable-ldrtl/background_image_scrim.xml
new file mode 100644
index 0000000..9035a65
--- /dev/null
+++ b/car-apps-common/res/drawable-ldrtl/background_image_scrim.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2020 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <item>
+        <shape>
+            <gradient
+                android:angle="270"
+                android:startColor="#F5000000"
+                android:centerColor="@android:color/transparent"
+                android:endColor="#F5000000"/>
+        </shape>
+    </item>
+    <item>
+        <shape>
+            <gradient
+                android:angle="180"
+                android:centerX="0.52"
+                android:startColor="@android:color/transparent"
+                android:centerColor="@android:color/black"
+                android:endColor="@android:color/black" />
+        </shape>
+    </item>
+    <item>
+        <shape>
+            <gradient
+                android:angle="180"
+                android:centerX="0.62"
+                android:startColor="@android:color/transparent"
+                android:centerColor="#B3000000"
+                android:endColor="#B3000000" />
+        </shape>
+    </item>
+    <item>
+        <shape>
+            <solid android:color="@color/background_image_30p_black"/>
+        </shape>
+    </item>
+</layer-list>
diff --git a/car-apps-common/res/drawable-mdpi/ic_contact.png b/car-apps-common/res/drawable-mdpi/ic_contact.png
deleted file mode 100644
index 9461076..0000000
--- a/car-apps-common/res/drawable-mdpi/ic_contact.png
+++ /dev/null
Binary files differ
diff --git a/car-apps-common/res/drawable-xhdpi/ic_contact.png b/car-apps-common/res/drawable-xhdpi/ic_contact.png
deleted file mode 100644
index fec660d..0000000
--- a/car-apps-common/res/drawable-xhdpi/ic_contact.png
+++ /dev/null
Binary files differ
diff --git a/car-apps-common/res/drawable-xxhdpi/ic_contact.png b/car-apps-common/res/drawable-xxhdpi/ic_contact.png
deleted file mode 100644
index 199fd7b..0000000
--- a/car-apps-common/res/drawable-xxhdpi/ic_contact.png
+++ /dev/null
Binary files differ
diff --git a/car-apps-common/res/drawable/car_button_ripple_background.xml b/car-apps-common/res/drawable/car_button_ripple_background.xml
deleted file mode 100644
index 3975d12..0000000
--- a/car-apps-common/res/drawable/car_button_ripple_background.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2019 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-<ripple
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:color="@*android:color/car_card_ripple_background" />
diff --git a/car-apps-common/res/drawable/car_card_ripple_background.xml b/car-apps-common/res/drawable/car_card_ripple_background.xml
deleted file mode 100644
index 6b8a041..0000000
--- a/car-apps-common/res/drawable/car_card_ripple_background.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2019 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-<ripple
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:color="@*android:color/car_card_ripple_background">
-  <item
-      android:id="@android:id/mask"
-      android:drawable="@*android:color/white" />
-</ripple>
diff --git a/car-apps-common/res/drawable/car_scrollbar_thumb.xml b/car-apps-common/res/drawable/car_scrollbar_thumb.xml
deleted file mode 100644
index 0464f2f..0000000
--- a/car-apps-common/res/drawable/car_scrollbar_thumb.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2019 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License
-  -->
-
-<shape
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:shape="rectangle">
-  <solid android:color="@*android:color/car_scrollbar_thumb" />
-  <corners android:radius="@*android:dimen/car_radius_5"/>
-</shape>
diff --git a/car-apps-common/res/drawable/control_bar_button_background.xml b/car-apps-common/res/drawable/control_bar_button_background.xml
index 0412fd3..7009ecd 100644
--- a/car-apps-common/res/drawable/control_bar_button_background.xml
+++ b/car-apps-common/res/drawable/control_bar_button_background.xml
@@ -16,7 +16,15 @@
   ~ limitations under the License.
   ~
  -->
-<ripple xmlns:android="http://schemas.android.com/apk/res/android"
-        android:color="@color/control_bar_button_background_color"
-        android:radius="@dimen/control_bar_button_background_radius">
-</ripple>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_focused="true">
+        <ripple android:color="@color/car_ui_rotary_focus_color"
+                android:radius="@dimen/control_bar_button_background_radius">
+        </ripple>
+    </item>
+    <item>
+        <ripple android:color="@color/control_bar_button_background_color"
+                android:radius="@dimen/control_bar_button_background_radius">
+        </ripple>
+    </item>
+</selector>
diff --git a/car-apps-common/res/drawable/hero_button_background.xml b/car-apps-common/res/drawable/hero_button_background.xml
index 15e9b2a..88177cd 100644
--- a/car-apps-common/res/drawable/hero_button_background.xml
+++ b/car-apps-common/res/drawable/hero_button_background.xml
@@ -14,7 +14,7 @@
 limitations under the License.
 -->
 <ripple xmlns:android="http://schemas.android.com/apk/res/android"
-        android:color="@*android:color/car_card_ripple_background">
+        android:color="@color/car_card_ripple_background">
     <item>
         <shape android:shape="rectangle">
             <solid android:color="@color/hero_button_background_color" />
diff --git a/car-apps-common/res/layout-port/background_image.xml b/car-apps-common/res/layout-port/background_image.xml
index e7c547c..7e4ee8e 100644
--- a/car-apps-common/res/layout-port/background_image.xml
+++ b/car-apps-common/res/layout-port/background_image.xml
@@ -22,11 +22,11 @@
         android:id="@+id/background_image_image"
         android:layout_width="0dp"
         android:layout_height="0dp"
-        app:align_horizontal="left"
+        app:align_horizontal="start"
         app:layout_constraintTop_toTopOf="parent"
         app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintLeft_toLeftOf="parent"
-        app:layout_constraintRight_toRightOf="parent"/>
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"/>
 
     <View
         android:layout_width="0dp"
@@ -34,8 +34,8 @@
         android:background="@drawable/background_image_scrim"
         app:layout_constraintTop_toTopOf="parent"
         app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintLeft_toLeftOf="parent"
-        app:layout_constraintRight_toRightOf="parent"/>
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"/>
 
     <View
         android:id="@+id/background_image_darkening_scrim"
@@ -45,6 +45,6 @@
         android:visibility="gone"
         app:layout_constraintTop_toTopOf="parent"
         app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintLeft_toRightOf="parent"
-        app:layout_constraintRight_toRightOf="parent"/>
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"/>
 </merge>
diff --git a/car-apps-common/res/layout/background_image.xml b/car-apps-common/res/layout/background_image.xml
index f230600..bb889ea 100644
--- a/car-apps-common/res/layout/background_image.xml
+++ b/car-apps-common/res/layout/background_image.xml
@@ -29,11 +29,11 @@
         android:id="@+id/background_image_image"
         android:layout_width="0dp"
         android:layout_height="0dp"
-        app:align_horizontal="right"
+        app:align_horizontal="end"
         app:layout_constraintTop_toTopOf="parent"
         app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintLeft_toLeftOf="parent"
-        app:layout_constraintRight_toLeftOf="@+id/background_image_guideline"/>
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintEnd_toStartOf="@+id/background_image_guideline"/>
 
     <View
         android:layout_width="0dp"
@@ -41,8 +41,8 @@
         android:background="@drawable/background_image_scrim"
         app:layout_constraintTop_toTopOf="parent"
         app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintLeft_toLeftOf="parent"
-        app:layout_constraintRight_toRightOf="parent"/>
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"/>
 
     <View
         android:id="@+id/background_image_darkening_scrim"
@@ -52,6 +52,6 @@
         android:visibility="gone"
         app:layout_constraintTop_toTopOf="parent"
         app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintLeft_toRightOf="parent"
-        app:layout_constraintRight_toRightOf="parent"/>
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"/>
 </merge>
diff --git a/car-apps-common/res/layout/car_paged_scrollbar_buttons.xml b/car-apps-common/res/layout/car_paged_scrollbar_buttons.xml
deleted file mode 100644
index 4a0ccae..0000000
--- a/car-apps-common/res/layout/car_paged_scrollbar_buttons.xml
+++ /dev/null
@@ -1,53 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2019 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-<LinearLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:orientation="vertical"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:gravity="center">
-
-  <ImageButton
-      android:id="@+id/page_up"
-      android:layout_width="@dimen/car_scroll_bar_button_size"
-      android:layout_height="@dimen/car_scroll_bar_button_size"
-      android:background="@drawable/car_button_ripple_background"
-      android:contentDescription="@string/scroll_bar_page_up_button"
-      android:focusable="false"
-      android:hapticFeedbackEnabled="false"
-      android:src="@drawable/ic_up"
-      android:scaleType="centerInside" />
-
-  <!-- View height is dynamically calculated during layout. -->
-  <View
-      android:id="@+id/scrollbar_thumb"
-      android:layout_width="@dimen/car_scroll_bar_thumb_width"
-      android:layout_height="0dp"
-      android:layout_gravity="center_horizontal"
-      android:background="@drawable/car_scrollbar_thumb" />
-
-  <ImageButton
-      android:id="@+id/page_down"
-      android:layout_width="@dimen/car_scroll_bar_button_size"
-      android:layout_height="@dimen/car_scroll_bar_button_size"
-      android:background="@drawable/car_button_ripple_background"
-      android:contentDescription="@string/scroll_bar_page_down_button"
-      android:focusable="false"
-      android:hapticFeedbackEnabled="false"
-      android:src="@drawable/ic_down"
-      android:scaleType="centerInside" />
-</LinearLayout>
diff --git a/car-apps-common/res/layout/minimized_control_bar.xml b/car-apps-common/res/layout/minimized_control_bar.xml
index 814fe15..286af0f 100644
--- a/car-apps-common/res/layout/minimized_control_bar.xml
+++ b/car-apps-common/res/layout/minimized_control_bar.xml
@@ -28,7 +28,7 @@
         android:id="@+id/metadata_background"
         android:layout_width="0dp"
         android:layout_height="0dp"
-        android:background="@drawable/car_card_ripple_background"
+        android:background="?android:attr/selectableItemBackground"
         app:layout_constraintTop_toTopOf="parent"
         app:layout_constraintBottom_toBottomOf="parent"
         app:layout_constraintStart_toStartOf="parent"
diff --git a/car-apps-common/res/values-port/dimens.xml b/car-apps-common/res/values-port/dimens.xml
index c46b0b6..e7b2546 100644
--- a/car-apps-common/res/values-port/dimens.xml
+++ b/car-apps-common/res/values-port/dimens.xml
@@ -21,5 +21,5 @@
     <dimen name="car_tab_width">-2px</dimen>
 
     <!-- Control Bar - typically at the bottom of the application's space. -->
-    <dimen name="control_bar_margin_x">@*android:dimen/car_padding_5</dimen>
+    <dimen name="control_bar_margin_x">@dimen/car_ui_padding_5</dimen>
 </resources>
diff --git a/car-apps-common/res/values/attrs.xml b/car-apps-common/res/values/attrs.xml
index f99da29..0f953ee 100644
--- a/car-apps-common/res/values/attrs.xml
+++ b/car-apps-common/res/values/attrs.xml
@@ -37,57 +37,11 @@
         <attr name="textAppearanceGridItemSecondary" format="reference" />
     </declare-styleable>
 
-    <!-- Attributes for tab layout. -->
-    <declare-styleable name="CarTabLayout">
-        <attr name="tabPaddingX" format="reference|dimension"/>
-        <attr name="tabFlexibleLayout" format="reference|boolean"/>
-        <attr name="tabItemLayout" format="reference"/>
-    </declare-styleable>
-
-    <declare-styleable name="PagedRecyclerView">
-        <!-- Whether to include a gutter to the start, end or both sides of the list view items.
-             The gutter width will be the width of the scrollbar, and by default will be set to
-             both. -->
-        <attr name="gutter" format="enum">
-            <!-- No gutter on either side, the list view items will extend the full width of the
-                 PagedRecyclerView. -->
-            <enum name="none" value="0" />
-            <!-- Include a gutter on the start side only (i.e. the side with the scrollbar). -->
-            <enum name="start" value="1" />
-            <!-- Include a gutter on the end side only (i.e. the opposite side to the
-                 scrollbar). -->
-            <enum name="end" value="2" />
-            <!-- Include a gutter on both sides of the list view items. -->
-            <enum name="both" value="3" />
-        </attr>
-        <!-- Position of the scrollbar. Default to left. -->
-        <attr name="scrollBarPosition" format="enum">
-            <!-- Position scrollbar on the left side of the screen -->
-            <enum name="start" value="0" />
-            <!-- Position scrollbar on the right side of the screen -->
-            <enum name="end" value="1" />
-        </attr>
-        <!-- Whether to display the Scroll Bar or not. Defaults to true. If this is set to false,
-             the PagedRecyclerView will behave exactly like the RecyclerView. -->
-        <attr name="scrollBarEnabled" format="boolean" />
-        <!-- Whether to place the scrollbar z-index above the recycler view. Defaults to
-             true. -->
-        <attr name="scrollBarAboveRecyclerView" format="boolean" />
-        <!-- Width of the scrollbar container. -->
-        <attr name="scrollBarContainerWidth" format="dimension" />
-        <!-- Custom Scrollbar class path -->
-        <attr name="scrollBarCustomClass" format="string" />
-    </declare-styleable>
-
-    <declare-styleable name="PagedRecyclerViewTheme">
-        <attr name="pagedRecyclerViewStyle" format="reference" />
-    </declare-styleable>
-
     <declare-styleable name="CrossfadeImageView">
         <attr name="align_horizontal" format="enum">
             <enum name="center" value="0"/>
-            <enum name="left" value="1"/>
-            <enum name="right" value="2"/>
+            <enum name="start" value="1"/>
+            <enum name="end" value="2"/>
         </attr>
     </declare-styleable>
 
@@ -113,6 +67,16 @@
     <declare-styleable name="BackgroundImageView">
         <!-- Sets a scale to be applied on top of the scaling that was used to fit the image to the frame of the view. Defaults to 1.05 -->
         <attr name="imageAdditionalScale" format="float"/>
+
+        <!-- The layout to load as background. Defaults to R.layout.background_image. -->
+        <attr name="contentLayout" format="reference"/>
+
+        <!-- The strength of the blur. Defaults to R.dimen.background_bitmap_blur_percent. -->
+        <attr name="bitmap_blur_percent" format="float"/>
+
+        <!-- Size for the image. Defaults to R.integer.background_bitmap_target_size_px. -->
+        <attr name="bitmap_target_size_px" format="integer"/>
+
     </declare-styleable>
     <!-- Attribute for specifying a default style for all BackgroundImageViews -->
     <attr name="backgroundImageViewStyle" format="reference"/>
diff --git a/car-apps-common/res/values/colors.xml b/car-apps-common/res/values/colors.xml
index 37a7bda..6cf7ba7 100644
--- a/car-apps-common/res/values/colors.xml
+++ b/car-apps-common/res/values/colors.xml
@@ -34,14 +34,14 @@
         <item>#757575</item>
     </array>
 
-    <color name="loading_image_placeholder_color">@*android:color/car_grey_800</color>
+    <color name="loading_image_placeholder_color">@color/car_grey_800</color>
     <color name="improper_image_refs_tint_color">#C8FF0000</color>
 
     <color name="control_bar_background_color">@android:color/transparent</color>
     <color name="minimized_control_bar_background_color">#F50E1013</color>
     <color name="scrim_overlay_color">#C7000000</color>
     <color name="app_bar_background_color">#E0000000</color>
-    <color name="icon_tint">@*android:color/car_tint</color>
+    <color name="icon_tint">@color/car_grey_50</color>
 
     <color name="car_tab_selected_color">@color/car_tab_selected_color_light</color>
     <color name="car_tab_selected_color_dark">#E2FFFFFF</color>
@@ -55,8 +55,6 @@
 
     <color name="primary_app_icon_color">#FFFFFFFF</color>
     <color name="secondary_app_icon_color">#B8FFFFFF</color>
-    <color name="car_tint_inverse">@*android:color/car_tint_inverse</color>
-    <color name="car_scrollbar_thumb_inverse">@*android:color/car_scrollbar_thumb_dark</color>
     <color name="car_card_ripple_background">#17000000</color>
 
     <color name="background_image_30p_black">#4D000000</color>
@@ -68,6 +66,41 @@
 
     <color name="control_bar_button_background_color">#66ffffff</color>
 
-    <color name="hero_button_background_color">@*android:color/car_grey_868</color>
+    <color name="hero_button_background_color">@color/car_grey_868</color>
     <color name="hero_button_text_color">@color/uxr_button_text_color_selector</color>
+
+
+
+    <!--
+        Color palette for cars.
+        Those values are NOT part of the car-ui-lib "resource API", they are just constants used in
+        various places to give a default value to the attributes of the "api".
+     -->
+    <color name="car_grey_972">#ff090A0C</color>
+    <color name="car_grey_958">#ff0e1013</color>
+    <color name="car_grey_928">#ff17181b</color>
+    <color name="car_grey_900">#ff202124</color>
+    <color name="car_grey_868">#ff282a2d</color>
+    <color name="car_grey_846">#ff2e3234</color>
+    <color name="car_grey_800">#ff3c4043</color>
+    <color name="car_grey_772">#ff464a4d</color>
+    <color name="car_grey_746">#ff4d5256</color>
+    <color name="car_grey_700">#ff5f6368</color>
+    <color name="car_grey_600">#ff80868b</color>
+    <color name="car_grey_500">#ff9aa0a6</color>
+    <color name="car_grey_400">#ffbdc1c6</color>
+    <color name="car_grey_300">#ffdadce0</color>
+    <color name="car_grey_200">#ffe8eaed</color>
+    <color name="car_grey_100">#fff1f3f4</color>
+    <color name="car_grey_50">#fff8f9fa</color>
+
+    <color name="car_dark_blue_grey_700">#ff172026</color>
+
+    <color name="car_green_700">#ff218c48</color>
+    <color name="car_green_500">#ff41af6a</color>
+
+    <color name="car_red_500a">#ffd50000</color>
+
+    <!-- End color palette -->
+
 </resources>
diff --git a/car-apps-common/res/values/config.xml b/car-apps-common/res/values/config.xml
index f274eb8..eecb9ea 100644
--- a/car-apps-common/res/values/config.xml
+++ b/car-apps-common/res/values/config.xml
@@ -15,16 +15,6 @@
   ~ limitations under the License
   -->
 <resources>
-    <!--
-    Configuration for a default scrollbar for the PagedRecyclerView. This component must inherit
-    abstract class ScrollBarUI. If the ScrollBar is enabled, the component will be initialized from
-    PagedRecyclerView#createScrollBarFromConfig().
-    -->
-    <string name="config_scrollBarComponent" translatable="false">
-        com.android.car.apps.common.widget.CarScrollBar
-    </string>
-
-
     <!-- This value must remain false for production builds. It is intended to be overlaid in
         the simulator, so third party app developers can notice quickly that they are sending
         improper image references.
@@ -41,4 +31,18 @@
          1 (show one letter) or 0 (show avatar anonymous icon)
     -->
     <integer name="config_number_of_letters_shown_for_avatar">1</integer>
+
+    <!-- A default mask to apply to icons cropped via IconCropper. The mask is defined as
+     an SVG path in the range of [0..100, 0..100], it is automatically scaled to fit
+     the actual icon size, following the adaptive icon definition guideline:
+     https://source.android.com/devices/tech/display/adaptive-icons#implementation -->
+    <string name="config_crop_icon_mask" translatable="false">
+        M0,50 a50,50 0 1,0 100,0 a50,50 0 1,0 -100,0
+    </string>
+
+    <!-- String format used to format a address Uri. -->
+    <string name="config_address_uri_format" translatable="false">geo:0,0?q=%s</string>
+    <!-- String format used to format a navigation Uri. -->
+    <string name="config_navigation_uri_format" translatable="false">google.navigation:q=%s</string>
+
 </resources>
diff --git a/car-apps-common/res/values/dimens.xml b/car-apps-common/res/values/dimens.xml
index b1a51f5..85f6d90 100644
--- a/car-apps-common/res/values/dimens.xml
+++ b/car-apps-common/res/values/dimens.xml
@@ -20,12 +20,12 @@
     <dimen name="fab_focused_stroke_width">8dp</dimen>
     <dimen name="fab_focused_growth">1.2dp</dimen>
 
-    <dimen name="touch_target_size">@*android:dimen/car_touch_target_size</dimen>
+    <dimen name="touch_target_size">@dimen/car_ui_touch_target_size</dimen>
 
     <!-- Control Bar - typically at the bottom of the application's space. -->
     <dimen name="control_bar_height">128dp</dimen>
-    <dimen name="control_bar_margin_x">@*android:dimen/car_margin</dimen>
-    <dimen name="control_bar_margin_bottom">@*android:dimen/car_padding_2</dimen>
+    <dimen name="control_bar_margin_x">@dimen/car_ui_margin</dimen>
+    <dimen name="control_bar_margin_bottom">@dimen/car_ui_padding_2</dimen>
     <dimen name="control_bar_button_size">76dp</dimen>
     <dimen name="control_bar_button_slot_height">@dimen/control_bar_height</dimen>
     <dimen name="control_bar_button_slot_width">@dimen/control_bar_button_size</dimen>
@@ -43,9 +43,9 @@
     <dimen name="minimized_control_bar_radius">0dp</dimen>
     <dimen name="minimized_control_bar_margin_x">0dp</dimen>
     <dimen name="minimized_control_bar_margin_bottom">0dp</dimen>
-    <dimen name="minimized_control_bar_edge_padding">@*android:dimen/car_padding_4</dimen>
-    <dimen name="minimized_control_bar_text_padding">@*android:dimen/car_padding_3</dimen>
-    <dimen name="minimized_control_bar_button_padding">@*android:dimen/car_padding_5</dimen>
+    <dimen name="minimized_control_bar_edge_padding">@dimen/car_ui_padding_4</dimen>
+    <dimen name="minimized_control_bar_text_padding">@dimen/car_ui_padding_3</dimen>
+    <dimen name="minimized_control_bar_button_padding">@dimen/car_ui_padding_5</dimen>
     <dimen name="minimized_control_bar_button_size">76dp</dimen>
 
     <!-- Tabs -->
@@ -61,16 +61,6 @@
     <item name="letter_spacing_body2" format="float" type="dimen">0.0</item>
     <item name="letter_spacing_body3" format="float" type="dimen">0.0</item>
 
-    <!-- Default Scroll Bar for PagedRecyclerView -->
-    <dimen name="car_scroll_bar_button_size">@*android:dimen/car_touch_target_size</dimen>
-    <dimen name="car_scroll_bar_thumb_width">@*android:dimen/car_seekbar_height</dimen>
-    <dimen name="car_scroll_bar_separator_margin">@*android:dimen/car_padding_2</dimen>
-    <dimen name="car_scroll_bar_margin">@*android:dimen/car_margin</dimen>
-    <item name="button_disabled_alpha" format="float" type="dimen">0.2</item>
-    <item name="scroller_milliseconds_per_inch" format="float" type="dimen">150</item>
-    <item name="scroller_deceleration_time_divisor" format="float" type="dimen">0.45</item>
-    <item name="scroller_interpolator_factor" format="float" type="dimen">1.8</item>
-
     <!-- Target size for the background bitmap to blur (in pixels) -->
     <integer name="background_bitmap_target_size_px">64</integer>
     <!-- Value used to blur background images, the blur radius is P * (W + H)/2.
diff --git a/car-apps-common/res/values/id.xml b/car-apps-common/res/values/id.xml
index 82905b8..548e7cc 100644
--- a/car-apps-common/res/values/id.xml
+++ b/car-apps-common/res/values/id.xml
@@ -3,4 +3,6 @@
     <item type="id" name="imageDownloadTask"/>
     <item type="id" name="car_tab_item_icon"/>
     <item type="id" name="car_tab_item_text"/>
+    <item type="id" name="minimized_control_bar_content_tile"/>
+    <item type="id" name="art_background"/>
 </resources>
\ No newline at end of file
diff --git a/car-apps-common/res/values/styles.xml b/car-apps-common/res/values/styles.xml
index 6983bdc..3b5a5d6 100644
--- a/car-apps-common/res/values/styles.xml
+++ b/car-apps-common/res/values/styles.xml
@@ -29,6 +29,12 @@
         <item name="android:layout_height">@dimen/control_bar_button_size</item>
         <!-- This padding is used to force resizing of provided icons. -->
         <item name="android:padding">@dimen/control_bar_button_padding</item>
+        <!-- Added paddingStart/End explicitly to make sure style works regardless of whether -->
+        <!-- RTL is enabled or disabled. -->
+        <!-- Note: When RTL is enabled, paddingStart/End overrides value of padding, -->
+        <!-- while padding overrides value of paddingStart/End when RTL is disabled. -->
+        <item name="android:paddingStart">@dimen/control_bar_button_padding</item>
+        <item name="android:paddingEnd">@dimen/control_bar_button_padding</item>
         <!-- Note: fitCenter makes icons disappear if the view is too small... -->
         <item name="android:scaleType">fitCenter</item>
         <item name="android:layout_gravity">center</item>
@@ -69,6 +75,7 @@
     <style name="TextAppearance">
         <item name="android:fontFamily">roboto-regular</item>
         <item name="android:textColor">@color/primary_text_color</item>
+        <item name="android:textAlignment">viewStart</item>
     </style>
 
     <style name="TextAppearance.Display1" parent="TextAppearance">
@@ -101,12 +108,8 @@
         <item name="android:letterSpacing">@dimen/letter_spacing_body3</item>
     </style>
 
-    <style name="MinimizedControlBarTitle" parent="TextAppearance.Body1">
-        <item name="android:textDirection">locale</item>
-    </style>
-    <style name="MinimizedControlBarSubtitle" parent="TextAppearance.Body3">
-        <item name="android:textDirection">locale</item>
-    </style>
+    <style name="MinimizedControlBarTitle" parent="TextAppearance.Body1"/>
+    <style name="MinimizedControlBarSubtitle" parent="TextAppearance.Body3"/>
 
     <!-- Styles for ControlBar -->
     <style name="ControlBar">
@@ -119,14 +122,6 @@
         <item name="android:layout_height">@dimen/minimized_control_bar_height</item>
     </style>
 
-    <style name="PagedRecyclerView">
-        <item name="gutter">both</item>
-        <item name="scrollBarPosition">start</item>
-        <item name="scrollBarAboveRecyclerView">true</item>
-    </style>
-    <style name="PagedRecyclerView.NestedRecyclerView">
-    </style>
-
     <style name="FullScreenErrorMessageStyle">
         <item name="android:layout_width">wrap_content</item>
         <item name="android:layout_height">wrap_content</item>
diff --git a/car-apps-common/src/com/android/car/apps/common/AccountImageHelper.java b/car-apps-common/src/com/android/car/apps/common/AccountImageHelper.java
deleted file mode 100644
index 97286ce..0000000
--- a/car-apps-common/src/com/android/car/apps/common/AccountImageHelper.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.car.apps.common;
-
-import android.accounts.Account;
-import android.content.ContentUris;
-import android.content.Context;
-import android.content.Intent;
-import android.content.Intent.ShortcutIconResource;
-import android.database.Cursor;
-import android.net.Uri;
-import android.provider.ContactsContract;
-import android.provider.ContactsContract.RawContacts;
-import android.text.TextUtils;
-
-/**
- * Utility functions for retrieving account pictures.
- * @hide
- */
-public final class AccountImageHelper {
-
-    static final String[] CONTACT_PROJECTION_DATA = new String[] {
-        ContactsContract.Data._ID,
-        ContactsContract.Data.CONTACT_ID,
-        ContactsContract.Data.RAW_CONTACT_ID,
-        ContactsContract.Data.LOOKUP_KEY,
-        ContactsContract.Data.PHOTO_URI,
-        ContactsContract.Data.PHOTO_FILE_ID
-    };
-    static final String CONTACT_SELECTION =
-            ContactsContract.CommonDataKinds.Email.ADDRESS + " LIKE ?";
-
-    /**
-     * Non instantiable.
-     */
-    private AccountImageHelper() {
-    }
-
-    /**
-     * Tries to retrieve the Picture for the provided account, from the Contacts database.
-     */
-    public static String getAccountPictureUri(Context context, Account account) {
-        // Look up this account in the contacts database.
-
-        String[] selectionArgs = new String[] {
-        account.name };
-        Cursor c = null;
-        long contactId = -1;
-        String lookupKey = null;
-        String photoUri = null;
-        int photoFileId = 0;
-        long rawContactId = 0;
-        try {
-            c = context.getContentResolver().query(ContactsContract.Data.CONTENT_URI,
-                    CONTACT_PROJECTION_DATA, CONTACT_SELECTION, selectionArgs, null);
-            if (c.moveToNext()) {
-                contactId = c.getLong(1);
-                rawContactId = c.getLong(2);
-                lookupKey = c.getString(3);
-                photoUri = c.getString(4);
-                photoFileId = c.getInt(5);
-            }
-        } finally {
-            if (c != null) {
-                c.close();
-            }
-        }
-
-        if (contactId != -1 && !TextUtils.isEmpty(lookupKey) && !TextUtils.isEmpty(photoUri)) {
-            if (photoFileId == 0) {
-                // Trigger a VIEW action on this photo, which will force the Contacts
-                // Sync adapter to sync the HiRes version of the contact photo.
-                syncContactHiResPhoto(context, rawContactId);
-            }
-            return photoUri;
-        }
-        return getDefaultPictureUri(context);
-    }
-
-    private static void syncContactHiResPhoto(Context context, long rawContactId) {
-        final String serviceName = "com.google.android.syncadapters.contacts." +
-                "SyncHighResPhotoIntentService";
-        final String servicePackageName = "com.google.android.syncadapters.contacts";
-        final Uri uri = ContentUris.withAppendedId(RawContacts.CONTENT_URI,
-                rawContactId);
-        final Intent intent = new Intent();
-        intent.setClassName(servicePackageName, serviceName);
-        intent.setAction(Intent.ACTION_VIEW);
-        intent.setDataAndType(uri, RawContacts.CONTENT_ITEM_TYPE);
-        try {
-            context.startService(intent);
-        } catch (Exception e) {
-
-        }
-    }
-
-    /**
-     * Returns a default image to be used when an account has no picture associated with it.
-     */
-    public static String getDefaultPictureUri(Context context) {
-        // TODO: get a better default image.
-        ShortcutIconResource iconResource = new ShortcutIconResource();
-        iconResource.packageName = context.getPackageName();
-        iconResource.resourceName = context.getResources().getResourceName(
-                R.drawable.ic_contact);
-        return UriUtils.getShortcutIconResourceUri(iconResource).toString();
-    }
-}
diff --git a/car-apps-common/src/com/android/car/apps/common/BackgroundImageView.java b/car-apps-common/src/com/android/car/apps/common/BackgroundImageView.java
index 043f41a..b6555b4 100644
--- a/car-apps-common/src/com/android/car/apps/common/BackgroundImageView.java
+++ b/car-apps-common/src/com/android/car/apps/common/BackgroundImageView.java
@@ -52,24 +52,30 @@
     public BackgroundImageView(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
 
-        inflate(getContext(), R.layout.background_image, this);
+        float extraScale;
+        int resId;
+        TypedArray a = context.getTheme().obtainStyledAttributes(attrs,
+                R.styleable.BackgroundImageView, defStyle, 0);
+        try {
+            extraScale = a.getFloat(R.styleable.BackgroundImageView_imageAdditionalScale, 1.05f);
+            resId = a.getResourceId(R.styleable.BackgroundImageView_contentLayout,
+                    R.layout.background_image);
+            mBitmapBlurPercent = a.getFloat(R.styleable.BackgroundImageView_bitmap_blur_percent,
+                    getResources().getFloat(R.dimen.background_bitmap_blur_percent));
+
+            int size = a.getInteger(R.styleable.BackgroundImageView_bitmap_target_size_px,
+                    getResources().getInteger(R.integer.background_bitmap_target_size_px));
+            mBitmapTargetSize = new Size(size, size);
+        } finally {
+            a.recycle();
+        }
+
+        inflate(getContext(), resId, this);
 
         mImageView = findViewById(R.id.background_image_image);
         mDarkeningScrim = findViewById(R.id.background_image_darkening_scrim);
 
-        int size = getResources().getInteger(R.integer.background_bitmap_target_size_px);
-        mBitmapTargetSize = new Size(size, size);
-        mBitmapBlurPercent = getResources().getFloat(R.dimen.background_bitmap_blur_percent);
-
-        TypedArray a = context.getTheme().obtainStyledAttributes(attrs,
-                R.styleable.BackgroundImageView, defStyle, 0);
-
-        try {
-            setImageAdditionalScale(a.getFloat(R.styleable.BackgroundImageView_imageAdditionalScale,
-                    1.05f));
-        } finally {
-            a.recycle();
-        }
+        setImageAdditionalScale(extraScale);
     }
 
     /**
diff --git a/car-apps-common/src/com/android/car/apps/common/BitmapUtils.java b/car-apps-common/src/com/android/car/apps/common/BitmapUtils.java
index 08b5dd1..bd96ee5 100644
--- a/car-apps-common/src/com/android/car/apps/common/BitmapUtils.java
+++ b/car-apps-common/src/com/android/car/apps/common/BitmapUtils.java
@@ -17,9 +17,6 @@
 
 import static android.graphics.Bitmap.Config.ARGB_8888;
 
-import android.annotation.ColorInt;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
 import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
@@ -32,6 +29,10 @@
 import android.util.Log;
 import android.util.Size;
 
+import androidx.annotation.ColorInt;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
 public class BitmapUtils {
     private static final String TAG = "BitmapUtils";
 
diff --git a/car-apps-common/src/com/android/car/apps/common/CarUxRestrictionsUtil.java b/car-apps-common/src/com/android/car/apps/common/CarUxRestrictionsUtil.java
deleted file mode 100644
index 219bf59..0000000
--- a/car-apps-common/src/com/android/car/apps/common/CarUxRestrictionsUtil.java
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.car.apps.common;
-
-import static android.car.drivingstate.CarUxRestrictions.UX_RESTRICTIONS_LIMIT_STRING_LENGTH;
-
-import android.car.Car;
-import android.car.CarNotConnectedException;
-import android.car.drivingstate.CarUxRestrictions;
-import android.car.drivingstate.CarUxRestrictions.CarUxRestrictionsInfo;
-import android.car.drivingstate.CarUxRestrictionsManager;
-import android.content.Context;
-import android.util.Log;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import java.util.Collections;
-import java.util.Set;
-import java.util.WeakHashMap;
-
-/**
- * Utility class to access Car Restriction Manager.
- *
- * This class must be a singleton because only one listener can be registered with
- * {@link CarUxRestrictionsManager} at a time, as documented in
- * {@link CarUxRestrictionsManager#registerListener}.
- *
- * @deprecated Use {@link com.android.car.ui.utils.CarUxRestrictionsUtil} instead
- */
-public class CarUxRestrictionsUtil {
-    private static final String TAG = "CarUxRestrictionsUtil";
-
-    private final Car mCarApi;
-    private CarUxRestrictionsManager mCarUxRestrictionsManager;
-    @NonNull
-    private CarUxRestrictions mCarUxRestrictions = getDefaultRestrictions();
-
-    private Set<OnUxRestrictionsChangedListener> mObservers;
-    private static CarUxRestrictionsUtil sInstance = null;
-
-    private CarUxRestrictionsUtil(Context context) {
-        CarUxRestrictionsManager.OnUxRestrictionsChangedListener listener = (carUxRestrictions) -> {
-            if (carUxRestrictions == null) {
-                mCarUxRestrictions = getDefaultRestrictions();
-            } else {
-                mCarUxRestrictions = carUxRestrictions;
-            }
-
-            for (OnUxRestrictionsChangedListener observer : mObservers) {
-                observer.onRestrictionsChanged(mCarUxRestrictions);
-            }
-        };
-
-        mCarApi = Car.createCar(context.getApplicationContext());
-        mObservers = Collections.newSetFromMap(new WeakHashMap<>());
-
-        try {
-            mCarUxRestrictionsManager = (CarUxRestrictionsManager) mCarApi
-                    .getCarManager(Car.CAR_UX_RESTRICTION_SERVICE);
-            mCarUxRestrictionsManager.registerListener(listener);
-            listener.onUxRestrictionsChanged(
-                    mCarUxRestrictionsManager.getCurrentCarUxRestrictions());
-        } catch (CarNotConnectedException e) {
-            Log.e(TAG, "Car not connected", e);
-            // mCarUxRestrictions will be the default
-        } catch (NullPointerException e) {
-            Log.e(TAG, "Car not connected", e);
-            // mCarUxRestrictions will be the default
-        }
-    }
-
-    @NonNull
-    private CarUxRestrictions getDefaultRestrictions() {
-        return new CarUxRestrictions.Builder(true,
-                CarUxRestrictions.UX_RESTRICTIONS_FULLY_RESTRICTED, 0).build();
-    }
-
-    /**
-     * Listener interface used to update clients on UxRestrictions changes
-     */
-    public interface OnUxRestrictionsChangedListener {
-        /**
-         * Called when CarUxRestrictions changes
-         */
-        void onRestrictionsChanged(@NonNull CarUxRestrictions carUxRestrictions);
-    }
-
-    /**
-     * Returns the singleton instance of this class
-     */
-    @NonNull
-    public static CarUxRestrictionsUtil getInstance(Context context) {
-        if (sInstance == null) {
-            sInstance = new CarUxRestrictionsUtil(context);
-        }
-
-        return sInstance;
-    }
-
-    /**
-     * Registers a listener on this class for updates to CarUxRestrictions.
-     * Multiple listeners may be registered.
-     */
-    public void register(OnUxRestrictionsChangedListener listener) {
-        mObservers.add(listener);
-        listener.onRestrictionsChanged(mCarUxRestrictions);
-    }
-
-    /**
-     * Unregisters a registered listener
-     */
-    public void unregister(OnUxRestrictionsChangedListener listener) {
-        mObservers.remove(listener);
-    }
-
-    /**
-     * Returns whether any of the given flags is blocked by the current restrictions. If null is
-     * given, the method returns true for safety.
-     */
-    public static boolean isRestricted(@CarUxRestrictionsInfo int restrictionFlags,
-            @Nullable CarUxRestrictions uxr) {
-        return (uxr == null) || ((uxr.getActiveRestrictions() & restrictionFlags) != 0);
-    }
-
-    /**
-     * Complies the input string with the given UX restrictions.
-     * Returns the original string if already compliant, otherwise a shortened ellipsized string.
-     */
-    public static String complyString(Context context, String str, CarUxRestrictions uxr) {
-
-        if (isRestricted(UX_RESTRICTIONS_LIMIT_STRING_LENGTH, uxr)) {
-            int maxLength = uxr == null
-                    ? context.getResources().getInteger(R.integer.default_max_string_length)
-                    : uxr.getMaxRestrictedStringLength();
-
-            if (str.length() > maxLength) {
-                return str.substring(0, maxLength) + context.getString(R.string.ellipsis);
-            }
-        }
-
-        return str;
-    }
-}
diff --git a/car-apps-common/src/com/android/car/apps/common/ClickThroughToolbar.java b/car-apps-common/src/com/android/car/apps/common/ClickThroughToolbar.java
deleted file mode 100644
index 7e5b79c..0000000
--- a/car-apps-common/src/com/android/car/apps/common/ClickThroughToolbar.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.car.apps.common;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.util.AttributeSet;
-import android.view.MotionEvent;
-import android.widget.Toolbar;
-
-/**
- * A toolbar that optionally supports allowing clicks on it to pass through to any underlying views.
- *
- * <p>By default, the {@link Toolbar} eats all touches on it. This view will override
- * {@link #onTouchEvent(MotionEvent)} and return {@code false} if configured to allow pass through.
- *
- * @deprecated Use {@link com.android.car.ui.toolbar.Toolbar} instead
- */
-@Deprecated
-public class ClickThroughToolbar extends Toolbar {
-    private boolean mAllowClickPassThrough;
-
-    public ClickThroughToolbar(Context context) {
-        super(context);
-    }
-
-    public ClickThroughToolbar(Context context, AttributeSet attrs) {
-        super(context, attrs);
-        initAttributes(context, attrs, 0 /* defStyleAttrs */);
-    }
-
-    public ClickThroughToolbar(Context context, AttributeSet attrs, int defStyleAttrs) {
-        super(context, attrs, defStyleAttrs);
-        initAttributes(context, attrs, defStyleAttrs);
-    }
-
-    private void initAttributes(Context context, AttributeSet attrs, int defStyleAttrs) {
-        TypedArray a = context.obtainStyledAttributes(
-                attrs, R.styleable.ClickThroughToolbar, defStyleAttrs, 0 /* defStyleRes */);
-
-        mAllowClickPassThrough = a.getBoolean(R.styleable.ClickThroughToolbar_clickThrough, false);
-
-        a.recycle();
-    }
-
-    /**
-     * Whether or not clicks on this toolbar will pass through to any views that are underneath
-     * it. By default, this value is {@code false}.
-     *
-     * @param allowPassThrough {@code true} if clicks will pass through to an underlying view;
-     *                         {@code false} otherwise.
-     */
-    public void setClickPassThrough(boolean allowPassThrough) {
-        mAllowClickPassThrough = allowPassThrough;
-    }
-
-    @Override
-    public boolean onTouchEvent(MotionEvent ev) {
-        if (mAllowClickPassThrough) {
-            return false;
-        }
-
-        return super.onTouchEvent(ev);
-    }
-}
diff --git a/car-apps-common/src/com/android/car/apps/common/CommonFlags.java b/car-apps-common/src/com/android/car/apps/common/CommonFlags.java
index 5fbc4a0..f70d296 100644
--- a/car-apps-common/src/com/android/car/apps/common/CommonFlags.java
+++ b/car-apps-common/src/com/android/car/apps/common/CommonFlags.java
@@ -17,11 +17,12 @@
 package com.android.car.apps.common;
 
 
-import android.annotation.NonNull;
 import android.content.Context;
 import android.content.res.Resources;
 import android.os.SystemProperties;
 
+import androidx.annotation.NonNull;
+
 /** Singleton class regrouping common library feature flags. */
 public class CommonFlags {
 
diff --git a/car-apps-common/src/com/android/car/apps/common/ControlBar.java b/car-apps-common/src/com/android/car/apps/common/ControlBar.java
index 3ed7331..5d6d76c 100644
--- a/car-apps-common/src/com/android/car/apps/common/ControlBar.java
+++ b/car-apps-common/src/com/android/car/apps/common/ControlBar.java
@@ -38,10 +38,9 @@
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
+import androidx.core.util.Preconditions;
 import androidx.interpolator.view.animation.FastOutSlowInInterpolator;
 
-import com.android.internal.util.Preconditions;
-
 import java.util.Locale;
 
 
@@ -292,8 +291,12 @@
     }
 
     private void setView(@Nullable View view, FrameLayout container) {
-        container.removeAllViews();
         if (view != null) {
+            // Don't set the view if it stays the same.
+            if (container.getChildCount() == 1 && container.getChildAt(0) == view) {
+                return;
+            }
+
             ViewGroup parent = (ViewGroup) view.getParent();
             // As we are removing views (on BT disconnect, for example), some items will be
             // shifting from expanded to collapsed (like Queue item) - remove those from the
@@ -301,9 +304,13 @@
             if (view.getParent() != null) {
                 parent.removeView(view);
             }
+            container.removeAllViews();
             container.addView(view);
             container.setVisibility(VISIBLE);
         } else {
+            if (container.getChildCount() != 0) {
+                container.removeAllViews();
+            }
             container.setVisibility(INVISIBLE);
         }
     }
diff --git a/car-apps-common/src/com/android/car/apps/common/CropAlignedImageView.java b/car-apps-common/src/com/android/car/apps/common/CropAlignedImageView.java
index f11f33b..0adbcf6 100644
--- a/car-apps-common/src/com/android/car/apps/common/CropAlignedImageView.java
+++ b/car-apps-common/src/com/android/car/apps/common/CropAlignedImageView.java
@@ -19,9 +19,13 @@
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.graphics.Matrix;
+import android.text.TextUtils;
 import android.util.AttributeSet;
+import android.view.View;
 import android.widget.ImageView;
 
+import java.util.Locale;
+
 /**
  * A {@link ImageView} that scales in a similar way as {@link ScaleType#CENTER_CROP} but aligning
  * the image to the specified edge of the view.
@@ -29,8 +33,8 @@
 public class CropAlignedImageView extends ImageView {
 
     private static final int ALIGN_HORIZONTAL_CENTER = 0;
-    private static final int ALIGN_HORIZONTAL_LEFT = 1;
-    private static final int ALIGN_HORIZONTAL_RIGHT = 2;
+    private static final int ALIGN_HORIZONTAL_START = 1;
+    private static final int ALIGN_HORIZONTAL_END = 2;
 
     private int mAlignHorizontal;
     private float mAdditionalScale = 1f;
@@ -82,6 +86,8 @@
             float fitHorizontallyScaleFactor = mFrameWidth / originalImageWidth;
             float fitVerticallyScaleFactor = mFrameHeight / originalImageHeight;
             float usedScaleFactor = Math.max(fitHorizontallyScaleFactor, fitVerticallyScaleFactor);
+            int layoutDirection = TextUtils.getLayoutDirectionFromLocale(Locale.getDefault());
+            boolean isRTL = layoutDirection == View.LAYOUT_DIRECTION_RTL;
 
             // mAdditionalScale isn't factored into the fittedImageWidth
             // because we want to scale from the center of the fitted image, so our translations
@@ -97,11 +103,11 @@
                 case ALIGN_HORIZONTAL_CENTER:
                     dx = mFrameWidth / 2f;
                     break;
-                case ALIGN_HORIZONTAL_LEFT:
-                    dx = fittedImageWidth / 2f;
+                case ALIGN_HORIZONTAL_START:
+                    dx = isRTL ? (mFrameWidth - fittedImageWidth / 2f) : fittedImageWidth / 2f;
                     break;
-                case ALIGN_HORIZONTAL_RIGHT:
-                    dx = (mFrameWidth - fittedImageWidth / 2f);
+                case ALIGN_HORIZONTAL_END:
+                    dx = isRTL ? fittedImageWidth / 2f : (mFrameWidth - fittedImageWidth / 2f);
                     break;
             }
             matrix.postTranslate(dx, mFrameHeight / 2f);
diff --git a/car-apps-common/src/com/android/car/apps/common/IconCropper.java b/car-apps-common/src/com/android/car/apps/common/IconCropper.java
new file mode 100644
index 0000000..49d4abc
--- /dev/null
+++ b/car-apps-common/src/com/android/car/apps/common/IconCropper.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.car.apps.common;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Bitmap.Config;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffXfermode;
+import android.graphics.drawable.Drawable;
+
+import androidx.annotation.NonNull;
+import androidx.core.graphics.PathParser;
+
+/** A helper to crop icons to a shape using a given or the default path. */
+public final class IconCropper {
+    private static final float ICON_MASK_SIZE = 100.0f;
+
+    @NonNull
+    private final Path mIconMask;
+
+    /** Sets up the icon cropper with the given icon mask. */
+    public IconCropper(@NonNull Path iconMask) {
+        mIconMask = iconMask;
+    }
+
+    /**
+     * Sets up the icon cropper instance with the default crop mask.
+     *
+     * The SVG path mask is read from the {@code R.string.config_crop_icon_mask} resource value.
+     */
+    public IconCropper(@NonNull Context context) {
+        this(getDefaultMask(context));
+    }
+
+    private static Path getDefaultMask(@NonNull Context context) {
+        return PathParser.createPathFromPathData(
+                context.getString(R.string.config_crop_icon_mask));
+    }
+
+    /** Crops the given drawable according to the current object settings. */
+    @NonNull
+    public Bitmap crop(@NonNull Drawable source) {
+        return crop(BitmapUtils.fromDrawable(source, null));
+    }
+
+    /** Crops the given bitmap according to the current object settings. */
+    @NonNull
+    public Bitmap crop(@NonNull Bitmap icon) {
+        int width = icon.getWidth();
+        int height = icon.getHeight();
+
+        Bitmap output = Bitmap.createBitmap(width, height, Config.ARGB_8888);
+        Canvas canvas = new Canvas(output);
+
+        Paint paint = new Paint();
+        paint.setAntiAlias(true);
+        // Note: only alpha component of the color set below matters, since we
+        // overlay the mask using PorterDuff.Mode.SRC_IN mode (more details here:
+        // https://d.android.com/reference/android/graphics/PorterDuff.Mode).
+        paint.setColor(Color.WHITE);
+
+        canvas.save();
+        canvas.scale(width / ICON_MASK_SIZE, height / ICON_MASK_SIZE);
+        canvas.drawPath(mIconMask, paint);
+        canvas.restore();
+
+        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
+        canvas.drawBitmap(icon, 0, 0, paint);
+
+        return output;
+    }
+}
diff --git a/car-apps-common/src/com/android/car/apps/common/ImageUtils.java b/car-apps-common/src/com/android/car/apps/common/ImageUtils.java
index e110e76..cfdbe57 100644
--- a/car-apps-common/src/com/android/car/apps/common/ImageUtils.java
+++ b/car-apps-common/src/com/android/car/apps/common/ImageUtils.java
@@ -16,7 +16,6 @@
 
 package com.android.car.apps.common;
 
-import android.annotation.NonNull;
 import android.content.Context;
 import android.graphics.Bitmap;
 import android.renderscript.Allocation;
@@ -25,6 +24,8 @@
 import android.renderscript.ScriptIntrinsicBlur;
 import android.util.Size;
 
+import androidx.annotation.NonNull;
+
 /**
  * Utility methods to manipulate images.
  */
diff --git a/car-apps-common/src/com/android/car/apps/common/NavigationUtils.java b/car-apps-common/src/com/android/car/apps/common/NavigationUtils.java
new file mode 100644
index 0000000..aa0171e
--- /dev/null
+++ b/car-apps-common/src/com/android/car/apps/common/NavigationUtils.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.car.apps.common;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.net.Uri;
+
+/**
+ * Helper methods for addresses and navigation.
+ */
+public class NavigationUtils {
+
+    /**
+     * Returns the search location intent.
+     *
+     * @param address should be a location as either a place name or address.
+     */
+    public static Intent getViewAddressIntent(Resources res, String address) {
+        String formattedAddress = String.format(res.getString(R.string.config_address_uri_format),
+                Uri.encode(address));
+        Uri addressUri = Uri.parse(formattedAddress);
+        return new Intent(Intent.ACTION_VIEW, addressUri);
+    }
+
+    /**
+     * Returns the search location intent.
+     *
+     * @param address should be a location as either a place name or address.
+     */
+    public static Intent getViewAddressIntent(Context context, String address) {
+        Resources resources = context.getResources();
+        return getViewAddressIntent(resources, address);
+    }
+
+    /**
+     * Returns the navigation intent.
+     *
+     * @param address should be a location as either a place name or address.
+     */
+    public static Intent getNavigationIntent(Resources res, String address) {
+        String formattedAddress = String.format(
+                res.getString(R.string.config_navigation_uri_format), Uri.encode(address));
+        Uri addressUri = Uri.parse(formattedAddress);
+        return new Intent(Intent.ACTION_VIEW, addressUri);
+    }
+
+    /**
+     * Returns the navigation Intent.
+     *
+     * @param address should be a location as either a place name or address.
+     */
+    public static Intent getNavigationIntent(Context context, String address) {
+        Resources resources = context.getResources();
+        return getNavigationIntent(resources, address);
+    }
+}
diff --git a/car-apps-common/src/com/android/car/apps/common/UxrButton.java b/car-apps-common/src/com/android/car/apps/common/UxrButton.java
index aae5aa3..0da6056 100644
--- a/car-apps-common/src/com/android/car/apps/common/UxrButton.java
+++ b/car-apps-common/src/com/android/car/apps/common/UxrButton.java
@@ -16,7 +16,6 @@
 
 package com.android.car.apps.common;
 
-import android.annotation.Nullable;
 import android.car.drivingstate.CarUxRestrictions;
 import android.content.Context;
 import android.content.res.TypedArray;
@@ -26,6 +25,10 @@
 import android.widget.TextView;
 import android.widget.Toast;
 
+import androidx.annotation.Nullable;
+
+import com.android.car.ui.utils.CarUxRestrictionsUtil;
+
 /**
  * UX Restrictions compliant Button.
  * This class will automatically listen to Car UXRestrictions, and respond to click event
diff --git a/car-apps-common/src/com/android/car/apps/common/UxrTextView.java b/car-apps-common/src/com/android/car/apps/common/UxrTextView.java
index c84d158..10c92c4 100644
--- a/car-apps-common/src/com/android/car/apps/common/UxrTextView.java
+++ b/car-apps-common/src/com/android/car/apps/common/UxrTextView.java
@@ -24,6 +24,8 @@
 import android.view.View;
 import android.widget.TextView;
 
+import com.android.car.ui.utils.CarUxRestrictionsUtil;
+
 /**
  * UX Restrictions compliant TextView.
  * This class will automatically listen to Car UXRestrictions and truncate text accordingly.
diff --git a/car-apps-common/src/com/android/car/apps/common/imaging/ImageBinder.java b/car-apps-common/src/com/android/car/apps/common/imaging/ImageBinder.java
index f640218..6270a89 100644
--- a/car-apps-common/src/com/android/car/apps/common/imaging/ImageBinder.java
+++ b/car-apps-common/src/com/android/car/apps/common/imaging/ImageBinder.java
@@ -17,16 +17,17 @@
 package com.android.car.apps.common.imaging;
 
 
-import static com.android.internal.util.Preconditions.checkNotNull;
+import static androidx.core.util.Preconditions.checkNotNull;
 
-import android.annotation.NonNull;
-import android.annotation.Nullable;
 import android.content.Context;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.util.Size;
 
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
 import com.android.car.apps.common.R;
 import com.android.car.apps.common.UriUtils;
 
diff --git a/car-apps-common/src/com/android/car/apps/common/imaging/ImageKey.java b/car-apps-common/src/com/android/car/apps/common/imaging/ImageKey.java
index 464d974..2682cb0 100644
--- a/car-apps-common/src/com/android/car/apps/common/imaging/ImageKey.java
+++ b/car-apps-common/src/com/android/car/apps/common/imaging/ImageKey.java
@@ -19,8 +19,9 @@
 import android.net.Uri;
 import android.util.Size;
 
+import androidx.core.util.Preconditions;
+
 import com.android.car.apps.common.UriUtils;
-import com.android.internal.util.Preconditions;
 
 import java.util.Objects;
 
diff --git a/car-apps-common/src/com/android/car/apps/common/imaging/ImageViewBinder.java b/car-apps-common/src/com/android/car/apps/common/imaging/ImageViewBinder.java
index ee50b72..896d5af 100644
--- a/car-apps-common/src/com/android/car/apps/common/imaging/ImageViewBinder.java
+++ b/car-apps-common/src/com/android/car/apps/common/imaging/ImageViewBinder.java
@@ -16,13 +16,14 @@
 
 package com.android.car.apps.common.imaging;
 
-import android.annotation.Nullable;
 import android.content.Context;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.util.Size;
 import android.widget.ImageView;
 
+import androidx.annotation.Nullable;
+
 import com.android.car.apps.common.CommonFlags;
 import com.android.car.apps.common.R;
 
diff --git a/car-apps-common/src/com/android/car/apps/common/imaging/LocalImageFetcher.java b/car-apps-common/src/com/android/car/apps/common/imaging/LocalImageFetcher.java
index e8b245e..84fb530 100644
--- a/car-apps-common/src/com/android/car/apps/common/imaging/LocalImageFetcher.java
+++ b/car-apps-common/src/com/android/car/apps/common/imaging/LocalImageFetcher.java
@@ -16,10 +16,8 @@
 
 package com.android.car.apps.common.imaging;
 
-import android.annotation.UiThread;
 import android.content.ContentResolver;
 import android.content.Context;
-import android.content.res.AssetFileDescriptor;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.ImageDecoder;
@@ -30,21 +28,21 @@
 import android.util.Log;
 import android.util.LruCache;
 
+import androidx.annotation.UiThread;
+
 import com.android.car.apps.common.BitmapUtils;
 import com.android.car.apps.common.CommonFlags;
 import com.android.car.apps.common.R;
 import com.android.car.apps.common.UriUtils;
 import com.android.car.apps.common.util.CarAppsIOUtils;
 
-import libcore.io.IoUtils;
-
 import java.io.BufferedInputStream;
 import java.io.ByteArrayOutputStream;
-import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
 import java.lang.ref.WeakReference;
 import java.net.URL;
+import java.nio.ByteBuffer;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
@@ -248,7 +246,7 @@
         };
 
         // ALLOCATOR_HARDWARE causes crashes on some emulators (in media center's queue).
-        private @ImageDecoder.Allocator int mAllocatorMode = ImageDecoder.ALLOCATOR_SOFTWARE;
+        private int mAllocatorMode = ImageDecoder.ALLOCATOR_SOFTWARE;
 
         @Override
         protected Drawable doInBackground(Void... voids) {
@@ -265,18 +263,8 @@
                             UriUtils.getIconResource(context, imageUri));
                 } else if (UriUtils.isContentUri(imageUri)) {
                     ContentResolver resolver = context.getContentResolver();
-
-                    // TODO(b/140959390): Remove the check once the bug is fixed in framework.
-                    if (!hasFile(resolver, imageUri)) {
-                        if (L_WARN) {
-                            Log.w(TAG, "File not found in uri: " + imageUri);
-                        }
-                        return null;
-                    }
-
                     ImageDecoder.Source src = ImageDecoder.createSource(resolver, imageUri);
                     return ImageDecoder.decodeDrawable(src, mOnHeaderDecodedListener);
-
                 } else if (mFlagRemoteImages) {
                     mAllocatorMode = ImageDecoder.ALLOCATOR_SOFTWARE; // Needed for canvas drawing.
                     URL url = new URL(imageUri.toString());
@@ -285,7 +273,8 @@
                          ByteArrayOutputStream bytes = new ByteArrayOutputStream()) {
 
                         CarAppsIOUtils.copy(is, bytes);
-                        ImageDecoder.Source src = ImageDecoder.createSource(bytes.toByteArray());
+                        ImageDecoder.Source src =
+                                ImageDecoder.createSource(ByteBuffer.wrap(bytes.toByteArray()));
                         Bitmap decoded = ImageDecoder.decodeBitmap(src, mOnHeaderDecodedListener);
                         Bitmap tinted = BitmapUtils.createTintedBitmap(decoded,
                                 context.getColor(R.color.improper_image_refs_tint_color));
@@ -300,34 +289,6 @@
             return null;
         }
 
-        private boolean hasFile(ContentResolver resolver, Uri uri) {
-            AssetFileDescriptor assetFd = null;
-            try {
-                if (uri.getScheme() == ContentResolver.SCHEME_CONTENT) {
-                    assetFd = resolver.openTypedAssetFileDescriptor(uri, "image/*", null);
-                } else {
-                    assetFd = resolver.openAssetFileDescriptor(uri, "r");
-                }
-            } catch (FileNotFoundException e) {
-                // Some images cannot be opened as AssetFileDescriptors (e.g.bmp, ico). Open them
-                // as InputStreams.
-                try {
-                    InputStream is = resolver.openInputStream(uri);
-                    if (is != null) {
-                        IoUtils.closeQuietly(is);
-                        return true;
-                    }
-                } catch (IOException exception) {
-                    return false;
-                }
-            }
-            if (assetFd != null) {
-                IoUtils.closeQuietly(assetFd);
-                return true;
-            }
-            return false;
-        }
-
         @UiThread
         @Override
         protected void onPostExecute(Drawable drawable) {
diff --git a/car-apps-common/src/com/android/car/apps/common/log/L.java b/car-apps-common/src/com/android/car/apps/common/log/L.java
new file mode 100644
index 0000000..ad1c284
--- /dev/null
+++ b/car-apps-common/src/com/android/car/apps/common/log/L.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.car.apps.common.log;
+
+import android.os.Build;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Util class for logging.
+ */
+public class L {
+    private static final List<String> TYPE_LIST = Arrays.asList("eng", "userdebug");
+    /**
+     * Logs verbose level logs if loggable.
+     *
+     * <p>@see String#format(String, Object...) for formatting log string.
+     */
+    public static void v(String tag, @NonNull String msg, Object... args) {
+        if (Log.isLoggable(tag, Log.VERBOSE) || TYPE_LIST.contains(Build.TYPE)) {
+            Log.v(tag, String.format(msg, args));
+        }
+    }
+
+    /**
+     * Logs debug level logs if loggable.
+     *
+     * <p>@see String#format(String, Object...) for formatting log string.
+     */
+    public static void d(String tag, @NonNull String msg, Object... args) {
+        if (Log.isLoggable(tag, Log.DEBUG) || TYPE_LIST.contains(Build.TYPE)) {
+            Log.d(tag, String.format(msg, args));
+        }
+    }
+
+    /**
+     * Logs info level logs if loggable.
+     *
+     * <p>@see String#format(String, Object...) for formatting log string.
+     */
+    public static void i(String tag, @NonNull String msg, Object... args) {
+        if (Log.isLoggable(tag, Log.INFO) || TYPE_LIST.contains(Build.TYPE)) {
+            Log.i(tag, String.format(msg, args));
+        }
+    }
+
+    /**
+     * Logs warning level logs if loggable.
+     *
+     * <p>@see String#format(String, Object...) for formatting log string.
+     */
+    public static void w(String tag, @NonNull String msg, Object... args) {
+        if (Log.isLoggable(tag, Log.WARN) || TYPE_LIST.contains(Build.TYPE)) {
+            Log.w(tag, String.format(msg, args));
+        }
+    }
+
+    /**
+     * Logs error level logs if loggable.
+     *
+     * <p>@see String#format(String, Object...) for formatting log string.
+     */
+    public static void e(String tag, @NonNull String msg, Object... args) {
+        if (Log.isLoggable(tag, Log.ERROR) || TYPE_LIST.contains(Build.TYPE)) {
+            Log.e(tag, String.format(msg, args));
+        }
+    }
+
+    /**
+     * Logs warning level logs if loggable.
+     *
+     * <p>@see String#format(String, Object...) for formatting log string.
+     */
+    public static void e(String tag, Exception e, @NonNull String msg, Object... args) {
+        if (Log.isLoggable(tag, Log.ERROR) || TYPE_LIST.contains(Build.TYPE)) {
+            Log.e(tag, String.format(msg, args), e);
+        }
+    }
+}
diff --git a/car-apps-common/src/com/android/car/apps/common/util/CarPackageManagerUtils.java b/car-apps-common/src/com/android/car/apps/common/util/CarPackageManagerUtils.java
index 43e4381..6d43424 100644
--- a/car-apps-common/src/com/android/car/apps/common/util/CarPackageManagerUtils.java
+++ b/car-apps-common/src/com/android/car/apps/common/util/CarPackageManagerUtils.java
@@ -16,15 +16,12 @@
 
 package com.android.car.apps.common.util;
 
-import android.car.Car;
-import android.car.CarNotConnectedException;
+import android.app.PendingIntent;
 import android.car.content.pm.CarPackageManager;
-import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
-import android.util.Log;
 
 import androidx.annotation.NonNull;
 
@@ -34,43 +31,26 @@
 public class CarPackageManagerUtils {
     private static final String TAG = "CarPackageManagerUtils";
 
-    private final Car mCarApi;
-    private CarPackageManager mCarPackageManager;
-
-    private static CarPackageManagerUtils sInstance = null;
-
-    private CarPackageManagerUtils(Context context) {
-        mCarApi = Car.createCar(context.getApplicationContext());
-        try {
-            mCarPackageManager = (CarPackageManager) mCarApi.getCarManager(Car.PACKAGE_SERVICE);
-        } catch (CarNotConnectedException e) {
-            Log.e(TAG, "Car not connected when retrieving car package manager", e);
-        }
-    }
-
     /**
-     * Returns the singleton instance of this class
+     * Returns whether the given {@link PendingIntent} represents an activity that is distraction
+     * optimized.
      */
-    @NonNull
-    public static CarPackageManagerUtils getInstance(Context context) {
-        if (sInstance == null) {
-            sInstance = new CarPackageManagerUtils(context);
+    public static boolean isDistractionOptimized(CarPackageManager carPackageManager,
+            @NonNull PendingIntent pendingIntent) {
+        if (carPackageManager != null) {
+            return carPackageManager.isPendingIntentDistractionOptimized(pendingIntent);
         }
-        return sInstance;
+        return false;
     }
 
     /**
      * Returns true if the provided Activity is distraction optimized
      */
-    public boolean isDistractionOptimized(@NonNull ActivityInfo activityInfo) {
-        if (mCarPackageManager != null) {
-            try {
-                return mCarPackageManager.isActivityDistractionOptimized(
-                        activityInfo.packageName, activityInfo.name);
-            } catch (CarNotConnectedException e) {
-                Log.e(TAG, "Car not connected when getting driver optimization info", e);
-                return false;
-            }
+    public static boolean isDistractionOptimized(CarPackageManager carPackageManager,
+            @NonNull ActivityInfo activityInfo) {
+        if (carPackageManager != null) {
+            return carPackageManager.isActivityDistractionOptimized(
+                    activityInfo.packageName, activityInfo.name);
         }
         return false;
     }
@@ -79,9 +59,11 @@
      * Attempts to resolve the provided intent into an activity, and returns true if the
      * resolved activity is distraction optimized
      */
-    public boolean isDistractionOptimized(PackageManager packageManager, Intent intent) {
+    public static boolean isDistractionOptimized(CarPackageManager carPackageManager,
+            PackageManager packageManager, Intent intent) {
         ResolveInfo info = packageManager.resolveActivity(
                 intent, PackageManager.MATCH_DEFAULT_ONLY);
-        return (info != null) ? isDistractionOptimized(info.activityInfo) : false;
+        return (info != null) ? isDistractionOptimized(carPackageManager, info.activityInfo)
+                : false;
     }
 }
diff --git a/car-apps-common/src/com/android/car/apps/common/util/SafeLog.java b/car-apps-common/src/com/android/car/apps/common/util/SafeLog.java
index a3d10e4..c056f84 100644
--- a/car-apps-common/src/com/android/car/apps/common/util/SafeLog.java
+++ b/car-apps-common/src/com/android/car/apps/common/util/SafeLog.java
@@ -16,10 +16,11 @@
 
 package com.android.car.apps.common.util;
 
-import android.annotation.NonNull;
-import android.annotation.Nullable;
 import android.util.Log;
 
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
 /**
  * Convenience logging methods that respect whitelisted tags.
  */
diff --git a/car-apps-common/src/com/android/car/apps/common/util/ScrollBarUI.java b/car-apps-common/src/com/android/car/apps/common/util/ScrollBarUI.java
deleted file mode 100644
index 7098a82..0000000
--- a/car-apps-common/src/com/android/car/apps/common/util/ScrollBarUI.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.car.apps.common.util;
-
-import android.content.Context;
-
-import androidx.recyclerview.widget.RecyclerView;
-
-import com.android.car.apps.common.widget.PagedRecyclerView;
-import com.android.car.apps.common.widget.PagedRecyclerView.ScrollBarPosition;
-
-/**
- * An abstract class that defines required contract for a custom scroll bar for the
- * {@link PagedRecyclerView}. All custom scroll bar must inherit from this class.
- */
-public abstract class ScrollBarUI {
-    protected RecyclerView mRecyclerView;
-
-    public RecyclerView getRecyclerView() {
-        return mRecyclerView;
-    }
-
-    /**
-     * The concrete class should implement this method to initialize configuration of a scrollbar
-     * view.
-     */
-    public abstract void initialize(Context context, RecyclerView recyclerView,
-            int scrollBarContainerWidth, @ScrollBarPosition int scrollBarPosition,
-            boolean scrollBarAboveRecyclerView);
-
-    /**
-     * Requests layout of the scrollbar. Should be called when there's been a change that will
-     * affect the size of the scrollbar view.
-     */
-    public abstract void requestLayout();
-
-    /**
-     * Sets the padding of the scrollbar, relative to the padding of the RecyclerView.
-     */
-    public abstract void setPadding(int padddingStart, int paddingEnd);
-}
diff --git a/car-apps-common/src/com/android/car/apps/common/util/VectorMath.java b/car-apps-common/src/com/android/car/apps/common/util/VectorMath.java
new file mode 100644
index 0000000..cd6ad03
--- /dev/null
+++ b/car-apps-common/src/com/android/car/apps/common/util/VectorMath.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.car.apps.common.util;
+
+/**
+ * Simple utilities to deal with vector math.
+ */
+public class VectorMath {
+
+    private VectorMath() {
+    }
+
+    /** Error threshold constant. */
+    public static final float EPSILON = 0.0001f;
+
+    /** Returns the dot product of the given vectors. */
+    public static float dotProduct(float vx, float vy, float ux, float uy) {
+        return (vx * ux) + (vy * uy);
+    }
+
+    /** Returns the Euclidean norm of the given vector. */
+    public static float norm2(float vx, float vy) {
+        return (float) Math.sqrt(dotProduct(vx, vy, vx, vy));
+    }
+
+    /** Returns the center of the given coordinates. */
+    public static float center(float a, float b) {
+        return (a + b) / 2.0f;
+    }
+}
diff --git a/car-apps-common/src/com/android/car/apps/common/util/ViewUtils.java b/car-apps-common/src/com/android/car/apps/common/util/ViewUtils.java
index fe11f38..e067573 100644
--- a/car-apps-common/src/com/android/car/apps/common/util/ViewUtils.java
+++ b/car-apps-common/src/com/android/car/apps/common/util/ViewUtils.java
@@ -18,12 +18,12 @@
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
-import android.annotation.NonNull;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.view.View;
 import android.widget.TextView;
 
+import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.StringRes;
 
diff --git a/car-apps-common/src/com/android/car/apps/common/widget/CarScrollBar.java b/car-apps-common/src/com/android/car/apps/common/widget/CarScrollBar.java
deleted file mode 100644
index 2de23a3..0000000
--- a/car-apps-common/src/com/android/car/apps/common/widget/CarScrollBar.java
+++ /dev/null
@@ -1,760 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.car.apps.common.widget;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.PointF;
-import android.os.Handler;
-import android.util.Log;
-import android.view.Gravity;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.View.MeasureSpec;
-import android.view.ViewGroup;
-import android.view.ViewGroup.LayoutParams;
-import android.view.animation.AccelerateDecelerateInterpolator;
-import android.view.animation.Interpolator;
-import android.widget.FrameLayout;
-import android.widget.ImageView;
-
-import androidx.annotation.IntRange;
-import androidx.recyclerview.widget.LinearLayoutManager;
-import androidx.recyclerview.widget.OrientationHelper;
-import androidx.recyclerview.widget.RecyclerView;
-
-import com.android.car.apps.common.R;
-import com.android.car.apps.common.util.ScrollBarUI;
-import com.android.car.apps.common.widget.PagedRecyclerView.ScrollBarPosition;
-
-/**
- * Inspired by {@link androidx.car.widget.PagedListView}. Most pagination and scrolling logic has
- * been ported from the PLV with minor updates.
- *
- * The default scroll bar widget for the {@link PagedRecyclerView}.
- */
-class CarScrollBar extends ScrollBarUI {
-    private float mButtonDisabledAlpha;
-    private static final String TAG = "CarScrollBar";
-    private PagedSnapHelper mSnapHelper;
-
-    private ImageView mUpButton;
-    private PaginateButtonClickListener mUpButtonClickListener;
-    private View mScrollView;
-    private View mScrollThumb;
-    private ImageView mDownButton;
-    private PaginateButtonClickListener mDownButtonClickListener;
-
-    private int mSeparatingMargin;
-    private int mScrollBarThumbWidth;
-
-    private int mPaddingStart;
-    private int mPaddingEnd;
-
-    /** The amount of space that the scroll thumb is allowed to roam over. */
-    private int mScrollThumbTrackHeight;
-
-    private final Interpolator mPaginationInterpolator = new AccelerateDecelerateInterpolator();
-
-    private int mRowsPerPage = -1;
-    private final Handler mHandler = new Handler();
-
-    private OrientationHelper mOrientationHelper;
-
-    /**
-     * When doing a snap, offset the snap by this number of position and then do a smooth scroll to
-     * the final position.
-     */
-    private static final int SNAP_SCROLL_OFFSET_POSITION = 2;
-
-    /**
-     * The amount of time after settling to wait before autoscrolling to the next page when the user
-     * holds down a pagination button.
-     */
-    private static final int PAGINATION_HOLD_DELAY_MS = 400;
-
-    @Override
-    public void initialize(Context context, RecyclerView recyclerView,
-            int scrollBarContainerWidth, @ScrollBarPosition int scrollBarPosition,
-            boolean scrollBarAboveRecyclerView) {
-
-        mRecyclerView = recyclerView;
-
-        LayoutInflater inflater = (LayoutInflater) context.getSystemService(
-                Context.LAYOUT_INFLATER_SERVICE);
-
-        FrameLayout parent = (FrameLayout) getRecyclerView().getParent();
-
-        mScrollView = inflater.inflate(R.layout.car_paged_scrollbar_buttons, parent, false);
-        mScrollView.setLayoutParams(
-                new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT));
-
-        mButtonDisabledAlpha = context.getResources().getFloat(R.dimen.button_disabled_alpha);
-
-        if (scrollBarAboveRecyclerView) {
-            parent.addView(mScrollView);
-        } else {
-            parent.addView(mScrollView, /* index= */0);
-        }
-
-        setScrollBarContainerWidth(scrollBarContainerWidth);
-        setScrollBarPosition(scrollBarPosition);
-
-        getRecyclerView().addOnScrollListener(mRecyclerViewOnScrollListener);
-        getRecyclerView().getRecycledViewPool().setMaxRecycledViews(0, 12);
-
-        Resources res = context.getResources();
-        mSeparatingMargin = res.getDimensionPixelSize(R.dimen.car_scroll_bar_separator_margin);
-        mScrollBarThumbWidth = res.getDimensionPixelSize(R.dimen.car_scroll_bar_thumb_width);
-
-        mUpButton = mScrollView.findViewById(R.id.page_up);
-        mUpButtonClickListener = new PaginateButtonClickListener(PaginationListener.PAGE_UP);
-        mUpButton.setOnClickListener(mUpButtonClickListener);
-
-        mDownButton = mScrollView.findViewById(R.id.page_down);
-        mDownButtonClickListener = new PaginateButtonClickListener(PaginationListener.PAGE_DOWN);
-        mDownButton.setOnClickListener(mDownButtonClickListener);
-
-        mScrollThumb = mScrollView.findViewById(R.id.scrollbar_thumb);
-
-        mSnapHelper = new PagedSnapHelper(context);
-        getRecyclerView().setOnFlingListener(null);
-        mSnapHelper.attachToRecyclerView(getRecyclerView());
-
-        mScrollView.addOnLayoutChangeListener((View v, int left, int top, int right, int bottom,
-                    int oldLeft, int oldTop, int oldRight, int oldBottom) -> {
-            int width = right - left;
-
-            OrientationHelper orientationHelper =
-                    getOrientationHelper(getRecyclerView().getLayoutManager());
-
-            // This value will keep track of the top of the current view being laid out.
-            int layoutTop = orientationHelper.getStartAfterPadding() + mPaddingStart;
-
-            // Lay out the up button at the top of the view.
-            layoutViewCenteredFromTop(mUpButton, layoutTop, width);
-            layoutTop = mUpButton.getBottom();
-
-            // Lay out the scroll thumb
-            layoutTop += mSeparatingMargin;
-            layoutViewCenteredFromTop(mScrollThumb, layoutTop, width);
-
-            // Lay out the bottom button at the bottom of the view.
-            int downBottom = orientationHelper.getEndAfterPadding() - mPaddingEnd;
-            layoutViewCenteredFromBottom(mDownButton, downBottom, width);
-
-            mHandler.post(this::calculateScrollThumbTrackHeight);
-            mHandler.post(() -> updatePaginationButtons(/* animate= */false));
-        });
-    }
-
-    @Override
-    public void requestLayout() {
-        mScrollView.requestLayout();
-    }
-
-    @Override
-    public void setPadding(int paddingStart, int paddingEnd) {
-        mPaddingStart = paddingStart;
-        mPaddingEnd = paddingEnd;
-        requestLayout();
-    }
-
-    /**
-     * Sets the listener that will be notified when the up and down buttons have been pressed.
-     *
-     * @param listener The listener to set.
-     */
-    void setPaginationListener(PaginationListener listener) {
-        mUpButtonClickListener.setPaginationListener(listener);
-        mDownButtonClickListener.setPaginationListener(listener);
-    }
-
-    /** Returns {@code true} if the "up" button is pressed */
-    private boolean isUpPressed() {
-        return mUpButton.isPressed();
-    }
-
-    /** Returns {@code true} if the "down" button is pressed */
-    private boolean isDownPressed() {
-        return mDownButton.isPressed();
-    }
-
-    /**
-     * Sets the width of the container that holds the scrollbar. The scrollbar will be centered
-     * within this width.
-     *
-     * @param width The width of the scrollbar container.
-     */
-    void setScrollBarContainerWidth(int width) {
-        ViewGroup.LayoutParams layoutParams = mScrollView.getLayoutParams();
-        layoutParams.width = width;
-        mScrollView.requestLayout();
-    }
-
-    /**
-     * Sets the position of the scrollbar.
-     *
-     * @param position Enum value of the scrollbar position. 0 for Start and 1 for end.
-     */
-    void setScrollBarPosition(@ScrollBarPosition int position) {
-        FrameLayout.LayoutParams layoutParams =
-                (FrameLayout.LayoutParams) mScrollView.getLayoutParams();
-        if (position == ScrollBarPosition.START) {
-            layoutParams.gravity = Gravity.LEFT;
-        } else {
-            layoutParams.gravity = Gravity.RIGHT;
-        }
-
-        mScrollView.requestLayout();
-    }
-
-    /**
-     * Sets whether or not the up button on the scroll bar is clickable.
-     *
-     * @param enabled {@code true} if the up button is enabled.
-     */
-    private void setUpEnabled(boolean enabled) {
-        mUpButton.setEnabled(enabled);
-        mUpButton.setAlpha(enabled ? 1f : mButtonDisabledAlpha);
-    }
-
-    /**
-     * Sets whether or not the down button on the scroll bar is clickable.
-     *
-     * @param enabled {@code true} if the down button is enabled.
-     */
-    private void setDownEnabled(boolean enabled) {
-        mDownButton.setEnabled(enabled);
-        mDownButton.setAlpha(enabled ? 1f : mButtonDisabledAlpha);
-    }
-
-    /**
-     * Returns whether or not the down button on the scroll bar is clickable.
-     *
-     * @return {@code true} if the down button is enabled. {@code false} otherwise.
-     */
-    private boolean isDownEnabled() {
-        return mDownButton.isEnabled();
-    }
-
-    /** Listener for when the list should paginate. */
-    interface PaginationListener {
-        int PAGE_UP = 0;
-        int PAGE_DOWN = 1;
-
-        /** Called when the linked view should be paged in the given direction */
-        void onPaginate(int direction);
-    }
-
-    /**
-     * Calculate the amount of space that the scroll bar thumb is allowed to roam. The thumb
-     * is allowed to take up the space between the down bottom and the up or alpha jump
-     * button, depending on if the latter is visible.
-     */
-    private void calculateScrollThumbTrackHeight() {
-        // Subtracting (2 * mSeparatingMargin) for the top/bottom margin above and below the
-        // scroll bar thumb.
-        mScrollThumbTrackHeight = mDownButton.getTop() - (2 * mSeparatingMargin);
-
-        // If there's an alpha jump button, then the thumb is laid out starting from below that.
-        mScrollThumbTrackHeight -= mUpButton.getBottom();
-    }
-
-    private void measureScrollThumb() {
-        int scrollWidth = MeasureSpec.makeMeasureSpec(mScrollBarThumbWidth, MeasureSpec.EXACTLY);
-        int scrollHeight = MeasureSpec.makeMeasureSpec(
-                mScrollThumb.getLayoutParams().height,
-                MeasureSpec.EXACTLY);
-        mScrollThumb.measure(scrollWidth, scrollHeight);
-    }
-
-    /**
-     * An optimization method to only remeasure and lay out the scroll thumb. This method should be
-     * used when the height of the thumb has changed, but no other views need to be remeasured.
-     */
-    private void measureAndLayoutScrollThumb() {
-        measureScrollThumb();
-
-        // The top value should not change from what it was before; only the height is assumed to
-        // be changing.
-        int layoutTop = mScrollThumb.getTop();
-        layoutViewCenteredFromTop(mScrollThumb, layoutTop, mScrollView.getMeasuredWidth());
-    }
-
-    /**
-     * Lays out the given View starting from the given {@code top} value downwards and centered
-     * within the given {@code availableWidth}.
-     *
-     * @param  view The view to lay out.
-     * @param  top The top value to start laying out from. This value will be the resulting top
-     *             value of the view.
-     * @param  availableWidth The width in which to center the given view.
-     */
-    private void layoutViewCenteredFromTop(View view, int top, int availableWidth) {
-        int viewWidth = view.getMeasuredWidth();
-        int viewLeft = (availableWidth - viewWidth) / 2;
-        view.layout(viewLeft, top, viewLeft + viewWidth,
-                top + view.getMeasuredHeight());
-    }
-
-    /**
-     * Lays out the given View starting from the given {@code bottom} value upwards and centered
-     * within the given {@code availableSpace}.
-     *
-     * @param  view The view to lay out.
-     * @param  bottom The bottom value to start laying out from. This value will be the resulting
-     *                bottom value of the view.
-     * @param  availableWidth The width in which to center the given view.
-     */
-    private void layoutViewCenteredFromBottom(View view, int bottom, int availableWidth) {
-        int viewWidth = view.getMeasuredWidth();
-        int viewLeft = (availableWidth - viewWidth) / 2;
-        view.layout(viewLeft, bottom - view.getMeasuredHeight(),
-                viewLeft + viewWidth, bottom);
-    }
-
-    /**
-     * Sets the range, offset and extent of the scroll bar. The range represents the size of a
-     * container for the scrollbar thumb; offset is the distance from the start of the container
-     * to where the thumb should be; and finally, extent is the size of the thumb.
-     *
-     * <p>These values can be expressed in arbitrary units, so long as they share the same units.
-     * The values should also be positive.
-     *
-     * @param range The range of the scrollbar's thumb
-     * @param offset The offset of the scrollbar's thumb
-     * @param extent The extent of the scrollbar's thumb
-     * @param animate Whether or not the thumb should animate from its current position to the
-     *                position specified by the given range, offset and extent.
-     */
-    void setParameters(
-            @IntRange(from = 0) int range,
-            @IntRange(from = 0) int offset,
-            @IntRange(from = 0) int extent, boolean animate) {
-        // Not laid out yet, so values cannot be calculated.
-        if (!mScrollView.isLaidOut()) {
-            return;
-        }
-
-        // If the scroll bars aren't visible, then no need to update.
-        if (mScrollView.getVisibility() == View.GONE || range == 0) {
-            return;
-        }
-
-        int thumbLength = calculateScrollThumbLength(range, extent);
-        int thumbOffset = calculateScrollThumbOffset(range, offset, thumbLength);
-
-        // Sets the size of the thumb and request a redraw if needed.
-        ViewGroup.LayoutParams lp = mScrollThumb.getLayoutParams();
-
-        if (lp.height != thumbLength) {
-            lp.height = thumbLength;
-            mScrollThumb.requestLayout();
-        }
-
-        moveY(mScrollThumb, thumbOffset, animate);
-    }
-
-    /**
-     * An optimized version of {@link #setParameters(int, int, int, boolean)} that is meant to be
-     * called if a view is laying itself out. This method will avoid a complete remeasure of
-     * the views in the {@code PagedScrollBarView} if the scroll thumb's height needs to be changed.
-     * Instead, only the thumb itself will be remeasured and laid out.
-     *
-     * <p>These values can be expressed in arbitrary units, so long as they share the same units.
-     *
-     * @param range The range of the scrollbar's thumb
-     * @param offset The offset of the scrollbar's thumb
-     * @param extent The extent of the scrollbar's thumb
-     *
-     * @see #setParameters(int, int, int, boolean)
-     */
-    void setParametersInLayout(int range, int offset, int extent) {
-        // If the scroll bars aren't visible, then no need to update.
-        if (mScrollView.getVisibility() == View.GONE || range == 0) {
-            return;
-        }
-
-        int thumbLength = calculateScrollThumbLength(range, extent);
-        int thumbOffset = calculateScrollThumbOffset(range, offset, thumbLength);
-
-        // Sets the size of the thumb and request a redraw if needed.
-        ViewGroup.LayoutParams lp = mScrollThumb.getLayoutParams();
-
-        if (lp.height != thumbLength) {
-            lp.height = thumbLength;
-            measureAndLayoutScrollThumb();
-        }
-
-        mScrollThumb.setY(thumbOffset);
-    }
-
-    /**
-     * Calculates and returns how big the scroll bar thumb should be based on the given range and
-     * extent.
-     *
-     * @param range The total amount of space the scroll bar is allowed to roam over.
-     * @param extent The amount of space that the scroll bar takes up relative to the range.
-     * @return The height of the scroll bar thumb in pixels.
-     */
-    private int calculateScrollThumbLength(int range, int extent) {
-        // Scale the length by the available space that the thumb can fill.
-        return Math.round(((float) extent / range) * mScrollThumbTrackHeight);
-    }
-
-    /**
-     * Calculates and returns how much the scroll thumb should be offset from the top of where it
-     * has been laid out.
-     *
-     * @param  range The total amount of space the scroll bar is allowed to roam over.
-     * @param  offset The amount the scroll bar should be offset, expressed in the same units as
-     *                the given range.
-     * @param  thumbLength The current length of the thumb in pixels.
-     * @return The amount the thumb should be offset in pixels.
-     */
-    private int calculateScrollThumbOffset(int range, int offset, int thumbLength) {
-        // Ensure that if the user has reached the bottom of the list, then the scroll bar is
-        // aligned to the bottom as well. Otherwise, scale the offset appropriately.
-        // This offset will be a value relative to the parent of this scrollbar, so start by where
-        // the top of mScrollThumb is.
-        return mScrollThumb.getTop() + (isDownEnabled()
-                ? Math.round(((float) offset / range) * mScrollThumbTrackHeight)
-                : mScrollThumbTrackHeight - thumbLength);
-    }
-
-    /** Moves the given view to the specified 'y' position. */
-    private void moveY(final View view, float newPosition, boolean animate) {
-        final int duration = animate ? 200 : 0;
-        view.animate()
-                .y(newPosition)
-                .setDuration(duration)
-                .setInterpolator(mPaginationInterpolator)
-                .start();
-    }
-
-    /**
-     * Updates the rows number per current page, which is used for calculating how many items we
-     * want to show.
-     */
-    private void updateRowsPerPage() {
-        RecyclerView.LayoutManager layoutManager = getRecyclerView().getLayoutManager();
-        if (layoutManager == null) {
-            mRowsPerPage = 1;
-            return;
-        }
-
-        View firstChild = layoutManager.getChildAt(0);
-        if (firstChild == null || firstChild.getHeight() == 0) {
-            mRowsPerPage = 1;
-        } else {
-            mRowsPerPage = Math.max(1, getRecyclerView().getHeight() / firstChild.getHeight());
-        }
-    }
-
-    private class PaginateButtonClickListener implements View.OnClickListener {
-        private final int mPaginateDirection;
-        private PaginationListener mPaginationListener;
-
-        PaginateButtonClickListener(int paginateDirection) {
-            mPaginateDirection = paginateDirection;
-        }
-
-        public void setPaginationListener(PaginationListener listener) {
-            mPaginationListener = listener;
-        }
-
-        @Override
-        public void onClick(View v) {
-            if (mPaginationListener != null) {
-                mPaginationListener.onPaginate(mPaginateDirection);
-            }
-            if (mPaginateDirection == PaginationListener.PAGE_DOWN) {
-                pageDown();
-            } else if (mPaginateDirection == PaginationListener.PAGE_UP) {
-                pageUp();
-            }
-        }
-    }
-
-    private final RecyclerView.OnScrollListener mRecyclerViewOnScrollListener =
-            new RecyclerView.OnScrollListener() {
-                @Override
-                public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
-                    updatePaginationButtons(false);
-                }
-            };
-
-    private final Runnable mPaginationRunnable = () -> {
-        boolean upPressed = isUpPressed();
-        boolean downPressed = isDownPressed();
-        if (upPressed && downPressed) {
-            return;
-        }
-        if (upPressed) {
-            pageUp();
-        } else if (downPressed) {
-            pageDown();
-        }
-    };
-
-    /** Returns the page the given position is on, starting with page 0. */
-    int getPage(int position) {
-        if (mRowsPerPage == -1) {
-            return -1;
-        }
-        if (mRowsPerPage == 0) {
-            return 0;
-        }
-        return position / mRowsPerPage;
-    }
-
-    private OrientationHelper getOrientationHelper(RecyclerView.LayoutManager layoutManager) {
-        if (mOrientationHelper == null || mOrientationHelper.getLayoutManager() != layoutManager) {
-            // PagedRecyclerView is assumed to be a list that always vertically scrolls.
-            mOrientationHelper = OrientationHelper.createVerticalHelper(layoutManager);
-        }
-        return mOrientationHelper;
-    }
-
-    /**
-     * Scrolls the contents of the RecyclerView up a page. A page is defined as the height of the
-     * {@code PagedRecyclerView}.
-     *
-     * <p>The resulting first item in the list will be snapped to so that it is completely visible.
-     * If this is not possible due to the first item being taller than the containing
-     * {@code PagedRecyclerView}, then the snapping will not occur.
-     */
-    void pageUp() {
-        int currentOffset = getRecyclerView().computeVerticalScrollOffset();
-        if (getRecyclerView().getLayoutManager() == null
-                || getRecyclerView().getChildCount() == 0 || currentOffset == 0) {
-            return;
-        }
-
-        // Use OrientationHelper to calculate scroll distance in order to match snapping behavior.
-        OrientationHelper orientationHelper =
-                getOrientationHelper(getRecyclerView().getLayoutManager());
-        int screenSize = orientationHelper.getTotalSpace();
-
-        int scrollDistance = screenSize;
-        // The iteration order matters. In case where there are 2 items longer than screen size, we
-        // want to focus on upcoming view.
-        for (int i = 0; i < getRecyclerView().getChildCount(); i++) {
-            /*
-             * We treat child View longer than screen size differently:
-             * 1) When it enters screen, next pageUp will align its bottom with parent bottom;
-             * 2) When it leaves screen, next pageUp will align its top with parent top.
-             */
-            View child = getRecyclerView().getChildAt(i);
-            if (child.getHeight() > screenSize) {
-                if (orientationHelper.getDecoratedEnd(child) < screenSize) {
-                    // Child view bottom is entering screen. Align its bottom with parent bottom.
-                    scrollDistance = screenSize - orientationHelper.getDecoratedEnd(child);
-                } else if (-screenSize < orientationHelper.getDecoratedStart(child)
-                        && orientationHelper.getDecoratedStart(child) < 0) {
-                    // Child view top is about to enter screen - its distance to parent top
-                    // is less than a full scroll. Align child top with parent top.
-                    scrollDistance = Math.abs(orientationHelper.getDecoratedStart(child));
-                }
-                // There can be two items that are longer than the screen. We stop at the first one.
-                // This is affected by the iteration order.
-                break;
-            }
-        }
-        // Distance should always be positive. Negate its value to scroll up.
-        getRecyclerView().smoothScrollBy(0, -scrollDistance);
-    }
-
-    /**
-     * Scrolls the contents of the RecyclerView down a page. A page is defined as the height of the
-     * {@code PagedRecyclerView}.
-     *
-     * <p>This method will attempt to bring the last item in the list as the first item. If the
-     * current first item in the list is taller than the {@code PagedRecyclerView}, then it will be
-     * scrolled the length of a page, but not snapped to.
-     */
-    void pageDown() {
-        if (getRecyclerView().getLayoutManager() == null
-                || getRecyclerView().getChildCount() == 0) {
-            return;
-        }
-
-        OrientationHelper orientationHelper =
-                getOrientationHelper(getRecyclerView().getLayoutManager());
-        int screenSize = orientationHelper.getTotalSpace();
-        int scrollDistance = screenSize;
-
-        // If the last item is partially visible, page down should bring it to the top.
-        View lastChild = getRecyclerView().getChildAt(getRecyclerView().getChildCount() - 1);
-        if (getRecyclerView().getLayoutManager().isViewPartiallyVisible(lastChild,
-                /* completelyVisible= */ false, /* acceptEndPointInclusion= */ false)) {
-            scrollDistance = orientationHelper.getDecoratedStart(lastChild);
-            if (scrollDistance < 0) {
-                // Scroll value can be negative if the child is longer than the screen size and the
-                // visible area of the screen does not show the start of the child.
-                // Scroll to the next screen if the start value is negative
-                scrollDistance = screenSize;
-            }
-        }
-
-        // The iteration order matters. In case where there are 2 items longer than screen size, we
-        // want to focus on upcoming view (the one at the bottom of screen).
-        for (int i = getRecyclerView().getChildCount() - 1; i >= 0; i--) {
-            /* We treat child View longer than screen size differently:
-             * 1) When it enters screen, next pageDown will align its top with parent top;
-             * 2) When it leaves screen, next pageDown will align its bottom with parent bottom.
-             */
-            View child = getRecyclerView().getChildAt(i);
-            if (child.getHeight() > screenSize) {
-                if (orientationHelper.getDecoratedStart(child) > 0) {
-                    // Child view top is entering screen. Align its top with parent top.
-                    scrollDistance = orientationHelper.getDecoratedStart(child);
-                } else if (screenSize < orientationHelper.getDecoratedEnd(child)
-                        && orientationHelper.getDecoratedEnd(child) < 2 * screenSize) {
-                    // Child view bottom is about to enter screen - its distance to parent bottom
-                    // is less than a full scroll. Align child bottom with parent bottom.
-                    scrollDistance = orientationHelper.getDecoratedEnd(child) - screenSize;
-                }
-                // There can be two items that are longer than the screen. We stop at the first one.
-                // This is affected by the iteration order.
-                break;
-            }
-        }
-
-        getRecyclerView().smoothScrollBy(0, scrollDistance);
-    }
-
-    /**
-     * Determines if scrollbar should be visible or not and shows/hides it accordingly. If this is
-     * being called as a result of adapter changes, it should be called after the new layout has
-     * been calculated because the method of determining scrollbar visibility uses the current
-     * layout. If this is called after an adapter change but before the new layout, the visibility
-     * determination may not be correct.
-     *
-     * @param animate {@code true} if the scrollbar should animate to its new position.
-     *                {@code false} if no animation is used
-     */
-    private void updatePaginationButtons(boolean animate) {
-
-        boolean isAtStart = isAtStart();
-        boolean isAtEnd = isAtEnd();
-        RecyclerView.LayoutManager layoutManager = getRecyclerView().getLayoutManager();
-
-        if ((isAtStart && isAtEnd) || layoutManager == null || layoutManager.getItemCount() == 0) {
-            mScrollView.setVisibility(View.INVISIBLE);
-        } else {
-            mScrollView.setVisibility(View.VISIBLE);
-        }
-        setUpEnabled(!isAtStart);
-        setDownEnabled(!isAtEnd);
-
-        if (layoutManager == null) {
-            return;
-        }
-
-        if (layoutManager.canScrollVertically()) {
-            setParameters(
-                    getRecyclerView().computeVerticalScrollRange(),
-                    getRecyclerView().computeVerticalScrollOffset(),
-                    getRecyclerView().computeVerticalScrollExtent(), animate);
-        } else {
-            setParameters(
-                    getRecyclerView().computeHorizontalScrollRange(),
-                    getRecyclerView().computeHorizontalScrollOffset(),
-                    getRecyclerView().computeHorizontalScrollExtent(), animate);
-        }
-
-        mScrollView.invalidate();
-    }
-
-    /** Returns {@code true} if the RecyclerView is completely displaying the first item. */
-    boolean isAtStart() {
-        return mSnapHelper.isAtStart(getRecyclerView().getLayoutManager());
-    }
-
-    /** Returns {@code true} if the RecyclerView is completely displaying the last item. */
-    boolean isAtEnd() {
-        return mSnapHelper.isAtEnd(getRecyclerView().getLayoutManager());
-    }
-
-    /**
-     * Scrolls to the given position in the PagedRecyclerView.
-     *
-     * @param position The position in the list to scroll to.
-     */
-    private void scrollToPosition(int position) {
-        RecyclerView.LayoutManager layoutManager = getRecyclerView().getLayoutManager();
-        if (layoutManager == null) {
-            return;
-        }
-
-        RecyclerView.SmoothScroller smoothScroller = mSnapHelper.createScroller(layoutManager);
-        smoothScroller.setTargetPosition(position);
-
-        layoutManager.startSmoothScroll(smoothScroller);
-
-        // Sometimes #scrollToPosition doesn't change the scroll state so we need to make sure
-        // the pagination arrows actually get updated. See b/15801119
-        mHandler.post(() -> updatePaginationButtons(true /*animate*/));
-    }
-
-    /**
-     * Snap to the given position. This method will snap instantly to a position that's "close" to
-     * the given position and then animate a short decelerate to indicate the direction that the
-     * snap happened.
-     *
-     * @param position The position in the list to scroll to.
-     */
-    void snapToPosition(int position) {
-        RecyclerView.LayoutManager layoutManager = getRecyclerView().getLayoutManager();
-
-        if (layoutManager == null) {
-            return;
-        }
-
-        int startPosition = position;
-        if ((layoutManager instanceof RecyclerView.SmoothScroller.ScrollVectorProvider)) {
-            PointF vector = ((RecyclerView.SmoothScroller.ScrollVectorProvider) layoutManager)
-                    .computeScrollVectorForPosition(position);
-            // A positive value in the vector means scrolling down, so should offset by scrolling to
-            // an item previous in the list.
-            int offsetDirection = (vector == null || vector.y > 0) ? -1 : 1;
-            startPosition += offsetDirection * SNAP_SCROLL_OFFSET_POSITION;
-
-            // Clamp the start position.
-            startPosition = Math.max(0, Math.min(startPosition, layoutManager.getItemCount() - 1));
-        } else {
-            // If the LayoutManager doesn't implement ScrollVectorProvider (the default for
-            // PagedRecyclerView, LinearLayoutManager does, but if the user has overridden it) then
-            // we cannot compute the direction we need to scroll. So just snap instantly instead.
-            Log.w(TAG, "LayoutManager is not a ScrollVectorProvider, can't do snap animation.");
-        }
-
-        if (layoutManager instanceof LinearLayoutManager) {
-            ((LinearLayoutManager) layoutManager).scrollToPositionWithOffset(startPosition, 0);
-        } else {
-            layoutManager.scrollToPosition(startPosition);
-        }
-
-        if (startPosition != position) {
-            // The actual scroll above happens on the next update, so we wait for that to finish
-            // before doing the smooth scroll.
-            mScrollView.post(() -> scrollToPosition(position));
-        }
-    }
-}
diff --git a/car-apps-common/src/com/android/car/apps/common/widget/CarTabLayout.java b/car-apps-common/src/com/android/car/apps/common/widget/CarTabLayout.java
deleted file mode 100644
index 4dd427f..0000000
--- a/car-apps-common/src/com/android/car/apps/common/widget/CarTabLayout.java
+++ /dev/null
@@ -1,378 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.car.apps.common.widget;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.graphics.Typeface;
-import android.graphics.drawable.Drawable;
-import android.util.ArraySet;
-import android.util.AttributeSet;
-import android.view.Gravity;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.BaseAdapter;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-import android.widget.TextView;
-
-import androidx.annotation.LayoutRes;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.annotation.StyleRes;
-
-import com.android.car.apps.common.R;
-import com.android.car.apps.common.util.Themes;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Set;
-
-/**
- * Custom tab layout which supports adding tabs dynamically
- *
- * <p>It supports two layout modes:
- * <ul><li>Flexible layout which will fill the width
- * <li>Non-flexible layout which wraps content with a minimum tab width. By setting tab gravity,
- * it can left aligned, right aligned or center aligned.
- *
- * <p>Scrolling function is not supported. If a tab item runs out of the tab layout bound, there
- * is no way to access it. It's better to set the layout mode to flexible in this case.
- *
- * <p>Default tab item inflates from R.layout.car_tab_item, but it also supports custom layout id.
- * By doing this, appearance of tab item view can be customized.
- *
- * <p>Touch feedback is using @android:attr/selectableItemBackground.
- *
- * @param <T> Presents a CarTab entity
- * @deprecated Use {@link com.android.car.ui.TabLayout} instead
- */
-@Deprecated
-public class CarTabLayout<T extends CarTabLayout.CarTab> extends LinearLayout {
-
-    /**
-     * Listener that listens the car tab selection change.
-     *
-     * @param <T> Presents a CarTab entity that has state update on a tab select action
-     */
-    public interface OnCarTabSelectedListener<T extends CarTab> {
-        /** Callback triggered when a car tab is selected. */
-        void onCarTabSelected(T carTab);
-
-        /** Callback triggered when a car tab is unselected. */
-        void onCarTabUnselected(T carTab);
-
-        /** Callback triggered when a car tab is reselected. */
-        void onCarTabReselected(T carTab);
-    }
-
-    /**
-     * No-op implementation of {@link OnCarTabSelectedListener}.
-     *
-     * @param <T> See {@link OnCarTabSelectedListener}
-     */
-    public static class SimpleOnCarTabSelectedListener<T extends CarTab> implements
-            OnCarTabSelectedListener<T> {
-
-        @Override
-        public void onCarTabSelected(T carTab) {
-            // No-op
-        }
-
-        @Override
-        public void onCarTabUnselected(T carTab) {
-            // No-op
-        }
-
-        @Override
-        public void onCarTabReselected(T carTab) {
-            // No-op
-        }
-    }
-
-    // View attributes
-    private final boolean mTabFlexibleLayout;
-    private final int mTabPaddingX;
-
-    private final Set<OnCarTabSelectedListener<T>> mOnCarTabSelectedListeners;
-
-    private final CarTabAdapter<T> mCarTabAdapter;
-
-    public CarTabLayout(@NonNull Context context) {
-        this(context, null);
-    }
-
-    public CarTabLayout(@NonNull Context context, @Nullable AttributeSet attrs) {
-        this(context, attrs, 0);
-    }
-
-    public CarTabLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyle) {
-        super(context, attrs, defStyle);
-        mOnCarTabSelectedListeners = new ArraySet<>();
-
-        TypedArray ta = context.obtainStyledAttributes(
-                attrs, R.styleable.CarTabLayout, defStyle, 0);
-        mTabPaddingX = ta.getDimensionPixelSize(R.styleable.CarTabLayout_tabPaddingX,
-                context.getResources().getDimensionPixelSize(R.dimen.car_tab_padding_x));
-        mTabFlexibleLayout = ta.getBoolean(R.styleable.CarTabLayout_tabFlexibleLayout,
-                context.getResources().getBoolean(R.bool.car_tab_flexible_layout));
-        int tabItemLayout = ta.getResourceId(R.styleable.CarTabLayout_tabItemLayout,
-                R.layout.car_tab_item);
-        ta.recycle();
-
-        mCarTabAdapter = new CarTabAdapter(context, tabItemLayout, this);
-    }
-
-    /**
-     * Add a tab to this layout. The tab will be added at the end of the list. If this is the first
-     * tab to be added it will become the selected tab.
-     */
-    public void addCarTab(T carTab) {
-        mCarTabAdapter.add(carTab);
-        // If there is only one tab in the group, set it to be selected.
-        if (mCarTabAdapter.getCount() == 1) {
-            mCarTabAdapter.selectCarTab(0);
-        }
-    }
-
-    /** Set the tab as the current selected tab. */
-    public void selectCarTab(T carTab) {
-        mCarTabAdapter.selectCarTab(carTab);
-    }
-
-    /** Set the tab at given position as the current selected tab. */
-    public void selectCarTab(int position) {
-        mCarTabAdapter.selectCarTab(position);
-    }
-
-    /** Returns how tab items it has. */
-    public int getCarTabCount() {
-        return mCarTabAdapter.getCount();
-    }
-
-    /** Returns the position of the given car tab. */
-    public int getCarTabPosition(T carTab) {
-        return mCarTabAdapter.getPosition(carTab);
-    }
-
-    /** Return the car tab at the given position. */
-    public T get(int position) {
-        return mCarTabAdapter.getItem(position);
-    }
-
-    /** Clear all car tabs. */
-    public void clearAllCarTabs() {
-        mCarTabAdapter.clear();
-    }
-
-    /** Register a {@link OnCarTabSelectedListener}. Same listener will only be registered once. */
-    public void addOnCarTabSelectedListener(
-            @NonNull OnCarTabSelectedListener onCarTabSelectedListener) {
-        mOnCarTabSelectedListeners.add(onCarTabSelectedListener);
-    }
-
-    /** Unregister a {@link OnCarTabSelectedListener} */
-    public void removeOnCarTabSelectedListener(
-            @NonNull OnCarTabSelectedListener onCarTabSelectedListener) {
-        mOnCarTabSelectedListeners.remove(onCarTabSelectedListener);
-    }
-
-    private void dispatchOnCarTabSelected(T carTab) {
-        for (OnCarTabSelectedListener onCarTabSelectedListener : mOnCarTabSelectedListeners) {
-            onCarTabSelectedListener.onCarTabSelected(carTab);
-        }
-    }
-
-    private void dispatchOnCarTabUnselected(T carTab) {
-        for (OnCarTabSelectedListener onCarTabSelectedListener : mOnCarTabSelectedListeners) {
-            onCarTabSelectedListener.onCarTabUnselected(carTab);
-        }
-    }
-
-    private void dispatchOnCarTabReselected(T carTab) {
-        for (OnCarTabSelectedListener onCarTabSelectedListener : mOnCarTabSelectedListeners) {
-            onCarTabSelectedListener.onCarTabReselected(carTab);
-        }
-    }
-
-    private void addCarTabView(View carTabView, int position) {
-        LayoutParams layoutParams;
-        if (mTabFlexibleLayout) {
-            layoutParams = new LayoutParams(0, ViewGroup.LayoutParams.MATCH_PARENT);
-            layoutParams.weight = 1;
-        } else {
-            layoutParams = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
-                    ViewGroup.LayoutParams.MATCH_PARENT);
-        }
-        addView(carTabView, position, layoutParams);
-    }
-
-    private ViewGroup createCarTabItemView() {
-        LinearLayout carTabItemView = new LinearLayout(mContext);
-        carTabItemView.setOrientation(LinearLayout.VERTICAL);
-        carTabItemView.setGravity(Gravity.CENTER);
-        carTabItemView.setPadding(mTabPaddingX, 0, mTabPaddingX, 0);
-        Drawable backgroundDrawable = Themes.getAttrDrawable(getContext(),
-                R.style.CarTabItemBackground, android.R.attr.background);
-        carTabItemView.setBackground(backgroundDrawable);
-        return carTabItemView;
-    }
-
-    private static class CarTabAdapter<T extends CarTab> extends BaseAdapter {
-        private final Context mContext;
-        private final CarTabLayout mCarTabLayout;
-        @LayoutRes
-        private final int mCarTabItemLayoutRes;
-        private final Typeface mUnselectedTypeface;
-        private final Typeface mSelectedTypeface;
-        private final List<T> mCarTabList;
-
-        private CarTabAdapter(Context context, @LayoutRes int res, CarTabLayout carTabLayout) {
-            mCarTabList = new ArrayList<>();
-            mContext = context;
-            mCarTabItemLayoutRes = res;
-            mCarTabLayout = carTabLayout;
-            mUnselectedTypeface = createStyledTypeface(context, R.style.CarTabItemText);
-            mSelectedTypeface = createStyledTypeface(context, R.style.CarTabSelectedTextTypeface);
-        }
-
-        private void add(@NonNull T carTab) {
-            mCarTabList.add(carTab);
-            notifyItemInserted(mCarTabList.size() - 1);
-        }
-
-        private void clear() {
-            mCarTabList.clear();
-            mCarTabLayout.removeAllViews();
-        }
-
-        private int getPosition(CarTab carTab) {
-            return mCarTabList.indexOf(carTab);
-        }
-
-        @Override
-        public int getCount() {
-            return mCarTabList.size();
-        }
-
-        @Override
-        public T getItem(int position) {
-            return mCarTabList.get(position);
-        }
-
-        @Override
-        public long getItemId(int position) {
-            return position;
-        }
-
-        @Override
-        @NonNull
-        public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
-            ViewGroup carTabItemView = mCarTabLayout.createCarTabItemView();
-            LayoutInflater.from(mContext).inflate(mCarTabItemLayoutRes, carTabItemView, true);
-
-            presentCarTabItemView(position, carTabItemView);
-            return carTabItemView;
-        }
-
-        private void selectCarTab(CarTab carTab) {
-            selectCarTab(getPosition(carTab));
-        }
-
-        private void selectCarTab(int position) {
-            if (position < 0 || position >= getCount()) {
-                throw new IndexOutOfBoundsException("Invalid position");
-            }
-
-            for (int i = 0; i < getCount(); i++) {
-                CarTab carTabItem = mCarTabList.get(i);
-                boolean isTabSelected = position == i;
-                if (carTabItem.mIsSelected != isTabSelected) {
-                    carTabItem.mIsSelected = isTabSelected;
-                    notifyItemChanged(i);
-                    if (carTabItem.mIsSelected) {
-                        mCarTabLayout.dispatchOnCarTabSelected(carTabItem);
-                    } else {
-                        mCarTabLayout.dispatchOnCarTabUnselected(carTabItem);
-                    }
-                } else if (carTabItem.mIsSelected) {
-                    mCarTabLayout.dispatchOnCarTabReselected(carTabItem);
-                }
-            }
-        }
-
-        /** Represent the car tab item at given position without destroying and recreating UI. */
-        private void notifyItemChanged(int position) {
-            View carTabItemView = mCarTabLayout.getChildAt(position);
-            presentCarTabItemView(position, carTabItemView);
-        }
-
-        private void notifyItemInserted(int position) {
-            View insertedView = getView(position, null, mCarTabLayout);
-            mCarTabLayout.addCarTabView(insertedView, position);
-        }
-
-        private void presentCarTabItemView(int position, @NonNull View carTabItemView) {
-            CarTab carTab = mCarTabList.get(position);
-
-            ImageView iconView = carTabItemView.findViewById(R.id.car_tab_item_icon);
-            TextView textView = carTabItemView.findViewById(R.id.car_tab_item_text);
-
-            carTabItemView.setOnClickListener(view -> selectCarTab(carTab));
-            carTab.bindText(textView);
-            carTab.bindIcon(iconView);
-
-            carTabItemView.setSelected(carTab.mIsSelected);
-            iconView.setSelected(carTab.mIsSelected);
-            textView.setSelected(carTab.mIsSelected);
-            textView.setTypeface(carTab.mIsSelected ? mSelectedTypeface : mUnselectedTypeface);
-        }
-
-        private static Typeface createStyledTypeface(Context context, @StyleRes int styleResId) {
-            // If not specified, default to 0, which stands for normal.
-            int textStyle = Themes.getAttrInteger(context, styleResId, android.R.attr.textStyle);
-            // If not specified, default value will be 0 which is a light font.
-            int textFontWeight = Themes.getAttrInteger(context, styleResId,
-                    android.R.attr.textFontWeight);
-            return Typeface.create(Typeface.defaultFromStyle(textStyle), textFontWeight,
-                    (textStyle & Typeface.ITALIC) != 0);
-        }
-    }
-
-    /** Car tab entity. */
-    public static class CarTab {
-        private final Drawable mIcon;
-        private final CharSequence mText;
-        private boolean mIsSelected;
-
-        public CarTab(@Nullable Drawable icon, @Nullable CharSequence text) {
-            mIcon = icon;
-            mText = text;
-        }
-
-        /** Set tab text. */
-        protected void bindText(TextView textView) {
-            textView.setText(mText);
-        }
-
-        /** Set icon drawable. TODO(b/139444064): revise this api. */
-        protected void bindIcon(ImageView imageView) {
-            imageView.setImageDrawable(mIcon);
-        }
-    }
-}
diff --git a/car-apps-common/src/com/android/car/apps/common/widget/PagedRecyclerView.java b/car-apps-common/src/com/android/car/apps/common/widget/PagedRecyclerView.java
deleted file mode 100644
index 2917967..0000000
--- a/car-apps-common/src/com/android/car/apps/common/widget/PagedRecyclerView.java
+++ /dev/null
@@ -1,695 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.car.apps.common.widget;
-
-import static java.lang.annotation.RetentionPolicy.SOURCE;
-
-import android.car.drivingstate.CarUxRestrictions;
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.util.SparseArray;
-import android.view.View;
-import android.view.ViewTreeObserver.OnGlobalLayoutListener;
-
-import androidx.annotation.IntDef;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.annotation.VisibleForTesting;
-import androidx.recyclerview.widget.LinearLayoutManager;
-import androidx.recyclerview.widget.RecyclerView;
-
-import com.android.car.apps.common.CarUxRestrictionsUtil;
-import com.android.car.apps.common.R;
-import com.android.car.apps.common.util.ScrollBarUI;
-
-import java.lang.annotation.Retention;
-
-/**
- * View that extends a {@link RecyclerView} and creates a nested {@code RecyclerView} with an option
- * to render a custom scroll bar that has page up and down arrows. Interaction with this view is
- * similar to a {@code RecyclerView} as it takes the same adapter and the layout manager.
- */
-public final class PagedRecyclerView extends RecyclerView {
-
-    private static final boolean DEBUG = false;
-    private static final String TAG = "PagedRecyclerView";
-
-    private final CarUxRestrictionsUtil mCarUxRestrictionsUtil;
-    private final CarUxRestrictionsUtil.OnUxRestrictionsChangedListener mListener;
-
-    private boolean mScrollBarEnabled;
-    private int mScrollBarContainerWidth;
-    private @ScrollBarPosition int mScrollBarPosition;
-    private boolean mScrollBarAboveRecyclerView;
-    private String mScrollBarClass;
-    private int mScrollBarPaddingStart;
-    private int mScrollBarPaddingEnd;
-    private boolean mFullyInitialized;
-
-    @Gutter
-    private int mGutter;
-    private int mGutterSize;
-    private RecyclerView mNestedRecyclerView;
-    private Adapter mAdapter;
-    private ScrollBarUI mScrollBarUI;
-
-    /**
-     * The possible values for @{link #setGutter}. The default value is actually
-     * {@link PagedRecyclerView.Gutter#BOTH}.
-     */
-    @IntDef({
-            Gutter.NONE,
-            Gutter.START,
-            Gutter.END,
-            Gutter.BOTH,
-    })
-
-    @Retention(SOURCE)
-    public @interface Gutter {
-        /**
-         * No gutter on either side of the list items. The items will span the full width of the
-         * RecyclerView
-         */
-        int NONE = 0;
-
-        /**
-         * Include a gutter only on the start side (that is, the same side as the scroll bar).
-         */
-        int START = 1;
-
-        /**
-         * Include a gutter only on the end side (that is, the opposite side of the scroll bar).
-         */
-        int END = 2;
-
-        /**
-         * Include a gutter on both sides of the list items. This is the default behaviour.
-         */
-        int BOTH = 3;
-    }
-
-    /**
-     * The possible values for setScrollbarPosition. The default value is actually
-     * {@link PagedRecyclerView.ScrollBarPosition#START}.
-     */
-    @IntDef({
-            ScrollBarPosition.START,
-            ScrollBarPosition.END,
-    })
-
-    @Retention(SOURCE)
-    public @interface ScrollBarPosition {
-        /**
-         * Position the scrollbar to the left of the screen. This is default.
-         */
-        int START = 0;
-
-        /**
-         * Position scrollbar to the right of the screen.
-         */
-        int END = 2;
-    }
-
-    /**
-     * Interface for a {@link RecyclerView.Adapter} to cap the number of items.
-     *
-     * <p>NOTE: it is still up to the adapter to use maxItems in {@link
-     * RecyclerView.Adapter#getItemCount()}.
-     *
-     * <p>the recommended way would be with:
-     *
-     * <pre>{@code
-     * {@literal@}Override
-     * public int getItemCount() {
-     *   return Math.min(super.getItemCount(), mMaxItems);
-     * }
-     * }</pre>
-     */
-    public interface ItemCap {
-        /**
-         * A value to pass to {@link #setMaxItems(int)} that indicates there should be no limit.
-         */
-        int UNLIMITED = -1;
-
-        /**
-         * Sets the maximum number of items available in the adapter. A value less than '0' means
-         * the list should not be capped.
-         */
-        void setMaxItems(int maxItems);
-    }
-
-    /**
-     * Custom layout manager for the outer recyclerview. Since paddings should be applied by the
-     * inner recycler view within its bounds, this layout manager should always have 0 padding.
-     */
-    private class PagedRecyclerViewLayoutManager extends LinearLayoutManager {
-        PagedRecyclerViewLayoutManager(Context context) {
-            super(context);
-        }
-
-        @Override
-        public int getPaddingTop() {
-            return 0;
-        }
-
-        @Override
-        public int getPaddingBottom() {
-            return 0;
-        }
-
-        @Override
-        public int getPaddingStart() {
-            return 0;
-        }
-
-        @Override
-        public int getPaddingEnd() {
-            return 0;
-        }
-
-        @Override
-        public boolean canScrollHorizontally() {
-            return false;
-        }
-
-        @Override
-        public boolean canScrollVertically() {
-            return false;
-        }
-    }
-
-    public PagedRecyclerView(@NonNull Context context) {
-        this(context, null, 0);
-    }
-
-    public PagedRecyclerView(@NonNull Context context, @Nullable AttributeSet attrs) {
-        this(context, attrs, 0);
-    }
-
-    public PagedRecyclerView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyle) {
-        super(context, attrs, defStyle);
-
-        mCarUxRestrictionsUtil = CarUxRestrictionsUtil.getInstance(context);
-        mListener = this::updateCarUxRestrictions;
-
-        init(context, attrs, defStyle);
-    }
-
-    private void init(Context context, AttributeSet attrs, int defStyleAttr) {
-        TypedArray a = context.obtainStyledAttributes(
-                attrs, R.styleable.PagedRecyclerView, defStyleAttr,
-                R.style.PagedRecyclerView);
-
-        mScrollBarEnabled = a.getBoolean(R.styleable.PagedRecyclerView_scrollBarEnabled,
-                /* defValue= */true);
-        mFullyInitialized = false;
-
-        if (!mScrollBarEnabled) {
-            a.recycle();
-            mFullyInitialized = true;
-            return;
-        }
-
-        mNestedRecyclerView = new RecyclerView(context, attrs,
-                R.style.PagedRecyclerView_NestedRecyclerView);
-
-        super.setLayoutManager(new PagedRecyclerViewLayoutManager(context));
-        super.setAdapter(new PagedRecyclerViewAdapter());
-        super.setNestedScrollingEnabled(false);
-        super.setClipToPadding(false);
-
-        // Gutter
-        mGutter = a.getInt(R.styleable.PagedRecyclerView_gutter, Gutter.BOTH);
-        mGutterSize = getResources().getDimensionPixelSize(R.dimen.car_scroll_bar_margin);
-
-        int carMargin = getResources().getDimensionPixelSize(R.dimen.car_scroll_bar_margin);
-        mScrollBarContainerWidth = a.getDimensionPixelSize(
-                R.styleable.PagedRecyclerView_scrollBarContainerWidth, carMargin);
-
-        mScrollBarPosition = a.getInt(R.styleable.PagedRecyclerView_scrollBarPosition,
-                ScrollBarPosition.START);
-
-        mScrollBarAboveRecyclerView = a.getBoolean(
-                R.styleable.PagedRecyclerView_scrollBarAboveRecyclerView, /* defValue= */true);
-
-        mScrollBarClass = a.getString(R.styleable.PagedRecyclerView_scrollBarCustomClass);
-        a.recycle();
-
-        // Apply inner RV layout changes after the layout has been calculated for this view.
-        this.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
-            @Override
-            public void onGlobalLayout() {
-                // View holder layout is still pending.
-                if (PagedRecyclerView.this.findViewHolderForAdapterPosition(0) == null) return;
-
-                PagedRecyclerView.this.getViewTreeObserver().removeOnGlobalLayoutListener(this);
-                initNestedRecyclerView();
-                setNestedViewLayout();
-
-                createScrollBarFromConfig();
-
-                mNestedRecyclerView.getViewTreeObserver().addOnGlobalLayoutListener(
-                        new OnGlobalLayoutListener() {
-                            @Override
-                            public void onGlobalLayout() {
-                                mNestedRecyclerView.getViewTreeObserver()
-                                        .removeOnGlobalLayoutListener(this);
-                                mFullyInitialized = true;
-                            }
-                        });
-            }
-        });
-    }
-
-    /**
-     * Returns {@code true} if the {@PagedRecyclerView} is fully drawn. Using a global layout
-     * listener may not necessarily signify that this view is fully drawn (i.e. when the
-     * scrollbar is enabled). This is because the inner views (scrollbar and inner recycler view)
-     * are drawn after the outer views are finished.
-     */
-    public boolean fullyInitialized() {
-        return mFullyInitialized;
-    }
-
-    @Override
-    protected void onAttachedToWindow() {
-        super.onAttachedToWindow();
-        mCarUxRestrictionsUtil.register(mListener);
-    }
-
-    @Override
-    protected void onDetachedFromWindow() {
-        super.onDetachedFromWindow();
-        mCarUxRestrictionsUtil.unregister(mListener);
-    }
-
-    private void updateCarUxRestrictions(CarUxRestrictions carUxRestrictions) {
-        // If the adapter does not implement ItemCap, then the max items on it cannot be updated.
-        if (!(mAdapter instanceof ItemCap)) {
-            return;
-        }
-
-        int maxItems = ItemCap.UNLIMITED;
-        if ((carUxRestrictions.getActiveRestrictions()
-                & CarUxRestrictions.UX_RESTRICTIONS_LIMIT_CONTENT) != 0) {
-            maxItems = carUxRestrictions.getMaxCumulativeContentItems();
-        }
-
-        int originalCount = mAdapter.getItemCount();
-        ((ItemCap) mAdapter).setMaxItems(maxItems);
-        int newCount = mAdapter.getItemCount();
-
-        if (newCount == originalCount) {
-            return;
-        }
-
-        if (newCount < originalCount) {
-            mAdapter.notifyItemRangeRemoved(
-                    newCount, originalCount - newCount);
-        } else {
-            mAdapter.notifyItemRangeInserted(
-                    originalCount, newCount - originalCount);
-        }
-    }
-
-    @Override
-    public void setClipToPadding(boolean clipToPadding) {
-        if (mScrollBarEnabled) {
-            mNestedRecyclerView.setClipToPadding(clipToPadding);
-        } else {
-            super.setClipToPadding(clipToPadding);
-        }
-    }
-
-    @Override
-    public void setAdapter(@Nullable Adapter adapter) {
-        mAdapter = adapter;
-        if (mScrollBarEnabled) {
-            mNestedRecyclerView.setAdapter(adapter);
-        } else {
-            super.setAdapter(adapter);
-        }
-    }
-
-    @Nullable
-    @Override
-    public Adapter getAdapter() {
-        if (mScrollBarEnabled) {
-            return mNestedRecyclerView.getAdapter();
-        }
-        return super.getAdapter();
-    }
-
-    @Override
-    public void setLayoutManager(@Nullable LayoutManager layout) {
-        if (mScrollBarEnabled) {
-            mNestedRecyclerView.setLayoutManager(layout);
-        } else {
-            super.setLayoutManager(layout);
-        }
-    }
-
-    /**
-     * Returns the {@link LayoutManager} for the {@link RecyclerView} displaying the content.
-     *
-     * <p>In cases where the scroll bar is visible and the nested {@link RecyclerView} is
-     * displaying content, {@link #getLayoutManager()} cannot be used because it returns the
-     * {@link LayoutManager} of the outer {@link RecyclerView}. {@link #getLayoutManager()} could
-     * not be overridden to return the effective manager due to interference with accessibility
-     * node tree traversal.
-     */
-    @Nullable
-    public LayoutManager getEffectiveLayoutManager() {
-        if (mScrollBarEnabled) {
-            return mNestedRecyclerView.getLayoutManager();
-        }
-        return super.getLayoutManager();
-    }
-
-    @Override
-    public void setOnScrollChangeListener(OnScrollChangeListener l) {
-        if (mScrollBarEnabled) {
-            mNestedRecyclerView.setOnScrollChangeListener(l);
-        } else {
-            super.setOnScrollChangeListener(l);
-        }
-    }
-
-    @Override
-    public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
-        if (mScrollBarEnabled) {
-            mNestedRecyclerView.setVerticalFadingEdgeEnabled(verticalFadingEdgeEnabled);
-        } else {
-            super.setVerticalFadingEdgeEnabled(verticalFadingEdgeEnabled);
-        }
-    }
-
-    @Override
-    public void setFadingEdgeLength(int length) {
-        if (mScrollBarEnabled) {
-            mNestedRecyclerView.setFadingEdgeLength(length);
-        } else {
-            super.setFadingEdgeLength(length);
-        }
-    }
-
-    @Override
-    public void addItemDecoration(@NonNull ItemDecoration decor, int index) {
-        if (mScrollBarEnabled) {
-            mNestedRecyclerView.addItemDecoration(decor, index);
-        } else {
-            super.addItemDecoration(decor, index);
-        }
-    }
-
-    @Override
-    public void addItemDecoration(@NonNull ItemDecoration decor) {
-        if (mScrollBarEnabled) {
-            mNestedRecyclerView.addItemDecoration(decor);
-        } else {
-            super.addItemDecoration(decor);
-        }
-    }
-
-    @Override
-    public void setItemAnimator(@Nullable ItemAnimator animator) {
-        if (mScrollBarEnabled) {
-            mNestedRecyclerView.setItemAnimator(animator);
-        } else {
-            super.setItemAnimator(animator);
-        }
-    }
-
-    @Override
-    public void setPadding(int left, int top, int right, int bottom) {
-        if (mScrollBarEnabled) {
-            mNestedRecyclerView.setPadding(left, top, right, bottom);
-            if (mScrollBarUI != null) mScrollBarUI.requestLayout();
-        } else {
-            super.setPadding(left, top, right, bottom);
-        }
-    }
-
-    @Override
-    public void setPaddingRelative(int start, int top, int end, int bottom) {
-        if (mScrollBarEnabled) {
-            mNestedRecyclerView.setPaddingRelative(start, top, end, bottom);
-            if (mScrollBarUI != null) mScrollBarUI.requestLayout();
-        } else {
-            super.setPaddingRelative(start, top, end, bottom);
-        }
-    }
-
-    @Override
-    public ViewHolder findViewHolderForLayoutPosition(int position) {
-        if (mScrollBarEnabled) {
-            return mNestedRecyclerView.findViewHolderForLayoutPosition(position);
-        } else {
-            return super.findViewHolderForLayoutPosition(position);
-        }
-    }
-
-    @Override
-    public ViewHolder findContainingViewHolder(View view) {
-        if (mScrollBarEnabled) {
-            return mNestedRecyclerView.findContainingViewHolder(view);
-        } else {
-            return super.findContainingViewHolder(view);
-        }
-    }
-
-    @Override
-    @Nullable
-    public View findChildViewUnder(float x, float y) {
-        if (mScrollBarEnabled) {
-            return mNestedRecyclerView.findChildViewUnder(x, y);
-        } else {
-            return super.findChildViewUnder(x, y);
-        }
-    }
-
-    @Override
-    public void addOnScrollListener(@NonNull OnScrollListener listener) {
-        if (mScrollBarEnabled) {
-            mNestedRecyclerView.addOnScrollListener(listener);
-        } else {
-            super.addOnScrollListener(listener);
-        }
-    }
-
-    @Override
-    public void removeOnScrollListener(@NonNull OnScrollListener listener) {
-        if (mScrollBarEnabled) {
-            mNestedRecyclerView.removeOnScrollListener(listener);
-        } else {
-            super.removeOnScrollListener(listener);
-        }
-    }
-
-    /**
-     * Calls {@link #layout(int, int, int, int)} for both this RecyclerView and the nested one.
-     */
-    @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
-    public void layoutBothForTesting(int l, int t, int r, int b) {
-        super.layout(l, t, r, b);
-        if (mScrollBarEnabled) {
-            mNestedRecyclerView.layout(l, t, r, b);
-        }
-    }
-
-    @Override
-    public int getPaddingStart() {
-        return mScrollBarEnabled ? mNestedRecyclerView.getPaddingStart() : super.getPaddingStart();
-    }
-
-    @Override
-    public int getPaddingEnd() {
-        return mScrollBarEnabled ? mNestedRecyclerView.getPaddingEnd() : super.getPaddingEnd();
-    }
-
-    @Override
-    public int getPaddingTop() {
-        return mScrollBarEnabled ? mNestedRecyclerView.getPaddingTop() : super.getPaddingTop();
-    }
-
-    @Override
-    public int getPaddingBottom() {
-        return mScrollBarEnabled ? mNestedRecyclerView.getPaddingBottom()
-                : super.getPaddingBottom();
-    }
-
-    @Override
-    public void setVisibility(int visibility) {
-        super.setVisibility(visibility);
-        if (mScrollBarEnabled) {
-            mNestedRecyclerView.setVisibility(visibility);
-        }
-    }
-
-    private void initNestedRecyclerView() {
-        PagedRecyclerViewAdapter.NestedRowViewHolder vh =
-                (PagedRecyclerViewAdapter.NestedRowViewHolder)
-                        this.findViewHolderForAdapterPosition(0);
-        if (vh == null) {
-            throw new Error("Outer RecyclerView failed to initialize.");
-        }
-
-        vh.mFrameLayout.addView(mNestedRecyclerView);
-    }
-
-    private void createScrollBarFromConfig() {
-        if (DEBUG) Log.d(TAG, "createScrollBarFromConfig");
-        final String clsName = mScrollBarClass == null
-                ? getContext().getString(R.string.config_scrollBarComponent) : mScrollBarClass;
-        if (clsName == null || clsName.length() == 0) {
-            throw andLog("No scroll bar component configured", null);
-        }
-
-        Class<?> cls;
-        try {
-            cls = getContext().getClassLoader().loadClass(clsName);
-        } catch (Throwable t) {
-            throw andLog("Error loading scroll bar component: " + clsName, t);
-        }
-        try {
-            mScrollBarUI = (ScrollBarUI) cls.newInstance();
-        } catch (Throwable t) {
-            throw andLog("Error creating scroll bar component: " + clsName, t);
-        }
-
-        mScrollBarUI.initialize(getContext(), mNestedRecyclerView, mScrollBarContainerWidth,
-                mScrollBarPosition, mScrollBarAboveRecyclerView);
-
-        mScrollBarUI.setPadding(mScrollBarPaddingStart, mScrollBarPaddingEnd);
-
-        if (DEBUG) Log.d(TAG, "started " + mScrollBarUI.getClass().getSimpleName());
-    }
-
-    /**
-     * Sets the scrollbar's padding start (top) and end (bottom).
-     * This padding is applied in addition to the padding of the inner RecyclerView.
-     */
-    public void setScrollBarPadding(int paddingStart, int paddingEnd) {
-        if (mScrollBarEnabled) {
-            mScrollBarPaddingStart = paddingStart;
-            mScrollBarPaddingEnd = paddingEnd;
-
-            if (mScrollBarUI != null) {
-                mScrollBarUI.setPadding(paddingStart, paddingEnd);
-            }
-        }
-    }
-
-    /**
-     * Set the nested view's layout to the specified value.
-     *
-     * <p>The gutter is the space to the start/end of the list view items and will be equal in size
-     * to the scroll bars. By default, there is a gutter to both the left and right of the list
-     * view items, to account for the scroll bar.
-     */
-    private void setNestedViewLayout() {
-        int startMargin = 0;
-        int endMargin = 0;
-        if ((mGutter & Gutter.START) != 0) {
-            startMargin = mGutterSize;
-        }
-        if ((mGutter & Gutter.END) != 0) {
-            endMargin = mGutterSize;
-        }
-
-        MarginLayoutParams layoutParams =
-                (MarginLayoutParams) mNestedRecyclerView.getLayoutParams();
-
-        layoutParams.setMarginStart(startMargin);
-        layoutParams.setMarginEnd(endMargin);
-
-        layoutParams.height = LayoutParams.MATCH_PARENT;
-        layoutParams.width = super.getLayoutManager().getWidth() - startMargin - endMargin;
-        // requestLayout() isn't sufficient because we also need to resolveLayoutParams().
-        mNestedRecyclerView.setLayoutParams(layoutParams);
-
-        // If there's a gutter, set ClipToPadding to false so that CardView's shadow will still
-        // appear outside of the padding.
-        mNestedRecyclerView.setClipToPadding(startMargin == 0 && endMargin == 0);
-    }
-
-    private RuntimeException andLog(String msg, Throwable t) {
-        Log.e(TAG, msg, t);
-        throw new RuntimeException(msg, t);
-    }
-
-    @Override
-    public Parcelable onSaveInstanceState() {
-        Parcelable superState = super.onSaveInstanceState();
-        SavedState ss = new SavedState(superState, getContext());
-        if (mScrollBarEnabled) {
-            mNestedRecyclerView.saveHierarchyState(ss.mNestedRecyclerViewState);
-        }
-        return ss;
-    }
-
-    @Override
-    public void onRestoreInstanceState(Parcelable state) {
-        if (!(state instanceof SavedState)) {
-            Log.w(TAG, "onRestoreInstanceState called with an unsupported state");
-            super.onRestoreInstanceState(state);
-        } else {
-            SavedState ss = (SavedState) state;
-            super.onRestoreInstanceState(ss.getSuperState());
-            if (mScrollBarEnabled) {
-                mNestedRecyclerView.restoreHierarchyState(ss.mNestedRecyclerViewState);
-            }
-        }
-    }
-
-    static class SavedState extends BaseSavedState {
-        SparseArray mNestedRecyclerViewState;
-        Context mContext;
-
-        SavedState(Parcelable superState, Context c) {
-            super(superState);
-            mContext = c;
-            mNestedRecyclerViewState = new SparseArray();
-        }
-
-        private SavedState(Parcel source, ClassLoader loader) {
-            super(source, loader);
-            mNestedRecyclerViewState = source.readSparseArray(loader);
-        }
-
-        @Override
-        public void writeToParcel(Parcel out, int flags) {
-            super.writeToParcel(out, flags);
-            out.writeSparseArray(mNestedRecyclerViewState);
-        }
-
-        public static final Parcelable.Creator<SavedState> CREATOR =
-                new Parcelable.Creator<SavedState>() {
-            public SavedState createFromParcel(Parcel in) {
-                return new SavedState(in, getClass().getClassLoader());
-            }
-
-            public SavedState[] newArray(int size) {
-                return new SavedState[size];
-            }
-        };
-    }
-}
diff --git a/car-apps-common/src/com/android/car/apps/common/widget/PagedRecyclerViewAdapter.java b/car-apps-common/src/com/android/car/apps/common/widget/PagedRecyclerViewAdapter.java
deleted file mode 100644
index bc35a37..0000000
--- a/car-apps-common/src/com/android/car/apps/common/widget/PagedRecyclerViewAdapter.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.car.apps.common.widget;
-
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.FrameLayout;
-
-import androidx.recyclerview.widget.RecyclerView;
-
-import com.android.car.apps.common.R;
-
-/**
- * The adapter for the parent recyclerview in {@link PagedRecyclerView} widget.
- */
-final class PagedRecyclerViewAdapter
-        extends RecyclerView.Adapter<PagedRecyclerViewAdapter.NestedRowViewHolder> {
-
-    @Override
-    public PagedRecyclerViewAdapter.NestedRowViewHolder onCreateViewHolder(ViewGroup parent,
-            int viewType) {
-        View v = LayoutInflater.from(parent.getContext())
-                .inflate(R.layout.paged_recycler_view_item, parent, false);
-        return new NestedRowViewHolder(v);
-    }
-
-    // Replace the contents of a view (invoked by the layout manager). Intentionally left empty
-    // since this adapter is an empty shell for the nested recyclerview.
-    @Override
-    public void onBindViewHolder(NestedRowViewHolder holder, int position) {
-    }
-
-    // Return the size of your dataset (invoked by the layout manager)
-    @Override
-    public int getItemCount() {
-        return 1;
-    }
-
-    /**
-     * The viewholder class for the parent recyclerview.
-     */
-    static class NestedRowViewHolder extends RecyclerView.ViewHolder {
-        public FrameLayout mFrameLayout;
-
-        NestedRowViewHolder(View view) {
-            super(view);
-            mFrameLayout = view.findViewById(R.id.nested_recycler_view_layout);
-        }
-    }
-}
diff --git a/car-apps-common/tests/Android.mk b/car-apps-common/tests/Android.mk
deleted file mode 100644
index 9f0a4e8..0000000
--- a/car-apps-common/tests/Android.mk
+++ /dev/null
@@ -1,19 +0,0 @@
-# Copyright (C) 2019 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-# Include all makefiles in subdirectories
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/car-apps-common/tests/robotests/Android.mk b/car-apps-common/tests/robotests/Android.mk
deleted file mode 100644
index 2438678..0000000
--- a/car-apps-common/tests/robotests/Android.mk
+++ /dev/null
@@ -1,73 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-############################################################
-# CarAppsCommon app just for Robolectric test target.     #
-############################################################
-include $(CLEAR_VARS)
-
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-
-LOCAL_PACKAGE_NAME := CarAppsCommon
-LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_USE_AAPT2 := true
-
-LOCAL_PRIVILEGED_MODULE := true
-
-LOCAL_JAVA_LIBRARIES := android.car
-
-LOCAL_STATIC_ANDROID_LIBRARIES := \
-    car-apps-common
-
-include $(BUILD_PACKAGE)
-
-################################################
-# Car Apps Common Robolectric test target. #
-################################################
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := CarAppsCommonRoboTests
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_JAVA_RESOURCE_DIRS := config
-
-# Include the testing libraries
-LOCAL_JAVA_LIBRARIES := \
-    android.car \
-    robolectric_android-all-stub \
-    Robolectric_all-target \
-    mockito-robolectric-prebuilt \
-    truth-prebuilt
-
-
-LOCAL_INSTRUMENTATION_FOR := CarAppsCommon
-
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
-##################################################################
-# Car Apps Common runner target to run the previous target. #
-##################################################################
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := RunCarAppsCommonRoboTests
-
-LOCAL_JAVA_LIBRARIES := \
-    android.car \
-    CarAppsCommonRoboTests \
-    robolectric_android-all-stub \
-    Robolectric_all-target \
-    mockito-robolectric-prebuilt \
-    truth-prebuilt
-
-LOCAL_TEST_PACKAGE := CarAppsCommon
-
-LOCAL_ROBOTEST_FILES := $(filter-out %/BaseRobolectricTest.java,\
-    $(call find-files-in-subdirs,$(LOCAL_PATH)/src,*Test.java,.))
-
-LOCAL_INSTRUMENT_SOURCE_DIRS := $(dir $(LOCAL_PATH))../src
-
-include external/robolectric-shadows/run_robotests.mk
diff --git a/car-apps-common/tests/robotests/AndroidManifest.xml b/car-apps-common/tests/robotests/AndroidManifest.xml
deleted file mode 100644
index 81f5739..0000000
--- a/car-apps-common/tests/robotests/AndroidManifest.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-    Copyright (C) 2019 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
--->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-          package="com.android.car.apps.common.robotests">
-</manifest>
diff --git a/car-apps-common/tests/robotests/config/robolectric.properties b/car-apps-common/tests/robotests/config/robolectric.properties
deleted file mode 100644
index fa63823..0000000
--- a/car-apps-common/tests/robotests/config/robolectric.properties
+++ /dev/null
@@ -1,17 +0,0 @@
-#
-# Copyright (C) 2019 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-manifest=packages/apps/Car/libs/car-apps-common/tests/robotests/AndroidManifest.xml
-sdk=NEWEST_SDK
diff --git a/car-apps-common/tests/robotests/src/com/android/car/apps/common/CarUxRestrictionsUtilTest.java b/car-apps-common/tests/robotests/src/com/android/car/apps/common/CarUxRestrictionsUtilTest.java
deleted file mode 100755
index 2cadad3..0000000
--- a/car-apps-common/tests/robotests/src/com/android/car/apps/common/CarUxRestrictionsUtilTest.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.car.apps.common;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.car.drivingstate.CarUxRestrictions;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.annotation.Config;
-
-@RunWith(RobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
-public class CarUxRestrictionsUtilTest {
-    private int[] mRestrictionsArray;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        mRestrictionsArray = new int[]{
-                CarUxRestrictions.UX_RESTRICTIONS_NO_DIALPAD,
-                CarUxRestrictions.UX_RESTRICTIONS_NO_KEYBOARD,
-                CarUxRestrictions.UX_RESTRICTIONS_NO_DIALPAD
-                        | CarUxRestrictions.UX_RESTRICTIONS_NO_KEYBOARD,
-                CarUxRestrictions.UX_RESTRICTIONS_FULLY_RESTRICTED
-        };
-    }
-
-    @Test
-    public void testNullActiveRestriction() {
-        CarUxRestrictions activeRestrictions = null;
-        boolean[] expectedResults = {true, true, true, true};
-        for (int i = 0; i < mRestrictionsArray.length; i++) {
-            boolean actualResult = CarUxRestrictionsUtil.isRestricted(mRestrictionsArray[i],
-                    activeRestrictions);
-            assertThat(actualResult == expectedResults[i]).isTrue();
-        }
-    }
-
-    @Test
-    public void testOneActiveRestriction() {
-        CarUxRestrictions activeRestrictions = new CarUxRestrictions.Builder(/* reqOpt= */true,
-                CarUxRestrictions.UX_RESTRICTIONS_NO_DIALPAD, /* timestamp= */0).build();
-        boolean[] expectedResults = {true, false, true, true};
-        for (int i = 0; i < mRestrictionsArray.length; i++) {
-            boolean actualResult = CarUxRestrictionsUtil.isRestricted(mRestrictionsArray[i],
-                    activeRestrictions);
-            assertThat(actualResult == expectedResults[i]).isTrue();
-        }
-    }
-
-    @Test
-    public void testMultipleActiveRestrictions() {
-        CarUxRestrictions activeRestrictions = new CarUxRestrictions.Builder(/* reqOpt= */true,
-                CarUxRestrictions.UX_RESTRICTIONS_NO_DIALPAD
-                        | CarUxRestrictions.UX_RESTRICTIONS_NO_TEXT_MESSAGE, /* timestamp= */
-                0).build();
-        boolean[] expectedResults = {true, false, true, true};
-        for (int i = 0; i < mRestrictionsArray.length; i++) {
-            boolean actualResult = CarUxRestrictionsUtil.isRestricted(mRestrictionsArray[i],
-                    activeRestrictions);
-            assertThat(actualResult == expectedResults[i]).isTrue();
-        }
-    }
-}
diff --git a/car-apps-common/tests/robotests/src/com/android/car/apps/common/TestConfig.java b/car-apps-common/tests/robotests/src/com/android/car/apps/common/TestConfig.java
deleted file mode 100644
index baf9b51..0000000
--- a/car-apps-common/tests/robotests/src/com/android/car/apps/common/TestConfig.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.car.apps.common;
-
-public class TestConfig {
-    public static final int SDK_VERSION = 23;
-    public static final String MANIFEST_PATH =
-            "packages/apps/Car/car-apps-common/AndroidManifest.xml";
-}
diff --git a/car-arch-common/Android.bp b/car-arch-common/Android.bp
new file mode 100644
index 0000000..6272d40
--- /dev/null
+++ b/car-arch-common/Android.bp
@@ -0,0 +1,36 @@
+//
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// This is an unbundled target, sdk_version must be "system_current". If the car library is ever
+// needed, android."car-stubs" or "android.car-system-stubs" must be used.
+android_library {
+    name: "car-arch-common",
+
+    srcs: ["src/**/*.java"],
+
+    optimize: {
+        enabled: false,
+    },
+
+    sdk_version: "system_current",
+
+    static_libs: [
+        "androidx.lifecycle_lifecycle-extensions",
+        "androidx.lifecycle_lifecycle-common-java8",
+        "androidx.annotation_annotation",
+        "junit",
+    ],
+}
diff --git a/car-arch-common/Android.mk b/car-arch-common/Android.mk
deleted file mode 100644
index 712f170..0000000
--- a/car-arch-common/Android.mk
+++ /dev/null
@@ -1,49 +0,0 @@
-#
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-
-LOCAL_MODULE := car-arch-common
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_PRIVILEGED_MODULE := true
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-LOCAL_USE_AAPT2 := true
-
-LOCAL_STATIC_ANDROID_LIBRARIES := \
-    androidx.lifecycle_lifecycle-extensions \
-    androidx.lifecycle_lifecycle-common-java8 \
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
-    androidx.annotation_annotation \
-    junit \
-
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
-ifeq (,$(ONE_SHOT_MAKEFILE))
-    include $(call all-makefiles-under,$(LOCAL_PATH))
-endif
diff --git a/car-arch-common/src/com/android/car/arch/common/LiveDataFunctions.java b/car-arch-common/src/com/android/car/arch/common/LiveDataFunctions.java
index 632096b..1fc4ff1 100644
--- a/car-arch-common/src/com/android/car/arch/common/LiveDataFunctions.java
+++ b/car-arch-common/src/com/android/car/arch/common/LiveDataFunctions.java
@@ -18,9 +18,8 @@
 
 import static java.util.Objects.requireNonNull;
 
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 import androidx.arch.core.util.Function;
 import androidx.core.util.Pair;
 import androidx.lifecycle.LiveData;
diff --git a/car-arch-common/src/com/android/car/arch/common/testing/CaptureObserver.java b/car-arch-common/src/com/android/car/arch/common/testing/CaptureObserver.java
index 625d48c..f553609 100644
--- a/car-arch-common/src/com/android/car/arch/common/testing/CaptureObserver.java
+++ b/car-arch-common/src/com/android/car/arch/common/testing/CaptureObserver.java
@@ -17,8 +17,7 @@
 package com.android.car.arch.common.testing;
 
 
-import android.annotation.Nullable;
-
+import androidx.annotation.Nullable;
 import androidx.annotation.RestrictTo;
 import androidx.lifecycle.Observer;
 
diff --git a/car-arch-common/src/com/android/car/arch/common/testing/TestLifecycleOwner.java b/car-arch-common/src/com/android/car/arch/common/testing/TestLifecycleOwner.java
index 540581d..c27b51e 100644
--- a/car-arch-common/src/com/android/car/arch/common/testing/TestLifecycleOwner.java
+++ b/car-arch-common/src/com/android/car/arch/common/testing/TestLifecycleOwner.java
@@ -16,8 +16,7 @@
 
 package com.android.car.arch.common.testing;
 
-import android.annotation.NonNull;
-
+import androidx.annotation.NonNull;
 import androidx.annotation.RestrictTo;
 import androidx.lifecycle.Lifecycle;
 import androidx.lifecycle.LifecycleOwner;
diff --git a/car-arch-common/tests/Android.mk b/car-arch-common/tests/Android.mk
deleted file mode 100644
index 0903c90..0000000
--- a/car-arch-common/tests/Android.mk
+++ /dev/null
@@ -1,19 +0,0 @@
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-# Include all makefiles in subdirectories
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/car-arch-common/tests/robotests/Android.bp b/car-arch-common/tests/robotests/Android.bp
new file mode 100644
index 0000000..dbe65bf
--- /dev/null
+++ b/car-arch-common/tests/robotests/Android.bp
@@ -0,0 +1,47 @@
+//
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+//###########################################################
+// CarArchCommon app just for Robolectric test target.     #
+//###########################################################
+android_app {
+    name: "CarArchCommon",
+
+    platform_apis: true,
+
+    privileged: true,
+
+    static_libs: ["car-arch-common"],
+}
+
+//###############################################
+// Car Arch Common Robolectric test target. #
+//###############################################
+android_robolectric_test {
+    name: "CarArchCommonRoboTests",
+
+    srcs: ["src/**/*.java"],
+
+    java_resource_dirs: ["config"],
+
+    // Include the testing libraries
+    libs: [
+        "androidx.arch.core_core-runtime",
+        "androidx.arch.core_core-common",
+    ],
+
+    instrumentation_for: "CarArchCommon",
+}
diff --git a/car-arch-common/tests/robotests/Android.mk b/car-arch-common/tests/robotests/Android.mk
deleted file mode 100644
index 83ba038..0000000
--- a/car-arch-common/tests/robotests/Android.mk
+++ /dev/null
@@ -1,86 +0,0 @@
-#
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-############################################################
-# CarArchCommon app just for Robolectric test target.     #
-############################################################
-include $(CLEAR_VARS)
-
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-
-LOCAL_PACKAGE_NAME := CarArchCommon
-LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_USE_AAPT2 := true
-
-LOCAL_PRIVILEGED_MODULE := true
-
-LOCAL_STATIC_ANDROID_LIBRARIES := \
-    car-arch-common
-
-include $(BUILD_PACKAGE)
-
-################################################
-# Car Arch Common Robolectric test target. #
-################################################
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := CarArchCommonRoboTests
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_JAVA_RESOURCE_DIRS := config
-
-# Include the testing libraries
-LOCAL_JAVA_LIBRARIES := \
-    androidx.arch.core_core-runtime \
-    androidx.arch.core_core-common \
-    robolectric_android-all-stub \
-    Robolectric_all-target \
-    mockito-robolectric-prebuilt \
-    truth-prebuilt
-
-LOCAL_INSTRUMENTATION_FOR := CarArchCommon
-
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
-##################################################################
-# Car Arch Common runner target to run the previous target. #
-##################################################################
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := RunCarArchCommonRoboTests
-
-LOCAL_JAVA_LIBRARIES := \
-    CarArchCommonRoboTests \
-    robolectric_android-all-stub \
-    Robolectric_all-target \
-    mockito-robolectric-prebuilt \
-    truth-prebuilt
-
-LOCAL_TEST_PACKAGE := CarArchCommon
-
-LOCAL_ROBOTEST_FILES := $(filter-out %/BaseRobolectricTest.java,\
-    $(call find-files-in-subdirs,$(LOCAL_PATH)/src,*Test.java,.))
-
-LOCAL_INSTRUMENT_SOURCE_DIRS := $(dir $(LOCAL_PATH))../src
-
-include external/robolectric-shadows/run_robotests.mk
diff --git a/car-arch-common/tests/robotests/config/robolectric.properties b/car-arch-common/tests/robotests/config/robolectric.properties
index 6b56350..4c863dc 100644
--- a/car-arch-common/tests/robotests/config/robolectric.properties
+++ b/car-arch-common/tests/robotests/config/robolectric.properties
@@ -13,5 +13,4 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
-manifest=packages/apps/Car/libs/car-arch-common/tests/robotests/AndroidManifest.xml
 sdk=NEWEST_SDK
diff --git a/car-arch-common/tests/robotests/src/com/android/car/arch/common/LiveDataFunctionsTest.java b/car-arch-common/tests/robotests/src/com/android/car/arch/common/LiveDataFunctionsTest.java
index d41db9f..cdcfcb0 100644
--- a/car-arch-common/tests/robotests/src/com/android/car/arch/common/LiveDataFunctionsTest.java
+++ b/car-arch-common/tests/robotests/src/com/android/car/arch/common/LiveDataFunctionsTest.java
@@ -42,7 +42,6 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.robolectric.RobolectricTestRunner;
-import org.robolectric.annotation.Config;
 
 import java.util.Objects;
 import java.util.function.BiFunction;
@@ -50,7 +49,6 @@
 import java.util.function.Supplier;
 
 @RunWith(RobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class LiveDataFunctionsTest {
 
     @Rule
diff --git a/car-arch-common/tests/robotests/src/com/android/car/arch/common/LoadingSwitchMapTest.java b/car-arch-common/tests/robotests/src/com/android/car/arch/common/LoadingSwitchMapTest.java
index fd3d883..d64a0c1 100644
--- a/car-arch-common/tests/robotests/src/com/android/car/arch/common/LoadingSwitchMapTest.java
+++ b/car-arch-common/tests/robotests/src/com/android/car/arch/common/LoadingSwitchMapTest.java
@@ -32,10 +32,8 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.robolectric.RobolectricTestRunner;
-import org.robolectric.annotation.Config;
 
 @RunWith(RobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class LoadingSwitchMapTest {
 
     @Rule
diff --git a/car-arch-common/tests/robotests/src/com/android/car/arch/common/TestConfig.java b/car-arch-common/tests/robotests/src/com/android/car/arch/common/TestConfig.java
deleted file mode 100644
index 1ae5174..0000000
--- a/car-arch-common/tests/robotests/src/com/android/car/arch/common/TestConfig.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.car.arch.common;
-
-public class TestConfig {
-    public static final int SDK_VERSION = 23;
-    public static final String MANIFEST_PATH =
-            "packages/apps/Car/car-arch-common/AndroidManifest.xml";
-}
diff --git a/car-assist-client-lib/src/com/android/car/assist/client/FallbackAssistant.java b/car-assist-client-lib/src/com/android/car/assist/client/FallbackAssistant.java
index db13ab1..fe8c5ae 100644
--- a/car-assist-client-lib/src/com/android/car/assist/client/FallbackAssistant.java
+++ b/car-assist-client-lib/src/com/android/car/assist/client/FallbackAssistant.java
@@ -115,7 +115,6 @@
         }
 
         List<CharSequence> messages = new ArrayList<>();
-
         List<Message> messageList = Message.getMessagesFromBundleArray(messagesBundle);
         if (messageList == null || messageList.isEmpty()) {
             Log.w(TAG, "No messages could be extracted from the bundle");
diff --git a/car-broadcastradio-support/Android.bp b/car-broadcastradio-support/Android.bp
new file mode 100644
index 0000000..cf0b1bb
--- /dev/null
+++ b/car-broadcastradio-support/Android.bp
@@ -0,0 +1,33 @@
+//
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+android_library {
+    name: "car-broadcastradio-support",
+
+    srcs: ["src/**/*.java"],
+    aidl: {
+        export_include_dirs: ["src"],
+    },
+    resource_dirs: ["res"],
+
+    optimize: {
+        enabled: false,
+    },
+
+    dist: {
+        targets: ["dist_files"],
+    },
+}
diff --git a/car-broadcastradio-support/Android.mk b/car-broadcastradio-support/Android.mk
deleted file mode 100644
index 67f37ef..0000000
--- a/car-broadcastradio-support/Android.mk
+++ /dev/null
@@ -1,37 +0,0 @@
-#
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := car-broadcastradio-support
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_AIDL_INCLUDES := $(LOCAL_PATH)/src
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-
-LOCAL_MODULE_TAGS := optional
-LOCAL_PRIVILEGED_MODULE := true
-
-LOCAL_PROGUARD_ENABLED := disabled
-LOCAL_USE_AAPT2 := true
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
-ifeq ($(BOARD_IS_AUTOMOTIVE), true)
-$(call dist-for-goals,dist_files,$(full_classes_jar):$(LOCAL_MODULE).jar)
-endif
diff --git a/car-media-common/Android.bp b/car-media-common/Android.bp
new file mode 100644
index 0000000..b85ea3b
--- /dev/null
+++ b/car-media-common/Android.bp
@@ -0,0 +1,41 @@
+//
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+android_library {
+    name: "car-media-common",
+
+    srcs: ["src/**/*.java"],
+
+    resource_dirs: ["res"],
+
+    optimize: {
+        enabled: false,
+    },
+
+    static_libs: [
+        "androidx.cardview_cardview",
+        "androidx.legacy_legacy-support-v4",
+        "androidx.recyclerview_recyclerview",
+        "androidx.mediarouter_mediarouter",
+        "androidx-constraintlayout_constraintlayout",
+        "car-apps-common",
+        "car-arch-common",
+        "androidx-constraintlayout_constraintlayout-solver",
+    ],
+
+    libs: ["android.car-system-stubs"],
+    sdk_version: "system_current",
+}
diff --git a/car-media-common/Android.mk b/car-media-common/Android.mk
deleted file mode 100644
index c5041c4..0000000
--- a/car-media-common/Android.mk
+++ /dev/null
@@ -1,86 +0,0 @@
-#
-# Copyright (C) 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-
-LOCAL_MODULE := car-media-common
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_PRIVILEGED_MODULE := true
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-LOCAL_STATIC_ANDROID_LIBRARIES += \
-    androidx.cardview_cardview \
-    androidx.legacy_legacy-support-v4 \
-    androidx.recyclerview_recyclerview \
-    androidx.mediarouter_mediarouter \
-    androidx-constraintlayout_constraintlayout \
-    car-apps-common \
-    car-arch-common
-
-LOCAL_STATIC_JAVA_LIBRARIES += \
-    androidx-constraintlayout_constraintlayout-solver
-
-LOCAL_USE_AAPT2 := true
-
-LOCAL_JAVA_LIBRARIES += android.car
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_CLASS := JAVA_LIBRARIES
-LOCAL_MODULE := car-media-common-disklrucache-target
-LOCAL_SDK_VERSION := current
-LOCAL_SRC_FILES := ../../../../../prebuilts/maven_repo/bumptech/com/github/bumptech/glide/disklrucache/SNAPSHOT/disklrucache-SNAPSHOT$(COMMON_JAVA_PACKAGE_SUFFIX)
-LOCAL_JETIFIER_ENABLED := true
-LOCAL_UNINSTALLABLE_MODULE := true
-
-include $(BUILD_PREBUILT)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_CLASS := JAVA_LIBRARIES
-LOCAL_MODULE := car-media-common-gifdecoder-target
-LOCAL_SDK_VERSION := current
-LOCAL_SRC_FILES := ../../../../../prebuilts/maven_repo/bumptech/com/github/bumptech/glide/gifdecoder/SNAPSHOT/gifdecoder-SNAPSHOT$(COMMON_JAVA_PACKAGE_SUFFIX)
-LOCAL_JETIFIER_ENABLED := true
-LOCAL_UNINSTALLABLE_MODULE := true
-
-include $(BUILD_PREBUILT)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_CLASS := JAVA_LIBRARIES
-LOCAL_MODULE := car-media-common-glide-target
-LOCAL_SDK_VERSION := current
-LOCAL_SRC_FILES := ../../../../../prebuilts/maven_repo/bumptech/com/github/bumptech/glide/glide/SNAPSHOT/glide-SNAPSHOT$(COMMON_JAVA_PACKAGE_SUFFIX)
-LOCAL_JETIFIER_ENABLED := true
-LOCAL_UNINSTALLABLE_MODULE := true
-
-include $(BUILD_PREBUILT)
-
-ifeq (,$(ONE_SHOT_MAKEFILE))
-    include $(call all-makefiles-under,$(LOCAL_PATH))
-endif
\ No newline at end of file
diff --git a/car-media-common/res/drawable/fab_empty_foreground.xml b/car-media-common/res/drawable/fab_empty_foreground.xml
index 8af802a..d9fb901 100644
--- a/car-media-common/res/drawable/fab_empty_foreground.xml
+++ b/car-media-common/res/drawable/fab_empty_foreground.xml
@@ -17,4 +17,4 @@
 <ripple
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:radius="0dp"
-    android:color="@*android:color/car_card" />
+    android:color="@color/car_dark_blue_grey_700" />
diff --git a/car-media-common/res/layout/playback_fragment.xml b/car-media-common/res/layout/playback_fragment.xml
index 6d751cc..5575087 100644
--- a/car-media-common/res/layout/playback_fragment.xml
+++ b/car-media-common/res/layout/playback_fragment.xml
@@ -27,7 +27,8 @@
         android:foreground="?android:attr/selectableItemBackground"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
-        android:scaleType="fitStart" />
+        android:focusable="false"
+        android:scaleType="fitStart"/>
 
     <View
         android:id="@+id/playback_scrim"
@@ -36,92 +37,98 @@
         android:background="@color/album_art_scrim"
         android:alpha="@dimen/album_art_scrim_alpha"/>
 
-    <androidx.constraintlayout.widget.ConstraintLayout
-        android:id="@+id/playback_container"
+    <com.android.car.ui.FocusArea
         android:layout_width="match_parent"
         android:layout_height="match_parent">
 
-        <ImageView
-            android:id="@+id/app_icon"
-            android:layout_width="@dimen/app_selector_icon_size"
-            android:layout_height="@dimen/app_selector_icon_size"
-            android:layout_gravity="center"
-            android:layout_marginLeft="@dimen/playback_fragment_text_margin_x"
-            android:background="?android:attr/selectableItemBackground"
-            android:src="@drawable/ic_app_switch"
-            app:layout_constraintTop_toTopOf="@+id/app_name"
-            app:layout_constraintBottom_toBottomOf="@+id/app_name"
-            app:layout_constraintLeft_toLeftOf="parent"/>
-
-        <TextView
-            android:id="@+id/app_name"
-            android:layout_width="0dp"
-            android:layout_height="wrap_content"
-            android:layout_marginTop="@dimen/playback_fragment_text_margin_top"
-            android:layout_marginLeft="@dimen/playback_fragment_text_margin_x"
-            android:layout_marginRight="@dimen/playback_fragment_text_margin_x"
-            android:textAppearance="?android:attr/textAppearanceMedium"
-            android:singleLine="true"
-            android:includeFontPadding="false"
-            app:layout_constraintLeft_toRightOf="@+id/app_icon"
-            app:layout_constraintRight_toLeftOf="@+id/app_selector_container"
-            app:layout_constraintTop_toTopOf="parent"/>
-
-        <TextView
-            android:id="@+id/title"
-            style="@style/PlaybackTitleStyle"
-            android:layout_width="0dp"
-            android:layout_height="wrap_content"
-            android:layout_marginTop="@dimen/playback_fragment_text_margin_top"
-            android:layout_marginLeft="@dimen/playback_fragment_text_margin_x"
-            android:layout_marginRight="@dimen/playback_fragment_text_margin_x"
-            app:layout_constraintLeft_toLeftOf="parent"
-            app:layout_constraintRight_toRightOf="parent"
-            app:layout_constraintTop_toBottomOf="@+id/app_name"/>
-
-        <TextView
-            android:id="@+id/subtitle"
-            style="@style/PlaybackSubtitleStyle"
-            android:layout_width="0dp"
-            android:layout_height="wrap_content"
-            android:layout_marginTop="@dimen/playback_fragment_text_margin_top"
-            android:layout_marginLeft="@dimen/playback_fragment_text_margin_x"
-            android:layout_marginRight="@dimen/playback_fragment_text_margin_x"
-            app:layout_constraintLeft_toLeftOf="parent"
-            app:layout_constraintRight_toLeftOf="@+id/app_selector_container"
-            app:layout_constraintTop_toBottomOf="@+id/title"/>
-
-        <FrameLayout
-            android:id="@+id/app_selector_container"
-            xmlns:android="http://schemas.android.com/apk/res/android"
-            android:layout_width="@dimen/app_selector_icon_touch_target"
-            android:layout_height="@dimen/app_selector_icon_touch_target"
-            android:background="?android:attr/selectableItemBackground"
-            android:layout_marginRight="@dimen/app_selector_margin_x"
-            app:layout_constraintTop_toTopOf="@+id/app_name"
-            app:layout_constraintBottom_toBottomOf="@+id/app_name"
-            app:layout_constraintRight_toRightOf="parent">
+        <androidx.constraintlayout.widget.ConstraintLayout
+            android:id="@+id/playback_container"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent">
 
             <ImageView
-                android:id="@+id/app_selector"
+                android:id="@+id/app_icon"
                 android:layout_width="@dimen/app_selector_icon_size"
                 android:layout_height="@dimen/app_selector_icon_size"
                 android:layout_gravity="center"
+                android:layout_marginStart="@dimen/playback_fragment_text_margin_x"
+                android:background="?android:attr/selectableItemBackground"
                 android:src="@drawable/ic_app_switch"
-                android:tint="@color/icon_tint" />
-        </FrameLayout>
+                app:layout_constraintTop_toTopOf="@+id/app_name"
+                app:layout_constraintBottom_toBottomOf="@+id/app_name"
+                app:layout_constraintStart_toStartOf="parent"/>
 
-        <com.android.car.media.common.PlaybackControlsActionBar
-            android:id="@+id/playback_controls"
-            android:layout_width="0dp"
-            android:layout_height="wrap_content"
-            android:layout_marginBottom="@dimen/playback_fragment_controls_margin_bottom"
-            app:columns="3"
-            app:enableOverflow="false"
-            app:layout_constraintBottom_toBottomOf="parent"
-            app:layout_constraintLeft_toLeftOf="parent"
-            app:layout_constraintRight_toRightOf="parent"/>
+            <TextView
+                android:id="@+id/app_name"
+                android:layout_width="0dp"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="@dimen/playback_fragment_text_margin_top"
+                android:layout_marginStart="@dimen/playback_fragment_text_margin_x"
+                android:layout_marginEnd="@dimen/playback_fragment_text_margin_x"
+                android:textAppearance="?android:attr/textAppearanceMedium"
+                android:singleLine="true"
+                android:includeFontPadding="false"
+                app:layout_constraintStart_toEndOf="@+id/app_icon"
+                app:layout_constraintEnd_toStartOf="@+id/app_selector_container"
+                app:layout_constraintTop_toTopOf="parent"/>
 
-    </androidx.constraintlayout.widget.ConstraintLayout>
+            <TextView
+                android:id="@+id/title"
+                style="@style/PlaybackTitleStyle"
+                android:layout_width="0dp"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="@dimen/playback_fragment_text_margin_top"
+                android:layout_marginStart="@dimen/playback_fragment_text_margin_x"
+                android:layout_marginEnd="@dimen/playback_fragment_text_margin_x"
+                app:layout_constraintStart_toStartOf="parent"
+                app:layout_constraintEnd_toEndOf="parent"
+                app:layout_constraintTop_toBottomOf="@+id/app_name"/>
 
-</androidx.cardview.widget.CardView>
+            <TextView
+                android:id="@+id/subtitle"
+                style="@style/PlaybackSubtitleStyle"
+                android:layout_width="0dp"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="@dimen/playback_fragment_text_margin_top"
+                android:layout_marginStart="@dimen/playback_fragment_text_margin_x"
+                android:layout_marginEnd="@dimen/playback_fragment_text_margin_x"
+                app:layout_constraintStart_toStartOf="parent"
+                app:layout_constraintEnd_toStartOf="@+id/app_selector_container"
+                app:layout_constraintTop_toBottomOf="@+id/title"/>
+
+            <FrameLayout
+                android:id="@+id/app_selector_container"
+                xmlns:android="http://schemas.android.com/apk/res/android"
+                android:layout_width="@dimen/app_selector_icon_touch_target"
+                android:layout_height="@dimen/app_selector_icon_touch_target"
+                android:background="?android:attr/selectableItemBackground"
+                android:layout_marginEnd="@dimen/app_selector_margin_x"
+                app:layout_constraintTop_toTopOf="@+id/app_name"
+                app:layout_constraintBottom_toBottomOf="@+id/app_name"
+                app:layout_constraintEnd_toEndOf="parent">
+
+                <ImageView
+                    android:id="@+id/app_selector"
+                    android:layout_width="@dimen/app_selector_icon_size"
+                    android:layout_height="@dimen/app_selector_icon_size"
+                    android:layout_gravity="center"
+                    android:src="@drawable/ic_app_switch"
+                    android:tint="@color/icon_tint"/>
+            </FrameLayout>
+
+            <com.android.car.media.common.PlaybackControlsActionBar
+                android:id="@+id/playback_controls"
+                android:layout_width="0dp"
+                android:layout_height="wrap_content"
+                android:layout_marginBottom="@dimen/playback_fragment_controls_margin_bottom"
+                app:columns="3"
+                app:enableOverflow="false"
+                app:layout_constraintBottom_toBottomOf="parent"
+                app:layout_constraintStart_toStartOf="parent"
+                app:layout_constraintEnd_toEndOf="parent"/>
+
+        </androidx.constraintlayout.widget.ConstraintLayout>
+
+    </com.android.car.ui.FocusArea>
+
+</androidx.cardview.widget.CardView>
\ No newline at end of file
diff --git a/car-media-common/res/values-port/dimens.xml b/car-media-common/res/values-port/dimens.xml
deleted file mode 100644
index 721ed93..0000000
--- a/car-media-common/res/values-port/dimens.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  Copyright 2019, The Android Open Source Project
-
-  Licensed under the Apache License, Version 2.0 (the "License");
-  you may not use this file except in compliance with the License.
-  You may obtain a copy of the License at
-
-      http://www.apache.org/licenses/LICENSE-2.0
-
-  Unless required by applicable law or agreed to in writing, software
-  distributed under the License is distributed on an "AS IS" BASIS,
-  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  See the License for the specific language governing permissions and
-  limitations under the License.
--->
-<resources>
-    <!-- App bar -->
-    <dimen name="appbar_second_row_height">@*android:dimen/car_app_bar_height</dimen>
-</resources>
diff --git a/car-media-common/res/values/attrs.xml b/car-media-common/res/values/attrs.xml
index 75ff716..04e2dbb 100644
--- a/car-media-common/res/values/attrs.xml
+++ b/car-media-common/res/values/attrs.xml
@@ -34,8 +34,8 @@
     <declare-styleable name="CrossfadeImageView">
         <attr name="align_horizontal" format="enum">
             <enum name="center" value="0"/>
-            <enum name="left" value="1"/>
-            <enum name="right" value="2"/>
+            <enum name="start" value="1"/>
+            <enum name="end" value="2"/>
         </attr>
     </declare-styleable>
 </resources>
diff --git a/car-media-common/res/values/colors.xml b/car-media-common/res/values/colors.xml
index 51927a7..f649ba5 100644
--- a/car-media-common/res/values/colors.xml
+++ b/car-media-common/res/values/colors.xml
@@ -21,12 +21,8 @@
     <!-- App icons selection background -->
     <color name="appbar_view_icon_background_color">#66ffffff</color>
 
-    <!-- ColorChecker.java -->
-    <color name="media_tint_light">@*android:color/car_tint_light</color>
-    <color name="media_tint_dark">@*android:color/car_tint_dark</color>
-
     <!-- Color used on the placeholder album art -->
-    <color name="album_art_placeholder_color">@*android:color/car_grey_800</color>
+    <color name="album_art_placeholder_color">@color/car_grey_800</color>
 
     <!-- Media source's color if not provided -->
     <color name="media_source_default_color">@android:color/background_dark</color>
diff --git a/car-media-common/res/values/dimens.xml b/car-media-common/res/values/dimens.xml
index eedc8a6..d888e4b 100644
--- a/car-media-common/res/values/dimens.xml
+++ b/car-media-common/res/values/dimens.xml
@@ -22,14 +22,14 @@
     <dimen name="fab_spinner_size">128dp</dimen>
 
     <!-- playback_fragment.xml -->
-    <dimen name="playback_fragment_text_margin_top">@*android:dimen/car_padding_4</dimen>
-    <dimen name="playback_fragment_text_margin_x">@*android:dimen/car_padding_4</dimen>
+    <dimen name="playback_fragment_text_margin_top">@dimen/car_ui_padding_4</dimen>
+    <dimen name="playback_fragment_text_margin_x">@dimen/car_ui_padding_4</dimen>
 
-    <dimen name="playback_fragment_app_icon_margin_right">@*android:dimen/car_padding_4</dimen>
-    <dimen name="playback_fragment_controls_margin_bottom">@*android:dimen/car_padding_4</dimen>
+    <dimen name="playback_fragment_app_icon_margin_right">@dimen/car_ui_padding_4</dimen>
+    <dimen name="playback_fragment_controls_margin_bottom">@dimen/car_ui_padding_4</dimen>
 
     <!-- Drawable appbar_view_icon_background.xml -->
-    <dimen name="appbar_view_icon_background_corner_radius">@*android:dimen/car_radius_2</dimen>
+    <dimen name="appbar_view_icon_background_corner_radius">8dp</dimen>
     <dimen name="appbar_view_icon_touch_target_size">76dp</dimen>
     <dimen name="appbar_view_icon_background_radius">38dp</dimen>
 
@@ -37,7 +37,7 @@
     <dimen name="minimized_progress_bar_track_thickness">4dp</dimen>
 
     <!-- App selector -->
-    <dimen name="app_selector_icon_size">@*android:dimen/car_primary_icon_size</dimen>
-    <dimen name="app_selector_icon_touch_target">@*android:dimen/car_touch_target_size</dimen>
-    <dimen name="app_selector_margin_x">@*android:dimen/car_padding_2</dimen>
+    <dimen name="app_selector_icon_size">@dimen/car_ui_primary_icon_size</dimen>
+    <dimen name="app_selector_icon_touch_target">@dimen/car_ui_touch_target_size</dimen>
+    <dimen name="app_selector_margin_x">@dimen/car_ui_padding_2</dimen>
 </resources>
diff --git a/car-media-common/res/values/styles.xml b/car-media-common/res/values/styles.xml
index 5d00241..972837d 100644
--- a/car-media-common/res/values/styles.xml
+++ b/car-media-common/res/values/styles.xml
@@ -18,13 +18,11 @@
     <style name="PlaybackTitleStyle" parent="TextAppearance.Body1">
         <item name="android:singleLine">true</item>
         <item name="android:includeFontPadding">false</item>
-        <item name="android:textDirection">locale</item>
     </style>
 
     <style name="PlaybackSubtitleStyle" parent="TextAppearance.Body3">
         <item name="android:textColor">@color/secondary_text_color</item>
         <item name="android:singleLine">true</item>
         <item name="android:includeFontPadding">false</item>
-        <item name="android:textDirection">locale</item>
     </style>
 </resources>
diff --git a/car-media-common/src/com/android/car/media/common/ColorChecker.java b/car-media-common/src/com/android/car/media/common/ColorChecker.java
deleted file mode 100644
index 722ecb3..0000000
--- a/car-media-common/src/com/android/car/media/common/ColorChecker.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.car.media.common;
-
-import android.content.Context;
-import android.graphics.Color;
-import android.util.Log;
-
-/**
- * A class that checks to make sure that given colors are within the acceptable contract ratio for
- * the car environment.
- */
-public class ColorChecker {
-    private static final String TAG = "ColorChecker";
-    private static final double MIN_CONTRAST_RATIO = 4.5;
-
-    /**
-     * Calls {@link #getTintColor(int, int...)} with:
-     *     {@code R.color.car_tint_light} and
-     *     {@code R.color.car_tint_dark}
-     */
-    public static int getTintColor(Context context, int backgroundColor) {
-        int lightTintColor = context.getResources().getColor(R.color.media_tint_light);
-        int darkTintColor = context.getResources().getColor(R.color.media_tint_dark);
-
-        return getTintColor(backgroundColor, lightTintColor, darkTintColor);
-    }
-
-    /**
-     * Calls {@link #getTintColor(int, int...)} with {@link #MIN_CONTRAST_RATIO}.
-     */
-    public static int getTintColor(int backgroundColor, int... tintColors) {
-        return getTintColor(MIN_CONTRAST_RATIO, backgroundColor, tintColors);
-    }
-
-    /**
-     *
-     * Determines what color to tint icons given the background color that they sit on.
-     *
-     * @param minAllowedContrastRatio The minimum contrast ratio
-     * @param bgColor The background color that the icons sit on.
-     * @param tintColors A list of potential colors to tint the icons with.
-     * @return The color that the icons should be tinted. Will be the first tinted color that
-     *         meets the requirements. If none of the tint colors meet the minimum requirements,
-     *         either black or white will be returned, whichever has a higher contrast.
-     */
-    public static int getTintColor(double minAllowedContrastRatio, int bgColor, int... tintColors) {
-        for (int tc : tintColors) {
-            double contrastRatio = getContrastRatio(bgColor, tc);
-            if (contrastRatio >= minAllowedContrastRatio) {
-                return tc;
-            }
-        }
-        double blackContrastRatio = getContrastRatio(bgColor, Color.BLACK);
-        double whiteContrastRatio = getContrastRatio(bgColor, Color.WHITE);
-        if (whiteContrastRatio >= blackContrastRatio) {
-            Log.w(TAG, "Tint color does not meet contrast requirements. Using white.");
-            return Color.WHITE;
-        } else {
-            Log.w(TAG, "Tint color does not meet contrast requirements. Using black.");
-            return Color.BLACK;
-        }
-    }
-
-    /**
-     * Returns the contrast radio between the two given colors.
-     */
-    public static double getContrastRatio(int color1, int color2) {
-        return getContrastRatio(getLuminance(color1), getLuminance(color2));
-    }
-
-    /**
-     * Returns the contrast ratio between the two luminances. Luminances maps to colors and is the
-     * result returned from {@link #getLuminance(int)}.
-     */
-    public static double getContrastRatio(double luminance1, double luminance2) {
-        return (Math.max(luminance1, luminance2) + 0.05)
-                / (Math.min(luminance1, luminance2) + 0.05);
-    }
-
-    /**
-     * Calculates the luminance of a color as specified by:
-     *     http://www.w3.org/TR/WCAG20-TECHS/G17.html
-     *
-     * @param color The color to calculate the luminance of.
-     * @return The luminance.
-     */
-    public static double getLuminance(int color) {
-        // Values are in sRGB
-        double r = convert8BitToLuminanceComponent(Color.red(color));
-        double g = convert8BitToLuminanceComponent(Color.green(color));
-        double b = convert8BitToLuminanceComponent(Color.blue(color));
-        return r * 0.2126 + g * 0.7152 + b * 0.0722;
-    }
-
-    /**
-     * Converts am 8 bit color component (0-255) to the luminance component as specified by:
-     *     http://www.w3.org/TR/WCAG20-TECHS/G17.html
-     */
-    private static double convert8BitToLuminanceComponent(double component) {
-        component /= 255.0;
-        if (component <= 0.03928) {
-            return component / 12.92;
-        } else {
-            return Math.pow(((component + 0.055) / 1.055), 2.4);
-        }
-    }
-
-    private ColorChecker() {}
-}
diff --git a/car-media-common/src/com/android/car/media/common/CustomPlaybackAction.java b/car-media-common/src/com/android/car/media/common/CustomPlaybackAction.java
index 9012a3b..3cc9f30 100644
--- a/car-media-common/src/com/android/car/media/common/CustomPlaybackAction.java
+++ b/car-media-common/src/com/android/car/media/common/CustomPlaybackAction.java
@@ -16,11 +16,12 @@
 
 package com.android.car.media.common;
 
-import android.annotation.NonNull;
-import android.annotation.Nullable;
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
 
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
 import com.android.car.media.common.playback.PlaybackViewModel.PlaybackStateWrapper;
 
 
diff --git a/car-media-common/src/com/android/car/media/common/MediaButtonController.java b/car-media-common/src/com/android/car/media/common/MediaButtonController.java
index c281ff7..48e0406 100644
--- a/car-media-common/src/com/android/car/media/common/MediaButtonController.java
+++ b/car-media-common/src/com/android/car/media/common/MediaButtonController.java
@@ -80,6 +80,7 @@
         mPlayPauseStopImageContainer.setOnClickListener(this::onPlayPauseStopClicked);
         mPlayPauseStopImageView = mPlayPauseStopImageContainer.findViewById(R.id.play_pause_stop);
         mPlayPauseStopImageView.setVisibility(View.INVISIBLE);
+        mPlayPauseStopImageView.setFocusedByDefault(true);
         mCircularProgressBar = mPlayPauseStopImageContainer.findViewById(
                 R.id.circular_progress_bar);
         mPlayPauseStopImageView.setAction(PlayPauseStopImageView.ACTION_DISABLED);
diff --git a/car-media-common/src/com/android/car/media/common/MediaItemMetadata.java b/car-media-common/src/com/android/car/media/common/MediaItemMetadata.java
index 317bb7a..8b7894c 100644
--- a/car-media-common/src/com/android/car/media/common/MediaItemMetadata.java
+++ b/car-media-common/src/com/android/car/media/common/MediaItemMetadata.java
@@ -16,8 +16,6 @@
 
 package com.android.car.media.common;
 
-import android.annotation.NonNull;
-import android.annotation.Nullable;
 import android.content.Context;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
@@ -35,6 +33,8 @@
 import android.support.v4.media.session.MediaSessionCompat;
 import android.text.TextUtils;
 
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
 
 import com.android.car.apps.common.BitmapUtils;
diff --git a/car-media-common/src/com/android/car/media/common/MetadataController.java b/car-media-common/src/com/android/car/media/common/MetadataController.java
index 49e5a26..baeca11 100644
--- a/car-media-common/src/com/android/car/media/common/MetadataController.java
+++ b/car-media-common/src/com/android/car/media/common/MetadataController.java
@@ -19,8 +19,6 @@
 import static com.android.car.arch.common.LiveDataFunctions.combine;
 import static com.android.car.arch.common.LiveDataFunctions.pair;
 
-import android.annotation.NonNull;
-import android.annotation.Nullable;
 import android.content.Context;
 import android.text.TextUtils;
 import android.util.Size;
@@ -29,6 +27,8 @@
 import android.widget.SeekBar;
 import android.widget.TextView;
 
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 import androidx.lifecycle.LifecycleOwner;
 
 import com.android.car.apps.common.imaging.ImageViewBinder;
diff --git a/car-media-common/src/com/android/car/media/common/MinimizedPlaybackControlBar.java b/car-media-common/src/com/android/car/media/common/MinimizedPlaybackControlBar.java
index 7ce34b2..9cfda34 100644
--- a/car-media-common/src/com/android/car/media/common/MinimizedPlaybackControlBar.java
+++ b/car-media-common/src/com/android/car/media/common/MinimizedPlaybackControlBar.java
@@ -24,7 +24,9 @@
 import androidx.annotation.NonNull;
 import androidx.lifecycle.LifecycleOwner;
 
+import com.android.car.apps.common.BackgroundImageView;
 import com.android.car.apps.common.MinimizedControlBar;
+import com.android.car.apps.common.imaging.ImageBinder;
 import com.android.car.media.common.playback.PlaybackViewModel;
 
 /**
@@ -39,6 +41,7 @@
     private MetadataController mMetadataController;
     private ProgressBar mLinearProgressBar;
     private ProgressBar mCircularProgressBar;
+    private ImageBinder<MediaItemMetadata.ArtworkRef> mArtBinder = null;
     private PlaybackViewModel mPlaybackViewModel;
 
     private boolean mShowLinearProgressBar;
@@ -68,6 +71,15 @@
         mShowCircularProgressBar = context.getResources().getBoolean(
                 R.bool.show_circular_progress_bar);
         mCircularProgressBar = findViewById(R.id.circular_progress_bar);
+
+        BackgroundImageView artBackground = findViewById(R.id.art_background);
+        if (artBackground != null) {
+            int max = getResources().getInteger(R.integer.media_items_bitmap_max_size_px);
+            Size maxArtSize = new Size(max, max);
+            mArtBinder = new ImageBinder<>(
+                    ImageBinder.PlaceholderType.BACKGROUND, maxArtSize,
+                    drawable -> artBackground.setBackgroundDrawable(drawable));
+        }
     }
 
     /** Connects the bar to the {@link PlaybackViewModel}. */
@@ -82,5 +94,11 @@
                 mLinearProgressBar, mShowLinearProgressBar);
         ControlBarHelper.initProgressBar(getContext(), owner, mPlaybackViewModel,
                 mCircularProgressBar, mShowCircularProgressBar);
+
+        if (mArtBinder != null) {
+            mPlaybackViewModel.getMetadata().observe(owner,
+                    item -> mArtBinder.setImage(getContext(),
+                            item != null ? item.getArtworkKey() : null));
+        }
     }
 }
diff --git a/car-media-common/src/com/android/car/media/common/PlaybackFragment.java b/car-media-common/src/com/android/car/media/common/PlaybackFragment.java
index 36f428d..a9285ba 100644
--- a/car-media-common/src/com/android/car/media/common/PlaybackFragment.java
+++ b/car-media-common/src/com/android/car/media/common/PlaybackFragment.java
@@ -16,6 +16,8 @@
 
 package com.android.car.media.common;
 
+import static android.car.media.CarMediaManager.MEDIA_SOURCE_MODE_PLAYBACK;
+
 import static com.android.car.arch.common.LiveDataFunctions.mapNonNull;
 
 import android.app.Application;
@@ -62,8 +64,10 @@
     public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
             Bundle savedInstanceState) {
         FragmentActivity activity = requireActivity();
-        PlaybackViewModel playbackViewModel = PlaybackViewModel.get(activity.getApplication());
-        mMediaSourceViewModel = MediaSourceViewModel.get(activity.getApplication());
+        PlaybackViewModel playbackViewModel = PlaybackViewModel.get(activity.getApplication(),
+                MEDIA_SOURCE_MODE_PLAYBACK);
+        mMediaSourceViewModel = MediaSourceViewModel.get(activity.getApplication(),
+                MEDIA_SOURCE_MODE_PLAYBACK);
         mAppSelectorIntent = MediaSource.getSourceSelectorIntent(getContext(), true);
 
         ViewModel innerViewModel = ViewModelProviders.of(activity).get(ViewModel.class);
@@ -140,7 +144,7 @@
             mMediaSourceViewModel = mediaSourceViewModel;
             mMediaSource = mMediaSourceViewModel.getPrimaryMediaSource();
             mAppName = mapNonNull(mMediaSource, MediaSource::getDisplayName);
-            mAppIcon = mapNonNull(mMediaSource, MediaSource::getRoundPackageIcon);
+            mAppIcon = mapNonNull(mMediaSource, MediaSource::getCroppedPackageIcon);
             mTitle = mapNonNull(playbackViewModel.getMetadata(), MediaItemMetadata::getTitle);
             mSubtitle = mapNonNull(playbackViewModel.getMetadata(), MediaItemMetadata::getArtist);
         }
diff --git a/car-media-common/src/com/android/car/media/common/browse/BrowsedMediaItems.java b/car-media-common/src/com/android/car/media/common/browse/BrowsedMediaItems.java
index dea0d6a..d46f027 100644
--- a/car-media-common/src/com/android/car/media/common/browse/BrowsedMediaItems.java
+++ b/car-media-common/src/com/android/car/media/common/browse/BrowsedMediaItems.java
@@ -16,11 +16,11 @@
 
 package com.android.car.media.common.browse;
 
-import android.annotation.NonNull;
 import android.os.Bundle;
 import android.os.Handler;
 import android.support.v4.media.MediaBrowserCompat;
 
+import androidx.annotation.NonNull;
 import androidx.lifecycle.LiveData;
 
 import com.android.car.media.common.MediaItemMetadata;
diff --git a/car-media-common/src/com/android/car/media/common/browse/MediaBrowserViewModel.java b/car-media-common/src/com/android/car/media/common/browse/MediaBrowserViewModel.java
index 5a4626a..323b4ce 100644
--- a/car-media-common/src/com/android/car/media/common/browse/MediaBrowserViewModel.java
+++ b/car-media-common/src/com/android/car/media/common/browse/MediaBrowserViewModel.java
@@ -16,11 +16,11 @@
 
 package com.android.car.media.common.browse;
 
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.UiThread;
 import android.support.v4.media.MediaBrowserCompat;
 
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.UiThread;
 import androidx.lifecycle.LiveData;
 import androidx.lifecycle.ViewModelProvider;
 
@@ -37,31 +37,11 @@
 public interface MediaBrowserViewModel {
 
     /**
-     * Possible states of the application UI
-     */
-    enum BrowseState {
-        /** There is no content to show */
-        EMPTY,
-        /** We are still in the process of obtaining data */
-        LOADING,
-        /** Data has been loaded */
-        LOADED,
-        /** The content can't be shown due an error */
-        ERROR
-    }
-
-    /**
      * Returns a LiveData that emits the current package name of the browser's service component.
      */
     LiveData<String> getPackageName();
 
     /**
-     * Returns a LiveData that emits the current {@link BrowseState}
-     */
-    LiveData<BrowseState> getBrowseState();
-
-
-    /**
      * Fetches the MediaItemMetadatas for the current browsed id, and the loading status of the
      * fetch operation.
      *
diff --git a/car-media-common/src/com/android/car/media/common/browse/MediaBrowserViewModelImpl.java b/car-media-common/src/com/android/car/media/common/browse/MediaBrowserViewModelImpl.java
index 7d47ba7..949c81d 100644
--- a/car-media-common/src/com/android/car/media/common/browse/MediaBrowserViewModelImpl.java
+++ b/car-media-common/src/com/android/car/media/common/browse/MediaBrowserViewModelImpl.java
@@ -23,17 +23,16 @@
 import static com.android.car.arch.common.LiveDataFunctions.pair;
 import static com.android.car.arch.common.LiveDataFunctions.split;
 
-import android.annotation.NonNull;
-import android.annotation.Nullable;
 import android.app.Application;
 import android.os.Bundle;
 import android.support.v4.media.MediaBrowserCompat;
 import android.text.TextUtils;
 
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 import androidx.annotation.RestrictTo;
 import androidx.lifecycle.AndroidViewModel;
 import androidx.lifecycle.LiveData;
-import androidx.lifecycle.MediatorLiveData;
 import androidx.lifecycle.MutableLiveData;
 
 import com.android.car.arch.common.FutureData;
@@ -62,9 +61,6 @@
 
     private final LiveData<FutureData<List<MediaItemMetadata>>> mSearchedMediaItems;
     private final LiveData<FutureData<List<MediaItemMetadata>>> mBrowsedMediaItems;
-
-    private final LiveData<BrowseState> mBrowseState;
-
     private final LiveData<String> mPackageName;
 
     MediaBrowserViewModelImpl(@NonNull Application application, boolean isRoot) {
@@ -94,39 +90,6 @@
                                 (mediaBrowser == null || TextUtils.isEmpty(query))
                                         ? null
                                         : new SearchedMediaItems(mediaBrowser, query)));
-
-        mBrowseState = new MediatorLiveData<BrowseState>() {
-            {
-                setValue(BrowseState.EMPTY);
-                addSource(mBrowsedMediaItems, items -> update());
-            }
-
-            private void update() {
-                setValue(getState());
-            }
-
-            private BrowseState getState() {
-                if (mBrowsedMediaItems.getValue() == null) {
-                    // Uninitialized
-                    return BrowseState.EMPTY;
-                }
-                if (mBrowsedMediaItems.getValue().isLoading()) {
-                    return BrowseState.LOADING;
-                }
-                List<MediaItemMetadata> items = mBrowsedMediaItems.getValue().getData();
-                if (items == null) {
-                    // Normally this could be null if it hasn't been initialized, but in that case
-                    // isLoading would not be false, so this means it must have encountered an
-                    // error.
-                    return BrowseState.ERROR;
-                }
-                if (items.isEmpty()) {
-                    return BrowseState.EMPTY;
-                }
-                return BrowseState.LOADED;
-            }
-        };
-
     }
 
     private static MediaBrowserCompat requireConnected(@Nullable MediaBrowserCompat mediaBrowser) {
@@ -155,11 +118,6 @@
     }
 
     @Override
-    public LiveData<BrowseState> getBrowseState() {
-        return mBrowseState;
-    }
-
-    @Override
     public LiveData<FutureData<List<MediaItemMetadata>>> getBrowsedMediaItems() {
         return mBrowsedMediaItems;
     }
diff --git a/car-media-common/src/com/android/car/media/common/browse/MutableMediaBrowserViewModel.java b/car-media-common/src/com/android/car/media/common/browse/MutableMediaBrowserViewModel.java
index 482efdd..1290b20 100644
--- a/car-media-common/src/com/android/car/media/common/browse/MutableMediaBrowserViewModel.java
+++ b/car-media-common/src/com/android/car/media/common/browse/MutableMediaBrowserViewModel.java
@@ -16,12 +16,12 @@
 
 package com.android.car.media.common.browse;
 
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.UiThread;
 import android.app.Application;
 
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 import androidx.annotation.RestrictTo;
+import androidx.annotation.UiThread;
 
 /** This isn't a comment. */
 @RestrictTo(RestrictTo.Scope.LIBRARY)
diff --git a/car-media-common/src/com/android/car/media/common/browse/RootMediaBrowserViewModel.java b/car-media-common/src/com/android/car/media/common/browse/RootMediaBrowserViewModel.java
index 1edb484..f1ffc64 100644
--- a/car-media-common/src/com/android/car/media/common/browse/RootMediaBrowserViewModel.java
+++ b/car-media-common/src/com/android/car/media/common/browse/RootMediaBrowserViewModel.java
@@ -16,9 +16,9 @@
 
 package com.android.car.media.common.browse;
 
-import android.annotation.NonNull;
 import android.app.Application;
 
+import androidx.annotation.NonNull;
 import androidx.annotation.RestrictTo;
 
 /** This isn't a comment. */
diff --git a/car-media-common/src/com/android/car/media/common/browse/SearchedMediaItems.java b/car-media-common/src/com/android/car/media/common/browse/SearchedMediaItems.java
index 51411f0..5399e06 100644
--- a/car-media-common/src/com/android/car/media/common/browse/SearchedMediaItems.java
+++ b/car-media-common/src/com/android/car/media/common/browse/SearchedMediaItems.java
@@ -18,11 +18,11 @@
 
 import static java.util.stream.Collectors.toList;
 
-import android.annotation.NonNull;
-import android.annotation.Nullable;
 import android.os.Bundle;
 import android.support.v4.media.MediaBrowserCompat;
 
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 import androidx.lifecycle.LiveData;
 
 import com.android.car.media.common.MediaItemMetadata;
diff --git a/car-media-common/src/com/android/car/media/common/playback/PlaybackStateAnnotations.java b/car-media-common/src/com/android/car/media/common/playback/PlaybackStateAnnotations.java
index 0d4c06b..88b3a0b 100644
--- a/car-media-common/src/com/android/car/media/common/playback/PlaybackStateAnnotations.java
+++ b/car-media-common/src/com/android/car/media/common/playback/PlaybackStateAnnotations.java
@@ -16,10 +16,11 @@
 
 package com.android.car.media.common.playback;
 
-import android.annotation.IntDef;
-import android.annotation.LongDef;
 import android.media.session.PlaybackState;
 
+import androidx.annotation.IntDef;
+import androidx.annotation.LongDef;
+
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 
diff --git a/car-media-common/src/com/android/car/media/common/playback/PlaybackViewModel.java b/car-media-common/src/com/android/car/media/common/playback/PlaybackViewModel.java
index 95c0dd5..02583c7 100644
--- a/car-media-common/src/com/android/car/media/common/playback/PlaybackViewModel.java
+++ b/car-media-common/src/com/android/car/media/common/playback/PlaybackViewModel.java
@@ -16,14 +16,13 @@
 
 package com.android.car.media.common.playback;
 
+import static android.car.media.CarMediaManager.MEDIA_SOURCE_MODE_PLAYBACK;
+
 import static androidx.lifecycle.Transformations.switchMap;
 
 import static com.android.car.arch.common.LiveDataFunctions.dataOf;
 import static com.android.car.media.common.playback.PlaybackStateAnnotations.Actions;
 
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
 import android.app.Application;
 import android.content.Context;
 import android.content.pm.PackageManager;
@@ -38,6 +37,10 @@
 import android.support.v4.media.session.PlaybackStateCompat;
 import android.util.Log;
 
+import androidx.annotation.IntDef;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
 import androidx.lifecycle.AndroidViewModel;
 import androidx.lifecycle.LiveData;
 import androidx.lifecycle.MutableLiveData;
@@ -49,7 +52,6 @@
 import com.android.car.media.common.R;
 import com.android.car.media.common.source.MediaSourceColors;
 import com.android.car.media.common.source.MediaSourceViewModel;
-import com.android.internal.annotations.VisibleForTesting;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -74,14 +76,22 @@
             "com.android.car.media.common.ACTION_SET_RATING";
     private static final String EXTRA_SET_HEART = "com.android.car.media.common.EXTRA_SET_HEART";
 
-    private static PlaybackViewModel sInstance;
+    private static PlaybackViewModel[] sInstances = new PlaybackViewModel[2];
+
+    /**
+     * Returns the PlaybackViewModel singleton tied to the application.
+     * @deprecated should use get(Application application, int mode) instead
+     */
+    public static PlaybackViewModel get(@NonNull Application application) {
+        return get(application, MEDIA_SOURCE_MODE_PLAYBACK);
+    }
 
     /** Returns the PlaybackViewModel singleton tied to the application. */
-    public static PlaybackViewModel get(@NonNull Application application) {
-        if (sInstance == null) {
-            sInstance = new PlaybackViewModel(application);
+    public static PlaybackViewModel get(@NonNull Application application, int mode) {
+        if (sInstances[mode] == null) {
+            sInstances[mode] = new PlaybackViewModel(application, mode);
         }
-        return sInstance;
+        return sInstances[mode];
     }
 
     /**
@@ -137,8 +147,8 @@
                     state -> state == null ? dataOf(new PlaybackProgress(0L, 0L))
                             : new ProgressLiveData(state.mState, state.getMaxProgress()));
 
-    private PlaybackViewModel(Application application) {
-        this(application, MediaSourceViewModel.get(application).getMediaController());
+    private PlaybackViewModel(Application application, int mode) {
+        this(application, MediaSourceViewModel.get(application, mode).getMediaController());
     }
 
     @VisibleForTesting
diff --git a/car-media-common/src/com/android/car/media/common/source/MediaBrowserConnector.java b/car-media-common/src/com/android/car/media/common/source/MediaBrowserConnector.java
index b16164a..14271e4 100644
--- a/car-media-common/src/com/android/car/media/common/source/MediaBrowserConnector.java
+++ b/car-media-common/src/com/android/car/media/common/source/MediaBrowserConnector.java
@@ -18,14 +18,15 @@
 
 import static com.android.car.apps.common.util.CarAppsDebugUtils.idHash;
 
-import android.annotation.NonNull;
-import android.annotation.Nullable;
 import android.content.ComponentName;
 import android.content.Context;
 import android.os.Bundle;
 import android.support.v4.media.MediaBrowserCompat;
 import android.util.Log;
 
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
 import com.android.car.media.common.MediaConstants;
 
 /**
@@ -56,7 +57,7 @@
      *
      * @param context The Context with which to build MediaBrowsers.
      */
-    MediaBrowserConnector(@NonNull Context context, @NonNull Callback callback) {
+    public MediaBrowserConnector(@NonNull Context context, @NonNull Callback callback) {
         mContext = context;
         mCallback = callback;
         mMaxBitmapSizePx = mContext.getResources().getInteger(
diff --git a/car-media-common/src/com/android/car/media/common/source/MediaSource.java b/car-media-common/src/com/android/car/media/common/source/MediaSource.java
index f856eb2..e09c248 100644
--- a/car-media-common/src/com/android/car/media/common/source/MediaSource.java
+++ b/car-media-common/src/com/android/car/media/common/source/MediaSource.java
@@ -16,8 +16,6 @@
 
 package com.android.car.media.common.source;
 
-import android.annotation.NonNull;
-import android.annotation.Nullable;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -26,17 +24,16 @@
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
 import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.PorterDuff;
-import android.graphics.PorterDuffXfermode;
-import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.service.media.MediaBrowserService;
 import android.text.TextUtils;
 import android.util.Log;
 
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
 import com.android.car.apps.common.BitmapUtils;
+import com.android.car.apps.common.IconCropper;
 import com.android.car.media.common.R;
 
 import java.net.URISyntaxException;
@@ -57,6 +54,8 @@
     private final CharSequence mDisplayName;
     @NonNull
     private final Drawable mIcon;
+    @NonNull
+    private final IconCropper mIconCropper;
 
     /**
      * Creates a {@link MediaSource} for the given {@link ComponentName}
@@ -78,7 +77,7 @@
             CharSequence displayName = extractDisplayName(context, serviceInfo, packageName);
             Drawable icon = extractIcon(context, serviceInfo, packageName);
             ComponentName browseService = new ComponentName(packageName, className);
-            return new MediaSource(browseService, displayName, icon);
+            return new MediaSource(browseService, displayName, icon, new IconCropper(context));
         } catch (PackageManager.NameNotFoundException e) {
             Log.w(TAG, "Component not found " + componentName.flattenToString());
             return null;
@@ -86,10 +85,11 @@
     }
 
     private MediaSource(@NonNull ComponentName browseService, @NonNull CharSequence displayName,
-            @NonNull Drawable icon) {
+            @NonNull Drawable icon, @NonNull IconCropper iconCropper) {
         mBrowseService = browseService;
         mDisplayName = displayName;
         mIcon = icon;
+        mIconCropper = iconCropper;
     }
 
     /**
@@ -186,29 +186,11 @@
     }
 
     /**
-     * Returns this media source's icon cropped to a circle.
+     * Returns this media source's icon cropped to a predefined shape (see
+     * {@link #IconCropper(Context)} on where and how the shape is defined).
      */
-    public Bitmap getRoundPackageIcon() {
-        return getRoundCroppedBitmap(BitmapUtils.fromDrawable(mIcon, null));
-    }
-
-    private static Bitmap getRoundCroppedBitmap(Bitmap bitmap) {
-        Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(),
-                Bitmap.Config.ARGB_8888);
-        Canvas canvas = new Canvas(output);
-
-        final int color = 0xff424242;
-        final Paint paint = new Paint();
-        final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
-
-        paint.setAntiAlias(true);
-        canvas.drawARGB(0, 0, 0, 0);
-        paint.setColor(color);
-        canvas.drawCircle(bitmap.getWidth() / 2, bitmap.getHeight() / 2,
-                bitmap.getWidth() / 2f, paint);
-        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
-        canvas.drawBitmap(bitmap, rect, rect, paint);
-        return output;
+    public Bitmap getCroppedPackageIcon() {
+        return mIconCropper.crop(mIcon);
     }
 
     @Override
diff --git a/car-media-common/src/com/android/car/media/common/source/MediaSourceViewModel.java b/car-media-common/src/com/android/car/media/common/source/MediaSourceViewModel.java
index 1d02209..4fbb202 100644
--- a/car-media-common/src/com/android/car/media/common/source/MediaSourceViewModel.java
+++ b/car-media-common/src/com/android/car/media/common/source/MediaSourceViewModel.java
@@ -16,11 +16,11 @@
 
 package com.android.car.media.common.source;
 
+import static android.car.media.CarMediaManager.MEDIA_SOURCE_MODE_PLAYBACK;
+
 import static com.android.car.apps.common.util.CarAppsDebugUtils.idHash;
 import static com.android.car.arch.common.LiveDataFunctions.dataOf;
 
-import android.annotation.NonNull;
-import android.annotation.Nullable;
 import android.app.Application;
 import android.car.Car;
 import android.car.CarNotConnectedException;
@@ -28,12 +28,13 @@
 import android.content.ComponentName;
 import android.media.session.MediaController;
 import android.os.Handler;
-import android.os.RemoteException;
 import android.support.v4.media.MediaBrowserCompat;
 import android.support.v4.media.session.MediaControllerCompat;
 import android.support.v4.media.session.MediaSessionCompat;
 import android.util.Log;
 
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
 import androidx.lifecycle.AndroidViewModel;
 import androidx.lifecycle.LiveData;
@@ -48,12 +49,13 @@
 public class MediaSourceViewModel extends AndroidViewModel {
     private static final String TAG = "MediaSourceViewModel";
 
-    private static MediaSourceViewModel sInstance;
+    private static MediaSourceViewModel[] sInstances = new MediaSourceViewModel[2];
     private final Car mCar;
     private CarMediaManager mCarMediaManager;
 
     // Primary media source.
     private final MutableLiveData<MediaSource> mPrimaryMediaSource = dataOf(null);
+
     // Connected browser for the primary media source.
     private final MutableLiveData<MediaBrowserCompat> mConnectedMediaBrowser = dataOf(null);
     // Media controller for the connected browser.
@@ -79,12 +81,20 @@
         MediaSource getMediaSource(ComponentName componentName);
     }
 
-    /** Returns the MediaSourceViewModel singleton tied to the application. */
+    /**
+     * Returns the MediaSourceViewModel singleton tied to the application.
+     * @deprecated should use get(Application application, int mode) instead
+     */
     public static MediaSourceViewModel get(@NonNull Application application) {
-        if (sInstance == null) {
-            sInstance = new MediaSourceViewModel(application);
+        return get(application, MEDIA_SOURCE_MODE_PLAYBACK);
+    }
+
+    /** Returns the MediaSourceViewModel singleton tied to the application. */
+    public static MediaSourceViewModel get(@NonNull Application application, int mode) {
+        if (sInstances[mode] == null) {
+            sInstances[mode] = new MediaSourceViewModel(application, mode);
         }
-        return sInstance;
+        return sInstances[mode];
     }
 
     /**
@@ -92,8 +102,8 @@
      *
      * @see AndroidViewModel
      */
-    private MediaSourceViewModel(@NonNull Application application) {
-        this(application, new InputFactory() {
+    private MediaSourceViewModel(@NonNull Application application, int mode) {
+        this(application, mode, new InputFactory() {
             @Override
             public MediaBrowserConnector createMediaBrowserConnector(
                     @NonNull Application application,
@@ -104,13 +114,7 @@
             @Override
             public MediaControllerCompat getControllerForSession(
                     @Nullable MediaSessionCompat.Token token) {
-                if (token == null) return null;
-                try {
-                    return new MediaControllerCompat(application, token);
-                } catch (RemoteException e) {
-                    Log.e(TAG, "Couldn't get MediaControllerCompat", e);
-                    return null;
-                }
+                return token == null ? null : new MediaControllerCompat(application, token);
             }
 
             @Override
@@ -136,7 +140,8 @@
     private final MediaBrowserConnector.Callback mConnectedBrowserCallback;
 
     @VisibleForTesting
-    MediaSourceViewModel(@NonNull Application application, @NonNull InputFactory inputFactory) {
+    MediaSourceViewModel(@NonNull Application application, int mode,
+            @NonNull InputFactory inputFactory) {
         super(application);
 
         mInputFactory = inputFactory;
@@ -166,13 +171,19 @@
 
         try {
             mCarMediaManager = mInputFactory.getCarMediaManager(mCar);
-            mCarMediaManager.registerMediaSourceListener(mMediaSourceListener);
-            updateModelState(mInputFactory.getMediaSource(mCarMediaManager.getMediaSource()));
+            mCarMediaManager.addMediaSourceListener(mMediaSourceListener, mode);
+            updateModelState(mInputFactory.getMediaSource(mCarMediaManager.getMediaSource(mode)));
         } catch (CarNotConnectedException e) {
             Log.e(TAG, "Car not connected", e);
         }
     }
 
+    @Override
+    protected void onCleared() {
+        super.onCleared();
+        mCar.disconnect();
+    }
+
     @VisibleForTesting
     MediaBrowserConnector.Callback getConnectedBrowserCallback() {
         return mConnectedBrowserCallback;
@@ -188,8 +199,8 @@
     /**
      * Updates the primary media source.
      */
-    public void setPrimaryMediaSource(@NonNull MediaSource mediaSource) {
-        mCarMediaManager.setMediaSource(mediaSource.getBrowseServiceComponentName());
+    public void setPrimaryMediaSource(@NonNull MediaSource mediaSource, int mode) {
+        mCarMediaManager.setMediaSource(mediaSource.getBrowseServiceComponentName(), mode);
     }
 
     /**
diff --git a/car-media-common/src/com/android/car/media/common/source/MediaSourcesLiveData.java b/car-media-common/src/com/android/car/media/common/source/MediaSourcesLiveData.java
index 7d423c8..9f9cc26 100644
--- a/car-media-common/src/com/android/car/media/common/source/MediaSourcesLiveData.java
+++ b/car-media-common/src/com/android/car/media/common/source/MediaSourcesLiveData.java
@@ -16,7 +16,6 @@
 
 package com.android.car.media.common.source;
 
-import android.annotation.NonNull;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
@@ -27,6 +26,7 @@
 import android.service.media.MediaBrowserService;
 import android.util.Log;
 
+import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
 
diff --git a/car-media-common/tests/Android.mk b/car-media-common/tests/Android.mk
deleted file mode 100644
index 0903c90..0000000
--- a/car-media-common/tests/Android.mk
+++ /dev/null
@@ -1,19 +0,0 @@
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-# Include all makefiles in subdirectories
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/car-media-common/tests/robotests/Android.bp b/car-media-common/tests/robotests/Android.bp
new file mode 100644
index 0000000..13e19f7
--- /dev/null
+++ b/car-media-common/tests/robotests/Android.bp
@@ -0,0 +1,37 @@
+
+
+//###########################################################
+// CarMediaCommon app just for Robolectric test target.     #
+//###########################################################
+android_app {
+    name: "CarMediaCommon",
+
+    platform_apis: true,
+
+    privileged: true,
+
+    static_libs: [
+        "car-arch-common",
+        "car-media-common",
+    ],
+}
+
+//###############################################
+// Car Media Common Robolectric test target. #
+//###############################################
+android_robolectric_test {
+    name: "CarMediaCommonRoboTests",
+
+    srcs: ["src/**/*.java"],
+
+    java_resource_dirs: ["config"],
+
+    // Include the testing libraries
+    libs: [
+        "android.car",
+        "androidx.arch.core_core-runtime",
+        "androidx.arch.core_core-common",
+    ],
+
+    instrumentation_for: "CarMediaCommon",
+}
diff --git a/car-media-common/tests/robotests/Android.mk b/car-media-common/tests/robotests/Android.mk
deleted file mode 100644
index 342f5c0..0000000
--- a/car-media-common/tests/robotests/Android.mk
+++ /dev/null
@@ -1,74 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-############################################################
-# CarMediaCommon app just for Robolectric test target.     #
-############################################################
-include $(CLEAR_VARS)
-
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-
-LOCAL_PACKAGE_NAME := CarMediaCommon
-LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_USE_AAPT2 := true
-
-LOCAL_PRIVILEGED_MODULE := true
-
-LOCAL_STATIC_ANDROID_LIBRARIES := \
-    car-arch-common \
-    car-media-common
-
-include $(BUILD_PACKAGE)
-
-################################################
-# Car Media Common Robolectric test target. #
-################################################
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := CarMediaCommonRoboTests
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_JAVA_RESOURCE_DIRS := config
-
-# Include the testing libraries
-LOCAL_JAVA_LIBRARIES := \
-    android.car \
-    androidx.arch.core_core-runtime \
-    androidx.arch.core_core-common \
-    robolectric_android-all-stub \
-    Robolectric_all-target \
-    mockito-robolectric-prebuilt \
-    truth-prebuilt
-
-
-LOCAL_INSTRUMENTATION_FOR := CarMediaCommon
-
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
-##################################################################
-# Car Media Common runner target to run the previous target. #
-##################################################################
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := RunCarMediaCommonRoboTests
-
-LOCAL_JAVA_LIBRARIES := \
-    android.car \
-    CarMediaCommonRoboTests \
-    robolectric_android-all-stub \
-    Robolectric_all-target \
-    mockito-robolectric-prebuilt \
-    truth-prebuilt
-
-LOCAL_TEST_PACKAGE := CarMediaCommon
-
-LOCAL_ROBOTEST_FILES := $(filter-out %/BaseRobolectricTest.java,\
-    $(call find-files-in-subdirs,$(LOCAL_PATH)/src,*Test.java,.))
-
-LOCAL_INSTRUMENT_SOURCE_DIRS := $(dir $(LOCAL_PATH))../src
-
-include external/robolectric-shadows/run_robotests.mk
diff --git a/car-media-common/tests/robotests/AndroidManifest.xml b/car-media-common/tests/robotests/AndroidManifest.xml
index 63b3855..83a5e47 100644
--- a/car-media-common/tests/robotests/AndroidManifest.xml
+++ b/car-media-common/tests/robotests/AndroidManifest.xml
@@ -17,5 +17,4 @@
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
           package="com.android.car.media.common.robotests">
-
 </manifest>
diff --git a/car-media-common/tests/robotests/config/robolectric.properties b/car-media-common/tests/robotests/config/robolectric.properties
index 715d744..4c863dc 100644
--- a/car-media-common/tests/robotests/config/robolectric.properties
+++ b/car-media-common/tests/robotests/config/robolectric.properties
@@ -13,5 +13,4 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
-manifest=packages/apps/Car/libs/car-media-common/tests/robotests/AndroidManifest.xml
 sdk=NEWEST_SDK
diff --git a/car-media-common/tests/robotests/src/com/android/car/media/common/MediaItemMetadataTest.java b/car-media-common/tests/robotests/src/com/android/car/media/common/MediaItemMetadataTest.java
index 1373d4c..81f4066 100644
--- a/car-media-common/tests/robotests/src/com/android/car/media/common/MediaItemMetadataTest.java
+++ b/car-media-common/tests/robotests/src/com/android/car/media/common/MediaItemMetadataTest.java
@@ -23,10 +23,8 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.robolectric.RobolectricTestRunner;
-import org.robolectric.annotation.Config;
 
 @RunWith(RobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class MediaItemMetadataTest {
     private static final String EXTRA_METADATA = "metadata";
 
diff --git a/car-media-common/tests/robotests/src/com/android/car/media/common/TestConfig.java b/car-media-common/tests/robotests/src/com/android/car/media/common/TestConfig.java
deleted file mode 100644
index 8e45ad3..0000000
--- a/car-media-common/tests/robotests/src/com/android/car/media/common/TestConfig.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.car.media.common;
-
-public class TestConfig {
-    public static final int SDK_VERSION = 23;
-    public static final String MANIFEST_PATH =
-            "packages/apps/Car/car-media-common/AndroidManifest.xml";
-}
diff --git a/car-media-common/tests/robotests/src/com/android/car/media/common/playback/PlaybackViewModelTest.java b/car-media-common/tests/robotests/src/com/android/car/media/common/playback/PlaybackViewModelTest.java
index 8eb6283..ad6cfe8 100644
--- a/car-media-common/tests/robotests/src/com/android/car/media/common/playback/PlaybackViewModelTest.java
+++ b/car-media-common/tests/robotests/src/com/android/car/media/common/playback/PlaybackViewModelTest.java
@@ -39,7 +39,6 @@
 import com.android.car.arch.common.testing.InstantTaskExecutorRule;
 import com.android.car.arch.common.testing.TestLifecycleOwner;
 import com.android.car.media.common.MediaItemMetadata;
-import com.android.car.media.common.TestConfig;
 
 import org.junit.Before;
 import org.junit.Rule;
@@ -51,13 +50,11 @@
 import org.mockito.junit.MockitoJUnit;
 import org.mockito.junit.MockitoRule;
 import org.robolectric.RobolectricTestRunner;
-import org.robolectric.annotation.Config;
 
 import java.util.Collections;
 import java.util.List;
 
 @RunWith(RobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class PlaybackViewModelTest {
 
     @Rule
diff --git a/car-media-common/tests/robotests/src/com/android/car/media/common/playback/ProgressLiveDataTest.java b/car-media-common/tests/robotests/src/com/android/car/media/common/playback/ProgressLiveDataTest.java
index fc4959c..991e4f2 100644
--- a/car-media-common/tests/robotests/src/com/android/car/media/common/playback/ProgressLiveDataTest.java
+++ b/car-media-common/tests/robotests/src/com/android/car/media/common/playback/ProgressLiveDataTest.java
@@ -27,7 +27,6 @@
 import com.android.car.arch.common.testing.CaptureObserver;
 import com.android.car.arch.common.testing.InstantTaskExecutorRule;
 import com.android.car.arch.common.testing.TestLifecycleOwner;
-import com.android.car.media.common.TestConfig;
 
 import org.junit.Before;
 import org.junit.Rule;
@@ -37,13 +36,11 @@
 import org.mockito.junit.MockitoJUnit;
 import org.mockito.junit.MockitoRule;
 import org.robolectric.RobolectricTestRunner;
-import org.robolectric.annotation.Config;
 import org.robolectric.shadows.ShadowLooper;
 
 import java.util.concurrent.TimeUnit;
 
 @RunWith(RobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class ProgressLiveDataTest {
     private static final long START_TIME = 500L;
     private static final long START_PROGRESS = 1000L;
diff --git a/car-media-common/tests/robotests/src/com/android/car/media/common/source/MediaBrowserConnectorTest.java b/car-media-common/tests/robotests/src/com/android/car/media/common/source/MediaBrowserConnectorTest.java
index f955e47..eeccb5e 100644
--- a/car-media-common/tests/robotests/src/com/android/car/media/common/source/MediaBrowserConnectorTest.java
+++ b/car-media-common/tests/robotests/src/com/android/car/media/common/source/MediaBrowserConnectorTest.java
@@ -24,13 +24,13 @@
 import static org.mockito.Mockito.when;
 import static org.robolectric.RuntimeEnvironment.application;
 
-import android.annotation.NonNull;
 import android.content.ComponentName;
 import android.support.v4.media.MediaBrowserCompat;
 
+import androidx.annotation.NonNull;
+
 import com.android.car.arch.common.testing.InstantTaskExecutorRule;
 import com.android.car.arch.common.testing.TestLifecycleOwner;
-import com.android.car.media.common.TestConfig;
 
 import org.junit.Before;
 import org.junit.Rule;
@@ -42,14 +42,12 @@
 import org.mockito.junit.MockitoJUnit;
 import org.mockito.junit.MockitoRule;
 import org.robolectric.RobolectricTestRunner;
-import org.robolectric.annotation.Config;
 
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
 @RunWith(RobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class MediaBrowserConnectorTest {
 
     @Rule
diff --git a/car-media-common/tests/robotests/src/com/android/car/media/common/source/MediaSourceViewModelTest.java b/car-media-common/tests/robotests/src/com/android/car/media/common/source/MediaSourceViewModelTest.java
index b825fa1..b22bba2 100644
--- a/car-media-common/tests/robotests/src/com/android/car/media/common/source/MediaSourceViewModelTest.java
+++ b/car-media-common/tests/robotests/src/com/android/car/media/common/source/MediaSourceViewModelTest.java
@@ -16,13 +16,14 @@
 
 package com.android.car.media.common.source;
 
+import static android.car.media.CarMediaManager.MEDIA_SOURCE_MODE_PLAYBACK;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 import static org.robolectric.RuntimeEnvironment.application;
 
-import android.annotation.NonNull;
 import android.app.Application;
 import android.car.Car;
 import android.car.media.CarMediaManager;
@@ -31,12 +32,12 @@
 import android.support.v4.media.session.MediaControllerCompat;
 import android.support.v4.media.session.MediaSessionCompat;
 
+import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 
 import com.android.car.arch.common.testing.CaptureObserver;
 import com.android.car.arch.common.testing.InstantTaskExecutorRule;
 import com.android.car.arch.common.testing.TestLifecycleOwner;
-import com.android.car.media.common.TestConfig;
 
 import org.junit.Before;
 import org.junit.Rule;
@@ -46,10 +47,8 @@
 import org.mockito.junit.MockitoJUnit;
 import org.mockito.junit.MockitoRule;
 import org.robolectric.RobolectricTestRunner;
-import org.robolectric.annotation.Config;
 
 @RunWith(RobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class MediaSourceViewModelTest {
 
     private static final String BROWSER_CONTROLLER_PACKAGE_NAME = "browser";
@@ -90,7 +89,8 @@
     }
 
     private void initializeViewModel() {
-        mViewModel = new MediaSourceViewModel(application, new MediaSourceViewModel.InputFactory() {
+        mViewModel = new MediaSourceViewModel(application, MEDIA_SOURCE_MODE_PLAYBACK,
+                new MediaSourceViewModel.InputFactory() {
             @Override
             public MediaBrowserConnector createMediaBrowserConnector(
                     @NonNull Application application,
diff --git a/car-media-common/tests/robotests/src/com/android/car/media/common/source/MediaSourcesLiveDataTest.java b/car-media-common/tests/robotests/src/com/android/car/media/common/source/MediaSourcesLiveDataTest.java
index d9d4e82..f97b278 100644
--- a/car-media-common/tests/robotests/src/com/android/car/media/common/source/MediaSourcesLiveDataTest.java
+++ b/car-media-common/tests/robotests/src/com/android/car/media/common/source/MediaSourcesLiveDataTest.java
@@ -21,7 +21,6 @@
 import static org.robolectric.RuntimeEnvironment.application;
 import static org.robolectric.Shadows.shadowOf;
 
-import android.annotation.NonNull;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
@@ -31,9 +30,10 @@
 import android.os.Bundle;
 import android.service.media.MediaBrowserService;
 
+import androidx.annotation.NonNull;
+
 import com.android.car.arch.common.testing.InstantTaskExecutorRule;
 import com.android.car.arch.common.testing.TestLifecycleOwner;
-import com.android.car.media.common.TestConfig;
 
 import org.junit.Before;
 import org.junit.Rule;
@@ -42,7 +42,6 @@
 import org.mockito.junit.MockitoJUnit;
 import org.mockito.junit.MockitoRule;
 import org.robolectric.RobolectricTestRunner;
-import org.robolectric.annotation.Config;
 import org.robolectric.shadows.ShadowApplication;
 import org.robolectric.shadows.ShadowPackageManager;
 
@@ -51,7 +50,6 @@
 import java.util.stream.Collectors;
 
 @RunWith(RobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class MediaSourcesLiveDataTest {
 
     @Rule
diff --git a/car-messenger-common/Android.bp b/car-messenger-common/Android.bp
index 19ed50f..f826816 100644
--- a/car-messenger-common/Android.bp
+++ b/car-messenger-common/Android.bp
@@ -30,8 +30,10 @@
     static_libs: [
         "android.car.userlib",
         "androidx.legacy_legacy-support-v4",
-        "car-apps-common-bp",
+        "car-apps-common",
         "car-messenger-protos",
+        "car-telephony-common",
         "connected-device-protos",
+        "libphonenumber",
     ],
 }
diff --git a/car-messenger-common/src/com/android/car/messenger/common/BaseNotificationDelegate.java b/car-messenger-common/src/com/android/car/messenger/common/BaseNotificationDelegate.java
index 3045cdc..da48646 100644
--- a/car-messenger-common/src/com/android/car/messenger/common/BaseNotificationDelegate.java
+++ b/car-messenger-common/src/com/android/car/messenger/common/BaseNotificationDelegate.java
@@ -16,6 +16,7 @@
 
 package com.android.car.messenger.common;
 
+import android.annotation.Nullable;
 import android.app.Notification;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
@@ -28,8 +29,9 @@
 import androidx.core.app.NotificationCompat;
 import androidx.core.app.NotificationCompat.Action;
 import androidx.core.app.Person;
+import androidx.core.graphics.drawable.IconCompat;
 
-import com.android.car.apps.common.LetterTileDrawable;
+import com.android.car.telephony.common.TelecomUtils;
 
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -73,8 +75,7 @@
             "com.android.car.messenger.common.REMOTE_INPUT_KEY";
 
     protected final Context mContext;
-    protected final String mClassName;
-    protected final NotificationManager mNotificationManager;
+    protected NotificationManager mNotificationManager;
     protected final boolean mUseLetterTile;
 
     /**
@@ -101,29 +102,16 @@
      **/
     protected final Map<MessageKey, Message> mMessages = new HashMap<>();
 
-    /**
-     * Maps a Bitmap of a sender's Large Icon to the sender's unique key.
-     * The extending class should always keep this map updated with the loaded Sender large icons
-     * before calling {@link BaseNotificationDelegate#postNotification(
-     * ConversationKey, ConversationNotificationInfo, String)}. If the large icon is not found for
-     * the {@link SenderKey} when constructing the notification, a {@link LetterTileDrawable} will
-     * be created for the sender, unless {@link BaseNotificationDelegate#mUseLetterTile} is set to
-     * false.
-     **/
-    protected final Map<SenderKey, Bitmap> mSenderLargeIcons = new HashMap<>();
-
     private final int mBitmapSize;
     private final float mCornerRadiusPercent;
 
     /**
      * Constructor for the BaseNotificationDelegate class.
      * @param context of the calling application.
-     * @param className of the calling application.
      * @param useLetterTile whether a letterTile icon should be used if no avatar icon is given.
      **/
-    public BaseNotificationDelegate(Context context, String className, boolean useLetterTile) {
+    public BaseNotificationDelegate(Context context, boolean useLetterTile) {
         mContext = context;
-        mClassName = className;
         mUseLetterTile = useLetterTile;
         mNotificationManager =
                 (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
@@ -141,7 +129,6 @@
         clearNotifications(predicate);
         mNotificationBuilders.entrySet().removeIf(entry -> predicate.test(entry.getKey()));
         mNotificationInfos.entrySet().removeIf(entry -> predicate.test(entry.getKey()));
-        mSenderLargeIcons.entrySet().removeIf(entry -> predicate.test(entry.getKey()));
         mMessages.entrySet().removeIf(
                 messageKeyMapMessageEntry -> predicate.test(messageKeyMapMessageEntry.getKey()));
     }
@@ -159,6 +146,23 @@
         });
     }
 
+    protected void dismissInternal(ConversationKey convoKey) {
+        clearNotifications(key -> key.equals(convoKey));
+        excludeFromNotification(convoKey);
+    }
+
+    /**
+     * Excludes messages from a notification so that the messages are not shown to the user once
+     * the notification gets updated with newer messages.
+     */
+    protected void excludeFromNotification(ConversationKey convoKey) {
+        ConversationNotificationInfo info = mNotificationInfos.get(convoKey);
+        for (MessageKey key : info.mMessageKeys) {
+            Message message = mMessages.get(key);
+            message.excludeFromNotification();
+        }
+    }
+
     /**
      * Helper method to add {@link Message}s to the {@link ConversationNotificationInfo}. This
      * should be called when a new message has arrived.
@@ -180,7 +184,8 @@
      * and all of its {@link Message} objects have been linked to it.
      **/
     protected void postNotification(ConversationKey conversationKey,
-            ConversationNotificationInfo notificationInfo, String channelId) {
+            ConversationNotificationInfo notificationInfo, String channelId,
+            @Nullable Bitmap avatarIcon) {
         boolean newNotification = !mNotificationBuilders.containsKey(conversationKey);
 
         NotificationCompat.Builder builder = newNotification ? new NotificationCompat.Builder(
@@ -194,17 +199,16 @@
                 R.plurals.notification_new_message, notificationInfo.mMessageKeys.size(),
                 notificationInfo.mMessageKeys.size()));
 
-        if (mSenderLargeIcons.containsKey(getSenderKeyFromConversation(conversationKey))) {
-            builder.setLargeIcon(
-                    mSenderLargeIcons.get(getSenderKeyFromConversation(conversationKey)));
+        if (avatarIcon != null) {
+            builder.setLargeIcon(avatarIcon);
         } else if (mUseLetterTile) {
-            builder.setLargeIcon(Utils.createLetterTile(mContext,
+            builder.setLargeIcon(TelecomUtils.createLetterTile(mContext,
                     Utils.getInitials(lastMessage.getSenderName(), ""),
-                    lastMessage.getSenderName(), mBitmapSize, mCornerRadiusPercent));
+                    lastMessage.getSenderName(), mBitmapSize, mCornerRadiusPercent).getBitmap());
         }
         // Else, no avatar icon will be shown.
 
-        builder.setWhen(lastMessage.getReceiveTime());
+        builder.setWhen(lastMessage.getReceivedTime());
 
         // Create MessagingStyle
         String userName = (notificationInfo.getUserDisplayName() == null
@@ -223,7 +227,7 @@
             if (!message.shouldExcludeFromNotification()) {
                 messagingStyle.addMessage(
                         message.getMessageText(),
-                        message.getReceiveTime(),
+                        message.getReceivedTime(),
                         notificationInfo.isGroupConvo() ? new Person.Builder()
                                 .setName(message.getSenderName())
                                 .setUri(message.getSenderContactUri())
@@ -239,10 +243,10 @@
         // We are creating this notification for the first time.
         if (newNotification) {
             builder.setCategory(Notification.CATEGORY_MESSAGE);
-            if (notificationInfo.getAppSmallIconResId() == 0) {
-                builder.setSmallIcon(R.drawable.ic_message);
+            if (notificationInfo.getAppIcon() != null) {
+                builder.setSmallIcon(IconCompat.createFromIcon(notificationInfo.getAppIcon()));
             } else {
-                builder.setSmallIcon(notificationInfo.getAppSmallIconResId());
+                builder.setSmallIcon(R.drawable.ic_message);
             }
 
             builder.setShowWhen(true);
@@ -319,16 +323,11 @@
             String action) {
         Intent intent = new Intent(mContext, mContext.getClass())
                 .setAction(action)
-                .setClassName(mContext, mClassName)
+                .setClassName(mContext, mContext.getClass().getName())
                 .putExtra(EXTRA_CONVERSATION_KEY, conversationKey);
 
         return PendingIntent.getForegroundService(mContext, notificationId, intent,
                 PendingIntent.FLAG_UPDATE_CURRENT);
     }
 
-    protected SenderKey getSenderKeyFromConversation(ConversationKey conversationKey) {
-        ConversationNotificationInfo info = mNotificationInfos.get(conversationKey);
-        return mMessages.get(info.getLastMessageKey()).getSenderKey();
-    }
-
 }
diff --git a/car-messenger-common/src/com/android/car/messenger/common/ConversationKey.java b/car-messenger-common/src/com/android/car/messenger/common/ConversationKey.java
index 1b9b7b9..93a774a 100644
--- a/car-messenger-common/src/com/android/car/messenger/common/ConversationKey.java
+++ b/car-messenger-common/src/com/android/car/messenger/common/ConversationKey.java
@@ -16,6 +16,8 @@
 
 package com.android.car.messenger.common;
 
+import android.bluetooth.BluetoothDevice;
+import android.content.Intent;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -29,6 +31,18 @@
         super(deviceId, key);
     }
 
+    /** Creates a ConversationKey from a BluetoothMapClient intent. **/
+    public static ConversationKey createConversationKey(Intent intent) {
+        BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
+        String senderUri = Utils.getSenderUri(intent);
+        String senderName = Utils.getSenderName(intent);
+        String subKey = senderName + "/" + senderUri;
+        if (Utils.isGroupConversation(intent)) {
+            subKey = Utils.getInclusiveRecipientsUrisList(intent).toString();
+        }
+        return new ConversationKey(device.getAddress(), subKey);
+    }
+
     @Override
     public int describeContents() {
         return 0;
diff --git a/car-messenger-common/src/com/android/car/messenger/common/ConversationNotificationInfo.java b/car-messenger-common/src/com/android/car/messenger/common/ConversationNotificationInfo.java
index 5567f50..3baf3fd 100644
--- a/car-messenger-common/src/com/android/car/messenger/common/ConversationNotificationInfo.java
+++ b/car-messenger-common/src/com/android/car/messenger/common/ConversationNotificationInfo.java
@@ -20,6 +20,9 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.bluetooth.BluetoothDevice;
+import android.content.Intent;
+import android.graphics.drawable.Icon;
 import android.os.Build;
 import android.util.Log;
 
@@ -29,6 +32,7 @@
 import com.android.car.messenger.NotificationMsgProto.NotificationMsg.PhoneToCarMessage;
 
 import java.util.LinkedList;
+import java.util.List;
 
 /**
  * Represents a conversation notification's metadata that is shared between the conversation's
@@ -36,14 +40,14 @@
  * ConversationNotificationInfo object.
  **/
 public class ConversationNotificationInfo {
-    private static final String TAG = "CMC.ConversationNotificationInfo";
+    private static final String TAG = "CMC.ConvoNotifInfo";
     private static int sNextNotificationId = 0;
     final int mNotificationId = sNextNotificationId++;
 
     private final String mDeviceName;
     private final String mDeviceId;
     // This is always the sender name for SMS Messages from Bluetooth MAP.
-    private final String mConvoTitle;
+    private String mConvoTitle;
     private final boolean mIsGroupConvo;
 
     /** Only used for {@link NotificationMsg} conversations. **/
@@ -51,9 +55,14 @@
     private final String mNotificationKey;
     @Nullable
     private final String mAppDisplayName;
+    private final String mAppPackageName;
     @Nullable
     private final String mUserDisplayName;
-    private final int mAppSmallIconResId;
+    @Nullable
+    private final Icon mAppIcon;
+    /** Uris of all members in a MMS Group Conversation. **/
+    @Nullable
+    private final List<String> mCcRecipientsUris;
 
     public final LinkedList<MessageKey> mMessageKeys = new LinkedList<>();
 
@@ -77,18 +86,39 @@
             }
         }
 
+        Icon appIcon = null;
+        if (conversation.getAppIcon() != null) {
+            byte[] iconBytes = conversation.getAppIcon().toByteArray();
+            appIcon = Icon.createWithData(iconBytes, 0, iconBytes.length);
+        }
+
         return new ConversationNotificationInfo(deviceName, deviceId,
                 messagingStyle.getConvoTitle(),
                 messagingStyle.getIsGroupConvo(), notificationKey,
                 conversation.getMessagingAppDisplayName(),
-                messagingStyle.getUserDisplayName(), /* appSmallIconResId= */ 0);
+                conversation.getMessagingAppPackageName(),
+                messagingStyle.getUserDisplayName(),
+                appIcon,
+                /* ccUris= */null);
 
     }
+    /** Creates a ConversationNotificationInfo for a BluetoothMapClient intent. **/
+    public static ConversationNotificationInfo createConversationNotificationInfo(Intent intent,
+            String conversationTitle, String appPackageName, @Nullable Icon appIcon) {
+        BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
+
+        return new ConversationNotificationInfo(device.getName(), device.getAddress(),
+                conversationTitle, Utils.isGroupConversation(intent), /* notificationKey */ null,
+                /* appDisplayName */ null, appPackageName, /* userDisplayName */ null,
+                appIcon,
+                Utils.getInclusiveRecipientsUrisList(intent));
+    }
 
     private ConversationNotificationInfo(@Nullable String deviceName, String deviceId,
             String convoTitle, boolean isGroupConvo, @Nullable String notificationKey,
-            @Nullable String appDisplayName, @Nullable String userDisplayName,
-            int appSmallIconResId) {
+            @Nullable String appDisplayName, String appPackageName,
+            @Nullable String userDisplayName, @Nullable Icon appIcon,
+            @Nullable List<String> ccUris) {
         boolean missingDeviceId = (deviceId == null);
         boolean missingTitle = (convoTitle == null);
         if (missingDeviceId || missingTitle) {
@@ -107,8 +137,10 @@
         this.mIsGroupConvo = isGroupConvo;
         this.mNotificationKey = notificationKey;
         this.mAppDisplayName = appDisplayName;
+        this.mAppPackageName = appPackageName;
         this.mUserDisplayName = userDisplayName;
-        this.mAppSmallIconResId = appSmallIconResId;
+        this.mAppIcon = appIcon;
+        this.mCcRecipientsUris = ccUris;
     }
 
     /** Returns the id that should be used for this object's {@link android.app.Notification} **/
@@ -134,6 +166,11 @@
         return mConvoTitle;
     }
 
+    /** Update the conversation title. **/
+    public void setConvoTitle(String newTitle) {
+        mConvoTitle = newTitle;
+    }
+
     /** Returns {@code true} if this message is in a group conversation **/
     public boolean isGroupConvo() {
         return mIsGroupConvo;
@@ -158,6 +195,13 @@
     }
 
     /**
+     * Returns the package name of the application that posted this notification.
+     **/
+    public String getAppPackageName() {
+        return mAppPackageName;
+    }
+
+    /**
      * Returns the User Display Name if this object is based on a @link ConversationNotification}.
      * This is needed for {@link android.app.Notification.MessagingStyle}.
      */
@@ -167,12 +211,22 @@
     }
 
 
-    /** Returns the icon's resource id of the application that posted this notification. **/
-    public int getAppSmallIconResId() {
-        return mAppSmallIconResId;
+    /** Returns the app's icon of the application that posted this notification. **/
+    @Nullable
+    public Icon getAppIcon() {
+        return mAppIcon;
     }
 
     public MessageKey getLastMessageKey() {
         return mMessageKeys.getLast();
     }
+
+    /**
+     * Returns the sorted URIs of all the participants of a MMS/SMS/RCS conversation. Returns
+     * {@code null} if this is based on a {@link NotificationMsg} conversation.
+     */
+    @Nullable
+    public List<String> getCcRecipientsUris() {
+        return mCcRecipientsUris;
+    }
 }
diff --git a/car-messenger-common/src/com/android/car/messenger/common/Message.java b/car-messenger-common/src/com/android/car/messenger/common/Message.java
index 017d055..a2c1d60 100644
--- a/car-messenger-common/src/com/android/car/messenger/common/Message.java
+++ b/car-messenger-common/src/com/android/car/messenger/common/Message.java
@@ -17,8 +17,13 @@
 package com.android.car.messenger.common;
 
 import static com.android.car.apps.common.util.SafeLog.logw;
+import static com.android.car.messenger.common.Utils.BMC_EXTRA_MESSAGE_HANDLE;
+import static com.android.car.messenger.common.Utils.BMC_EXTRA_MESSAGE_READ_STATUS;
+import static com.android.car.messenger.common.Utils.BMC_EXTRA_MESSAGE_TIMESTAMP;
 
 import android.annotation.Nullable;
+import android.bluetooth.BluetoothDevice;
+import android.content.Intent;
 import android.os.Build;
 import android.util.Log;
 
@@ -36,7 +41,7 @@
     private final String mSenderName;
     private final String mDeviceId;
     private final String mMessageText;
-    private final long mReceiveTime;
+    private final long mReceivedTime;
     private final boolean mIsReadOnPhone;
     private boolean mShouldExclude;
     private final String mHandle;
@@ -64,11 +69,12 @@
      *
      * @param deviceId of the phone that received this message.
      * @param updatedMessage containing the information to base this message object off of.
-     * @param appDisplayName of the messaging app this message belongs to.
+     * @param senderKey of the sender of the message. Not guaranteed to be unique for all senders
+     *                  if this message is part of a group conversation.
      **/
     @Nullable
     public static Message parseFromMessage(String deviceId,
-            MessagingStyleMessage updatedMessage, String appDisplayName) {
+            MessagingStyleMessage updatedMessage, SenderKey senderKey) {
 
         if (!Utils.isValidMessagingStyleMessage(updatedMessage)) {
             if (Log.isLoggable(TAG, Log.DEBUG) || Build.IS_DEBUGGABLE) {
@@ -88,12 +94,44 @@
                 Utils.createMessageHandle(updatedMessage),
                 MessageType.NOTIFICATION_MESSAGE,
                 /* senderContactUri */ null,
-                appDisplayName);
+                senderKey);
     }
 
-    private Message(String senderName, String deviceId, String messageText, long receiveTime,
+    /**
+     * Creates a Message based on BluetoothMapClient intent. Returns {@code null} if the
+     * intent is missing required fields.
+     **/
+    public static Message parseFromIntent(Intent intent) {
+        if (!Utils.isValidMapClientIntent(intent)) {
+            if (Log.isLoggable(TAG, Log.DEBUG) || Build.IS_DEBUGGABLE) {
+                throw new IllegalArgumentException(
+                        "BluetoothMapClient intent is missing required fields");
+            } else {
+                logw(TAG, "BluetoothMapClient intent is missing required fields");
+                return null;
+            }
+        }
+        BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
+        String senderUri = Utils.getSenderUri(intent);
+
+        return new Message(
+                Utils.getSenderName(intent),
+                device.getAddress(),
+                intent.getStringExtra(android.content.Intent.EXTRA_TEXT),
+                intent.getLongExtra(BMC_EXTRA_MESSAGE_TIMESTAMP,
+                        System.currentTimeMillis()),
+                intent.getBooleanExtra(BMC_EXTRA_MESSAGE_READ_STATUS,
+                        false),
+                intent.getStringExtra(BMC_EXTRA_MESSAGE_HANDLE),
+                MessageType.BLUETOOTH_MAP_MESSAGE,
+                senderUri,
+                SenderKey.createSenderKey(intent)
+        );
+    }
+
+    private Message(String senderName, String deviceId, String messageText, long receivedTime,
             boolean isReadOnPhone, String handle, MessageType messageType,
-            @Nullable String senderContactUri, String senderKeyMetadata) {
+            @Nullable String senderContactUri, SenderKey senderKey) {
         boolean missingSenderName = (senderName == null);
         boolean missingDeviceId = (deviceId == null);
         boolean missingText = (messageText == null);
@@ -121,13 +159,13 @@
         this.mSenderName = senderName;
         this.mDeviceId = deviceId;
         this.mMessageText = messageText;
-        this.mReceiveTime = receiveTime;
+        this.mReceivedTime = receivedTime;
         this.mIsReadOnPhone = isReadOnPhone;
         this.mShouldExclude = false;
         this.mHandle = handle;
         this.mMessageType = messageType;
         this.mSenderContactUri = senderContactUri;
-        this.mSenderKey = new SenderKey(deviceId, senderName, senderKeyMetadata);
+        this.mSenderKey = senderKey;
     }
 
     /**
@@ -157,8 +195,8 @@
      * Returns the milliseconds since epoch at which this message notification was received on the
      * head-unit.
      */
-    public long getReceiveTime() {
-        return mReceiveTime;
+    public long getReceivedTime() {
+        return mReceivedTime;
     }
 
     /**
@@ -196,7 +234,12 @@
     }
 
     /**
-     * Returns the {@link SenderKey} that is unique for each contact per device.
+     * If the message came from BluetoothMapClient, this retrieves a key that is unique
+     * for each contact per device.
+     * If the message came from {@link NotificationMsg}, this retrieves a key that is only
+     * guaranteed to be unique per sender in a 1-1 conversation. If this message is part of a
+     * group conversation, the senderKey will not be unique if more than one participant in the
+     * conversation share the same name.
      */
     public SenderKey getSenderKey() {
         return mSenderKey;
@@ -223,7 +266,7 @@
                 + " mSenderName='" + mSenderName + '\''
                 + ", mMessageText='" + mMessageText + '\''
                 + ", mSenderContactUri='" + mSenderContactUri + '\''
-                + ", mReceiveTime=" + mReceiveTime + '\''
+                + ", mReceiveTime=" + mReceivedTime + '\''
                 + ", mIsReadOnPhone= " + mIsReadOnPhone + '\''
                 + ", mShouldExclude= " + mShouldExclude + '\''
                 + ", mHandle='" + mHandle + '\''
diff --git a/car-messenger-common/src/com/android/car/messenger/common/ProjectionStateListener.java b/car-messenger-common/src/com/android/car/messenger/common/ProjectionStateListener.java
index 5557830..ddc8fac 100644
--- a/car-messenger-common/src/com/android/car/messenger/common/ProjectionStateListener.java
+++ b/car-messenger-common/src/com/android/car/messenger/common/ProjectionStateListener.java
@@ -37,38 +37,45 @@
  * {@link ProjectionStatus} listener that exposes APIs to detect whether a projection application
  * is active.
  */
-public class ProjectionStateListener implements CarProjectionManager.ProjectionStatusListener{
+public class ProjectionStateListener {
     private static final String TAG = "CMC.ProjectionStateHandler";
     static final String PROJECTION_STATUS_EXTRA_DEVICE_STATE =
             "android.car.projection.DEVICE_STATE";
 
-    private final CarProjectionManager mCarProjectionManager;
+    private CarProjectionManager mCarProjectionManager = null;
+    private final CarProjectionManager.ProjectionStatusListener mListener =
+            (state, packageName, details) -> {
+                mProjectionState = state;
+                mProjectionDetails = details;
+            };
+    private Car mCar;
 
     private int mProjectionState = ProjectionStatus.PROJECTION_STATE_INACTIVE;
     private List<ProjectionStatus> mProjectionDetails = Collections.emptyList();
 
     public ProjectionStateListener(Context context) {
-        mCarProjectionManager = (CarProjectionManager)
-                Car.createCar(context).getCarManager(Car.PROJECTION_SERVICE);
-    }
-
-    /** Registers the listener. Should be called when the caller starts up. **/
-    public void start() {
-        mCarProjectionManager.registerProjectionStatusListener(this);
+        Car.createCar(context, /* handler= */ null, Car.CAR_WAIT_TIMEOUT_DO_NOT_WAIT,
+                (car, ready) -> {
+                    mCar = car;
+                    mCarProjectionManager = (CarProjectionManager) mCar.getCarManager(
+                            Car.PROJECTION_SERVICE);
+                    if (mCarProjectionManager != null) {
+                        mCarProjectionManager.registerProjectionStatusListener(mListener);
+                    }
+                });
     }
 
     /** Unregisters the listener. Should be called when the caller's lifecycle is ending. **/
-    public void stop() {
-        mCarProjectionManager.unregisterProjectionStatusListener(this);
-    }
-
-
-    @Override
-    public void onProjectionStatusChanged(int state, String packageName,
-            List<ProjectionStatus> details) {
-        mProjectionState = state;
-        mProjectionDetails = details;
-
+    public void destroy() {
+        if (mCarProjectionManager != null) {
+            mCarProjectionManager.unregisterProjectionStatusListener(mListener);
+        }
+        if (mCar != null) {
+            mCar.disconnect();
+            mCar = null;
+        }
+        mProjectionState = ProjectionStatus.PROJECTION_STATE_INACTIVE;
+        mProjectionDetails = Collections.emptyList();
     }
 
     /**
diff --git a/car-messenger-common/src/com/android/car/messenger/common/SenderKey.java b/car-messenger-common/src/com/android/car/messenger/common/SenderKey.java
index 2fcd273..8e220b4 100644
--- a/car-messenger-common/src/com/android/car/messenger/common/SenderKey.java
+++ b/car-messenger-common/src/com/android/car/messenger/common/SenderKey.java
@@ -16,6 +16,9 @@
 
 package com.android.car.messenger.common;
 
+import android.bluetooth.BluetoothDevice;
+import android.content.Intent;
+
 import com.android.car.messenger.NotificationMsgProto.NotificationMsg;
 
 /**
@@ -24,7 +27,28 @@
  */
 public class SenderKey extends CompositeKey {
     /** Creates a senderkey for SMS, MMS, and {@link NotificationMsg}. **/
-    protected SenderKey(String deviceId, String senderName, String keyMetadata) {
+    private SenderKey(String deviceId, String senderName, String keyMetadata) {
         super(deviceId, senderName + "/" + keyMetadata);
     }
+
+    /**
+     * Returns the SenderKey for the BluetoothMapClient intent. This should be unique
+     * for each contact per device.
+     */
+    public static SenderKey createSenderKey(Intent intent) {
+        BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
+        return new SenderKey(device.getAddress(), Utils.getSenderName(intent),
+                Utils.getSenderUri(intent));
+    }
+
+    /**
+     * Returns the SenderKey based on a {@link NotificationMsg} DAO. This key is only
+     * guaranteed to be unique for a 1-1 conversation. If the ConversationKey is for a
+     * group conversation, the senderKey will not be unique if more than one participant in the
+     * conversation share the same name.
+     */
+    public static SenderKey createSenderKey(ConversationKey convoKey,
+            NotificationMsg.Person person) {
+        return new SenderKey(convoKey.getDeviceId(), person.getName(), convoKey.getSubKey());
+    }
 }
diff --git a/car-messenger-common/src/com/android/car/messenger/common/Utils.java b/car-messenger-common/src/com/android/car/messenger/common/Utils.java
index 027189e..282c1f5 100644
--- a/car-messenger-common/src/com/android/car/messenger/common/Utils.java
+++ b/car-messenger-common/src/com/android/car/messenger/common/Utils.java
@@ -18,7 +18,9 @@
 
 import static com.android.car.apps.common.util.SafeLog.logw;
 
+import android.bluetooth.BluetoothDevice;
 import android.content.Context;
+import android.content.Intent;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.text.TextUtils;
@@ -29,11 +31,22 @@
 
 import com.android.car.apps.common.LetterTileDrawable;
 import com.android.car.messenger.NotificationMsgProto.NotificationMsg;
+import com.android.car.messenger.NotificationMsgProto.NotificationMsg.AvatarIconSync;
 import com.android.car.messenger.NotificationMsgProto.NotificationMsg.ConversationNotification;
 import com.android.car.messenger.NotificationMsgProto.NotificationMsg.MessagingStyle;
 import com.android.car.messenger.NotificationMsgProto.NotificationMsg.MessagingStyleMessage;
 import com.android.car.messenger.NotificationMsgProto.NotificationMsg.Person;
 
+import com.google.i18n.phonenumbers.NumberParseException;
+import com.google.i18n.phonenumbers.PhoneNumberUtil;
+import com.google.i18n.phonenumbers.Phonenumber;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
 /** Utils methods for the car-messenger-common lib. **/
 public class Utils {
     private static final String TAG = "CMC.Utils";
@@ -43,6 +56,24 @@
      */
     private static final int MAX_SUB_MESSAGE_LENGTH = 5;
 
+    /** The Regex format of a telephone number in a BluetoothMapClient contact URI. **/
+    private static final String MAP_CLIENT_URI_REGEX = "tel:(.+)";
+
+    /** The starting substring index for a string formatted with the MAP_CLIENT_URI_REGEX above. **/
+    private static final int MAP_CLIENT_URI_PHONE_NUMBER_SUBSTRING_INDEX = 4;
+
+    // TODO (150711637): Reference BluetoothMapClient Extras once BluetoothMapClient is SystemApi.
+    protected static final String BMC_EXTRA_MESSAGE_HANDLE =
+            "android.bluetooth.mapmce.profile.extra.MESSAGE_HANDLE";
+    protected static final String BMC_EXTRA_SENDER_CONTACT_URI =
+            "android.bluetooth.mapmce.profile.extra.SENDER_CONTACT_URI";
+    protected static final String BMC_EXTRA_SENDER_CONTACT_NAME =
+            "android.bluetooth.mapmce.profile.extra.SENDER_CONTACT_NAME";
+    protected static final String BMC_EXTRA_MESSAGE_TIMESTAMP =
+            "android.bluetooth.mapmce.profile.extra.MESSAGE_TIMESTAMP";
+    protected static final String BMC_EXTRA_MESSAGE_READ_STATUS =
+            "android.bluetooth.mapmce.profile.extra.MESSAGE_READ_STATUS";
+
     /** Gets the latest message for a {@link NotificationMsg} Conversation. **/
     public static MessagingStyleMessage getLatestMessage(
             ConversationNotification notification) {
@@ -152,6 +183,49 @@
     }
 
     /**
+     * Ensure the {@link AvatarIconSync} object has all the required fields.
+     **/
+    public static boolean isValidAvatarIconSync(AvatarIconSync iconSync) {
+        if (iconSync == null) {
+            logw(TAG, "AvatarIconSync is null");
+            return false;
+        } else if (iconSync.getMessagingAppPackageName() == null) {
+            logw(TAG, "AvatarIconSync is missing required field: appPackageName");
+            return false;
+        } else if (iconSync.getPerson().getName() == null) {
+            logw(TAG, "AvatarIconSync is missing required field: Person's name");
+            return false;
+        } else if (iconSync.getPerson().getAvatar() == null) {
+            logw(TAG, "AvatarIconSync is missing required field: Person's avatar");
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Ensure the BluetoothMapClient intent has all the required fields.
+     **/
+    public static boolean isValidMapClientIntent(Intent intent) {
+        if (intent == null) {
+            logw(TAG, "BluetoothMapClient intent is null");
+            return false;
+        } else if (intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE) == null) {
+            logw(TAG, "BluetoothMapClient intent is missing required field: device");
+            return false;
+        } else if (intent.getStringExtra(BMC_EXTRA_MESSAGE_HANDLE) == null) {
+            logw(TAG, "BluetoothMapClient intent is missing required field: senderName");
+            return false;
+        } else if (intent.getStringExtra(BMC_EXTRA_SENDER_CONTACT_NAME) == null) {
+            logw(TAG, "BluetoothMapClient intent is missing required field: handle");
+            return false;
+        } else if (intent.getStringExtra(android.content.Intent.EXTRA_TEXT) == null) {
+            logw(TAG, "BluetoothMapClient intent is missing required field: messageText");
+            return false;
+        }
+        return true;
+    }
+
+    /**
      * Creates a Letter Tile Icon that will display the given initials. If the initials are null,
      * then an avatar anonymous icon will be drawn.
      **/
@@ -205,6 +279,11 @@
         return letterTileDrawable;
     }
 
+    /** Returns whether the BluetoothMapClient intent represents a group conversation. **/
+    public static boolean isGroupConversation(Intent intent) {
+        return (intent.getStringArrayExtra(Intent.EXTRA_CC) != null
+                && intent.getStringArrayExtra(Intent.EXTRA_CC).length > 0);
+    }
 
     /**
      * Returns the initials based on the name and nameAlt.
@@ -226,4 +305,69 @@
         return initials.toString();
     }
 
+    /** Returns the list of sender uri for a BluetoothMapClient intent. **/
+    public static String getSenderUri(Intent intent) {
+        return intent.getStringExtra(BMC_EXTRA_SENDER_CONTACT_URI);
+    }
+
+    /** Returns the sender name for a BluetoothMapClient intent. **/
+    public static String getSenderName(Intent intent) {
+        return intent.getStringExtra(BMC_EXTRA_SENDER_CONTACT_NAME);
+    }
+
+    /** Returns the list of recipient uris for a BluetoothMapClient intent. **/
+    public static List<String> getInclusiveRecipientsUrisList(Intent intent) {
+        List<String> ccUris = new ArrayList<>();
+        ccUris.add(getSenderUri(intent));
+        if (isGroupConversation(intent)) {
+            ccUris.addAll(Arrays.asList(intent.getStringArrayExtra(Intent.EXTRA_CC)));
+            Collections.sort(ccUris);
+        }
+        return ccUris;
+    }
+
+    /**
+     * Extracts the phone number from the BluetoothMapClient contact Uri.
+     **/
+    @Nullable
+    public static String getPhoneNumberFromMapClient(@Nullable String senderContactUri) {
+        if (senderContactUri == null || !senderContactUri.matches(MAP_CLIENT_URI_REGEX)) {
+            return null;
+        }
+
+        return senderContactUri.substring(MAP_CLIENT_URI_PHONE_NUMBER_SUBSTRING_INDEX);
+    }
+
+    /** Comparator that sorts names alphabetically first, then phone numbers numerically. **/
+    public static final Comparator<String> ALPHA_THEN_NUMERIC_COMPARATOR =
+            new Comparator<String>() {
+                private boolean isPhoneNumber(String input) {
+                    PhoneNumberUtil util = PhoneNumberUtil.getInstance();
+                    try {
+                        Phonenumber.PhoneNumber phoneNumber = util.parse(input, /* defaultRegion */
+                                null);
+                        return util.isValidNumber(phoneNumber);
+                    } catch (NumberParseException e) {
+                        return false;
+                    }
+                }
+
+                private boolean isOfSameType(String o1, String o2) {
+                    boolean isO1PhoneNumber = isPhoneNumber(o1);
+                    boolean isO2PhoneNumber = isPhoneNumber(o2);
+                    return isO1PhoneNumber == isO2PhoneNumber;
+                }
+
+                @Override
+                public int compare(String o1, String o2) {
+                    // if both are names, sort based on names.
+                    // if both are number, sort numerically.
+                    // if one is phone number and the other is a name, give name precedence.
+                    if (!isOfSameType(o1, o2)) {
+                        return isPhoneNumber(o1) ? 1 : -1;
+                    } else {
+                        return o1.compareTo(o2);
+                    }
+                }
+            };
 }
diff --git a/car-settings-lib/Android.mk b/car-settings-lib/Android.mk
deleted file mode 100644
index 9cddc18..0000000
--- a/car-settings-lib/Android.mk
+++ /dev/null
@@ -1,43 +0,0 @@
-#
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-
-LOCAL_MODULE := car-settings-lib
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_USE_AAPT2 := true
-
-LOCAL_STATIC_ANDROID_LIBRARIES := \
-    androidx.annotation_annotation \
-    androidx.loader_loader
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-LOCAL_MIN_SDK_VERSION := 24
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
-# Use the following include to make our test apk.
-ifeq (,$(ONE_SHOT_MAKEFILE))
-    include $(call all-makefiles-under,$(LOCAL_PATH))
-endif
diff --git a/car-settings-lib/AndroidManifest.xml b/car-settings-lib/AndroidManifest.xml
deleted file mode 100644
index 5c2e6c9..0000000
--- a/car-settings-lib/AndroidManifest.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  Copyright (C) 2018 The Android Open Source Project
-
-  Licensed under the Apache License, Version 2.0 (the "License");
-  you may not use this file except in compliance with the License.
-  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-  Unless required by applicable law or agreed to in writing, software
-  distributed under the License is distributed on an "AS IS" BASIS,
-  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  See the License for the specific language governing permissions and
-  limitations under the License.
-  -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-          package="com.android.car.settingslib">
-    <uses-sdk android:minSdkVersion="24"/>
-    <application />
-</manifest>
\ No newline at end of file
diff --git a/car-settings-lib/OWNERS b/car-settings-lib/OWNERS
deleted file mode 100644
index e8ed8af..0000000
--- a/car-settings-lib/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# People who can approve changes for submission.
[email protected]
[email protected]
[email protected]
diff --git a/car-settings-lib/README.txt b/car-settings-lib/README.txt
deleted file mode 100644
index 8dcdb8a..0000000
--- a/car-settings-lib/README.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-Library Project for Car settings.
-Intended for sharing related code between Car Settings and CarSetUpWizard.
\ No newline at end of file
diff --git a/car-settings-lib/res/values-af/strings.xml b/car-settings-lib/res/values-af/strings.xml
deleted file mode 100644
index 38a0e1b..0000000
--- a/car-settings-lib/res/values-af/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Voorgestel"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Alle tale"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Veld kan nie leeg wees nie."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Ingevoerde gebruikernaam is ongeldig."</string>
-</resources>
diff --git a/car-settings-lib/res/values-am/strings.xml b/car-settings-lib/res/values-am/strings.xml
deleted file mode 100644
index 7aec3e0..0000000
--- a/car-settings-lib/res/values-am/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"የተጠቆሙ"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"ሁሉም ቋንቋዎች"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"መስክ ባዶ መሆን አይችልም።"</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"የገባው ተጠቃሚ ስም የማይሠራ ነው።"</string>
-</resources>
diff --git a/car-settings-lib/res/values-ar/strings.xml b/car-settings-lib/res/values-ar/strings.xml
deleted file mode 100644
index 2fb7894..0000000
--- a/car-settings-lib/res/values-ar/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"اللغات المقترحة"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"جميع اللغات"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"يجب عدم ترك الحقل فارغًا."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"اسم المستخدم المُدخل غير صالح."</string>
-</resources>
diff --git a/car-settings-lib/res/values-as/strings.xml b/car-settings-lib/res/values-as/strings.xml
deleted file mode 100644
index 747e8ab..0000000
--- a/car-settings-lib/res/values-as/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"পৰামৰ্শ দিয়া ভাষা"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"সকলো ভাষা"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"এই খালী ঠাই পূৰ নকৰাকৈ এৰিব নোৱাৰি।"</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"আপুনি দিয়া ব্য়ৱহাৰকাৰীৰ নাম মান্য় নহয়।"</string>
-</resources>
diff --git a/car-settings-lib/res/values-az/strings.xml b/car-settings-lib/res/values-az/strings.xml
deleted file mode 100644
index 29f7cfb..0000000
--- a/car-settings-lib/res/values-az/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Təklif edilmiş"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Bütün dillər"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Sahə boş ola bilməz."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Daxil edilən istifadəçi adı yanlışdır."</string>
-</resources>
diff --git a/car-settings-lib/res/values-b+sr+Latn/strings.xml b/car-settings-lib/res/values-b+sr+Latn/strings.xml
deleted file mode 100644
index c9450b1..0000000
--- a/car-settings-lib/res/values-b+sr+Latn/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Predloženi"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Svi jezici"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Polje ne sme da bude prazno."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Korisničko ime koje ste uneli je nevažeće."</string>
-</resources>
diff --git a/car-settings-lib/res/values-be/strings.xml b/car-settings-lib/res/values-be/strings.xml
deleted file mode 100644
index 0a55864..0000000
--- a/car-settings-lib/res/values-be/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Прапанавана"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Усе мовы"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Поле не можа быць пустым."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Уведзена несапраўднае імя карыстальніка"</string>
-</resources>
diff --git a/car-settings-lib/res/values-bg/strings.xml b/car-settings-lib/res/values-bg/strings.xml
deleted file mode 100644
index 7427987..0000000
--- a/car-settings-lib/res/values-bg/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Предложени"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Всички езици"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Полето трябва да се попълни."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Въведеното потребителско име е невалидно."</string>
-</resources>
diff --git a/car-settings-lib/res/values-bn/strings.xml b/car-settings-lib/res/values-bn/strings.xml
deleted file mode 100644
index 2023f4f..0000000
--- a/car-settings-lib/res/values-bn/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"প্রস্তাবিত"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"সমস্ত ভাষা"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"ক্ষেত্র খালি রাখা যাবে না।"</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"প্রদান করা ব্যবহারকারীর নামটি সঠিক নয়।"</string>
-</resources>
diff --git a/car-settings-lib/res/values-bs/strings.xml b/car-settings-lib/res/values-bs/strings.xml
deleted file mode 100644
index adf86c9..0000000
--- a/car-settings-lib/res/values-bs/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Predloženo"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Svi jezici"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Polje ne može biti prazno."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Korisničko ime koje ste unijeli je nevažeće."</string>
-</resources>
diff --git a/car-settings-lib/res/values-ca/strings.xml b/car-settings-lib/res/values-ca/strings.xml
deleted file mode 100644
index ee2b958..0000000
--- a/car-settings-lib/res/values-ca/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Suggerits"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Tots els idiomes"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"El camp no pot estar en blanc."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"El nom d\'usuari que has introduït no és vàlid."</string>
-</resources>
diff --git a/car-settings-lib/res/values-cs/strings.xml b/car-settings-lib/res/values-cs/strings.xml
deleted file mode 100644
index fca045b..0000000
--- a/car-settings-lib/res/values-cs/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Navrženo"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Všechny jazyky"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Pole nesmí být prázdné."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Zadané uživatelské jméno není platné."</string>
-</resources>
diff --git a/car-settings-lib/res/values-da/strings.xml b/car-settings-lib/res/values-da/strings.xml
deleted file mode 100644
index 2a585cb..0000000
--- a/car-settings-lib/res/values-da/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Foreslået"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Alle sprog"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Feltet må ikke være tomt."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Det brugernavn, du har angivet, er ugyldigt."</string>
-</resources>
diff --git a/car-settings-lib/res/values-de/strings.xml b/car-settings-lib/res/values-de/strings.xml
deleted file mode 100644
index a138ce7..0000000
--- a/car-settings-lib/res/values-de/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Vorgeschlagen"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Alle Sprachen"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Das Feld darf nicht leer sein."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Der eingegebene Nutzername ist ungültig."</string>
-</resources>
diff --git a/car-settings-lib/res/values-el/strings.xml b/car-settings-lib/res/values-el/strings.xml
deleted file mode 100644
index 2496924..0000000
--- a/car-settings-lib/res/values-el/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Προτεινόμενες"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Όλες οι γλώσσες"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Το πεδίο δεν μπορεί να παραμείνει κενό."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Το όνομα χρήστη που καταχωρίστηκε είναι μη έγκυρο."</string>
-</resources>
diff --git a/car-settings-lib/res/values-en-rAU/strings.xml b/car-settings-lib/res/values-en-rAU/strings.xml
deleted file mode 100644
index 96a64e0..0000000
--- a/car-settings-lib/res/values-en-rAU/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Suggested"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"All languages"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Field can\'t be blank."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Username entered is invalid."</string>
-</resources>
diff --git a/car-settings-lib/res/values-en-rCA/strings.xml b/car-settings-lib/res/values-en-rCA/strings.xml
deleted file mode 100644
index 96a64e0..0000000
--- a/car-settings-lib/res/values-en-rCA/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Suggested"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"All languages"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Field can\'t be blank."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Username entered is invalid."</string>
-</resources>
diff --git a/car-settings-lib/res/values-en-rGB/strings.xml b/car-settings-lib/res/values-en-rGB/strings.xml
deleted file mode 100644
index 96a64e0..0000000
--- a/car-settings-lib/res/values-en-rGB/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Suggested"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"All languages"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Field can\'t be blank."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Username entered is invalid."</string>
-</resources>
diff --git a/car-settings-lib/res/values-en-rIN/strings.xml b/car-settings-lib/res/values-en-rIN/strings.xml
deleted file mode 100644
index 96a64e0..0000000
--- a/car-settings-lib/res/values-en-rIN/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Suggested"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"All languages"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Field can\'t be blank."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Username entered is invalid."</string>
-</resources>
diff --git a/car-settings-lib/res/values-en-rXC/strings.xml b/car-settings-lib/res/values-en-rXC/strings.xml
deleted file mode 100644
index 80192d2..0000000
--- a/car-settings-lib/res/values-en-rXC/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‏‎‏‏‏‏‏‏‎‎‏‎‏‏‎‏‎‏‏‎‏‏‎‏‎‎‎‎‎‎‎‏‎‎‎‏‏‏‎‎‎‏‎‎‏‏‏‏‏‏‏‎‏‎‎‎‎‎‏‏‎Suggested‎‏‎‎‏‎"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‏‎‏‏‎‏‏‎‎‎‏‏‏‎‏‎‏‏‎‎‏‏‏‏‎‎‏‎‎‎‏‎‎‏‏‏‏‏‏‏‎‎‎‏‏‏‏‏‏‎‏‎‎‎‎‏‎‏‎‎‏‏‏‎‎All languages‎‏‎‎‏‎"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‏‎‏‏‏‏‎‎‏‎‎‎‎‎‎‎‏‏‏‏‏‎‎‎‏‏‎‎‏‎‎‏‏‏‏‏‎‏‏‎‏‏‏‎‎‏‏‎‏‎‎‎‎‎‏‏‎‏‎‏‎Field can’t be blank.‎‏‎‎‏‎"</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‏‎‎‏‎‎‏‏‏‎‎‏‎‎‏‏‏‏‏‎‎‏‏‎‏‏‏‎‏‎‏‎‎‏‎‏‎‎‏‎‎‏‎‏‎‎‎‏‎‏‎‎‎‎‎‎‏‎‏‎‎Username entered is invalid.‎‏‎‎‏‎"</string>
-</resources>
diff --git a/car-settings-lib/res/values-es-rUS/strings.xml b/car-settings-lib/res/values-es-rUS/strings.xml
deleted file mode 100644
index 92eff9f..0000000
--- a/car-settings-lib/res/values-es-rUS/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Sugerencias"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Todos los idiomas"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Este campo no puede quedar vacío."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"El nombre de usuario ingresado no es válido."</string>
-</resources>
diff --git a/car-settings-lib/res/values-es/strings.xml b/car-settings-lib/res/values-es/strings.xml
deleted file mode 100644
index 0e70ac6..0000000
--- a/car-settings-lib/res/values-es/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Sugerencias"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Todos los idiomas"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"El campo no puede estar vacío."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"El nombre de usuario introducido no es válido."</string>
-</resources>
diff --git a/car-settings-lib/res/values-et/strings.xml b/car-settings-lib/res/values-et/strings.xml
deleted file mode 100644
index 0282368..0000000
--- a/car-settings-lib/res/values-et/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Soovitatud"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Kõik keeled"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Väli ei tohi olla tühi."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Sisestatud kasutajanimi on sobimatu."</string>
-</resources>
diff --git a/car-settings-lib/res/values-eu/strings.xml b/car-settings-lib/res/values-eu/strings.xml
deleted file mode 100644
index c8c0e10..0000000
--- a/car-settings-lib/res/values-eu/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Iradokitakoak"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Hizkuntza guztiak"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Eremuak ezin du hutsik egon."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Idatzitako erabiltzaile-izenak ez du balio."</string>
-</resources>
diff --git a/car-settings-lib/res/values-fa/strings.xml b/car-settings-lib/res/values-fa/strings.xml
deleted file mode 100644
index 3ce1002..0000000
--- a/car-settings-lib/res/values-fa/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"پیشنهادشده"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"همه زبان‌ها"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"این فیلد نمی‌تواند خالی باشد."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"نام کاربری واردشده نامعتبر است."</string>
-</resources>
diff --git a/car-settings-lib/res/values-fi/strings.xml b/car-settings-lib/res/values-fi/strings.xml
deleted file mode 100644
index cb5f2c9..0000000
--- a/car-settings-lib/res/values-fi/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Ehdotettu"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Kaikki kielet"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Kenttä ei voi olla tyhjä."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Annettu käyttäjänimi on virheellinen."</string>
-</resources>
diff --git a/car-settings-lib/res/values-fr-rCA/strings.xml b/car-settings-lib/res/values-fr-rCA/strings.xml
deleted file mode 100644
index ee93f50..0000000
--- a/car-settings-lib/res/values-fr-rCA/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Suggestions"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Toutes les langues"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Champ obligatoire."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Le nom d\'utilisateur entré n\'est pas valide."</string>
-</resources>
diff --git a/car-settings-lib/res/values-fr/strings.xml b/car-settings-lib/res/values-fr/strings.xml
deleted file mode 100644
index 250d38a..0000000
--- a/car-settings-lib/res/values-fr/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Suggestion"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Toutes les langues"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Champ obligatoire."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Le nom d\'utilisateur saisi est incorrect."</string>
-</resources>
diff --git a/car-settings-lib/res/values-gl/strings.xml b/car-settings-lib/res/values-gl/strings.xml
deleted file mode 100644
index e2a772a..0000000
--- a/car-settings-lib/res/values-gl/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Idiomas suxeridos"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Todos os idiomas"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"O campo non pode estar en branco."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"O nome de usuario que introduciches non é válido."</string>
-</resources>
diff --git a/car-settings-lib/res/values-gu/strings.xml b/car-settings-lib/res/values-gu/strings.xml
deleted file mode 100644
index 22826c7..0000000
--- a/car-settings-lib/res/values-gu/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"સૂચવેલા"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"બધી ભાષાઓ"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"ફીલ્ડ ખાલી રાખી શકાય નહીં."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"દાખલ કરેલું વપરાશકર્તાનું નામ અમાન્ય છે."</string>
-</resources>
diff --git a/car-settings-lib/res/values-hi/strings.xml b/car-settings-lib/res/values-hi/strings.xml
deleted file mode 100644
index 042be3b..0000000
--- a/car-settings-lib/res/values-hi/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"सुझाए गए"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"सभी भाषाएं"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"नाम लिखने की जगह (फ़ील्ड) खाली नहीं रखी जा सकती."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"डाला गया उपयोगकर्ता नाम गलत है."</string>
-</resources>
diff --git a/car-settings-lib/res/values-hr/strings.xml b/car-settings-lib/res/values-hr/strings.xml
deleted file mode 100644
index c0a69ff..0000000
--- a/car-settings-lib/res/values-hr/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Predloženo"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Svi jezici"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Polje ne može biti prazno."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Uneseno korisničko ime nije važeće."</string>
-</resources>
diff --git a/car-settings-lib/res/values-hu/strings.xml b/car-settings-lib/res/values-hu/strings.xml
deleted file mode 100644
index 275ea75..0000000
--- a/car-settings-lib/res/values-hu/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Javasolt"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Minden nyelv"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"A mező nem lehet üres."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"A megadott felhasználónév érvénytelen."</string>
-</resources>
diff --git a/car-settings-lib/res/values-hy/strings.xml b/car-settings-lib/res/values-hy/strings.xml
deleted file mode 100644
index fcab9c7..0000000
--- a/car-settings-lib/res/values-hy/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Առաջարկվող"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Բոլոր լեզուները"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Դաշտը չի կարող դատարկ լինել:"</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Մուտքագրված օգտանունն անվավեր է։"</string>
-</resources>
diff --git a/car-settings-lib/res/values-in/strings.xml b/car-settings-lib/res/values-in/strings.xml
deleted file mode 100644
index 51e4d3e..0000000
--- a/car-settings-lib/res/values-in/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Disarankan"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Semua bahasa"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Kolom harus diisi."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Nama pengguna yang dimasukkan tidak valid."</string>
-</resources>
diff --git a/car-settings-lib/res/values-is/strings.xml b/car-settings-lib/res/values-is/strings.xml
deleted file mode 100644
index 3dffde3..0000000
--- a/car-settings-lib/res/values-is/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Tillögur"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Öll tungumál"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Reiturinn má ekki vera auður."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Ógilt notandanafn var slegið inn."</string>
-</resources>
diff --git a/car-settings-lib/res/values-it/strings.xml b/car-settings-lib/res/values-it/strings.xml
deleted file mode 100644
index 69e1425..0000000
--- a/car-settings-lib/res/values-it/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Suggerite"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Tutte le lingue"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Il campo non può essere vuoto."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Il nome utente inserito non è valido."</string>
-</resources>
diff --git a/car-settings-lib/res/values-iw/strings.xml b/car-settings-lib/res/values-iw/strings.xml
deleted file mode 100644
index 180b3e8..0000000
--- a/car-settings-lib/res/values-iw/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"הצעות"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"כל השפות"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"חובה למלא את השדה."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"שם המשתמש שהוזן לא חוקי."</string>
-</resources>
diff --git a/car-settings-lib/res/values-ja/strings.xml b/car-settings-lib/res/values-ja/strings.xml
deleted file mode 100644
index 6374217..0000000
--- a/car-settings-lib/res/values-ja/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"言語の候補"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"すべての言語"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"フィールドは空欄にできません。"</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"入力されたユーザー名が無効です。"</string>
-</resources>
diff --git a/car-settings-lib/res/values-ka/strings.xml b/car-settings-lib/res/values-ka/strings.xml
deleted file mode 100644
index 6f93ba9..0000000
--- a/car-settings-lib/res/values-ka/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"რეკომენდებული"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"ყველა ენა"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"არ შეიძლება ველი ცარიელი იყოს."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"მომხმარებლის სახელი არასწორადაა შეყვანილი."</string>
-</resources>
diff --git a/car-settings-lib/res/values-kk/strings.xml b/car-settings-lib/res/values-kk/strings.xml
deleted file mode 100644
index ebf2013..0000000
--- a/car-settings-lib/res/values-kk/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Ұсынылған"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Барлық тілдер"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Өріс бос болмауы керек."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Енгізілген пайдаланушы аты жарамсыз."</string>
-</resources>
diff --git a/car-settings-lib/res/values-km/strings.xml b/car-settings-lib/res/values-km/strings.xml
deleted file mode 100644
index 2274c4c..0000000
--- a/car-settings-lib/res/values-km/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"បាន​ណែនាំ"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"ភាសាទាំងអស់"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"កន្លែងបញ្ចូលមិន​អាច​ទទេឡើយ។"</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"ឈ្មោះ​អ្នកប្រើប្រាស់​ដែល​បាន​បញ្ចូល​គឺមិនត្រឹមត្រូវទេ។"</string>
-</resources>
diff --git a/car-settings-lib/res/values-kn/strings.xml b/car-settings-lib/res/values-kn/strings.xml
deleted file mode 100644
index c5815cc..0000000
--- a/car-settings-lib/res/values-kn/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"ಸೂಚಿಸಲಾಗಿರುವುದು"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"ಎಲ್ಲಾ ಭಾಷೆಗಳು"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"ಕ್ಷೇತ್ರವು ಖಾಲಿ ಇರುವಂತಿಲ್ಲ."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"ನಮೂದಿಸಿದ ಬಳಕೆದಾರರ ಹೆಸರು ಅಮಾನ್ಯವಾಗಿದೆ."</string>
-</resources>
diff --git a/car-settings-lib/res/values-ko/strings.xml b/car-settings-lib/res/values-ko/strings.xml
deleted file mode 100644
index 1a818d9..0000000
--- a/car-settings-lib/res/values-ko/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"추천"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"모든 언어"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"입력란을 비워 둘 수 없습니다."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"입력한 사용자 이름이 올바르지 않습니다."</string>
-</resources>
diff --git a/car-settings-lib/res/values-ky/strings.xml b/car-settings-lib/res/values-ky/strings.xml
deleted file mode 100644
index 03e5756..0000000
--- a/car-settings-lib/res/values-ky/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Сунушталган тилдер"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Бардык тилдер"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Талаа бош болбошу керек."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Киргизилген колдонуучунун аты жараксыз."</string>
-</resources>
diff --git a/car-settings-lib/res/values-lo/strings.xml b/car-settings-lib/res/values-lo/strings.xml
deleted file mode 100644
index 439bafa..0000000
--- a/car-settings-lib/res/values-lo/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"ແນະນຳ"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"ທຸກພາສາ"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"ຊ່ອງຂໍ້ມູນບໍ່ສາມາດຫວ່າງເປົ່າໄດ້."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"ຊື່ຜູ້ໃຊ້ທີ່ປ້ອນເຂົ້າບໍ່ຖືກຕ້ອງ."</string>
-</resources>
diff --git a/car-settings-lib/res/values-lt/strings.xml b/car-settings-lib/res/values-lt/strings.xml
deleted file mode 100644
index 3b3f481..0000000
--- a/car-settings-lib/res/values-lt/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Siūloma"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Visos kalbos"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Laukas negali būti tuščias."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Įvestas naudotojo vardas yra netinkamas."</string>
-</resources>
diff --git a/car-settings-lib/res/values-lv/strings.xml b/car-settings-lib/res/values-lv/strings.xml
deleted file mode 100644
index 856dcf4..0000000
--- a/car-settings-lib/res/values-lv/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Ieteiktās"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Visas valodas"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Lauks nedrīkst būt tukšs."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Ievadītais lietotājvārds nav derīgs."</string>
-</resources>
diff --git a/car-settings-lib/res/values-mk/strings.xml b/car-settings-lib/res/values-mk/strings.xml
deleted file mode 100644
index f344b18..0000000
--- a/car-settings-lib/res/values-mk/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Предложени"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Сите јазици"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Полето не може да биде празно."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Внесеното корисничко име е неважечко."</string>
-</resources>
diff --git a/car-settings-lib/res/values-ml/strings.xml b/car-settings-lib/res/values-ml/strings.xml
deleted file mode 100644
index afb887d..0000000
--- a/car-settings-lib/res/values-ml/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"നിര്‍‌ദ്ദേശിക്കുന്നവ"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"എല്ലാ ഭാഷകളും"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"ഫീൽഡ് ശൂന്യമായിടരുത്."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"നൽകിയ ഉപയോക്തൃ നാമം അസാധുവാണ്."</string>
-</resources>
diff --git a/car-settings-lib/res/values-mn/strings.xml b/car-settings-lib/res/values-mn/strings.xml
deleted file mode 100644
index d747c7b..0000000
--- a/car-settings-lib/res/values-mn/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Санал болгосон"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Бүх хэл"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Талбар хоосон байж болохгүй."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Оруулсан хэрэглэгчийн нэр буруу байна."</string>
-</resources>
diff --git a/car-settings-lib/res/values-mr/strings.xml b/car-settings-lib/res/values-mr/strings.xml
deleted file mode 100644
index f915f65..0000000
--- a/car-settings-lib/res/values-mr/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"सूचित"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"सर्व भाषा"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"फील्ड रिकामे असू शकत नाही."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"एंटर केलेले वापरकर्ता नाव चुकीचे आहे."</string>
-</resources>
diff --git a/car-settings-lib/res/values-ms/strings.xml b/car-settings-lib/res/values-ms/strings.xml
deleted file mode 100644
index e67f995..0000000
--- a/car-settings-lib/res/values-ms/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Dicadangkan"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Semua bahasa"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Medan tidak boleh kosong."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Nama pengguna yang dimasukkan tidak sah."</string>
-</resources>
diff --git a/car-settings-lib/res/values-my/strings.xml b/car-settings-lib/res/values-my/strings.xml
deleted file mode 100644
index dd448fa..0000000
--- a/car-settings-lib/res/values-my/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"အကြံပြုထားသော"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"ဘာသာစကားအားလုံး"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"အကွက်ကို ကွက်လပ်ထား၍ မရပါ။"</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"ထည့်ထားသော အသုံးပြုသူအမည် မမှန်ကန်ပါ။"</string>
-</resources>
diff --git a/car-settings-lib/res/values-nb/strings.xml b/car-settings-lib/res/values-nb/strings.xml
deleted file mode 100644
index 77dc43a..0000000
--- a/car-settings-lib/res/values-nb/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Foreslått"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Alle språk"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Feltet må fylles ut."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Brukernavnet du skrev inn, er ugyldig."</string>
-</resources>
diff --git a/car-settings-lib/res/values-ne/strings.xml b/car-settings-lib/res/values-ne/strings.xml
deleted file mode 100644
index 6d32ddc..0000000
--- a/car-settings-lib/res/values-ne/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"सुझाव दिइयो"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"सम्पूर्ण भाषाहरू"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"फिल्ड खाली हुन सक्दैन।"</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"प्रविष्ट गरिएको प्रयोगकर्ता नाम अमान्य छ।"</string>
-</resources>
diff --git a/car-settings-lib/res/values-nl/strings.xml b/car-settings-lib/res/values-nl/strings.xml
deleted file mode 100644
index 25f84ef..0000000
--- a/car-settings-lib/res/values-nl/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Voorgesteld"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Alle talen"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Veld mag niet leeg zijn."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"De ingevoerde gebruikersnaam is ongeldig."</string>
-</resources>
diff --git a/car-settings-lib/res/values-or/strings.xml b/car-settings-lib/res/values-or/strings.xml
deleted file mode 100644
index 3690ef6..0000000
--- a/car-settings-lib/res/values-or/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"ପରାମର୍ଶିତ"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"ସମସ୍ତ ଭାଷା"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"ସ୍ଥାନକୁ ଖାଲି ଛାଡ଼ି ହେବନାହିଁ।"</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"ଲେଖାଯାଇଥିବା ଉପଯୋଗକର୍ତ୍ତାନାମଟି ଠିକ୍‍ ନାହିଁ।"</string>
-</resources>
diff --git a/car-settings-lib/res/values-pa/strings.xml b/car-settings-lib/res/values-pa/strings.xml
deleted file mode 100644
index c501aaf..0000000
--- a/car-settings-lib/res/values-pa/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"ਸੁਝਾਏ ਗਏ"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"ਸਾਰੀਆਂ ਭਾਸ਼ਾਵਾਂ"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"ਖੇਤਰ ਖਾਲੀ ਨਹੀਂ ਛੱਡਿਆ ਜਾ ਸਕਦਾ।"</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"ਦਾਖਲ ਕੀਤਾ ਗਿਆ ਵਰਤੋਂਕਾਰ ਨਾਮ ਅਵੈਧ ਹੈ।"</string>
-</resources>
diff --git a/car-settings-lib/res/values-pl/strings.xml b/car-settings-lib/res/values-pl/strings.xml
deleted file mode 100644
index 00bbad3..0000000
--- a/car-settings-lib/res/values-pl/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Sugerowane"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Wszystkie języki"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Pole nie może być puste."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Podana nazwa użytkownika jest nieprawidłowa."</string>
-</resources>
diff --git a/car-settings-lib/res/values-pt-rPT/strings.xml b/car-settings-lib/res/values-pt-rPT/strings.xml
deleted file mode 100644
index 7ad6367..0000000
--- a/car-settings-lib/res/values-pt-rPT/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Sugeridos"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Todos os idiomas"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"O campo não pode estar em branco."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"O nome de utilizador introduzido é inválido."</string>
-</resources>
diff --git a/car-settings-lib/res/values-pt/strings.xml b/car-settings-lib/res/values-pt/strings.xml
deleted file mode 100644
index ac5fb11..0000000
--- a/car-settings-lib/res/values-pt/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Sugeridos"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Todos os idiomas"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"O campo não pode ficar em branco."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"O nome de usuário informado é inválido."</string>
-</resources>
diff --git a/car-settings-lib/res/values-ro/strings.xml b/car-settings-lib/res/values-ro/strings.xml
deleted file mode 100644
index b79ede1..0000000
--- a/car-settings-lib/res/values-ro/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Sugerate"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Toate limbile"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Câmpul trebuie completat."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Numele de utilizator introdus este nevalid."</string>
-</resources>
diff --git a/car-settings-lib/res/values-ru/strings.xml b/car-settings-lib/res/values-ru/strings.xml
deleted file mode 100644
index d5f064c..0000000
--- a/car-settings-lib/res/values-ru/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Рекомендуемые"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Все языки"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Поле должно быть заполнено."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Указано недопустимое имя пользователя."</string>
-</resources>
diff --git a/car-settings-lib/res/values-si/strings.xml b/car-settings-lib/res/values-si/strings.xml
deleted file mode 100644
index 79e83f7..0000000
--- a/car-settings-lib/res/values-si/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"යෝජිත"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"සියලු භාෂා"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"ක්ෂේත්‍රය හිස් විය නොහැක."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"ඇතුළු කළ පරිශීලක නාමය අවලංගුය."</string>
-</resources>
diff --git a/car-settings-lib/res/values-sk/strings.xml b/car-settings-lib/res/values-sk/strings.xml
deleted file mode 100644
index 7bf3819..0000000
--- a/car-settings-lib/res/values-sk/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Navrhované"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Všetky jazyky"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Pole nesmie byť prázdne."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Zadané používateľské meno je neplatné."</string>
-</resources>
diff --git a/car-settings-lib/res/values-sl/strings.xml b/car-settings-lib/res/values-sl/strings.xml
deleted file mode 100644
index 5f46458..0000000
--- a/car-settings-lib/res/values-sl/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Predlagano"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Vsi jeziki"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Polje ne sme biti prazno."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Vneseno uporabniško ime ni veljavno."</string>
-</resources>
diff --git a/car-settings-lib/res/values-sq/strings.xml b/car-settings-lib/res/values-sq/strings.xml
deleted file mode 100644
index 18cbe0f..0000000
--- a/car-settings-lib/res/values-sq/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Sugjeruar"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Të gjitha gjuhët"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Fusha nuk mund të lihet bosh."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Emri i përdoruesit që fute është i pavlefshëm."</string>
-</resources>
diff --git a/car-settings-lib/res/values-sr/strings.xml b/car-settings-lib/res/values-sr/strings.xml
deleted file mode 100644
index 46b5008..0000000
--- a/car-settings-lib/res/values-sr/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Предложени"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Сви језици"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Поље не сме да буде празно."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Корисничко име које сте унели је неважеће."</string>
-</resources>
diff --git a/car-settings-lib/res/values-sv/strings.xml b/car-settings-lib/res/values-sv/strings.xml
deleted file mode 100644
index d9e2309..0000000
--- a/car-settings-lib/res/values-sv/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Förslag"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Alla språk"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Fältet får inte vara tomt."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Du har angett ett ogiltigt användarnamn."</string>
-</resources>
diff --git a/car-settings-lib/res/values-sw/strings.xml b/car-settings-lib/res/values-sw/strings.xml
deleted file mode 100644
index dbe4958..0000000
--- a/car-settings-lib/res/values-sw/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Zinazopendekezwa"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Lugha zote"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Ni lazima ujaze sehemu hii"</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Jina uliloweka la mtumiaji si sahihi."</string>
-</resources>
diff --git a/car-settings-lib/res/values-ta/strings.xml b/car-settings-lib/res/values-ta/strings.xml
deleted file mode 100644
index e21d564..0000000
--- a/car-settings-lib/res/values-ta/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"பரிந்துரைகள்"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"எல்லா மொழிகளும்"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"புலம், வெறுமையாக இருக்கக்கூடாது."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"பயனர்பெயரைத் தவறாக உள்ளிட்டுள்ளீர்கள்."</string>
-</resources>
diff --git a/car-settings-lib/res/values-te/strings.xml b/car-settings-lib/res/values-te/strings.xml
deleted file mode 100644
index 38b470d..0000000
--- a/car-settings-lib/res/values-te/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"సూచించినవి"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"అన్ని భాషలు"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"ఫీల్డ్ ఖాళీగా ఉండరాదు."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"నమోదు చేసిన వినియోగదారు పేరు చెల్లదు."</string>
-</resources>
diff --git a/car-settings-lib/res/values-th/strings.xml b/car-settings-lib/res/values-th/strings.xml
deleted file mode 100644
index 10ac43a..0000000
--- a/car-settings-lib/res/values-th/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"แนะนำ"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"ทุกภาษา"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"ต้องกรอกข้อมูลในช่อง"</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"ชื่อผู้ใช้ที่ป้อนไม่ถูกต้อง"</string>
-</resources>
diff --git a/car-settings-lib/res/values-tl/strings.xml b/car-settings-lib/res/values-tl/strings.xml
deleted file mode 100644
index 852721f..0000000
--- a/car-settings-lib/res/values-tl/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Iminumungkahi"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Lahat ng wika"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Hindi maaaring blangko ang field."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Invalid ang inilagay na username."</string>
-</resources>
diff --git a/car-settings-lib/res/values-tr/strings.xml b/car-settings-lib/res/values-tr/strings.xml
deleted file mode 100644
index bb7499e..0000000
--- a/car-settings-lib/res/values-tr/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Önerilen"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Tüm diller"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Alan boş olamaz."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Girilen kullanıcı adı geçersiz."</string>
-</resources>
diff --git a/car-settings-lib/res/values-uk/strings.xml b/car-settings-lib/res/values-uk/strings.xml
deleted file mode 100644
index 4429605..0000000
--- a/car-settings-lib/res/values-uk/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Пропонується"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Усі мови"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Поле не може бути порожнім."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Введене ім’я користувача недійсне."</string>
-</resources>
diff --git a/car-settings-lib/res/values-ur/strings.xml b/car-settings-lib/res/values-ur/strings.xml
deleted file mode 100644
index 64f8d4a..0000000
--- a/car-settings-lib/res/values-ur/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"تجویز کردہ"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"سبھی زبانیں"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"فیلڈ خالی نہیں رہ سکتی۔"</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"درج کردہ صارف نام غلط ہے۔"</string>
-</resources>
diff --git a/car-settings-lib/res/values-uz/strings.xml b/car-settings-lib/res/values-uz/strings.xml
deleted file mode 100644
index 1947548..0000000
--- a/car-settings-lib/res/values-uz/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Taklif qilingan"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Barcha tillar"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Maydon bo‘sh qoldirilishi mumkin emas."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Kiritilgan foydalanuvchi nomi xato."</string>
-</resources>
diff --git a/car-settings-lib/res/values-vi/strings.xml b/car-settings-lib/res/values-vi/strings.xml
deleted file mode 100644
index 6dbc7d7..0000000
--- a/car-settings-lib/res/values-vi/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Ðược đề xuất"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Tất cả ngôn ngữ"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Không được để trống trường."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Tên người dùng đã nhập là không hợp lệ."</string>
-</resources>
diff --git a/car-settings-lib/res/values-zh-rCN/strings.xml b/car-settings-lib/res/values-zh-rCN/strings.xml
deleted file mode 100644
index f9462c5..0000000
--- a/car-settings-lib/res/values-zh-rCN/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"建议"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"所有语言"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"此字段不能留空。"</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"输入的用户名无效。"</string>
-</resources>
diff --git a/car-settings-lib/res/values-zh-rHK/strings.xml b/car-settings-lib/res/values-zh-rHK/strings.xml
deleted file mode 100644
index 8c5d191..0000000
--- a/car-settings-lib/res/values-zh-rHK/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"建議"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"所有語言"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"欄位不得留空。"</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"輸入的使用者名稱無效。"</string>
-</resources>
diff --git a/car-settings-lib/res/values-zh-rTW/strings.xml b/car-settings-lib/res/values-zh-rTW/strings.xml
deleted file mode 100644
index 8e9c84a..0000000
--- a/car-settings-lib/res/values-zh-rTW/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"建議"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"所有語言"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"欄位不能空白。"</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"輸入的使用者名稱無效。"</string>
-</resources>
diff --git a/car-settings-lib/res/values-zu/strings.xml b/car-settings-lib/res/values-zu/strings.xml
deleted file mode 100644
index 2e55b3f..0000000
--- a/car-settings-lib/res/values-zu/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Okuphakanyisiwe"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Zonke izilimi"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Inkundla ayikwazi ukungabi nalutho."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Igama lomsebenzisi elifakiwe alivumelekile."</string>
-</resources>
diff --git a/car-settings-lib/res/values/strings.xml b/car-settings-lib/res/values/strings.xml
deleted file mode 100644
index c9f76e7..0000000
--- a/car-settings-lib/res/values/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
--->
-<resources>
-
-    <!-- Language picker list suggested locale header [CHAR LIMIT=40] -->
-    <string name="language_picker_list_suggested_header">Suggested</string>
-
-    <!-- Language picker list all other locales header [CHAR LIMIT=40] -->
-    <string name="language_picker_list_all_header">All languages</string>
-
-    <!-- An error message indicating that the name input field has been left blank and cannot be. [CHAR_LIMIT=50] -->
-    <string name="name_input_blank_error">Field can\u2019t be blank.</string>
-
-    <!-- An error message indicating that the name the user has entered is invalid. [CHAR_LIMIT=50] -->
-    <string name="name_input_invalid_error">Username entered is invalid.</string>
-
-</resources>
\ No newline at end of file
diff --git a/car-settings-lib/src/com/android/car/settingslib/language/LanguagePickerUtils.java b/car-settings-lib/src/com/android/car/settingslib/language/LanguagePickerUtils.java
deleted file mode 100644
index ef5dc46..0000000
--- a/car-settings-lib/src/com/android/car/settingslib/language/LanguagePickerUtils.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2018 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.car.settingslib.language;
-
-import android.app.ActivityManager;
-import android.content.Context;
-import android.os.RemoteException;
-
-import androidx.annotation.Nullable;
-
-import com.android.internal.app.LocaleHelper;
-import com.android.internal.app.LocaleStore;
-import com.android.internal.app.SuggestedLocaleAdapter;
-
-import java.util.Locale;
-import java.util.Set;
-
-/**
- * Utility class that supports the language/locale picker flows.
- */
-public final class LanguagePickerUtils {
-    /**
-     * Creates an instance of {@link SuggestedLocaleAdapter} with a locale
-     * {@link LocaleStore.LocaleInfo} that is scoped to a parent locale if a parent locale is
-     * provided.
-     */
-    public static SuggestedLocaleAdapter createSuggestedLocaleAdapter(
-            Context context,
-            Set<LocaleStore.LocaleInfo> localeInfoSet,
-            @Nullable LocaleStore.LocaleInfo parent) {
-        boolean countryMode = (parent != null);
-        Locale displayLocale = countryMode ? parent.getLocale() : Locale.getDefault();
-        SuggestedLocaleAdapter adapter = new SuggestedLocaleAdapter(localeInfoSet, countryMode);
-        LocaleHelper.LocaleInfoComparator comp =
-                new LocaleHelper.LocaleInfoComparator(displayLocale, countryMode);
-        adapter.sort(comp);
-        adapter.setDisplayLocale(context, displayLocale);
-        return adapter;
-    }
-
-    /**
-     * Returns the locale from current system configuration, or the default locale if no system
-     * locale is available.
-     */
-    public static Locale getConfiguredLocale() {
-        try {
-            Locale configLocale =
-                    ActivityManager.getService().getConfiguration().getLocales().get(0);
-            return configLocale != null ? configLocale : Locale.getDefault();
-        } catch (RemoteException e) {
-            return Locale.getDefault();
-        }
-    }
-
-    private LanguagePickerUtils() {}
-}
diff --git a/car-settings-lib/src/com/android/car/settingslib/language/LocaleSelectionListener.java b/car-settings-lib/src/com/android/car/settingslib/language/LocaleSelectionListener.java
deleted file mode 100644
index 2541bf8..0000000
--- a/car-settings-lib/src/com/android/car/settingslib/language/LocaleSelectionListener.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2018 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.car.settingslib.language;
-
-import com.android.internal.app.LocaleStore;
-
-/**
- * Listener interface that facilitates notification of changes is locale selection.
- */
-public interface LocaleSelectionListener {
-    /**
-     * Called when a language choice has been selected.
-     */
-    void onLocaleSelected(LocaleStore.LocaleInfo localeInfo);
-
-    /**
-     * Called when a parent locale that has at least 2 child locales is selected. The
-     * expectation here is what the PagedList in the LanguagePickerFragment will be updated to
-     * display the child locales.
-     */
-    void onParentWithChildrenLocaleSelected(LocaleStore.LocaleInfo localeInfo);
-}
diff --git a/car-settings-lib/src/com/android/car/settingslib/loader/AsyncLoader.java b/car-settings-lib/src/com/android/car/settingslib/loader/AsyncLoader.java
deleted file mode 100644
index d706c3a..0000000
--- a/car-settings-lib/src/com/android/car/settingslib/loader/AsyncLoader.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.car.settingslib.loader;
-
-import android.annotation.Nullable;
-import android.content.Context;
-
-import androidx.loader.content.AsyncTaskLoader;
-
-/**
- * This class fills in some boilerplate for AsyncTaskLoader to actually load things.
- * Classes the extend {@link AsyncLoader} need to properly implement required methods expressed in
- * {@link AsyncTaskLoader}
- *
- * <p>Taken from {@link com.android.settingslib.utils.AsyncLoader}. Only change to extend from
- * support library {@link AsyncTaskLoader}
- *
- * @param <T> the data type to be loaded.
- */
-public abstract class AsyncLoader<T> extends AsyncTaskLoader<T> {
-    @Nullable
-    private T mResult;
-
-    public AsyncLoader(Context context) {
-        super(context);
-    }
-
-    @Override
-    protected void onStartLoading() {
-        if (mResult != null) {
-            deliverResult(mResult);
-        }
-
-        if (takeContentChanged() || mResult == null) {
-            forceLoad();
-        }
-    }
-
-    @Override
-    protected void onStopLoading() {
-        cancelLoad();
-    }
-
-    @Override
-    public void deliverResult(T data) {
-        if (isReset()) {
-            return;
-        }
-        mResult = data;
-        if (isStarted()) {
-            super.deliverResult(data);
-        }
-    }
-
-    @Override
-    protected void onReset() {
-        super.onReset();
-        onStopLoading();
-        mResult = null;
-    }
-}
diff --git a/car-settings-lib/src/com/android/car/settingslib/log/LoggerBase.java b/car-settings-lib/src/com/android/car/settingslib/log/LoggerBase.java
deleted file mode 100644
index 2d59899..0000000
--- a/car-settings-lib/src/com/android/car/settingslib/log/LoggerBase.java
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- * Copyright (C) 2018 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.car.settingslib.log;
-
-import android.text.TextUtils;
-import android.util.Log;
-
-import androidx.annotation.NonNull;
-
-/**
- * Helper class that wraps {@link Log} to log messages to logcat. The intended use for a Logger is
- * to include one per file, using the class.getSimpleName as the prefix, like this:
- *     <pre> private static final Logger LOG = new Logger(MyClass.class); </pre>
- *
- * <p>
- * The logger will log statements in this format:
- *     mTag: [PREFIX] MESSAGE
- *
- * <p>
- * Where mTag is defined by the subclass. This helps differentiate logs while staying within the
- * 23 character limit of the log mTag.
- *
- * <p>
- * When logging verbose and debug logs, the logs should either be guarded by {@code if (LOG.isV())},
- * or a constant if (DEBUG). That DEBUG constant should be false on any submitted code.
- */
-public abstract class LoggerBase {
-    private final String mTag;
-    private final String mPrefix;
-
-    public LoggerBase(Class<?> cls) {
-        this(cls.getSimpleName());
-    }
-
-    public LoggerBase(String prefix) {
-        mTag = getTag();
-        if (TextUtils.isEmpty(mTag)) {
-            throw new IllegalStateException("Tag must be not null or empty");
-        }
-        if (mTag.length() > 23) {
-            throw new IllegalStateException("Tag must be 23 characters or less");
-        }
-        mPrefix = "[" + prefix + "] ";
-    }
-
-    /**
-     * Gets the tag that will be used in all logging calls.
-     */
-    @NonNull
-    protected abstract String getTag();
-
-    /**
-     * Returns true when it is desired to force log all messages.
-     */
-    protected boolean forceAllLogging() {
-        return false;
-    }
-
-    /**
-     * Logs a {@link Log#VERBOSE} log message. Will only be logged if {@link Log#VERBOSE} is
-     * loggable. This is a wrapper around {@link Log#v(String, String)}.
-     *
-     * @param message The message you would like logged.
-     */
-    public void v(String message) {
-        if (isV()) {
-            Log.v(mTag, mPrefix.concat(message));
-        }
-    }
-
-    /**
-     * Logs a {@link Log#VERBOSE} log message. Will only be logged if {@link Log#VERBOSE} is
-     * loggable. This is a wrapper around {@link Log#v(String, String, Throwable)}.
-     *
-     * @param message The message you would like logged.
-     * @param throwable An exception to log
-     */
-    public void v(String message, Throwable throwable) {
-        if (isV()) {
-            Log.v(mTag, mPrefix.concat(message), throwable);
-        }
-    }
-
-    /**
-     * Logs a {@link Log#DEBUG} log message. Will only be logged if {@link Log#DEBUG} is
-     * loggable. This is a wrapper around {@link Log#d(String, String)}.
-     *
-     * @param message The message you would like logged.
-     */
-    public void d(String message) {
-        if (isD()) {
-            Log.d(mTag, mPrefix.concat(message));
-        }
-    }
-
-    /**
-     * Logs a {@link Log#DEBUG} log message. Will only be logged if {@link Log#DEBUG} is
-     * loggable. This is a wrapper around {@link Log#d(String, String, Throwable)}.
-     *
-     * @param message The message you would like logged.
-     * @param throwable An exception to log
-     */
-    public void d(String message, Throwable throwable) {
-        if (isD()) {
-            Log.d(mTag, mPrefix.concat(message), throwable);
-        }
-    }
-
-    /**
-     * Logs a {@link Log#INFO} log message. Will only be logged if {@link Log#INFO} is loggable.
-     * This is a wrapper around {@link Log#i(String, String)}.
-     *
-     * @param message The message you would like logged.
-     */
-    public void i(String message) {
-        if (isI()) {
-            Log.i(mTag, mPrefix.concat(message));
-        }
-    }
-
-    /**
-     * Logs a {@link Log#INFO} log message. Will only be logged if {@link Log#INFO} is loggable.
-     * This is a wrapper around {@link Log#i(String, String, Throwable)}.
-     *
-     * @param message The message you would like logged.
-     * @param throwable An exception to log
-     */
-    public void i(String message, Throwable throwable) {
-        if (isI()) {
-            Log.i(mTag, mPrefix.concat(message), throwable);
-        }
-    }
-
-    /**
-     * Logs a {@link Log#WARN} log message. This is a wrapper around {@link Log#w(String, String)}.
-     *
-     * @param message The message you would like logged.
-     */
-    public void w(String message) {
-        Log.w(mTag, mPrefix.concat(message));
-    }
-
-    /**
-     * Logs a {@link Log#WARN} log message. This is a wrapper around
-     * {@link Log#w(String, String, Throwable)}.
-     *
-     * @param message The message you would like logged.
-     * @param throwable An exception to log
-     */
-    public void w(String message, Throwable throwable) {
-        Log.w(mTag, mPrefix.concat(message), throwable);
-    }
-
-    /**
-     * Logs a {@link Log#ERROR} log message. This is a wrapper around {@link Log#e(String, String)}.
-     *
-     * @param message The message you would like logged.
-     */
-    public void e(String message) {
-        Log.e(mTag, mPrefix.concat(message));
-    }
-
-    /**
-     * Logs a {@link Log#ERROR} log message. This is a wrapper around
-     * {@link Log#e(String, String, Throwable)}.
-     *
-     * @param message The message you would like logged.
-     * @param throwable An exception to log
-     */
-    public void e(String message, Throwable throwable) {
-        Log.e(mTag, mPrefix.concat(message), throwable);
-    }
-
-    /**
-     * Logs a "What a Terrible Failure" as an {@link Log#ASSERT} log message. This is a wrapper
-     * around {@link Log#w(String, String)}.
-     *
-     * @param message The message you would like logged.
-     */
-    public void wtf(String message) {
-        Log.wtf(mTag, mPrefix.concat(message));
-    }
-
-    /**
-     * Logs a "What a Terrible Failure" as an {@link Log#ASSERT} log message. This is a wrapper
-     * around {@link Log#wtf(String, String, Throwable)}.
-     *
-     * @param message The message you would like logged.
-     * @param throwable An exception to log
-     */
-    public void wtf(String message, Throwable throwable) {
-        Log.wtf(mTag, mPrefix.concat(message), throwable);
-    }
-
-    private boolean isV() {
-        return Log.isLoggable(mTag, Log.VERBOSE) || forceAllLogging();
-    }
-
-    private boolean isD() {
-        return Log.isLoggable(mTag, Log.DEBUG) || forceAllLogging();
-    }
-
-    private boolean isI() {
-        return Log.isLoggable(mTag, Log.INFO) || forceAllLogging();
-    }
-}
diff --git a/car-settings-lib/src/com/android/car/settingslib/util/ProfileNameSaver.java b/car-settings-lib/src/com/android/car/settingslib/util/ProfileNameSaver.java
deleted file mode 100644
index 8f7067c..0000000
--- a/car-settings-lib/src/com/android/car/settingslib/util/ProfileNameSaver.java
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.car.settingslib.util;
-
-import android.content.ContentResolver;
-import android.content.ContentUris;
-import android.content.ContentValues;
-import android.database.Cursor;
-import android.net.Uri;
-import android.provider.ContactsContract;
-import android.text.TextUtils;
-import android.util.Log;
-
-/**
- * Saves name as GIVEN_NAME on "Me" Profile. If "Me" contact does not exist, it's created.
- */
-public class ProfileNameSaver {
-    private static final String TAG = "ProfileNameSaver";
-    private static final Uri PROFILE_URI = ContactsContract.Profile.CONTENT_RAW_CONTACTS_URI;
-    private static final int INVALID_ID = -1;
-
-    /**
-     * The projection into the profiles database that retrieves just the id of a profile.
-     */
-    private static final String[] CONTACTS_PROJECTION =
-            new String[]{ContactsContract.RawContacts._ID};
-
-    /**
-     * A projection into the profile data for one particular contact that includes the
-     * contact's MIME type.
-     */
-    private static final String[] CONTACTS_PROFILE_PROJECTION = new String[]{
-            ContactsContract.Data._ID,
-            ContactsContract.Data.MIMETYPE};
-
-    /**
-     * A selection into the profiles database that queries for a MIME type.
-     */
-    private static final String CONTACT_MIME_QUERY = ContactsContract.Data.MIMETYPE + " = ?";
-
-    /**
-     * Updates the "Me" contact profile card with the given name as the first name of the
-     * contact. If the "Me" contact does not exist, then one will be created.
-     *
-     * @param name The first name for the "Me" contact. If this value is {@code null} or
-     *             empty, then the contact will not be updated.
-     */
-    public static void updateMeContactWith(String name, ContentResolver contentResolver) {
-        if (Log.isLoggable(TAG, Log.VERBOSE)) {
-            Log.v(TAG, "updateMeContactWith name=" + name);
-        }
-
-        if (TextUtils.isEmpty(name)) {
-            return;
-        }
-
-        // Check if there is already an existing "me" contact.
-        Cursor cursor = contentResolver.query(
-                PROFILE_URI,
-                CONTACTS_PROJECTION,
-                /* selection= */ null,
-                /* selectionArgs= */ null,
-                /* sortOrder= */ null);
-
-        if (cursor == null) {
-            // Error in querying the content resolver, skip the update flow
-            Log.e(TAG, "Received null from query to the \"me\" contact at " + PROFILE_URI);
-            return;
-        }
-
-        long meRawContactId = -1;  // no ID can be < 0
-        boolean newContact = true;
-        try {
-            if (cursor.moveToFirst()) {
-                meRawContactId = cursor.getLong(0);
-                newContact = false;  // An entry indicates that the "me" contact exists.
-            }
-        } finally {
-            cursor.close();
-        }
-
-        ContentValues values = new ContentValues();
-
-        if (newContact) {
-            meRawContactId = ContentUris.parseId(contentResolver.insert(PROFILE_URI, values));
-        }
-
-        values.put(ContactsContract.Data.RAW_CONTACT_ID, meRawContactId);
-        values.put(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME, name);
-        values.put(ContactsContract.Data.MIMETYPE,
-                ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE);
-
-        long structuredNameId = getProfileItem(meRawContactId, contentResolver);
-        if (newContact || structuredNameId == INVALID_ID) {
-            contentResolver.insert(ContactsContract.Data.CONTENT_URI, values);
-        } else {
-            contentResolver.update(ContentUris.withAppendedId(
-                    ContactsContract.Data.CONTENT_URI, structuredNameId), values,
-                    /* where= */ null, /* selectionArgs= */ null);
-        }
-    }
-
-    /**
-     * Helper method to search for the first profile item of the type {@link
-     * ContactsContract.CommonDataKinds.StructuredName#CONTENT_ITEM_TYPE}.
-     *
-     * @return The item's ID or {@link #INVALID_ID} if not found.
-     */
-    private static long getProfileItem(long profileContactId, ContentResolver contentResolver) {
-        if (Log.isLoggable(TAG, Log.VERBOSE)) {
-            Log.v(TAG, "getProfileItem profileContactId=" + profileContactId);
-        }
-        Uri dataUri = ContactsContract.Profile.CONTENT_RAW_CONTACTS_URI.buildUpon()
-                .appendPath(String.valueOf(profileContactId))
-                .appendPath(ContactsContract.RawContacts.Data.CONTENT_DIRECTORY)
-                .build();
-
-        Cursor cursor = contentResolver.query(
-                dataUri,
-                CONTACTS_PROFILE_PROJECTION,
-                CONTACT_MIME_QUERY,
-                new String[]{
-                        ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE},
-                /* sortOrder= */ null);
-
-        // Error in querying the content resolver.
-        if (cursor == null) {
-            Log.e(TAG, "Received null from query to the first profile item at " + dataUri);
-            return INVALID_ID;
-        }
-
-        try {
-            return cursor.moveToFirst() ? cursor.getLong(0) : INVALID_ID;
-        } finally {
-            cursor.close();
-        }
-    }
-}
diff --git a/car-settings-lib/src/com/android/car/settingslib/util/ResultCodes.java b/car-settings-lib/src/com/android/car/settingslib/util/ResultCodes.java
deleted file mode 100644
index 2ac5ef2..0000000
--- a/car-settings-lib/src/com/android/car/settingslib/util/ResultCodes.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.car.settingslib.util;
-
-import static android.app.Activity.RESULT_FIRST_USER;
-
-/**
- * Result code set shared between Settings and other Car components
- */
-public final class ResultCodes {
-    public static final int RESULT_SKIP = RESULT_FIRST_USER;
-    public static final int RESULT_NONE = RESULT_FIRST_USER + 1;
-}
diff --git a/car-settings-lib/src/com/android/car/settingslib/util/SettingsConstants.java b/car-settings-lib/src/com/android/car/settingslib/util/SettingsConstants.java
deleted file mode 100644
index cec6146..0000000
--- a/car-settings-lib/src/com/android/car/settingslib/util/SettingsConstants.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.car.settingslib.util;
-
-/**
- * Contains car specific settings constants.
- */
-public class SettingsConstants {
-
-    public static final String USER_NAME_SET = "user_name_set";
-
-}
diff --git a/car-settings-lib/tests/Android.mk b/car-settings-lib/tests/Android.mk
deleted file mode 100644
index 0903c90..0000000
--- a/car-settings-lib/tests/Android.mk
+++ /dev/null
@@ -1,19 +0,0 @@
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-# Include all makefiles in subdirectories
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/car-settings-lib/tests/robotests/Android.mk b/car-settings-lib/tests/robotests/Android.mk
deleted file mode 100644
index 59e61b2..0000000
--- a/car-settings-lib/tests/robotests/Android.mk
+++ /dev/null
@@ -1,73 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-##################################################################
-# Car Settings Library app just for Robolectric test target.     #
-##################################################################
-include $(CLEAR_VARS)
-
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-
-LOCAL_PACKAGE_NAME := CarSettingsLib
-LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_USE_AAPT2 := true
-
-LOCAL_PRIVILEGED_MODULE := true
-
-LOCAL_STATIC_ANDROID_LIBRARIES := \
-    car-settings-lib
-
-include $(BUILD_PACKAGE)
-
-##################################################################
-# Car Settings Library Robolectric test target.                  #
-##################################################################
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := CarSettingsLibRoboTests
-LOCAL_MODULE_CLASS := JAVA_LIBRARIES
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_JAVA_RESOURCE_DIRS := config
-
-LOCAL_JAVA_LIBRARIES := \
-    robolectric_android-all-stub \
-    Robolectric_all-target \
-    mockito-robolectric-prebuilt \
-    truth-prebuilt \
-    android.car
-
-LOCAL_INSTRUMENTATION_FOR := CarSettingsLib
-
-LOCAL_MODULE_TAGS := optional
-
-# Generate test_config.properties
-include external/robolectric-shadows/gen_test_config.mk
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
-##################################################################
-# Car Settings Library runner target to run the previous target. #
-##################################################################
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := RunCarSettingsLibRoboTests
-
-LOCAL_JAVA_LIBRARIES := \
-    CarSettingsLibRoboTests \
-    robolectric_android-all-stub \
-    Robolectric_all-target \
-    mockito-robolectric-prebuilt \
-    truth-prebuilt \
-    android.car
-
-LOCAL_TEST_PACKAGE := CarSettingsLib
-
-LOCAL_ROBOTEST_FILES := $(filter-out %/BaseRobolectricTest.java,\
-    $(call find-files-in-subdirs,$(LOCAL_PATH)/src,*Test.java,.))
-
-LOCAL_INSTRUMENT_SOURCE_DIRS := $(dir $(LOCAL_PATH))../src
-
-include external/robolectric-shadows/run_robotests.mk
\ No newline at end of file
diff --git a/car-settings-lib/tests/robotests/AndroidManifest.xml b/car-settings-lib/tests/robotests/AndroidManifest.xml
deleted file mode 100644
index dd1a985..0000000
--- a/car-settings-lib/tests/robotests/AndroidManifest.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-    Copyright (C) 2018 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
--->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-          package="com.android.car.settingslib.robotests">
-
-</manifest>
diff --git a/car-settings-lib/tests/robotests/config/robolectric.properties b/car-settings-lib/tests/robotests/config/robolectric.properties
deleted file mode 100644
index 3626c87..0000000
--- a/car-settings-lib/tests/robotests/config/robolectric.properties
+++ /dev/null
@@ -1,16 +0,0 @@
-#
-# Copyright (C) 2018 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-sdk=NEWEST_SDK
\ No newline at end of file
diff --git a/car-settings-lib/tests/robotests/src/com/android/car/settingslib/log/LoggerBaseTest.java b/car-settings-lib/tests/robotests/src/com/android/car/settingslib/log/LoggerBaseTest.java
deleted file mode 100644
index 468c010..0000000
--- a/car-settings-lib/tests/robotests/src/com/android/car/settingslib/log/LoggerBaseTest.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (C) 2018 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.car.settingslib.log;
-
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-
-/**
- * Tests {@link LoggerBase}
- */
-@RunWith(RobolectricTestRunner.class)
-public class LoggerBaseTest {
-
-    @Rule
-    public ExpectedException mExpectedException = ExpectedException.none();
-
-    @Test
-    public void testNullTag() {
-        mExpectedException.expect(IllegalStateException.class);
-        mExpectedException.expectMessage("Tag must be not null or empty");
-        new NullTagLogger("NullLogger");
-    }
-
-    @Test
-    public void testEmptyTag() {
-        mExpectedException.expect(IllegalStateException.class);
-        mExpectedException.expectMessage("Tag must be not null or empty");
-        new EmptyTagLogger("EmptyTagLogger");
-    }
-
-    @Test
-    public void testTooLongTag() {
-        mExpectedException.expect(IllegalStateException.class);
-        mExpectedException.expectMessage("Tag must be 23 characters or less");
-        new TooLongTagLogger("TooLongTagLogger");
-    }
-
-    private class NullTagLogger extends LoggerBase {
-
-        NullTagLogger(String prefix) {
-            super(prefix);
-        }
-
-        @Override
-        protected String getTag() {
-            return null;
-        }
-    }
-
-    private class EmptyTagLogger extends LoggerBase {
-
-        EmptyTagLogger(String prefix) {
-            super(prefix);
-        }
-
-        @Override
-        protected String getTag() {
-            return "";
-        }
-    }
-
-    /**
-     * A Logger with a tag that is 24 characters long.
-     */
-    private class TooLongTagLogger extends LoggerBase {
-
-        TooLongTagLogger(String prefix) {
-            super(prefix);
-        }
-
-        @Override
-        protected String getTag() {
-            return "LoremIpsumLoremIpsumLore";
-        }
-    }
-}
diff --git a/car-settings-lib/tests/robotests/src/com/android/car/settingslib/robolectric/BaseRobolectricTest.java b/car-settings-lib/tests/robotests/src/com/android/car/settingslib/robolectric/BaseRobolectricTest.java
deleted file mode 100644
index 280faea..0000000
--- a/car-settings-lib/tests/robotests/src/com/android/car/settingslib/robolectric/BaseRobolectricTest.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2018 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.car.settingslib.robolectric;
-
-import org.junit.Rule;
-import org.mockito.junit.MockitoJUnit;
-import org.mockito.junit.MockitoRule;
-
-/**
- * Base test for CarSettingsLib Robolectric tests.
- */
-public abstract class BaseRobolectricTest {
-    // This rule automatically initializes any mocks created using the @Mock annotation
-    @Rule
-    public MockitoRule mMockitoRule = MockitoJUnit.rule();
-}
diff --git a/car-telephony-common/Android.bp b/car-telephony-common/Android.bp
new file mode 100644
index 0000000..8f9318e
--- /dev/null
+++ b/car-telephony-common/Android.bp
@@ -0,0 +1,37 @@
+//
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+android_library {
+    name: "car-telephony-common",
+
+    srcs: ["src/**/*.java"],
+
+    resource_dirs: ["res"],
+
+    optimize: {
+        enabled: false,
+    },
+
+    static_libs: [
+        "androidx.legacy_legacy-support-v4",
+        "car-apps-common",
+        "glide-prebuilt",
+        "libphonenumber",
+    ],
+
+    libs: ["android.car"],
+
+}
diff --git a/car-telephony-common/Android.mk b/car-telephony-common/Android.mk
deleted file mode 100644
index 3a592d6..0000000
--- a/car-telephony-common/Android.mk
+++ /dev/null
@@ -1,51 +0,0 @@
-#
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-
-LOCAL_MODULE := car-telephony-common
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_PRIVILEGED_MODULE := true
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-LOCAL_STATIC_ANDROID_LIBRARIES += \
-    androidx.legacy_legacy-support-v4 \
-    car-apps-common
-
-LOCAL_STATIC_JAVA_LIBRARIES += \
-    car-glide \
-    car-glide-disklrucache \
-    car-gifdecoder \
-    libphonenumber
-
-LOCAL_USE_AAPT2 := true
-
-LOCAL_JAVA_LIBRARIES += android.car
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
-ifeq (,$(ONE_SHOT_MAKEFILE))
-    include $(call all-makefiles-under,$(LOCAL_PATH))
-endif
\ No newline at end of file
diff --git a/car-telephony-common/res/values-af/strings.xml b/car-telephony-common/res/values-af/strings.xml
index 7e19555..56aebcf 100644
--- a/car-telephony-common/res/values-af/strings.xml
+++ b/car-telephony-common/res/values-af/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Koppel tans …"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Bel tans …"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"Hou aan"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Oproep beëindig"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Hou aan"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Oproep beëindig"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Gekoppel"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Lui tans …"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Ontkoppel tans …"</string>
diff --git a/car-telephony-common/res/values-am/strings.xml b/car-telephony-common/res/values-am/strings.xml
index 6d0315e..2714928 100644
--- a/car-telephony-common/res/values-am/strings.xml
+++ b/car-telephony-common/res/values-am/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"በመገናኘት ላይ…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"በመደወል ላይ"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"ያዝናቆይ"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"ጥሪ አብቅቷል"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"ያዝና ቆይ"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"ጥሪ አብቅቷል"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"ተገናኝቷል"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"በመጥራት ላይ…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"ግንኝነትን በማቋረጥ ላይ…"</string>
diff --git a/car-telephony-common/res/values-ar/strings.xml b/car-telephony-common/res/values-ar/strings.xml
index fcc72fb..aa5ceca 100644
--- a/car-telephony-common/res/values-ar/strings.xml
+++ b/car-telephony-common/res/values-ar/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"جارٍ الاتصال…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"جارٍ طلب الرقم…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"قيد الانتظار"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"انتهت المكالمة"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"قيد الانتظار"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"تم إنهاء المكالمة"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"متّصل"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"جارٍ إطلاق الرنين…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"جارٍ قطع الاتصال…"</string>
diff --git a/car-telephony-common/res/values-as/strings.xml b/car-telephony-common/res/values-as/strings.xml
index a4c90ae..c2d94c4 100644
--- a/car-telephony-common/res/values-as/strings.xml
+++ b/car-telephony-common/res/values-as/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"সংযোগ কৰি থকা হৈছে…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"ডায়েল কৰি থকা হৈছে…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"হ’ল্ডত আছে"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"কল শেষ হৈছে"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"হ’ল্ডত আছে"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"কলটো সমাপ্ত হ’ল"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"সংযোগ কৰা হ’ল"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"ৰিং কৰি আছে…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"সংযোগ ছেদ হৈ আছে…"</string>
diff --git a/car-telephony-common/res/values-az/strings.xml b/car-telephony-common/res/values-az/strings.xml
index d29aeab..6882db1 100644
--- a/car-telephony-common/res/values-az/strings.xml
+++ b/car-telephony-common/res/values-az/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Qoşulur…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Nömrə yığılır…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"Gözləmədə"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Zəng sona çatdı"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Xətdə"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Zəng bitdi"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Qoşuldu"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Zəng çalır…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Bağlantı kəsilir…"</string>
diff --git a/car-telephony-common/res/values-b+sr+Latn/strings.xml b/car-telephony-common/res/values-b+sr+Latn/strings.xml
index d05ef72..04dcbbe 100644
--- a/car-telephony-common/res/values-b+sr+Latn/strings.xml
+++ b/car-telephony-common/res/values-b+sr+Latn/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Povezuje se…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Poziva se…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"Na čekanju"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Poziv je završen"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Na čekanju"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Poziv je završen"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Povezan"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Zvoni…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Prekida se veza…"</string>
diff --git a/car-telephony-common/res/values-be/strings.xml b/car-telephony-common/res/values-be/strings.xml
index 1e1bcdf..49e9f44 100644
--- a/car-telephony-common/res/values-be/strings.xml
+++ b/car-telephony-common/res/values-be/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Ідзе падключэнне…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Ідзе набор нумара…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"На ўтрыманні"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Выклік скончаны"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"На ўтрыманні"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Выклік завершаны"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Падключана"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Ідзе празвон…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Ідзе адключэнне…"</string>
diff --git a/car-telephony-common/res/values-bg/strings.xml b/car-telephony-common/res/values-bg/strings.xml
index 1f38d61..f308b5e 100644
--- a/car-telephony-common/res/values-bg/strings.xml
+++ b/car-telephony-common/res/values-bg/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Свързва се…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Набира се…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"Задържано"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Обаждането завърши"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Задържане на обаждането"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Обаждането завърши"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Установена е връзка"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Звъни се…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Връзката се прекр…"</string>
diff --git a/car-telephony-common/res/values-bn/strings.xml b/car-telephony-common/res/values-bn/strings.xml
index 4855b6e..65f38ef 100644
--- a/car-telephony-common/res/values-bn/strings.xml
+++ b/car-telephony-common/res/values-bn/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"কানেক্ট হচ্ছে…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"ডায়াল করা হচ্ছে…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"হোল্ডে আছে"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"কল শেষ হয়েছে"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"হোল্ডে রয়েছে"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"কল শেষ হয়েছে"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"কানেক্ট করা হয়েছে"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"রিং হচ্ছে…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"ডিসকানেক্ট করা হচ্ছে…"</string>
diff --git a/car-telephony-common/res/values-bs/strings.xml b/car-telephony-common/res/values-bs/strings.xml
index 1d6a8b8..fbfb012 100644
--- a/car-telephony-common/res/values-bs/strings.xml
+++ b/car-telephony-common/res/values-bs/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Povezivanje…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Biranje…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"Na čekanju"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Poziv je završen"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Na čekanju"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Poziv je završen"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Povezan"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Zvoni…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Prekidanje veze…"</string>
diff --git a/car-telephony-common/res/values-ca/strings.xml b/car-telephony-common/res/values-ca/strings.xml
index 356f31c..1ff8957 100644
--- a/car-telephony-common/res/values-ca/strings.xml
+++ b/car-telephony-common/res/values-ca/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"S\'està connectant…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"S\'està marcant…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"En espera"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Trucada finalitzada"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"En espera"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Trucada finalitzada"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Connectat"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Està sonant…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"S\'està desconnectant…"</string>
diff --git a/car-telephony-common/res/values-cs/strings.xml b/car-telephony-common/res/values-cs/strings.xml
index 41a29b5..7b6e1d7 100644
--- a/car-telephony-common/res/values-cs/strings.xml
+++ b/car-telephony-common/res/values-cs/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Připojování…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Vytáčení…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"Podrženo"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Hovor byl ukončen"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Přidržený hovor"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Hovor byl ukončen"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Připojeno"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Vyzvánění…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Odpojování…"</string>
diff --git a/car-telephony-common/res/values-da/strings.xml b/car-telephony-common/res/values-da/strings.xml
index dcd52a0..c1507fe 100644
--- a/car-telephony-common/res/values-da/strings.xml
+++ b/car-telephony-common/res/values-da/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Tilslutter…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Ringer op…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"Afventer"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Opkaldet er slut"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"På hold"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Opkaldet er slut"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Der er forbindelse"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Ringer…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Afbryder…"</string>
diff --git a/car-telephony-common/res/values-de/strings.xml b/car-telephony-common/res/values-de/strings.xml
index a5257d3..131fc08 100644
--- a/car-telephony-common/res/values-de/strings.xml
+++ b/car-telephony-common/res/values-de/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Verbinden…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Rufaufbau…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"Warten"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Anruf beendet"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Anruf wird gehalten"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Anruf beendet"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Verbunden"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Klingelt…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Verbindung wird getrennt…"</string>
diff --git a/car-telephony-common/res/values-el/strings.xml b/car-telephony-common/res/values-el/strings.xml
index 40d1716..6392460 100644
--- a/car-telephony-common/res/values-el/strings.xml
+++ b/car-telephony-common/res/values-el/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Σύνδεση…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Κλήση…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"Σε αναμονή"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Η κλήση τερματίστηκε"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Σε αναμονή"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Η κλήση τερματίστηκε"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Συνδέθηκε"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Κλήση…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Αποσύνδεση…"</string>
diff --git a/car-telephony-common/res/values-en-rAU/strings.xml b/car-telephony-common/res/values-en-rAU/strings.xml
index 06d1973..cc8a536 100644
--- a/car-telephony-common/res/values-en-rAU/strings.xml
+++ b/car-telephony-common/res/values-en-rAU/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Connecting…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Dialling…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"On Hold"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Call Ended"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"On hold"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Call ended"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Connected"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Ringing…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Disconnecting…"</string>
diff --git a/car-telephony-common/res/values-en-rCA/strings.xml b/car-telephony-common/res/values-en-rCA/strings.xml
index 06d1973..cc8a536 100644
--- a/car-telephony-common/res/values-en-rCA/strings.xml
+++ b/car-telephony-common/res/values-en-rCA/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Connecting…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Dialling…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"On Hold"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Call Ended"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"On hold"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Call ended"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Connected"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Ringing…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Disconnecting…"</string>
diff --git a/car-telephony-common/res/values-en-rGB/strings.xml b/car-telephony-common/res/values-en-rGB/strings.xml
index 06d1973..cc8a536 100644
--- a/car-telephony-common/res/values-en-rGB/strings.xml
+++ b/car-telephony-common/res/values-en-rGB/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Connecting…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Dialling…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"On Hold"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Call Ended"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"On hold"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Call ended"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Connected"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Ringing…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Disconnecting…"</string>
diff --git a/car-telephony-common/res/values-en-rIN/strings.xml b/car-telephony-common/res/values-en-rIN/strings.xml
index 06d1973..cc8a536 100644
--- a/car-telephony-common/res/values-en-rIN/strings.xml
+++ b/car-telephony-common/res/values-en-rIN/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Connecting…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Dialling…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"On Hold"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Call Ended"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"On hold"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Call ended"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Connected"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Ringing…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Disconnecting…"</string>
diff --git a/car-telephony-common/res/values-en-rXC/strings.xml b/car-telephony-common/res/values-en-rXC/strings.xml
index b80f8fa..43e60e9 100644
--- a/car-telephony-common/res/values-en-rXC/strings.xml
+++ b/car-telephony-common/res/values-en-rXC/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‏‏‏‎‎‏‏‏‎‎‏‏‏‏‏‎‎‎‎‏‏‎‎‎‎‏‏‎‎‏‎‎‏‎‎‎‏‏‏‏‏‏‏‎‎‎‎‏‎‏‎‎‏‎‎‏‏‎<xliff:g id="LABEL">%1$s</xliff:g>‎‏‎‎‏‏‏‎  ·  ‎‏‎‎‏‏‎<xliff:g id="DURATION">%2$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‎‎‏‎‎‏‎‎‏‏‏‎‎‎‏‎‏‎‏‎‏‎‏‏‏‏‎‎‎‎‎‎‏‎‎‎‎‏‎‏‎‎‎‏‎‏‏‎‏‏‏‏‏‎‎‏‎‎‏‎‎Connecting…‎‏‎‎‏‎"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‎‏‏‎‏‎‏‎‏‎‎‏‎‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‎‏‏‏‏‏‎‎‎‏‎‎‎‎‎‎‏‏‏‏‏‏‎‎‏‎‎‏‎‏‏‎‎‏‎‎Dialing…‎‏‎‎‏‎"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‏‏‏‎‏‏‎‏‎‏‏‏‎‏‎‏‏‎‎‎‎‏‎‏‏‎‎‏‏‏‏‎‏‏‎‎‎‎‏‏‏‎‏‎‏‏‎‎‎‎‎‎‏‏‏‎‎‏‎‎‎On Hold‎‏‎‎‏‎"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‎‎‏‏‎‏‏‏‎‎‎‏‏‏‏‏‎‏‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‎‏‏‎‎‏‏‎‏‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‎‏‎Call Ended‎‏‎‎‏‎"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‏‏‏‏‏‏‏‎‎‏‏‏‎‏‏‏‎‏‎‎‏‎‏‏‏‎‏‏‎‏‎‎‎‎‏‎‏‏‎‎‎‏‏‎‏‎‏‏‎‎‏‎‎‏‏‏‏‎‏‎‎On hold‎‏‎‎‏‎"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‎‏‏‎‎‏‏‏‏‎‏‏‏‏‏‏‏‏‏‎‎‎‎‎‎‏‏‏‎‏‏‎‎‎‎‏‏‎‏‏‎‏‎‎‎‎‏‏‏‎‏‏‏‎‏‎‎‎‎‏‎‎‎‎Call ended‎‏‎‎‏‎"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‏‏‎‎‏‏‎‏‏‏‏‏‏‎‎‎‎‎‏‎‏‎‎‎‎‎‏‏‎‏‎‏‎‏‏‏‏‏‏‎‎‎‎‏‏‎‎‏‏‎‎‎‎‎‎‏‎‏‎‎Connected‎‏‎‎‏‎"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‎‎‎‎‎‎‎‏‏‎‎‏‎‏‎‎‏‎‎‏‎‎‏‏‏‎‎‏‎‎‏‏‏‎‎‎‎‏‏‏‎‏‎‏‏‏‏‏‏‏‏‏‎‏‏‎‏‎‎‏‎Ringing…‎‏‎‎‏‎"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‎‏‎‏‏‏‏‎‏‎‎‎‏‏‎‎‏‎‏‎‎‎‎‎‏‏‏‏‎‎‏‏‏‎‏‎‎‏‎‎‏‏‏‎‏‏‏‏‎‎‎‏‏‏‏‏‎‏‏‏‎Disconnecting…‎‏‎‎‏‎"</string>
diff --git a/car-telephony-common/res/values-es-rUS/strings.xml b/car-telephony-common/res/values-es-rUS/strings.xml
index 2e71140..12fb629 100644
--- a/car-telephony-common/res/values-es-rUS/strings.xml
+++ b/car-telephony-common/res/values-es-rUS/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Conectando…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Marcando…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"En espera"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Llamada finalizada"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"En espera"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Llamada finalizada"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Conectado"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Sonando…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Desconectando…"</string>
diff --git a/car-telephony-common/res/values-es/strings.xml b/car-telephony-common/res/values-es/strings.xml
index 390354f..6cff2e2 100644
--- a/car-telephony-common/res/values-es/strings.xml
+++ b/car-telephony-common/res/values-es/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Conectando…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Marcando…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"En espera"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Llamada finalizada"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"En espera"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Llamada finalizada"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Conectado"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Sonando…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Desconectando…"</string>
diff --git a/car-telephony-common/res/values-et/strings.xml b/car-telephony-common/res/values-et/strings.xml
index ee65909..6707e93 100644
--- a/car-telephony-common/res/values-et/strings.xml
+++ b/car-telephony-common/res/values-et/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Ühendamine …"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Valimine …"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"Ootel"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Kõne lõpetati"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Ootel"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Kõne lõpetati"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Ühendatud"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Heliseb …"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Ühenduse katkest. …"</string>
diff --git a/car-telephony-common/res/values-eu/strings.xml b/car-telephony-common/res/values-eu/strings.xml
index ddaec85..ff34106 100644
--- a/car-telephony-common/res/values-eu/strings.xml
+++ b/car-telephony-common/res/values-eu/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Konektatzen…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Markatzen…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"Zain"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Deia amaituta"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Zain"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Amaitu da deia"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Konektatuta"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Deitzen…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Deskonektatzen…"</string>
diff --git a/car-telephony-common/res/values-fa/strings.xml b/car-telephony-common/res/values-fa/strings.xml
index 092b944..0418d6e 100644
--- a/car-telephony-common/res/values-fa/strings.xml
+++ b/car-telephony-common/res/values-fa/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"درحال اتصال…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"درحال شماره‌گیری"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"در انتظار"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"تماس پایان یافت"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"درانتظار"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"تماس پایان یافت"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"متصل"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"درحال زنگ زدن…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"درحال قطع اتصال…"</string>
diff --git a/car-telephony-common/res/values-fi/strings.xml b/car-telephony-common/res/values-fi/strings.xml
index ce6ff53..bf46e0b 100644
--- a/car-telephony-common/res/values-fi/strings.xml
+++ b/car-telephony-common/res/values-fi/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Yhdistetään…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Soitetaan…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"Pidossa"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Puhelu päättyi"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Pidossa"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Puhelu lopetettu"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Yhdistetty"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Soi…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Katkaistaan…"</string>
diff --git a/car-telephony-common/res/values-fr-rCA/strings.xml b/car-telephony-common/res/values-fr-rCA/strings.xml
index cef9278..bed5d9d 100644
--- a/car-telephony-common/res/values-fr-rCA/strings.xml
+++ b/car-telephony-common/res/values-fr-rCA/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g> : <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Connexion en cours…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Composition…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"En attente"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Appel terminé"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"En attente"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Appel terminé"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Connecté"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Sonnerie en cours…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Déconnexion…"</string>
diff --git a/car-telephony-common/res/values-fr/strings.xml b/car-telephony-common/res/values-fr/strings.xml
index 164f23d..35833e0 100644
--- a/car-telephony-common/res/values-fr/strings.xml
+++ b/car-telephony-common/res/values-fr/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Connexion…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Composition numéro…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"En attente"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Appel terminé"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"En attente"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Appel terminé"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Appel en cours"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Sonnerie…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Déconnexion…"</string>
diff --git a/car-telephony-common/res/values-gl/strings.xml b/car-telephony-common/res/values-gl/strings.xml
index 2251c16..2058cad 100644
--- a/car-telephony-common/res/values-gl/strings.xml
+++ b/car-telephony-common/res/values-gl/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Conectando…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Marcando…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"En espera"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Chamada finalizada"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"En espera"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Chamada finalizada"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Conectado"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Facendo soar…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Desconectando…"</string>
diff --git a/car-telephony-common/res/values-gu/strings.xml b/car-telephony-common/res/values-gu/strings.xml
index 04cf443..7040087 100644
--- a/car-telephony-common/res/values-gu/strings.xml
+++ b/car-telephony-common/res/values-gu/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"કનેક્ટ થઈ રહ્યું છે…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"ડાયલ કરી રહ્યાં છે…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"હોલ્ડ પર"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"કૉલ સમાપ્ત થયો"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"હોલ્ડ પર"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"કૉલ સમાપ્ત થયો"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"કનેક્ટેડ"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"રિંગ વાગી રહી છે…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"ડિસ્કનેક્ટ થાય છે…"</string>
diff --git a/car-telephony-common/res/values-hi/strings.xml b/car-telephony-common/res/values-hi/strings.xml
index 5fdb213..418e776 100644
--- a/car-telephony-common/res/values-hi/strings.xml
+++ b/car-telephony-common/res/values-hi/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"कनेक्ट हो रहा है…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"डायल किया जा रहा है…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"कॉल होल्ड पर है"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"कॉल खत्म हो गया"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"होल्ड पर है"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"कॉल खत्म हुआ"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"जुड़ गया है"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"घंटी बज रही है…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"डिसकनेक्ट हो रहा है…"</string>
diff --git a/car-telephony-common/res/values-hr/strings.xml b/car-telephony-common/res/values-hr/strings.xml
index 5e0f4d7..6a35140 100644
--- a/car-telephony-common/res/values-hr/strings.xml
+++ b/car-telephony-common/res/values-hr/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Povezivanje…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Biranje broja…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"Na čekanju"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Poziv je završio"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Na čekanju"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Poziv je završio"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Povezano"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Zvonjenje…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Isključivanje…"</string>
diff --git a/car-telephony-common/res/values-hu/strings.xml b/car-telephony-common/res/values-hu/strings.xml
index fa95e1a..26e0165 100644
--- a/car-telephony-common/res/values-hu/strings.xml
+++ b/car-telephony-common/res/values-hu/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Csatlakozás…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Tárcsázás…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"Várakoztatva"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"A hívás befejeződött"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Várakoztatva"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"A hívás befejeződött"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Csatlakozva"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Csörgés…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Kapcsolat bontása…"</string>
diff --git a/car-telephony-common/res/values-hy/strings.xml b/car-telephony-common/res/values-hy/strings.xml
index c8d7ea9..9a0cdeb 100644
--- a/car-telephony-common/res/values-hy/strings.xml
+++ b/car-telephony-common/res/values-hy/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Միացում…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Համարհավաքում…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"Սպասում"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Զանգն ավարտվեց"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Զանգը սպասման մեջ է"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Զանգն ավարտվեց"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Միացած է"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Զանգ…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Անջատվում է…"</string>
diff --git a/car-telephony-common/res/values-in/strings.xml b/car-telephony-common/res/values-in/strings.xml
index 53a7831..fe742e7 100644
--- a/car-telephony-common/res/values-in/strings.xml
+++ b/car-telephony-common/res/values-in/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Menghubungkan…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Memanggil…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"Harap Tunggu"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Panggilan Diakhiri"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Ditangguhkan"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Panggilan diakhiri"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Terhubung"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Berdering…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Memutus hubungan..."</string>
diff --git a/car-telephony-common/res/values-is/strings.xml b/car-telephony-common/res/values-is/strings.xml
index b91a805..e330acb 100644
--- a/car-telephony-common/res/values-is/strings.xml
+++ b/car-telephony-common/res/values-is/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Tengist…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Hringir…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"Í bið"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Símtali lokið"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Í bið"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Lagt á"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Tengt"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Hringir…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Aftengist…"</string>
diff --git a/car-telephony-common/res/values-it/strings.xml b/car-telephony-common/res/values-it/strings.xml
index cb4bc61..47b659c 100644
--- a/car-telephony-common/res/values-it/strings.xml
+++ b/car-telephony-common/res/values-it/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Connessione…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Chiamata…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"In attesa"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Chiamata terminata"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"In attesa"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Chiamata terminata"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Connesso"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Sta squillando…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Disconnessione…"</string>
diff --git a/car-telephony-common/res/values-iw/strings.xml b/car-telephony-common/res/values-iw/strings.xml
index 0d1cd68..aad5c48 100644
--- a/car-telephony-common/res/values-iw/strings.xml
+++ b/car-telephony-common/res/values-iw/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"מתחבר…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"מחייג…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"בהמתנה"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"השיחה הסתיימה"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"בהמתנה"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"השיחה הסתיימה"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"מתבצעת שיחה"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"מצלצל…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"מתנתק…"</string>
diff --git a/car-telephony-common/res/values-ja/strings.xml b/car-telephony-common/res/values-ja/strings.xml
index 4c0a6c1..a231047 100644
--- a/car-telephony-common/res/values-ja/strings.xml
+++ b/car-telephony-common/res/values-ja/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"接続中…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"発信中…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"保留中"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"通話終了"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"保留中"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"通話終了"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"接続済み"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"着信中…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"切断中…"</string>
diff --git a/car-telephony-common/res/values-ka/strings.xml b/car-telephony-common/res/values-ka/strings.xml
index 858ffa3..6db5a44 100644
--- a/car-telephony-common/res/values-ka/strings.xml
+++ b/car-telephony-common/res/values-ka/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"დაკავშირება…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"მიმდინარეობს აკრეფა…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"შეყოვნების რეჟიმში"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"ზარი დასრულდა"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"შეყოვნების რეჟიმში"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"ზარი დასრულდა"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"დაკავშირებულია"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"ირეკება…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"კავშირი წყდება…"</string>
diff --git a/car-telephony-common/res/values-kk/strings.xml b/car-telephony-common/res/values-kk/strings.xml
index 48eba3d..0e767dd 100644
--- a/car-telephony-common/res/values-kk/strings.xml
+++ b/car-telephony-common/res/values-kk/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Жалғануда…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Терілуде…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"Күтуде"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Қоңырау аяқталды"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Күтуде"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Қоңырау аяқталды"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Жалғанды"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Шылдырлату…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Ажыратылуда…"</string>
diff --git a/car-telephony-common/res/values-km/strings.xml b/car-telephony-common/res/values-km/strings.xml
index a483de3..44b7870 100644
--- a/car-telephony-common/res/values-km/strings.xml
+++ b/car-telephony-common/res/values-km/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"កំពុងភ្ជាប់…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"កំពុងហៅ…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"រង់ចាំ"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"បាន​បញ្ចប់​ការ​ហៅ"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"កំពុងរង់ចាំ"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"បានបញ្ចប់​ការហៅទូរសព្ទ"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"បានភ្ជាប់"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"កំពុង​រោទ៍…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"កំពុង​ផ្ដាច់…"</string>
diff --git a/car-telephony-common/res/values-kn/strings.xml b/car-telephony-common/res/values-kn/strings.xml
index 7b57804..2f04e28 100644
--- a/car-telephony-common/res/values-kn/strings.xml
+++ b/car-telephony-common/res/values-kn/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"ಸಂಪರ್ಕಿಸಲಾಗುತ್ತಿದೆ…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"ಡಯಲ್‌ ಮಾಡಲಾಗುತ್ತಿದೆ…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"ಹೋಲ್ಡ್‌ ಮಾಡಲಾಗಿದೆ"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"ಕರೆ ಅಂತ್ಯಗೊಂಡಿದೆ"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"ಹೋಲ್ಡ್‌ ಮಾಡಲಾಗಿದೆ"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"ಕರೆ ಅಂತ್ಯಗೊಂಡಿದೆ"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"ಸಂಪರ್ಕಿಸಲಾಗಿದೆ"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"ರಿಂಗ್‍ ಆಗುತ್ತಿದೆ…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"ಸಂಪರ್ಕ ಕಡಿತಗೊಳಿಸಲಾ…"</string>
diff --git a/car-telephony-common/res/values-ko/strings.xml b/car-telephony-common/res/values-ko/strings.xml
index 1171186..b210c69 100644
--- a/car-telephony-common/res/values-ko/strings.xml
+++ b/car-telephony-common/res/values-ko/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"연결 중…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"전화 거는 중..."</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"대기 중"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"통화 종료됨"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"대기 중"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"통화 종료됨"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"연결됨"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"벨소리 울리는 중…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"연결 해제 중..."</string>
diff --git a/car-telephony-common/res/values-ky/strings.xml b/car-telephony-common/res/values-ky/strings.xml
index b76e748..599ca63 100644
--- a/car-telephony-common/res/values-ky/strings.xml
+++ b/car-telephony-common/res/values-ky/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Туташууда…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Терилүүдө…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"Күтүү режиминде"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Чалуу аяктады"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Күтүү режиминде"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Чалуу аяктады"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Туташты"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Шыңгырап жатат…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Ажыратылууда…"</string>
diff --git a/car-telephony-common/res/values-lo/strings.xml b/car-telephony-common/res/values-lo/strings.xml
index b6cc9df..ec95f01 100644
--- a/car-telephony-common/res/values-lo/strings.xml
+++ b/car-telephony-common/res/values-lo/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"ກຳລັງເຊື່ອມຕໍ່…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"ກຳລັງໂທ…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"ຖືສາຍລໍຖ້າ"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"ວາງສາຍແລ້ວ"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"ພັກສາຍ"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"ວາງສາຍແລ້ວ"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"ເຊື່ອມຕໍ່ແລ້ວ"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"ກຳລັງດັງ…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"ກຳລັງຕັດການເຊື່ອມຕໍ່…"</string>
diff --git a/car-telephony-common/res/values-lt/strings.xml b/car-telephony-common/res/values-lt/strings.xml
index ea0508a..550d875 100644
--- a/car-telephony-common/res/values-lt/strings.xml
+++ b/car-telephony-common/res/values-lt/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Prisijungiama…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Renkamas numeris…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"Sulaikyta"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Skambutis baigtas"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Sulaikyta"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Skambutis baigtas"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Sujungta"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Skambinama…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Atsijungiama…"</string>
diff --git a/car-telephony-common/res/values-lv/strings.xml b/car-telephony-common/res/values-lv/strings.xml
index 28e49f5..184c937 100644
--- a/car-telephony-common/res/values-lv/strings.xml
+++ b/car-telephony-common/res/values-lv/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Veido savienojumu…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Sastāda numuru…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"Aizturēts"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Zvans ir pabeigts"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Aizturēts"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Zvans pabeigts"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Savienots"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Zvana…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Notiek atvienošana…"</string>
diff --git a/car-telephony-common/res/values-mk/strings.xml b/car-telephony-common/res/values-mk/strings.xml
index b6053e3..c3ef6eb 100644
--- a/car-telephony-common/res/values-mk/strings.xml
+++ b/car-telephony-common/res/values-mk/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Се поврзува…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Бирање…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"На чекање"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Повикот заврши"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"На чекање"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Повикот заврши"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Поврзан"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Ѕвони…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Се исклучува…"</string>
diff --git a/car-telephony-common/res/values-ml/strings.xml b/car-telephony-common/res/values-ml/strings.xml
index e940e9b..85d886c 100644
--- a/car-telephony-common/res/values-ml/strings.xml
+++ b/car-telephony-common/res/values-ml/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"കണക്റ്റ് ചെയ്യുന്നു…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"ഡയൽ ചെയ്യുന്നു…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"ഹോള്‍ഡിലാണ്"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"കോൾ അവസാനിച്ചു"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"ഹോൾഡിലാണ്"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"കോൾ അവസാനിച്ചു"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"കണക്‌റ്റ് ചെയ്‌തു"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"റിംഗ് ചെയ്യുന്നു…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"വിച്ഛേദിക്കുന്നു…"</string>
diff --git a/car-telephony-common/res/values-mn/strings.xml b/car-telephony-common/res/values-mn/strings.xml
index 5fdc776..74956f3 100644
--- a/car-telephony-common/res/values-mn/strings.xml
+++ b/car-telephony-common/res/values-mn/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Холбогдож байна…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Залгаж байна…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"Хүлээлгэнд байна"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Дуудлагыг тасалсан"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Хүлээлгэд байгаа"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Дуудлага дууссан"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Холбогдсон"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Дуугарч байна…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Салгаж байна…"</string>
diff --git a/car-telephony-common/res/values-mr/strings.xml b/car-telephony-common/res/values-mr/strings.xml
index 9c7f085..d3036e1 100644
--- a/car-telephony-common/res/values-mr/strings.xml
+++ b/car-telephony-common/res/values-mr/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"कनेक्ट करत आहे…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"डायल करत आहे…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"होल्ड वर"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"कॉल संपला"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"होल्डवर आहे"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"कॉल संपला आहे"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"कनेक्ट केले"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"रिंग होत आहे…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"डिस्कनेक्ट करत आहे…"</string>
diff --git a/car-telephony-common/res/values-ms/strings.xml b/car-telephony-common/res/values-ms/strings.xml
index 1c1d5de..98bcb58 100644
--- a/car-telephony-common/res/values-ms/strings.xml
+++ b/car-telephony-common/res/values-ms/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Menyambung…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Mendail…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"Ditunda"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Panggilan Tamat"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Ditunda"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Panggilan tamat"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Disambungkan"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Berdering…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Memutuskan sambungn…"</string>
diff --git a/car-telephony-common/res/values-my/strings.xml b/car-telephony-common/res/values-my/strings.xml
index 130935a..e2d5565 100644
--- a/car-telephony-common/res/values-my/strings.xml
+++ b/car-telephony-common/res/values-my/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"ချိတ်ဆက်နေသည်…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"ခေါ်ဆိုနေသည်…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"ဖုန်းကိုင်ထားသည်"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"ခေါ်ဆိုမှု ပြီးပါပြီ"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"ဖုန်းကိုင်ထားသည်"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"ခေါ်ဆိုမှု ပြီးသွားပါပြီ"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"ချိတ်ဆက်ထားသည်"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"အသံမြည်နေသည်…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"အဆက်အသွယ် ဖြတ်နေသည်…"</string>
diff --git a/car-telephony-common/res/values-nb/strings.xml b/car-telephony-common/res/values-nb/strings.xml
index 119f352..e6e90b3 100644
--- a/car-telephony-common/res/values-nb/strings.xml
+++ b/car-telephony-common/res/values-nb/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Kobler til …"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Slår nummeret …"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"På vent"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Anropet er avsluttet"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"På vent"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Anropet er avsluttet"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Tilkoblet"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Ringer …"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Kobler fra …"</string>
diff --git a/car-telephony-common/res/values-ne/strings.xml b/car-telephony-common/res/values-ne/strings.xml
index b021f11..8c3f1ff 100644
--- a/car-telephony-common/res/values-ne/strings.xml
+++ b/car-telephony-common/res/values-ne/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"जोड्दै…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"डायल गर्दै…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"होल्डमा छ"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"कल समाप्त भयो"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"होल्डमा छ"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"कल समाप्त भयो"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"जडान गरिएको छ"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"घन्टी बज्दै छ…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"विच्छेद गर्दै…"</string>
diff --git a/car-telephony-common/res/values-nl/strings.xml b/car-telephony-common/res/values-nl/strings.xml
index 7d00163..e97b569 100644
--- a/car-telephony-common/res/values-nl/strings.xml
+++ b/car-telephony-common/res/values-nl/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Verbinden…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Kiezen…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"In de wacht"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Gesprek beëindigd"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"In de wacht"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Gesprek beëindigd"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Verbonden"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Gaat over…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Verb. verbreken…"</string>
diff --git a/car-telephony-common/res/values-or/strings.xml b/car-telephony-common/res/values-or/strings.xml
index 775e33c..c95fa40 100644
--- a/car-telephony-common/res/values-or/strings.xml
+++ b/car-telephony-common/res/values-or/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"ସଂଯୋଗ ହେଉଛି…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"ଡାଏଲ୍ କରାଯାଉଛି…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"ହୋଲ୍ଡରେ ଅଛି"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"କଲ୍ ସମାପ୍ତ ହେଲା"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"ହୋଲ୍ଡରେ ଅଛି"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"କଲ୍ ଶେଷ ହୋଇଛି"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"ସଂଯୋଗ ହୋଇଛି"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"ରିଙ୍ଗ ହେଉଛି…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"ବିଚ୍ଛିନ୍ନ ହେଉଛି…"</string>
diff --git a/car-telephony-common/res/values-pa/strings.xml b/car-telephony-common/res/values-pa/strings.xml
index 129276b..dcad72f 100644
--- a/car-telephony-common/res/values-pa/strings.xml
+++ b/car-telephony-common/res/values-pa/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"ਕਨੈਕਟ ਹੋ ਰਿਹਾ ਹੈ…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"ਡਾਇਲ ਹੋ ਰਿਹਾ ਹੈ…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"ਰੋਕ ਕੇ ਰੱਖੀ ਗਈ"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"ਕਾਲ ਸਮਾਪਤ ਹੋਈ"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"ਰੋਕ ਕੇ ਰੱਖੀ ਗਈ"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"ਕਾਲ ਸਮਾਪਤ ਹੋਈ"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"ਕਨੈਕਟ ਹੈ"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"ਘੰਟੀ ਵੱਜ ਰਹੀ ਹੈ…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"ਡਿਸਕਨੈਕਟ ਹੋ ਰਿਹਾ ਹੈ…"</string>
diff --git a/car-telephony-common/res/values-pl/strings.xml b/car-telephony-common/res/values-pl/strings.xml
index 1212857..7b87eef 100644
--- a/car-telephony-common/res/values-pl/strings.xml
+++ b/car-telephony-common/res/values-pl/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Łączę…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Wybieram numer…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"Oczekujące"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Koniec połączenia"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Oczekujące"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Połączenie zakończone"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Połączono"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Dzwonię…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Rozłączam…"</string>
diff --git a/car-telephony-common/res/values-pt-rPT/strings.xml b/car-telephony-common/res/values-pt-rPT/strings.xml
index 3b518e6..b0577d0 100644
--- a/car-telephony-common/res/values-pt-rPT/strings.xml
+++ b/car-telephony-common/res/values-pt-rPT/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"A ligar…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"A marcar…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"Em espera"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Chamada terminada"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Em espera"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Chamada terminada"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Ligado"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"A tocar…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"A desligar…"</string>
diff --git a/car-telephony-common/res/values-pt/strings.xml b/car-telephony-common/res/values-pt/strings.xml
index 7531adb..9ac136b 100644
--- a/car-telephony-common/res/values-pt/strings.xml
+++ b/car-telephony-common/res/values-pt/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Conectando…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Discando…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"Em espera"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Chamada encerrada"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Em espera"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Chamada encerrada"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Conectado"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Tocando…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Desconectando…"</string>
diff --git a/car-telephony-common/res/values-ro/strings.xml b/car-telephony-common/res/values-ro/strings.xml
index a9883de..7d78d46 100644
--- a/car-telephony-common/res/values-ro/strings.xml
+++ b/car-telephony-common/res/values-ro/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Se conectează…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Se apelează…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"În așteptare"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Apel încheiat"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"În așteptare"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Apel încheiat"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Conectat"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Sună…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Se deconectează…"</string>
diff --git a/car-telephony-common/res/values-ru/strings.xml b/car-telephony-common/res/values-ru/strings.xml
index 2e37211..6731414 100644
--- a/car-telephony-common/res/values-ru/strings.xml
+++ b/car-telephony-common/res/values-ru/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Подключение…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Набор номера…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"На удержании"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Вызов завершен"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Вызов на удержании"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Вызов завершен"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Подключено"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Вызов…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Отключение…"</string>
diff --git a/car-telephony-common/res/values-si/strings.xml b/car-telephony-common/res/values-si/strings.xml
index 399c8d8..b0ac2e8 100644
--- a/car-telephony-common/res/values-si/strings.xml
+++ b/car-telephony-common/res/values-si/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"සබැඳෙමින්…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"අමතමින්…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"රඳවා ඇත"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"ඇමතුම නිමා විය"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"රඳවා ගනිමින්"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"ඇමතුම අවසන් විය"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"සම්බන්ධයි"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"නාද වෙමින්…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"විසන්ධි වෙමින්…"</string>
diff --git a/car-telephony-common/res/values-sk/strings.xml b/car-telephony-common/res/values-sk/strings.xml
index 83721d3..0aeef23 100644
--- a/car-telephony-common/res/values-sk/strings.xml
+++ b/car-telephony-common/res/values-sk/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Pripája sa…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Vytáča sa…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"Podržané"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Hovor bol ukončený"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Podržaný hovor"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Hovor bol ukončený"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Pripojené"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Prezváňa sa…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Odpája sa…"</string>
diff --git a/car-telephony-common/res/values-sl/strings.xml b/car-telephony-common/res/values-sl/strings.xml
index 03a7063..ce84056 100644
--- a/car-telephony-common/res/values-sl/strings.xml
+++ b/car-telephony-common/res/values-sl/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Povezovanje …"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Klicanje …"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"Zadržan"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Klic je bil končan"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Na čakanju"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Klic je končan"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Povezano"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Zvonjenje …"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Prekin. povezave …"</string>
diff --git a/car-telephony-common/res/values-sq/strings.xml b/car-telephony-common/res/values-sq/strings.xml
index f6439eb..87af7f4 100644
--- a/car-telephony-common/res/values-sq/strings.xml
+++ b/car-telephony-common/res/values-sq/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Po lidhet…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Po formon numrin…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"Në pritje"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Telefonata përfundoi"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Në pritje"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Telefonata përfundoi"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Lidhur"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Po bie zilja…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Po shkëputet…"</string>
diff --git a/car-telephony-common/res/values-sr/strings.xml b/car-telephony-common/res/values-sr/strings.xml
index 1f3837f..4b48d1a 100644
--- a/car-telephony-common/res/values-sr/strings.xml
+++ b/car-telephony-common/res/values-sr/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Повезује се…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Позива се…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"На чекању"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Позив је завршен"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"На чекању"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Позив је завршен"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Повезан"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Звони…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Прекида се веза…"</string>
diff --git a/car-telephony-common/res/values-sv/strings.xml b/car-telephony-common/res/values-sv/strings.xml
index f4b9b1a..2aff4e7 100644
--- a/car-telephony-common/res/values-sv/strings.xml
+++ b/car-telephony-common/res/values-sv/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Ansluter …"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Ringer upp …"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"Parkerat"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Samtal avslutat"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Parkerat"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Samtal avslutat"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Ansluten"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Ringer …"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Kopplar från …"</string>
diff --git a/car-telephony-common/res/values-sw/strings.xml b/car-telephony-common/res/values-sw/strings.xml
index f6adbc1..6711f55 100644
--- a/car-telephony-common/res/values-sw/strings.xml
+++ b/car-telephony-common/res/values-sw/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Inaunganisha…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Inapigia…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"Inangoja"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Simu Imekamilika"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Imesitishwa"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Simu imekamilika"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Imeunganisha"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Inalia…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Inaondoa…"</string>
diff --git a/car-telephony-common/res/values-ta/strings.xml b/car-telephony-common/res/values-ta/strings.xml
index d835fab..d6bb4c9 100644
--- a/car-telephony-common/res/values-ta/strings.xml
+++ b/car-telephony-common/res/values-ta/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"இணைக்கிறது…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"டயல் செய்கிறது…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"காத்திருப்பில்"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"அழைப்பு முடிந்தது"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"ஹோல்டில் உள்ளது"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"அழைப்பு முடிந்தது"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"இணைக்கப்பட்டது"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"அழைக்கிறது…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"துண்டிக்கிறது…"</string>
diff --git a/car-telephony-common/res/values-te/strings.xml b/car-telephony-common/res/values-te/strings.xml
index 2ebcb08..39975e4 100644
--- a/car-telephony-common/res/values-te/strings.xml
+++ b/car-telephony-common/res/values-te/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"కనెక్ట్ అవుతోంది…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"డయల్ చేస్తోంది…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"హోల్డ్‌లో ఉంది"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"కాల్ ముగిసింది"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"హోల్డ్‌లో ఉంది"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"కాల్ ముగిసింది"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"కనెక్ట్ చేయబడింది"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"రింగ్ అవుతోంది…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"డిస్కనెక్టవుతోంది…"</string>
diff --git a/car-telephony-common/res/values-th/strings.xml b/car-telephony-common/res/values-th/strings.xml
index 7af5876..0a8a28c 100644
--- a/car-telephony-common/res/values-th/strings.xml
+++ b/car-telephony-common/res/values-th/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"กำลังเชื่อมต่อ…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"กำลังโทรออก…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"พักสาย"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"วางสายแล้ว"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"พักสาย"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"วางสายแล้ว"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"เชื่อมต่อแล้ว"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"กำลังส่งเสียง…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"ยกเลิกการเชื่อมต่อ…"</string>
diff --git a/car-telephony-common/res/values-tl/strings.xml b/car-telephony-common/res/values-tl/strings.xml
index f5f02ef..2bdda5c 100644
--- a/car-telephony-common/res/values-tl/strings.xml
+++ b/car-telephony-common/res/values-tl/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Kumokonekta…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Dina-dial…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"Naka-hold"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Natapos ang Tawag"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Naka-hold"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Tinapos ang tawag"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Nakakonekta"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Nagri-ring…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Dinidiskonekta…"</string>
diff --git a/car-telephony-common/res/values-tr/strings.xml b/car-telephony-common/res/values-tr/strings.xml
index 8da8d62..dc05ebf 100644
--- a/car-telephony-common/res/values-tr/strings.xml
+++ b/car-telephony-common/res/values-tr/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Bağlanıyor…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Numara çevriliyor…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"Beklemede"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Çağrı Sonlandırıldı"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Beklemede"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Çağrı sonlandırıldı"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Bağlandı"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Zil çaldırılıyor…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Bağlantı kesiliyor…"</string>
diff --git a/car-telephony-common/res/values-uk/strings.xml b/car-telephony-common/res/values-uk/strings.xml
index 6c05db2..f72fa83 100644
--- a/car-telephony-common/res/values-uk/strings.xml
+++ b/car-telephony-common/res/values-uk/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"З’єднання…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Набір номера…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"Утримується"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Виклик завершено"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Утримується"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Виклик завершено"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Під’єднано"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Дзвінок…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Від’єднання…"</string>
diff --git a/car-telephony-common/res/values-ur/strings.xml b/car-telephony-common/res/values-ur/strings.xml
index 92dfe09..3deac0b 100644
--- a/car-telephony-common/res/values-ur/strings.xml
+++ b/car-telephony-common/res/values-ur/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"منسلک ہو رہا ہے…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"ڈائل کر رہا ہے…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"ہولڈ پر ہے"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"کال ختم ہوگئی"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"ہولڈ پر ہے"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"کال ختم ہو گئی"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"منسلک ہے"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"گھنٹی بج رہی ہے…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"غیر منسلک ہو رہا ہے…"</string>
diff --git a/car-telephony-common/res/values-uz/strings.xml b/car-telephony-common/res/values-uz/strings.xml
index 2683304..a818836 100644
--- a/car-telephony-common/res/values-uz/strings.xml
+++ b/car-telephony-common/res/values-uz/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Ulanmoqda…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Raqam terilmoqda…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"Kutish holatida"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Chaqiruv yakunlandi"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Pauzada"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Chaqiruv tugadi"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Ulandi"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Jiringlamoqda…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Uzilmoqda…"</string>
diff --git a/car-telephony-common/res/values-vi/strings.xml b/car-telephony-common/res/values-vi/strings.xml
index e52194a..d0dc77b 100644
--- a/car-telephony-common/res/values-vi/strings.xml
+++ b/car-telephony-common/res/values-vi/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Đang kết nối…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Đang quay số..."</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"Đang chờ"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Cuộc gọi đã kết thúc"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Đang giữ máy"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Cuộc gọi đã kết thúc"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Đã kết nối"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Đang đổ chuông..."</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Đang ngắt kết nối…"</string>
diff --git a/car-telephony-common/res/values-zh-rCN/strings.xml b/car-telephony-common/res/values-zh-rCN/strings.xml
index 1a6a652..0c2fc09 100644
--- a/car-telephony-common/res/values-zh-rCN/strings.xml
+++ b/car-telephony-common/res/values-zh-rCN/strings.xml
@@ -17,12 +17,12 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="unknown" msgid="3237922751873109097">"未知"</string>
-    <string name="voicemail" msgid="2125552157407909509">"语音邮件"</string>
+    <string name="voicemail" msgid="2125552157407909509">"语音信息"</string>
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"正在连接…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"正在拨号…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"呼叫等待"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"通话已结束"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"保持"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"通话已结束"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"已连接"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"正在响铃…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"正在断开连接…"</string>
diff --git a/car-telephony-common/res/values-zh-rHK/strings.xml b/car-telephony-common/res/values-zh-rHK/strings.xml
index c92766e..6872577 100644
--- a/car-telephony-common/res/values-zh-rHK/strings.xml
+++ b/car-telephony-common/res/values-zh-rHK/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"正在連接…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"正在撥號…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"保留通話"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"通話已結束"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"保留通話"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"通話已結束"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"已連接"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"正在發出鈴聲…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"正在解除連接…"</string>
diff --git a/car-telephony-common/res/values-zh-rTW/strings.xml b/car-telephony-common/res/values-zh-rTW/strings.xml
index decc1db..41928bb 100644
--- a/car-telephony-common/res/values-zh-rTW/strings.xml
+++ b/car-telephony-common/res/values-zh-rTW/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"連線中…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"撥號中…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"保留中"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"通話結束"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"保留中"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"通話已結束"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"已連線"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"鈴響中…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"正在中斷連線…"</string>
diff --git a/car-telephony-common/res/values-zu/strings.xml b/car-telephony-common/res/values-zu/strings.xml
index 0978e00..fa90708 100644
--- a/car-telephony-common/res/values-zu/strings.xml
+++ b/car-telephony-common/res/values-zu/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Iyaxhuma…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Iyadayela…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"Ibanjiwe"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Ikholi iqediwe"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Ibambile"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Ikholi iqediwe"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Ixhunyiwe"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Iyakhala…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Iyanqamula…"</string>
diff --git a/car-telephony-common/res/values/strings.xml b/car-telephony-common/res/values/strings.xml
index 24a3300..89ec0f1 100644
--- a/car-telephony-common/res/values/strings.xml
+++ b/car-telephony-common/res/values/strings.xml
@@ -32,19 +32,13 @@
     <!-- Status label for phone state. &#8230; is an ellipsis. [CHAR LIMIT=25] -->
     <string name="call_state_dialing">Dialing&#8230;</string>
     <!-- Status label for phone state [CHAR LIMIT=25] -->
-    <string name="call_state_hold">On Hold</string>
+    <string name="call_state_hold">On hold</string>
     <!-- Status label for phone state [CHAR LIMIT=25] -->
-    <string name="call_state_call_ended">Call Ended</string>
+    <string name="call_state_call_ended">Call ended</string>
     <!-- Status label for phone state [CHAR LIMIT=25] -->
     <string name="call_state_call_active">Connected</string>
     <!-- Status label for phone state. &#8230; is an ellipsis. [CHAR LIMIT=25] -->
     <string name="call_state_call_ringing">Ringing&#8230;</string>
     <!-- Status label for phone state. &#8230; is an ellipsis. [CHAR LIMIT=25] -->
     <string name="call_state_call_ending">Disconnecting&#8230;</string>
-
-    <!-- String format used to format a address Uri. -->
-    <string name="address_uri_format" translatable="false">geo:0,0?q=%s</string>
-    <!-- String format used to format a navigation Uri. -->
-    <string name="navigation_uri_format" translatable="false">https://maps.google.com/maps?daddr=%s&amp;nav=1</string>
-
 </resources>
\ No newline at end of file
diff --git a/car-telephony-common/src/com/android/car/telephony/common/AsyncQueryLiveData.java b/car-telephony-common/src/com/android/car/telephony/common/AsyncQueryLiveData.java
index 69f00d5..ecacb51 100644
--- a/car-telephony-common/src/com/android/car/telephony/common/AsyncQueryLiveData.java
+++ b/car-telephony-common/src/com/android/car/telephony/common/AsyncQueryLiveData.java
@@ -19,13 +19,14 @@
 import android.content.ContentResolver;
 import android.content.Context;
 import android.database.Cursor;
-import android.util.Log;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.WorkerThread;
 import androidx.lifecycle.LiveData;
 
+import com.android.car.apps.common.log.L;
+
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Future;
 
@@ -78,7 +79,7 @@
     protected abstract T convertToEntity(@NonNull Cursor cursor);
 
     private void onCursorLoaded(Cursor cursor) {
-        Log.d(TAG, "onCursorLoaded: " + this);
+        L.d(TAG, "onCursorLoaded: " + this);
         if (mCurrentCursorRunnable != null) {
             mCurrentCursorRunnable.closeCursorIfNecessary();
             mCurrentRunnableFuture.cancel(false);
diff --git a/car-telephony-common/src/com/android/car/telephony/common/CallDetail.java b/car-telephony-common/src/com/android/car/telephony/common/CallDetail.java
index 83f3291..828b7f7 100644
--- a/car-telephony-common/src/com/android/car/telephony/common/CallDetail.java
+++ b/car-telephony-common/src/com/android/car/telephony/common/CallDetail.java
@@ -32,13 +32,16 @@
     private final CharSequence mDisconnectCause;
     private final Uri mGatewayInfoOriginalAddress;
     private final long mConnectTimeMillis;
+    private final boolean mIsConference;
 
     private CallDetail(String number, CharSequence disconnectCause,
-                       Uri gatewayInfoOriginalAddress, long connectTimeMillis) {
+                       Uri gatewayInfoOriginalAddress, long connectTimeMillis,
+                       boolean isConference) {
         mNumber = number;
         mDisconnectCause = disconnectCause;
         mGatewayInfoOriginalAddress = gatewayInfoOriginalAddress;
         this.mConnectTimeMillis = connectTimeMillis;
+        mIsConference = isConference;
     }
 
     /**
@@ -46,7 +49,8 @@
      */
     public static CallDetail fromTelecomCallDetail(@Nullable Call.Details callDetail) {
         return new CallDetail(getNumber(callDetail), getDisconnectCause(callDetail),
-                getGatewayInfoOriginalAddress(callDetail), getConnectTimeMillis(callDetail));
+                getGatewayInfoOriginalAddress(callDetail), getConnectTimeMillis(callDetail),
+                callDetail.hasProperty(Call.Details.PROPERTY_CONFERENCE));
     }
 
     /**
@@ -80,6 +84,13 @@
         return mConnectTimeMillis;
     }
 
+    /**
+     * Returns whether the call is a conference.
+     */
+    public boolean isConference() {
+        return mIsConference;
+    }
+
     private static String getNumber(Call.Details callDetail) {
         String number = "";
         if (callDetail == null) {
diff --git a/car-telephony-common/src/com/android/car/telephony/common/Contact.java b/car-telephony-common/src/com/android/car/telephony/common/Contact.java
index 42a1b9a..e700632 100644
--- a/car-telephony-common/src/com/android/car/telephony/common/Contact.java
+++ b/car-telephony-common/src/com/android/car/telephony/common/Contact.java
@@ -24,11 +24,12 @@
 import android.os.Parcelable;
 import android.provider.ContactsContract;
 import android.text.TextUtils;
-import android.util.Log;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 
+import com.android.car.apps.common.log.L;
+
 import java.util.ArrayList;
 import java.util.List;
 
@@ -233,7 +234,7 @@
 
         if (!TextUtils.equals(accountName, contact.mAccountName)
                 || !TextUtils.equals(lookupKey, contact.mLookupKey)) {
-            Log.w(TAG, "A wrong contact is passed in. A new contact will be created.");
+            L.w(TAG, "A wrong contact is passed in. A new contact will be created.");
             contact = new Contact();
             contact.loadBasicInfo(cursor);
         }
@@ -253,8 +254,7 @@
                 contact.addPostalAddress(cursor);
                 break;
             default:
-                Log.d(TAG,
-                        String.format("This mimetype %s will not be loaded right now.", mimeType));
+                L.d(TAG, String.format("This mimetype %s will not be loaded right now.", mimeType));
         }
 
         return contact;
diff --git a/car-telephony-common/src/com/android/car/telephony/common/InMemoryPhoneBook.java b/car-telephony-common/src/com/android/car/telephony/common/InMemoryPhoneBook.java
index 960714a..5d8e3eb 100644
--- a/car-telephony-common/src/com/android/car/telephony/common/InMemoryPhoneBook.java
+++ b/car-telephony-common/src/com/android/car/telephony/common/InMemoryPhoneBook.java
@@ -20,13 +20,14 @@
 import android.database.Cursor;
 import android.provider.ContactsContract;
 import android.text.TextUtils;
-import android.util.Log;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.lifecycle.LiveData;
 import androidx.lifecycle.Observer;
 
+import com.android.car.apps.common.log.L;
+
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
@@ -146,13 +147,13 @@
      */
     @Nullable
     public Contact lookupContactEntry(String phoneNumber) {
-        Log.v(TAG, String.format("lookupContactEntry: %s", phoneNumber));
+        L.v(TAG, String.format("lookupContactEntry: %s", TelecomUtils.piiLog(phoneNumber)));
         if (!isLoaded()) {
-            Log.w(TAG, "looking up a contact while loading.");
+            L.w(TAG, "looking up a contact while loading.");
         }
 
         if (TextUtils.isEmpty(phoneNumber)) {
-            Log.w(TAG, "looking up an empty phone number.");
+            L.w(TAG, "looking up an empty phone number.");
             return null;
         }
 
@@ -168,10 +169,10 @@
     @Nullable
     public Contact lookupContactByKey(String lookupKey, @Nullable String accountName) {
         if (!isLoaded()) {
-            Log.w(TAG, "looking up a contact while loading.");
+            L.w(TAG, "looking up a contact while loading.");
         }
         if (TextUtils.isEmpty(lookupKey)) {
-            Log.w(TAG, "looking up an empty lookup key.");
+            L.w(TAG, "looking up an empty lookup key.");
             return null;
         }
         if (mLookupKeyContactMap.containsKey(accountName)) {
@@ -189,11 +190,11 @@
     @NonNull
     public List<Contact> lookupContactByKey(String lookupKey) {
         if (!isLoaded()) {
-            Log.w(TAG, "looking up a contact while loading.");
+            L.w(TAG, "looking up a contact while loading.");
         }
 
         if (TextUtils.isEmpty(lookupKey)) {
-            Log.w(TAG, "looking up an empty lookup key.");
+            L.w(TAG, "looking up an empty lookup key.");
             return Collections.emptyList();
         }
         List<Contact> results = new ArrayList<>();
@@ -244,7 +245,7 @@
 
     @Override
     public void onChanged(List<Contact> contacts) {
-        Log.d(TAG, "Contacts loaded:" + (contacts == null ? 0 : contacts.size()));
+        L.d(TAG, "Contacts loaded:" + (contacts == null ? 0 : contacts.size()));
         mIsLoaded = true;
     }
 }
diff --git a/car-telephony-common/src/com/android/car/telephony/common/ObservableAsyncQuery.java b/car-telephony-common/src/com/android/car/telephony/common/ObservableAsyncQuery.java
index de0242b..b3c1fb1 100644
--- a/car-telephony-common/src/com/android/car/telephony/common/ObservableAsyncQuery.java
+++ b/car-telephony-common/src/com/android/car/telephony/common/ObservableAsyncQuery.java
@@ -20,12 +20,13 @@
 import android.content.ContentResolver;
 import android.database.ContentObserver;
 import android.database.Cursor;
-import android.util.Log;
 
 import androidx.annotation.MainThread;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 
+import com.android.car.apps.common.log.L;
+
 /**
  * Asynchronously queries data and observes them. A new query will be triggered automatically if
  * data set have changed.
@@ -80,7 +81,7 @@
      */
     @MainThread
     public void startQuery() {
-        Log.d(TAG, "startQuery");
+        L.d(TAG, "startQuery");
         mAsyncQueryHandler.cancelOperation(mToken); // Cancel the query task.
 
         mToken++;
@@ -106,7 +107,7 @@
      */
     @MainThread
     public void stopQuery() {
-        Log.d(TAG, "stopQuery");
+        L.d(TAG, "stopQuery");
         mIsActive = false;
         cleanupCursorIfNecessary();
         mAsyncQueryHandler.cancelOperation(mToken); // Cancel the query task.
@@ -116,7 +117,7 @@
         if (!mIsActive) {
             return;
         }
-        Log.d(TAG, "onQueryComplete");
+        L.d(TAG, "onQueryComplete");
         cleanupCursorIfNecessary();
         if (cursor != null) {
             cursor.registerContentObserver(mContentObserver);
diff --git a/car-telephony-common/src/com/android/car/telephony/common/PhoneCallLog.java b/car-telephony-common/src/com/android/car/telephony/common/PhoneCallLog.java
index d90e2ba..815e3d5 100644
--- a/car-telephony-common/src/com/android/car/telephony/common/PhoneCallLog.java
+++ b/car-telephony-common/src/com/android/car/telephony/common/PhoneCallLog.java
@@ -19,7 +19,6 @@
 import android.content.Context;
 import android.database.Cursor;
 import android.provider.CallLog;
-import android.telecom.Log;
 import android.text.TextUtils;
 
 import androidx.annotation.NonNull;
@@ -161,7 +160,7 @@
     public String toString() {
         StringBuilder sb = new StringBuilder();
         sb.append("PhoneNumber: ");
-        sb.append(Log.pii(mPhoneNumberString));
+        sb.append(TelecomUtils.piiLog(mPhoneNumberString));
         sb.append(" CallLog: ");
         sb.append(mCallRecords.size());
         return sb.toString();
diff --git a/car-telephony-common/src/com/android/car/telephony/common/PostalAddress.java b/car-telephony-common/src/com/android/car/telephony/common/PostalAddress.java
index cb7c774..a3d4862 100644
--- a/car-telephony-common/src/com/android/car/telephony/common/PostalAddress.java
+++ b/car-telephony-common/src/com/android/car/telephony/common/PostalAddress.java
@@ -16,16 +16,18 @@
 
 package com.android.car.telephony.common;
 
+import android.content.Intent;
 import android.content.res.Resources;
 import android.database.Cursor;
-import android.net.Uri;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.provider.ContactsContract;
-import android.util.Log;
 
 import androidx.annotation.Nullable;
 
+import com.android.car.apps.common.NavigationUtils;
+import com.android.car.apps.common.log.L;
+
 /**
  * Encapsulates data about an address entry. Typically loaded from the local Address store.
  */
@@ -106,21 +108,17 @@
     /**
      * Returns the address Uri for {@link #mFormattedAddress}.
      */
-    public Uri getAddressUri(Resources res) {
-        String address = String.format(res.getString(R.string.address_uri_format),
-                Uri.encode(mFormattedAddress));
-        Log.d(TAG, "The address is: " + address);
-        return Uri.parse(address);
+    public Intent getAddressIntent(Resources res) {
+        L.d(TAG, "The address is: " + TelecomUtils.piiLog(mFormattedAddress));
+        return NavigationUtils.getViewAddressIntent(res, mFormattedAddress);
     }
 
     /**
      * Returns the navigation Uri for {@link #mFormattedAddress}.
      */
-    public Uri getNavigationUri(Resources res) {
-        String address = String.format(res.getString(R.string.navigation_uri_format),
-                Uri.encode(mFormattedAddress));
-        Log.d(TAG, "The address is: " + address);
-        return Uri.parse(address);
+    public Intent getNavigationIntent(Resources res) {
+        L.d(TAG, "The address is: " + TelecomUtils.piiLog(mFormattedAddress));
+        return NavigationUtils.getNavigationIntent(res, mFormattedAddress);
     }
 
     @Override
diff --git a/car-telephony-common/src/com/android/car/telephony/common/TelecomUtils.java b/car-telephony-common/src/com/android/car/telephony/common/TelecomUtils.java
index 090f223..0ad3d57 100644
--- a/car-telephony-common/src/com/android/car/telephony/common/TelecomUtils.java
+++ b/car-telephony-common/src/com/android/car/telephony/common/TelecomUtils.java
@@ -38,8 +38,9 @@
 import android.telecom.Call;
 import android.telephony.PhoneNumberUtils;
 import android.telephony.TelephonyManager;
+import android.text.BidiFormatter;
+import android.text.TextDirectionHeuristics;
 import android.text.TextUtils;
-import android.util.Log;
 import android.widget.ImageView;
 
 import androidx.annotation.Nullable;
@@ -48,6 +49,7 @@
 import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory;
 
 import com.android.car.apps.common.LetterTileDrawable;
+import com.android.car.apps.common.log.L;
 
 import com.bumptech.glide.Glide;
 import com.bumptech.glide.request.RequestOptions;
@@ -65,6 +67,8 @@
  */
 public class TelecomUtils {
     private static final String TAG = "CD.TelecomUtils";
+    private static final int PII_STRING_LENGTH = 4;
+    private static final String COUNTRY_US = "US";
 
     private static String sVoicemailNumber;
     private static TelephonyManager sTelephonyManager;
@@ -113,24 +117,20 @@
      * Format a number as a phone number.
      */
     public static String getFormattedNumber(Context context, String number) {
-        if (Log.isLoggable(TAG, Log.DEBUG)) {
-            Log.d(TAG, "getFormattedNumber: " + number);
-        }
+        L.d(TAG, "getFormattedNumber: " + piiLog(number));
         if (number == null) {
             return "";
         }
 
-        String countryIso = getCurrentCountryIso(context);
-        if (Log.isLoggable(TAG, Log.DEBUG)) {
-            Log.d(TAG, "PhoneNumberUtils.formatNumberToE16, number: "
-                    + number + ", country: " + countryIso);
-        }
+        String countryIso = getCurrentCountryIsoFromLocale(context);
+        L.d(TAG, "PhoneNumberUtils.formatNumberToE16, number: "
+                    + piiLog(number) + ", country: " + countryIso);
+
         String e164 = PhoneNumberUtils.formatNumberToE164(number, countryIso);
         String formattedNumber = PhoneNumberUtils.formatNumber(number, e164, countryIso);
         formattedNumber = TextUtils.isEmpty(formattedNumber) ? number : formattedNumber;
-        if (Log.isLoggable(TAG, Log.DEBUG)) {
-            Log.d(TAG, "getFormattedNumber, result: " + formattedNumber);
-        }
+        L.d(TAG, "getFormattedNumber, result: " + piiLog(formattedNumber));
+
         return formattedNumber;
     }
 
@@ -146,17 +146,17 @@
             if (country != null) {
                 countryIso = country.getCountryIso();
             } else {
-                Log.e(TAG, "CountryDetector.detectCountry() returned null.");
+                L.e(TAG, "CountryDetector.detectCountry() returned null.");
             }
         }
         if (countryIso == null) {
             countryIso = locale.getCountry();
-            Log.w(TAG, "No CountryDetector; falling back to countryIso based on locale: "
+            L.w(TAG, "No CountryDetector; falling back to countryIso based on locale: "
                     + countryIso);
         }
         if (countryIso == null || countryIso.length() != 2) {
-            Log.w(TAG, "Invalid locale, falling back to US");
-            countryIso = "US";
+            L.w(TAG, "Invalid locale, falling back to US");
+            countryIso = COUNTRY_US;
         }
         return countryIso;
     }
@@ -165,6 +165,18 @@
         return getCurrentCountryIso(context, Locale.getDefault());
     }
 
+    private static String getCurrentCountryIsoFromLocale(Context context) {
+        String countryIso;
+        countryIso = context.getResources().getConfiguration().getLocales().get(0).getCountry();
+
+        if (countryIso == null) {
+            L.w(TAG, "Invalid locale, falling back to US");
+            countryIso = COUNTRY_US;
+        }
+
+        return countryIso;
+    }
+
     /**
      * Creates a new instance of {@link Phonenumber.PhoneNumber} base on the given number and sim
      * card country code. Returns {@code null} if the number in an invalid number.
@@ -486,7 +498,7 @@
     public static void markCallLogAsRead(Context context, String phoneNumberString) {
         if (context.checkSelfPermission(Manifest.permission.WRITE_CALL_LOG)
                 != PackageManager.PERMISSION_GRANTED) {
-            Log.w(TAG, "Missing WRITE_CALL_LOG permission; not marking missed calls as read.");
+            L.w(TAG, "Missing WRITE_CALL_LOG permission; not marking missed calls as read.");
             return;
         }
         ContentValues contentValues = new ContentValues();
@@ -516,7 +528,7 @@
                             where.toString(),
                             selectionArgs.toArray(selectionArgsArray));
         } catch (IllegalArgumentException e) {
-            Log.e(TAG, "markCallLogAsRead failed", e);
+            L.e(TAG, "markCallLogAsRead failed", e);
         }
     }
 
@@ -550,7 +562,7 @@
         RoundedBitmapDrawable roundedBitmapDrawable = RoundedBitmapDrawableFactory.create(
                 context.getResources(), letterTileDrawable.toBitmap(avatarSize));
         return createFromRoundedBitmapDrawable(roundedBitmapDrawable, avatarSize,
-            cornerRadiusPercent);
+                cornerRadiusPercent);
     }
 
     /** Creates an Icon based on the given roundedBitmapDrawable. **/
@@ -567,6 +579,13 @@
         return Icon.createWithBitmap(result);
     }
 
+    /**
+     * Sets the direction of a string, used for displaying phone numbers.
+     */
+    public static String getBidiWrappedNumber(String string) {
+        return BidiFormatter.getInstance().unicodeWrap(string, TextDirectionHeuristics.LTR);
+    }
+
     private static Uri makeResourceUri(Context context, int resourceId) {
         return new Uri.Builder()
                 .scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
@@ -575,4 +594,13 @@
                 .build();
     }
 
+    /**
+     * This is a workaround for Log.Pii(). It will only show the last {@link #PII_STRING_LENGTH}
+     * characters.
+     */
+    public static String piiLog(Object pii) {
+        String piiString = String.valueOf(pii);
+        return piiString.length() >= PII_STRING_LENGTH ? "*" + piiString.substring(
+                piiString.length() - PII_STRING_LENGTH) : piiString;
+    }
 }
diff --git a/car-telephony-common/tests/Android.mk b/car-telephony-common/tests/Android.mk
deleted file mode 100644
index 0903c90..0000000
--- a/car-telephony-common/tests/Android.mk
+++ /dev/null
@@ -1,19 +0,0 @@
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-# Include all makefiles in subdirectories
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/car-telephony-common/tests/robotests/Android.bp b/car-telephony-common/tests/robotests/Android.bp
new file mode 100644
index 0000000..57bf759
--- /dev/null
+++ b/car-telephony-common/tests/robotests/Android.bp
@@ -0,0 +1,27 @@
+//###########################################################
+// car-telephony-common just for Robolectric test target.   #
+//###########################################################
+android_app {
+    name: "CarTelephonyCommonForTesting",
+
+    platform_apis: true,
+
+    libs: ["android.car"],
+
+    privileged: true,
+
+    static_libs: ["car-telephony-common"],
+}
+
+//############################################################
+// car-telephony-common Robolectric test target.             #
+//############################################################
+android_robolectric_test {
+    name: "CarTelephonyCommonRoboTests",
+
+    srcs: ["src/**/*.java"],
+
+    java_resource_dirs: ["config"],
+
+    instrumentation_for: "CarTelephonyCommonForTesting",
+}
diff --git a/car-telephony-common/tests/robotests/Android.mk b/car-telephony-common/tests/robotests/Android.mk
deleted file mode 100644
index e67530d..0000000
--- a/car-telephony-common/tests/robotests/Android.mk
+++ /dev/null
@@ -1,68 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-
-############################################################
-# car-telephony-common just for Robolectric test target.   #
-############################################################
-include $(CLEAR_VARS)
-
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-
-LOCAL_PACKAGE_NAME := CarTelephonyCommonForTesting
-LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_USE_AAPT2 := true
-
-LOCAL_JAVA_LIBRARIES += android.car
-
-LOCAL_PRIVILEGED_MODULE := true
-
-LOCAL_STATIC_ANDROID_LIBRARIES := car-telephony-common
-
-include $(BUILD_PACKAGE)
-
-#############################################################
-# car-telephony-common Robolectric test target.             #
-#############################################################
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := CarTelephonyCommonRoboTests
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_JAVA_RESOURCE_DIRS := config
-
-# Include the testing libraries
-LOCAL_JAVA_LIBRARIES := \
-    robolectric_android-all-stub \
-    Robolectric_all-target \
-    mockito-robolectric-prebuilt \
-    truth-prebuilt
-
-LOCAL_INSTRUMENTATION_FOR := CarTelephonyCommonForTesting
-
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
-##################################################################
-# car-telephony-common runner target to run the previous target. #
-##################################################################
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := RunCarTelephonyCommonRoboTests
-
-LOCAL_JAVA_LIBRARIES := \
-    CarTelephonyCommonRoboTests \
-    robolectric_android-all-stub \
-    Robolectric_all-target \
-    mockito-robolectric-prebuilt \
-    truth-prebuilt
-
-
-LOCAL_TEST_PACKAGE := CarTelephonyCommonForTesting
-
-LOCAL_INSTRUMENT_SOURCE_DIRS := $(dir $(LOCAL_PATH))../src
-
-include external/robolectric-shadows/run_robotests.mk
diff --git a/car-telephony-common/tests/robotests/config/robolectric.properties b/car-telephony-common/tests/robotests/config/robolectric.properties
index 9228597..fc4f8ca 100644
--- a/car-telephony-common/tests/robotests/config/robolectric.properties
+++ b/car-telephony-common/tests/robotests/config/robolectric.properties
@@ -11,5 +11,4 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
-manifest=packages/apps/Car/libs/car-telephony-common/tests/robotests/AndroidManifest.xml
 sdk=NEWEST_SDK
diff --git a/car-theme-lib/Android.bp b/car-theme-lib/Android.bp
index 990148c..30c780c 100644
--- a/car-theme-lib/Android.bp
+++ b/car-theme-lib/Android.bp
@@ -15,7 +15,7 @@
 //
 
 android_library {
-    name: "car-theme-lib-bp",
+    name: "car-theme-lib",
 
     srcs: ["src/**/*.java"],
 
@@ -26,5 +26,4 @@
     optimize: {
         enabled: false,
     },
-
 }
diff --git a/car-theme-lib/Android.mk b/car-theme-lib/Android.mk
deleted file mode 100644
index c22048c..0000000
--- a/car-theme-lib/Android.mk
+++ /dev/null
@@ -1,30 +0,0 @@
-#
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_USE_AAPT2 := true
-
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-
-LOCAL_MODULE := car-theme-lib
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/car-ui-lib/Android.bp b/car-ui-lib/Android.bp
index f433c4c..3506a3e 100644
--- a/car-ui-lib/Android.bp
+++ b/car-ui-lib/Android.bp
@@ -15,26 +15,39 @@
 // limitations under the License.
 
 android_library {
-
-    name: "car-ui-lib-bp",
-
+    name: "car-ui-lib",
+    sdk_version: "system_current",
+    min_sdk_version: "28",
     srcs: ["src/**/*.java"],
-
     resource_dirs: ["res"],
-
     optimize: {
         enabled: false,
     },
-
-    libs: ["android.car"],
-
+    libs: ["android.car-stubs"],
     static_libs: [
         "androidx.annotation_annotation",
         "androidx.appcompat_appcompat",
-	"androidx.asynclayoutinflater_asynclayoutinflater",
         "androidx-constraintlayout_constraintlayout",
         "androidx.preference_preference",
         "androidx.recyclerview_recyclerview",
         "androidx-constraintlayout_constraintlayout-solver",
+        "androidx.asynclayoutinflater_asynclayoutinflater",
     ],
 }
+
+android_library {
+    name: "car-ui-lib-testing-support",
+    sdk_version: "system_current",
+    min_sdk_version: "28",
+    srcs: [
+        "tests/baselayouttests/src/**/*.java",
+    ],
+    optimize: {
+        enabled: false,
+    },
+    libs: ["android.car-stubs"],
+    static_libs: [
+        "car-ui-lib",
+        "Robolectric_all-target",
+    ],
+}
\ No newline at end of file
diff --git a/car-ui-lib/Android.mk b/car-ui-lib/Android.mk
index c67ea5c..1df872c 100644
--- a/car-ui-lib/Android.mk
+++ b/car-ui-lib/Android.mk
@@ -30,45 +30,9 @@
 #
 # Your AndroidManifest must use {{TARGET_PACKAGE_NAME}} and {{RRO_PACKAGE_NAME}}
 # tags, which will be replaced accordingly during build.
-
-CAR_UI_GENERATE_RRO_SET := $(call my-dir)/generate_rros.mk
-
-# Build car-ui library
-
 LOCAL_PATH:= $(call my-dir)
 
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-
-LOCAL_MODULE := car-ui-lib
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_PRIVILEGED_MODULE := true
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-LOCAL_USE_AAPT2 := true
-
-LOCAL_JAVA_LIBRARIES += android.car
-
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-
-LOCAL_STATIC_ANDROID_LIBRARIES += \
-    androidx.annotation_annotation \
-    androidx.appcompat_appcompat \
-    androidx-constraintlayout_constraintlayout \
-    androidx.preference_preference \
-    androidx.recyclerview_recyclerview \
-    androidx.asynclayoutinflater_asynclayoutinflater \
-
-LOCAL_STATIC_JAVA_LIBRARIES += \
-    androidx-constraintlayout_constraintlayout-solver \
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
+CAR_UI_GENERATE_RRO_SET := $(call my-dir)/generate_rros.mk
 
 ifeq (,$(ONE_SHOT_MAKEFILE))
     include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/car-ui-lib/AndroidManifest-gradle.xml b/car-ui-lib/AndroidManifest-gradle.xml
index b6e8ee6..36ffbb8 100644
--- a/car-ui-lib/AndroidManifest-gradle.xml
+++ b/car-ui-lib/AndroidManifest-gradle.xml
@@ -17,4 +17,10 @@
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
           package="com.android.car.ui">
+    <application>
+        <provider
+            android:name="com.android.car.ui.core.CarUiInstaller"
+            android:authorities="${applicationId}.CarUiInstaller"
+            android:exported="false"/>
+    </application>
 </manifest>
diff --git a/car-ui-lib/AndroidManifest.xml b/car-ui-lib/AndroidManifest.xml
index 038ee67..5136dc2 100644
--- a/car-ui-lib/AndroidManifest.xml
+++ b/car-ui-lib/AndroidManifest.xml
@@ -17,7 +17,16 @@
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
           package="com.android.car.ui">
-  <uses-sdk
-      android:minSdkVersion="14"
-      android:targetSdkVersion="28" />
+    <uses-sdk
+        android:minSdkVersion="14"
+        android:targetSdkVersion="28" />
+
+    <application>
+        <provider
+            android:name="com.android.car.ui.core.CarUiInstaller"
+            android:authorities="${applicationId}.CarUiInstaller"
+            android:directBootAware="true"
+            android:exported="false"
+            android:process="@string/car_ui_installer_process_name"/>
+    </application>
 </manifest>
diff --git a/car-ui-lib/build.gradle b/car-ui-lib/build.gradle
index 7775382..c230345 100644
--- a/car-ui-lib/build.gradle
+++ b/car-ui-lib/build.gradle
@@ -23,7 +23,7 @@
 
     }
     dependencies {
-        classpath 'com.android.tools.build:gradle:3.5.1'
+        classpath 'com.android.tools.build:gradle:3.6.1'
 
         // NOTE: Do not place your application dependencies here; they belong
         // in the individual module build.gradle files
@@ -46,11 +46,11 @@
 apply plugin: 'com.android.library'
 
 android {
-    compileSdkVersion 28
+    compileSdkVersion 29
 
     defaultConfig {
         minSdkVersion 28
-        targetSdkVersion 28
+        targetSdkVersion 29
         versionCode 1
         versionName "1.0"
     }
@@ -75,6 +75,8 @@
     api 'androidx.constraintlayout:constraintlayout:1.1.3'
     api 'androidx.preference:preference:1.1.0'
     api 'androidx.recyclerview:recyclerview:1.0.0'
+    api 'androidx.core:core:1.2.0'
+    implementation 'com.android.support:support-annotations:28.0.0'
 
     // This is the gradle equivalent of the libs: ["android.car"] in our Android.bp
     implementation files('../../../../../out/target/common/obj/JAVA_LIBRARIES/android.car_intermediates/classes.jar')
diff --git a/car-ui-lib/findviewbyid-preupload-hook.sh b/car-ui-lib/findviewbyid-preupload-hook.sh
index 4969536..6478802 100755
--- a/car-ui-lib/findviewbyid-preupload-hook.sh
+++ b/car-ui-lib/findviewbyid-preupload-hook.sh
@@ -1,11 +1,7 @@
 #!/bin/bash
 
-if grep -rq "findViewById\|requireViewById" car-ui-lib/src/com/android/car/ui/toolbar/; then
-    grep -r "findViewById\|requireViewById" car-ui-lib/src/com/android/car/ui/toolbar/;
+if grep -rq --exclude=CarUiUtils.java "findViewById\|requireViewById" car-ui-lib/src/com/android/car/ui/; then
+    grep -r --exclude-CarUiUtils.java "findViewById\|requireViewById" car-ui-lib/src/com/android/car/ui/;
     echo "Illegal use of findViewById or requireViewById in car-ui-lib. Please consider using CarUiUtils#findViewByRefId or CarUiUtils#requireViewByRefId" && false;
 fi
 
-if grep -rq "findViewById\|requireViewById" car-ui-lib/src/com/android/car/ui/recyclerview/; then
-    grep -r "findViewById\|requireViewById" car-ui-lib/src/com/android/car/ui/recyclerview/;
-    echo "Illegal use of findViewById or requireViewById in car-ui-lib. Please consider using CarUiUtils#findViewByRefId or CarUiUtils#requireViewByRefId" && false;
-fi
diff --git a/car-ui-lib/referencedesign/Android.mk b/car-ui-lib/referencedesign/Android.mk
new file mode 100644
index 0000000..7da04dc
--- /dev/null
+++ b/car-ui-lib/referencedesign/Android.mk
@@ -0,0 +1,33 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+CAR_UI_RRO_SET_NAME := googlecarui
+CAR_UI_RESOURCE_DIR := $(LOCAL_PATH)/res
+CAR_UI_RRO_TARGETS := \
+    com.android.car.ui.paintbooth \
+    com.android.car.rotaryplayground \
+    com.android.car.themeplayground \
+    com.android.car.carlauncher \
+    com.android.car.home \
+    com.android.car.media \
+    com.android.car.radio \
+    com.android.car.calendar \
+    com.android.car.companiondevicesupport \
+    com.android.car.systemupdater \
+    com.android.car.dialer \
+    com.android.car.linkviewer \
+    com.android.car.settings \
+    com.android.car.voicecontrol \
+    com.android.car.faceenroll \
+    com.android.permissioncontroller \
+    com.android.settings.intelligence \
+    com.google.android.apps.automotive.inputmethod \
+    com.google.android.apps.automotive.inputmethod.dev \
+    com.google.android.embedded.projection \
+    com.google.android.gms \
+    com.google.android.packageinstaller \
+    com.google.android.carassistant \
+    com.google.android.tts \
+    com.android.vending \
+
+include packages/apps/Car/libs/car-ui-lib/generate_rros.mk
diff --git a/car-ui-lib/referencedesign/AndroidManifest.xml b/car-ui-lib/referencedesign/AndroidManifest.xml
new file mode 100644
index 0000000..a6dbae3
--- /dev/null
+++ b/car-ui-lib/referencedesign/AndroidManifest.xml
@@ -0,0 +1,10 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="{{RRO_PACKAGE_NAME}}">
+    <application android:hasCode="false"/>
+    <overlay android:priority="10"
+        android:targetPackage="{{TARGET_PACKAGE_NAME}}"
+        android:resourcesMap="@xml/overlays"
+        android:isStatic="true"
+        android:requiredSystemPropertyName="ro.build.characteristics"
+        android:requiredSystemPropertyValue="automotive"/>
+</manifest>
diff --git a/car-ui-lib/referencedesign/product.mk b/car-ui-lib/referencedesign/product.mk
new file mode 100644
index 0000000..915f31b
--- /dev/null
+++ b/car-ui-lib/referencedesign/product.mk
@@ -0,0 +1,29 @@
+# Inherit from this product to include the "Reference Design" RROs for CarUi
+
+# Include generated RROs
+PRODUCT_PACKAGES += \
+    googlecarui-com-android-car-ui-paintbooth \
+    googlecarui-com-android-car-rotaryplayground \
+    googlecarui-com-android-car-themeplayground \
+    googlecarui-com-android-car-carlauncher \
+    googlecarui-com-android-car-home \
+    googlecarui-com-android-car-media \
+    googlecarui-com-android-car-radio \
+    googlecarui-com-android-car-calendar \
+    googlecarui-com-android-car-companiondevicesupport \
+    googlecarui-com-android-car-systemupdater \
+    googlecarui-com-android-car-dialer \
+    googlecarui-com-android-car-linkviewer \
+    googlecarui-com-android-car-settings \
+    googlecarui-com-android-car-voicecontrol \
+    googlecarui-com-android-car-faceenroll \
+    googlecarui-com-android-permissioncontroller \
+    googlecarui-com-android-settings-intelligence \
+    googlecarui-com-google-android-apps-automotive-inputmethod \
+    googlecarui-com-google-android-apps-automotive-inputmethod-dev \
+    googlecarui-com-google-android-embedded-projection \
+    googlecarui-com-google-android-gms \
+    googlecarui-com-google-android-packageinstaller \
+    googlecarui-com-google-android-carassistant \
+    googlecarui-com-google-android-tts \
+    googlecarui-com-android-vending \
diff --git a/car-ui-lib/referencedesign/res/color/car_ui_text_color_primary.xml b/car-ui-lib/referencedesign/res/color/car_ui_text_color_primary.xml
new file mode 100644
index 0000000..34033e2
--- /dev/null
+++ b/car-ui-lib/referencedesign/res/color/car_ui_text_color_primary.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2019 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<!-- Copy of ?android:attr/textColorPrimary (frameworks/base/res/res/color/text_color_primary.xml)
+     but with a ux restricted state. -->
+<selector xmlns:android="http://schemas.android.com/apk/res/android"
+          xmlns:app="http://schemas.android.com/apk/res-auto">
+    <item android:state_enabled="false"
+          android:alpha="?android:attr/disabledAlpha"
+          android:color="?android:attr/colorForeground"/>
+    <item android:color="?android:attr/colorForeground"/>
+</selector>
diff --git a/car-ui-lib/referencedesign/res/drawable/car_ui_toolbar_menu_item_divider.xml b/car-ui-lib/referencedesign/res/drawable/car_ui_toolbar_menu_item_divider.xml
new file mode 100644
index 0000000..1e9a5a2
--- /dev/null
+++ b/car-ui-lib/referencedesign/res/drawable/car_ui_toolbar_menu_item_divider.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~
+  ~ Copyright (C) 2019 Google Inc.
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+ -->
+<shape
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+    <size
+        android:width="16dp"/>
+</shape>
diff --git a/car-ui-lib/referencedesign/res/drawable/car_ui_toolbar_menu_item_icon_ripple.xml b/car-ui-lib/referencedesign/res/drawable/car_ui_toolbar_menu_item_icon_ripple.xml
new file mode 100644
index 0000000..03f8d82
--- /dev/null
+++ b/car-ui-lib/referencedesign/res/drawable/car_ui_toolbar_menu_item_icon_ripple.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~
+  ~ Copyright (C) 2019 Google Inc.
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+ -->
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+        android:color="#27ffffff"
+        android:radius="48dp"/>
diff --git a/car-ui-lib/referencedesign/res/layout-ldrtl-port/car_ui_base_layout_toolbar.xml b/car-ui-lib/referencedesign/res/layout-ldrtl-port/car_ui_base_layout_toolbar.xml
new file mode 100644
index 0000000..10c7de6
--- /dev/null
+++ b/car-ui-lib/referencedesign/res/layout-ldrtl-port/car_ui_base_layout_toolbar.xml
@@ -0,0 +1,170 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2020 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<!-- This is for the two-row version of the toolbar -->
+<androidx.constraintlayout.widget.ConstraintLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:tag="carUiToolbar">
+
+    <!-- When not in touch mode, if we clear focus in current window, Android will re-focus the
+         first focusable view in the window automatically. Adding a FocusParkingView to the window
+         can fix this issue, because it can take focus, and it is transparent and its default focus
+         highlight is disabled, so it's invisible to the user no matter whether it's focused or not.
+         -->
+    <com.android.car.ui.FocusParkingView
+        android:layout_width="1dp"
+        android:layout_height="1dp"/>
+
+    <FrameLayout
+        android:id="@+id/content"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <com.android.car.ui.FocusArea
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content">
+        <androidx.constraintlayout.widget.ConstraintLayout
+            android:id="@+id/car_ui_toolbar_background"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:tag="car_ui_top_inset"
+            app:layout_constraintTop_toTopOf="parent">
+            <com.android.car.ui.baselayout.ClickBlockingView
+                android:layout_width="0dp"
+                android:layout_height="0dp"
+                app:layout_constraintLeft_toLeftOf="parent"
+                app:layout_constraintRight_toRightOf="parent"
+                app:layout_constraintTop_toTopOf="parent"
+                app:layout_constraintBottom_toBottomOf="parent"/>
+
+            <androidx.constraintlayout.widget.Guideline
+                android:id="@+id/car_ui_toolbar_row_separator_guideline"
+                android:layout_width="0dp"
+                android:layout_height="0dp"
+                android:orientation="horizontal"
+                app:layout_constraintGuide_begin="96dp"/>
+
+            <FrameLayout
+                android:id="@+id/car_ui_toolbar_nav_icon_container"
+                android:layout_width="112dp"
+                android:layout_height="0dp"
+                app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_row_separator_guideline"
+                app:layout_constraintLeft_toLeftOf="parent"
+                app:layout_constraintTop_toTopOf="parent">
+
+                <ImageView
+                    android:id="@+id/car_ui_toolbar_nav_icon"
+                    android:layout_width="@dimen/car_ui_toolbar_nav_icon_size"
+                    android:layout_height="@dimen/car_ui_toolbar_nav_icon_size"
+                    android:layout_gravity="center"
+                    android:scaleType="fitXY"
+                    android:background="@drawable/car_ui_toolbar_menu_item_icon_ripple"
+                    android:tint="@color/car_ui_text_color_primary"/>
+
+                <ImageView
+                    android:id="@+id/car_ui_toolbar_logo"
+                    android:layout_width="@dimen/car_ui_toolbar_logo_size"
+                    android:layout_height="@dimen/car_ui_toolbar_logo_size"
+                    android:layout_gravity="center"
+                    android:scaleType="fitXY" />
+            </FrameLayout>
+
+            <FrameLayout
+                android:id="@+id/car_ui_toolbar_title_logo_container"
+                android:layout_width="112dp"
+                android:layout_height="0dp"
+                app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_row_separator_guideline"
+                app:layout_constraintRight_toRightOf="parent"
+                app:layout_constraintTop_toTopOf="parent">
+
+                <ImageView
+                    android:id="@+id/car_ui_toolbar_title_logo"
+                    android:layout_width="@dimen/car_ui_toolbar_logo_size"
+                    android:layout_height="@dimen/car_ui_toolbar_logo_size"
+                    android:layout_gravity="center"
+                    android:scaleType="fitXY" />
+            </FrameLayout>
+
+            <LinearLayout android:layout_height="wrap_content"
+                          android:layout_width="0dp"
+                          android:id="@+id/car_ui_toolbar_title_container"
+                          android:orientation="vertical"
+                          android:layout_marginRight="112dp"
+                          app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_row_separator_guideline"
+                          app:layout_constraintLeft_toRightOf="@id/car_ui_toolbar_menu_items_container"
+                          app:layout_constraintRight_toRightOf="parent"
+                          app:layout_constraintTop_toTopOf="parent" >
+                <TextView android:id="@+id/car_ui_toolbar_title"
+                          android:layout_width="wrap_content"
+                          android:layout_height="wrap_content"
+                          android:singleLine="true"
+                          android:textAlignment="viewStart"
+                          android:textAppearance="@style/TextAppearance.CarUi.Widget.Toolbar.Title"/>
+                <TextView android:id="@+id/car_ui_toolbar_subtitle"
+                          android:layout_width="wrap_content"
+                          android:layout_height="wrap_content"
+                          android:visibility="gone"
+                          android:textAlignment="viewStart"
+                          android:textAppearance="?android:attr/textAppearanceSmall"/>
+            </LinearLayout>
+
+            <FrameLayout
+                android:id="@+id/car_ui_toolbar_search_view_container"
+                android:layout_width="0dp"
+                android:layout_height="0dp"
+                app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_row_separator_guideline"
+                app:layout_constraintLeft_toRightOf="@+id/car_ui_toolbar_menu_items_container"
+                app:layout_constraintRight_toRightOf="parent"
+                app:layout_constraintTop_toTopOf="parent" />
+
+            <LinearLayout
+                android:id="@+id/car_ui_toolbar_menu_items_container"
+                android:divider="@drawable/car_ui_toolbar_menu_item_divider"
+                android:showDividers="beginning|middle|end"
+                android:layout_width="wrap_content"
+                android:layout_height="0dp"
+                android:orientation="horizontal"
+                app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_row_separator_guideline"
+                app:layout_constraintLeft_toRightOf="@id/car_ui_toolbar_nav_icon_container"
+                app:layout_constraintTop_toTopOf="parent" />
+
+            <com.android.car.ui.toolbar.TabLayout
+                android:id="@+id/car_ui_toolbar_tabs"
+                android:layout_width="match_parent"
+                android:layout_height="96dp"
+                app:layout_constraintBottom_toBottomOf="parent"
+                app:layout_constraintTop_toBottomOf="@id/car_ui_toolbar_row_separator_guideline" />
+
+            <ProgressBar
+                android:id="@+id/car_ui_toolbar_progress_bar"
+                style="@android:style/Widget.DeviceDefault.ProgressBar.Horizontal"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:indeterminate="true"
+                android:visibility="gone"
+                app:layout_constraintBottom_toBottomOf="parent"
+                app:layout_constraintRight_toRightOf="parent"
+                app:layout_constraintLeft_toLeftOf="parent" />
+
+        </androidx.constraintlayout.widget.ConstraintLayout>
+    </com.android.car.ui.FocusArea>
+
+</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/car-ui-lib/referencedesign/res/layout-ldrtl/car_ui_base_layout_toolbar.xml b/car-ui-lib/referencedesign/res/layout-ldrtl/car_ui_base_layout_toolbar.xml
new file mode 100644
index 0000000..2028530
--- /dev/null
+++ b/car-ui-lib/referencedesign/res/layout-ldrtl/car_ui_base_layout_toolbar.xml
@@ -0,0 +1,166 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2020 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<androidx.constraintlayout.widget.ConstraintLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:tag="CarUiBaseLayoutToolbar">
+
+    <!-- When not in touch mode, if we clear focus in current window, Android will re-focus the
+         first focusable view in the window automatically. Adding a FocusParkingView to the window
+         can fix this issue, because it can take focus, and it is transparent and its default focus
+         highlight is disabled, so it's invisible to the user no matter whether it's focused or not.
+         -->
+    <com.android.car.ui.FocusParkingView
+        android:layout_width="1dp"
+        android:layout_height="1dp"/>
+
+    <FrameLayout
+        android:id="@+id/content"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <com.android.car.ui.FocusArea
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content">
+        <androidx.constraintlayout.widget.ConstraintLayout
+            android:id="@+id/car_ui_toolbar_background"
+            android:layout_width="match_parent"
+            android:layout_height="96dp"
+            android:tag="car_ui_top_inset"
+            app:layout_constraintTop_toTopOf="parent">
+            <com.android.car.ui.baselayout.ClickBlockingView
+                android:layout_width="0dp"
+                android:layout_height="0dp"
+                app:layout_constraintLeft_toLeftOf="parent"
+                app:layout_constraintRight_toRightOf="parent"
+                app:layout_constraintTop_toTopOf="parent"
+                app:layout_constraintBottom_toBottomOf="parent"/>
+
+            <FrameLayout
+                android:id="@+id/car_ui_toolbar_nav_icon_container"
+                android:layout_width="112dp"
+                android:layout_height="0dp"
+                app:layout_constraintBottom_toBottomOf="parent"
+                app:layout_constraintLeft_toLeftOf="parent"
+                app:layout_constraintTop_toTopOf="parent">
+
+                <ImageView
+                    android:id="@+id/car_ui_toolbar_nav_icon"
+                    android:background="@drawable/car_ui_toolbar_menu_item_icon_ripple"
+                    android:tint="@color/car_ui_text_color_primary"
+                    android:layout_width="@dimen/car_ui_toolbar_nav_icon_size"
+                    android:layout_height="@dimen/car_ui_toolbar_nav_icon_size"
+                    android:layout_gravity="center"
+                    android:scaleType="fitXY" />
+
+                <ImageView
+                    android:id="@+id/car_ui_toolbar_logo"
+                    android:layout_width="@dimen/car_ui_toolbar_logo_size"
+                    android:layout_height="@dimen/car_ui_toolbar_logo_size"
+                    android:layout_gravity="center"
+                    android:scaleType="fitXY" />
+            </FrameLayout>
+
+            <FrameLayout
+                android:id="@+id/car_ui_toolbar_title_logo_container"
+                android:layout_width="112dp"
+                android:layout_height="wrap_content"
+                app:layout_constraintBottom_toBottomOf="parent"
+                app:layout_constraintRight_toRightOf="parent"
+                app:layout_constraintTop_toTopOf="parent">
+
+                <ImageView
+                    android:id="@+id/car_ui_toolbar_title_logo"
+                    android:layout_width="@dimen/car_ui_toolbar_logo_size"
+                    android:layout_height="@dimen/car_ui_toolbar_logo_size"
+                    android:layout_gravity="center"
+                    android:scaleType="fitXY" />
+            </FrameLayout>
+
+            <LinearLayout android:layout_height="wrap_content"
+                          android:layout_width="0dp"
+                          android:id="@+id/car_ui_toolbar_title_container"
+                          android:orientation="vertical"
+                          android:layout_marginRight="112dp"
+                          app:layout_constraintBottom_toBottomOf="parent"
+                          app:layout_constraintLeft_toRightOf="@id/car_ui_toolbar_menu_items_container"
+                          app:layout_constraintTop_toTopOf="parent"
+                          app:layout_constraintRight_toRightOf="parent">
+                <TextView android:id="@+id/car_ui_toolbar_title"
+                          android:layout_width="wrap_content"
+                          android:layout_height="wrap_content"
+                          android:singleLine="true"
+                          android:textAlignment="viewStart"
+                          android:textAppearance="@style/TextAppearance.CarUi.Widget.Toolbar.Title"/>
+                <TextView android:id="@+id/car_ui_toolbar_subtitle"
+                          android:layout_width="wrap_content"
+                          android:layout_height="wrap_content"
+                          android:visibility="gone"
+                          android:textAlignment="viewStart"
+                          android:textAppearance="?android:attr/textAppearanceSmall"/>
+            </LinearLayout>
+
+            <com.android.car.ui.toolbar.TabLayout
+                android:id="@+id/car_ui_toolbar_tabs"
+                android:layout_width="wrap_content"
+                android:layout_height="0dp"
+                app:layout_constraintBottom_toBottomOf="parent"
+                app:layout_constraintTop_toTopOf="parent"
+                app:layout_constraintLeft_toRightOf="@+id/car_ui_toolbar_menu_items_container"
+                app:layout_constraintRight_toLeftOf="@+id/car_ui_toolbar_title_logo_container"
+                app:layout_constraintHorizontal_bias="0.0"/>
+
+            <LinearLayout
+                android:id="@+id/car_ui_toolbar_menu_items_container"
+                android:divider="@drawable/car_ui_toolbar_menu_item_divider"
+                android:showDividers="beginning|middle|end"
+                android:layout_width="wrap_content"
+                android:layout_height="0dp"
+                android:orientation="horizontal"
+                app:layout_constraintTop_toTopOf="parent"
+                app:layout_constraintBottom_toBottomOf="parent"
+                app:layout_constraintLeft_toRightOf="@id/car_ui_toolbar_nav_icon_container"/>
+
+            <FrameLayout
+                android:id="@+id/car_ui_toolbar_search_view_container"
+                android:layout_width="0dp"
+                android:layout_height="0dp"
+                app:layout_constraintBottom_toBottomOf="parent"
+                app:layout_constraintLeft_toRightOf="@+id/car_ui_toolbar_menu_items_container"
+                app:layout_constraintRight_toRightOf="parent"
+                app:layout_constraintTop_toTopOf="parent" />
+
+            <ProgressBar
+                android:id="@+id/car_ui_toolbar_progress_bar"
+                style="@android:style/Widget.DeviceDefault.ProgressBar.Horizontal"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:indeterminate="true"
+                android:visibility="gone"
+                app:layout_constraintBottom_toBottomOf="parent"
+                app:layout_constraintLeft_toLeftOf="parent"
+                app:layout_constraintRight_toRightOf="parent" />
+
+        </androidx.constraintlayout.widget.ConstraintLayout>
+    </com.android.car.ui.FocusArea>
+
+</androidx.constraintlayout.widget.ConstraintLayout>
+
diff --git a/car-ui-lib/referencedesign/res/layout-ldrtl/car_ui_toolbar.xml b/car-ui-lib/referencedesign/res/layout-ldrtl/car_ui_toolbar.xml
new file mode 100644
index 0000000..a2d884d
--- /dev/null
+++ b/car-ui-lib/referencedesign/res/layout-ldrtl/car_ui_toolbar.xml
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright 2020, The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<androidx.constraintlayout.widget.ConstraintLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:id="@+id/car_ui_toolbar_background"
+    android:layout_width="match_parent"
+    android:layout_height="96dp">
+
+    <FrameLayout
+        android:id="@+id/car_ui_toolbar_nav_icon_container"
+        android:layout_width="112dp"
+        android:layout_height="0dp"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintTop_toTopOf="parent">
+
+        <ImageView
+            android:id="@+id/car_ui_toolbar_nav_icon"
+            android:background="@drawable/car_ui_toolbar_menu_item_icon_ripple"
+            android:tint="@color/car_ui_text_color_primary"
+            android:layout_width="@dimen/car_ui_toolbar_nav_icon_size"
+            android:layout_height="@dimen/car_ui_toolbar_nav_icon_size"
+            android:layout_gravity="center"
+            android:scaleType="fitXY" />
+
+        <ImageView
+            android:id="@+id/car_ui_toolbar_logo"
+            android:layout_width="@dimen/car_ui_toolbar_logo_size"
+            android:layout_height="@dimen/car_ui_toolbar_logo_size"
+            android:layout_gravity="center"
+            android:scaleType="fitXY" />
+    </FrameLayout>
+
+    <FrameLayout
+        android:id="@+id/car_ui_toolbar_title_logo_container"
+        android:layout_width="112dp"
+        android:layout_height="wrap_content"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintRight_toRightOf="parent"
+        app:layout_constraintTop_toTopOf="parent">
+
+        <ImageView
+            android:id="@+id/car_ui_toolbar_title_logo"
+            android:layout_width="@dimen/car_ui_toolbar_logo_size"
+            android:layout_height="@dimen/car_ui_toolbar_logo_size"
+            android:layout_gravity="center"
+            android:scaleType="fitXY" />
+    </FrameLayout>
+
+    <LinearLayout android:layout_height="wrap_content"
+                  android:layout_width="0dp"
+                  android:id="@+id/car_ui_toolbar_title_container"
+                  android:orientation="vertical"
+                  android:layout_marginRight="112dp"
+                  app:layout_constraintBottom_toBottomOf="parent"
+                  app:layout_constraintLeft_toRightOf="@id/car_ui_toolbar_menu_items_container"
+                  app:layout_constraintTop_toTopOf="parent"
+                  app:layout_constraintRight_toRightOf="parent">
+        <TextView android:id="@+id/car_ui_toolbar_title"
+                  android:layout_width="wrap_content"
+                  android:layout_height="wrap_content"
+                  android:singleLine="true"
+                  android:textAlignment="viewStart"
+                  android:textAppearance="@style/TextAppearance.CarUi.Widget.Toolbar.Title"/>
+        <TextView android:id="@+id/car_ui_toolbar_subtitle"
+                  android:layout_width="wrap_content"
+                  android:layout_height="wrap_content"
+                  android:visibility="gone"
+                  android:textAlignment="viewStart"
+                  android:textAppearance="?android:attr/textAppearanceSmall"/>
+    </LinearLayout>
+
+    <com.android.car.ui.toolbar.TabLayout
+        android:id="@+id/car_ui_toolbar_tabs"
+        android:layout_width="wrap_content"
+        android:layout_height="0dp"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintLeft_toRightOf="@+id/car_ui_toolbar_menu_items_container"
+        app:layout_constraintRight_toLeftOf="@+id/car_ui_toolbar_title_logo_container"
+        app:layout_constraintHorizontal_bias="0.0"/>
+
+    <LinearLayout
+        android:id="@+id/car_ui_toolbar_menu_items_container"
+        android:divider="@drawable/car_ui_toolbar_menu_item_divider"
+        android:showDividers="beginning|middle|end"
+        android:layout_width="wrap_content"
+        android:layout_height="0dp"
+        android:orientation="horizontal"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintLeft_toRightOf="@id/car_ui_toolbar_nav_icon_container"/>
+
+    <FrameLayout
+        android:id="@+id/car_ui_toolbar_search_view_container"
+        android:layout_width="0dp"
+        android:layout_height="0dp"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintLeft_toRightOf="@+id/car_ui_toolbar_menu_items_container"
+        app:layout_constraintRight_toRightOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <ProgressBar
+        android:id="@+id/car_ui_toolbar_progress_bar"
+        style="@android:style/Widget.DeviceDefault.ProgressBar.Horizontal"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:indeterminate="true"
+        android:visibility="gone"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintRight_toRightOf="parent" />
+
+</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/car-ui-lib/referencedesign/res/layout-ldrtl/car_ui_toolbar_two_row.xml b/car-ui-lib/referencedesign/res/layout-ldrtl/car_ui_toolbar_two_row.xml
new file mode 100644
index 0000000..395e48a
--- /dev/null
+++ b/car-ui-lib/referencedesign/res/layout-ldrtl/car_ui_toolbar_two_row.xml
@@ -0,0 +1,133 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright 2020, The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<androidx.constraintlayout.widget.ConstraintLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:id="@+id/car_ui_toolbar_background"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content">
+
+    <androidx.constraintlayout.widget.Guideline
+        android:id="@+id/car_ui_toolbar_row_separator_guideline"
+        android:layout_width="0dp"
+        android:layout_height="0dp"
+        android:orientation="horizontal"
+        app:layout_constraintGuide_begin="96dp"/>
+
+    <FrameLayout
+        android:id="@+id/car_ui_toolbar_nav_icon_container"
+        android:layout_width="112dp"
+        android:layout_height="0dp"
+        app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_row_separator_guideline"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintTop_toTopOf="parent">
+
+        <ImageView
+            android:id="@+id/car_ui_toolbar_nav_icon"
+            android:layout_width="@dimen/car_ui_toolbar_nav_icon_size"
+            android:layout_height="@dimen/car_ui_toolbar_nav_icon_size"
+            android:layout_gravity="center"
+            android:scaleType="fitXY"
+            android:background="@drawable/car_ui_toolbar_menu_item_icon_ripple"
+            android:tint="@color/car_ui_text_color_primary"/>
+
+        <ImageView
+            android:id="@+id/car_ui_toolbar_logo"
+            android:layout_width="@dimen/car_ui_toolbar_logo_size"
+            android:layout_height="@dimen/car_ui_toolbar_logo_size"
+            android:layout_gravity="center"
+            android:scaleType="fitXY" />
+    </FrameLayout>
+
+    <FrameLayout
+        android:id="@+id/car_ui_toolbar_title_logo_container"
+        android:layout_width="112dp"
+        android:layout_height="0dp"
+        app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_row_separator_guideline"
+        app:layout_constraintRight_toRightOf="parent"
+        app:layout_constraintTop_toTopOf="parent">
+
+        <ImageView
+            android:id="@+id/car_ui_toolbar_title_logo"
+            android:layout_width="@dimen/car_ui_toolbar_logo_size"
+            android:layout_height="@dimen/car_ui_toolbar_logo_size"
+            android:layout_gravity="center"
+            android:scaleType="fitXY" />
+    </FrameLayout>
+
+    <LinearLayout android:layout_height="wrap_content"
+                  android:layout_width="0dp"
+                  android:id="@+id/car_ui_toolbar_title_container"
+                  android:orientation="vertical"
+                  android:layout_marginRight="112dp"
+                  app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_row_separator_guideline"
+                  app:layout_constraintLeft_toRightOf="@id/car_ui_toolbar_menu_items_container"
+                  app:layout_constraintRight_toRightOf="parent"
+                  app:layout_constraintTop_toTopOf="parent" >
+        <TextView android:id="@+id/car_ui_toolbar_title"
+                  android:layout_width="wrap_content"
+                  android:layout_height="wrap_content"
+                  android:singleLine="true"
+                  android:textAlignment="viewStart"
+                  android:textAppearance="@style/TextAppearance.CarUi.Widget.Toolbar.Title"/>
+        <TextView android:id="@+id/car_ui_toolbar_subtitle"
+                  android:layout_width="wrap_content"
+                  android:layout_height="wrap_content"
+                  android:visibility="gone"
+                  android:textAlignment="viewStart"
+                  android:textAppearance="?android:attr/textAppearanceSmall"/>
+    </LinearLayout>
+
+    <FrameLayout
+        android:id="@+id/car_ui_toolbar_search_view_container"
+        android:layout_width="0dp"
+        android:layout_height="0dp"
+        app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_row_separator_guideline"
+        app:layout_constraintLeft_toRightOf="@+id/car_ui_toolbar_menu_items_container"
+        app:layout_constraintRight_toRightOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <LinearLayout
+        android:id="@+id/car_ui_toolbar_menu_items_container"
+        android:divider="@drawable/car_ui_toolbar_menu_item_divider"
+        android:showDividers="beginning|middle|end"
+        android:layout_width="wrap_content"
+        android:layout_height="0dp"
+        android:orientation="horizontal"
+        app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_row_separator_guideline"
+        app:layout_constraintLeft_toRightOf="@id/car_ui_toolbar_nav_icon_container"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <com.android.car.ui.toolbar.TabLayout
+        android:id="@+id/car_ui_toolbar_tabs"
+        android:layout_width="match_parent"
+        android:layout_height="96dp"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/car_ui_toolbar_row_separator_guideline" />
+
+    <ProgressBar
+        android:id="@+id/car_ui_toolbar_progress_bar"
+        style="@android:style/Widget.DeviceDefault.ProgressBar.Horizontal"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:indeterminate="true"
+        android:visibility="gone"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent" />
+
+</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/car-ui-lib/referencedesign/res/layout-port/car_ui_base_layout_toolbar.xml b/car-ui-lib/referencedesign/res/layout-port/car_ui_base_layout_toolbar.xml
new file mode 100644
index 0000000..7aaa72d
--- /dev/null
+++ b/car-ui-lib/referencedesign/res/layout-port/car_ui_base_layout_toolbar.xml
@@ -0,0 +1,171 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2020 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<!-- This is for the two-row version of the toolbar -->
+<androidx.constraintlayout.widget.ConstraintLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:tag="CarUiBaseLayoutToolbar">
+
+    <!-- When not in touch mode, if we clear focus in current window, Android will re-focus the
+         first focusable view in the window automatically. Adding a FocusParkingView to the window
+         can fix this issue, because it can take focus, and it is transparent and its default focus
+         highlight is disabled, so it's invisible to the user no matter whether it's focused or not.
+         -->
+    <com.android.car.ui.FocusParkingView
+        android:layout_width="1dp"
+        android:layout_height="1dp"/>
+
+    <FrameLayout
+        android:id="@+id/content"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <com.android.car.ui.FocusArea
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content">
+        <androidx.constraintlayout.widget.ConstraintLayout
+            android:id="@+id/car_ui_toolbar_background"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:tag="car_ui_top_inset"
+            app:layout_constraintTop_toTopOf="parent">
+            <com.android.car.ui.baselayout.ClickBlockingView
+                android:layout_width="0dp"
+                android:layout_height="0dp"
+                app:layout_constraintStart_toStartOf="parent"
+                app:layout_constraintEnd_toEndOf="parent"
+                app:layout_constraintTop_toTopOf="parent"
+                app:layout_constraintBottom_toBottomOf="parent"/>
+
+            <androidx.constraintlayout.widget.Guideline
+                android:id="@+id/car_ui_toolbar_row_separator_guideline"
+                android:layout_width="0dp"
+                android:layout_height="0dp"
+                android:orientation="horizontal"
+                app:layout_constraintGuide_begin="96dp" />
+
+            <FrameLayout
+                android:id="@+id/car_ui_toolbar_nav_icon_container"
+                android:layout_width="112dp"
+                android:layout_height="0dp"
+                app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_row_separator_guideline"
+                app:layout_constraintStart_toStartOf="parent"
+                app:layout_constraintTop_toTopOf="parent">
+
+                <ImageView
+                    android:id="@+id/car_ui_toolbar_nav_icon"
+                    android:layout_width="@dimen/car_ui_toolbar_nav_icon_size"
+                    android:layout_height="@dimen/car_ui_toolbar_nav_icon_size"
+                    android:layout_gravity="center"
+                    android:scaleType="fitXY"
+                    android:background="@drawable/car_ui_toolbar_menu_item_icon_ripple"
+                    android:tint="@color/car_ui_text_color_primary"/>
+
+                <ImageView
+                    android:id="@+id/car_ui_toolbar_logo"
+                    android:layout_width="@dimen/car_ui_toolbar_logo_size"
+                    android:layout_height="@dimen/car_ui_toolbar_logo_size"
+                    android:layout_gravity="center"
+                    android:scaleType="fitXY" />
+            </FrameLayout>
+
+            <FrameLayout
+                android:id="@+id/car_ui_toolbar_title_logo_container"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_row_separator_guideline"
+                app:layout_constraintStart_toEndOf="@id/car_ui_toolbar_nav_icon_container"
+                app:layout_constraintTop_toTopOf="parent">
+
+                <ImageView
+                    android:id="@+id/car_ui_toolbar_title_logo"
+                    android:layout_width="@dimen/car_ui_toolbar_logo_size"
+                    android:layout_height="@dimen/car_ui_toolbar_logo_size"
+                    android:layout_gravity="center"
+                    android:scaleType="fitXY" />
+            </FrameLayout>
+
+            <LinearLayout android:layout_height="wrap_content"
+                          android:layout_width="0dp"
+                          android:id="@+id/car_ui_toolbar_title_container"
+                          android:orientation="vertical"
+                          android:layout_marginStart="16dp"
+                          app:layout_goneMarginStart="0dp"
+                          app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_row_separator_guideline"
+                          app:layout_constraintEnd_toStartOf="@id/car_ui_toolbar_menu_items_container"
+                          app:layout_constraintStart_toEndOf="@id/car_ui_toolbar_title_logo_container"
+                          app:layout_constraintTop_toTopOf="parent" >
+                <TextView android:id="@+id/car_ui_toolbar_title"
+                          android:layout_width="wrap_content"
+                          android:layout_height="wrap_content"
+                          android:singleLine="true"
+                          android:textAlignment="viewStart"
+                          android:textAppearance="@style/TextAppearance.CarUi.Widget.Toolbar.Title"/>
+                <TextView android:id="@+id/car_ui_toolbar_subtitle"
+                          android:layout_width="wrap_content"
+                          android:layout_height="wrap_content"
+                          android:visibility="gone"
+                          android:textAlignment="viewStart"
+                          android:textAppearance="?android:attr/textAppearanceSmall"/>
+            </LinearLayout>
+
+            <FrameLayout
+                android:id="@+id/car_ui_toolbar_search_view_container"
+                android:layout_width="0dp"
+                android:layout_height="0dp"
+                app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_row_separator_guideline"
+                app:layout_constraintEnd_toStartOf="@+id/car_ui_toolbar_menu_items_container"
+                app:layout_constraintStart_toEndOf="@+id/car_ui_toolbar_nav_icon_container"
+                app:layout_constraintTop_toTopOf="parent" />
+
+            <LinearLayout
+                android:id="@+id/car_ui_toolbar_menu_items_container"
+                android:divider="@drawable/car_ui_toolbar_menu_item_divider"
+                android:showDividers="beginning|middle|end"
+                android:layout_width="wrap_content"
+                android:layout_height="0dp"
+                android:orientation="horizontal"
+                app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_row_separator_guideline"
+                app:layout_constraintEnd_toEndOf="parent"
+                app:layout_constraintTop_toTopOf="parent" />
+
+            <com.android.car.ui.toolbar.TabLayout
+                android:id="@+id/car_ui_toolbar_tabs"
+                android:layout_width="match_parent"
+                android:layout_height="96dp"
+                app:layout_constraintBottom_toBottomOf="parent"
+                app:layout_constraintTop_toBottomOf="@id/car_ui_toolbar_row_separator_guideline" />
+
+            <ProgressBar
+                android:id="@+id/car_ui_toolbar_progress_bar"
+                style="@android:style/Widget.DeviceDefault.ProgressBar.Horizontal"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:indeterminate="true"
+                android:visibility="gone"
+                app:layout_constraintBottom_toBottomOf="parent"
+                app:layout_constraintEnd_toEndOf="parent"
+                app:layout_constraintStart_toStartOf="parent" />
+
+        </androidx.constraintlayout.widget.ConstraintLayout>
+    </com.android.car.ui.FocusArea>
+
+</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/car-ui-lib/referencedesign/res/values-ldrtl/values.xml b/car-ui-lib/referencedesign/res/values-ldrtl/values.xml
new file mode 100644
index 0000000..2d50133
--- /dev/null
+++ b/car-ui-lib/referencedesign/res/values-ldrtl/values.xml
@@ -0,0 +1,4 @@
+<resources>
+    <bool name="car_ui_toolbar_nav_icon_reserve_space">false</bool>
+    <bool name="car_ui_toolbar_logo_fills_nav_icon_space">false</bool>
+</resources>
diff --git a/car-ui-lib/referencedesign/res/values/attrs.xml b/car-ui-lib/referencedesign/res/values/attrs.xml
new file mode 100644
index 0000000..a0b53df
--- /dev/null
+++ b/car-ui-lib/referencedesign/res/values/attrs.xml
@@ -0,0 +1,59 @@
+<resources>
+    <!-- ConstraintLayout attributes. For a more complete list, see: -->
+    <!-- https://android.googlesource.com/platform/frameworks/opt/sherpa/+/studio-3.0/constraintlayout/src/main/res/values/attrs.xml -->
+
+    <attr name="layout_constraintGuide_begin" format="dimension"/>
+    <attr name="layout_constraintGuide_end" format="dimension"/>
+    <attr name="layout_constraintGuide_percent" format="float"/>
+
+    <attr name="layout_constraintLeft_toLeftOf" format="reference|enum">
+        <enum name="parent" value="0"/>
+    </attr>
+    <attr name="layout_constraintLeft_toRightOf" format="reference|enum">
+        <enum name="parent" value="0"/>
+    </attr>
+    <attr name="layout_constraintRight_toLeftOf" format="reference|enum">
+        <enum name="parent" value="0"/>
+    </attr>
+    <attr name="layout_constraintRight_toRightOf" format="reference|enum">
+        <enum name="parent" value="0"/>
+    </attr>
+    <attr name="layout_constraintTop_toTopOf" format="reference|enum">
+        <enum name="parent" value="0"/>
+    </attr>
+    <attr name="layout_constraintTop_toBottomOf" format="reference|enum">
+        <enum name="parent" value="0"/>
+    </attr>
+    <attr name="layout_constraintBottom_toTopOf" format="reference|enum">
+        <enum name="parent" value="0"/>
+    </attr>
+    <attr name="layout_constraintBottom_toBottomOf" format="reference|enum">
+        <enum name="parent" value="0"/>
+    </attr>
+    <attr name="layout_constraintBaseline_toBaselineOf" format="reference|enum">
+        <enum name="parent" value="0"/>
+    </attr>
+    <attr name="layout_constraintStart_toEndOf" format="reference|enum">
+        <enum name="parent" value="0"/>
+    </attr>
+    <attr name="layout_constraintStart_toStartOf" format="reference|enum">
+        <enum name="parent" value="0"/>
+    </attr>
+    <attr name="layout_constraintEnd_toStartOf" format="reference|enum">
+        <enum name="parent" value="0"/>
+    </attr>
+    <attr name="layout_constraintEnd_toEndOf" format="reference|enum">
+        <enum name="parent" value="0"/>
+    </attr>
+
+    <attr name="layout_constraintHorizontal_bias" format="float"/>
+    <attr name="layout_constraintVertical_bias" format="float"/>
+
+    <attr name="layout_goneMarginLeft" format="dimension"/>
+    <attr name="layout_goneMarginTop" format="dimension"/>
+    <attr name="layout_goneMarginRight" format="dimension"/>
+    <attr name="layout_goneMarginBottom" format="dimension"/>
+    <attr name="layout_goneMarginStart" format="dimension"/>
+    <attr name="layout_goneMarginEnd" format="dimension"/>
+
+</resources>
diff --git a/car-ui-lib/referencedesign/res/values/values.xml b/car-ui-lib/referencedesign/res/values/values.xml
new file mode 100644
index 0000000..0cbb8ee
--- /dev/null
+++ b/car-ui-lib/referencedesign/res/values/values.xml
@@ -0,0 +1,15 @@
+<resources>
+    <style name="TextAppearance.CarUi.Widget" parent="android:TextAppearance.DeviceDefault.Widget">
+        <item name="android:textAlignment">viewStart</item>
+    </style>
+
+    <style name="TextAppearance.CarUi.Widget.Toolbar"/>
+
+    <style name="TextAppearance.CarUi.Widget.Toolbar.Title">
+        <item name="android:singleLine">true</item>
+        <item name="android:textSize">32sp</item>
+    </style>
+
+    <dimen name="car_ui_toolbar_logo_size">44dp</dimen>
+    <dimen name="car_ui_toolbar_nav_icon_size">44dp</dimen>
+</resources>
diff --git a/car-ui-lib/referencedesign/res/xml/overlays.xml b/car-ui-lib/referencedesign/res/xml/overlays.xml
new file mode 100644
index 0000000..0d0eb74
--- /dev/null
+++ b/car-ui-lib/referencedesign/res/xml/overlays.xml
@@ -0,0 +1,45 @@
+<overlay>
+    <item target="layout/car_ui_base_layout_toolbar" value="@layout/car_ui_base_layout_toolbar"/>
+    <item target="layout/car_ui_toolbar" value="@layout/car_ui_toolbar"/>
+    <item target="layout/car_ui_toolbar_two_row" value="@layout/car_ui_toolbar_two_row"/>
+
+    <item target="bool/car_ui_toolbar_nav_icon_reserve_space" value="@bool/car_ui_toolbar_nav_icon_reserve_space" />
+    <item target="bool/car_ui_toolbar_logo_fills_nav_icon_space" value="@bool/car_ui_toolbar_logo_fills_nav_icon_space" />
+
+    <item target="id/car_ui_toolbar_background" value="@id/car_ui_toolbar_background" />
+    <item target="id/car_ui_toolbar_nav_icon_container" value="@id/car_ui_toolbar_nav_icon_container" />
+    <item target="id/car_ui_toolbar_nav_icon" value="@id/car_ui_toolbar_nav_icon" />
+    <item target="id/car_ui_toolbar_logo" value="@id/car_ui_toolbar_logo" />
+    <item target="id/car_ui_toolbar_title_logo_container" value="@id/car_ui_toolbar_title_logo_container" />
+    <item target="id/car_ui_toolbar_title_logo" value="@id/car_ui_toolbar_title_logo" />
+    <item target="id/car_ui_toolbar_title" value="@id/car_ui_toolbar_title" />
+    <item target="id/car_ui_toolbar_title_container" value="@id/car_ui_toolbar_title_container" />
+    <item target="id/car_ui_toolbar_subtitle" value="@id/car_ui_toolbar_subtitle" />
+    <item target="id/car_ui_toolbar_tabs" value="@id/car_ui_toolbar_tabs" />
+    <item target="id/car_ui_toolbar_menu_items_container" value="@id/car_ui_toolbar_menu_items_container" />
+    <item target="id/car_ui_toolbar_search_view_container" value="@id/car_ui_toolbar_search_view_container" />
+    <item target="id/car_ui_toolbar_progress_bar" value="@id/car_ui_toolbar_progress_bar" />
+    <item target="id/content" value="@id/content" />
+
+    <item target="attr/layout_constraintGuide_begin" value="@attr/layout_constraintGuide_begin"/>
+    <item target="attr/layout_constraintGuide_end" value="@attr/layout_constraintGuide_end"/>
+    <item target="attr/layout_constraintStart_toStartOf" value="@attr/layout_constraintStart_toStartOf"/>
+    <item target="attr/layout_constraintStart_toEndOf" value="@attr/layout_constraintStart_toEndOf"/>
+    <item target="attr/layout_constraintEnd_toStartOf" value="@attr/layout_constraintEnd_toStartOf"/>
+    <item target="attr/layout_constraintEnd_toEndOf" value="@attr/layout_constraintEnd_toEndOf"/>
+    <item target="attr/layout_constraintLeft_toLeftOf" value="@attr/layout_constraintLeft_toLeftOf"/>
+    <item target="attr/layout_constraintLeft_toRightOf" value="@attr/layout_constraintLeft_toRightOf"/>
+    <item target="attr/layout_constraintRight_toLeftOf" value="@attr/layout_constraintRight_toLeftOf"/>
+    <item target="attr/layout_constraintRight_toRightOf" value="@attr/layout_constraintRight_toRightOf"/>
+    <item target="attr/layout_constraintTop_toTopOf" value="@attr/layout_constraintTop_toTopOf"/>
+    <item target="attr/layout_constraintTop_toBottomOf" value="@attr/layout_constraintTop_toBottomOf"/>
+    <item target="attr/layout_constraintBottom_toTopOf" value="@attr/layout_constraintBottom_toTopOf"/>
+    <item target="attr/layout_constraintBottom_toBottomOf" value="@attr/layout_constraintBottom_toBottomOf"/>
+    <item target="attr/layout_constraintHorizontal_bias" value="@attr/layout_constraintHorizontal_bias"/>
+    <item target="attr/layout_goneMarginLeft" value="@attr/layout_goneMarginLeft"/>
+    <item target="attr/layout_goneMarginLeft" value="@attr/layout_goneMarginRight"/>
+    <item target="attr/layout_goneMarginLeft" value="@attr/layout_goneMarginTop"/>
+    <item target="attr/layout_goneMarginLeft" value="@attr/layout_goneMarginBottom"/>
+    <item target="attr/layout_goneMarginLeft" value="@attr/layout_goneMarginStart"/>
+    <item target="attr/layout_goneMarginLeft" value="@attr/layout_goneMarginEnd"/>
+</overlay>
diff --git a/car-ui-lib/res/color/car_ui_dialog_icon_color.xml b/car-ui-lib/res/color/car_ui_dialog_icon_color.xml
new file mode 100644
index 0000000..2965a49
--- /dev/null
+++ b/car-ui-lib/res/color/car_ui_dialog_icon_color.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2020 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:color="?android:attr/colorForeground"/>
+</selector>
diff --git a/car-ui-lib/res/drawable/car_ui_focus_area_background_highlight.xml b/car-ui-lib/res/drawable/car_ui_focus_area_background_highlight.xml
new file mode 100644
index 0000000..74b8d13
--- /dev/null
+++ b/car-ui-lib/res/drawable/car_ui_focus_area_background_highlight.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright 2020 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+       android:shape="rectangle">
+    <solid android:color="#00FF00"/>
+</shape>
diff --git a/car-ui-lib/res/drawable/car_ui_focus_area_foreground_highlight.xml b/car-ui-lib/res/drawable/car_ui_focus_area_foreground_highlight.xml
new file mode 100644
index 0000000..b6955f6
--- /dev/null
+++ b/car-ui-lib/res/drawable/car_ui_focus_area_foreground_highlight.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright 2020 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+       android:shape="rectangle" >
+    <stroke android:width="10dp" android:color="#FF0000"/>
+</shape>
diff --git a/car-ui-lib/res/drawable/car_ui_icon_add.xml b/car-ui-lib/res/drawable/car_ui_icon_add.xml
new file mode 100644
index 0000000..2fa6580
--- /dev/null
+++ b/car-ui-lib/res/drawable/car_ui_icon_add.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2020 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<!-- Used in Carboard's toolbar. -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="48dp"
+        android:height="48dp"
+        android:viewportWidth="24"
+        android:viewportHeight="24">
+<path
+    android:fillColor="@color/car_ui_toolbar_menu_item_icon_color"
+    android:pathData="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/>
+</vector>
diff --git a/car-ui-lib/res/drawable/car_ui_icon_close.xml b/car-ui-lib/res/drawable/car_ui_icon_close.xml
index 482df0f..a02d199 100644
--- a/car-ui-lib/res/drawable/car_ui_icon_close.xml
+++ b/car-ui-lib/res/drawable/car_ui_icon_close.xml
@@ -24,4 +24,4 @@
     <path
         android:fillColor="#FFF"
         android:pathData="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,12z"/>
-</vector>
\ No newline at end of file
+</vector>
diff --git a/car-ui-lib/res/drawable/car_ui_icon_delete.xml b/car-ui-lib/res/drawable/car_ui_icon_delete.xml
new file mode 100644
index 0000000..63aa782
--- /dev/null
+++ b/car-ui-lib/res/drawable/car_ui_icon_delete.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2020 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<!-- Used in Carboard's toolbar. -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="48dp"
+        android:height="48dp"
+        android:viewportWidth="24"
+        android:viewportHeight="24">
+<path
+    android:fillColor="@color/car_ui_toolbar_menu_item_icon_color"
+    android:pathData="M6,19c0,1.1 0.9,2 2,2h8c1.1,0 2,-0.9 2,-2V7H6v12zM19,4h-3.5l-1,-1h-5l-1,1H5v2h14V4z"/>
+</vector>
diff --git a/car-ui-lib/res/drawable/car_ui_icon_edit.xml b/car-ui-lib/res/drawable/car_ui_icon_edit.xml
new file mode 100644
index 0000000..a418c7f
--- /dev/null
+++ b/car-ui-lib/res/drawable/car_ui_icon_edit.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2020 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<!-- Used in Carboard's toolbar. -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="48dp"
+        android:height="48dp"
+        android:viewportWidth="24"
+        android:viewportHeight="24">
+<path
+    android:fillColor="@color/car_ui_toolbar_menu_item_icon_color"
+    android:pathData="M3,17.25V21h3.75L17.81,9.94l-3.75,-3.75L3,17.25zM20.71,7.04c0.39,-0.39 0.39,-1.02 0,-1.41l-2.34,-2.34c-0.39,-0.39 -1.02,-0.39 -1.41,0l-1.83,1.83 3.75,3.75 1.83,-1.83z"/>
+</vector>
diff --git a/car-ui-lib/res/drawable/car_ui_icon_save.xml b/car-ui-lib/res/drawable/car_ui_icon_save.xml
new file mode 100644
index 0000000..f65682a
--- /dev/null
+++ b/car-ui-lib/res/drawable/car_ui_icon_save.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2020 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<!-- Used in Carboard's toolbar. -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="48dp"
+        android:height="48dp"
+        android:viewportWidth="24"
+        android:viewportHeight="24">
+<path
+    android:fillColor="@color/car_ui_toolbar_menu_item_icon_color"
+    android:pathData="M17,3L5,3c-1.11,0 -2,0.9 -2,2v14c0,1.1 0.89,2 2,2h14c1.1,0 2,-0.9 2,-2L21,7l-4,-4zM12,19c-1.66,0 -3,-1.34 -3,-3s1.34,-3 3,-3 3,1.34 3,3 -1.34,3 -3,3zM15,9L5,9L5,5h10v4z"/>
+</vector>
diff --git a/car-ui-lib/res/drawable/car_ui_list_item_background.xml b/car-ui-lib/res/drawable/car_ui_list_item_background.xml
index df8df2f..15585b2 100644
--- a/car-ui-lib/res/drawable/car_ui_list_item_background.xml
+++ b/car-ui-lib/res/drawable/car_ui_list_item_background.xml
@@ -13,11 +13,24 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<ripple xmlns:android="http://schemas.android.com/apk/res/android"
-    android:color="?android:colorControlHighlight">
-    <item android:id="@android:id/mask">
-        <shape android:shape="rectangle">
-            <solid android:color="?android:colorAccent" />
-        </shape>
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_focused="true">
+        <ripple android:color="@color/car_ui_rotary_focus_color">
+            <item android:id="@android:id/mask">
+                <shape android:shape="rectangle">
+                    <solid android:color="?android:colorAccent"/>
+                </shape>
+            </item>
+        </ripple>
     </item>
-</ripple>
\ No newline at end of file
+    <item>
+        <ripple android:color="?android:attr/colorControlHighlight">
+            <item android:id="@android:id/mask">
+                <shape android:shape="rectangle">
+                    <solid android:color="?android:colorAccent"/>
+                </shape>
+            </item>
+        </ripple>
+    </item>
+</selector>
diff --git a/car-ui-lib/res/drawable/car_ui_list_item_divider.xml b/car-ui-lib/res/drawable/car_ui_list_item_divider.xml
index 1e229c8..6f8e742 100644
--- a/car-ui-lib/res/drawable/car_ui_list_item_divider.xml
+++ b/car-ui-lib/res/drawable/car_ui_list_item_divider.xml
@@ -19,4 +19,4 @@
     android:shape="rectangle">
     <size android:height="@dimen/car_ui_list_item_action_divider_height" />
     <solid android:color="@color/car_ui_list_item_divider" />
-</shape>
\ No newline at end of file
+</shape>
diff --git a/car-ui-lib/res/drawable/car_ui_preference_icon_chevron.xml b/car-ui-lib/res/drawable/car_ui_preference_icon_chevron.xml
index 61d594c..8011b92 100644
--- a/car-ui-lib/res/drawable/car_ui_preference_icon_chevron.xml
+++ b/car-ui-lib/res/drawable/car_ui_preference_icon_chevron.xml
@@ -18,4 +18,4 @@
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
   <item android:state_enabled="false" android:drawable="@drawable/car_ui_preference_icon_chevron_disabled"/>
   <item android:state_enabled="true" android:drawable="@drawable/car_ui_preference_icon_chevron_enabled"/>
-</selector>
\ No newline at end of file
+</selector>
diff --git a/car-ui-lib/res/layout-ldrtl/car_ui_recycler_view.xml b/car-ui-lib/res/layout-ldrtl/car_ui_recycler_view.xml
new file mode 100644
index 0000000..4847388
--- /dev/null
+++ b/car-ui-lib/res/layout-ldrtl/car_ui_recycler_view.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2020 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <com.android.car.ui.recyclerview.CarUiRecyclerViewContainer
+        android:id="@+id/car_ui_recycler_view"
+        android:layout_width="0dp"
+        android:layout_height="match_parent"
+        android:layout_marginStart="@dimen/car_ui_scrollbar_margin"
+        android:tag="carUiRecyclerView"
+        android:layout_weight="1"/>
+
+    <include layout="@layout/car_ui_recyclerview_scrollbar"/>
+</merge>
diff --git a/car-ui-lib/res/layout-port/car_ui_base_layout_toolbar.xml b/car-ui-lib/res/layout-port/car_ui_base_layout_toolbar.xml
deleted file mode 100644
index 57d08ce..0000000
--- a/car-ui-lib/res/layout-port/car_ui_base_layout_toolbar.xml
+++ /dev/null
@@ -1,196 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2020 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-<!-- This is for the two-row version of the toolbar -->
-<androidx.constraintlayout.widget.ConstraintLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent">
-
-    <!-- When the user finishes searching, we call clearFocus() on the editText in the search bar.
-     clearFocus() will actually send the focus to the first focusable thing in the layout.
-     If that focusable thing is still the search bar it will just reselect it, and the user won't
-     be able to deselect. So make a focusable view here to guarantee that we can clear the focus -->
-    <View
-        android:layout_width="1dp"
-        android:layout_height="1dp"
-        android:focusable="true"
-        android:focusableInTouchMode="true" />
-
-    <FrameLayout
-        android:id="@+id/content"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintTop_toTopOf="parent" />
-
-    <androidx.constraintlayout.widget.ConstraintLayout
-        android:id="@+id/car_ui_toolbar_background"
-        style="@style/Widget.CarUi.Toolbar.Container"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:tag="car_ui_top_inset"
-        app:layout_constraintTop_toTopOf="parent">
-
-        <androidx.constraintlayout.widget.Guideline
-            android:id="@+id/car_ui_toolbar_start_guideline"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:orientation="vertical"
-            app:layout_constraintGuide_begin="@dimen/car_ui_toolbar_start_inset" />
-
-        <androidx.constraintlayout.widget.Guideline
-            android:id="@+id/car_ui_toolbar_top_guideline"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:orientation="horizontal"
-            app:layout_constraintGuide_begin="@dimen/car_ui_toolbar_top_inset" />
-
-        <androidx.constraintlayout.widget.Guideline
-            android:id="@+id/car_ui_toolbar_end_guideline"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:orientation="vertical"
-            app:layout_constraintGuide_end="@dimen/car_ui_toolbar_end_inset" />
-
-        <androidx.constraintlayout.widget.Guideline
-            android:id="@+id/car_ui_toolbar_bottom_guideline"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:orientation="horizontal"
-            app:layout_constraintGuide_end="@dimen/car_ui_toolbar_bottom_inset" />
-
-        <androidx.constraintlayout.widget.Guideline
-            android:id="@+id/car_ui_toolbar_row_separator_guideline"
-            android:layout_width="0dp"
-            android:layout_height="0dp"
-            android:orientation="horizontal"
-            app:layout_constraintGuide_begin="@dimen/car_ui_toolbar_first_row_height" />
-
-        <View
-            android:id="@+id/car_ui_toolbar_row_separator"
-            style="@style/Widget.CarUi.Toolbar.SeparatorView"
-            android:layout_width="match_parent"
-            android:layout_height="@dimen/car_ui_toolbar_separator_height"
-            app:layout_constraintEnd_toEndOf="parent"
-            app:layout_constraintStart_toStartOf="parent"
-            app:layout_constraintTop_toBottomOf="@id/car_ui_toolbar_row_separator_guideline" />
-
-        <FrameLayout
-            android:id="@+id/car_ui_toolbar_nav_icon_container"
-            style="@style/Widget.CarUi.Toolbar.NavIconContainer"
-            android:layout_width="@dimen/car_ui_toolbar_margin"
-            android:layout_height="0dp"
-            app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_row_separator"
-            app:layout_constraintStart_toStartOf="@id/car_ui_toolbar_start_guideline"
-            app:layout_constraintTop_toTopOf="@id/car_ui_toolbar_top_guideline">
-
-            <ImageView
-                android:id="@+id/car_ui_toolbar_nav_icon"
-                style="@style/Widget.CarUi.Toolbar.NavIcon"
-                android:layout_width="@dimen/car_ui_toolbar_nav_icon_size"
-                android:layout_height="@dimen/car_ui_toolbar_nav_icon_size"
-                android:layout_gravity="center"
-                android:scaleType="fitXY" />
-
-            <ImageView
-                android:id="@+id/car_ui_toolbar_logo"
-                android:layout_width="@dimen/car_ui_toolbar_logo_size"
-                android:layout_height="@dimen/car_ui_toolbar_logo_size"
-                android:layout_gravity="center"
-                android:scaleType="fitXY" />
-        </FrameLayout>
-
-        <FrameLayout
-            android:id="@+id/car_ui_toolbar_title_logo_container"
-            style="@style/Widget.CarUi.Toolbar.LogoContainer"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_row_separator"
-            app:layout_constraintStart_toEndOf="@id/car_ui_toolbar_nav_icon_container"
-            app:layout_constraintTop_toTopOf="@id/car_ui_toolbar_top_guideline">
-
-            <ImageView
-                android:id="@+id/car_ui_toolbar_title_logo"
-                style="@style/Widget.CarUi.Toolbar.Logo"
-                android:layout_width="@dimen/car_ui_toolbar_logo_size"
-                android:layout_height="@dimen/car_ui_toolbar_logo_size"
-                android:layout_gravity="center"
-                android:scaleType="fitXY" />
-        </FrameLayout>
-
-        <TextView
-            android:id="@+id/car_ui_toolbar_title"
-            style="@style/Widget.CarUi.Toolbar.Title"
-            android:layout_width="0dp"
-            android:layout_height="wrap_content"
-            android:singleLine="true"
-            app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_row_separator"
-            app:layout_constraintEnd_toStartOf="@id/car_ui_toolbar_menu_items_container"
-            app:layout_constraintStart_toEndOf="@id/car_ui_toolbar_title_logo_container"
-            app:layout_constraintTop_toTopOf="@id/car_ui_toolbar_top_guideline" />
-
-        <FrameLayout
-            android:id="@+id/car_ui_toolbar_search_view_container"
-            android:layout_width="0dp"
-            android:layout_height="@dimen/car_ui_toolbar_search_height"
-            app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_row_separator"
-            app:layout_constraintEnd_toStartOf="@+id/car_ui_toolbar_menu_items_container"
-            app:layout_constraintStart_toEndOf="@+id/car_ui_toolbar_nav_icon_container"
-            app:layout_constraintTop_toTopOf="@id/car_ui_toolbar_top_guideline" />
-
-        <LinearLayout
-            android:id="@+id/car_ui_toolbar_menu_items_container"
-            style="@style/Widget.CarUi.Toolbar.MenuItem.Container"
-            android:layout_width="wrap_content"
-            android:layout_height="0dp"
-            android:orientation="horizontal"
-            app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_row_separator"
-            app:layout_constraintEnd_toStartOf="@id/car_ui_toolbar_end_guideline"
-            app:layout_constraintTop_toTopOf="@id/car_ui_toolbar_top_guideline" />
-
-        <com.android.car.ui.toolbar.TabLayout
-            android:id="@+id/car_ui_toolbar_tabs"
-            android:layout_width="match_parent"
-            android:layout_height="@dimen/car_ui_toolbar_second_row_height"
-            app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_bottom_guideline"
-            app:layout_constraintTop_toBottomOf="@id/car_ui_toolbar_row_separator" />
-
-        <View
-            android:id="@+id/car_ui_toolbar_bottom_styleable"
-            style="@style/Widget.CarUi.Toolbar.BottomView"
-            android:layout_width="match_parent"
-            android:layout_height="@dimen/car_ui_toolbar_bottom_view_height"
-            app:layout_constraintBottom_toBottomOf="parent"
-            app:layout_constraintEnd_toEndOf="parent"
-            app:layout_constraintStart_toStartOf="parent" />
-
-        <ProgressBar
-            android:id="@+id/car_ui_toolbar_progress_bar"
-            style="@style/Widget.CarUi.Toolbar.ProgressBar"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:indeterminate="true"
-            android:visibility="gone"
-            app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_bottom_styleable"
-            app:layout_constraintEnd_toEndOf="parent"
-            app:layout_constraintStart_toStartOf="parent" />
-
-    </androidx.constraintlayout.widget.ConstraintLayout>
-
-</androidx.constraintlayout.widget.ConstraintLayout>
-
diff --git a/car-ui-lib/res/layout/car_ui_alert_dialog_edit_text.xml b/car-ui-lib/res/layout/car_ui_alert_dialog_edit_text.xml
index 3cc87c1..d654b2b 100644
--- a/car-ui-lib/res/layout/car_ui_alert_dialog_edit_text.xml
+++ b/car-ui-lib/res/layout/car_ui_alert_dialog_edit_text.xml
@@ -24,4 +24,4 @@
               android:layout_marginBottom="@dimen/car_ui_dialog_edittext_margin_bottom"
               android:layout_marginStart="@dimen/car_ui_dialog_edittext_margin_start"
               android:layout_marginEnd="@dimen/car_ui_dialog_edittext_margin_end"/>
-</FrameLayout>
\ No newline at end of file
+</FrameLayout>
diff --git a/car-ui-lib/res/layout/car_ui_alert_dialog_title_with_subtitle.xml b/car-ui-lib/res/layout/car_ui_alert_dialog_title_with_subtitle.xml
index 271280d..f8d73c3 100644
--- a/car-ui-lib/res/layout/car_ui_alert_dialog_title_with_subtitle.xml
+++ b/car-ui-lib/res/layout/car_ui_alert_dialog_title_with_subtitle.xml
@@ -23,7 +23,7 @@
     style="@style/Widget.CarUi.AlertDialog.HeaderContainer">
 
     <ImageView
-        android:id="@+id/icon"
+        android:id="@+id/car_ui_alert_icon"
         android:layout_width="@dimen/car_ui_dialog_icon_size"
         android:layout_height="@dimen/car_ui_dialog_icon_size"
         style="@style/Widget.CarUi.AlertDialog.Icon"/>
@@ -33,17 +33,15 @@
         android:layout_height="wrap_content"
         style="@style/Widget.CarUi.AlertDialog.TitleContainer">
         <TextView
-            android:id="@+id/alertTitle"
-            android:singleLine="true"
+            android:id="@+id/car_ui_alert_title"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:textAlignment="viewStart"
-            style="?android:attr/windowTitleStyle" />
+            android:textAppearance="@style/TextAppearance.CarUi.AlertDialog.Title" />
 
         <TextView
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:id="@+id/alertSubtitle"
+            android:id="@+id/car_ui_alert_subtitle"
             android:textAppearance="@style/TextAppearance.CarUi.AlertDialog.Subtitle"/>
     </LinearLayout>
 
diff --git a/car-ui-lib/res/layout/car_ui_base_layout.xml b/car-ui-lib/res/layout/car_ui_base_layout.xml
index 4cf7e8d..14dfb75 100644
--- a/car-ui-lib/res/layout/car_ui_base_layout.xml
+++ b/car-ui-lib/res/layout/car_ui_base_layout.xml
@@ -19,4 +19,12 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:id="@+id/content">
-</FrameLayout>
\ No newline at end of file
+    <!-- When not in touch mode, if we clear focus in current window, Android will re-focus the
+         first focusable view in the window automatically. Adding a FocusParkingView to the window
+         can fix this issue, because it can take focus, and it is transparent and its default focus
+         highlight is disabled, so it's invisible to the user no matter whether it's focused or not.
+         -->
+    <com.android.car.ui.FocusParkingView
+        android:layout_width="1dp"
+        android:layout_height="1dp"/>
+</FrameLayout>
diff --git a/car-ui-lib/res/layout/car_ui_base_layout_toolbar.xml b/car-ui-lib/res/layout/car_ui_base_layout_toolbar.xml
index 90b083a..2d0cde8 100644
--- a/car-ui-lib/res/layout/car_ui_base_layout_toolbar.xml
+++ b/car-ui-lib/res/layout/car_ui_base_layout_toolbar.xml
@@ -18,177 +18,152 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
     android:layout_width="match_parent"
-    android:layout_height="match_parent">
+    android:layout_height="match_parent"
+    android:tag="CarUiBaseLayoutToolbar">
 
-    <!-- When the user finishes searching, we call clearFocus() on the editText in the search bar.
-     clearFocus() will actually send the focus to the first focusable thing in the layout.
-     If that focusable thing is still the search bar it will just reselect it, and the user won't
-     be able to deselect. So make a focusable view here to guarantee that we can clear the focus -->
-    <View
+    <!-- When not in touch mode, if we clear focus in current window, Android will re-focus the
+         first focusable view in the window automatically. Adding a FocusParkingView to the window
+         can fix this issue, because it can take focus, and it is transparent and its default focus
+         highlight is disabled, so it's invisible to the user no matter whether it's focused or not.
+         -->
+    <com.android.car.ui.FocusParkingView
         android:layout_width="1dp"
-        android:layout_height="1dp"
-        android:focusable="true"
-        android:focusableInTouchMode="true" />
+        android:layout_height="1dp"/>
 
     <FrameLayout
         android:id="@+id/content"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintTop_toTopOf="parent" />
+        app:layout_constraintTop_toTopOf="parent"/>
 
-    <androidx.constraintlayout.widget.ConstraintLayout
-        android:id="@+id/car_ui_toolbar_background"
-        style="@style/Widget.CarUi.Toolbar.Container"
+    <com.android.car.ui.FocusArea
         android:layout_width="match_parent"
-        android:layout_height="@dimen/car_ui_toolbar_first_row_height"
-        android:tag="car_ui_top_inset"
-        app:layout_constraintTop_toTopOf="parent">
-
-        <androidx.constraintlayout.widget.Guideline
-            android:id="@+id/car_ui_toolbar_start_guideline"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:orientation="vertical"
-            app:layout_constraintGuide_begin="@dimen/car_ui_toolbar_start_inset" />
-
-        <androidx.constraintlayout.widget.Guideline
-            android:id="@+id/car_ui_toolbar_top_guideline"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:orientation="horizontal"
-            app:layout_constraintGuide_begin="@dimen/car_ui_toolbar_top_inset" />
-
-        <androidx.constraintlayout.widget.Guideline
-            android:id="@+id/car_ui_toolbar_end_guideline"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:orientation="vertical"
-            app:layout_constraintGuide_end="@dimen/car_ui_toolbar_end_inset" />
-
-        <androidx.constraintlayout.widget.Guideline
-            android:id="@+id/car_ui_toolbar_bottom_guideline"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:orientation="horizontal"
-            app:layout_constraintGuide_end="@dimen/car_ui_toolbar_bottom_inset" />
-
-        <!-- The horizontal bias set to 0.0 here is so that when you set this view as GONE, it will
-             be treated as if it's all the way to the left instead of centered in the margin -->
-        <FrameLayout
-            android:id="@+id/car_ui_toolbar_nav_icon_container"
-            style="@style/Widget.CarUi.Toolbar.NavIconContainer"
-            android:layout_width="@dimen/car_ui_toolbar_margin"
-            android:layout_height="0dp"
-            app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_bottom_guideline"
-            app:layout_constraintHorizontal_bias="0.0"
-            app:layout_constraintStart_toEndOf="@id/car_ui_toolbar_start_guideline"
-            app:layout_constraintTop_toTopOf="@id/car_ui_toolbar_top_guideline">
-
-            <ImageView
-                android:id="@+id/car_ui_toolbar_nav_icon"
-                style="@style/Widget.CarUi.Toolbar.NavIcon"
-                android:layout_width="@dimen/car_ui_toolbar_nav_icon_size"
-                android:layout_height="@dimen/car_ui_toolbar_nav_icon_size"
-                android:layout_gravity="center"
-                android:scaleType="fitXY" />
-
-            <ImageView
-                android:id="@+id/car_ui_toolbar_logo"
-                android:layout_width="@dimen/car_ui_toolbar_logo_size"
-                android:layout_height="@dimen/car_ui_toolbar_logo_size"
-                android:layout_gravity="center"
-                android:scaleType="fitXY" />
-        </FrameLayout>
-
-        <FrameLayout
-            android:id="@+id/car_ui_toolbar_title_logo_container"
-            style="@style/Widget.CarUi.Toolbar.LogoContainer"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_bottom_guideline"
-            app:layout_constraintStart_toEndOf="@id/car_ui_toolbar_nav_icon_container"
-            app:layout_constraintTop_toTopOf="@id/car_ui_toolbar_top_guideline">
-
-            <ImageView
-                android:id="@+id/car_ui_toolbar_title_logo"
-                style="@style/Widget.CarUi.Toolbar.Logo"
-                android:layout_width="@dimen/car_ui_toolbar_logo_size"
-                android:layout_height="@dimen/car_ui_toolbar_logo_size"
-                android:layout_gravity="center"
-                android:scaleType="fitXY" />
-        </FrameLayout>
-
-        <TextView
-            android:id="@+id/car_ui_toolbar_title"
-            style="@style/Widget.CarUi.Toolbar.Title"
-            android:layout_width="0dp"
-            android:layout_height="wrap_content"
-            android:singleLine="true"
-            app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_bottom_guideline"
-            app:layout_constraintEnd_toStartOf="@+id/car_ui_toolbar_menu_items_container"
-            app:layout_constraintStart_toEndOf="@+id/car_ui_toolbar_title_logo_container"
-            app:layout_constraintTop_toTopOf="@id/car_ui_toolbar_top_guideline" />
-
-        <com.android.car.ui.toolbar.TabLayout
-            android:id="@+id/car_ui_toolbar_tabs"
-            android:layout_width="wrap_content"
-            android:layout_height="0dp"
-            app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_bottom_guideline"
-            app:layout_constraintEnd_toStartOf="@+id/car_ui_toolbar_menu_items_container"
-            app:layout_constraintHorizontal_bias="0.0"
-            app:layout_constraintStart_toEndOf="@+id/car_ui_toolbar_title_logo_container"
-            app:layout_constraintTop_toTopOf="@id/car_ui_toolbar_top_guideline" />
-
-        <LinearLayout
-            android:id="@+id/car_ui_toolbar_menu_items_container"
-            style="@style/Widget.CarUi.Toolbar.MenuItem.Container"
-            android:layout_width="wrap_content"
-            android:layout_height="0dp"
-            android:orientation="horizontal"
-            app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_bottom_guideline"
-            app:layout_constraintEnd_toStartOf="@+id/car_ui_toolbar_end_guideline"
-            app:layout_constraintTop_toTopOf="@id/car_ui_toolbar_top_guideline" />
-
-        <FrameLayout
-            android:id="@+id/car_ui_toolbar_search_view_container"
-            android:layout_width="0dp"
-            android:layout_height="@dimen/car_ui_toolbar_search_height"
-            app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_bottom_guideline"
-            app:layout_constraintEnd_toStartOf="@+id/car_ui_toolbar_menu_items_container"
-            app:layout_constraintStart_toEndOf="@+id/car_ui_toolbar_nav_icon_container"
-            app:layout_constraintTop_toTopOf="@id/car_ui_toolbar_top_guideline" />
-
-        <View
-            android:id="@+id/car_ui_toolbar_row_separator"
-            style="@style/Widget.CarUi.Toolbar.SeparatorView"
+        android:layout_height="@dimen/car_ui_toolbar_first_row_height">
+        <androidx.constraintlayout.widget.ConstraintLayout
+            android:id="@+id/car_ui_toolbar_background"
+            style="@style/Widget.CarUi.Toolbar.Container"
             android:layout_width="match_parent"
-            android:layout_height="@dimen/car_ui_toolbar_separator_height"
-            app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_bottom_guideline"
-            app:layout_constraintEnd_toEndOf="parent"
-            app:layout_constraintStart_toStartOf="parent" />
+            android:layout_height="match_parent"
+            android:tag="car_ui_top_inset"
+            app:layout_constraintTop_toTopOf="parent">
+            <com.android.car.ui.baselayout.ClickBlockingView
+                android:layout_width="0dp"
+                android:layout_height="0dp"
+                app:layout_constraintStart_toStartOf="parent"
+                app:layout_constraintEnd_toEndOf="parent"
+                app:layout_constraintTop_toTopOf="parent"
+                app:layout_constraintBottom_toBottomOf="parent"/>
 
-        <ProgressBar
-            android:id="@+id/car_ui_toolbar_progress_bar"
-            style="@style/Widget.CarUi.Toolbar.ProgressBar"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:indeterminate="true"
-            android:visibility="gone"
-            app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_row_separator"
-            app:layout_constraintEnd_toEndOf="parent"
-            app:layout_constraintStart_toStartOf="parent" />
+            <!-- The horizontal bias set to 0.0 here is so that when you set this view as GONE, it will
+                 be treated as if it's all the way to the left instead of centered in the margin -->
+            <FrameLayout
+                android:id="@+id/car_ui_toolbar_nav_icon_container"
+                style="@style/Widget.CarUi.Toolbar.NavIconContainer"
+                android:layout_width="@dimen/car_ui_toolbar_margin"
+                android:layout_height="0dp"
+                app:layout_constraintBottom_toBottomOf="parent"
+                app:layout_constraintHorizontal_bias="0.0"
+                app:layout_constraintStart_toStartOf="parent"
+                app:layout_constraintTop_toTopOf="parent">
 
-        <View
-            android:id="@+id/car_ui_toolbar_bottom_styleable"
-            style="@style/Widget.CarUi.Toolbar.BottomView"
-            android:layout_width="match_parent"
-            android:layout_height="@dimen/car_ui_toolbar_bottom_view_height"
-            app:layout_constraintBottom_toTopOf="@+id/car_ui_toolbar_progress_bar"
-            app:layout_constraintEnd_toEndOf="parent"
-            app:layout_constraintStart_toStartOf="parent" />
+                <ImageView
+                    android:id="@+id/car_ui_toolbar_nav_icon"
+                    style="@style/Widget.CarUi.Toolbar.NavIcon"
+                    android:layout_width="@dimen/car_ui_toolbar_nav_icon_size"
+                    android:layout_height="@dimen/car_ui_toolbar_nav_icon_size"
+                    android:layout_gravity="center"
+                    android:scaleType="fitXY"/>
 
-    </androidx.constraintlayout.widget.ConstraintLayout>
+                <ImageView
+                    android:id="@+id/car_ui_toolbar_logo"
+                    android:layout_width="@dimen/car_ui_toolbar_logo_size"
+                    android:layout_height="@dimen/car_ui_toolbar_logo_size"
+                    android:layout_gravity="center"
+                    android:scaleType="fitXY"/>
+            </FrameLayout>
+
+            <FrameLayout
+                android:id="@+id/car_ui_toolbar_title_logo_container"
+                style="@style/Widget.CarUi.Toolbar.LogoContainer"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                app:layout_constraintBottom_toBottomOf="parent"
+                app:layout_constraintStart_toEndOf="@id/car_ui_toolbar_nav_icon_container"
+                app:layout_constraintTop_toTopOf="parent">
+
+                <ImageView
+                    android:id="@+id/car_ui_toolbar_title_logo"
+                    style="@style/Widget.CarUi.Toolbar.Logo"
+                    android:layout_width="@dimen/car_ui_toolbar_logo_size"
+                    android:layout_height="@dimen/car_ui_toolbar_logo_size"
+                    android:layout_gravity="center"
+                    android:scaleType="fitXY"/>
+            </FrameLayout>
+
+            <LinearLayout android:layout_height="wrap_content"
+                          android:layout_width="0dp"
+                          android:id="@+id/car_ui_toolbar_title_container"
+                          android:orientation="vertical"
+                          android:layout_marginStart="@dimen/car_ui_toolbar_title_margin_start"
+                          app:layout_goneMarginStart="@dimen/car_ui_toolbar_title_no_logo_margin_start"
+                          app:layout_constraintBottom_toBottomOf="parent"
+                          app:layout_constraintEnd_toStartOf="@+id/car_ui_toolbar_menu_items_container"
+                          app:layout_constraintStart_toEndOf="@+id/car_ui_toolbar_title_logo_container"
+                          app:layout_constraintTop_toTopOf="parent">
+                <TextView android:id="@+id/car_ui_toolbar_title"
+                          android:layout_width="wrap_content"
+                          android:layout_height="wrap_content"
+                          android:singleLine="true"
+                          style="@style/Widget.CarUi.Toolbar.Title"/>
+                <TextView android:id="@+id/car_ui_toolbar_subtitle"
+                          android:layout_width="wrap_content"
+                          android:layout_height="wrap_content"
+                          android:visibility="gone"
+                          style="@style/Widget.CarUi.Toolbar.Subtitle"/>
+            </LinearLayout>
+
+            <com.android.car.ui.toolbar.TabLayout
+                android:id="@+id/car_ui_toolbar_tabs"
+                android:layout_width="wrap_content"
+                android:layout_height="0dp"
+                app:layout_constraintBottom_toBottomOf="parent"
+                app:layout_constraintEnd_toStartOf="@+id/car_ui_toolbar_menu_items_container"
+                app:layout_constraintHorizontal_bias="0.0"
+                app:layout_constraintStart_toEndOf="@+id/car_ui_toolbar_title_logo_container"
+                app:layout_constraintTop_toTopOf="parent"/>
+
+            <LinearLayout
+                android:id="@+id/car_ui_toolbar_menu_items_container"
+                style="@style/Widget.CarUi.Toolbar.MenuItem.Container"
+                android:layout_width="wrap_content"
+                android:layout_height="0dp"
+                android:orientation="horizontal"
+                app:layout_constraintBottom_toBottomOf="parent"
+                app:layout_constraintEnd_toEndOf="parent"
+                app:layout_constraintTop_toTopOf="parent"/>
+
+            <FrameLayout
+                android:id="@+id/car_ui_toolbar_search_view_container"
+                android:layout_width="0dp"
+                android:layout_height="@dimen/car_ui_toolbar_search_height"
+                app:layout_constraintBottom_toBottomOf="parent"
+                app:layout_constraintEnd_toStartOf="@+id/car_ui_toolbar_menu_items_container"
+                app:layout_constraintStart_toEndOf="@+id/car_ui_toolbar_nav_icon_container"
+                app:layout_constraintTop_toTopOf="parent"/>
+
+            <ProgressBar
+                android:id="@+id/car_ui_toolbar_progress_bar"
+                style="@style/Widget.CarUi.Toolbar.ProgressBar"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:indeterminate="true"
+                android:visibility="gone"
+                app:layout_constraintBottom_toBottomOf="parent"
+                app:layout_constraintEnd_toEndOf="parent"
+                app:layout_constraintStart_toStartOf="parent"/>
+
+        </androidx.constraintlayout.widget.ConstraintLayout>
+    </com.android.car.ui.FocusArea>
 
 </androidx.constraintlayout.widget.ConstraintLayout>
-
diff --git a/car-ui-lib/res/layout/car_ui_base_layout_toolbar_legacy.xml b/car-ui-lib/res/layout/car_ui_base_layout_toolbar_legacy.xml
new file mode 100644
index 0000000..0a55746
--- /dev/null
+++ b/car-ui-lib/res/layout/car_ui_base_layout_toolbar_legacy.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2020 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<!-- This layout is used on P or earlier, to support OEMs that shipped
+     on P and only customized the non-baselayout version of the toolbar -->
+<androidx.constraintlayout.widget.ConstraintLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <!-- When not in touch mode, if we clear focus in current window, Android will re-focus the
+         first focusable view in the window automatically. Adding a FocusParkingView to the window
+         can fix this issue, because it can take focus, and it is transparent and its default focus
+         highlight is disabled, so it's invisible to the user no matter whether it's focused or not.
+         -->
+    <com.android.car.ui.FocusParkingView
+        android:layout_width="1dp"
+        android:layout_height="1dp"/>
+
+    <FrameLayout
+        android:id="@+id/content"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <com.android.car.ui.toolbar.Toolbar
+        android:id="@+id/car_ui_toolbar"
+        android:tag="car_ui_top_inset"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        app:layout_constraintTop_toTopOf="parent" />
+
+</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/car-ui-lib/res/layout/car_ui_check_box_list_item.xml b/car-ui-lib/res/layout/car_ui_check_box_list_item.xml
index 59f0726..2f5c7a8 100644
--- a/car-ui-lib/res/layout/car_ui_check_box_list_item.xml
+++ b/car-ui-lib/res/layout/car_ui_check_box_list_item.xml
@@ -62,4 +62,4 @@
         app:layout_constraintStart_toEndOf="@+id/check_box_container"
         app:layout_constraintTop_toTopOf="parent" />
 
-</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
+</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/car-ui-lib/res/layout/car_ui_header_list_item.xml b/car-ui-lib/res/layout/car_ui_header_list_item.xml
index 8f07636..d91512e 100644
--- a/car-ui-lib/res/layout/car_ui_header_list_item.xml
+++ b/car-ui-lib/res/layout/car_ui_header_list_item.xml
@@ -33,7 +33,7 @@
         android:id="@+id/title"
         android:layout_width="0dp"
         android:layout_height="wrap_content"
-        android:layout_marginStart="@dimen/car_ui_list_item_text_no_icon_start_margin"
+        android:layout_marginStart="@dimen/car_ui_header_list_item_text_start_margin"
         android:textAppearance="@style/TextAppearance.CarUi.ListItem.Header"
         app:layout_constraintBottom_toTopOf="@+id/body"
         app:layout_constraintEnd_toEndOf="parent"
@@ -52,4 +52,4 @@
         app:layout_constraintStart_toStartOf="@id/car_ui_list_item_start_guideline"
         app:layout_constraintTop_toBottomOf="@+id/title" />
 
-</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
+</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/car-ui-lib/res/layout/car_ui_list_item.xml b/car-ui-lib/res/layout/car_ui_list_item.xml
index d838fcb..cc5c39a 100644
--- a/car-ui-lib/res/layout/car_ui_list_item.xml
+++ b/car-ui-lib/res/layout/car_ui_list_item.xml
@@ -20,7 +20,9 @@
     xmlns:app="http://schemas.android.com/apk/res-auto"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:minHeight="@dimen/car_ui_list_item_height">
+    android:tag="carUiListItem"
+    android:minHeight="@dimen/car_ui_list_item_height"
+    app:layout_optimizationLevel="none">
 
     <!-- The following touch interceptor views are sized to encompass the specific sub-sections of
     the list item view to easily control the bounds of a background ripple effects. -->
@@ -183,4 +185,5 @@
         android:orientation="vertical"
         app:layout_constraintGuide_end="@dimen/car_ui_list_item_end_inset" />
 
-</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
+</androidx.constraintlayout.widget.ConstraintLayout>
+
diff --git a/car-ui-lib/res/layout/car_ui_list_preference.xml b/car-ui-lib/res/layout/car_ui_list_preference.xml
index 88957b0..70bf96d 100644
--- a/car-ui-lib/res/layout/car_ui_list_preference.xml
+++ b/car-ui-lib/res/layout/car_ui_list_preference.xml
@@ -26,12 +26,7 @@
         android:id="@+id/list"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
+        android:tag="carUiPreferenceRecyclerView"
         app:enableDivider="true" />
 
-    <com.android.car.ui.toolbar.Toolbar
-        android:id="@+id/toolbar"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        app:state="subpage" />
-
-</FrameLayout>
\ No newline at end of file
+</FrameLayout>
diff --git a/car-ui-lib/res/layout/car_ui_list_preference_with_toolbar.xml b/car-ui-lib/res/layout/car_ui_list_preference_with_toolbar.xml
new file mode 100644
index 0000000..f42c9f1
--- /dev/null
+++ b/car-ui-lib/res/layout/car_ui_list_preference_with_toolbar.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright 2020 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:id="@+id/container"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="@drawable/car_ui_activity_background">
+
+    <com.android.car.ui.recyclerview.CarUiRecyclerView
+        android:id="@+id/list"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:tag="carUiPreferenceRecyclerView"
+        app:enableDivider="true" />
+
+    <com.android.car.ui.toolbar.Toolbar
+        android:id="@+id/toolbar"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        app:car_ui_state="subpage" />
+
+</FrameLayout>
diff --git a/car-ui-lib/res/layout/car_ui_preference.xml b/car-ui-lib/res/layout/car_ui_preference.xml
index 03e101d..52dbd68 100644
--- a/car-ui-lib/res/layout/car_ui_preference.xml
+++ b/car-ui-lib/res/layout/car_ui_preference.xml
@@ -23,6 +23,7 @@
     android:clipToPadding="false"
     android:minHeight="?android:attr/listPreferredItemHeightSmall"
     android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+    android:tag="carUiPreference"
     android:paddingStart="?android:attr/listPreferredItemPaddingStart">
 
     <ImageView
diff --git a/car-ui-lib/res/layout/car_ui_preference_chevron.xml b/car-ui-lib/res/layout/car_ui_preference_chevron.xml
index efeaddb..e63e74c 100644
--- a/car-ui-lib/res/layout/car_ui_preference_chevron.xml
+++ b/car-ui-lib/res/layout/car_ui_preference_chevron.xml
@@ -18,4 +18,4 @@
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:layout_gravity="center_horizontal"
-    android:src="@drawable/car_ui_preference_icon_chevron"/>
\ No newline at end of file
+    android:src="@drawable/car_ui_preference_icon_chevron"/>
diff --git a/car-ui-lib/res/layout/car_ui_preference_fragment.xml b/car-ui-lib/res/layout/car_ui_preference_fragment.xml
index 7298055..e17664a 100644
--- a/car-ui-lib/res/layout/car_ui_preference_fragment.xml
+++ b/car-ui-lib/res/layout/car_ui_preference_fragment.xml
@@ -30,6 +30,7 @@
             android:id="@+id/recycler_view"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
+            android:tag="carUiPreferenceRecyclerView"
             app:enableDivider="true"/>
     </FrameLayout>
 </FrameLayout>
diff --git a/car-ui-lib/res/layout/car_ui_preference_fragment_with_toolbar.xml b/car-ui-lib/res/layout/car_ui_preference_fragment_with_toolbar.xml
index 4acb10d..cf55067 100644
--- a/car-ui-lib/res/layout/car_ui_preference_fragment_with_toolbar.xml
+++ b/car-ui-lib/res/layout/car_ui_preference_fragment_with_toolbar.xml
@@ -31,6 +31,7 @@
             android:id="@+id/recycler_view"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
+            android:tag="carUiPreferenceRecyclerView"
             app:enableDivider="true"/>
     </FrameLayout>
 
@@ -38,5 +39,5 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:id="@+id/toolbar"
-        app:state="subpage"/>
+        app:car_ui_state="subpage"/>
 </FrameLayout>
diff --git a/car-ui-lib/res/layout/car_ui_radio_button_preference_widget.xml b/car-ui-lib/res/layout/car_ui_radio_button_preference_widget.xml
new file mode 100644
index 0000000..d179a09
--- /dev/null
+++ b/car-ui-lib/res/layout/car_ui_radio_button_preference_widget.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright 2019 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+
+<RadioButton
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/radio_button"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:layout_gravity="center"
+    android:clickable="false"
+    android:focusable="false"/>
diff --git a/car-ui-lib/res/layout/car_ui_recycler_view.xml b/car-ui-lib/res/layout/car_ui_recycler_view.xml
index 29150d7..1aa70fa 100644
--- a/car-ui-lib/res/layout/car_ui_recycler_view.xml
+++ b/car-ui-lib/res/layout/car_ui_recycler_view.xml
@@ -16,12 +16,13 @@
   -->
 <merge xmlns:android="http://schemas.android.com/apk/res/android">
 
-  <include layout="@layout/car_ui_recyclerview_scrollbar"/>
+    <include layout="@layout/car_ui_recyclerview_scrollbar"/>
 
-  <FrameLayout
-      android:id="@+id/car_ui_recycler_view"
-      android:layout_width="0dp"
-      android:layout_height="match_parent"
-      android:layout_marginEnd="@dimen/car_ui_scrollbar_margin"
-      android:layout_weight="1"/>
-</merge>
\ No newline at end of file
+    <com.android.car.ui.recyclerview.CarUiRecyclerViewContainer
+        android:id="@+id/car_ui_recycler_view"
+        android:layout_width="0dp"
+        android:layout_height="match_parent"
+        android:layout_marginEnd="@dimen/car_ui_scrollbar_margin"
+        android:tag="carUiRecyclerView"
+        android:layout_weight="1"/>
+</merge>
diff --git a/car-ui-lib/res/layout/car_ui_recyclerview_scrollbar.xml b/car-ui-lib/res/layout/car_ui_recyclerview_scrollbar.xml
index ceadfaf..5896819 100644
--- a/car-ui-lib/res/layout/car_ui_recyclerview_scrollbar.xml
+++ b/car-ui-lib/res/layout/car_ui_recyclerview_scrollbar.xml
@@ -15,16 +15,16 @@
   ~ limitations under the License.
   -->
 
-<LinearLayout
+<androidx.constraintlayout.widget.ConstraintLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
-    android:orientation="vertical"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
     android:layout_width="@dimen/car_ui_scrollbar_container_width"
     android:layout_height="match_parent"
     android:id="@+id/car_ui_scroll_bar"
     android:gravity="center">
 
-    <ImageButton
-        android:id="@+id/page_up"
+    <ImageView
+        android:id="@+id/car_ui_scrollbar_page_up"
         android:layout_width="@dimen/car_ui_scrollbar_button_size"
         android:layout_height="@dimen/car_ui_scrollbar_button_size"
         android:background="@drawable/car_ui_recyclerview_button_ripple_background"
@@ -32,18 +32,36 @@
         android:focusable="false"
         android:hapticFeedbackEnabled="false"
         android:src="@drawable/car_ui_recyclerview_ic_up"
-        android:scaleType="centerInside" />
+        android:scaleType="centerInside"
+        android:layout_marginTop="15dp"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintRight_toRightOf="parent"/>
 
     <!-- View height is dynamically calculated during layout. -->
     <View
-        android:id="@+id/scrollbar_thumb"
+        android:id="@+id/car_ui_scrollbar_thumb"
         android:layout_width="@dimen/car_ui_scrollbar_thumb_width"
         android:layout_height="0dp"
         android:layout_gravity="center_horizontal"
-        android:background="@drawable/car_ui_recyclerview_scrollbar_thumb" />
+        android:background="@drawable/car_ui_recyclerview_scrollbar_thumb"
+        app:layout_constraintTop_toBottomOf="@+id/car_ui_scrollbar_page_up"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintRight_toRightOf="parent"/>
 
-    <ImageButton
-        android:id="@+id/page_down"
+    <View
+        android:id="@+id/car_ui_scrollbar_track"
+        android:layout_width="0dp"
+        android:layout_height="0dp"
+        android:layout_marginTop="@dimen/car_ui_scrollbar_separator_margin"
+        android:layout_marginBottom="@dimen/car_ui_scrollbar_separator_margin"
+        app:layout_constraintTop_toBottomOf="@+id/car_ui_scrollbar_page_up"
+        app:layout_constraintBottom_toTopOf="@+id/car_ui_scrollbar_page_down"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"/>
+
+    <ImageView
+        android:id="@+id/car_ui_scrollbar_page_down"
         android:layout_width="@dimen/car_ui_scrollbar_button_size"
         android:layout_height="@dimen/car_ui_scrollbar_button_size"
         android:background="@drawable/car_ui_recyclerview_button_ripple_background"
@@ -51,5 +69,9 @@
         android:focusable="false"
         android:hapticFeedbackEnabled="false"
         android:src="@drawable/car_ui_recyclerview_ic_down"
-        android:scaleType="centerInside" />
-</LinearLayout>
+        android:scaleType="centerInside"
+        android:layout_marginBottom="15dp"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintRight_toRightOf="parent"/>
+</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/car-ui-lib/res/layout/car_ui_seekbar_dialog.xml b/car-ui-lib/res/layout/car_ui_seekbar_dialog.xml
new file mode 100644
index 0000000..90124c4
--- /dev/null
+++ b/car-ui-lib/res/layout/car_ui_seekbar_dialog.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+     Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              android:layout_width="match_parent"
+              android:layout_height="match_parent"
+              android:gravity="center_horizontal"
+              android:orientation="vertical">
+
+    <TextView
+        android:id="@+id/seek_bar_text_top"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:gravity="center_horizontal"
+        style="@style/Preference.CarUi.DialogSeekBarPreference.TopText"/>
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="horizontal" >
+
+        <TextView
+            android:id="@+id/seek_bar_text_left"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:visibility="gone"
+            style="@style/Preference.CarUi.DialogSeekBarPreference.LeftText"/>
+
+        <SeekBar
+            android:id="@+id/seek_bar"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            style="@style/Preference.CarUi.DialogSeekBarPreference.Seekbar"/>
+
+        <TextView
+            android:id="@+id/seek_bar_text_right"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:visibility="gone"
+            style="@style/Preference.CarUi.DialogSeekBarPreference.RightText"/>
+    </LinearLayout>
+
+</LinearLayout>
diff --git a/car-ui-lib/res/layout/car_ui_toolbar.xml b/car-ui-lib/res/layout/car_ui_toolbar.xml
index f6ba021..42cc59a 100644
--- a/car-ui-lib/res/layout/car_ui_toolbar.xml
+++ b/car-ui-lib/res/layout/car_ui_toolbar.xml
@@ -14,163 +14,169 @@
   See the License for the specific language governing permissions and
   limitations under the License.
 -->
-<androidx.constraintlayout.widget.ConstraintLayout
+<com.android.car.ui.FocusArea
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
     android:layout_width="match_parent"
-    android:layout_height="@dimen/car_ui_toolbar_first_row_height"
-    android:id="@+id/car_ui_toolbar_background"
-    style="@style/Widget.CarUi.Toolbar.Container">
-
-    <!-- When the user finishes searching, we call clearFocus() on the editText in the search bar.
-         clearFocus() will actually send the focus to the first focusable thing in the layout.
-         If that focusable thing is still the search bar it will just reselect it, and the user won't
-         be able to deselect. So make a focusable view here to guarantee that we can clear the focus -->
-    <View
-        android:layout_width="1dp"
-        android:layout_height="1dp"
-        android:focusable="true"
-        android:focusableInTouchMode="true"/>
-
-    <androidx.constraintlayout.widget.Guideline
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:id="@+id/car_ui_toolbar_start_guideline"
-        app:layout_constraintGuide_begin="@dimen/car_ui_toolbar_start_inset"
-        android:orientation="vertical"/>
-
-    <androidx.constraintlayout.widget.Guideline
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:id="@+id/car_ui_toolbar_top_guideline"
-        app:layout_constraintGuide_begin="@dimen/car_ui_toolbar_top_inset"
-        android:orientation="horizontal"/>
-
-    <androidx.constraintlayout.widget.Guideline
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:id="@+id/car_ui_toolbar_end_guideline"
-        app:layout_constraintGuide_end="@dimen/car_ui_toolbar_end_inset"
-        android:orientation="vertical"/>
-
-    <androidx.constraintlayout.widget.Guideline
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:id="@+id/car_ui_toolbar_bottom_guideline"
-        app:layout_constraintGuide_end="@dimen/car_ui_toolbar_bottom_inset"
-        android:orientation="horizontal"/>
-
-    <!-- The horizontal bias here is so that when you set this view as GONE, it will be
-         treated as if it's all the way to the left instead of centered in the margin -->
-    <FrameLayout
-        android:id="@+id/car_ui_toolbar_nav_icon_container"
-        android:layout_width="@dimen/car_ui_toolbar_margin"
-        android:layout_height="0dp"
-        style="@style/Widget.CarUi.Toolbar.NavIconContainer"
-        app:layout_constraintTop_toTopOf="@id/car_ui_toolbar_top_guideline"
-        app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_bottom_guideline"
-        app:layout_constraintStart_toEndOf="@id/car_ui_toolbar_start_guideline"
-        app:layout_constraintHorizontal_bias="0.0">
-        <ImageView
-            android:id="@+id/car_ui_toolbar_nav_icon"
-            android:layout_width="@dimen/car_ui_toolbar_nav_icon_size"
-            android:layout_height="@dimen/car_ui_toolbar_nav_icon_size"
-            android:layout_gravity="center"
-            android:scaleType="fitXY"
-            style="@style/Widget.CarUi.Toolbar.NavIcon"/>
-        <ImageView
-            android:id="@+id/car_ui_toolbar_logo"
-            android:layout_width="@dimen/car_ui_toolbar_logo_size"
-            android:layout_height="@dimen/car_ui_toolbar_logo_size"
-            android:layout_gravity="center"
-            android:scaleType="fitXY"/>
-    </FrameLayout>
-
-    <FrameLayout
-        android:id="@+id/car_ui_toolbar_title_logo_container"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        style="@style/Widget.CarUi.Toolbar.LogoContainer"
-        app:layout_constraintTop_toTopOf="@id/car_ui_toolbar_top_guideline"
-        app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_bottom_guideline"
-        app:layout_constraintStart_toEndOf="@id/car_ui_toolbar_nav_icon_container">
-
-        <ImageView
-            android:id="@+id/car_ui_toolbar_title_logo"
-            android:layout_width="@dimen/car_ui_toolbar_logo_size"
-            android:layout_height="@dimen/car_ui_toolbar_logo_size"
-            android:scaleType="fitXY"
-            android:layout_gravity="center"
-            style="@style/Widget.CarUi.Toolbar.Logo"/>
-    </FrameLayout>
-
-    <TextView
-        android:id="@+id/car_ui_toolbar_title"
-        android:layout_width="0dp"
-        android:layout_height="wrap_content"
-        android:singleLine="true"
-        style="@style/Widget.CarUi.Toolbar.Title"
-        app:layout_constraintTop_toTopOf="@id/car_ui_toolbar_top_guideline"
-        app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_bottom_guideline"
-        app:layout_constraintStart_toEndOf="@+id/car_ui_toolbar_title_logo_container"
-        app:layout_constraintEnd_toStartOf="@+id/car_ui_toolbar_menu_items_container"/>
-
-    <com.android.car.ui.toolbar.TabLayout
-        android:id="@+id/car_ui_toolbar_tabs"
-        android:layout_width="wrap_content"
-        android:layout_height="0dp"
-        app:layout_constraintTop_toTopOf="@id/car_ui_toolbar_top_guideline"
-        app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_bottom_guideline"
-        app:layout_constraintStart_toEndOf="@+id/car_ui_toolbar_title_logo_container"
-        app:layout_constraintEnd_toStartOf="@+id/car_ui_toolbar_menu_items_container"
-        app:layout_constraintHorizontal_bias="0.0"/>
-
-    <LinearLayout
-        android:id="@+id/car_ui_toolbar_menu_items_container"
-        android:layout_width="wrap_content"
-        android:layout_height="0dp"
-        android:orientation="horizontal"
-        style="@style/Widget.CarUi.Toolbar.MenuItem.Container"
-        app:layout_constraintTop_toTopOf="@id/car_ui_toolbar_top_guideline"
-        app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_bottom_guideline"
-        app:layout_constraintEnd_toStartOf="@+id/car_ui_toolbar_end_guideline"/>
-
-    <FrameLayout
-        android:id="@+id/car_ui_toolbar_search_view_container"
-        android:layout_width="0dp"
-        android:layout_height="@dimen/car_ui_toolbar_search_height"
-        app:layout_constraintTop_toTopOf="@id/car_ui_toolbar_top_guideline"
-        app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_bottom_guideline"
-        app:layout_constraintStart_toEndOf="@+id/car_ui_toolbar_nav_icon_container"
-        app:layout_constraintEnd_toStartOf="@+id/car_ui_toolbar_menu_items_container"/>
-
-    <View
-        android:id="@+id/car_ui_toolbar_row_separator"
+    android:layout_height="@dimen/car_ui_toolbar_first_row_height">
+    <androidx.constraintlayout.widget.ConstraintLayout
+        xmlns:app="http://schemas.android.com/apk/res-auto"
         android:layout_width="match_parent"
-        android:layout_height="@dimen/car_ui_toolbar_separator_height"
-        style="@style/Widget.CarUi.Toolbar.SeparatorView"
-        app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_bottom_guideline"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintEnd_toEndOf="parent"/>
+        android:layout_height="match_parent"
+        android:id="@+id/car_ui_toolbar_background"
+        android:tag="carUiToolbar"
+        style="@style/Widget.CarUi.Toolbar.Container">
 
-    <ProgressBar
-        android:id="@+id/car_ui_toolbar_progress_bar"
-        style="@style/Widget.CarUi.Toolbar.ProgressBar"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_row_separator"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintEnd_toEndOf="parent"
-        android:indeterminate="true"
-        android:visibility="gone"/>
+        <androidx.constraintlayout.widget.Guideline
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:id="@+id/car_ui_toolbar_start_guideline"
+            app:layout_constraintGuide_begin="@dimen/car_ui_toolbar_start_inset"
+            android:orientation="vertical"/>
 
-    <View
-        android:id="@+id/car_ui_toolbar_bottom_styleable"
-        android:layout_width="match_parent"
-        android:layout_height="@dimen/car_ui_toolbar_bottom_view_height"
-        style="@style/Widget.CarUi.Toolbar.BottomView"
-        app:layout_constraintBottom_toTopOf="@+id/car_ui_toolbar_progress_bar"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintEnd_toEndOf="parent"/>
+        <androidx.constraintlayout.widget.Guideline
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:id="@+id/car_ui_toolbar_top_guideline"
+            app:layout_constraintGuide_begin="@dimen/car_ui_toolbar_top_inset"
+            android:orientation="horizontal"/>
 
-</androidx.constraintlayout.widget.ConstraintLayout>
+        <androidx.constraintlayout.widget.Guideline
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:id="@+id/car_ui_toolbar_end_guideline"
+            app:layout_constraintGuide_end="@dimen/car_ui_toolbar_end_inset"
+            android:orientation="vertical"/>
+
+        <androidx.constraintlayout.widget.Guideline
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:id="@+id/car_ui_toolbar_bottom_guideline"
+            app:layout_constraintGuide_end="@dimen/car_ui_toolbar_bottom_inset"
+            android:orientation="horizontal"/>
+
+        <!-- The horizontal bias here is so that when you set this view as GONE, it will be
+             treated as if it's all the way to the left instead of centered in the margin -->
+        <FrameLayout
+            android:id="@+id/car_ui_toolbar_nav_icon_container"
+            android:layout_width="@dimen/car_ui_toolbar_margin"
+            android:layout_height="0dp"
+            style="@style/Widget.CarUi.Toolbar.NavIconContainer"
+            app:layout_constraintTop_toTopOf="@id/car_ui_toolbar_top_guideline"
+            app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_bottom_guideline"
+            app:layout_constraintStart_toEndOf="@id/car_ui_toolbar_start_guideline"
+            app:layout_constraintHorizontal_bias="0.0">
+            <ImageView
+                android:id="@+id/car_ui_toolbar_nav_icon"
+                android:layout_width="@dimen/car_ui_toolbar_nav_icon_size"
+                android:layout_height="@dimen/car_ui_toolbar_nav_icon_size"
+                android:layout_gravity="center"
+                android:scaleType="fitXY"
+                style="@style/Widget.CarUi.Toolbar.NavIcon"/>
+            <ImageView
+                android:id="@+id/car_ui_toolbar_logo"
+                android:layout_width="@dimen/car_ui_toolbar_logo_size"
+                android:layout_height="@dimen/car_ui_toolbar_logo_size"
+                android:layout_gravity="center"
+                android:scaleType="fitXY"/>
+        </FrameLayout>
+
+        <FrameLayout
+            android:id="@+id/car_ui_toolbar_title_logo_container"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            style="@style/Widget.CarUi.Toolbar.LogoContainer"
+            app:layout_constraintTop_toTopOf="@id/car_ui_toolbar_top_guideline"
+            app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_bottom_guideline"
+            app:layout_constraintStart_toEndOf="@id/car_ui_toolbar_nav_icon_container">
+
+            <ImageView
+                android:id="@+id/car_ui_toolbar_title_logo"
+                android:layout_width="@dimen/car_ui_toolbar_logo_size"
+                android:layout_height="@dimen/car_ui_toolbar_logo_size"
+                android:scaleType="fitXY"
+                android:layout_gravity="center"
+                style="@style/Widget.CarUi.Toolbar.Logo"/>
+        </FrameLayout>
+
+        <LinearLayout android:layout_height="wrap_content"
+                      android:layout_width="0dp"
+                      android:id="@+id/car_ui_toolbar_title_container"
+                      android:orientation="vertical"
+                      android:layout_marginStart="@dimen/car_ui_toolbar_title_margin_start"
+                      app:layout_goneMarginStart="@dimen/car_ui_toolbar_title_no_logo_margin_start"
+                      app:layout_constraintTop_toTopOf="@id/car_ui_toolbar_top_guideline"
+                      app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_bottom_guideline"
+                      app:layout_constraintStart_toEndOf="@+id/car_ui_toolbar_title_logo_container"
+                      app:layout_constraintEnd_toStartOf="@+id/car_ui_toolbar_menu_items_container">
+            <TextView android:id="@+id/car_ui_toolbar_title"
+                      android:layout_width="wrap_content"
+                      android:layout_height="wrap_content"
+                      android:singleLine="true"
+                      style="@style/Widget.CarUi.Toolbar.Title"/>
+            <TextView android:id="@+id/car_ui_toolbar_subtitle"
+                      android:layout_width="wrap_content"
+                      android:layout_height="wrap_content"
+                      android:visibility="gone"
+                      style="@style/Widget.CarUi.Toolbar.Subtitle"/>
+        </LinearLayout>
+
+        <com.android.car.ui.toolbar.TabLayout
+            android:id="@+id/car_ui_toolbar_tabs"
+            android:layout_width="wrap_content"
+            android:layout_height="0dp"
+            app:layout_constraintTop_toTopOf="@id/car_ui_toolbar_top_guideline"
+            app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_bottom_guideline"
+            app:layout_constraintStart_toEndOf="@+id/car_ui_toolbar_title_logo_container"
+            app:layout_constraintEnd_toStartOf="@+id/car_ui_toolbar_menu_items_container"
+            app:layout_constraintHorizontal_bias="0.0"/>
+
+        <LinearLayout
+            android:id="@+id/car_ui_toolbar_menu_items_container"
+            android:layout_width="wrap_content"
+            android:layout_height="0dp"
+            android:orientation="horizontal"
+            style="@style/Widget.CarUi.Toolbar.MenuItem.Container"
+            app:layout_constraintTop_toTopOf="@id/car_ui_toolbar_top_guideline"
+            app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_bottom_guideline"
+            app:layout_constraintEnd_toStartOf="@+id/car_ui_toolbar_end_guideline"/>
+
+        <FrameLayout
+            android:id="@+id/car_ui_toolbar_search_view_container"
+            android:layout_width="0dp"
+            android:layout_height="@dimen/car_ui_toolbar_search_height"
+            app:layout_constraintTop_toTopOf="@id/car_ui_toolbar_top_guideline"
+            app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_bottom_guideline"
+            app:layout_constraintStart_toEndOf="@+id/car_ui_toolbar_nav_icon_container"
+            app:layout_constraintEnd_toStartOf="@+id/car_ui_toolbar_menu_items_container"/>
+
+        <View
+            android:id="@+id/car_ui_toolbar_row_separator"
+            android:layout_width="match_parent"
+            android:layout_height="@dimen/car_ui_toolbar_separator_height"
+            style="@style/Widget.CarUi.Toolbar.SeparatorView"
+            app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_bottom_guideline"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"/>
+
+        <ProgressBar
+            android:id="@+id/car_ui_toolbar_progress_bar"
+            style="@style/Widget.CarUi.Toolbar.ProgressBar"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_row_separator"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"
+            android:indeterminate="true"
+            android:visibility="gone"/>
+
+        <View
+            android:id="@+id/car_ui_toolbar_bottom_styleable"
+            android:layout_width="match_parent"
+            android:layout_height="@dimen/car_ui_toolbar_bottom_view_height"
+            style="@style/Widget.CarUi.Toolbar.BottomView"
+            app:layout_constraintBottom_toTopOf="@+id/car_ui_toolbar_progress_bar"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"/>
+
+    </androidx.constraintlayout.widget.ConstraintLayout>
+</com.android.car.ui.FocusArea>
diff --git a/car-ui-lib/res/layout/car_ui_toolbar_two_row.xml b/car-ui-lib/res/layout/car_ui_toolbar_two_row.xml
index 428a2b6..9fecb3f 100644
--- a/car-ui-lib/res/layout/car_ui_toolbar_two_row.xml
+++ b/car-ui-lib/res/layout/car_ui_toolbar_two_row.xml
@@ -14,164 +14,169 @@
   See the License for the specific language governing permissions and
   limitations under the License.
 -->
-<androidx.constraintlayout.widget.ConstraintLayout
+<com.android.car.ui.FocusArea
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
     android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:id="@+id/car_ui_toolbar_background"
-    style="@style/Widget.CarUi.Toolbar.Container">
-
-    <androidx.constraintlayout.widget.Guideline
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:id="@+id/car_ui_toolbar_start_guideline"
-        app:layout_constraintGuide_begin="@dimen/car_ui_toolbar_start_inset"
-        android:orientation="vertical"/>
-
-    <androidx.constraintlayout.widget.Guideline
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:id="@+id/car_ui_toolbar_top_guideline"
-        app:layout_constraintGuide_begin="@dimen/car_ui_toolbar_top_inset"
-        android:orientation="horizontal"/>
-
-    <androidx.constraintlayout.widget.Guideline
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:id="@+id/car_ui_toolbar_end_guideline"
-        app:layout_constraintGuide_end="@dimen/car_ui_toolbar_end_inset"
-        android:orientation="vertical"/>
-
-    <androidx.constraintlayout.widget.Guideline
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:id="@+id/car_ui_toolbar_bottom_guideline"
-        app:layout_constraintGuide_end="@dimen/car_ui_toolbar_bottom_inset"
-        android:orientation="horizontal"/>
-
-    <!-- When the user finishes searching, we call clearFocus() on the editText in the search bar.
-         clearFocus() will actually send the focus to the first focusable thing in the layout.
-         If that focusable thing is still the search bar it will just reselect it, and the user won't
-         be able to deselect. So make a focusable view here to guarantee that we can clear the focus -->
-    <View
-        android:layout_width="1dp"
-        android:layout_height="1dp"
-        android:focusable="true"
-        android:focusableInTouchMode="true"/>
-
-    <androidx.constraintlayout.widget.Guideline
-        android:id="@+id/car_ui_toolbar_row_separator_guideline"
-        android:layout_width="0dp"
-        android:layout_height="0dp"
-        android:orientation="horizontal"
-        app:layout_constraintGuide_begin="@dimen/car_ui_toolbar_first_row_height"/>
-
-    <View
-        android:id="@+id/car_ui_toolbar_row_separator"
-        android:layout_width="match_parent"
-        android:layout_height="@dimen/car_ui_toolbar_separator_height"
-        style="@style/Widget.CarUi.Toolbar.SeparatorView"
-        app:layout_constraintTop_toBottomOf="@id/car_ui_toolbar_row_separator_guideline"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintEnd_toEndOf="parent"/>
-
-    <FrameLayout
-        android:id="@+id/car_ui_toolbar_nav_icon_container"
-        android:layout_width="@dimen/car_ui_toolbar_margin"
-        android:layout_height="0dp"
-        style="@style/Widget.CarUi.Toolbar.NavIconContainer"
-        app:layout_constraintTop_toTopOf="@id/car_ui_toolbar_top_guideline"
-        app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_row_separator"
-        app:layout_constraintStart_toStartOf="@id/car_ui_toolbar_start_guideline">
-        <ImageView
-            android:id="@+id/car_ui_toolbar_nav_icon"
-            android:layout_width="@dimen/car_ui_toolbar_nav_icon_size"
-            android:layout_height="@dimen/car_ui_toolbar_nav_icon_size"
-            android:layout_gravity="center"
-            android:scaleType="fitXY"
-            style="@style/Widget.CarUi.Toolbar.NavIcon"/>
-        <ImageView
-            android:id="@+id/car_ui_toolbar_logo"
-            android:layout_width="@dimen/car_ui_toolbar_logo_size"
-            android:layout_height="@dimen/car_ui_toolbar_logo_size"
-            android:layout_gravity="center"
-            android:scaleType="fitXY"/>
-    </FrameLayout>
-
-    <FrameLayout
-        android:id="@+id/car_ui_toolbar_title_logo_container"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        style="@style/Widget.CarUi.Toolbar.LogoContainer"
-        app:layout_constraintTop_toTopOf="@id/car_ui_toolbar_top_guideline"
-        app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_row_separator"
-        app:layout_constraintStart_toEndOf="@id/car_ui_toolbar_nav_icon_container">
-
-        <ImageView
-            android:id="@+id/car_ui_toolbar_title_logo"
-            android:layout_width="@dimen/car_ui_toolbar_logo_size"
-            android:layout_height="@dimen/car_ui_toolbar_logo_size"
-            android:scaleType="fitXY"
-            android:layout_gravity="center"
-            style="@style/Widget.CarUi.Toolbar.Logo"/>
-    </FrameLayout>
-
-    <TextView
-        android:id="@+id/car_ui_toolbar_title"
-        android:layout_width="0dp"
-        android:layout_height="wrap_content"
-        android:singleLine="true"
-        style="@style/Widget.CarUi.Toolbar.Title"
-        app:layout_constraintTop_toTopOf="@id/car_ui_toolbar_top_guideline"
-        app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_row_separator"
-        app:layout_constraintStart_toEndOf="@id/car_ui_toolbar_title_logo_container"
-        app:layout_constraintEnd_toStartOf="@id/car_ui_toolbar_menu_items_container"/>
-
-    <FrameLayout
-        android:id="@+id/car_ui_toolbar_search_view_container"
-        android:layout_width="0dp"
-        android:layout_height="@dimen/car_ui_toolbar_search_height"
-        app:layout_constraintTop_toTopOf="@id/car_ui_toolbar_top_guideline"
-        app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_row_separator"
-        app:layout_constraintStart_toEndOf="@+id/car_ui_toolbar_nav_icon_container"
-        app:layout_constraintEnd_toStartOf="@+id/car_ui_toolbar_menu_items_container"/>
-
-    <LinearLayout
-        android:id="@+id/car_ui_toolbar_menu_items_container"
-        android:layout_width="wrap_content"
-        android:layout_height="0dp"
-        android:orientation="horizontal"
-        style="@style/Widget.CarUi.Toolbar.MenuItem.Container"
-        app:layout_constraintTop_toTopOf="@id/car_ui_toolbar_top_guideline"
-        app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_row_separator"
-        app:layout_constraintEnd_toStartOf="@id/car_ui_toolbar_end_guideline"/>
-
-    <com.android.car.ui.toolbar.TabLayout
-        android:id="@+id/car_ui_toolbar_tabs"
-        android:layout_width="match_parent"
-        android:layout_height="@dimen/car_ui_toolbar_second_row_height"
-        app:layout_constraintTop_toBottomOf="@id/car_ui_toolbar_row_separator"
-        app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_bottom_guideline"/>
-
-    <View
-        android:id="@+id/car_ui_toolbar_bottom_styleable"
-        android:layout_width="match_parent"
-        android:layout_height="@dimen/car_ui_toolbar_bottom_view_height"
-        style="@style/Widget.CarUi.Toolbar.BottomView"
-        app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintEnd_toEndOf="parent"/>
-
-    <ProgressBar
-        android:id="@+id/car_ui_toolbar_progress_bar"
-        style="@style/Widget.CarUi.Toolbar.ProgressBar"
+    android:layout_height="wrap_content">
+    <androidx.constraintlayout.widget.ConstraintLayout
+        xmlns:app="http://schemas.android.com/apk/res-auto"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_bottom_styleable"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintEnd_toEndOf="parent"
-        android:indeterminate="true"
-        android:visibility="gone"/>
+        android:id="@+id/car_ui_toolbar_background"
+        style="@style/Widget.CarUi.Toolbar.Container">
 
-</androidx.constraintlayout.widget.ConstraintLayout>
+        <androidx.constraintlayout.widget.Guideline
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:id="@+id/car_ui_toolbar_start_guideline"
+            app:layout_constraintGuide_begin="@dimen/car_ui_toolbar_start_inset"
+            android:orientation="vertical"/>
+
+        <androidx.constraintlayout.widget.Guideline
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:id="@+id/car_ui_toolbar_top_guideline"
+            app:layout_constraintGuide_begin="@dimen/car_ui_toolbar_top_inset"
+            android:orientation="horizontal"/>
+
+        <androidx.constraintlayout.widget.Guideline
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:id="@+id/car_ui_toolbar_end_guideline"
+            app:layout_constraintGuide_end="@dimen/car_ui_toolbar_end_inset"
+            android:orientation="vertical"/>
+
+        <androidx.constraintlayout.widget.Guideline
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:id="@+id/car_ui_toolbar_bottom_guideline"
+            app:layout_constraintGuide_end="@dimen/car_ui_toolbar_bottom_inset"
+            android:orientation="horizontal"/>
+
+        <androidx.constraintlayout.widget.Guideline
+            android:id="@+id/car_ui_toolbar_row_separator_guideline"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:orientation="horizontal"
+            app:layout_constraintGuide_begin="@dimen/car_ui_toolbar_first_row_height"/>
+
+        <View
+            android:id="@+id/car_ui_toolbar_row_separator"
+            android:layout_width="match_parent"
+            android:layout_height="@dimen/car_ui_toolbar_separator_height"
+            style="@style/Widget.CarUi.Toolbar.SeparatorView"
+            app:layout_constraintTop_toBottomOf="@id/car_ui_toolbar_row_separator_guideline"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"/>
+
+        <FrameLayout
+            android:id="@+id/car_ui_toolbar_nav_icon_container"
+            android:layout_width="@dimen/car_ui_toolbar_margin"
+            android:layout_height="0dp"
+            style="@style/Widget.CarUi.Toolbar.NavIconContainer"
+            app:layout_constraintTop_toTopOf="@id/car_ui_toolbar_top_guideline"
+            app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_row_separator"
+            app:layout_constraintStart_toStartOf="@id/car_ui_toolbar_start_guideline">
+            <ImageView
+                android:id="@+id/car_ui_toolbar_nav_icon"
+                android:layout_width="@dimen/car_ui_toolbar_nav_icon_size"
+                android:layout_height="@dimen/car_ui_toolbar_nav_icon_size"
+                android:layout_gravity="center"
+                android:scaleType="fitXY"
+                style="@style/Widget.CarUi.Toolbar.NavIcon"/>
+            <ImageView
+                android:id="@+id/car_ui_toolbar_logo"
+                android:layout_width="@dimen/car_ui_toolbar_logo_size"
+                android:layout_height="@dimen/car_ui_toolbar_logo_size"
+                android:layout_gravity="center"
+                android:scaleType="fitXY"/>
+        </FrameLayout>
+
+        <FrameLayout
+            android:id="@+id/car_ui_toolbar_title_logo_container"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            style="@style/Widget.CarUi.Toolbar.LogoContainer"
+            app:layout_constraintTop_toTopOf="@id/car_ui_toolbar_top_guideline"
+            app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_row_separator"
+            app:layout_constraintStart_toEndOf="@id/car_ui_toolbar_nav_icon_container">
+
+            <ImageView
+                android:id="@+id/car_ui_toolbar_title_logo"
+                android:layout_width="@dimen/car_ui_toolbar_logo_size"
+                android:layout_height="@dimen/car_ui_toolbar_logo_size"
+                android:scaleType="fitXY"
+                android:layout_gravity="center"
+                style="@style/Widget.CarUi.Toolbar.Logo"/>
+        </FrameLayout>
+
+        <LinearLayout android:layout_height="wrap_content"
+                      android:layout_width="0dp"
+                      android:id="@+id/car_ui_toolbar_title_container"
+                      android:orientation="vertical"
+                      android:layout_marginStart="@dimen/car_ui_toolbar_title_margin_start"
+                      app:layout_goneMarginStart="@dimen/car_ui_toolbar_title_no_logo_margin_start"
+                      app:layout_constraintTop_toTopOf="@id/car_ui_toolbar_top_guideline"
+                      app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_row_separator"
+                      app:layout_constraintStart_toEndOf="@id/car_ui_toolbar_title_logo_container"
+                      app:layout_constraintEnd_toStartOf="@id/car_ui_toolbar_menu_items_container">
+            <TextView android:id="@+id/car_ui_toolbar_title"
+                      android:layout_width="wrap_content"
+                      android:layout_height="wrap_content"
+                      android:singleLine="true"
+                      style="@style/Widget.CarUi.Toolbar.Title"/>
+            <TextView android:id="@+id/car_ui_toolbar_subtitle"
+                      android:layout_width="wrap_content"
+                      android:layout_height="wrap_content"
+                      android:visibility="gone"
+                      style="@style/Widget.CarUi.Toolbar.Subtitle"/>
+        </LinearLayout>
+
+        <FrameLayout
+            android:id="@+id/car_ui_toolbar_search_view_container"
+            android:layout_width="0dp"
+            android:layout_height="@dimen/car_ui_toolbar_search_height"
+            app:layout_constraintTop_toTopOf="@id/car_ui_toolbar_top_guideline"
+            app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_row_separator"
+            app:layout_constraintStart_toEndOf="@+id/car_ui_toolbar_nav_icon_container"
+            app:layout_constraintEnd_toStartOf="@+id/car_ui_toolbar_menu_items_container"/>
+
+        <LinearLayout
+            android:id="@+id/car_ui_toolbar_menu_items_container"
+            android:layout_width="wrap_content"
+            android:layout_height="0dp"
+            android:orientation="horizontal"
+            style="@style/Widget.CarUi.Toolbar.MenuItem.Container"
+            app:layout_constraintTop_toTopOf="@id/car_ui_toolbar_top_guideline"
+            app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_row_separator"
+            app:layout_constraintEnd_toStartOf="@id/car_ui_toolbar_end_guideline"/>
+
+        <com.android.car.ui.toolbar.TabLayout
+            android:id="@+id/car_ui_toolbar_tabs"
+            android:layout_width="match_parent"
+            android:layout_height="@dimen/car_ui_toolbar_second_row_height"
+            app:layout_constraintTop_toBottomOf="@id/car_ui_toolbar_row_separator"
+            app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_bottom_guideline"/>
+
+        <View
+            android:id="@+id/car_ui_toolbar_bottom_styleable"
+            android:layout_width="match_parent"
+            android:layout_height="@dimen/car_ui_toolbar_bottom_view_height"
+            style="@style/Widget.CarUi.Toolbar.BottomView"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"/>
+
+        <ProgressBar
+            android:id="@+id/car_ui_toolbar_progress_bar"
+            style="@style/Widget.CarUi.Toolbar.ProgressBar"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_bottom_styleable"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"
+            android:indeterminate="true"
+            android:visibility="gone"/>
+
+    </androidx.constraintlayout.widget.ConstraintLayout>
+</com.android.car.ui.FocusArea>
diff --git a/car-ui-lib/res/layout/car_ui_two_action_preference.xml b/car-ui-lib/res/layout/car_ui_two_action_preference.xml
new file mode 100644
index 0000000..4ad6ce4
--- /dev/null
+++ b/car-ui-lib/res/layout/car_ui_two_action_preference.xml
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright 2018 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:background="@android:color/transparent"
+    android:gravity="center_vertical"
+    android:minHeight="?android:attr/listPreferredItemHeightSmall">
+    <LinearLayout
+        android:layout_width="0dp"
+        android:layout_height="match_parent"
+        android:layout_weight="1"
+        android:background="?android:attr/selectableItemBackground"
+        android:clipToPadding="false"
+        android:gravity="start|center_vertical"
+        android:paddingBottom="@dimen/car_ui_preference_content_margin_bottom"
+        android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+        android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+        android:paddingTop="@dimen/car_ui_preference_content_margin_top">
+        <androidx.preference.internal.PreferenceImageView
+            android:id="@android:id/icon"
+            android:layout_width="@dimen/car_ui_preference_icon_size"
+            android:layout_height="@dimen/car_ui_preference_icon_size"
+            android:layout_marginEnd="@dimen/car_ui_preference_icon_margin_end"/>
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_centerVertical="true"
+            android:orientation="vertical">
+            <TextView
+                android:id="@android:id/title"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:ellipsize="end"
+                android:singleLine="true"
+                android:textAppearance="@style/TextAppearance.CarUi.PreferenceTitle"/>
+            <TextView
+                android:id="@android:id/summary"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:textAppearance="@style/TextAppearance.CarUi.PreferenceSummary"/>
+        </LinearLayout>
+    </LinearLayout>
+    <LinearLayout
+        android:id="@+id/action_widget_container"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent">
+        <View
+            android:layout_width="@dimen/car_ui_divider_width"
+            android:layout_height="match_parent"
+            android:layout_marginBottom="@dimen/car_ui_preference_content_margin_bottom"
+            android:layout_marginTop="@dimen/car_ui_preference_content_margin_top"
+            style="@style/Preference.CarUi.Divider"/>
+        <!-- Preference should place its actual preference widget here. -->
+        <FrameLayout
+            android:id="@android:id/widget_frame"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:background="?android:attr/selectableItemBackground"
+            android:minWidth="?android:attr/listPreferredItemHeightSmall"
+            android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+            android:paddingStart="?android:attr/listPreferredItemPaddingStart"/>
+    </LinearLayout>
+</LinearLayout>
diff --git a/car-ui-lib/res/values-night/colors.xml b/car-ui-lib/res/values-night/colors.xml
new file mode 100644
index 0000000..4295f07
--- /dev/null
+++ b/car-ui-lib/res/values-night/colors.xml
@@ -0,0 +1,19 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<resources>
+    <!-- Rotary focus -->
+    <color name="car_ui_rotary_focus_color">#2371cd</color>
+</resources>
diff --git a/car-ui-lib/res/values-w1280dp/dimens.xml b/car-ui-lib/res/values-w1280dp/dimens.xml
deleted file mode 100644
index a06df2b..0000000
--- a/car-ui-lib/res/values-w1280dp/dimens.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2019 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
-      http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<resources xmlns:android="http://schemas.android.com/apk/res/android">
-    <!-- Keylines -->
-    <dimen name="car_ui_keyline_1">32dp</dimen>
-    <dimen name="car_ui_keyline_2">108dp</dimen>
-    <dimen name="car_ui_keyline_3">128dp</dimen>
-    <dimen name="car_ui_keyline_4">168dp</dimen>
-</resources>
diff --git a/car-ui-lib/res/values/attrs.xml b/car-ui-lib/res/values/attrs.xml
index 8f7b3e0..4b06a60 100644
--- a/car-ui-lib/res/values/attrs.xml
+++ b/car-ui-lib/res/values/attrs.xml
@@ -32,7 +32,7 @@
         <!-- Whether or not to show the MenuItems while searching. Default false. -->
         <attr name="showMenuItemsWhileSearching" format="boolean"/>
         <!-- Initial state of the toolbar. See the Toolbar.State enum for more information -->
-        <attr name="state" format="enum">
+        <attr name="car_ui_state" format="enum">
             <enum name="home" value="0"/>
             <enum name="subpage" value="1"/>
             <enum name="search" value="2"/>
@@ -40,7 +40,7 @@
         <!-- Whether or not the toolbar should have a background. Default true. -->
         <attr name="showBackground" format="boolean"/>
         <!-- Mode of the navigation button See the Toolbar.NavButtonMode enum for more information -->
-        <attr name="navButtonMode" format="enum">
+        <attr name="car_ui_navButtonMode" format="enum">
             <enum name="back" value="0"/>
             <enum name="close" value="1"/>
             <enum name="down" value="2"/>
@@ -104,12 +104,14 @@
     <attr name="CarUiToolbarStyle" format="reference"/>
 
     <declare-styleable name="CarUiRecyclerView">
-        <!-- Whether to enable the car_ui_recyclerview_divider for linear layout or not. -->
+        <!-- Whether to enable the dividers or not. Linear and grid layout uses
+        car_ui_recyclerview_divider.xml and car_ui_divider.xml drawables
+        respectively for styling dividers. -->
         <attr name="enableDivider" format="boolean" />
         <!-- Top offset for car ui recycler view. -->
-        <attr name="startOffset" format="integer" />
+        <attr name="topOffset" format="integer" />
         <!-- Bottom offset for car ui recycler view for linear layout. -->
-        <attr name="endOffset" format="integer" />
+        <attr name="bottomOffset" format="integer" />
 
         <!-- Number of columns in a grid layout. -->
         <attr name="numOfColumns" format="integer" />
@@ -126,6 +128,13 @@
     <declare-styleable name="CarUiPreference">
         <!-- Toggle for showing chevron -->
         <attr name="showChevron" format="boolean" />
+        <!-- Show ripple when disabled preference is clicked -->
+        <attr name="showRippleOnDisabledPreference" format="boolean" />
+    </declare-styleable>
+
+    <declare-styleable name="CarUiTwoActionPreference">
+        <!-- Determines if the secondary action is initially shown -->
+        <attr name="actionShown" format="boolean"/>
     </declare-styleable>
 
     <!-- Theme attribute to specify a default style for all CarUiPreferences -->
diff --git a/car-ui-lib/res/values/bools.xml b/car-ui-lib/res/values/bools.xml
index 955956d..d85e840 100644
--- a/car-ui-lib/res/values/bools.xml
+++ b/car-ui-lib/res/values/bools.xml
@@ -46,4 +46,13 @@
     <!-- List items -->
 
     <bool name="car_ui_list_item_single_line_title">true</bool>
+
+    <!-- FocusArea -->
+
+    <!-- Whether to draw highlight (car_ui_focus_area_foreground_highlight) on top of the FocusArea
+         and its children when the FocusArea's descendant gets focused. -->
+    <bool name="car_ui_enable_focus_area_foreground_highlight">false</bool>
+    <!-- Whether to draw highlight (car_ui_focus_area_background_highlight) on top of the FocusArea
+         but behind its children when the FocusArea's descendant gets focused. -->
+    <bool name="car_ui_enable_focus_area_background_highlight">false</bool>
 </resources>
diff --git a/car-ui-lib/res/values/colors.xml b/car-ui-lib/res/values/colors.xml
index 78d1ecc..db62ad2 100644
--- a/car-ui-lib/res/values/colors.xml
+++ b/car-ui-lib/res/values/colors.xml
@@ -41,15 +41,9 @@
 
     <!-- Preferences -->
 
-    <color name="car_ui_preference_category_title_text_color">@color/car_ui_color_accent</color>
-    <color name="car_ui_preference_summary_text_color">@color/car_ui_text_color_secondary</color>
-    <color name="car_ui_preference_title_text_color">@color/car_ui_text_color_primary</color>
-    <color name="car_ui_preference_edit_text_dialog_message_text_color">@color/car_ui_text_color_primary</color>
     <color name="car_ui_preference_icon_color">@color/car_ui_text_color_primary</color>
-    <color name="car_ui_preference_switch_track_text_color">@color/car_ui_text_color_primary</color>
+    <color name="car_ui_preference_two_action_divider_color">#1fffffff</color>
 
-    <!-- List item -->
-    <color name="car_ui_list_item_header_text_color">@color/car_ui_color_accent</color>
-    <color name="car_ui_list_item_title_text_color">@color/car_ui_text_color_primary</color>
-    <color name="car_ui_list_item_body_text_color">@color/car_ui_text_color_secondary</color>
+    <!-- Rotary focus -->
+    <color name="car_ui_rotary_focus_color">#4b9eff</color>
 </resources>
diff --git a/car-ui-lib/res/values/dimens.xml b/car-ui-lib/res/values/dimens.xml
index 3a77194..3910c60 100644
--- a/car-ui-lib/res/values/dimens.xml
+++ b/car-ui-lib/res/values/dimens.xml
@@ -16,11 +16,11 @@
 <resources>
     <!-- General resources -->
 
-    <dimen name="car_ui_touch_target_width">76dp</dimen>
-    <dimen name="car_ui_touch_target_height">76dp</dimen>
+    <dimen name="car_ui_touch_target_size">76dp</dimen>
+    <dimen name="car_ui_touch_target_width">@dimen/car_ui_touch_target_size</dimen>
+    <dimen name="car_ui_touch_target_height">@dimen/car_ui_touch_target_size</dimen>
+
     <dimen name="car_ui_primary_icon_size">44dp</dimen>
-    <item name="car_ui_letter_spacing_body1" format="float" type="dimen">0.0</item>
-    <item name="car_ui_letter_spacing_body3" format="float" type="dimen">0.0</item>
 
     <!-- Horizontal margin between screen content and display border. In reference
      implementation, this value matches the CarUiRecyclerView scrollbar width -->
@@ -39,12 +39,9 @@
     <dimen name="car_ui_body1_size">32sp</dimen>
     <dimen name="car_ui_body2_size">28sp</dimen>
     <dimen name="car_ui_body3_size">24sp</dimen>
-
-    <!-- Keylines -->
-    <dimen name="car_ui_keyline_1">24dp</dimen>
-    <dimen name="car_ui_keyline_2">96dp</dimen>
-    <dimen name="car_ui_keyline_3">112dp</dimen>
-    <dimen name="car_ui_keyline_4">148dp</dimen>
+    <dimen name="car_ui_sub1_size">22sp</dimen>
+    <dimen name="car_ui_sub2_size">20sp</dimen>
+    <dimen name="car_ui_sub3_size">18sp</dimen>
 
     <!-- Tabs -->
 
@@ -86,6 +83,8 @@
     <dimen name="car_ui_toolbar_title_logo_padding">0dp</dimen>
     <!-- Margin at the start of the title -->
     <dimen name="car_ui_toolbar_title_margin_start">@dimen/car_ui_padding_2</dimen>
+    <!-- Margin at the start of the title when there is no logo present -->
+    <dimen name="car_ui_toolbar_title_no_logo_margin_start">0dp</dimen>
     <!-- Space at the end and in between menu items -->
     <dimen name="car_ui_toolbar_menu_item_margin">@dimen/car_ui_padding_2</dimen>
     <!-- Ripple effect radius for icon menu items -->
@@ -137,15 +136,12 @@
     <item name="car_ui_scrollbar_deceleration_times_divisor" format="float" type="dimen">0.45</item>
     <item name="car_ui_scrollbar_decelerate_interpolator_factor" format="float" type="dimen">1.8</item>
 
-    <dimen name="car_ui_scrollbar_padding_start">0dp</dimen>
-    <dimen name="car_ui_scrollbar_padding_end">0dp</dimen>
+    <dimen name="car_ui_scrollbar_padding_top">0dp</dimen>
+    <dimen name="car_ui_scrollbar_padding_bottom">0dp</dimen>
 
     <!-- Preferences -->
 
-    <dimen name="car_ui_preference_category_text_size">24sp</dimen>
-    <dimen name="car_ui_preference_summary_text_size">24sp</dimen>
-    <dimen name="car_ui_preference_title_text_size">32sp</dimen>
-    <dimen name="car_ui_preference_edit_text_dialog_message_text_size">24sp</dimen>
+    <dimen name="car_ui_divider_width">1dp</dimen>
 
     <dimen name="car_ui_preference_content_margin_top">16dp</dimen>
     <dimen name="car_ui_preference_content_margin_bottom">16dp</dimen>
@@ -166,11 +162,6 @@
     <dimen name="car_ui_preference_edit_text_dialog_text_margin_start">24dp</dimen>
     <dimen name="car_ui_preference_edit_text_dialog_text_margin_end">24dp</dimen>
 
-    <dimen name="car_ui_preference_switch_text_size">30sp</dimen>
-    <dimen name="car_ui_preference_switch_width">288dp</dimen>
-    <dimen name="car_ui_preference_switch_width_half">144dp</dimen>
-    <dimen name="car_ui_preference_switch_height">101dp</dimen>
-
     <!-- Alert dialog   -->
 
     <dimen name="car_ui_dialog_edittext_height">50dp</dimen>
@@ -179,18 +170,16 @@
     <dimen name="car_ui_dialog_edittext_margin_start">22dp</dimen>
     <dimen name="car_ui_dialog_edittext_margin_end">22dp</dimen>
     <dimen name="car_ui_dialog_icon_size">56dp</dimen>
-    <dimen name="car_ui_dialog_title_margin">@dimen/car_ui_keyline_1</dimen>
+    <dimen name="car_ui_dialog_title_margin">24dp</dimen>
 
     <!-- List item  -->
 
-    <dimen name="car_ui_list_item_header_text_size">24sp</dimen>
-    <dimen name="car_ui_list_item_title_text_size">32sp</dimen>
-    <dimen name="car_ui_list_item_body_text_size">24sp</dimen>
     <dimen name="car_ui_list_item_height">116dp</dimen>
     <dimen name="car_ui_list_item_header_height">76dp</dimen>
     <dimen name="car_ui_list_item_header_start_inset">0dp</dimen>
     <dimen name="car_ui_list_item_start_inset">0dp</dimen>
     <dimen name="car_ui_list_item_end_inset">0dp</dimen>
+    <dimen name="car_ui_header_list_item_text_start_margin">0dp</dimen>
     <dimen name="car_ui_list_item_text_start_margin">24dp</dimen>
     <dimen name="car_ui_list_item_text_no_icon_start_margin">24dp</dimen>
 
diff --git a/car-ui-lib/res/values/ids.xml b/car-ui-lib/res/values/ids.xml
index fcff109..2c23ac3 100644
--- a/car-ui-lib/res/values/ids.xml
+++ b/car-ui-lib/res/values/ids.xml
@@ -16,4 +16,4 @@
 <resources>
     <!-- Id used for the search button when using Toolbar.createSearch() method -->
     <item name="search" type="id"/>
-</resources>
\ No newline at end of file
+</resources>
diff --git a/car-ui-lib/res/values/integers.xml b/car-ui-lib/res/values/integers.xml
index 623ef00..963c955 100644
--- a/car-ui-lib/res/values/integers.xml
+++ b/car-ui-lib/res/values/integers.xml
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2019 The Android Open Source Project
+<?xml version="1.0" encoding="utf-8"?><!-- Copyright (C) 2019 The Android Open Source Project
 
  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
@@ -17,4 +16,6 @@
 <resources>
     <!-- Default max string length -->
     <integer name="car_ui_default_max_string_length">120</integer>
-</resources>
\ No newline at end of file
+    <integer name="car_ui_scrollbar_longpress_initial_delay">1000</integer>
+    <integer name="car_ui_scrollbar_longpress_repeat_interval">100</integer>
+</resources>
diff --git a/car-ui-lib/res/values/strings.xml b/car-ui-lib/res/values/strings.xml
index a42068f..ff101f7 100644
--- a/car-ui-lib/res/values/strings.xml
+++ b/car-ui-lib/res/values/strings.xml
@@ -29,6 +29,8 @@
     <string name="car_ui_scrollbar_page_down_button">Scroll down</string>
     <!-- Content description for car ui recycler view scroll bar up arrow [CHAR LIMIT=30] -->
     <string name="car_ui_scrollbar_page_up_button">Scroll up</string>
+    <!-- The content description on the toolbar back button -->
+    <string name="car_ui_toolbar_nav_icon_content_description">Back</string>
     <!-- Title of the search menu item. Will be displayed if the button is in the overflow menu. [CHAR_LIMIT=50] -->
     <string name="car_ui_toolbar_menu_item_search_title">Search</string>
     <!-- Title of the settings menu item. Will be displayed if the button is in the overflow menu. [CHAR_LIMIT=50] -->
@@ -37,22 +39,23 @@
     <string name="car_ui_toolbar_menu_item_overflow_title">Overflow</string>
 
     <!-- Positive option for a preference dialog. [CHAR_LIMIT=30] -->
-    <string name="car_ui_dialog_preference_positive">Ok</string>
+    <string name="car_ui_dialog_preference_positive" translatable="false">@android:string/ok</string>
     <!-- Negative option for a preference dialog. [CHAR_LIMIT=30] -->
-    <string name="car_ui_dialog_preference_negative">Cancel</string>
+    <string name="car_ui_dialog_preference_negative" translatable="false">@android:string/cancel</string>
     <!-- Text to show when a preference switch is on. [CHAR_LIMIT=30] -->
     <string name="car_ui_preference_switch_on">On</string>
     <!-- Text to show when a preference switch is off. [CHAR_LIMIT=30] -->
     <string name="car_ui_preference_switch_off">Off</string>
-    <!-- Font family to use for preference category titles. [CHAR_LIMIT=NONE] -->
-    <string name="car_ui_preference_category_title_font_family" translatable="false">sans-serif-medium</string>
-
-    <!-- Font family to use for list item headers. [CHAR_LIMIT=NONE] -->
-    <string name="car_ui_list_item_header_font_family" translatable="false">sans-serif-medium</string>
 
     <!-- Text to show when no button is provided and a default button is used. -->
     <string name="car_ui_alert_dialog_default_button" translatable="false">Close</string>
 
     <!-- Shown in a toast when the user attempts to do something distracting while driving [CHAR_LIMIT=200] -->
     <string name="car_ui_restricted_while_driving">Feature not available while driving</string>
+
+    <!-- Mostly used for GMSCore, this attribute is used to launch CarUiInstaller in a process -->
+    <!-- that can register to Application.ActivityLifecycleCallbacks. -->
+    <!-- Clients should override this value instead of changing the process name -->
+    <!-- from manifest file. -->
+    <string name="car_ui_installer_process_name" translatable="false"></string>
 </resources>
diff --git a/car-ui-lib/res/values/styles.xml b/car-ui-lib/res/values/styles.xml
index 9cbf41e..00cb56e 100644
--- a/car-ui-lib/res/values/styles.xml
+++ b/car-ui-lib/res/values/styles.xml
@@ -49,14 +49,19 @@
     </style>
 
     <style name="Widget.CarUi.Toolbar.Title">
-        <item name="android:layout_marginStart">@dimen/car_ui_toolbar_title_margin_start</item>
         <item name="android:textAppearance">@style/TextAppearance.CarUi.Widget.Toolbar.Title</item>
-        <item name="android:textDirection">locale</item>
+        <item name="android:textAlignment">viewStart</item>
+    </style>
+
+    <style name="Widget.CarUi.Toolbar.Subtitle">
+        <item name="android:textAppearance">?android:attr/textAppearanceSmall</item>
+        <item name="android:textAlignment">viewStart</item>
     </style>
 
     <style name="Widget.CarUi.Toolbar.TextButton" parent="Widget.CarUi.Button.Borderless.Colored">
         <item name="android:drawableTint">@color/car_ui_toolbar_menu_item_icon_color</item>
         <item name="android:drawablePadding">10dp</item>
+        <item name="android:maxWidth">350dp</item>
     </style>
 
     <style name="Widget.CarUi.Toolbar.TextButton.WithIcon">
@@ -179,6 +184,10 @@
         <item name="android:dialogLayout">@layout/car_ui_preference_dialog_edittext</item>
     </style>
 
+    <style name="Preference.CarUi.Divider">
+        <item name="android:background">@color/car_ui_preference_two_action_divider_color</item>
+    </style>
+
     <style name="Preference.CarUi.DropDown">
         <item name="android:layout">@layout/car_ui_preference_dropdown</item>
     </style>
@@ -200,6 +209,14 @@
         <item name="showSeekBarValue">false</item>
     </style>
 
+    <style name="Preference.CarUi.DialogSeekBarPreference"/>
+
+    <style name="Preference.CarUi.DialogSeekBarPreference.Seekbar"/>
+
+    <style name="Preference.CarUi.DialogSeekBarPreference.TopText"/>
+    <style name="Preference.CarUi.DialogSeekBarPreference.RightText"/>
+    <style name="Preference.CarUi.DialogSeekBarPreference.LeftText"/>
+
     <style name="Preference.CarUi.SwitchPreference">
         <item name="android:widgetLayout">@layout/car_ui_preference_widget_switch</item>
         <item name="android:switchTextOn">@string/car_ui_preference_switch_on</item>
@@ -230,6 +247,7 @@
 
     <style name="TextAppearance.CarUi" parent="android:TextAppearance.DeviceDefault">
         <item name="android:textColor">?android:attr/textColorPrimary</item>
+        <item name="android:textAlignment">viewStart</item>
     </style>
 
     <style name="TextAppearance.CarUi.Body1">
@@ -244,42 +262,45 @@
         <item name="android:textSize">@dimen/car_ui_body3_size</item>
     </style>
 
-    <style name="TextAppearance.CarUi.PreferenceCategoryTitle">
-        <item name="android:fontFamily">@string/car_ui_preference_category_title_font_family</item>
-        <item name="android:textColor">@color/car_ui_preference_category_title_text_color</item>
-        <item name="android:textSize">@dimen/car_ui_preference_category_text_size</item>
+    <style name="TextAppearance.CarUi.Sub1">
+        <item name="android:textSize">@dimen/car_ui_sub1_size</item>
     </style>
 
-    <style name="TextAppearance.CarUi.PreferenceSummary">
-        <item name="android:textColor">@color/car_ui_preference_summary_text_color</item>
-        <item name="android:textSize">@dimen/car_ui_preference_summary_text_size</item>
+    <style name="TextAppearance.CarUi.Sub2">
+        <item name="android:textSize">@dimen/car_ui_sub2_size</item>
     </style>
 
-    <style name="TextAppearance.CarUi.PreferenceTitle">
-        <item name="android:textColor">@color/car_ui_preference_title_text_color</item>
-        <item name="android:textSize">@dimen/car_ui_preference_title_text_size</item>
+    <style name="TextAppearance.CarUi.Sub3">
+        <item name="android:textSize">@dimen/car_ui_sub3_size</item>
     </style>
 
-    <style name="TextAppearance.CarUi.PreferenceEditTextDialogMessage">
-        <item name="android:textColor">@color/car_ui_preference_edit_text_dialog_message_text_color</item>
-        <item name="android:textSize">@dimen/car_ui_preference_edit_text_dialog_message_text_size</item>
+    <style name="TextAppearance.CarUi.PreferenceCategoryTitle" parent="TextAppearance.CarUi.Body3">
+        <item name="android:fontFamily">sans-serif-medium</item>
+        <item name="android:textColor">@color/car_ui_color_accent</item>
     </style>
 
-    <style name="TextAppearance.CarUi.AlertDialog.Subtitle" parent="android:TextAppearance.DeviceDefault"/>
+    <style name="TextAppearance.CarUi.PreferenceSummary" parent="TextAppearance.CarUi.Body3">
+        <item name="android:textColor">@color/car_ui_text_color_secondary</item>
+    </style>
 
-    <style name="TextAppearance.CarUi.Widget" parent="android:TextAppearance.DeviceDefault.Widget"/>
+    <style name="TextAppearance.CarUi.PreferenceTitle" parent="TextAppearance.CarUi.Body1"/>
+
+    <style name="TextAppearance.CarUi.PreferenceEditTextDialogMessage" parent="TextAppearance.CarUi.Body3"/>
+
+    <style name="TextAppearance.CarUi.AlertDialog.Title" parent="TextAppearance.CarUi.Body3"/>
+    <style name="TextAppearance.CarUi.AlertDialog.Subtitle" parent="TextAppearance.CarUi.Sub3"/>
+
+    <style name="TextAppearance.CarUi.Widget" parent="android:TextAppearance.DeviceDefault.Widget">
+        <item name="android:textAlignment">viewStart</item>
+    </style>
 
     <style name="TextAppearance.CarUi.Widget.Toolbar"/>
 
-    <style name="TextAppearance.CarUi.Widget.Toolbar.Title">
+    <style name="TextAppearance.CarUi.Widget.Toolbar.Title" parent="TextAppearance.CarUi.Body1">
         <item name="android:singleLine">true</item>
-        <item name="android:textSize">32sp</item>
-        <item name="android:letterSpacing">@dimen/car_ui_letter_spacing_body1</item>
     </style>
 
-    <style name="TextAppearance.CarUi.Widget.Toolbar.Tab">
-        <item name="android:textSize">24sp</item>
-        <item name="android:letterSpacing">@dimen/car_ui_letter_spacing_body3</item>
+    <style name="TextAppearance.CarUi.Widget.Toolbar.Tab" parent="TextAppearance.CarUi.Body3">
         <item name="android:textColor">@color/car_ui_toolbar_tab_item_selector</item>
         <item name="android:textStyle">normal</item>
         <item name="android:textFontWeight">400</item>
@@ -289,20 +310,15 @@
         <item name="android:textFontWeight">500</item>
     </style>
 
-    <style name="TextAppearance.CarUi.ListItem.Header">
-        <item name="android:fontFamily">@string/car_ui_list_item_header_font_family</item>
-        <item name="android:textColor">@color/car_ui_list_item_header_text_color</item>
-        <item name="android:textSize">@dimen/car_ui_list_item_header_text_size</item>
+    <style name="TextAppearance.CarUi.ListItem.Header" parent="TextAppearance.CarUi.Body3">
+        <item name="android:fontFamily">sans-serif-medium</item>
+        <item name="android:textColor">@color/car_ui_color_accent</item>
     </style>
 
-    <style name="TextAppearance.CarUi.ListItem">
-        <item name="android:textColor">@color/car_ui_list_item_title_text_color</item>
-        <item name="android:textSize">@dimen/car_ui_list_item_title_text_size</item>
-    </style>
+    <style name="TextAppearance.CarUi.ListItem" parent="TextAppearance.CarUi.Body1"/>
 
-    <style name="TextAppearance.CarUi.ListItem.Body">
-        <item name="android:textSize">@dimen/car_ui_list_item_body_text_size</item>
-        <item name="android:textColor">@color/car_ui_list_item_body_text_color</item>
+    <style name="TextAppearance.CarUi.ListItem.Body" parent="TextAppearance.CarUi.Body3">
+        <item name="android:textColor">@color/car_ui_text_color_secondary</item>
     </style>
 
 </resources>
diff --git a/car-ui-lib/settings.gradle b/car-ui-lib/settings.gradle
index 56f7f65..50c2c6d 100644
--- a/car-ui-lib/settings.gradle
+++ b/car-ui-lib/settings.gradle
@@ -18,4 +18,7 @@
 project(':PaintBooth').projectDir = new File('./tests/paintbooth')
 include ':RoboTests'
 project(':RoboTests').projectDir = new File('./tests/robotests')
+include ':InstrumentionTests'
+project(':InstrumentionTests').projectDir = new File('./tests/unit')
+
 rootProject.name='Chassis'
diff --git a/car-ui-lib/sharedlibrary/Android.bp b/car-ui-lib/sharedlibrary/Android.bp
new file mode 100644
index 0000000..1abaa30
--- /dev/null
+++ b/car-ui-lib/sharedlibrary/Android.bp
@@ -0,0 +1,31 @@
+
+//
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+android_app {
+    name: "car-ui-lib-sharedlibrary",
+    visibility: [
+        "//packages/apps/Car/libs/car-ui-lib/tests/PaintBooth:__pkg__",
+    ],
+    platform_apis: true,
+    resource_dirs: ["res"],
+    aaptflags: ["--shared-lib"],
+    optimize: {
+        enabled: false,
+    },
+    static_libs: [
+        "car-ui-lib",
+    ],
+}
diff --git a/car-ui-lib/sharedlibrary/AndroidManifest.xml b/car-ui-lib/sharedlibrary/AndroidManifest.xml
new file mode 100644
index 0000000..61b4515
--- /dev/null
+++ b/car-ui-lib/sharedlibrary/AndroidManifest.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2020 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.android.car.ui.sharedlibrary">
+  <uses-sdk
+      android:minSdkVersion="28"
+      android:targetSdkVersion="28" />
+    <application>
+        <library android:name="com.android.car.ui.sharedlibrary" />
+    </application>
+</manifest>
diff --git a/car-ui-lib/sharedlibrary/README.md b/car-ui-lib/sharedlibrary/README.md
new file mode 100644
index 0000000..21c6172
--- /dev/null
+++ b/car-ui-lib/sharedlibrary/README.md
@@ -0,0 +1,5 @@
+# Android Automotive 'Chassis' shared library
+Please refer to [Android Automotive 'Chassiss' library](../README.md)
+
+**Required**
+This module needs to be, and is included in PRODUCT_PACKAGES in vendor/auto/embeded/products/car.mk. It needs to be pre-installed with the system image.
\ No newline at end of file
diff --git a/car-ui-lib/sharedlibrary/res/values/public.xml b/car-ui-lib/sharedlibrary/res/values/public.xml
new file mode 100644
index 0000000..80ea2e7
--- /dev/null
+++ b/car-ui-lib/sharedlibrary/res/values/public.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<resources>
+    <!-- Any resource or attribute that is or can be referenced from RRO needs to be public go/rro-on-r -->
+
+    <!-- To add new resources to this file follow the following naming convention -->
+    <!-- 0cXXXX is used for styles -->
+    <!-- 0dXXXX is used for attributes -->
+    <!-- 0eXXXX is used for drawables -->
+    <!-- The first time that a resource type is seen, Android resource manager, assigns YY of the ID (0xXXYYXXXX) of the resouce to that type.
+         And you'll get a compile error if you use the same type with a different YY -->
+
+    <public type="style" name="Theme.CarUi" id="0x000c0000" />
+
+    <public type="attr" name="logo" id="0x000d0001" />
+    <public type="attr" name="car_ui_state" id="0x000d0002" />
+    <public type="attr" name="title" id="0x000d0003" />
+    <public type="attr" name="layoutStyle" id="0x000d0004" />
+    <public type="attr" name="numOfColumns" id="0x000d0005" />
+    <public type="attr" name="layout_constraintTop_toTopOf" id="0x000d0006" />
+    <public type="attr" name="layout_constraintTop_toBottomOf" id="0x000d0007" />
+    <public type="attr" name="layout_constraintLeft_toLeftOf" id="0x000d0008" />
+    <public type="attr" name="layout_constraintBottom_toTopOf" id="0x000d0009" />
+    <public type="attr" name="layout_constraintBottom_toBottomOf" id="0x000d0010" />
+    <public type="attr" name="layout_constraintRight_toRightOf" id="0x000d0011" />
+    <public type="attr" name="search" id="0x000d0012" />
+    <public type="attr" name="settings" id="0x000d0013" />
+    <public type="attr" name="id" id="0x000d0014" />
+    <public type="attr" name="icon" id="0x000d0015" />
+    <public type="attr" name="onClick" id="0x000d0016" />
+    <public type="attr" name="checkable" id="0x000d0017" />
+    <public type="attr" name="uxRestrictions" id="0x000d0018" />
+    <public type="attr" name="singleLineTitle" id="0x000d0019" />
+    <public type="attr" name="useSimpleSummaryProvider" id="0x000d0020" />
+    <public type="attr" name="initialExpandedChildrenCount" id="0x000d0021" />
+    <public type="attr" name="enableCopying" id="0x000d0022" />
+
+    <public type="drawable" name="car_ui_activity_background" id="0x000e0000" />
+
+</resources>
diff --git a/car-ui-lib/src/com/android/car/ui/AlertDialogBuilder.java b/car-ui-lib/src/com/android/car/ui/AlertDialogBuilder.java
index 4803b45..a025e9e 100644
--- a/car-ui-lib/src/com/android/car/ui/AlertDialogBuilder.java
+++ b/car-ui-lib/src/com/android/car/ui/AlertDialogBuilder.java
@@ -22,9 +22,12 @@
 import android.database.Cursor;
 import android.graphics.drawable.Drawable;
 import android.text.InputFilter;
+import android.text.TextUtils;
 import android.text.TextWatcher;
+import android.text.method.LinkMovementMethod;
 import android.view.LayoutInflater;
 import android.view.View;
+import android.view.ViewGroup;
 import android.widget.AdapterView;
 import android.widget.EditText;
 import android.widget.ImageView;
@@ -41,6 +44,7 @@
 
 import com.android.car.ui.recyclerview.CarUiListItemAdapter;
 import com.android.car.ui.recyclerview.CarUiRadioButtonListItemAdapter;
+import com.android.car.ui.utils.CarUiUtils;
 
 /**
  * Wrapper for AlertDialog.Builder
@@ -55,6 +59,7 @@
     private CharSequence mTitle;
     private CharSequence mSubtitle;
     private Drawable mIcon;
+    private boolean mIconTinted;
 
     public AlertDialogBuilder(Context context) {
         // Resource id specified as 0 uses the parent contexts resolved value for alertDialogTheme.
@@ -152,7 +157,18 @@
      */
     public AlertDialogBuilder setIcon(Drawable icon) {
         mIcon = icon;
-        mBuilder.setIcon(icon);
+        return this;
+    }
+
+    /**
+     * Whether the icon provided by {@link #setIcon(Drawable)} should be
+     * tinted with the default system color.
+     *
+     * @return this Builder object to allow for chaining of calls to set
+     * methods.
+     */
+    public AlertDialogBuilder setIconTinted(boolean tinted) {
+        mIconTinted = tinted;
         return this;
     }
 
@@ -160,8 +176,7 @@
      * Set an icon as supplied by a theme attribute. e.g.
      * {@link android.R.attr#alertDialogIcon}.
      * <p>
-     * Takes precedence over values set using {@link #setIcon(int)} or
-     * {@link #setIcon(Drawable)}.
+     * Takes precedence over values set using {@link #setIcon(Drawable)}.
      *
      * @param attrId ID of a theme attribute that points to a drawable resource.
      */
@@ -354,7 +369,7 @@
     private void setCustomList(@NonNull CarUiListItemAdapter adapter) {
         View customList = LayoutInflater.from(mContext).inflate(
                 R.layout.car_ui_alert_dialog_list, null);
-        RecyclerView mList = customList.requireViewById(R.id.list);
+        RecyclerView mList = CarUiUtils.requireViewByRefId(customList, R.id.list);
         mList.setLayoutManager(new LinearLayoutManager(mContext));
         mList.setAdapter(adapter);
         mBuilder.setView(customList);
@@ -587,7 +602,7 @@
         View contentView = LayoutInflater.from(mContext).inflate(
                 R.layout.car_ui_alert_dialog_edit_text, null);
 
-        EditText editText = contentView.requireViewById(R.id.textbox);
+        EditText editText = CarUiUtils.requireViewByRefId(contentView, R.id.textbox);
         editText.setText(prompt);
 
         if (textChangedListener != null) {
@@ -623,21 +638,26 @@
 
     /** Final steps common to both {@link #create()} and {@link #show()} */
     private void prepareDialog() {
-        if (mSubtitle != null) {
+        View customTitle = LayoutInflater.from(mContext).inflate(
+                R.layout.car_ui_alert_dialog_title_with_subtitle, null);
 
-            View customTitle = LayoutInflater.from(mContext).inflate(
-                    R.layout.car_ui_alert_dialog_title_with_subtitle, null);
+        TextView mTitleView = CarUiUtils.requireViewByRefId(customTitle, R.id.car_ui_alert_title);
+        TextView mSubtitleView =
+                CarUiUtils.requireViewByRefId(customTitle, R.id.car_ui_alert_subtitle);
+        mSubtitleView.setMovementMethod(LinkMovementMethod.getInstance());
+        ImageView mIconView = CarUiUtils.requireViewByRefId(customTitle, R.id.car_ui_alert_icon);
 
-            TextView mTitleView = customTitle.requireViewById(R.id.alertTitle);
-            TextView mSubtitleView = customTitle.requireViewById(R.id.alertSubtitle);
-            ImageView mIconView = customTitle.requireViewById(R.id.icon);
-
-            mTitleView.setText(mTitle);
-            mSubtitleView.setText(mSubtitle);
-            mIconView.setImageDrawable(mIcon);
-            mIconView.setVisibility(mIcon != null ? View.VISIBLE : View.GONE);
-            mBuilder.setCustomTitle(customTitle);
+        mTitleView.setText(mTitle);
+        mTitleView.setVisibility(TextUtils.isEmpty(mTitle) ? View.GONE : View.VISIBLE);
+        mSubtitleView.setText(mSubtitle);
+        mSubtitleView.setVisibility(TextUtils.isEmpty(mSubtitle) ? View.GONE : View.VISIBLE);
+        mIconView.setImageDrawable(mIcon);
+        mIconView.setVisibility(mIcon != null ? View.VISIBLE : View.GONE);
+        if (mIconTinted) {
+            mIconView.setImageTintList(
+                    mContext.getColorStateList(R.color.car_ui_dialog_icon_color));
         }
+        mBuilder.setCustomTitle(customTitle);
 
         if (!mNeutralButtonSet && !mNegativeButtonSet && !mPositiveButtonSet) {
             String mDefaultButtonText = mContext.getString(
@@ -657,21 +677,26 @@
      */
     public AlertDialog create() {
         prepareDialog();
-        return mBuilder.create();
+        AlertDialog alertDialog = mBuilder.create();
+
+        // Put a FocusParkingView at the end of dialog window to prevent rotary controller
+        // wrap-around. Android will focus on the first view automatically when the dialog is shown,
+        // and we want it to focus on the title instead of the FocusParkingView, so we put the
+        // FocusParkingView at the end of dialog window.
+        ViewGroup root = (ViewGroup) alertDialog.getWindow().getDecorView().getRootView();
+        FocusParkingView fpv = new FocusParkingView(mContext);
+        root.addView(fpv);
+
+        return alertDialog;
     }
 
     /**
      * Creates an {@link AlertDialog} with the arguments supplied to this
      * builder and immediately displays the dialog.
-     * <p>
-     * Calling this method is functionally identical to:
-     * <pre>
-     *     AlertDialog dialog = builder.create();
-     *     dialog.show();
-     * </pre>
      */
     public AlertDialog show() {
-        prepareDialog();
-        return mBuilder.show();
+        AlertDialog alertDialog = create();
+        alertDialog.show();
+        return alertDialog;
     }
 }
diff --git a/car-ui-lib/src/com/android/car/ui/FocusArea.java b/car-ui-lib/src/com/android/car/ui/FocusArea.java
new file mode 100644
index 0000000..f969380
--- /dev/null
+++ b/car-ui-lib/src/com/android/car/ui/FocusArea.java
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.car.ui;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.view.KeyEvent;
+import android.view.View;
+import android.widget.LinearLayout;
+
+import androidx.annotation.Nullable;
+
+/**
+ * A {@link LinearLayout} used as a navigation block for the rotary controller.
+ * <p>
+ * The {@link com.android.car.rotary.RotaryService} looks for instances of {@link FocusArea} in the
+ * view hierarchy when handling rotate and nudge actions. When receiving a rotation event ({@link
+ * android.car.input.RotaryEvent}), RotaryService will move the focus to another {@link View} that
+ * can take focus within the same FocusArea. When receiving a nudge event ({@link
+ * KeyEvent#KEYCODE_SYSTEM_NAVIGATION_UP}, {@link KeyEvent#KEYCODE_SYSTEM_NAVIGATION_DOWN}, {@link
+ * KeyEvent#KEYCODE_SYSTEM_NAVIGATION_LEFT}, or {@link KeyEvent#KEYCODE_SYSTEM_NAVIGATION_RIGHT}),
+ * RotaryService will move the focus to another view that can take focus in another (typically
+ * adjacent) FocusArea.
+ * <p>
+ * If enabled, FocusArea can draw highlights when one of its descendants has focus.
+ * <p>
+ * When creating a navigation block in the layout file, if you intend to use a LinearLayout as a
+ * container for that block, just use a FocusArea instead; otherwise wrap the block in a FocusArea.
+ * <p>
+ * DO NOT nest a FocusArea inside another FocusArea because it will result in undefined navigation
+ * behavior.
+ */
+public class FocusArea extends LinearLayout {
+
+    /** Whether the FocusArea's descendant has focus (the FocusArea itself is not focusable). */
+    private boolean mHasFocus;
+
+    /**
+     * Whether to draw {@link #mForegroundHighlight} when one of the FocusArea's descendants has
+     * focus.
+     */
+    private boolean mEnableForegroundHighlight;
+
+    /**
+     * Whether to draw {@link #mBackgroundHighlight} when one of the FocusArea's descendants has
+     * focus.
+     */
+    private boolean mEnableBackgroundHighlight;
+
+    /**
+     * Highlight (typically outline of the FocusArea) drawn on top of the FocusArea and its
+     * descendants.
+     */
+    private Drawable mForegroundHighlight;
+
+    /**
+     * Highlight (typically a solid or gradient shape) drawn on top of the FocusArea but behind its
+     * descendants.
+     */
+    private Drawable mBackgroundHighlight;
+
+    /** The padding (in pixels) of the FocusArea highlight. */
+    private int mPaddingLeft;
+    private int mPaddingRight;
+    private int mPaddingTop;
+    private int mPaddingBottom;
+
+    public FocusArea(Context context) {
+        super(context);
+        init();
+    }
+
+    public FocusArea(Context context, @Nullable AttributeSet attrs) {
+        super(context, attrs);
+        init();
+    }
+
+    public FocusArea(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+        init();
+    }
+
+    public FocusArea(Context context, @Nullable AttributeSet attrs, int defStyleAttr,
+            int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+        init();
+    }
+
+    private void init() {
+        mEnableForegroundHighlight = getContext().getResources().getBoolean(
+                R.bool.car_ui_enable_focus_area_foreground_highlight);
+        mEnableBackgroundHighlight = getContext().getResources().getBoolean(
+                R.bool.car_ui_enable_focus_area_background_highlight);
+        mForegroundHighlight = getContext().getResources().getDrawable(
+                R.drawable.car_ui_focus_area_foreground_highlight, getContext().getTheme());
+        mBackgroundHighlight = getContext().getResources().getDrawable(
+                R.drawable.car_ui_focus_area_background_highlight, getContext().getTheme());
+
+        // Ensure that an AccessibilityNodeInfo is created for this view.
+        setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
+
+        // By default all ViewGroup subclasses do not call their draw() and onDraw() methods. We
+        // should enable it since we override these methods.
+        setWillNotDraw(false);
+
+        // Update highlight of the FocusArea when the focus of its descendants has changed.
+        getViewTreeObserver().addOnGlobalFocusChangeListener(
+                (oldFocus, newFocus) -> {
+                    boolean hasFocus = hasFocus();
+                    if (mHasFocus != hasFocus) {
+                        mHasFocus = hasFocus;
+                        invalidate();
+                    }
+                });
+    }
+
+    @Override
+    public void onDraw(Canvas canvas) {
+        super.onDraw(canvas);
+
+        // Draw highlight on top of this FocusArea (including its background and content) but
+        // behind its children.
+        if (mEnableBackgroundHighlight && mHasFocus) {
+            mBackgroundHighlight.setBounds(
+                    mPaddingLeft + getScrollX(),
+                    mPaddingTop + getScrollY(),
+                    getScrollX() + getWidth() - mPaddingRight,
+                    getScrollY() + getHeight() - mPaddingBottom);
+            mBackgroundHighlight.draw(canvas);
+        }
+    }
+
+    @Override
+    public void draw(Canvas canvas) {
+        super.draw(canvas);
+
+        // Draw highlight on top of this FocusArea (including its background and content) and its
+        // children (including background, content, focus highlight, etc).
+        if (mEnableForegroundHighlight && mHasFocus) {
+            mForegroundHighlight.setBounds(
+                    mPaddingLeft + getScrollX(),
+                    mPaddingTop + getScrollY(),
+                    getScrollX() + getWidth() - mPaddingRight,
+                    getScrollY() + getHeight() - mPaddingBottom);
+            mForegroundHighlight.draw(canvas);
+        }
+    }
+
+    @Override
+    public CharSequence getAccessibilityClassName() {
+        return FocusArea.class.getName();
+    }
+
+    /** Sets the padding (in pixels) of the FocusArea highlight. */
+    public void setHighlightPadding(int left, int top, int right, int bottom) {
+        if (mPaddingLeft == left && mPaddingTop == top && mPaddingRight == right
+                && mPaddingBottom == bottom) {
+            return;
+        }
+        mPaddingLeft = left;
+        mPaddingTop = top;
+        mPaddingRight = right;
+        mPaddingBottom = bottom;
+        invalidate();
+    }
+}
diff --git a/car-ui-lib/src/com/android/car/ui/FocusParkingView.java b/car-ui-lib/src/com/android/car/ui/FocusParkingView.java
new file mode 100644
index 0000000..1b4bd13
--- /dev/null
+++ b/car-ui-lib/src/com/android/car/ui/FocusParkingView.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.car.ui;
+
+import static android.view.accessibility.AccessibilityNodeInfo.ACTION_DISMISS;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.util.AttributeSet;
+import android.view.View;
+
+import androidx.annotation.Nullable;
+
+/**
+ * A transparent {@link View} that can take focus. It's used by {@link
+ * com.android.car.rotary.RotaryService} to support rotary controller navigation. Each {@link
+ * android.view.Window} must have at least one FocusParkingView. The {@link FocusParkingView} must
+ * be the first in Tab order, and outside of all {@link FocusArea}s.
+ *
+ * <p>
+ * Android doesn't clear focus automatically when focus is set in another window. If we try to clear
+ * focus in the previous window, Android will re-focus a view in that window, resulting in two
+ * windows being focused simultaneously. Adding this view to each window can fix this issue. This
+ * view is transparent and its default focus highlight is disabled, so it's invisible to the user no
+ * matter whether it's focused or not. It can take focus so that RotaryService can "park" the focus
+ * on it to remove the focus highlight.
+ * <p>
+ * If the focused view is scrolled off the screen, Android will refocus the first focusable view in
+ * the window. The FocusParkingView should be the first view so that it gets focus. The
+ * RotaryService detects this and moves focus to the scrolling container.
+ * <p>
+ * If there is only one focus area in the current window, rotating the controller within the focus
+ * area will cause RotaryService to move the focus around from the view on the right to the view on
+ * the left or vice versa. Adding this view to each window can fix this issue. When RotaryService
+ * finds out the focus target is a FocusParkingView, it will know a wrap-around is going to happen.
+ * Then it will avoid the wrap-around by not moving focus.
+ */
+public class FocusParkingView extends View {
+
+    public FocusParkingView(Context context) {
+        super(context);
+        init();
+    }
+
+    public FocusParkingView(Context context, @Nullable AttributeSet attrs) {
+        super(context, attrs);
+        init();
+    }
+
+    public FocusParkingView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+        init();
+    }
+
+    public FocusParkingView(Context context, @Nullable AttributeSet attrs, int defStyleAttr,
+            int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+        init();
+    }
+
+    private void init() {
+        // This view is focusable, visible and enabled so it can take focus.
+        setFocusable(View.FOCUSABLE);
+        setVisibility(VISIBLE);
+        setEnabled(true);
+
+        // This view is not clickable so it won't affect the app's behavior when the user clicks on
+        // it by accident.
+        setClickable(false);
+
+        // This view is always transparent.
+        setAlpha(0f);
+
+        // Prevent Android from drawing the default focus highlight for this view when it's focused.
+        setDefaultFocusHighlightEnabled(false);
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        // This size of the view is always 1 x 1 pixel, no matter what value is set in the layout
+        // file (match_parent, wrap_content, 100dp, 0dp, etc). Small size is to ensure it has little
+        // impact on the layout, non-zero size is to ensure it can take focus.
+        setMeasuredDimension(1, 1);
+    }
+
+    @Override
+    public void onWindowFocusChanged(boolean hasWindowFocus) {
+        if (!hasWindowFocus) {
+            // We need to clear the focus (by parking the focus on the FocusParkingView) once the
+            // current window goes to background. This can't be done by RotaryService because
+            // RotaryService sees the window as removed, thus can't perform any action (such as
+            // focus, clear focus) on the nodes in the window. So FocusParkingView has to grab the
+            // focus proactively.
+            requestFocus();
+        }
+        super.onWindowFocusChanged(hasWindowFocus);
+    }
+
+    @Override
+    public CharSequence getAccessibilityClassName() {
+        return FocusParkingView.class.getName();
+    }
+
+    @Override
+    public boolean performAccessibilityAction(int action, Bundle arguments) {
+        if (action == ACTION_DISMISS) {
+            // Try to move focus to the default focus.
+            getRootView().restoreDefaultFocus();
+            // The action failed if the FocusParkingView is still focused.
+            return !isFocused();
+        }
+        return super.performAccessibilityAction(action, arguments);
+    }
+}
diff --git a/car-ui-lib/src/com/android/car/ui/baselayout/ClickBlockingView.java b/car-ui-lib/src/com/android/car/ui/baselayout/ClickBlockingView.java
new file mode 100644
index 0000000..181495c
--- /dev/null
+++ b/car-ui-lib/src/com/android/car/ui/baselayout/ClickBlockingView.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.car.ui.baselayout;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.View;
+
+import androidx.annotation.Nullable;
+
+/**
+ * A view that doesn't allow any touches to pass through it to views below.
+ *
+ * <p>Used in baselayouts to prevent clicking through the toolbar.
+ */
+public class ClickBlockingView extends View {
+
+    private boolean mEatingTouch = false;
+    private boolean mEatingHover = false;
+
+    public ClickBlockingView(Context context) {
+        super(context);
+    }
+
+    public ClickBlockingView(Context context,
+            @Nullable AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public ClickBlockingView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+    }
+
+    public ClickBlockingView(Context context, @Nullable AttributeSet attrs, int defStyleAttr,
+            int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent ev) {
+        // Copied from androidx.appcompat.widget.Toolbar
+
+        // We always eat touch events, but should still respect the touch event dispatch
+        // contract. If the normal View implementation doesn't want the events, we'll just silently
+        // eat the rest of the gesture without reporting the events to the default implementation
+        // since that's what it expects.
+
+        final int action = ev.getActionMasked();
+        if (action == MotionEvent.ACTION_DOWN) {
+            mEatingTouch = false;
+        }
+
+        if (!mEatingTouch) {
+            final boolean handled = super.onTouchEvent(ev);
+            if (action == MotionEvent.ACTION_DOWN && !handled) {
+                mEatingTouch = true;
+            }
+        }
+
+        if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
+            mEatingTouch = false;
+        }
+
+        return true;
+    }
+
+    @Override
+    public boolean onHoverEvent(MotionEvent ev) {
+        // Copied from androidx.appcompat.widget.Toolbar
+
+        // Same deal as onTouchEvent() above. Eat all hover events, but still
+        // respect the touch event dispatch contract.
+
+        final int action = ev.getActionMasked();
+        if (action == MotionEvent.ACTION_HOVER_ENTER) {
+            mEatingHover = false;
+        }
+
+        if (!mEatingHover) {
+            final boolean handled = super.onHoverEvent(ev);
+            if (action == MotionEvent.ACTION_HOVER_ENTER && !handled) {
+                mEatingHover = true;
+            }
+        }
+
+        if (action == MotionEvent.ACTION_HOVER_EXIT || action == MotionEvent.ACTION_CANCEL) {
+            mEatingHover = false;
+        }
+
+        return true;
+    }
+}
diff --git a/car-ui-lib/src/com/android/car/ui/baselayout/InsetsChangedListener.java b/car-ui-lib/src/com/android/car/ui/baselayout/InsetsChangedListener.java
index 595ad06..8902e1e 100644
--- a/car-ui-lib/src/com/android/car/ui/baselayout/InsetsChangedListener.java
+++ b/car-ui-lib/src/com/android/car/ui/baselayout/InsetsChangedListener.java
@@ -16,6 +16,8 @@
 
 package com.android.car.ui.baselayout;
 
+import androidx.annotation.NonNull;
+
 /**
  * Interface for receiving changes to {@link Insets}.
  *
@@ -27,5 +29,5 @@
  */
 public interface InsetsChangedListener {
     /** Called when the insets change */
-    void onCarUiInsetsChanged(Insets insets);
+    void onCarUiInsetsChanged(@NonNull Insets insets);
 }
diff --git a/car-ui-lib/src/com/android/car/ui/core/BaseLayoutController.java b/car-ui-lib/src/com/android/car/ui/core/BaseLayoutController.java
index f488e9c..153b4e6 100644
--- a/car-ui-lib/src/com/android/car/ui/core/BaseLayoutController.java
+++ b/car-ui-lib/src/com/android/car/ui/core/BaseLayoutController.java
@@ -15,10 +15,9 @@
  */
 package com.android.car.ui.core;
 
-import static com.android.car.ui.utils.CarUiUtils.requireViewByRefId;
-
 import android.app.Activity;
 import android.content.res.TypedArray;
+import android.os.Build;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -36,9 +35,10 @@
 import com.android.car.ui.baselayout.InsetsChangedListener;
 import com.android.car.ui.toolbar.ToolbarController;
 import com.android.car.ui.toolbar.ToolbarControllerImpl;
+import com.android.car.ui.utils.CarUiUtils;
 
-import java.util.HashMap;
 import java.util.Map;
+import java.util.WeakHashMap;
 
 /**
  * BaseLayoutController accepts an {@link Activity} and sets up the base layout inside of it.
@@ -47,7 +47,7 @@
  */
 class BaseLayoutController {
 
-    private static Map<Activity, BaseLayoutController> sBaseLayoutMap = new HashMap<>();
+    private static final Map<Activity, BaseLayoutController> sBaseLayoutMap = new WeakHashMap<>();
 
     private InsetsUpdater mInsetsUpdater;
 
@@ -72,14 +72,18 @@
      *
      * <p>You can get a reference to it by calling {@link #getBaseLayout(Activity)}.
      */
-    /* package */ static void build(Activity activity) {
-        sBaseLayoutMap.put(activity, new BaseLayoutController(activity));
+    /* package */
+    static void build(Activity activity) {
+        if (getThemeBoolean(activity, R.attr.carUiBaseLayout)) {
+            sBaseLayoutMap.put(activity, new BaseLayoutController(activity));
+        }
     }
 
     /**
      * Destroy the BaseLayoutController for the given {@link Activity}.
      */
-    /* package */ static void destroy(Activity activity) {
+    /* package */
+    static void destroy(Activity activity) {
         sBaseLayoutMap.remove(activity);
     }
 
@@ -96,6 +100,14 @@
         return mInsetsUpdater.getInsets();
     }
 
+    /* package */ void dispatchNewInsets(Insets insets) {
+        mInsetsUpdater.dispatchNewInsets(insets);
+    }
+
+    /* package */ void replaceInsetsChangedListenerWith(InsetsChangedListener listener) {
+        mInsetsUpdater.replaceInsetsChangedListenerWith(listener);
+    }
+
     /**
      * Installs the base layout into an activity, moving its content view under the base layout.
      *
@@ -104,34 +116,41 @@
      * @param activity The {@link Activity} to install a base layout in.
      */
     private void installBaseLayout(Activity activity) {
-        boolean baseLayoutEnabled = getThemeBoolean(activity, R.attr.carUiBaseLayout);
         boolean toolbarEnabled = getThemeBoolean(activity, R.attr.carUiToolbar);
-        if (!baseLayoutEnabled) {
-            return;
-        }
+        boolean legacyToolbar = Build.VERSION.SDK_INT <= Build.VERSION_CODES.Q;
+        @LayoutRes final int baseLayoutRes;
 
-        @LayoutRes final int baseLayoutRes = toolbarEnabled
-                ? R.layout.car_ui_base_layout_toolbar
-                : R.layout.car_ui_base_layout;
+        if (toolbarEnabled) {
+            baseLayoutRes = legacyToolbar
+                    ? R.layout.car_ui_base_layout_toolbar_legacy
+                    : R.layout.car_ui_base_layout_toolbar;
+        } else {
+            baseLayoutRes = R.layout.car_ui_base_layout;
+        }
 
         View baseLayout = LayoutInflater.from(activity)
                 .inflate(baseLayoutRes, null, false);
 
         // Replace windowContentView with baseLayout
-        ViewGroup windowContentView = activity.getWindow().findViewById(android.R.id.content);
+        ViewGroup windowContentView = CarUiUtils.findViewByRefId(
+                activity.getWindow().getDecorView(), android.R.id.content);
         ViewGroup contentViewParent = (ViewGroup) windowContentView.getParent();
         int contentIndex = contentViewParent.indexOfChild(windowContentView);
         contentViewParent.removeView(windowContentView);
         contentViewParent.addView(baseLayout, contentIndex, windowContentView.getLayoutParams());
 
         // Add windowContentView to the baseLayout's content view
-        FrameLayout contentView = requireViewByRefId(baseLayout, R.id.content);
+        FrameLayout contentView = CarUiUtils.requireViewByRefId(baseLayout, R.id.content);
         contentView.addView(windowContentView, new FrameLayout.LayoutParams(
                 ViewGroup.LayoutParams.MATCH_PARENT,
                 ViewGroup.LayoutParams.MATCH_PARENT));
 
         if (toolbarEnabled) {
-            mToolbarController = new ToolbarControllerImpl(baseLayout);
+            if (legacyToolbar) {
+                mToolbarController = CarUiUtils.requireViewByRefId(baseLayout, R.id.car_ui_toolbar);
+            } else {
+                mToolbarController = new ToolbarControllerImpl(baseLayout);
+            }
         }
 
         mInsetsUpdater = new InsetsUpdater(activity, baseLayout, windowContentView);
@@ -142,8 +161,8 @@
      * Gets the boolean value of an Attribute from an {@link Activity Activity's}
      * {@link android.content.res.Resources.Theme}.
      */
-    private boolean getThemeBoolean(Activity activity, int attr) {
-        TypedArray a = activity.getTheme().obtainStyledAttributes(new int[] { attr });
+    private static boolean getThemeBoolean(Activity activity, int attr) {
+        TypedArray a = activity.getTheme().obtainStyledAttributes(new int[]{attr});
 
         try {
             return a.getBoolean(0, false);
@@ -176,6 +195,7 @@
         private final View mRightInsetView;
         private final View mTopInsetView;
         private final View mBottomInsetView;
+        private InsetsChangedListener mInsetsChangedListenerDelegate;
 
         private boolean mInsetsDirty = true;
         @NonNull
@@ -184,8 +204,8 @@
         /**
          * Constructs an InsetsUpdater that calculates and dispatches insets to an {@link Activity}.
          *
-         * @param activity The activity that is using base layouts
-         * @param baseLayout The root view of the base layout
+         * @param activity    The activity that is using base layouts
+         * @param baseLayout  The root view of the base layout
          * @param contentView The android.R.id.content View
          */
         InsetsUpdater(Activity activity, View baseLayout, View contentView) {
@@ -236,6 +256,10 @@
             return mInsets;
         }
 
+        public void replaceInsetsChangedListenerWith(InsetsChangedListener listener) {
+            mInsetsChangedListenerDelegate = listener;
+        }
+
         /**
          * onGlobalLayout() should recalculate the amount of insets we need, and then dispatch them.
          */
@@ -245,11 +269,14 @@
                 return;
             }
 
-            View content = mActivity.requireViewById(android.R.id.content);
+            View content = CarUiUtils.requireViewByRefId(mActivity.getWindow().getDecorView(),
+                    android.R.id.content);
 
             // Calculate how much each inset view overlays the content view
-            int top, bottom, left, right;
-            top = bottom = left = right = 0;
+            int top = 0;
+            int left = 0;
+            int right = 0;
+            int bottom = 0;
             if (mTopInsetView != null) {
                 top = Math.max(0, getBottomOfView(mTopInsetView) - getTopOfView(content));
             }
@@ -278,26 +305,37 @@
          *
          * @param insets The newly-changed insets.
          */
-        private void dispatchNewInsets(Insets insets) {
-            boolean handled = false;
-            if (mActivity instanceof InsetsChangedListener) {
-                ((InsetsChangedListener) mActivity).onCarUiInsetsChanged(insets);
-                handled = true;
-            }
+        /* package */ void dispatchNewInsets(Insets insets) {
+            mInsets = insets;
 
-            if (mActivity instanceof FragmentActivity) {
-                for (Fragment fragment : ((FragmentActivity) mActivity).getSupportFragmentManager()
-                        .getFragments()) {
-                    if (fragment instanceof InsetsChangedListener) {
-                        ((InsetsChangedListener) fragment).onCarUiInsetsChanged(insets);
-                        handled = true;
+            boolean handled = false;
+
+            if (mInsetsChangedListenerDelegate != null) {
+                mInsetsChangedListenerDelegate.onCarUiInsetsChanged(insets);
+                handled = true;
+            } else {
+                // If an explicit InsetsChangedListener is not provided,
+                // pass the insets to activities and fragments
+                if (mActivity instanceof InsetsChangedListener) {
+                    ((InsetsChangedListener) mActivity).onCarUiInsetsChanged(insets);
+                    handled = true;
+                }
+
+                if (mActivity instanceof FragmentActivity) {
+                    for (Fragment fragment : ((FragmentActivity) mActivity)
+                            .getSupportFragmentManager().getFragments()) {
+                        if (fragment instanceof InsetsChangedListener) {
+                            ((InsetsChangedListener) fragment).onCarUiInsetsChanged(insets);
+                            handled = true;
+                        }
                     }
                 }
             }
 
             if (!handled) {
-                mActivity.requireViewById(android.R.id.content).setPadding(
-                        insets.getLeft(), insets.getTop(), insets.getRight(), insets.getBottom());
+                CarUiUtils.requireViewByRefId(mActivity.getWindow().getDecorView(),
+                        android.R.id.content).setPadding(insets.getLeft(), insets.getTop(),
+                        insets.getRight(), insets.getBottom());
             }
         }
 
diff --git a/car-ui-lib/src/com/android/car/ui/core/CarUi.java b/car-ui-lib/src/com/android/car/ui/core/CarUi.java
index 21050be..ad67121 100644
--- a/car-ui-lib/src/com/android/car/ui/core/CarUi.java
+++ b/car-ui-lib/src/com/android/car/ui/core/CarUi.java
@@ -21,13 +21,19 @@
 import androidx.annotation.Nullable;
 
 import com.android.car.ui.baselayout.Insets;
+import com.android.car.ui.baselayout.InsetsChangedListener;
 import com.android.car.ui.toolbar.ToolbarController;
 
+import java.lang.reflect.Method;
+
 /**
  * Public interface for general CarUi static functions.
  */
 public class CarUi {
 
+    /** Prevent instantiating this class */
+    private CarUi() {}
+
     /**
      * Gets the {@link ToolbarController} for an activity. Requires that the Activity uses
      * Theme.CarUi.WithToolbar, or otherwise sets carUiBaseLayout and carUiToolbar to true.
@@ -36,7 +42,7 @@
      */
     @Nullable
     public static ToolbarController getToolbar(Activity activity) {
-        BaseLayoutController controller = BaseLayoutController.getBaseLayout(activity);
+        BaseLayoutController controller = getBaseLayoutController(activity);
         if (controller != null) {
             return controller.getToolbarController();
         }
@@ -55,14 +61,26 @@
     public static ToolbarController requireToolbar(Activity activity) {
         ToolbarController result = getToolbar(activity);
         if (result == null) {
-            throw new IllegalArgumentException("Activity does not have a CarUi Toolbar! "
-                    + "Are you using Theme.CarUi.WithToolbar?");
+            throw new IllegalArgumentException("Activity " + activity
+                    + " does not have a CarUi Toolbar!"
+                    + " Are you using Theme.CarUi.WithToolbar?");
         }
 
         return result;
     }
 
     /**
+     * Registering a listener to receive the InsetsChanged updates instead of the Activity.
+     */
+    public static void replaceInsetsChangedListenerWith(Activity activity,
+            InsetsChangedListener listener) {
+        BaseLayoutController controller = getBaseLayoutController(activity);
+        if (controller != null) {
+            controller.replaceInsetsChangedListenerWith(listener);
+        }
+    }
+
+    /**
      * Gets the current {@link Insets} of the given {@link Activity}. Only applies to Activities
      * using the base layout, ie have the theme attribute "carUiBaseLayout" set to true.
      *
@@ -72,7 +90,7 @@
      */
     @Nullable
     public static Insets getInsets(Activity activity) {
-        BaseLayoutController controller = BaseLayoutController.getBaseLayout(activity);
+        BaseLayoutController controller = getBaseLayoutController(activity);
         if (controller != null) {
             return controller.getInsets();
         }
@@ -93,10 +111,30 @@
     public static Insets requireInsets(Activity activity) {
         Insets result = getInsets(activity);
         if (result == null) {
-            throw new IllegalArgumentException("Activity does not have a base layout! "
-                    + "Are you using Theme.CarUi.WithToolbar or Theme.CarUi.NoToolbar?");
+            throw new IllegalArgumentException("Activity " + activity
+                    + " does not have a base layout!"
+                    + " Are you using Theme.CarUi.WithToolbar or Theme.CarUi.NoToolbar?");
         }
 
         return result;
     }
+
+    /* package */ static BaseLayoutController getBaseLayoutController(Activity activity) {
+        if (activity.getClassLoader().equals(CarUi.class.getClassLoader())) {
+            return BaseLayoutController.getBaseLayout(activity);
+        } else {
+            // Note: (b/156532465)
+            // The usage of the alternate classloader is to accommodate GMSCore.
+            // Some activities are loaded dynamically from external modules.
+            try {
+                Class baseLayoutControllerClass = activity.getClassLoader()
+                        .loadClass(BaseLayoutController.class.getName());
+                Method method = baseLayoutControllerClass
+                        .getDeclaredMethod("getBaseLayout", Activity.class);
+                return (BaseLayoutController) method.invoke(null, activity);
+            } catch (ReflectiveOperationException e) {
+                throw new RuntimeException(e);
+            }
+        }
+    }
 }
diff --git a/car-ui-lib/src/com/android/car/ui/core/CarUiInstaller.java b/car-ui-lib/src/com/android/car/ui/core/CarUiInstaller.java
index 1aaa375..e845979 100644
--- a/car-ui-lib/src/com/android/car/ui/core/CarUiInstaller.java
+++ b/car-ui-lib/src/com/android/car/ui/core/CarUiInstaller.java
@@ -15,17 +15,27 @@
  */
 package com.android.car.ui.core;
 
+import static com.android.car.ui.core.CarUi.getBaseLayoutController;
+
 import android.app.Activity;
 import android.app.Application;
 import android.content.ContentProvider;
 import android.content.ContentValues;
+import android.content.Context;
 import android.database.Cursor;
 import android.net.Uri;
+import android.os.Build;
 import android.os.Bundle;
+import android.util.Log;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 
+import com.android.car.ui.baselayout.Insets;
+
+import java.lang.reflect.Method;
+import java.util.Locale;
+
 /**
  * {@link ContentProvider ContentProvider's} onCreate() methods are "called for all registered
  * content providers on the application main thread at application launch time." This means we
@@ -34,14 +44,59 @@
  */
 public class CarUiInstaller extends ContentProvider {
 
+    private static final String TAG = "CarUiInstaller";
+    private static final String CAR_UI_INSET_LEFT = "CAR_UI_INSET_LEFT";
+    private static final String CAR_UI_INSET_RIGHT = "CAR_UI_INSET_RIGHT";
+    private static final String CAR_UI_INSET_TOP = "CAR_UI_INSET_TOP";
+    private static final String CAR_UI_INSET_BOTTOM = "CAR_UI_INSET_BOTTOM";
+
+    private static final boolean IS_DEBUG_DEVICE =
+            Build.TYPE.toLowerCase(Locale.ROOT).contains("debug")
+                    || Build.TYPE.toLowerCase(Locale.ROOT).equals("eng");
+
     @Override
     public boolean onCreate() {
-        Application application = (Application) getContext().getApplicationContext();
+        Context context = getContext();
+        if (context == null) {
+            Log.e(TAG, "CarUiInstaller had a null context!");
+            return false;
+        }
+        Log.i(TAG, "CarUiInstaller started for " + context.getPackageName());
+
+        Application application = (Application) context.getApplicationContext();
         application.registerActivityLifecycleCallbacks(
                 new Application.ActivityLifecycleCallbacks() {
+                    private Insets mInsets = null;
+                    private boolean mIsActivityStartedForFirstTime = false;
+
                     @Override
                     public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
-                        BaseLayoutController.build(activity);
+                        if (activity.getClassLoader()
+                                .equals(CarUiInstaller.class.getClassLoader())) {
+                            BaseLayoutController.build(activity);
+                        } else {
+                            callBaseLayoutControllerMethod("build", activity);
+                        }
+
+                        if (savedInstanceState != null) {
+                            int inset_left = savedInstanceState.getInt(CAR_UI_INSET_LEFT);
+                            int inset_top = savedInstanceState.getInt(CAR_UI_INSET_TOP);
+                            int inset_right = savedInstanceState.getInt(CAR_UI_INSET_RIGHT);
+                            int inset_bottom = savedInstanceState.getInt(CAR_UI_INSET_BOTTOM);
+                            mInsets = new Insets(inset_left, inset_top, inset_right, inset_bottom);
+                        }
+
+                        mIsActivityStartedForFirstTime = true;
+                    }
+
+                    @Override
+                    public void onActivityPostStarted(Activity activity) {
+                        BaseLayoutController controller = getBaseLayoutController(activity);
+                        if (mInsets != null && controller != null
+                                && mIsActivityStartedForFirstTime) {
+                            controller.dispatchNewInsets(mInsets);
+                            mIsActivityStartedForFirstTime = false;
+                        }
                     }
 
                     @Override
@@ -62,13 +117,33 @@
 
                     @Override
                     public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
+                        BaseLayoutController controller = getBaseLayoutController(activity);
+                        if (controller != null) {
+                            Insets insets = controller.getInsets();
+                            outState.putInt(CAR_UI_INSET_LEFT, insets.getLeft());
+                            outState.putInt(CAR_UI_INSET_TOP, insets.getTop());
+                            outState.putInt(CAR_UI_INSET_RIGHT, insets.getRight());
+                            outState.putInt(CAR_UI_INSET_BOTTOM, insets.getBottom());
+                        }
                     }
 
                     @Override
                     public void onActivityDestroyed(Activity activity) {
-                        BaseLayoutController.destroy(activity);
+                        if (activity.getClassLoader()
+                                .equals(CarUiInstaller.class.getClassLoader())) {
+                            BaseLayoutController.destroy(activity);
+                        } else {
+                            callBaseLayoutControllerMethod("destroy", activity);
+                        }
                     }
                 });
+
+        // Check only if we are in debug mode.
+        if (IS_DEBUG_DEVICE) {
+            CheckCarUiComponents checkCarUiComponents = new CheckCarUiComponents(application);
+            application.registerActivityLifecycleCallbacks(checkCarUiComponents);
+        }
+
         return true;
     }
 
@@ -102,4 +177,20 @@
             @Nullable String[] selectionArgs) {
         return 0;
     }
+
+    private static void callBaseLayoutControllerMethod(String methodName, Activity activity) {
+        // Note: (b/156532465)
+        // The usage of the alternate classloader is to accommodate GMSCore.
+        // Some activities are loaded dynamically from external modules.
+        try {
+            Class baseLayoutControllerClass =
+                    activity.getClassLoader()
+                            .loadClass(BaseLayoutController.class.getName());
+            Method method = baseLayoutControllerClass
+                    .getDeclaredMethod(methodName, Activity.class);
+            method.invoke(null, activity);
+        } catch (ReflectiveOperationException e) {
+            throw new RuntimeException(e);
+        }
+    }
 }
diff --git a/car-ui-lib/src/com/android/car/ui/core/CheckCarUiComponents.java b/car-ui-lib/src/com/android/car/ui/core/CheckCarUiComponents.java
new file mode 100644
index 0000000..b4fd358
--- /dev/null
+++ b/car-ui-lib/src/com/android/car/ui/core/CheckCarUiComponents.java
@@ -0,0 +1,245 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.car.ui.core;
+
+import android.app.Activity;
+import android.app.Application;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Toast;
+
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.android.car.ui.utils.CarUiUtils;
+
+/**
+ * Class used to traverse through the view hierarchy of the activity and check if carUI components
+ * are being used as expected.
+ *
+ * To check if the activity is using the CarUI components properly, navigate to the activity and
+ * run: adb shell am broadcast -a com.android.car.ui.intent.CHECK_CAR_UI_COMPONENTS. Filter
+ * the logs with "CheckCarUiComponents". This is ONLY available for debug and eng builds.
+ */
+class CheckCarUiComponents implements Application.ActivityLifecycleCallbacks {
+    private static final String TAG = CheckCarUiComponents.class.getSimpleName();
+    private static final String INTENT_FILTER = "com.android.car.ui.intent.CHECK_CAR_UI_COMPONENTS";
+    private View mRootView;
+    private boolean mIsScreenVisible;
+
+    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (!mIsScreenVisible) {
+                return;
+            }
+
+            CarUiComponents carUiComponents = new CarUiComponents();
+            checkForCarUiComponents(mRootView, carUiComponents);
+            if (carUiComponents.mIsUsingCarUiRecyclerView
+                    && !carUiComponents.mIsCarUiRecyclerViewUsingListItem) {
+                Log.e(TAG, "CarUiListItem are not used within CarUiRecyclerView: ");
+                showToast(context, "CarUiListItem are not used within CarUiRecyclerView");
+            }
+            if (carUiComponents.mIsUsingAndroidXRecyclerView) {
+                Log.e(TAG, "CarUiRecyclerView not used: ");
+                showToast(context, "CarUiRecycler is not used");
+            }
+            if (!carUiComponents.mIsUsingCarUiToolbar) {
+                Log.e(TAG, "CarUiToolbar is not used: ");
+                showToast(context, "CarUiToolbar is not used");
+            }
+            if (!carUiComponents.mIsUsingCarUiBaseLayoutToolbar
+                    && carUiComponents.mIsUsingCarUiToolbar) {
+                Log.e(TAG, "CarUiBaseLayoutToolbar is not used: ");
+                showToast(context, "CarUiBaseLayoutToolbar is not used");
+            }
+            if (carUiComponents.mIsUsingCarUiRecyclerViewForPreference
+                    && !carUiComponents.mIsUsingCarUiPreference) {
+                Log.e(TAG, "CarUiPreference is not used: ");
+                showToast(context, "CarUiPreference is not used");
+            }
+        }
+    };
+
+    CheckCarUiComponents(Context context) {
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(INTENT_FILTER);
+        context.registerReceiver(mReceiver, filter);
+    }
+
+    @Override
+    public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
+    }
+
+    @Override
+    public void onActivityStarted(Activity activity) {
+    }
+
+    @Override
+    public void onActivityResumed(Activity activity) {
+        mRootView = activity.getWindow().getDecorView().getRootView();
+        mIsScreenVisible = true;
+    }
+
+    @Override
+    public void onActivityPaused(Activity activity) {
+        mIsScreenVisible = false;
+    }
+
+    @Override
+    public void onActivityStopped(Activity activity) {
+    }
+
+    @Override
+    public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
+    }
+
+    @Override
+    public void onActivityDestroyed(Activity activity) {
+        if (mRootView != null
+                && CarUiUtils.getActivity(mRootView.getContext()) == activity) {
+            mRootView = null;
+        }
+    }
+
+    private void checkForCarUiComponents(View v, CarUiComponents carUiComponents) {
+        viewHasChildMatching(v, view -> {
+            if (isCarUiRecyclerView(view)) {
+                carUiComponents.mIsUsingCarUiRecyclerView = true;
+
+                if (viewHasChildMatching(view, CheckCarUiComponents::isCarUiPreference)) {
+                    carUiComponents.mIsUsingCarUiPreference = true;
+                    return false;
+                }
+
+                carUiComponents.mIsCarUiRecyclerViewUsingListItem = viewHasChildMatching(view,
+                        CheckCarUiComponents::isCarUiListItem);
+                return false;
+            }
+
+            if (isAndroidXRecyclerView(view)) {
+                carUiComponents.mIsUsingAndroidXRecyclerView = true;
+            }
+
+            if (isCarUiToolbar(view)) {
+                carUiComponents.mIsUsingCarUiToolbar = true;
+            }
+
+            if (isCarUiBaseLayoutToolbar(view)) {
+                carUiComponents.mIsUsingCarUiBaseLayoutToolbar = true;
+            }
+            return false;
+        });
+    }
+
+    private static boolean viewHasChildMatching(View view, Predicate<View> p) {
+        if (view == null) {
+            return false;
+        }
+        if (p.test(view)) {
+            return true;
+        }
+        if (view instanceof ViewGroup) {
+            for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
+                if (viewHasChildMatching(((ViewGroup) view).getChildAt(i), p)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    private static boolean isCarUiRecyclerView(View view) {
+        return view.getTag() != null && view.getTag().toString().equals("carUiRecyclerView");
+    }
+
+    private static boolean isCarUiListItem(View view) {
+        return view.getTag() != null && view.getTag().toString().equals("carUiListItem");
+    }
+
+    private static boolean isCarUiPreference(View view) {
+        return view.getTag() != null && view.getTag().toString().equals("carUiPreference");
+    }
+
+    private static boolean isCarUiToolbar(View view) {
+        return view.getTag() != null && (view.getTag().toString().equals("carUiToolbar")
+                || view.getTag().toString().equals("CarUiBaseLayoutToolbar"));
+    }
+
+    private static boolean isCarUiBaseLayoutToolbar(View view) {
+        return view.getTag() != null && view.getTag().toString().equals("CarUiBaseLayoutToolbar");
+    }
+
+    private static boolean isAndroidXRecyclerView(View view) {
+        return view.getClass() == RecyclerView.class;
+    }
+
+    private static void showToast(Context context, String message) {
+        Toast.makeText(context, message, Toast.LENGTH_LONG).show();
+    }
+
+    private static class CarUiComponents {
+        boolean mIsUsingCarUiRecyclerView;
+        boolean mIsUsingCarUiRecyclerViewForPreference;
+        boolean mIsCarUiRecyclerViewUsingListItem;
+        boolean mIsUsingCarUiToolbar;
+        boolean mIsUsingCarUiBaseLayoutToolbar;
+        boolean mIsUsingCarUiPreference;
+        boolean mIsUsingAndroidXRecyclerView;
+    }
+
+    /**
+     * Dump's the view hierarchy.
+     */
+    private static void printViewHierarchy(String indent, View view) {
+        StringBuilder sb = new StringBuilder();
+        sb.append("\n ");
+        sb.append(indent);
+        sb.append('{');
+
+        if (view == null) {
+            sb.append("viewNode= NULL, ");
+            sb.append('}');
+            return;
+        }
+
+        sb.append("viewNode= ").append(view.toString()).append(", ");
+        sb.append("id= ").append(view.getId()).append(", ");
+        sb.append("name= ").append(view.getAccessibilityClassName()).append(", ");
+
+        sb.append('}');
+        System.out.println(sb.toString());
+
+        indent += "  ";
+        if (!(view instanceof ViewGroup)) {
+            return;
+        }
+        for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
+            printViewHierarchy(indent, ((ViewGroup) view).getChildAt(i));
+        }
+    }
+
+    private interface Predicate<T> {
+        boolean test(T input);
+    }
+}
diff --git a/car-ui-lib/src/com/android/car/ui/preference/CarUiDialogFragment.java b/car-ui-lib/src/com/android/car/ui/preference/CarUiDialogFragment.java
index 6a848b8..5929e02 100644
--- a/car-ui-lib/src/com/android/car/ui/preference/CarUiDialogFragment.java
+++ b/car-ui-lib/src/com/android/car/ui/preference/CarUiDialogFragment.java
@@ -33,9 +33,12 @@
 import androidx.annotation.CallSuper;
 import androidx.annotation.LayoutRes;
 import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 import androidx.fragment.app.DialogFragment;
 import androidx.preference.DialogPreference;
 
+import com.android.car.ui.utils.CarUiUtils;
+
 /**
  * Abstract base class which presents a dialog associated with a {@link
  * androidx.preference.DialogPreference}. Since the preference object may not be available during
@@ -74,7 +77,7 @@
     private int mWhichButtonClicked;
 
     @Override
-    public void onCreate(Bundle savedInstanceState) {
+    public void onCreate(@Nullable Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
 
         if (savedInstanceState != null) {
@@ -106,7 +109,7 @@
 
     @Override
     @NonNull
-    public Dialog onCreateDialog(Bundle savedInstanceState) {
+    public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
         Context context = getActivity();
         mWhichButtonClicked = DialogInterface.BUTTON_NEGATIVE;
 
@@ -143,7 +146,7 @@
      *
      * <p>Do not {@link AlertDialog.Builder#create()} or {@link AlertDialog.Builder#show()}.
      */
-    protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
+    protected void onPrepareDialogBuilder(@NonNull AlertDialog.Builder builder) {
     }
 
     /**
@@ -192,8 +195,8 @@
      * @param view the content View of the dialog, if it is custom.
      */
     @CallSuper
-    protected void onBindDialogView(View view) {
-        View dialogMessageView = view.findViewById(android.R.id.message);
+    protected void onBindDialogView(@NonNull View view) {
+        View dialogMessageView = CarUiUtils.findViewByRefId(view, android.R.id.message);
 
         if (dialogMessageView != null) {
             CharSequence message = mDialogMessage;
@@ -219,7 +222,7 @@
     }
 
     @Override
-    public void onDismiss(DialogInterface dialog) {
+    public void onDismiss(@NonNull DialogInterface dialog) {
         super.onDismiss(dialog);
         onDialogClosed(mWhichButtonClicked == DialogInterface.BUTTON_POSITIVE);
     }
diff --git a/car-ui-lib/src/com/android/car/ui/preference/CarUiEditTextPreference.java b/car-ui-lib/src/com/android/car/ui/preference/CarUiEditTextPreference.java
index 4480714..3882e03 100644
--- a/car-ui-lib/src/com/android/car/ui/preference/CarUiEditTextPreference.java
+++ b/car-ui-lib/src/com/android/car/ui/preference/CarUiEditTextPreference.java
@@ -18,10 +18,14 @@
 
 import android.content.Context;
 import android.util.AttributeSet;
+import android.view.View;
 
+import androidx.annotation.VisibleForTesting;
 import androidx.preference.EditTextPreference;
+import androidx.preference.PreferenceViewHolder;
 
 import com.android.car.ui.R;
+import com.android.car.ui.utils.CarUiUtils;
 
 /**
  * This class extends the base {@link EditTextPreference} class. Adds the drawable icon to
@@ -53,6 +57,18 @@
         mContext = context;
     }
 
+    protected void setTwoActionLayout() {
+        setLayoutResource(R.layout.car_ui_two_action_preference);
+    }
+
+    /**
+     * Returns the widget container if {@link #setTwoActionLayout) was called, otherwise null.
+     */
+    @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED)
+    public View getWidgetActionContainer(PreferenceViewHolder holder) {
+        return CarUiUtils.findViewByRefId(holder.itemView, R.id.action_widget_container);
+    }
+
     @Override
     public void onAttached() {
         super.onAttached();
diff --git a/car-ui-lib/src/com/android/car/ui/preference/CarUiMultiSelectListPreference.java b/car-ui-lib/src/com/android/car/ui/preference/CarUiMultiSelectListPreference.java
index 4752082..bc626a0 100644
--- a/car-ui-lib/src/com/android/car/ui/preference/CarUiMultiSelectListPreference.java
+++ b/car-ui-lib/src/com/android/car/ui/preference/CarUiMultiSelectListPreference.java
@@ -52,6 +52,11 @@
         mContext = context;
     }
 
+    /**
+     * This is to make getSelectedItems() visible from other classes in
+     * com.android.car.ui.preference.
+     */
+    @Override
     protected boolean[] getSelectedItems() {
         return super.getSelectedItems();
     }
diff --git a/car-ui-lib/src/com/android/car/ui/preference/CarUiPreference.java b/car-ui-lib/src/com/android/car/ui/preference/CarUiPreference.java
index 5db22cf..111fbf5 100644
--- a/car-ui-lib/src/com/android/car/ui/preference/CarUiPreference.java
+++ b/car-ui-lib/src/com/android/car/ui/preference/CarUiPreference.java
@@ -18,20 +18,31 @@
 
 import android.content.Context;
 import android.content.res.TypedArray;
+import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
+import android.view.View;
+import android.widget.Toast;
 
+import androidx.annotation.NonNull;
 import androidx.preference.Preference;
+import androidx.preference.PreferenceViewHolder;
 
 import com.android.car.ui.R;
+import com.android.car.ui.utils.CarUiUtils;
 
 /**
  * This class extends the base {@link Preference} class. Adds the support to add a drawable icon to
  * the preference if there is one of fragment, intent or onPreferenceClickListener set.
  */
-public class CarUiPreference extends Preference {
+public class CarUiPreference extends Preference implements DisabledPreferenceCallback {
 
     private Context mContext;
     private boolean mShowChevron;
+    private String mMessageToShowWhenDisabledPreferenceClicked;
+
+    private boolean mShouldShowRippleOnDisabledPreference;
+    private Drawable mBackground;
+    private View mPreference;
 
     public CarUiPreference(Context context, AttributeSet attrs,
             int defStyleAttr, int defStyleRes) {
@@ -61,6 +72,20 @@
                 defStyleRes);
 
         mShowChevron = a.getBoolean(R.styleable.CarUiPreference_showChevron, true);
+        mShouldShowRippleOnDisabledPreference = a.getBoolean(
+                R.styleable.CarUiPreference_showRippleOnDisabledPreference, false);
+
+        a.recycle();
+    }
+
+
+    @Override
+    public void onBindViewHolder(PreferenceViewHolder holder) {
+        super.onBindViewHolder(holder);
+        boolean viewEnabled = isEnabled();
+        mPreference = holder.itemView;
+        mBackground = CarUiUtils.setPreferenceViewEnabled(viewEnabled, holder.itemView, mBackground,
+                mShouldShowRippleOnDisabledPreference);
     }
 
     @Override
@@ -80,7 +105,38 @@
         }
     }
 
+    /**
+     * This is similar to {@link Preference#performClick()} with the only difference that we do not
+     * return when view is not enabled.
+     */
+    @Override
+    @SuppressWarnings("RestrictTo")
+    public void performClick() {
+        if (isEnabled()) {
+            super.performClick();
+        } else if (mMessageToShowWhenDisabledPreferenceClicked != null
+                && !mMessageToShowWhenDisabledPreferenceClicked.isEmpty()) {
+            Toast.makeText(mContext, mMessageToShowWhenDisabledPreferenceClicked,
+                    Toast.LENGTH_LONG).show();
+        }
+    }
+
     public void setShowChevron(boolean showChevron) {
         mShowChevron = showChevron;
     }
+
+    /**
+     * Sets the ripple on the disabled preference.
+     */
+    @Override
+    public void setShouldShowRippleOnDisabledPreference(boolean showRipple) {
+        mShouldShowRippleOnDisabledPreference = showRipple;
+        CarUiUtils.updateRippleStateOnDisabledPreference(isEnabled(),
+                mShouldShowRippleOnDisabledPreference, mBackground, mPreference);
+    }
+
+    @Override
+    public void setMessageToShowWhenDisabledPreferenceClicked(@NonNull String message) {
+        mMessageToShowWhenDisabledPreferenceClicked = message;
+    }
 }
diff --git a/car-ui-lib/src/com/android/car/ui/preference/CarUiRadioButtonPreference.java b/car-ui-lib/src/com/android/car/ui/preference/CarUiRadioButtonPreference.java
new file mode 100644
index 0000000..f02f105
--- /dev/null
+++ b/car-ui-lib/src/com/android/car/ui/preference/CarUiRadioButtonPreference.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.car.ui.preference;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.RadioButton;
+
+import androidx.preference.PreferenceViewHolder;
+import androidx.preference.TwoStatePreference;
+
+import com.android.car.ui.R;
+import com.android.car.ui.utils.CarUiUtils;
+
+/** A preference which shows a radio button at the start of the preference. */
+public class CarUiRadioButtonPreference extends TwoStatePreference {
+
+    public CarUiRadioButtonPreference(Context context, AttributeSet attrs,
+            int defStyleAttr, int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+        init();
+    }
+
+    public CarUiRadioButtonPreference(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+        init();
+    }
+
+    public CarUiRadioButtonPreference(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        init();
+    }
+
+    public CarUiRadioButtonPreference(Context context) {
+        super(context);
+        init();
+    }
+
+    private void init() {
+        setLayoutResource(R.layout.car_ui_preference);
+        setWidgetLayoutResource(R.layout.car_ui_radio_button_preference_widget);
+    }
+
+    @Override
+    public void onBindViewHolder(PreferenceViewHolder holder) {
+        super.onBindViewHolder(holder);
+
+        RadioButton radioButton = (RadioButton) CarUiUtils.findViewByRefId(holder.itemView,
+                R.id.radio_button);
+        radioButton.setChecked(isChecked());
+    }
+}
diff --git a/car-ui-lib/src/com/android/car/ui/preference/CarUiSeekBarDialogPreference.java b/car-ui-lib/src/com/android/car/ui/preference/CarUiSeekBarDialogPreference.java
new file mode 100644
index 0000000..29e9e33
--- /dev/null
+++ b/car-ui-lib/src/com/android/car/ui/preference/CarUiSeekBarDialogPreference.java
@@ -0,0 +1,268 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.car.ui.preference;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.preference.DialogPreference;
+
+import com.android.car.ui.R;
+import com.android.car.ui.utils.CarUiUtils;
+
+/** A class implements some basic methods of a seekbar dialog preference. */
+public class CarUiSeekBarDialogPreference extends DialogPreference
+        implements DialogFragmentCallbacks {
+
+    private int mSeekBarProgress;
+    private SeekBar mSeekBar;
+
+    private int mSeekBarTopTextViewVisibility;
+    private TextView mSeekBarTopTextView;
+    private String mSeekBarTopText;
+
+    private int mSeekBarLeftTextViewVisibility;
+    private TextView mSeekBarLeftTextView;
+    private String mSeekBarLeftText;
+
+    private int mSeekBarRightTextViewVisibility;
+    private TextView mSeekBarRightTextView;
+    private String mSeekBarRightText;
+
+    private SeekBar.OnSeekBarChangeListener mOnSeekBarChangeListener;
+    private int mMaxProgress = 100;
+
+    public CarUiSeekBarDialogPreference(Context context, AttributeSet attrs,
+            int defStyleAttr, int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+        init();
+    }
+
+    public CarUiSeekBarDialogPreference(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+        init();
+    }
+
+    public CarUiSeekBarDialogPreference(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        init();
+    }
+
+    public CarUiSeekBarDialogPreference(Context context) {
+        super(context);
+        init();
+    }
+
+    private void init() {
+        setDialogLayoutResource(R.layout.car_ui_seekbar_dialog);
+        setPositiveButtonText(R.string.car_ui_dialog_preference_positive);
+        setNegativeButtonText(R.string.car_ui_dialog_preference_negative);
+    }
+
+    @Override
+    public void onAttached() {
+        super.onAttached();
+        mSeekBarProgress = getPersistedInt(0);
+    }
+
+    @Override
+    public void onBindDialogView(@NonNull View view) {
+        mSeekBar = CarUiUtils.findViewByRefId(view, R.id.seek_bar);
+        mSeekBarTopTextView = CarUiUtils.findViewByRefId(view, R.id.seek_bar_text_top);
+        mSeekBarLeftTextView = CarUiUtils.findViewByRefId(view, R.id.seek_bar_text_left);
+        mSeekBarRightTextView = CarUiUtils.findViewByRefId(view, R.id.seek_bar_text_right);
+
+        setProgress(mSeekBarProgress);
+
+        setSeekBarTopTextViewVisibility(mSeekBarTopTextViewVisibility);
+        setSeekBarTopTextViewText(mSeekBarTopText);
+
+        setSeekBarLeftTextViewVisibility(mSeekBarLeftTextViewVisibility);
+        setSeekBarLeftTextViewText(mSeekBarLeftText);
+
+        setSeekBarRightTextViewVisibility(mSeekBarRightTextViewVisibility);
+        setSeekBarRightTextViewText(mSeekBarRightText);
+
+        setMaxProgress(mMaxProgress);
+        setOnSeekBarChangeListener(mOnSeekBarChangeListener);
+    }
+
+    /**
+     * Get the progress bar's current level of progress. Return 0 when the progress bar is in
+     * indeterminate mode.
+     */
+    public int getProgress() {
+        if (mSeekBar != null) {
+            return mSeekBar.getProgress();
+        }
+        return mSeekBarProgress;
+    }
+
+    /**
+     * Sets the current progress to the specified value.
+     */
+    public void setProgress(int progress) {
+        if (mSeekBar != null) {
+            mSeekBar.setProgress(progress);
+        }
+        mSeekBarProgress = progress;
+    }
+
+    @Override
+    public void onDialogClosed(boolean positiveResult) {
+        if (positiveResult) {
+            mSeekBarProgress = mSeekBar.getProgress();
+            persistInt(mSeekBarProgress);
+            notifyChanged();
+        }
+
+        mSeekBarTopTextView = null;
+        mSeekBarRightTextView = null;
+        mSeekBarLeftTextView = null;
+        mSeekBar = null;
+    }
+
+    /**
+     * Sets the text view visibility on top of the seekbar.
+     */
+    public void setSeekBarTopTextViewVisibility(int visibility) {
+        if (mSeekBarTopTextView != null) {
+            mSeekBarTopTextView.setVisibility(visibility);
+        }
+        mSeekBarTopTextViewVisibility = visibility;
+    }
+
+    /**
+     * Gets the text on top of the seekbar.
+     */
+    @Nullable
+    public String getSeekBarTopTextViewText() {
+        if (mSeekBarTopTextView != null) {
+            return mSeekBarTopTextView.getText().toString();
+        }
+        return mSeekBarTopText;
+    }
+
+    /**
+     * Sets the text on top of the seekbar.
+     */
+    public void setSeekBarTopTextViewText(String text) {
+        if (mSeekBarTopTextView != null) {
+            mSeekBarTopTextView.setText(text);
+        }
+        mSeekBarTopText = text;
+    }
+
+    /**
+     * Sets the text view visibility on left of the seekbar.
+     */
+    public void setSeekBarLeftTextViewVisibility(int visibility) {
+        if (mSeekBarLeftTextView != null) {
+            mSeekBarLeftTextView.setVisibility(visibility);
+        }
+        mSeekBarLeftTextViewVisibility = visibility;
+    }
+
+    /**
+     * Gets the text on left of the seekbar.
+     */
+    @Nullable
+    public String getSeekBarLeftTextViewText() {
+        if (mSeekBarLeftTextView != null) {
+            return mSeekBarLeftTextView.getText().toString();
+        }
+        return mSeekBarLeftText;
+    }
+
+    /**
+     * Sets the text on Left of the seekbar.
+     */
+    public void setSeekBarLeftTextViewText(@Nullable String text) {
+        if (mSeekBarLeftTextView != null) {
+            mSeekBarLeftTextView.setText(text);
+        }
+        mSeekBarLeftText = text;
+    }
+
+
+    /**
+     * Sets the text view visibility on right of the seekbar.
+     */
+    public void setSeekBarRightTextViewVisibility(int visibility) {
+        if (mSeekBarRightTextView != null) {
+            mSeekBarRightTextView.setVisibility(visibility);
+        }
+        mSeekBarRightTextViewVisibility = visibility;
+    }
+
+    /**
+     * Gets the text on right of the seekbar.
+     */
+    @Nullable
+    public String getSeekBarRightTextViewText() {
+        if (mSeekBarRightTextView != null) {
+            return mSeekBarRightTextView.getText().toString();
+        }
+        return mSeekBarRightText;
+    }
+
+
+    /**
+     * Sets the text on right of the seekbar.
+     */
+    public void setSeekBarRightTextViewText(@Nullable String text) {
+        if (mSeekBarRightTextView != null) {
+            mSeekBarRightTextView.setText(text);
+        }
+        mSeekBarRightText = text;
+    }
+
+    /**
+     * Sets a listener to receive notifications of changes to the SeekBar's progress level. Also
+     * provides notifications of when the user starts and stops a touch gesture within the SeekBar.
+     *
+     * @param listener The seek bar notification listener
+     * @see SeekBar.OnSeekBarChangeListener
+     */
+    public void setOnSeekBarChangeListener(SeekBar.OnSeekBarChangeListener listener) {
+        if (mSeekBar != null) {
+            mSeekBar.setOnSeekBarChangeListener(listener);
+        }
+        mOnSeekBarChangeListener = listener;
+    }
+
+    /** Get the upper range of the progress bar */
+    public int getMaxProgress() {
+        if (mSeekBar != null) {
+            return mSeekBar.getMax();
+        }
+        return mMaxProgress;
+    }
+
+    /** Set the upper range of the progress bar */
+    public void setMaxProgress(int maxProgress) {
+        if (mSeekBar != null) {
+            mSeekBar.setMax(maxProgress);
+        }
+        mMaxProgress = maxProgress;
+    }
+}
diff --git a/car-ui-lib/src/com/android/car/ui/preference/CarUiSwitchPreference.java b/car-ui-lib/src/com/android/car/ui/preference/CarUiSwitchPreference.java
new file mode 100644
index 0000000..e2b141d
--- /dev/null
+++ b/car-ui-lib/src/com/android/car/ui/preference/CarUiSwitchPreference.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.car.ui.preference;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.Toast;
+
+import androidx.annotation.NonNull;
+import androidx.preference.PreferenceViewHolder;
+import androidx.preference.SwitchPreference;
+
+import com.android.car.ui.R;
+import com.android.car.ui.utils.CarUiUtils;
+
+/**
+ * This class extends the base {@link SwitchPreference} class. Adds the functionality to show
+ * message when preference is disabled.
+ */
+public class CarUiSwitchPreference extends SwitchPreference implements DisabledPreferenceCallback {
+
+    private String mMessageToShowWhenDisabledPreferenceClicked;
+
+    private boolean mShouldShowRippleOnDisabledPreference;
+    private Drawable mBackground;
+    private View mPreference;
+    private Context mContext;
+
+    public CarUiSwitchPreference(Context context, AttributeSet attrs, int defStyleAttr,
+            int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+        init(context, attrs);
+    }
+
+    public CarUiSwitchPreference(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+        init(context, attrs);
+    }
+
+    public CarUiSwitchPreference(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        init(context, attrs);
+    }
+
+    public CarUiSwitchPreference(Context context) {
+        super(context);
+        init(context, null);
+    }
+
+    private void init(Context context, AttributeSet attrs) {
+        mContext = context;
+        TypedArray preferenceAttributes = getContext().obtainStyledAttributes(attrs,
+                R.styleable.CarUiPreference);
+        mShouldShowRippleOnDisabledPreference = preferenceAttributes.getBoolean(
+                R.styleable.CarUiPreference_showRippleOnDisabledPreference, false);
+        preferenceAttributes.recycle();
+    }
+
+    @Override
+    public void onBindViewHolder(PreferenceViewHolder holder) {
+        super.onBindViewHolder(holder);
+        mPreference = holder.itemView;
+        mBackground = CarUiUtils.setPreferenceViewEnabled(isEnabled(), holder.itemView, mBackground,
+                mShouldShowRippleOnDisabledPreference);
+    }
+
+    /**
+     * This is similar to {@link Preference#performClick()} with the only difference that we do not
+     * return when view is not enabled.
+     */
+    @Override
+    @SuppressWarnings("RestrictTo")
+    public void performClick() {
+        if (isEnabled()) {
+            super.performClick();
+        } else if (mMessageToShowWhenDisabledPreferenceClicked != null
+                && !mMessageToShowWhenDisabledPreferenceClicked.isEmpty()) {
+            Toast.makeText(mContext, mMessageToShowWhenDisabledPreferenceClicked,
+                    Toast.LENGTH_LONG).show();
+        }
+    }
+
+    /**
+     * Sets the ripple on the disabled preference.
+     */
+    @Override
+    public void setShouldShowRippleOnDisabledPreference(boolean showRipple) {
+        mShouldShowRippleOnDisabledPreference = showRipple;
+        CarUiUtils.updateRippleStateOnDisabledPreference(isEnabled(),
+                mShouldShowRippleOnDisabledPreference, mBackground, mPreference);
+    }
+
+    @Override
+    public void setMessageToShowWhenDisabledPreferenceClicked(@NonNull String message) {
+        mMessageToShowWhenDisabledPreferenceClicked = message;
+    }
+}
diff --git a/car-ui-lib/src/com/android/car/ui/preference/CarUiTwoActionPreference.java b/car-ui-lib/src/com/android/car/ui/preference/CarUiTwoActionPreference.java
new file mode 100644
index 0000000..3b9a583
--- /dev/null
+++ b/car-ui-lib/src/com/android/car/ui/preference/CarUiTwoActionPreference.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.car.ui.preference;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.util.AttributeSet;
+import android.view.View;
+
+import androidx.annotation.NonNull;
+import androidx.preference.PreferenceViewHolder;
+
+import com.android.car.ui.R;
+import com.android.car.ui.utils.CarUiUtils;
+
+/**
+ * A preference which can perform two actions. The secondary action is shown by default.
+ * {@link #showAction(boolean)} may be used to manually set the visibility of the action.
+ */
+public class CarUiTwoActionPreference extends CarUiPreference {
+
+    private boolean mIsActionShown;
+
+    public CarUiTwoActionPreference(Context context, AttributeSet attrs,
+            int defStyleAttr, int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+        init(attrs);
+    }
+
+    public CarUiTwoActionPreference(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+        init(attrs);
+    }
+
+    public CarUiTwoActionPreference(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        init(attrs);
+    }
+
+    public CarUiTwoActionPreference(Context context) {
+        super(context);
+        init(/* attrs= */ null);
+    }
+
+    /**
+     * Sets the custom two action preference layout and attributes.
+     * Check {@link #setLayoutResource} for layout requirements.
+     */
+    private void init(AttributeSet attrs) {
+        setLayoutResource(R.layout.car_ui_two_action_preference);
+        TypedArray preferenceAttributes = getContext().obtainStyledAttributes(attrs,
+                R.styleable.CarUiTwoActionPreference);
+        mIsActionShown = preferenceAttributes.getBoolean(
+                R.styleable.CarUiTwoActionPreference_actionShown, true);
+        setShowChevron(false);
+        preferenceAttributes.recycle();
+    }
+
+    /**
+     * Sets whether the secondary action is visible in the preference.
+     *
+     * @param isShown {@code true} if the secondary action should be shown.
+     */
+    public void showAction(boolean isShown) {
+        mIsActionShown = isShown;
+        notifyChanged();
+    }
+
+    /** Returns {@code true} if action is shown. */
+    public boolean isActionShown() {
+        return mIsActionShown;
+    }
+
+    @Override
+    public void onBindViewHolder(PreferenceViewHolder holder) {
+        super.onBindViewHolder(holder);
+        View actionContainer = CarUiUtils.findViewByRefId(holder.itemView,
+                R.id.action_widget_container);
+        View widgetFrame = CarUiUtils.findViewByRefId(holder.itemView, android.R.id.widget_frame);
+        if (mIsActionShown) {
+            actionContainer.setVisibility(View.VISIBLE);
+            onBindWidgetFrame(widgetFrame);
+        } else {
+            actionContainer.setVisibility(View.GONE);
+        }
+    }
+
+    /**
+     * Binds the created View for the second action.
+     *
+     * <p>This is a good place to set properties on any custom view.
+     *
+     * @param widgetFrame The widget frame which controls the 2nd action.
+     */
+    protected void onBindWidgetFrame(@NonNull View widgetFrame) {
+    }
+}
diff --git a/car-ui-lib/src/com/android/car/ui/preference/DialogFragmentCallbacks.java b/car-ui-lib/src/com/android/car/ui/preference/DialogFragmentCallbacks.java
new file mode 100644
index 0000000..ec92d9f
--- /dev/null
+++ b/car-ui-lib/src/com/android/car/ui/preference/DialogFragmentCallbacks.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.car.ui.preference;
+
+import android.app.AlertDialog;
+import android.content.DialogInterface;
+import android.view.View;
+
+import androidx.annotation.NonNull;
+import androidx.preference.DialogPreference;
+
+/**
+ * Interface for preferences to handle their own dialogs.
+ *
+ * A {@link androidx.preference.Preference} should implement this, and its {@link DialogPreference}
+ * will call these methods on the Preference.
+ */
+public interface DialogFragmentCallbacks extends DialogInterface.OnClickListener {
+
+    /** See {@link CarUiDialogFragment#onPrepareDialogBuilder(AlertDialog.Builder)}. */
+    default void onPrepareDialogBuilder(@NonNull AlertDialog.Builder builder) {}
+
+    @Override
+    default void onClick(@NonNull DialogInterface dialog, int which) {}
+
+    /** See {@link CarUiDialogFragment#onDialogClosed(boolean)}. */
+    default void onDialogClosed(boolean positiveResult) {}
+
+    /** See {@link CarUiDialogFragment#onBindDialogView(View)}. */
+    default void onBindDialogView(@NonNull View view) {}
+}
diff --git a/car-ui-lib/src/com/android/car/ui/preference/DisabledPreferenceCallback.java b/car-ui-lib/src/com/android/car/ui/preference/DisabledPreferenceCallback.java
new file mode 100644
index 0000000..ea3585b
--- /dev/null
+++ b/car-ui-lib/src/com/android/car/ui/preference/DisabledPreferenceCallback.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.car.ui.preference;
+
+import androidx.annotation.NonNull;
+
+/**
+ * Interface for preferences to handle clicks when its disabled.
+ */
+public interface DisabledPreferenceCallback {
+
+    /**
+     * Sets if the ripple effect should be shown on disabled preference.
+     */
+    default void setShouldShowRippleOnDisabledPreference(boolean showRipple) {}
+
+    /**
+     * Sets the message to be displayed when the disabled preference is clicked.
+     */
+    default void setMessageToShowWhenDisabledPreferenceClicked(@NonNull String message) {}
+}
diff --git a/car-ui-lib/src/com/android/car/ui/preference/EditTextPreferenceDialogFragment.java b/car-ui-lib/src/com/android/car/ui/preference/EditTextPreferenceDialogFragment.java
index 97a58d2..c40ba48 100644
--- a/car-ui-lib/src/com/android/car/ui/preference/EditTextPreferenceDialogFragment.java
+++ b/car-ui-lib/src/com/android/car/ui/preference/EditTextPreferenceDialogFragment.java
@@ -28,6 +28,8 @@
 import androidx.annotation.NonNull;
 import androidx.preference.EditTextPreference;
 
+import com.android.car.ui.utils.CarUiUtils;
+
 /**
  * Presents a dialog with an {@link EditText} associated with an {@link EditTextPreference}.
  *
@@ -49,6 +51,7 @@
      * Returns a new instance of {@link EditTextPreferenceDialogFragment} for the {@link
      * EditTextPreference} with the given {@code key}.
      */
+    @NonNull
     public static EditTextPreferenceDialogFragment newInstance(String key) {
         EditTextPreferenceDialogFragment fragment =
                 new EditTextPreferenceDialogFragment();
@@ -75,10 +78,10 @@
     }
 
     @Override
-    protected void onBindDialogView(View view) {
+    protected void onBindDialogView(@NonNull View view) {
         super.onBindDialogView(view);
 
-        mEditText = view.findViewById(android.R.id.edit);
+        mEditText = CarUiUtils.findViewByRefId(view, android.R.id.edit);
 
         if (mEditText == null) {
             throw new IllegalStateException(
diff --git a/car-ui-lib/src/com/android/car/ui/preference/ListPreferenceFragment.java b/car-ui-lib/src/com/android/car/ui/preference/ListPreferenceFragment.java
index 2543fb5..348ec54 100644
--- a/car-ui-lib/src/com/android/car/ui/preference/ListPreferenceFragment.java
+++ b/car-ui-lib/src/com/android/car/ui/preference/ListPreferenceFragment.java
@@ -31,11 +31,16 @@
 import androidx.preference.Preference;
 
 import com.android.car.ui.R;
+import com.android.car.ui.baselayout.Insets;
+import com.android.car.ui.baselayout.InsetsChangedListener;
+import com.android.car.ui.core.CarUi;
 import com.android.car.ui.recyclerview.CarUiContentListItem;
 import com.android.car.ui.recyclerview.CarUiListItem;
 import com.android.car.ui.recyclerview.CarUiListItemAdapter;
 import com.android.car.ui.recyclerview.CarUiRecyclerView;
 import com.android.car.ui.toolbar.Toolbar;
+import com.android.car.ui.toolbar.ToolbarController;
+import com.android.car.ui.utils.CarUiUtils;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -44,15 +49,29 @@
  * A fragment that provides a layout with a list of options associated with a {@link
  * ListPreference}.
  */
-public class ListPreferenceFragment extends Fragment {
+public class ListPreferenceFragment extends Fragment implements InsetsChangedListener {
 
+    private ToolbarController mToolbar;
     private ListPreference mPreference;
     private CarUiContentListItem mSelectedItem;
+    private int mSelectedIndex = -1;
+    private final Toolbar.OnBackListener mOnBackListener = () -> {
+        if (mSelectedIndex >= 0 && mPreference != null) {
+            String entryValue = mPreference.getEntryValues()[mSelectedIndex].toString();
+
+            if (mPreference.callChangeListener(entryValue)) {
+                mPreference.setValue(entryValue);
+            }
+        }
+
+        return false;
+    };
 
     /**
      * Returns a new instance of {@link ListPreferenceFragment} for the {@link ListPreference} with
      * the given {@code key}.
      */
+    @NonNull
     static ListPreferenceFragment newInstance(String key) {
         ListPreferenceFragment fragment = new ListPreferenceFragment();
         Bundle b = new Bundle(/* capacity= */ 1);
@@ -66,29 +85,40 @@
     public View onCreateView(
             @NonNull LayoutInflater inflater, @Nullable ViewGroup container,
             @Nullable Bundle savedInstanceState) {
-        return inflater.inflate(R.layout.car_ui_list_preference, container, false);
+        if (CarUi.getToolbar(getActivity()) == null) {
+            return inflater.inflate(R.layout.car_ui_list_preference_with_toolbar, container, false);
+        } else {
+            return inflater.inflate(R.layout.car_ui_list_preference, container, false);
+        }
     }
 
     @Override
     public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
         super.onViewCreated(view, savedInstanceState);
-        final CarUiRecyclerView carUiRecyclerView = view.requireViewById(R.id.list);
-        final Toolbar toolbar = view.requireViewById(R.id.toolbar);
+        final CarUiRecyclerView carUiRecyclerView = CarUiUtils.requireViewByRefId(view, R.id.list);
+        mToolbar = CarUi.getToolbar(getActivity());
 
-        carUiRecyclerView.setPadding(0, toolbar.getHeight(), 0, 0);
-        toolbar.registerToolbarHeightChangeListener(newHeight -> {
-            if (carUiRecyclerView.getPaddingTop() == newHeight) {
-                return;
-            }
+        // TODO(b/150230923) remove the code for the old toolbar height change when apps are ready
+        if (mToolbar == null) {
+            Toolbar toolbarView = CarUiUtils.requireViewByRefId(view, R.id.toolbar);
+            mToolbar = toolbarView;
 
-            int oldHeight = carUiRecyclerView.getPaddingTop();
-            carUiRecyclerView.setPadding(0, newHeight, 0, 0);
-            carUiRecyclerView.scrollBy(0, oldHeight - newHeight);
-        });
+            carUiRecyclerView.setPadding(0, toolbarView.getHeight(), 0, 0);
+            toolbarView.registerToolbarHeightChangeListener(newHeight -> {
+                if (carUiRecyclerView.getPaddingTop() == newHeight) {
+                    return;
+                }
+
+                int oldHeight = carUiRecyclerView.getPaddingTop();
+                carUiRecyclerView.setPadding(0, newHeight, 0, 0);
+                carUiRecyclerView.scrollBy(0, oldHeight - newHeight);
+            });
+        }
 
         carUiRecyclerView.setClipToPadding(false);
         mPreference = getListPreference();
-        toolbar.setTitle(mPreference.getTitle());
+        mToolbar.setTitle(mPreference.getTitle());
+        mToolbar.setState(Toolbar.State.SUBPAGE);
 
         CharSequence[] entries = mPreference.getEntries();
         CharSequence[] entryValues = mPreference.getEntryValues();
@@ -103,7 +133,7 @@
                     "ListPreference entries array length does not match entryValues array length.");
         }
 
-        int selectedEntryIndex = mPreference.findIndexOfValue(mPreference.getValue());
+        mSelectedIndex = mPreference.findIndexOfValue(mPreference.getValue());
         List<CarUiListItem> listItems = new ArrayList<>();
         CarUiListItemAdapter adapter = new CarUiListItemAdapter(listItems);
 
@@ -113,7 +143,7 @@
                     CarUiContentListItem.Action.RADIO_BUTTON);
             item.setTitle(entry);
 
-            if (i == selectedEntryIndex) {
+            if (i == mSelectedIndex) {
                 item.setChecked(true);
                 mSelectedItem = item;
             }
@@ -124,27 +154,31 @@
                     adapter.notifyItemChanged(listItems.indexOf(mSelectedItem));
                 }
                 mSelectedItem = listItem;
+                mSelectedIndex = listItems.indexOf(mSelectedItem);
             });
 
             listItems.add(item);
         }
 
-        toolbar.registerOnBackListener(() -> {
-            if (mSelectedItem != null) {
-                int selectedIndex = listItems.indexOf(mSelectedItem);
-                String entryValue = entryValues[selectedIndex].toString();
-
-                if (mPreference.callChangeListener(entryValue)) {
-                    mPreference.setValue(entryValue);
-                }
-            }
-
-            return false;
-        });
-
         carUiRecyclerView.setAdapter(adapter);
     }
 
+    @Override
+    public void onStart() {
+        super.onStart();
+        mToolbar.registerOnBackListener(mOnBackListener);
+        Insets insets = CarUi.getInsets(getActivity());
+        if (insets != null) {
+            onCarUiInsetsChanged(insets);
+        }
+    }
+
+    @Override
+    public void onStop() {
+        super.onStop();
+        mToolbar.unregisterOnBackListener(mOnBackListener);
+    }
+
     private ListPreference getListPreference() {
         if (getArguments() == null) {
             throw new IllegalStateException("Preference arguments cannot be null");
@@ -175,4 +209,12 @@
 
         return (ListPreference) preference;
     }
+
+    @Override
+    public void onCarUiInsetsChanged(@NonNull Insets insets) {
+        View view = requireView();
+        CarUiUtils.requireViewByRefId(view, R.id.list)
+                .setPadding(0, insets.getTop(), 0, insets.getBottom());
+        view.setPadding(insets.getLeft(), 0, insets.getRight(), 0);
+    }
 }
diff --git a/car-ui-lib/src/com/android/car/ui/preference/MultiSelectListPreferenceFragment.java b/car-ui-lib/src/com/android/car/ui/preference/MultiSelectListPreferenceFragment.java
index c445142..1d4a3a2 100644
--- a/car-ui-lib/src/com/android/car/ui/preference/MultiSelectListPreferenceFragment.java
+++ b/car-ui-lib/src/com/android/car/ui/preference/MultiSelectListPreferenceFragment.java
@@ -30,11 +30,16 @@
 import androidx.preference.Preference;
 
 import com.android.car.ui.R;
+import com.android.car.ui.baselayout.Insets;
+import com.android.car.ui.baselayout.InsetsChangedListener;
+import com.android.car.ui.core.CarUi;
 import com.android.car.ui.recyclerview.CarUiContentListItem;
 import com.android.car.ui.recyclerview.CarUiListItem;
 import com.android.car.ui.recyclerview.CarUiListItemAdapter;
 import com.android.car.ui.recyclerview.CarUiRecyclerView;
 import com.android.car.ui.toolbar.Toolbar;
+import com.android.car.ui.toolbar.ToolbarController;
+import com.android.car.ui.utils.CarUiUtils;
 
 import java.util.ArrayList;
 import java.util.HashSet;
@@ -45,15 +50,24 @@
  * A fragment that provides a layout with a list of options associated with a {@link
  * CarUiMultiSelectListPreference}.
  */
-public class MultiSelectListPreferenceFragment extends Fragment {
+public class MultiSelectListPreferenceFragment extends Fragment implements InsetsChangedListener {
 
     private CarUiMultiSelectListPreference mPreference;
     private Set<String> mNewValues;
+    private ToolbarController mToolbar;
+    private final Toolbar.OnBackListener mOnBackListener = () -> {
+        if (mPreference.callChangeListener(mNewValues)) {
+            mPreference.setValues(mNewValues);
+        }
+
+        return false;
+    };
 
     /**
      * Returns a new instance of {@link MultiSelectListPreferenceFragment} for the {@link
      * CarUiMultiSelectListPreference} with the given {@code key}.
      */
+    @NonNull
     static MultiSelectListPreferenceFragment newInstance(String key) {
         MultiSelectListPreferenceFragment fragment = new MultiSelectListPreferenceFragment();
         Bundle b = new Bundle(/* capacity= */ 1);
@@ -67,30 +81,41 @@
     public View onCreateView(
             @NonNull LayoutInflater inflater, @Nullable ViewGroup container,
             @Nullable Bundle savedInstanceState) {
-        return inflater.inflate(R.layout.car_ui_list_preference, container, false);
+        if (CarUi.getToolbar(getActivity()) == null) {
+            return inflater.inflate(R.layout.car_ui_list_preference_with_toolbar, container, false);
+        } else {
+            return inflater.inflate(R.layout.car_ui_list_preference, container, false);
+        }
     }
 
     @Override
     public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
         super.onViewCreated(view, savedInstanceState);
-        final CarUiRecyclerView recyclerView = view.requireViewById(R.id.list);
-        final Toolbar toolbar = view.requireViewById(R.id.toolbar);
+        final CarUiRecyclerView recyclerView = CarUiUtils.requireViewByRefId(view, R.id.list);
+        mToolbar = CarUi.getToolbar(requireActivity());
 
-        recyclerView.setPadding(0, toolbar.getHeight(), 0, 0);
-        toolbar.registerToolbarHeightChangeListener(newHeight -> {
-            if (recyclerView.getPaddingTop() == newHeight) {
-                return;
-            }
+        // TODO(b/150230923) remove the code for the old toolbar height change when apps are ready
+        if (mToolbar == null) {
+            Toolbar toolbarView = CarUiUtils.requireViewByRefId(view, R.id.toolbar);
+            mToolbar = toolbarView;
 
-            int oldHeight = recyclerView.getPaddingTop();
-            recyclerView.setPadding(0, newHeight, 0, 0);
-            recyclerView.scrollBy(0, oldHeight - newHeight);
-        });
+            recyclerView.setPadding(0, toolbarView.getHeight(), 0, 0);
+            toolbarView.registerToolbarHeightChangeListener(newHeight -> {
+                if (recyclerView.getPaddingTop() == newHeight) {
+                    return;
+                }
+
+                int oldHeight = recyclerView.getPaddingTop();
+                recyclerView.setPadding(0, newHeight, 0, 0);
+                recyclerView.scrollBy(0, oldHeight - newHeight);
+            });
+        }
 
         mPreference = getPreference();
 
         recyclerView.setClipToPadding(false);
-        toolbar.setTitle(mPreference.getTitle());
+        mToolbar.setTitle(mPreference.getTitle());
+        mToolbar.setState(Toolbar.State.SUBPAGE);
 
         mNewValues = new HashSet<>(mPreference.getValues());
         CharSequence[] entries = mPreference.getEntries();
@@ -131,14 +156,22 @@
 
         CarUiListItemAdapter adapter = new CarUiListItemAdapter(listItems);
         recyclerView.setAdapter(adapter);
+    }
 
-        toolbar.registerOnBackListener(() -> {
-            if (mPreference.callChangeListener(mNewValues)) {
-                mPreference.setValues(mNewValues);
-            }
+    @Override
+    public void onStart() {
+        super.onStart();
+        mToolbar.registerOnBackListener(mOnBackListener);
+        Insets insets = CarUi.getInsets(getActivity());
+        if (insets != null) {
+            onCarUiInsetsChanged(insets);
+        }
+    }
 
-            return false;
-        });
+    @Override
+    public void onStop() {
+        super.onStop();
+        mToolbar.unregisterOnBackListener(mOnBackListener);
     }
 
     private CarUiMultiSelectListPreference getPreference() {
@@ -171,4 +204,12 @@
 
         return (CarUiMultiSelectListPreference) preference;
     }
+
+    @Override
+    public void onCarUiInsetsChanged(@NonNull Insets insets) {
+        View view = requireView();
+        CarUiUtils.requireViewByRefId(view, R.id.list)
+                .setPadding(0, insets.getTop(), 0, insets.getBottom());
+        view.setPadding(insets.getLeft(), 0, insets.getRight(), 0);
+    }
 }
diff --git a/car-ui-lib/src/com/android/car/ui/preference/PreferenceDialogFragment.java b/car-ui-lib/src/com/android/car/ui/preference/PreferenceDialogFragment.java
index 8b2e79e..bd2a113 100644
--- a/car-ui-lib/src/com/android/car/ui/preference/PreferenceDialogFragment.java
+++ b/car-ui-lib/src/com/android/car/ui/preference/PreferenceDialogFragment.java
@@ -24,6 +24,7 @@
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
 
+import androidx.annotation.Nullable;
 import androidx.fragment.app.Fragment;
 import androidx.preference.DialogPreference;
 import androidx.preference.PreferenceFragmentCompat;
@@ -50,7 +51,7 @@
     private DialogPreference mPreference;
 
     @Override
-    public void onCreate(Bundle savedInstanceState) {
+    public void onCreate(@Nullable Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
 
         Fragment rawFragment = getTargetFragment();
diff --git a/car-ui-lib/src/com/android/car/ui/preference/PreferenceFragment.java b/car-ui-lib/src/com/android/car/ui/preference/PreferenceFragment.java
index bff6c13..8b66b8e 100644
--- a/car-ui-lib/src/com/android/car/ui/preference/PreferenceFragment.java
+++ b/car-ui-lib/src/com/android/car/ui/preference/PreferenceFragment.java
@@ -36,6 +36,7 @@
 import androidx.preference.PreferenceFragmentCompat;
 import androidx.preference.PreferenceGroup;
 import androidx.preference.PreferenceScreen;
+import androidx.preference.SwitchPreference;
 import androidx.recyclerview.widget.RecyclerView;
 
 import com.android.car.ui.R;
@@ -82,8 +83,8 @@
         }
 
         // TODO(b/150230923) remove the code for the old toolbar height change when apps are ready
-        final RecyclerView recyclerView = view.findViewById(R.id.recycler_view);
-        final Toolbar toolbar = view.findViewById(R.id.toolbar);
+        final RecyclerView recyclerView = CarUiUtils.findViewByRefId(view, R.id.recycler_view);
+        final Toolbar toolbar = CarUiUtils.findViewByRefId(view, R.id.toolbar);
         if (recyclerView == null || toolbar == null) {
             return;
         }
@@ -106,12 +107,20 @@
     }
 
     @Override
-    public void onCarUiInsetsChanged(Insets insets) {
+    public void onStart() {
+        super.onStart();
+        Insets insets = CarUi.getInsets(getActivity());
+        if (insets != null) {
+            onCarUiInsetsChanged(insets);
+        }
+    }
+
+    @Override
+    public void onCarUiInsetsChanged(@NonNull Insets insets) {
         View view = requireView();
-        view.requireViewById(R.id.recycler_view)
+        CarUiUtils.requireViewByRefId(view, R.id.recycler_view)
                 .setPadding(0, insets.getTop(), 0, insets.getBottom());
-        view.getRootView().requireViewById(android.R.id.content)
-                .setPadding(insets.getLeft(), 0, insets.getRight(), 0);
+        view.setPadding(insets.getLeft(), 0, insets.getRight(), 0);
     }
 
     /**
@@ -145,6 +154,8 @@
             f = ListPreferenceFragment.newInstance(preference.getKey());
         } else if (preference instanceof MultiSelectListPreference) {
             f = MultiSelectListPreferenceFragment.newInstance(preference.getKey());
+        } else if (preference instanceof CarUiSeekBarDialogPreference) {
+            f = SeekbarPreferenceDialogFragment.newInstance(preference.getKey());
         } else {
             throw new IllegalArgumentException(
                     "Cannot display dialog for an unknown Preference type: "
@@ -241,6 +252,7 @@
             new Pair<>(ListPreference.class, CarUiListPreference.class),
             new Pair<>(MultiSelectListPreference.class, CarUiMultiSelectListPreference.class),
             new Pair<>(EditTextPreference.class, CarUiEditTextPreference.class),
+            new Pair<>(SwitchPreference.class, CarUiSwitchPreference.class),
             new Pair<>(Preference.class, CarUiPreference.class)
     );
 
diff --git a/car-ui-lib/src/com/android/car/ui/preference/SeekbarPreferenceDialogFragment.java b/car-ui-lib/src/com/android/car/ui/preference/SeekbarPreferenceDialogFragment.java
new file mode 100644
index 0000000..57d2e75
--- /dev/null
+++ b/car-ui-lib/src/com/android/car/ui/preference/SeekbarPreferenceDialogFragment.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.car.ui.preference;
+
+import android.app.AlertDialog;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.view.View;
+
+import androidx.annotation.NonNull;
+
+/**
+ * A fragment that provides a layout with a seekbar within a dialog.
+ */
+public class SeekbarPreferenceDialogFragment extends PreferenceDialogFragment {
+
+    /**
+     * Returns a new instance of {@link SeekbarPreferenceDialogFragment} for the {@link
+     * CarUiSeekBarDialogPreference} with the given {@code key}.
+     */
+    public static SeekbarPreferenceDialogFragment newInstance(String key) {
+        SeekbarPreferenceDialogFragment fragment = new SeekbarPreferenceDialogFragment();
+        Bundle b = new Bundle(/* capacity= */ 1);
+        b.putString(ARG_KEY, key);
+        fragment.setArguments(b);
+        return fragment;
+    }
+
+    @Override
+    protected void onBindDialogView(@NonNull View view) {
+        super.onBindDialogView(view);
+
+        DialogFragmentCallbacks dialogPreference = (DialogFragmentCallbacks) getPreference();
+        dialogPreference.onBindDialogView(view);
+    }
+
+    @Override
+    public void onClick(DialogInterface dialog, int which) {
+        super.onClick(dialog, which);
+
+        DialogFragmentCallbacks dialogPreference = (DialogFragmentCallbacks) getPreference();
+        dialogPreference.onClick(dialog, which);
+    }
+
+    @Override
+    protected void onDialogClosed(boolean positiveResult) {
+        DialogFragmentCallbacks dialogPreference = (DialogFragmentCallbacks) getPreference();
+        dialogPreference.onDialogClosed(positiveResult);
+    }
+
+    @Override
+    protected void onPrepareDialogBuilder(@NonNull AlertDialog.Builder builder) {
+        DialogFragmentCallbacks dialogPreference = (DialogFragmentCallbacks) getPreference();
+        dialogPreference.onPrepareDialogBuilder(builder);
+    }
+}
diff --git a/car-ui-lib/src/com/android/car/ui/recyclerview/CarUiContentListItem.java b/car-ui-lib/src/com/android/car/ui/recyclerview/CarUiContentListItem.java
index 3fbe006..71f5d1a 100644
--- a/car-ui-lib/src/com/android/car/ui/recyclerview/CarUiContentListItem.java
+++ b/car-ui-lib/src/com/android/car/ui/recyclerview/CarUiContentListItem.java
@@ -93,7 +93,12 @@
         /**
          * For an action value of ICON, an icon is shown for the action element of the list item.
          */
-        ICON
+        ICON,
+        /**
+         * For an action value CHEVRON, a chevron is shown for the action element of the list
+         * item.
+         */
+        CHEVRON
     }
 
     private Drawable mIcon;
@@ -101,7 +106,7 @@
     private Drawable mSupplementalIcon;
     private CharSequence mTitle;
     private CharSequence mBody;
-    private Action mAction;
+    private final Action mAction;
     private IconType mPrimaryIconType;
     private boolean mIsActionDividerVisible;
     private boolean mIsChecked;
diff --git a/car-ui-lib/src/com/android/car/ui/recyclerview/CarUiHeaderListItem.java b/car-ui-lib/src/com/android/car/ui/recyclerview/CarUiHeaderListItem.java
index 57fd755..81dfa19 100644
--- a/car-ui-lib/src/com/android/car/ui/recyclerview/CarUiHeaderListItem.java
+++ b/car-ui-lib/src/com/android/car/ui/recyclerview/CarUiHeaderListItem.java
@@ -23,8 +23,8 @@
  */
 public class CarUiHeaderListItem extends CarUiListItem {
 
-    private CharSequence mTitle;
-    private CharSequence mBody;
+    private final CharSequence mTitle;
+    private final CharSequence mBody;
 
     public CarUiHeaderListItem(@NonNull CharSequence title) {
         this(title, "");
diff --git a/car-ui-lib/src/com/android/car/ui/recyclerview/CarUiListItemAdapter.java b/car-ui-lib/src/com/android/car/ui/recyclerview/CarUiListItemAdapter.java
index 65a6d40..eac856a 100644
--- a/car-ui-lib/src/com/android/car/ui/recyclerview/CarUiListItemAdapter.java
+++ b/car-ui-lib/src/com/android/car/ui/recyclerview/CarUiListItemAdapter.java
@@ -16,7 +16,7 @@
 
 package com.android.car.ui.recyclerview;
 
-import static com.android.car.ui.utils.CarUiUtils.findViewByRefId;
+import static com.android.car.ui.utils.CarUiUtils.requireViewByRefId;
 
 import android.graphics.drawable.Drawable;
 import android.text.TextUtils;
@@ -52,7 +52,7 @@
     static final int VIEW_TYPE_LIST_ITEM = 1;
     static final int VIEW_TYPE_LIST_HEADER = 2;
 
-    private List<? extends CarUiListItem> mItems;
+    private final List<? extends CarUiListItem> mItems;
     private int mMaxItems = CarUiRecyclerView.ItemCap.UNLIMITED;
 
     public CarUiListItemAdapter(List<? extends CarUiListItem> items) {
@@ -110,7 +110,7 @@
                 CarUiListItem item = mItems.get(position);
                 if (!(item instanceof CarUiContentListItem)) {
                     throw new IllegalStateException(
-                            "Expected item to be bound to viewholder to be instance of "
+                            "Expected item to be bound to viewHolder to be instance of "
                                     + "CarUiContentListItem.");
                 }
 
@@ -124,7 +124,7 @@
                 CarUiListItem header = mItems.get(position);
                 if (!(header instanceof CarUiHeaderListItem)) {
                     throw new IllegalStateException(
-                            "Expected item to be bound to viewholder to be instance of "
+                            "Expected item to be bound to viewHolder to be instance of "
                                     + "CarUiHeaderListItem.");
                 }
 
@@ -170,21 +170,21 @@
 
         ListItemViewHolder(@NonNull View itemView) {
             super(itemView);
-            mTitle = findViewByRefId(itemView, R.id.title);
-            mBody = findViewByRefId(itemView, R.id.body);
-            mIcon = findViewByRefId(itemView, R.id.icon);
-            mContentIcon = findViewByRefId(itemView, R.id.content_icon);
-            mAvatarIcon = findViewByRefId(itemView, R.id.avatar_icon);
-            mIconContainer = findViewByRefId(itemView, R.id.icon_container);
-            mActionContainer = findViewByRefId(itemView, R.id.action_container);
-            mActionDivider = findViewByRefId(itemView, R.id.action_divider);
-            mSwitch = findViewByRefId(itemView, R.id.switch_widget);
-            mCheckBox = findViewByRefId(itemView, R.id.checkbox_widget);
-            mRadioButton = findViewByRefId(itemView, R.id.radio_button_widget);
-            mSupplementalIcon = findViewByRefId(itemView, R.id.supplemental_icon);
-            mReducedTouchInterceptor = findViewByRefId(itemView, R.id.reduced_touch_interceptor);
-            mTouchInterceptor = findViewByRefId(itemView, R.id.touch_interceptor);
-            mActionContainerTouchInterceptor = findViewByRefId(itemView,
+            mTitle = requireViewByRefId(itemView, R.id.title);
+            mBody = requireViewByRefId(itemView, R.id.body);
+            mIcon = requireViewByRefId(itemView, R.id.icon);
+            mContentIcon = requireViewByRefId(itemView, R.id.content_icon);
+            mAvatarIcon = requireViewByRefId(itemView, R.id.avatar_icon);
+            mIconContainer = requireViewByRefId(itemView, R.id.icon_container);
+            mActionContainer = requireViewByRefId(itemView, R.id.action_container);
+            mActionDivider = requireViewByRefId(itemView, R.id.action_divider);
+            mSwitch = requireViewByRefId(itemView, R.id.switch_widget);
+            mCheckBox = requireViewByRefId(itemView, R.id.checkbox_widget);
+            mRadioButton = requireViewByRefId(itemView, R.id.radio_button_widget);
+            mSupplementalIcon = requireViewByRefId(itemView, R.id.supplemental_icon);
+            mReducedTouchInterceptor = requireViewByRefId(itemView, R.id.reduced_touch_interceptor);
+            mTouchInterceptor = requireViewByRefId(itemView, R.id.touch_interceptor);
+            mActionContainerTouchInterceptor = requireViewByRefId(itemView,
                     R.id.action_container_touch_interceptor);
         }
 
@@ -266,19 +266,24 @@
                 case RADIO_BUTTON:
                     bindCompoundButton(item, mRadioButton, itemOnClickListener);
                     break;
+                case CHEVRON:
+                    mSupplementalIcon.setVisibility(View.VISIBLE);
+                    mSupplementalIcon.setImageDrawable(itemView.getContext().getDrawable(
+                            R.drawable.car_ui_preference_icon_chevron));
+                    mActionContainer.setVisibility(View.VISIBLE);
+                    mTouchInterceptor.setVisibility(View.VISIBLE);
+                    mTouchInterceptor.setOnClickListener(v -> {
+                        if (itemOnClickListener != null) {
+                            itemOnClickListener.onClick(item);
+                        }
+                    });
+                    mReducedTouchInterceptor.setVisibility(View.GONE);
+                    mActionContainerTouchInterceptor.setVisibility(View.GONE);
+                    break;
                 case ICON:
                     mSupplementalIcon.setVisibility(View.VISIBLE);
                     mSupplementalIcon.setImageDrawable(item.getSupplementalIcon());
                     mActionContainer.setVisibility(View.VISIBLE);
-                    mActionContainerTouchInterceptor.setOnClickListener(
-                            (container) -> {
-                                if (item.getSupplementalIconOnClickListener() != null) {
-                                    item.getSupplementalIconOnClickListener().onClick(mIcon);
-                                }
-                                if (itemOnClickListener != null) {
-                                    itemOnClickListener.onClick(item);
-                                }
-                            });
 
                     // If the icon has a click listener, use a reduced touch interceptor to create
                     // two distinct touch area; the action container and the remainder of the list
@@ -301,6 +306,15 @@
                             }
                         });
                         mActionContainerTouchInterceptor.setVisibility(View.VISIBLE);
+                        mActionContainerTouchInterceptor.setOnClickListener(
+                                (container) -> {
+                                    if (item.getSupplementalIconOnClickListener() != null) {
+                                        item.getSupplementalIconOnClickListener().onClick(mIcon);
+                                    }
+                                    if (itemOnClickListener != null) {
+                                        itemOnClickListener.onClick(item);
+                                    }
+                                });
                         mTouchInterceptor.setVisibility(View.GONE);
                     }
                     break;
@@ -359,8 +373,8 @@
 
         HeaderViewHolder(@NonNull View itemView) {
             super(itemView);
-            mTitle = findViewByRefId(itemView, R.id.title);
-            mBody = findViewByRefId(itemView, R.id.body);
+            mTitle = requireViewByRefId(itemView, R.id.title);
+            mBody = requireViewByRefId(itemView, R.id.body);
         }
 
         private void bind(@NonNull CarUiHeaderListItem item) {
diff --git a/car-ui-lib/src/com/android/car/ui/recyclerview/CarUiRadioButtonListItemAdapter.java b/car-ui-lib/src/com/android/car/ui/recyclerview/CarUiRadioButtonListItemAdapter.java
index ed248c1..9485678 100644
--- a/car-ui-lib/src/com/android/car/ui/recyclerview/CarUiRadioButtonListItemAdapter.java
+++ b/car-ui-lib/src/com/android/car/ui/recyclerview/CarUiRadioButtonListItemAdapter.java
@@ -78,7 +78,7 @@
             CarUiListItem item = getItems().get(position);
             if (!(item instanceof CarUiRadioButtonListItem)) {
                 throw new IllegalStateException(
-                        "Expected item to be bound to viewholder to be instance of "
+                        "Expected item to be bound to viewHolder to be instance of "
                                 + "CarUiRadioButtonListItem.");
             }
 
diff --git a/car-ui-lib/src/com/android/car/ui/recyclerview/CarUiRecyclerView.java b/car-ui-lib/src/com/android/car/ui/recyclerview/CarUiRecyclerView.java
index dec9080..8f2cb7d 100644
--- a/car-ui-lib/src/com/android/car/ui/recyclerview/CarUiRecyclerView.java
+++ b/car-ui-lib/src/com/android/car/ui/recyclerview/CarUiRecyclerView.java
@@ -15,17 +15,25 @@
  */
 package com.android.car.ui.recyclerview;
 
-import static com.android.car.ui.utils.CarUiUtils.requireViewByRefId;
+import static com.android.car.ui.utils.CarUiUtils.findViewByRefId;
+import static com.android.car.ui.utils.RotaryConstants.ROTARY_HORIZONTALLY_SCROLLABLE;
+import static com.android.car.ui.utils.RotaryConstants.ROTARY_VERTICALLY_SCROLLABLE;
 
 import static java.lang.annotation.RetentionPolicy.SOURCE;
 
 import android.car.drivingstate.CarUxRestrictions;
 import android.content.Context;
 import android.content.res.TypedArray;
+import android.graphics.Rect;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Parcelable;
 import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.util.Log;
+import android.view.InputDevice;
 import android.view.LayoutInflater;
+import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.FrameLayout;
@@ -48,6 +56,7 @@
 import com.android.car.ui.utils.CarUxRestrictionsUtil;
 
 import java.lang.annotation.Retention;
+import java.util.Objects;
 
 /**
  * View that extends a {@link RecyclerView} and wraps itself into a {@link LinearLayout} which
@@ -59,27 +68,39 @@
 
     private static final String TAG = "CarUiRecyclerView";
 
-    private final UxRestrictionChangedListener mListener = new UxRestrictionChangedListener();
+    private final CarUxRestrictionsUtil.OnUxRestrictionsChangedListener mListener =
+            new UxRestrictionChangedListener();
 
-    private CarUxRestrictionsUtil mCarUxRestrictionsUtil;
+    @NonNull
+    private final CarUxRestrictionsUtil mCarUxRestrictionsUtil;
     private boolean mScrollBarEnabled;
+    @Nullable
     private String mScrollBarClass;
-    private boolean mFullyInitialized;
-    private float mScrollBarPaddingStart;
-    private float mScrollBarPaddingEnd;
+    private int mScrollBarPaddingTop;
+    private int mScrollBarPaddingBottom;
+    private boolean mHasScrolledToTop = false;
 
+    @Nullable
     private ScrollBar mScrollBar;
     private int mInitialTopPadding;
 
+    @Nullable
     private GridOffsetItemDecoration mOffsetItemDecoration;
-    private GridDividerItemDecoration mDividerItemDecoration;
-    @CarUiRecyclerViewLayout
-    private int mCarUiRecyclerViewLayout;
+    @NonNull
+    private GridDividerItemDecoration mDividerItemDecorationGrid;
+    @NonNull
+    private RecyclerView.ItemDecoration mDividerItemDecorationLinear;
     private int mNumOfColumns;
     private boolean mInstallingExtScrollBar = false;
     private int mContainerVisibility = View.VISIBLE;
+    @Nullable
+    private Rect mContainerPadding;
+    @Nullable
+    private Rect mContainerPaddingRelative;
+    @Nullable
     private LinearLayout mContainer;
 
+
     /**
      * The possible values for setScrollBarPosition. The default value is actually {@link
      * CarUiRecyclerViewLayout#LINEAR}.
@@ -141,11 +162,13 @@
     public CarUiRecyclerView(@NonNull Context context, @Nullable AttributeSet attrs,
             int defStyle) {
         super(context, attrs, defStyle);
+        mCarUxRestrictionsUtil = CarUxRestrictionsUtil.getInstance(context);
         init(context, attrs, defStyle);
     }
 
     private void init(Context context, AttributeSet attrs, int defStyleAttr) {
-        mCarUxRestrictionsUtil = CarUxRestrictionsUtil.getInstance(context);
+        initRotaryScroll(context, attrs, defStyleAttr);
+        setClipToPadding(false);
         TypedArray a = context.obtainStyledAttributes(
                 attrs,
                 R.styleable.CarUiRecyclerView,
@@ -153,62 +176,56 @@
                 R.style.Widget_CarUi_CarUiRecyclerView);
 
         mScrollBarEnabled = context.getResources().getBoolean(R.bool.car_ui_scrollbar_enable);
-        mFullyInitialized = false;
 
-        mScrollBarPaddingStart =
-                context.getResources().getDimension(R.dimen.car_ui_scrollbar_padding_start);
-        mScrollBarPaddingEnd =
-                context.getResources().getDimension(R.dimen.car_ui_scrollbar_padding_end);
+        mScrollBarPaddingTop = context.getResources()
+                .getDimensionPixelSize(R.dimen.car_ui_scrollbar_padding_top);
+        mScrollBarPaddingBottom = context.getResources()
+                .getDimensionPixelSize(R.dimen.car_ui_scrollbar_padding_bottom);
 
-        mCarUiRecyclerViewLayout =
+        @CarUiRecyclerViewLayout int carUiRecyclerViewLayout =
                 a.getInt(R.styleable.CarUiRecyclerView_layoutStyle, CarUiRecyclerViewLayout.LINEAR);
         mNumOfColumns = a.getInt(R.styleable.CarUiRecyclerView_numOfColumns, /* defValue= */ 2);
         boolean enableDivider =
                 a.getBoolean(R.styleable.CarUiRecyclerView_enableDivider, /* defValue= */ false);
 
-        if (mCarUiRecyclerViewLayout == CarUiRecyclerViewLayout.LINEAR) {
+        mDividerItemDecorationLinear = new LinearDividerItemDecoration(
+                context.getDrawable(R.drawable.car_ui_recyclerview_divider));
 
-            int linearTopOffset =
-                    a.getInteger(R.styleable.CarUiRecyclerView_startOffset, /* defValue= */ 0);
-            int linearBottomOffset =
-                    a.getInteger(R.styleable.CarUiRecyclerView_endOffset, /* defValue= */ 0);
+        mDividerItemDecorationGrid =
+                new GridDividerItemDecoration(
+                        context.getDrawable(R.drawable.car_ui_divider),
+                        context.getDrawable(R.drawable.car_ui_divider),
+                        mNumOfColumns);
+
+        int topOffset = a.getInteger(R.styleable.CarUiRecyclerView_topOffset, /* defValue= */0);
+        int bottomOffset = a.getInteger(
+                R.styleable.CarUiRecyclerView_bottomOffset, /* defValue= */0);
+        if (carUiRecyclerViewLayout == CarUiRecyclerViewLayout.LINEAR) {
 
             if (enableDivider) {
-                RecyclerView.ItemDecoration dividerItemDecoration =
-                        new LinearDividerItemDecoration(
-                                context.getDrawable(R.drawable.car_ui_recyclerview_divider));
-                addItemDecoration(dividerItemDecoration);
+                addItemDecoration(mDividerItemDecorationLinear);
             }
             RecyclerView.ItemDecoration topOffsetItemDecoration =
-                    new LinearOffsetItemDecoration(linearTopOffset, OffsetPosition.START);
+                    new LinearOffsetItemDecoration(topOffset, OffsetPosition.START);
 
             RecyclerView.ItemDecoration bottomOffsetItemDecoration =
-                    new LinearOffsetItemDecoration(linearBottomOffset, OffsetPosition.END);
+                    new LinearOffsetItemDecoration(bottomOffset, OffsetPosition.END);
 
             addItemDecoration(topOffsetItemDecoration);
             addItemDecoration(bottomOffsetItemDecoration);
             setLayoutManager(new LinearLayoutManager(getContext()));
         } else {
-            int gridTopOffset =
-                    a.getInteger(R.styleable.CarUiRecyclerView_startOffset, /* defValue= */ 0);
-            int gridBottomOffset =
-                    a.getInteger(R.styleable.CarUiRecyclerView_endOffset, /* defValue= */ 0);
 
             if (enableDivider) {
-                mDividerItemDecoration =
-                        new GridDividerItemDecoration(
-                                context.getDrawable(R.drawable.car_ui_divider),
-                                context.getDrawable(R.drawable.car_ui_divider),
-                                mNumOfColumns);
-                addItemDecoration(mDividerItemDecoration);
+                addItemDecoration(mDividerItemDecorationGrid);
             }
 
             mOffsetItemDecoration =
-                    new GridOffsetItemDecoration(gridTopOffset, mNumOfColumns,
+                    new GridOffsetItemDecoration(topOffset, mNumOfColumns,
                             OffsetPosition.START);
 
             GridOffsetItemDecoration bottomOffsetItemDecoration =
-                    new GridOffsetItemDecoration(gridBottomOffset, mNumOfColumns,
+                    new GridOffsetItemDecoration(bottomOffset, mNumOfColumns,
                             OffsetPosition.END);
 
             addItemDecoration(mOffsetItemDecoration);
@@ -217,23 +234,96 @@
             setNumOfColumns(mNumOfColumns);
         }
 
+        a.recycle();
         if (!mScrollBarEnabled) {
-            a.recycle();
-            mFullyInitialized = true;
             return;
         }
 
+        setVerticalScrollBarEnabled(false);
+        setHorizontalScrollBarEnabled(false);
+
         mScrollBarClass = context.getResources().getString(R.string.car_ui_scrollbar_component);
-        a.recycle();
         this.getViewTreeObserver()
                 .addOnGlobalLayoutListener(() -> {
+                    if (!mHasScrolledToTop && getLayoutManager() != null) {
+                        // Scroll to the top after the first global layout, so that
+                        // we can set padding for the insets and still have the
+                        // recyclerview start at the top.
+                        new Handler(Objects.requireNonNull(Looper.myLooper())).post(() ->
+                                getLayoutManager().scrollToPosition(0));
+                        mHasScrolledToTop = true;
+                    }
+
                     if (mInitialTopPadding == 0) {
                         mInitialTopPadding = getPaddingTop();
                     }
-                    mFullyInitialized = true;
                 });
     }
 
+    /**
+     * If this view's content description isn't set to opt out of scrolling via the rotary
+     * controller, initialize it accordingly.
+     */
+    private void initRotaryScroll(Context context, AttributeSet attrs, int defStyleAttr) {
+        CharSequence contentDescription = getContentDescription();
+        if (contentDescription == null) {
+            TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.RecyclerView,
+                    defStyleAttr, /* defStyleRes= */ 0);
+            int orientation = a.getInt(R.styleable.RecyclerView_android_orientation,
+                    LinearLayout.VERTICAL);
+            setContentDescription(
+                    orientation == LinearLayout.HORIZONTAL
+                            ? ROTARY_HORIZONTALLY_SCROLLABLE
+                            : ROTARY_VERTICALLY_SCROLLABLE);
+        } else if (!ROTARY_HORIZONTALLY_SCROLLABLE.contentEquals(contentDescription)
+                && !ROTARY_VERTICALLY_SCROLLABLE.contentEquals(contentDescription)) {
+            return;
+        }
+
+        // Convert SOURCE_ROTARY_ENCODER scroll events into SOURCE_MOUSE scroll events that
+        // RecyclerView knows how to handle.
+        setOnGenericMotionListener((v, event) -> {
+            if (event.getAction() == MotionEvent.ACTION_SCROLL) {
+                if (event.getSource() == InputDevice.SOURCE_ROTARY_ENCODER) {
+                    MotionEvent mouseEvent = MotionEvent.obtain(event);
+                    mouseEvent.setSource(InputDevice.SOURCE_MOUSE);
+                    CarUiRecyclerView.super.onGenericMotionEvent(mouseEvent);
+                    return true;
+                }
+            }
+            return false;
+        });
+
+        // Mark this view as focusable. This view will be focused when no focusable elements are
+        // visible.
+        setFocusable(true);
+
+        // Focus this view before descendants so that the RotaryService can focus this view when it
+        // wants to.
+        setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);
+
+        // Disable the default focus highlight. No highlight should appear when this view is
+        // focused.
+        setDefaultFocusHighlightEnabled(false);
+    }
+
+    @Override
+    protected void onRestoreInstanceState(Parcelable state) {
+        super.onRestoreInstanceState(state);
+
+        // If we're restoring an existing RecyclerView, we don't want
+        // to do the initial scroll to top
+        mHasScrolledToTop = true;
+    }
+
+    @Override
+    public void requestLayout() {
+        super.requestLayout();
+        if (mScrollBar != null) {
+            mScrollBar.requestLayout();
+        }
+    }
+
     @Override
     public void onHeightChanged(int height) {
         setPaddingRelative(getPaddingStart(), mInitialTopPadding + height,
@@ -241,15 +331,6 @@
     }
 
     /**
-     * Returns {@code true} if the {@link CarUiRecyclerView} is fully drawn. Using a global layout
-     * mListener may not necessarily signify that this view is fully drawn (i.e. when the scrollbar
-     * is enabled).
-     */
-    public boolean fullyInitialized() {
-        return mFullyInitialized;
-    }
-
-    /**
      * Sets the number of columns in which grid needs to be divided.
      */
     public void setNumOfColumns(int numberOfColumns) {
@@ -257,8 +338,8 @@
         if (mOffsetItemDecoration != null) {
             mOffsetItemDecoration.setNumOfColumns(mNumOfColumns);
         }
-        if (mDividerItemDecoration != null) {
-            mDividerItemDecoration.setNumOfColumns(mNumOfColumns);
+        if (mDividerItemDecorationGrid != null) {
+            mDividerItemDecorationGrid.setNumOfColumns(mNumOfColumns);
         }
     }
 
@@ -294,25 +375,38 @@
      * parent where the recycler view was set with the same layout params.
      */
     private void installExternalScrollBar() {
-        ViewGroup parent = (ViewGroup) getParent();
         mContainer = new LinearLayout(getContext());
         LayoutInflater inflater = LayoutInflater.from(getContext());
         inflater.inflate(R.layout.car_ui_recycler_view, mContainer, true);
+        mContainer.setVisibility(mContainerVisibility);
+
+        if (mContainerPadding != null) {
+            mContainer.setPadding(mContainerPadding.left, mContainerPadding.top,
+                    mContainerPadding.right, mContainerPadding.bottom);
+        } else if (mContainerPaddingRelative != null) {
+            mContainer.setPaddingRelative(mContainerPaddingRelative.left,
+                    mContainerPaddingRelative.top, mContainerPaddingRelative.right,
+                    mContainerPaddingRelative.bottom);
+        } else {
+            mContainer.setPadding(getPaddingLeft(), /* top= */ 0,
+                    getPaddingRight(), /* bottom= */ 0);
+            setPadding(/* left= */ 0, getPaddingTop(),
+                    /* right= */ 0, getPaddingBottom());
+        }
 
         mContainer.setLayoutParams(getLayoutParams());
-        mContainer.setVisibility(mContainerVisibility);
+        ViewGroup parent = (ViewGroup) getParent();
         int index = parent.indexOfChild(this);
-        parent.removeView(this);
-        ((FrameLayout) requireViewByRefId(mContainer, R.id.car_ui_recycler_view))
-                .addView(this,
-                        new FrameLayout.LayoutParams(
-                                ViewGroup.LayoutParams.MATCH_PARENT,
-                                ViewGroup.LayoutParams.MATCH_PARENT));
-        setVerticalScrollBarEnabled(false);
-        setHorizontalScrollBarEnabled(false);
+        parent.removeViewInLayout(this);
+
+        FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
+                ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
+        ((CarUiRecyclerViewContainer) Objects.requireNonNull(
+                findViewByRefId(mContainer, R.id.car_ui_recycler_view)))
+                .addRecyclerView(this, params);
         parent.addView(mContainer, index);
 
-        createScrollBarFromConfig(requireViewByRefId(mContainer, R.id.car_ui_scroll_bar));
+        createScrollBarFromConfig(findViewByRefId(mContainer, R.id.car_ui_scroll_bar));
     }
 
     private void createScrollBarFromConfig(View scrollView) {
@@ -332,7 +426,7 @@
 
         mScrollBar.initialize(this, scrollView);
 
-        mScrollBar.setPadding((int) mScrollBarPaddingStart, (int) mScrollBarPaddingEnd);
+        setScrollBarPadding(mScrollBarPaddingTop, mScrollBarPaddingBottom);
     }
 
     @Override
@@ -341,28 +435,72 @@
         mCarUxRestrictionsUtil.unregister(mListener);
     }
 
-    /**
-     * Sets the scrollbar's padding start (top) and end (bottom).
-     * This padding is applied in addition to the padding of the inner RecyclerView.
-     */
-    public void setScrollBarPadding(int paddingStart, int paddingEnd) {
+    @Override
+    public void setPadding(int left, int top, int right, int bottom) {
+        mContainerPaddingRelative = null;
         if (mScrollBarEnabled) {
-            mScrollBarPaddingStart = paddingStart;
-            mScrollBarPaddingEnd = paddingEnd;
+            super.setPadding(0, top, 0, bottom);
+            mContainerPadding = new Rect(left, 0, right, 0);
+            if (mContainer != null) {
+                mContainer.setPadding(left, 0, right, 0);
+            }
+            setScrollBarPadding(mScrollBarPaddingTop, mScrollBarPaddingBottom);
+        } else {
+            super.setPadding(left, top, right, bottom);
+        }
+    }
+
+    @Override
+    public void setPaddingRelative(int start, int top, int end, int bottom) {
+        mContainerPadding = null;
+        if (mScrollBarEnabled) {
+            super.setPaddingRelative(0, top, 0, bottom);
+            mContainerPaddingRelative = new Rect(start, 0, end, 0);
+            if (mContainer != null) {
+                mContainer.setPaddingRelative(start, 0, end, 0);
+            }
+            setScrollBarPadding(mScrollBarPaddingTop, mScrollBarPaddingBottom);
+        } else {
+            super.setPaddingRelative(start, top, end, bottom);
+        }
+    }
+
+    /**
+     * Sets the scrollbar's padding top and bottom.
+     * This padding is applied in addition to the padding of the RecyclerView.
+     */
+    public void setScrollBarPadding(int paddingTop, int paddingBottom) {
+        if (mScrollBarEnabled) {
+            mScrollBarPaddingTop = paddingTop;
+            mScrollBarPaddingBottom = paddingBottom;
 
             if (mScrollBar != null) {
-                mScrollBar.setPadding(paddingStart, paddingEnd);
+                mScrollBar.setPadding(paddingTop + getPaddingTop(),
+                        paddingBottom + getPaddingBottom());
             }
         }
     }
 
     /**
-     * @deprecated use {#getLayoutManager()}
+     * Sets divider item decoration for linear layout.
      */
-    @Nullable
-    @Deprecated
-    public LayoutManager getEffectiveLayoutManager() {
-        return super.getLayoutManager();
+    public void setLinearDividerItemDecoration(boolean enableDividers) {
+        if (enableDividers) {
+            addItemDecoration(mDividerItemDecorationLinear);
+            return;
+        }
+        removeItemDecoration(mDividerItemDecorationLinear);
+    }
+
+    /**
+     * Sets divider item decoration for grid layout.
+     */
+    public void setGridDividerItemDecoration(boolean enableDividers) {
+        if (enableDividers) {
+            addItemDecoration(mDividerItemDecorationGrid);
+            return;
+        }
+        removeItemDecoration(mDividerItemDecorationGrid);
     }
 
     private static RuntimeException andLog(String msg, Throwable t) {
diff --git a/car-ui-lib/src/com/android/car/ui/recyclerview/CarUiRecyclerViewAdapter.java b/car-ui-lib/src/com/android/car/ui/recyclerview/CarUiRecyclerViewAdapter.java
index 5b74b44..2f2a5b1 100644
--- a/car-ui-lib/src/com/android/car/ui/recyclerview/CarUiRecyclerViewAdapter.java
+++ b/car-ui-lib/src/com/android/car/ui/recyclerview/CarUiRecyclerViewAdapter.java
@@ -15,13 +15,14 @@
  */
 package com.android.car.ui.recyclerview;
 
-import static com.android.car.ui.utils.CarUiUtils.requireViewByRefId;
+import static com.android.car.ui.utils.CarUiUtils.findViewByRefId;
 
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.FrameLayout;
 
+import androidx.annotation.NonNull;
 import androidx.recyclerview.widget.RecyclerView;
 
 import com.android.car.ui.R;
@@ -42,22 +43,22 @@
     // Replace the contents of a view (invoked by the layout manager). Intentionally left empty
     // since this adapter is an empty shell for the nested recyclerview.
     @Override
-    public void onBindViewHolder(NestedRowViewHolder holder, int position) {
+    public void onBindViewHolder(@NonNull NestedRowViewHolder holder, int position) {
     }
 
-    // Return the size of your dataset (invoked by the layout manager)
+    // Return the size of your data set (invoked by the layout manager)
     @Override
     public int getItemCount() {
         return 1;
     }
 
-    /** The viewholder class for the parent recyclerview. */
+    /** The viewHolder class for the parent recyclerview. */
     static class NestedRowViewHolder extends RecyclerView.ViewHolder {
-        public FrameLayout frameLayout;
+        public final FrameLayout frameLayout;
 
         NestedRowViewHolder(View view) {
             super(view);
-            frameLayout = requireViewByRefId(view, R.id.nested_recycler_view_layout);
+            frameLayout = findViewByRefId(view, R.id.nested_recycler_view_layout);
         }
     }
 }
diff --git a/car-ui-lib/src/com/android/car/ui/recyclerview/CarUiRecyclerViewContainer.java b/car-ui-lib/src/com/android/car/ui/recyclerview/CarUiRecyclerViewContainer.java
new file mode 100644
index 0000000..4e9dc55
--- /dev/null
+++ b/car-ui-lib/src/com/android/car/ui/recyclerview/CarUiRecyclerViewContainer.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.car.ui.recyclerview;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.FrameLayout;
+
+/**
+ * Container that contains the scrollbar and RecyclerView when scrollbar is enabled.
+ *
+ * This container is required to expose addViewInLayout such that the scrollbar and be added without
+ * triggering multiple invalidate and relayout calls.
+ */
+public class CarUiRecyclerViewContainer extends FrameLayout {
+
+    public CarUiRecyclerViewContainer(Context context) {
+        super(context);
+    }
+
+    public CarUiRecyclerViewContainer(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public CarUiRecyclerViewContainer(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+    }
+
+    public CarUiRecyclerViewContainer(Context context, AttributeSet attrs, int defStyleAttr,
+            int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+    }
+
+    /**
+     * Adds the recyclerview using addViewInLayout so that invalidate and relayout calls are not
+     * triggered.
+     */
+    void addRecyclerView(View view, LayoutParams layoutParams) {
+        addViewInLayout(view, 0, layoutParams);
+    }
+}
diff --git a/car-ui-lib/src/com/android/car/ui/recyclerview/CarUiSnapHelper.java b/car-ui-lib/src/com/android/car/ui/recyclerview/CarUiSnapHelper.java
index 807d856..136dc6e 100644
--- a/car-ui-lib/src/com/android/car/ui/recyclerview/CarUiSnapHelper.java
+++ b/car-ui-lib/src/com/android/car/ui/recyclerview/CarUiSnapHelper.java
@@ -16,7 +16,6 @@
 package com.android.car.ui.recyclerview;
 
 import android.content.Context;
-import android.graphics.PointF;
 import android.view.View;
 
 import androidx.annotation.NonNull;
@@ -26,6 +25,8 @@
 import androidx.recyclerview.widget.RecyclerView;
 import androidx.recyclerview.widget.RecyclerView.LayoutManager;
 
+import java.util.Objects;
+
 /**
  * Inspired by {@link androidx.car.widget.PagedSnapHelper}
  *
@@ -67,6 +68,12 @@
     public int[] calculateDistanceToFinalSnap(
             @NonNull LayoutManager layoutManager, @NonNull View targetView) {
         int[] out = new int[2];
+
+        // Don't snap when not in touch mode, i.e. when using rotary.
+        if (!mRecyclerView.isInTouchMode()) {
+            return out;
+        }
+
         if (layoutManager.canScrollHorizontally()) {
             out[0] = distanceToTopMargin(targetView, getHorizontalHelper(layoutManager));
         }
@@ -79,106 +86,6 @@
     }
 
     /**
-     * Smooth scrolls the RecyclerView by a given distance.
-     */
-    public void smoothScrollBy(int scrollDistance) {
-        LayoutManager layoutManager = mRecyclerView.getLayoutManager();
-        if (layoutManager == null) {
-            return;
-        }
-
-        int position = findTargetSnapPosition(layoutManager, scrollDistance);
-        if (position == RecyclerView.NO_POSITION) {
-            mRecyclerView.smoothScrollBy(0, scrollDistance);
-            return;
-        }
-
-        RecyclerView.SmoothScroller scroller = createScroller(layoutManager);
-
-        if (scroller == null) {
-            return;
-        }
-
-        scroller.setTargetPosition(position);
-        layoutManager.startSmoothScroll(scroller);
-    }
-
-    /**
-     * Finds the target position for snapping.
-     *
-     * @param layoutManager the {@link RecyclerView.LayoutManager} associated with the attached
-     *                      {@link RecyclerView}
-     */
-    private int findTargetSnapPosition(RecyclerView.LayoutManager layoutManager,
-            int scrollDistance) {
-
-        if (!(layoutManager instanceof RecyclerView.SmoothScroller.ScrollVectorProvider)) {
-            return RecyclerView.NO_POSITION;
-        }
-
-        final int itemCount = layoutManager.getItemCount();
-        if (itemCount == 0) {
-            return RecyclerView.NO_POSITION;
-        }
-
-        final View currentView = findViewIfScrollable(layoutManager);
-        if (currentView == null) {
-            return RecyclerView.NO_POSITION;
-        }
-
-        final int currentPosition = layoutManager.getPosition(currentView);
-        if (currentPosition == RecyclerView.NO_POSITION) {
-            return RecyclerView.NO_POSITION;
-        }
-
-        RecyclerView.SmoothScroller.ScrollVectorProvider vectorProvider =
-                (RecyclerView.SmoothScroller.ScrollVectorProvider) layoutManager;
-        // deltaJumps sign comes from the velocity which may not match the order of children in
-        // the LayoutManager. To overcome this, we ask for a vector from the LayoutManager to
-        // get the direction.
-        PointF vectorForEnd = vectorProvider.computeScrollVectorForPosition(itemCount - 1);
-        if (vectorForEnd == null) {
-            // cannot get a vector for the given position.
-            return RecyclerView.NO_POSITION;
-        }
-
-        int vDeltaJump;
-        int hDeltaJump;
-        if (layoutManager.canScrollHorizontally()) {
-            hDeltaJump = estimateNextPositionDiffForFling(layoutManager,
-                    getHorizontalHelper(layoutManager), scrollDistance);
-            if (vectorForEnd.x < 0) {
-                hDeltaJump = -hDeltaJump;
-            }
-        } else {
-            hDeltaJump = 0;
-        }
-        if (layoutManager.canScrollVertically()) {
-            vDeltaJump = estimateNextPositionDiffForFling(layoutManager,
-                    getVerticalHelper(layoutManager), scrollDistance);
-            if (vectorForEnd.y < 0) {
-                vDeltaJump = -vDeltaJump;
-            }
-        } else {
-            vDeltaJump = 0;
-        }
-
-        int deltaJump = layoutManager.canScrollVertically() ? vDeltaJump : hDeltaJump;
-        if (deltaJump == 0) {
-            return RecyclerView.NO_POSITION;
-        }
-
-        int targetPos = currentPosition + deltaJump;
-        if (targetPos < 0) {
-            targetPos = 0;
-        }
-        if (targetPos >= itemCount) {
-            targetPos = itemCount - 1;
-        }
-        return targetPos;
-    }
-
-    /**
      * Finds the view to snap to. The view to snap to is the child of the LayoutManager that is
      * closest to the start of the RecyclerView. The "start" depends on if the LayoutManager
      * is scrolling horizontally or vertically. If it is horizontally scrolling, then the
@@ -226,7 +133,8 @@
             return null;
         }
 
-        View lastVisibleChild = layoutManager.getChildAt(childCount - 1);
+        @NonNull View lastVisibleChild = Objects.requireNonNull(
+                layoutManager.getChildAt(childCount - 1));
 
         // Check if the last child visible is the last item in the list.
         boolean lastItemVisible =
@@ -273,15 +181,6 @@
         return isValidSnapView(childToReturn, orientationHelper) ? childToReturn : null;
     }
 
-    private View findViewIfScrollable(LayoutManager layoutManager) {
-        if (layoutManager.canScrollVertically()) {
-            return findTopView(layoutManager, getVerticalHelper(layoutManager));
-        } else if (layoutManager.canScrollHorizontally()) {
-            return findTopView(layoutManager, getHorizontalHelper(layoutManager));
-        }
-        return null;
-    }
-
     private static int distanceToTopMargin(@NonNull View targetView, OrientationHelper helper) {
         final int childTop = helper.getDecoratedStart(targetView);
         final int containerTop = helper.getStartAfterPadding();
@@ -314,7 +213,7 @@
             }
             int absDistance = Math.abs(distanceToTopMargin(child, helper));
 
-            /** if child top is closer than previous closest, set it as closest */
+            /* if child top is closer than previous closest, set it as closest */
             if (absDistance < absClosest) {
                 absClosest = absDistance;
                 closestChild = child;
@@ -335,7 +234,7 @@
      * @param helper The {@link OrientationHelper} associated with the current RecyclerView.
      * @return {@code true} if the given view is a valid snapping view; {@code false} otherwise.
      */
-    private boolean isValidSnapView(View view, OrientationHelper helper) {
+    private static boolean isValidSnapView(View view, OrientationHelper helper) {
         return helper.getDecoratedMeasurement(view) <= helper.getTotalSpace();
     }
 
@@ -347,7 +246,7 @@
      * @param helper An {@link OrientationHelper} to aid with calculation.
      * @return A float indicating the percentage of the given view that is visible.
      */
-    private float getPercentageVisible(View view, OrientationHelper helper) {
+    private static float getPercentageVisible(View view, OrientationHelper helper) {
         int start = helper.getStartAfterPadding();
         int end = helper.getEndAfterPadding();
 
@@ -419,7 +318,8 @@
         int lastChildPosition = isAtEnd(layoutManager) ? 0 : layoutManager.getChildCount() - 1;
 
         OrientationHelper orientationHelper = getOrientationHelper(layoutManager);
-        View lastChild = layoutManager.getChildAt(lastChildPosition);
+        @NonNull View lastChild = Objects.requireNonNull(
+                layoutManager.getChildAt(lastChildPosition));
         float percentageVisible = getPercentageVisible(lastChild, orientationHelper);
 
         int maxDistance = layoutManager.getHeight();
@@ -447,7 +347,7 @@
             return true;
         }
 
-        View firstChild = layoutManager.getChildAt(0);
+        @NonNull View firstChild = Objects.requireNonNull(layoutManager.getChildAt(0));
         OrientationHelper orientationHelper =
                 layoutManager.canScrollVertically() ? getVerticalHelper(layoutManager)
                         : getHorizontalHelper(layoutManager);
@@ -471,7 +371,8 @@
                 layoutManager.canScrollVertically() ? getVerticalHelper(layoutManager)
                         : getHorizontalHelper(layoutManager);
 
-        View lastVisibleChild = layoutManager.getChildAt(childCount - 1);
+        @NonNull View lastVisibleChild = Objects.requireNonNull(
+                layoutManager.getChildAt(childCount - 1));
 
         // The list has reached the bottom if the last child that is visible is the last item
         // in the list and it's fully shown.
@@ -521,58 +422,4 @@
     private static int clamp(int value, int min, int max) {
         return Math.max(min, Math.min(max, value));
     }
-
-    private static int estimateNextPositionDiffForFling(RecyclerView.LayoutManager layoutManager,
-            OrientationHelper helper,
-            int scrollDistance) {
-        int[] distances = new int[]{scrollDistance, scrollDistance};
-        float distancePerChild = computeDistancePerChild(layoutManager, helper);
-
-        if (distancePerChild <= 0) {
-            return 0;
-        }
-        int distance =
-                Math.abs(distances[0]) > Math.abs(distances[1]) ? distances[0] : distances[1];
-        return (int) Math.round(distance / distancePerChild);
-    }
-
-    private static float computeDistancePerChild(RecyclerView.LayoutManager layoutManager,
-            OrientationHelper helper) {
-        View minPosView = null;
-        View maxPosView = null;
-        int minPos = Integer.MAX_VALUE;
-        int maxPos = Integer.MIN_VALUE;
-        int childCount = layoutManager.getChildCount();
-        if (childCount == 0) {
-            return -1;
-        }
-
-        for (int i = 0; i < childCount; i++) {
-            View child = layoutManager.getChildAt(i);
-            int pos = layoutManager.getPosition(child);
-            if (pos == RecyclerView.NO_POSITION) {
-                continue;
-            }
-            if (pos < minPos) {
-                minPos = pos;
-                minPosView = child;
-            }
-            if (pos > maxPos) {
-                maxPos = pos;
-                maxPosView = child;
-            }
-        }
-        if (minPosView == null || maxPosView == null) {
-            return -1;
-        }
-        int start = Math.min(helper.getDecoratedStart(minPosView),
-                helper.getDecoratedStart(maxPosView));
-        int end = Math.max(helper.getDecoratedEnd(minPosView),
-                helper.getDecoratedEnd(maxPosView));
-        int distance = end - start;
-        if (distance == 0) {
-            return -1;
-        }
-        return 1f * distance / ((maxPos - minPos) + 1);
-    }
 }
diff --git a/car-ui-lib/src/com/android/car/ui/recyclerview/DefaultScrollBar.java b/car-ui-lib/src/com/android/car/ui/recyclerview/DefaultScrollBar.java
index 7b38504..a643f6d 100644
--- a/car-ui-lib/src/com/android/car/ui/recyclerview/DefaultScrollBar.java
+++ b/car-ui-lib/src/com/android/car/ui/recyclerview/DefaultScrollBar.java
@@ -23,10 +23,9 @@
 import android.view.ViewGroup;
 import android.view.animation.AccelerateDecelerateInterpolator;
 import android.view.animation.Interpolator;
-import android.widget.ImageView;
 
 import androidx.annotation.IntRange;
-import androidx.annotation.VisibleForTesting;
+import androidx.annotation.NonNull;
 import androidx.recyclerview.widget.OrientationHelper;
 import androidx.recyclerview.widget.RecyclerView;
 
@@ -41,29 +40,19 @@
  */
 class DefaultScrollBar implements ScrollBar {
 
-    @VisibleForTesting
-    int mPaddingStart;
-    @VisibleForTesting
-    int mPaddingEnd;
-
     private float mButtonDisabledAlpha;
     private CarUiSnapHelper mSnapHelper;
 
-    private ImageView mUpButton;
     private View mScrollView;
+    private View mScrollTrack;
     private View mScrollThumb;
-    private ImageView mDownButton;
-
-    private int mSeparatingMargin;
+    private View mUpButton;
+    private View mDownButton;
 
     private RecyclerView mRecyclerView;
 
-    /** The amount of space that the scroll thumb is allowed to roam over. */
-    private int mScrollThumbTrackHeight;
-
     private final Interpolator mPaginationInterpolator = new AccelerateDecelerateInterpolator();
 
-    private final int mRowsPerPage = -1;
     private final Handler mHandler = new Handler();
 
     private OrientationHelper mOrientationHelper;
@@ -81,24 +70,30 @@
         getRecyclerView().addOnScrollListener(mRecyclerViewOnScrollListener);
         getRecyclerView().getRecycledViewPool().setMaxRecycledViews(0, 12);
 
-        mSeparatingMargin = res.getDimensionPixelSize(R.dimen.car_ui_scrollbar_separator_margin);
+        mUpButton = requireViewByRefId(mScrollView, R.id.car_ui_scrollbar_page_up);
+        View.OnClickListener paginateUpButtonOnClickListener = v -> pageUp();
+        mUpButton.setOnClickListener(paginateUpButtonOnClickListener);
+        mUpButton.setOnTouchListener(
+                new OnContinuousScrollListener(rv.getContext(), paginateUpButtonOnClickListener));
 
-        mUpButton = requireViewByRefId(mScrollView, R.id.page_up);
-        PaginateButtonClickListener upButtonClickListener =
-                new PaginateButtonClickListener(PaginationListener.PAGE_UP);
-        mUpButton.setOnClickListener(upButtonClickListener);
+        mDownButton = requireViewByRefId(mScrollView, R.id.car_ui_scrollbar_page_down);
+        View.OnClickListener paginateDownButtonOnClickListener = v -> pageDown();
+        mDownButton.setOnClickListener(paginateDownButtonOnClickListener);
+        mDownButton.setOnTouchListener(
+                new OnContinuousScrollListener(rv.getContext(), paginateDownButtonOnClickListener));
 
-        mDownButton = requireViewByRefId(mScrollView, R.id.page_down);
-        PaginateButtonClickListener downButtonClickListener =
-                new PaginateButtonClickListener(PaginationListener.PAGE_DOWN);
-        mDownButton.setOnClickListener(downButtonClickListener);
-
-        mScrollThumb = requireViewByRefId(mScrollView, R.id.scrollbar_thumb);
+        mScrollTrack = requireViewByRefId(mScrollView, R.id.car_ui_scrollbar_track);
+        mScrollThumb = requireViewByRefId(mScrollView, R.id.car_ui_scrollbar_thumb);
 
         mSnapHelper = new CarUiSnapHelper(rv.getContext());
         getRecyclerView().setOnFlingListener(null);
         mSnapHelper.attachToRecyclerView(getRecyclerView());
 
+        // enables fast scrolling.
+        FastScroller fastScroller = new FastScroller(mRecyclerView, mScrollTrack, mScrollView);
+        fastScroller.enable();
+
+        mScrollView.setVisibility(View.INVISIBLE);
         mScrollView.addOnLayoutChangeListener(
                 (View v,
                         int left,
@@ -108,30 +103,7 @@
                         int oldLeft,
                         int oldTop,
                         int oldRight,
-                        int oldBottom) -> {
-                    int width = right - left;
-
-                    OrientationHelper orientationHelper =
-                            getOrientationHelper(getRecyclerView().getLayoutManager());
-
-                    // This value will keep track of the top of the current view being laid out.
-                    int layoutTop = orientationHelper.getStartAfterPadding() + mPaddingStart;
-
-                    // Lay out the up button at the top of the view.
-                    layoutViewCenteredFromTop(mUpButton, layoutTop, width);
-                    layoutTop = mUpButton.getBottom();
-
-                    // Lay out the scroll thumb
-                    layoutTop += mSeparatingMargin;
-                    layoutViewCenteredFromTop(mScrollThumb, layoutTop, width);
-
-                    // Lay out the bottom button at the bottom of the view.
-                    int downBottom = orientationHelper.getEndAfterPadding() - mPaddingEnd;
-                    layoutViewCenteredFromBottom(mDownButton, downBottom, width);
-
-                    mHandler.post(this::calculateScrollThumbTrackHeight);
-                    mHandler.post(() -> updatePaginationButtons(/* animate= */ false));
-                });
+                        int oldBottom) -> mHandler.post(this::updatePaginationButtons));
     }
 
     public RecyclerView getRecyclerView() {
@@ -145,9 +117,8 @@
 
     @Override
     public void setPadding(int paddingStart, int paddingEnd) {
-        this.mPaddingStart = paddingStart;
-        this.mPaddingEnd = paddingEnd;
-        requestLayout();
+        mScrollView.setPadding(mScrollView.getPaddingLeft(), paddingStart,
+                mScrollView.getPaddingRight(), paddingEnd);
     }
 
     /**
@@ -179,60 +150,6 @@
         return mDownButton.isEnabled();
     }
 
-    /** Listener for when the list should paginate. */
-    interface PaginationListener {
-        int PAGE_UP = 0;
-        int PAGE_DOWN = 1;
-
-        /** Called when the linked view should be paged in the given direction */
-        void onPaginate(int direction);
-    }
-
-    /**
-     * Calculate the amount of space that the scroll bar thumb is allowed to roam. The thumb is
-     * allowed to take up the space between the down bottom and the up or alpha jump button,
-     * depending
-     * on if the latter is visible.
-     */
-    private void calculateScrollThumbTrackHeight() {
-        // Subtracting (2 * mSeparatingMargin) for the top/bottom margin above and below the
-        // scroll bar thumb.
-        mScrollThumbTrackHeight = mDownButton.getTop() - (2 * mSeparatingMargin);
-
-        // If there's an alpha jump button, then the thumb is laid out starting from below that.
-        mScrollThumbTrackHeight -= mUpButton.getBottom();
-    }
-
-    /**
-     * Lays out the given View starting from the given {@code top} value downwards and centered
-     * within the given {@code availableWidth}.
-     *
-     * @param view The view to lay out.
-     * @param top The top value to start laying out from. This value will be the resulting top value
-     * of the view.
-     * @param availableWidth The width in which to center the given view.
-     */
-    private static void layoutViewCenteredFromTop(View view, int top, int availableWidth) {
-        int viewWidth = view.getMeasuredWidth();
-        int viewLeft = (availableWidth - viewWidth) / 2;
-        view.layout(viewLeft, top, viewLeft + viewWidth, top + view.getMeasuredHeight());
-    }
-
-    /**
-     * Lays out the given View starting from the given {@code bottom} value upwards and centered
-     * within the given {@code availableSpace}.
-     *
-     * @param view The view to lay out.
-     * @param bottom The bottom value to start laying out from. This value will be the resulting
-     * bottom value of the view.
-     * @param availableWidth The width in which to center the given view.
-     */
-    private static void layoutViewCenteredFromBottom(View view, int bottom, int availableWidth) {
-        int viewWidth = view.getMeasuredWidth();
-        int viewLeft = (availableWidth - viewWidth) / 2;
-        view.layout(viewLeft, bottom - view.getMeasuredHeight(), viewLeft + viewWidth, bottom);
-    }
-
     /**
      * Sets the range, offset and extent of the scroll bar. The range represents the size of a
      * container for the scrollbar thumb; offset is the distance from the start of the container to
@@ -242,17 +159,14 @@
      * The
      * values should also be positive.
      *
-     * @param range The range of the scrollbar's thumb
+     * @param range  The range of the scrollbar's thumb
      * @param offset The offset of the scrollbar's thumb
      * @param extent The extent of the scrollbar's thumb
-     * @param animate Whether or not the thumb should animate from its current position to the
-     * position specified by the given range, offset and extent.
      */
     private void setParameters(
             @IntRange(from = 0) int range,
             @IntRange(from = 0) int offset,
-            @IntRange(from = 0) int extent,
-            boolean animate) {
+            @IntRange(from = 0) int extent) {
         // Not laid out yet, so values cannot be calculated.
         if (!mScrollView.isLaidOut()) {
             return;
@@ -274,20 +188,20 @@
             mScrollThumb.requestLayout();
         }
 
-        moveY(mScrollThumb, thumbOffset, animate);
+        moveY(mScrollThumb, thumbOffset);
     }
 
     /**
      * Calculates and returns how big the scroll bar thumb should be based on the given range and
      * extent.
      *
-     * @param range The total amount of space the scroll bar is allowed to roam over.
+     * @param range  The total amount of space the scroll bar is allowed to roam over.
      * @param extent The amount of space that the scroll bar takes up relative to the range.
      * @return The height of the scroll bar thumb in pixels.
      */
     private int calculateScrollThumbLength(int range, int extent) {
         // Scale the length by the available space that the thumb can fill.
-        return Math.round(((float) extent / range) * mScrollThumbTrackHeight);
+        return Math.round(((float) extent / range) * mScrollTrack.getHeight());
     }
 
     /**
@@ -295,9 +209,10 @@
      * has
      * been laid out.
      *
-     * @param range The total amount of space the scroll bar is allowed to roam over.
-     * @param offset The amount the scroll bar should be offset, expressed in the same units as the
-     * given range.
+     * @param range       The total amount of space the scroll bar is allowed to roam over.
+     * @param offset      The amount the scroll bar should be offset, expressed in the same units as
+     *                    the
+     *                    given range.
      * @param thumbLength The current length of the thumb in pixels.
      * @return The amount the thumb should be offset in pixels.
      */
@@ -305,63 +220,30 @@
         // Ensure that if the user has reached the bottom of the list, then the scroll bar is
         // aligned to the bottom as well. Otherwise, scale the offset appropriately.
         // This offset will be a value relative to the parent of this scrollbar, so start by where
-        // the top of mScrollThumb is.
-        return mScrollThumb.getTop()
+        // the top of scrollbar track is.
+        return mScrollTrack.getTop()
                 + (isDownEnabled()
-                ? Math.round(((float) offset / range) * mScrollThumbTrackHeight)
-                : mScrollThumbTrackHeight - thumbLength);
+                ? Math.round(((float) offset / range) * mScrollTrack.getHeight())
+                : mScrollTrack.getHeight() - thumbLength);
     }
 
     /** Moves the given view to the specified 'y' position. */
-    private void moveY(final View view, float newPosition, boolean animate) {
-        final int duration = animate ? 200 : 0;
+    private void moveY(final View view, float newPosition) {
         view.animate()
                 .y(newPosition)
-                .setDuration(duration)
+                .setDuration(/* duration= */ 0)
                 .setInterpolator(mPaginationInterpolator)
                 .start();
     }
 
-    private class PaginateButtonClickListener implements View.OnClickListener {
-        private final int mPaginateDirection;
-        private PaginationListener mPaginationListener;
-
-        PaginateButtonClickListener(int paginateDirection) {
-            this.mPaginateDirection = paginateDirection;
-        }
-
-        @Override
-        public void onClick(View v) {
-            if (mPaginationListener != null) {
-                mPaginationListener.onPaginate(mPaginateDirection);
-            }
-            if (mPaginateDirection == PaginationListener.PAGE_DOWN) {
-                pageDown();
-            } else if (mPaginateDirection == PaginationListener.PAGE_UP) {
-                pageUp();
-            }
-        }
-    }
-
     private final RecyclerView.OnScrollListener mRecyclerViewOnScrollListener =
             new RecyclerView.OnScrollListener() {
                 @Override
-                public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
-                    updatePaginationButtons(false);
+                public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
+                    updatePaginationButtons();
                 }
             };
 
-    /** Returns the page the given position is on, starting with page 0. */
-    int getPage(int position) {
-        if (mRowsPerPage == -1) {
-            return -1;
-        }
-        if (mRowsPerPage == 0) {
-            return 0;
-        }
-        return position / mRowsPerPage;
-    }
-
     private OrientationHelper getOrientationHelper(RecyclerView.LayoutManager layoutManager) {
         if (mOrientationHelper == null || mOrientationHelper.getLayoutManager() != layoutManager) {
             // CarUiRecyclerView is assumed to be a list that always vertically scrolls.
@@ -417,7 +299,7 @@
             }
         }
         // Distance should always be positive. Negate its value to scroll up.
-        mSnapHelper.smoothScrollBy(-scrollDistance);
+        mRecyclerView.smoothScrollBy(0, -scrollDistance);
     }
 
     /**
@@ -477,7 +359,7 @@
             }
         }
 
-        mSnapHelper.smoothScrollBy(scrollDistance);
+        mRecyclerView.smoothScrollBy(0, scrollDistance);
     }
 
     /**
@@ -489,24 +371,21 @@
      * this is called after an adapter change but before the new layout, the visibility
      * determination
      * may not be correct.
-     *
-     * @param animate {@code true} if the scrollbar should animate to its new position. {@code
-     * false}
-     * if no animation is used
      */
-    private void updatePaginationButtons(boolean animate) {
+    private void updatePaginationButtons() {
 
         boolean isAtStart = isAtStart();
         boolean isAtEnd = isAtEnd();
         RecyclerView.LayoutManager layoutManager = getRecyclerView().getLayoutManager();
 
+        // enable/disable the button before the view is shown. So there is no flicker.
+        setUpEnabled(!isAtStart);
+        setDownEnabled(!isAtEnd);
         if ((isAtStart && isAtEnd) || layoutManager == null || layoutManager.getItemCount() == 0) {
             mScrollView.setVisibility(View.INVISIBLE);
         } else {
             mScrollView.setVisibility(View.VISIBLE);
         }
-        setUpEnabled(!isAtStart);
-        setDownEnabled(!isAtEnd);
 
         if (layoutManager == null) {
             return;
@@ -516,14 +395,12 @@
             setParameters(
                     getRecyclerView().computeVerticalScrollRange(),
                     getRecyclerView().computeVerticalScrollOffset(),
-                    getRecyclerView().computeVerticalScrollExtent(),
-                    animate);
+                    getRecyclerView().computeVerticalScrollExtent());
         } else {
             setParameters(
                     getRecyclerView().computeHorizontalScrollRange(),
                     getRecyclerView().computeHorizontalScrollOffset(),
-                    getRecyclerView().computeHorizontalScrollExtent(),
-                    animate);
+                    getRecyclerView().computeHorizontalScrollExtent());
         }
 
         mScrollView.invalidate();
diff --git a/car-ui-lib/src/com/android/car/ui/recyclerview/FastScroller.java b/car-ui-lib/src/com/android/car/ui/recyclerview/FastScroller.java
new file mode 100644
index 0000000..9a44110
--- /dev/null
+++ b/car-ui-lib/src/com/android/car/ui/recyclerview/FastScroller.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.car.ui.recyclerview;
+
+import static com.android.car.ui.utils.CarUiUtils.requireViewByRefId;
+
+import android.view.MotionEvent;
+import android.view.View;
+
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.android.car.ui.R;
+
+/**
+ * Class responsible for fast scrolling. This class offers two functionalities.
+ * <ul>
+ *     <li>User can hold the thumb and drag.</li>
+ *     <li>User can click anywhere on the track and thumb will scroll to that position.</li>
+ * </ul>
+ */
+class FastScroller implements View.OnTouchListener {
+
+    private float mTouchDownY = -1;
+
+    private View mScrollTrackView;
+    private boolean mIsDragging;
+    private View mScrollThumb;
+    private RecyclerView mRecyclerView;
+
+    FastScroller(@NonNull RecyclerView recyclerView, @NonNull View scrollTrackView,
+            @NonNull View scrollView) {
+        mRecyclerView = recyclerView;
+        mScrollTrackView = scrollTrackView;
+        mScrollThumb = requireViewByRefId(scrollView, R.id.car_ui_scrollbar_thumb);
+    }
+
+    void enable() {
+        if (mRecyclerView != null) {
+            mScrollTrackView.setOnTouchListener(this);
+        }
+    }
+
+    @Override
+    public boolean onTouch(View v, MotionEvent me) {
+        switch (me.getAction()) {
+            case MotionEvent.ACTION_DOWN:
+                mTouchDownY = me.getY();
+                mIsDragging = false;
+                break;
+            case MotionEvent.ACTION_MOVE:
+                mIsDragging = true;
+                float thumbBottom = mScrollThumb.getY() + mScrollThumb.getHeight();
+                // check if the move coordinates are within the bounds of the thumb. i.e user is
+                // holding and dragging the thumb.
+                if (!(me.getY() + mScrollTrackView.getY() < thumbBottom
+                        && me.getY() + mScrollTrackView.getY() > mScrollThumb.getY())) {
+                    // don't do anything if touch is detected outside the thumb
+                    return true;
+                }
+                // calculate where the center of the thumb is on the screen.
+                float thumbCenter = mScrollThumb.getY() + mScrollThumb.getHeight() / 2.0f;
+                // me.getY() returns the coordinates relative to the view. For example, if we
+                // click the top left of the scroll track the coordinates will be 0,0. Hence, we
+                // need to add the relative coordinates to the actual coordinates computed by the
+                // thumb center and add them to get the final Y coordinate. "(me.getY() -
+                // mTouchDownY)" calculates the distance that is moved from the previous touch
+                // event.
+                verticalScrollTo(thumbCenter + (me.getY() - mTouchDownY));
+                mTouchDownY = me.getY();
+                break;
+            case MotionEvent.ACTION_UP:
+            default:
+                mTouchDownY = -1;
+                // if not dragged then it's a click. When a click is detected on the track and
+                // within the range we want to move the center of the thumb to the Y coordinate
+                // of the clicked position.
+                if (!mIsDragging) {
+                    verticalScrollTo(me.getY() + mScrollTrackView.getY());
+                }
+        }
+        return true;
+    }
+
+    private void verticalScrollTo(float y) {
+        int scrollingBy = calculateScrollDistance(y);
+        if (scrollingBy != 0) {
+            mRecyclerView.scrollBy(0, scrollingBy);
+        }
+    }
+
+    private int calculateScrollDistance(float newDragPos) {
+        final int[] scrollbarRange = getVerticalRange();
+        int scrollbarLength = scrollbarRange[1] - scrollbarRange[0];
+
+        float thumbCenter = mScrollThumb.getY() + mScrollThumb.getHeight() / 2.0f;
+
+        if (scrollbarLength == 0) {
+            return 0;
+        }
+        // percentage of data to be scrolled.
+        float percentage = ((newDragPos - thumbCenter) / (float) scrollbarLength);
+        int totalPossibleOffset =
+                mRecyclerView.computeVerticalScrollRange() - mRecyclerView.getHeight();
+        int scrollingBy = (int) (percentage * totalPossibleOffset);
+        int absoluteOffset = mRecyclerView.computeVerticalScrollOffset() + scrollingBy;
+        if (absoluteOffset < 0) {
+            return 0;
+        }
+        return scrollingBy;
+    }
+
+    /**
+     * Gets the (min, max) vertical positions of the vertical scroll bar. The range starts from the
+     * center of thumb when thumb is top aligned to center of the thumb when thumb is bottom
+     * aligned.
+     */
+    private int[] getVerticalRange() {
+        int[] verticalRange = new int[2];
+        verticalRange[0] = (int) mScrollTrackView.getY() + mScrollThumb.getHeight() / 2;
+        verticalRange[1] = (int) mScrollTrackView.getY() + mScrollTrackView.getHeight()
+                - mScrollThumb.getHeight() / 2;
+        return verticalRange;
+    }
+}
diff --git a/car-ui-lib/src/com/android/car/ui/recyclerview/OnContinuousScrollListener.java b/car-ui-lib/src/com/android/car/ui/recyclerview/OnContinuousScrollListener.java
new file mode 100644
index 0000000..4fafc8d
--- /dev/null
+++ b/car-ui-lib/src/com/android/car/ui/recyclerview/OnContinuousScrollListener.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.car.ui.recyclerview;
+
+import android.content.Context;
+import android.os.Handler;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.View.OnTouchListener;
+
+import androidx.annotation.NonNull;
+
+import com.android.car.ui.R;
+
+/**
+ * A class, that can be used as a TouchListener on any view (e.g. a Button).
+ * It periodically calls the provided clickListener. The first callback is fired after the
+ * initial Delay, and subsequent ones after the defined interval.
+ */
+public class OnContinuousScrollListener implements OnTouchListener {
+
+    private Handler mHandler = new Handler();
+
+    private int mInitialDelay;
+    private int mRepeatInterval;
+    private final OnClickListener mOnClickListener;
+    private View mTouchedView;
+    private boolean mIsLongPressed;
+
+    /**
+     * Notifies listener and self schedules to be re-run at next callback interval.
+     */
+    private Runnable mPeriodicRunnable = new Runnable() {
+        @Override
+        public void run() {
+            if (mTouchedView.isEnabled()) {
+                mHandler.postDelayed(this, mRepeatInterval);
+                mOnClickListener.onClick(mTouchedView);
+                mIsLongPressed = true;
+            } else {
+                mIsLongPressed = false;
+            }
+        }
+    };
+
+    /**
+     * @param clickListener The OnClickListener, that will be called
+     *                      periodically
+     */
+    public OnContinuousScrollListener(@NonNull Context context,
+            @NonNull OnClickListener clickListener) {
+        this.mInitialDelay = context.getResources().getInteger(
+                R.integer.car_ui_scrollbar_longpress_initial_delay);
+
+        this.mRepeatInterval = context.getResources().getInteger(
+                R.integer.car_ui_scrollbar_longpress_repeat_interval);
+
+        if (mInitialDelay < 0 || mRepeatInterval < 0) {
+            throw new IllegalArgumentException("negative intervals are not allowed");
+        }
+        this.mOnClickListener = clickListener;
+    }
+
+    @Override
+    public boolean onTouch(View view, MotionEvent motionEvent) {
+        mTouchedView = view;
+        switch (motionEvent.getAction()) {
+            case MotionEvent.ACTION_DOWN:
+                mHandler.removeCallbacks(mPeriodicRunnable);
+                mHandler.postDelayed(mPeriodicRunnable, mInitialDelay);
+                mTouchedView.setPressed(true);
+                return true;
+            case MotionEvent.ACTION_UP:
+            case MotionEvent.ACTION_CANCEL:
+                if (!mIsLongPressed) {
+                    mOnClickListener.onClick(view);
+                }
+                mHandler.removeCallbacks(mPeriodicRunnable);
+                mTouchedView.setPressed(false);
+                mIsLongPressed = false;
+                return true;
+        }
+        return false;
+    }
+}
diff --git a/car-ui-lib/src/com/android/car/ui/recyclerview/ScrollBar.java b/car-ui-lib/src/com/android/car/ui/recyclerview/ScrollBar.java
index ce58897..8e127f0 100644
--- a/car-ui-lib/src/com/android/car/ui/recyclerview/ScrollBar.java
+++ b/car-ui-lib/src/com/android/car/ui/recyclerview/ScrollBar.java
@@ -38,5 +38,5 @@
     void requestLayout();
 
     /** Sets the padding of the scrollbar, relative to the padding of the RecyclerView. */
-    void setPadding(int padddingStart, int paddingEnd);
+    void setPadding(int paddingStart, int paddingEnd);
 }
diff --git a/car-ui-lib/src/com/android/car/ui/recyclerview/decorations/grid/GridDividerItemDecoration.java b/car-ui-lib/src/com/android/car/ui/recyclerview/decorations/grid/GridDividerItemDecoration.java
index d462b92..abb90ca 100644
--- a/car-ui-lib/src/com/android/car/ui/recyclerview/decorations/grid/GridDividerItemDecoration.java
+++ b/car-ui-lib/src/com/android/car/ui/recyclerview/decorations/grid/GridDividerItemDecoration.java
@@ -20,6 +20,7 @@
 import android.graphics.drawable.Drawable;
 import android.view.View;
 
+import androidx.annotation.NonNull;
 import androidx.recyclerview.widget.RecyclerView;
 
 import com.android.car.ui.R;
@@ -36,12 +37,12 @@
      * dividers.
      *
      * @param horizontalDivider A divider {@code Drawable} to be drawn on the rows of the grid of
-     * the
-     * RecyclerView
-     * @param verticalDivider A divider {@code Drawable} to be drawn on the columns of the grid of
-     * the
-     * RecyclerView
-     * @param numColumns The number of columns in the grid of the RecyclerView
+     *                          the
+     *                          RecyclerView
+     * @param verticalDivider   A divider {@code Drawable} to be drawn on the columns of the grid of
+     *                          the
+     *                          RecyclerView
+     * @param numColumns        The number of columns in the grid of the RecyclerView
      */
     public GridDividerItemDecoration(
             Drawable horizontalDivider, Drawable verticalDivider, int numColumns) {
@@ -55,10 +56,11 @@
      *
      * @param canvas The {@link Canvas} onto which dividers will be drawn
      * @param parent The RecyclerView onto which dividers are being added
-     * @param state The current RecyclerView.State of the RecyclerView
+     * @param state  The current RecyclerView.State of the RecyclerView
      */
     @Override
-    public void onDrawOver(Canvas canvas, RecyclerView parent, RecyclerView.State state) {
+    public void onDrawOver(@NonNull Canvas canvas, @NonNull RecyclerView parent,
+            @NonNull RecyclerView.State state) {
         drawVerticalDividers(canvas, parent);
         drawHorizontalDividers(canvas, parent);
     }
@@ -67,13 +69,14 @@
      * Determines the size and location of offsets between items in the parent RecyclerView.
      *
      * @param outRect The {@link Rect} of offsets to be added around the child view
-     * @param view The child view to be decorated with an offset
-     * @param parent The RecyclerView onto which dividers are being added
-     * @param state The current RecyclerView.State of the RecyclerView
+     * @param view    The child view to be decorated with an offset
+     * @param parent  The RecyclerView onto which dividers are being added
+     * @param state   The current RecyclerView.State of the RecyclerView
      */
     @Override
     public void getItemOffsets(
-            Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
+            Rect outRect, @NonNull View view, @NonNull RecyclerView parent,
+            @NonNull RecyclerView.State state) {
         outRect.set(
                 0, 0, mHorizontalDivider.getIntrinsicWidth(),
                 mHorizontalDivider.getIntrinsicHeight());
@@ -131,7 +134,7 @@
         double rowCount = Math.ceil(childCount / mNumColumns);
         int rightmostChildIndex;
         for (int i = 1; i <= rowCount; i++) {
-            // we dont want the divider on top of first row.
+            // we don't want the divider on top of first row.
             if (i == 1) {
                 continue;
             }
diff --git a/car-ui-lib/src/com/android/car/ui/recyclerview/decorations/grid/GridOffsetItemDecoration.java b/car-ui-lib/src/com/android/car/ui/recyclerview/decorations/grid/GridOffsetItemDecoration.java
index 3dd6c19..f1085c2 100644
--- a/car-ui-lib/src/com/android/car/ui/recyclerview/decorations/grid/GridOffsetItemDecoration.java
+++ b/car-ui-lib/src/com/android/car/ui/recyclerview/decorations/grid/GridOffsetItemDecoration.java
@@ -23,6 +23,7 @@
 import android.view.View;
 
 import androidx.annotation.IntDef;
+import androidx.annotation.NonNull;
 import androidx.recyclerview.widget.RecyclerView;
 
 import java.lang.annotation.Retention;
@@ -53,8 +54,9 @@
     /**
      * Constructor that takes in the size of the offset to be added to the top of the RecyclerView.
      *
-     * @param offsetPx The size of the offset to be added to the top of the RecyclerView in pixels
-     * @param numColumns The number of columns in the grid of the RecyclerView
+     * @param offsetPx       The size of the offset to be added to the top of the RecyclerView in
+     *                       pixels
+     * @param numColumns     The number of columns in the grid of the RecyclerView
      * @param offsetPosition Position where offset needs to be applied.
      */
     public GridOffsetItemDecoration(int offsetPx, int numColumns, int offsetPosition) {
@@ -67,7 +69,7 @@
      * Constructor that takes in a {@link Drawable} to be drawn at the top of the RecyclerView.
      *
      * @param offsetDrawable The {@code Drawable} to be added to the top of the RecyclerView
-     * @param numColumns The number of columns in the grid of the RecyclerView
+     * @param numColumns     The number of columns in the grid of the RecyclerView
      */
     public GridOffsetItemDecoration(Drawable offsetDrawable, int numColumns, int offsetPosition) {
         this.mOffsetDrawable = offsetDrawable;
@@ -84,13 +86,14 @@
      * RecyclerView.
      *
      * @param outRect The {@link Rect} of offsets to be added around the child view
-     * @param view The child view to be decorated with an offset
-     * @param parent The RecyclerView onto which dividers are being added
-     * @param state The current RecyclerView.State of the RecyclerView
+     * @param view    The child view to be decorated with an offset
+     * @param parent  The RecyclerView onto which dividers are being added
+     * @param state   The current RecyclerView.State of the RecyclerView
      */
     @Override
     public void getItemOffsets(
-            Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
+            @NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent,
+            @NonNull RecyclerView.State state) {
         super.getItemOffsets(outRect, view, parent, state);
 
         if (mOffsetPosition == OffsetPosition.START) {
@@ -120,7 +123,8 @@
     }
 
     @Override
-    public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
+    public void onDraw(@NonNull Canvas c, @NonNull RecyclerView parent,
+            @NonNull RecyclerView.State state) {
         super.onDraw(c, parent, state);
         if (mOffsetDrawable == null) {
             return;
diff --git a/car-ui-lib/src/com/android/car/ui/recyclerview/decorations/linear/LinearDividerItemDecoration.java b/car-ui-lib/src/com/android/car/ui/recyclerview/decorations/linear/LinearDividerItemDecoration.java
index 0adbdeb..4d5e6bd 100644
--- a/car-ui-lib/src/com/android/car/ui/recyclerview/decorations/linear/LinearDividerItemDecoration.java
+++ b/car-ui-lib/src/com/android/car/ui/recyclerview/decorations/linear/LinearDividerItemDecoration.java
@@ -20,11 +20,14 @@
 import android.graphics.drawable.Drawable;
 import android.view.View;
 
+import androidx.annotation.NonNull;
 import androidx.recyclerview.widget.LinearLayoutManager;
 import androidx.recyclerview.widget.RecyclerView;
 
 import com.android.car.ui.R;
 
+import java.util.Objects;
+
 /** Adds interior dividers to a RecyclerView with a LinearLayoutManager or its subclass. */
 public class LinearDividerItemDecoration extends RecyclerView.ItemDecoration {
 
@@ -36,7 +39,7 @@
      * car_ui_recyclerview_divider.
      *
      * @param divider A car_ui_recyclerview_divider {@code Drawable} to be drawn on the
-     * RecyclerView
+     *                RecyclerView
      */
     public LinearDividerItemDecoration(Drawable divider) {
         this.mDivider = divider;
@@ -47,10 +50,11 @@
      *
      * @param canvas The {@link Canvas} onto which dividers will be drawn
      * @param parent The RecyclerView onto which dividers are being added
-     * @param state The current RecyclerView.State of the RecyclerView
+     * @param state  The current RecyclerView.State of the RecyclerView
      */
     @Override
-    public void onDraw(Canvas canvas, RecyclerView parent, RecyclerView.State state) {
+    public void onDraw(@NonNull Canvas canvas, @NonNull RecyclerView parent,
+            @NonNull RecyclerView.State state) {
         if (mOrientation == LinearLayoutManager.HORIZONTAL) {
             drawHorizontalDividers(canvas, parent);
         } else if (mOrientation == LinearLayoutManager.VERTICAL) {
@@ -62,20 +66,22 @@
      * Determines the size and location of offsets between items in the parent RecyclerView.
      *
      * @param outRect The {@link Rect} of offsets to be added around the child view
-     * @param view The child view to be decorated with an offset
-     * @param parent The RecyclerView onto which dividers are being added
-     * @param state The current RecyclerView.State of the RecyclerView
+     * @param view    The child view to be decorated with an offset
+     * @param parent  The RecyclerView onto which dividers are being added
+     * @param state   The current RecyclerView.State of the RecyclerView
      */
     @Override
     public void getItemOffsets(
-            Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
+            @NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent,
+            @NonNull RecyclerView.State state) {
         super.getItemOffsets(outRect, view, parent, state);
 
         if (parent.getChildAdapterPosition(view) == 0) {
             return;
         }
 
-        mOrientation = ((LinearLayoutManager) parent.getLayoutManager()).getOrientation();
+        mOrientation = ((LinearLayoutManager) Objects.requireNonNull(
+                parent.getLayoutManager())).getOrientation();
         if (mOrientation == LinearLayoutManager.HORIZONTAL) {
             outRect.left = mDivider.getIntrinsicWidth();
         } else if (mOrientation == LinearLayoutManager.VERTICAL) {
diff --git a/car-ui-lib/src/com/android/car/ui/recyclerview/decorations/linear/LinearOffsetItemDecoration.java b/car-ui-lib/src/com/android/car/ui/recyclerview/decorations/linear/LinearOffsetItemDecoration.java
index d757f05..33e14db 100644
--- a/car-ui-lib/src/com/android/car/ui/recyclerview/decorations/linear/LinearOffsetItemDecoration.java
+++ b/car-ui-lib/src/com/android/car/ui/recyclerview/decorations/linear/LinearOffsetItemDecoration.java
@@ -23,10 +23,12 @@
 import android.view.View;
 
 import androidx.annotation.IntDef;
+import androidx.annotation.NonNull;
 import androidx.recyclerview.widget.LinearLayoutManager;
 import androidx.recyclerview.widget.RecyclerView;
 
 import java.lang.annotation.Retention;
+import java.util.Objects;
 
 /**
  * Adds an offset to the start of a RecyclerView using a LinearLayoutManager or its subclass.
@@ -61,7 +63,8 @@
      * Constructor that takes in the size of the offset to be added to the start of the
      * RecyclerView.
      *
-     * @param offsetPx The size of the offset to be added to the start of the RecyclerView in pixels
+     * @param offsetPx       The size of the offset to be added to the start of the RecyclerView in
+     *                       pixels
      * @param offsetPosition Position where offset needs to be applied.
      */
     public LinearOffsetItemDecoration(int offsetPx, int offsetPosition) {
@@ -82,13 +85,14 @@
      * Determines the size and location of the offset to be added to the start of the RecyclerView.
      *
      * @param outRect The {@link Rect} of offsets to be added around the child view
-     * @param view The child view to be decorated with an offset
-     * @param parent The RecyclerView onto which dividers are being added
-     * @param state The current RecyclerView.State of the RecyclerView
+     * @param view    The child view to be decorated with an offset
+     * @param parent  The RecyclerView onto which dividers are being added
+     * @param state   The current RecyclerView.State of the RecyclerView
      */
     @Override
     public void getItemOffsets(
-            Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
+            @NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent,
+            @NonNull RecyclerView.State state) {
         super.getItemOffsets(outRect, view, parent, state);
 
         if (mOffsetPosition == OffsetPosition.START && parent.getChildAdapterPosition(view) > 0) {
@@ -101,7 +105,8 @@
             return;
         }
 
-        mOrientation = ((LinearLayoutManager) parent.getLayoutManager()).getOrientation();
+        mOrientation = ((LinearLayoutManager) Objects.requireNonNull(
+                parent.getLayoutManager())).getOrientation();
         if (mOrientation == LinearLayoutManager.HORIZONTAL) {
             if (mOffsetPx > 0) {
                 if (mOffsetPosition == OffsetPosition.START) {
@@ -136,12 +141,13 @@
     /**
      * Draws horizontal or vertical offset onto the start of the parent RecyclerView.
      *
-     * @param c The {@link Canvas} onto which an offset will be drawn
+     * @param c      The {@link Canvas} onto which an offset will be drawn
      * @param parent The RecyclerView onto which an offset is being added
-     * @param state The current RecyclerView.State of the RecyclerView
+     * @param state  The current RecyclerView.State of the RecyclerView
      */
     @Override
-    public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
+    public void onDraw(@NonNull Canvas c, @NonNull RecyclerView parent,
+            @NonNull RecyclerView.State state) {
         super.onDraw(c, parent, state);
         if (mOffsetDrawable == null) {
             return;
@@ -157,19 +163,18 @@
     private void drawOffsetHorizontal(Canvas canvas, RecyclerView parent) {
         int parentTop = parent.getPaddingTop();
         int parentBottom = parent.getHeight() - parent.getPaddingBottom();
-        int parentLeft = 0;
-        int offsetDrawableRight = 0;
+        int parentLeft;
+        int offsetDrawableRight;
 
         if (mOffsetPosition == OffsetPosition.START) {
             parentLeft = parent.getPaddingLeft();
-            offsetDrawableRight = parentLeft + mOffsetDrawable.getIntrinsicWidth();
         } else {
             View lastChild = parent.getChildAt(parent.getChildCount() - 1);
             RecyclerView.LayoutParams lastChildLayoutParams =
                     (RecyclerView.LayoutParams) lastChild.getLayoutParams();
             parentLeft = lastChild.getRight() + lastChildLayoutParams.rightMargin;
-            offsetDrawableRight = parentLeft + mOffsetDrawable.getIntrinsicWidth();
         }
+        offsetDrawableRight = parentLeft + mOffsetDrawable.getIntrinsicWidth();
 
         mOffsetDrawable.setBounds(parentLeft, parentTop, offsetDrawableRight, parentBottom);
         mOffsetDrawable.draw(canvas);
@@ -179,19 +184,18 @@
         int parentLeft = parent.getPaddingLeft();
         int parentRight = parent.getWidth() - parent.getPaddingRight();
 
-        int parentTop = 0;
-        int offsetDrawableBottom = 0;
+        int parentTop;
+        int offsetDrawableBottom;
 
         if (mOffsetPosition == OffsetPosition.START) {
             parentTop = parent.getPaddingTop();
-            offsetDrawableBottom = parentTop + mOffsetDrawable.getIntrinsicHeight();
         } else {
             View lastChild = parent.getChildAt(parent.getChildCount() - 1);
             RecyclerView.LayoutParams lastChildLayoutParams =
                     (RecyclerView.LayoutParams) lastChild.getLayoutParams();
             parentTop = lastChild.getBottom() + lastChildLayoutParams.bottomMargin;
-            offsetDrawableBottom = parentTop + mOffsetDrawable.getIntrinsicHeight();
         }
+        offsetDrawableBottom = parentTop + mOffsetDrawable.getIntrinsicHeight();
 
         mOffsetDrawable.setBounds(parentLeft, parentTop, parentRight, offsetDrawableBottom);
         mOffsetDrawable.draw(canvas);
diff --git a/car-ui-lib/src/com/android/car/ui/toolbar/MenuItem.java b/car-ui-lib/src/com/android/car/ui/toolbar/MenuItem.java
index 20d6847..6ee35d3 100644
--- a/car-ui-lib/src/com/android/car/ui/toolbar/MenuItem.java
+++ b/car-ui-lib/src/com/android/car/ui/toolbar/MenuItem.java
@@ -96,7 +96,7 @@
     private void update() {
         Listener listener = mListener.get();
         if (listener != null) {
-            listener.onMenuItemChanged();
+            listener.onMenuItemChanged(this);
         }
     }
 
@@ -343,15 +343,15 @@
             if (mIsActivatable && (mShowIconAndTitle || mIcon == null)) {
                 throw new IllegalStateException("Only simple icons can be activatable");
             }
-            if (mIsCheckable
-                    && (mDisplayBehavior == DisplayBehavior.NEVER
-                    || mShowIconAndTitle
-                    || mIsActivatable)) {
+            if (mIsCheckable && (mShowIconAndTitle || mIsActivatable)) {
                 throw new IllegalStateException("Unsupported options for a checkable MenuItem");
             }
             if (mIsSearch && mIsSettings) {
                 throw new IllegalStateException("Can't have both a search and settings MenuItem");
             }
+            if (mIsActivatable && mDisplayBehavior == DisplayBehavior.NEVER) {
+                throw new IllegalStateException("Activatable MenuItems not supported as Overflow");
+            }
 
             if (mIsSearch && (!mSearchTitle.contentEquals(mTitle)
                     || !mSearchIcon.equals(mIcon)
@@ -489,7 +489,7 @@
 
         /**
          * Makes the MenuItem checkable, meaning it will be displayed as a
-         * switch. Currently a checkable MenuItem cannot have a {@link DisplayBehavior} of NEVER.
+         * switch.
          *
          * <p>The MenuItem is not checkable by default.
          */
@@ -599,7 +599,7 @@
     /** Listener for {@link Toolbar} to update when this MenuItem changes */
     interface Listener {
         /** Called when the MenuItem is changed. For use only by {@link Toolbar} */
-        void onMenuItemChanged();
+        void onMenuItemChanged(MenuItem item);
     }
 
     /**
diff --git a/car-ui-lib/src/com/android/car/ui/toolbar/MenuItemRenderer.java b/car-ui-lib/src/com/android/car/ui/toolbar/MenuItemRenderer.java
index 77b9f53..7bf9025 100644
--- a/car-ui-lib/src/com/android/car/ui/toolbar/MenuItemRenderer.java
+++ b/car-ui-lib/src/com/android/car/ui/toolbar/MenuItemRenderer.java
@@ -88,7 +88,7 @@
     }
 
     @Override
-    public void onMenuItemChanged() {
+    public void onMenuItemChanged(MenuItem changedItem) {
         updateView();
     }
 
@@ -105,6 +105,7 @@
             mTextView = requireViewByRefId(mView, R.id.car_ui_toolbar_menu_item_text);
             mTextWithIconView =
                     requireViewByRefId(mView, R.id.car_ui_toolbar_menu_item_text_with_icon);
+
             updateView();
             callback.accept(mView);
         });
diff --git a/car-ui-lib/src/com/android/car/ui/toolbar/ProgressBarController.java b/car-ui-lib/src/com/android/car/ui/toolbar/ProgressBarController.java
new file mode 100644
index 0000000..d42ac1b
--- /dev/null
+++ b/car-ui-lib/src/com/android/car/ui/toolbar/ProgressBarController.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.car.ui.toolbar;
+
+/**
+ * Interface for a Progress Bar. It's methods are a subset of the methods of
+ * {@link android.widget.ProgressBar}. This is so that an application doesn't
+ * have access to customize the {@link android.widget.ProgressBar} or other
+ * views in it's hierarchy in ways that were not intended.
+ */
+public interface ProgressBarController {
+
+    /** Shows/hides the progress bar */
+    void setVisible(boolean visible);
+    /** Returns true if the progress bar is visible */
+    boolean isVisible();
+    /** Equivalent to {@link android.widget.ProgressBar#setIndeterminate(boolean)} */
+    void setIndeterminate(boolean indeterminate);
+    /** Equivalent to {@link android.widget.ProgressBar#isIndeterminate()} */
+    boolean isIndeterminate();
+    /** Equivalent to {@link android.widget.ProgressBar#setMax(int)} */
+    void setMax(int max);
+    /** Equivalent to {@link android.widget.ProgressBar#getMax()} */
+    int getMax();
+    /** Equivalent to {@link android.widget.ProgressBar#setMin(int)} */
+    void setMin(int min);
+    /** Equivalent to {@link android.widget.ProgressBar#getMin()} */
+    int getMin();
+    /** Equivalent to {@link android.widget.ProgressBar#setProgress(int)} */
+    void setProgress(int progress);
+    /** Equivalent to {@link android.widget.ProgressBar#getProgress()} */
+    int getProgress();
+}
diff --git a/car-ui-lib/src/com/android/car/ui/toolbar/ProgressBarControllerImpl.java b/car-ui-lib/src/com/android/car/ui/toolbar/ProgressBarControllerImpl.java
new file mode 100644
index 0000000..07a59b2
--- /dev/null
+++ b/car-ui-lib/src/com/android/car/ui/toolbar/ProgressBarControllerImpl.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.car.ui.toolbar;
+
+import android.view.View;
+import android.widget.ProgressBar;
+
+import androidx.annotation.NonNull;
+
+/**
+ * Implementation of {@link ProgressBarController}.
+ *
+ * <p>This class accepts a {@link ProgressBar} in it's constructor and forwards the methods
+ * of {@link ProgressBarController} to it.
+ */
+class ProgressBarControllerImpl implements ProgressBarController {
+
+    @NonNull
+    private final ProgressBar mProgressBar;
+
+    ProgressBarControllerImpl(@NonNull ProgressBar progressBar) {
+        mProgressBar = progressBar;
+    }
+
+    @Override
+    public void setVisible(boolean visible) {
+        mProgressBar.setVisibility(visible ? View.VISIBLE : View.GONE);
+    }
+
+    @Override
+    public boolean isVisible() {
+        return mProgressBar.getVisibility() == View.VISIBLE;
+    }
+
+    @Override
+    public void setIndeterminate(boolean indeterminate) {
+        mProgressBar.setIndeterminate(indeterminate);
+    }
+
+    @Override
+    public boolean isIndeterminate() {
+        return mProgressBar.isIndeterminate();
+    }
+
+    @Override
+    public void setMax(int max) {
+        mProgressBar.setMax(max);
+    }
+
+    @Override
+    public int getMax() {
+        return mProgressBar.getMax();
+    }
+
+    @Override
+    public void setMin(int min) {
+        mProgressBar.setMin(min);
+    }
+
+    @Override
+    public int getMin() {
+        return mProgressBar.getMin();
+    }
+
+    @Override
+    public void setProgress(int progress) {
+        mProgressBar.setProgress(progress);
+    }
+
+    @Override
+    public int getProgress() {
+        return mProgressBar.getProgress();
+    }
+}
diff --git a/car-ui-lib/src/com/android/car/ui/toolbar/TabLayout.java b/car-ui-lib/src/com/android/car/ui/toolbar/TabLayout.java
index 828e54a..1f973d2 100644
--- a/car-ui-lib/src/com/android/car/ui/toolbar/TabLayout.java
+++ b/car-ui-lib/src/com/android/car/ui/toolbar/TabLayout.java
@@ -19,8 +19,6 @@
 
 import android.content.Context;
 import android.content.res.Resources;
-import android.content.res.TypedArray;
-import android.graphics.Typeface;
 import android.graphics.drawable.Drawable;
 import android.util.ArraySet;
 import android.util.AttributeSet;
@@ -35,7 +33,6 @@
 import androidx.annotation.LayoutRes;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
-import androidx.annotation.StyleRes;
 
 import com.android.car.ui.R;
 
@@ -181,8 +178,6 @@
         private final TabLayout mTabLayout;
         @LayoutRes
         private final int mTabItemLayoutRes;
-        private final Typeface mUnselectedTypeface;
-        private final Typeface mSelectedTypeface;
         private final List<Tab> mTabList;
 
         private TabAdapter(Context context, @LayoutRes int res, TabLayout tabLayout) {
@@ -190,10 +185,6 @@
             mContext = context;
             mTabItemLayoutRes = res;
             mTabLayout = tabLayout;
-            mUnselectedTypeface = createStyledTypeface(context,
-                    R.style.TextAppearance_CarUi_Widget_Toolbar_Tab);
-            mSelectedTypeface = createStyledTypeface(context,
-                    R.style.TextAppearance_CarUi_Widget_Toolbar_Tab_Selected);
         }
 
         private void add(@NonNull Tab tab) {
@@ -282,26 +273,9 @@
             tab.bindText(textView);
             tab.bindIcon(iconView);
             tabItemView.setActivated(tab.mIsSelected);
-            textView.setTypeface(tab.mIsSelected ? mSelectedTypeface : mUnselectedTypeface);
-        }
-
-        private static Typeface createStyledTypeface(Context context, @StyleRes int styleResId) {
-            TypedArray ta = context.obtainStyledAttributes(styleResId, new int[] {
-                    android.R.attr.textStyle,
-                    android.R.attr.textFontWeight
-            });
-
-            try {
-                // If not specified, default to 0, which stands for normal.
-                int textStyle = ta.getInteger(0, 0);
-                // If not specified, default value will be 0 which is a light font.
-                int textFontWeight = ta.getInteger(1, 0);
-
-                return Typeface.create(Typeface.defaultFromStyle(textStyle), textFontWeight,
-                        (textStyle & Typeface.ITALIC) != 0);
-            } finally {
-                ta.recycle();
-            }
+            textView.setTextAppearance(tab.mIsSelected
+                    ? R.style.TextAppearance_CarUi_Widget_Toolbar_Tab_Selected
+                    : R.style.TextAppearance_CarUi_Widget_Toolbar_Tab);
         }
     }
 
diff --git a/car-ui-lib/src/com/android/car/ui/toolbar/Toolbar.java b/car-ui-lib/src/com/android/car/ui/toolbar/Toolbar.java
index 697c783..b069fb0 100644
--- a/car-ui-lib/src/com/android/car/ui/toolbar/Toolbar.java
+++ b/car-ui-lib/src/com/android/car/ui/toolbar/Toolbar.java
@@ -23,7 +23,6 @@
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.widget.FrameLayout;
-import android.widget.ProgressBar;
 
 import androidx.annotation.DrawableRes;
 import androidx.annotation.NonNull;
@@ -157,7 +156,7 @@
                 setSearchHint(searchHint);
             }
 
-            switch (a.getInt(R.styleable.CarUiToolbar_state, 0)) {
+            switch (a.getInt(R.styleable.CarUiToolbar_car_ui_state, 0)) {
                 case 0:
                     setState(State.HOME);
                     break;
@@ -174,7 +173,7 @@
                     break;
             }
 
-            switch (a.getInt(R.styleable.CarUiToolbar_navButtonMode, 0)) {
+            switch (a.getInt(R.styleable.CarUiToolbar_car_ui_navButtonMode, 0)) {
                 case 0:
                     setNavButtonMode(NavButtonMode.BACK);
                     break;
@@ -212,6 +211,7 @@
     /**
      * Returns {@code true} if a two row layout in enabled for the toolbar.
      */
+    @Override
     public boolean isTabsInSecondRow() {
         return mController.isTabsInSecondRow();
     }
@@ -221,6 +221,7 @@
      *
      * <p>The title may not always be shown, for example with one row layout with tabs.
      */
+    @Override
     public void setTitle(@StringRes int title) {
         mController.setTitle(title);
     }
@@ -230,17 +231,45 @@
      *
      * <p>The title may not always be shown, for example with one row layout with tabs.
      */
+    @Override
     public void setTitle(CharSequence title) {
         mController.setTitle(title);
     }
 
+    @Override
     public CharSequence getTitle() {
         return mController.getTitle();
     }
 
     /**
+     * Sets the subtitle of the toolbar to a string resource.
+     *
+     * <p>The title may not always be shown, for example with one row layout with tabs.
+     */
+    @Override
+    public void setSubtitle(@StringRes int title) {
+        mController.setSubtitle(title);
+    }
+
+    /**
+     * Sets the subtitle of the toolbar to a CharSequence.
+     *
+     * <p>The title may not always be shown, for example with one row layout with tabs.
+     */
+    @Override
+    public void setSubtitle(CharSequence title) {
+        mController.setSubtitle(title);
+    }
+
+    @Override
+    public CharSequence getSubtitle() {
+        return mController.getSubtitle();
+    }
+
+    /**
      * Gets the {@link TabLayout} for this toolbar.
      */
+    @Override
     public TabLayout getTabLayout() {
         return mController.getTabLayout();
     }
@@ -249,11 +278,13 @@
      * Adds a tab to this toolbar. You can listen for when it is selected via
      * {@link #registerOnTabSelectedListener(OnTabSelectedListener)}.
      */
+    @Override
     public void addTab(TabLayout.Tab tab) {
         mController.addTab(tab);
     }
 
     /** Removes all the tabs. */
+    @Override
     public void clearAllTabs() {
         mController.clearAllTabs();
     }
@@ -262,6 +293,7 @@
      * Gets a tab added to this toolbar. See
      * {@link #addTab(TabLayout.Tab)}.
      */
+    @Override
     public TabLayout.Tab getTab(int position) {
         return mController.getTab(position);
     }
@@ -270,6 +302,7 @@
      * Selects a tab added to this toolbar. See
      * {@link #addTab(TabLayout.Tab)}.
      */
+    @Override
     public void selectTab(int position) {
         mController.selectTab(position);
     }
@@ -277,6 +310,7 @@
     /**
      * Sets whether or not tabs should also be shown in the SUBPAGE {@link State}.
      */
+    @Override
     public void setShowTabsInSubpage(boolean showTabs) {
         mController.setShowTabsInSubpage(showTabs);
     }
@@ -284,6 +318,7 @@
     /**
      * Gets whether or not tabs should also be shown in the SUBPAGE {@link State}.
      */
+    @Override
     public boolean getShowTabsInSubpage() {
         return mController.getShowTabsInSubpage();
     }
@@ -292,6 +327,7 @@
      * Sets the logo to display in this toolbar. If navigation icon is being displayed, this logo
      * will be displayed next to the title.
      */
+    @Override
     public void setLogo(@DrawableRes int resId) {
         mController.setLogo(resId);
     }
@@ -300,21 +336,25 @@
      * Sets the logo to display in this toolbar. If navigation icon is being displayed, this logo
      * will be displayed next to the title.
      */
+    @Override
     public void setLogo(Drawable drawable) {
         mController.setLogo(drawable);
     }
 
     /** Sets the hint for the search bar. */
+    @Override
     public void setSearchHint(@StringRes int resId) {
         mController.setSearchHint(resId);
     }
 
     /** Sets the hint for the search bar. */
+    @Override
     public void setSearchHint(CharSequence hint) {
         mController.setSearchHint(hint);
     }
 
     /** Gets the search hint */
+    @Override
     public CharSequence getSearchHint() {
         return mController.getSearchHint();
     }
@@ -325,6 +365,7 @@
      * <p>The icon will be lost on configuration change, make sure to set it in onCreate() or
      * a similar place.
      */
+    @Override
     public void setSearchIcon(@DrawableRes int resId) {
         mController.setSearchIcon(resId);
     }
@@ -335,6 +376,7 @@
      * <p>The icon will be lost on configuration change, make sure to set it in onCreate() or
      * a similar place.
      */
+    @Override
     public void setSearchIcon(Drawable d) {
         mController.setSearchIcon(d);
     }
@@ -353,11 +395,13 @@
     }
 
     /** Sets the {@link NavButtonMode} */
+    @Override
     public void setNavButtonMode(NavButtonMode style) {
         mController.setNavButtonMode(style);
     }
 
     /** Gets the {@link NavButtonMode} */
+    @Override
     public NavButtonMode getNavButtonMode() {
         return mController.getNavButtonMode();
     }
@@ -373,11 +417,13 @@
     }
 
     /** Show/hide the background. When hidden, the toolbar is completely transparent. */
+    @Override
     public void setBackgroundShown(boolean shown) {
         mController.setBackgroundShown(shown);
     }
 
     /** Returns true is the toolbar background is shown */
+    @Override
     public boolean getBackgroundShown() {
         return mController.getBackgroundShown();
     }
@@ -385,6 +431,7 @@
     /**
      * Sets the {@link MenuItem Menuitems} to display.
      */
+    @Override
     public void setMenuItems(@Nullable List<MenuItem> items) {
         mController.setMenuItems(items);
     }
@@ -415,26 +462,30 @@
      * </MenuItems>
      * </pre>
      *
-     * @see #setMenuItems(List)
      * @return The MenuItems that were loaded from XML.
+     * @see #setMenuItems(List)
      */
+    @Override
     public List<MenuItem> setMenuItems(@XmlRes int resId) {
         return mController.setMenuItems(resId);
     }
 
     /** Gets the {@link MenuItem MenuItems} currently displayed */
+    @Override
     @NonNull
     public List<MenuItem> getMenuItems() {
         return mController.getMenuItems();
     }
 
     /** Gets a {@link MenuItem} by id. */
+    @Override
     @Nullable
     public MenuItem findMenuItemById(int id) {
         return mController.findMenuItemById(id);
     }
 
     /** Gets a {@link MenuItem} by id. Will throw an exception if not found. */
+    @Override
     @NonNull
     public MenuItem requireMenuItemById(int id) {
         return mController.requireMenuItemById(id);
@@ -445,11 +496,13 @@
      * Even if this is set to true, the {@link MenuItem} created by
      * {@link MenuItem.Builder#setToSearch()} will still be hidden.
      */
+    @Override
     public void setShowMenuItemsWhileSearching(boolean showMenuItems) {
         mController.setShowMenuItemsWhileSearching(showMenuItems);
     }
 
     /** Returns if {@link MenuItem MenuItems} are shown while searching */
+    @Override
     public boolean getShowMenuItemsWhileSearching() {
         return mController.getShowMenuItemsWhileSearching();
     }
@@ -457,6 +510,7 @@
     /**
      * Sets the search query.
      */
+    @Override
     public void setSearchQuery(String query) {
         mController.setSearchQuery(query);
     }
@@ -465,11 +519,13 @@
      * Sets the state of the toolbar. This will show/hide the appropriate elements of the toolbar
      * for the desired state.
      */
+    @Override
     public void setState(State state) {
         mController.setState(state);
     }
 
     /** Gets the current {@link State} of the toolbar. */
+    @Override
     public State getState() {
         return mController.getState();
     }
@@ -535,69 +591,70 @@
      * nothing else. {@link com.android.car.ui.recyclerview.CarUiRecyclerView} will
      * automatically adjust its height according to the height of the Toolbar.
      */
+    @Override
     public void registerToolbarHeightChangeListener(
             OnHeightChangedListener listener) {
         mController.registerToolbarHeightChangeListener(listener);
     }
 
     /** Unregisters an existing {@link OnHeightChangedListener} from the list of listeners. */
+    @Override
     public boolean unregisterToolbarHeightChangeListener(
             OnHeightChangedListener listener) {
         return mController.unregisterToolbarHeightChangeListener(listener);
     }
 
     /** Registers a new {@link OnTabSelectedListener} to the list of listeners. */
+    @Override
     public void registerOnTabSelectedListener(OnTabSelectedListener listener) {
         mController.registerOnTabSelectedListener(listener);
     }
 
     /** Unregisters an existing {@link OnTabSelectedListener} from the list of listeners. */
+    @Override
     public boolean unregisterOnTabSelectedListener(OnTabSelectedListener listener) {
         return mController.unregisterOnTabSelectedListener(listener);
     }
 
     /** Registers a new {@link OnSearchListener} to the list of listeners. */
+    @Override
     public void registerOnSearchListener(OnSearchListener listener) {
         mController.registerOnSearchListener(listener);
     }
 
     /** Unregisters an existing {@link OnSearchListener} from the list of listeners. */
+    @Override
     public boolean unregisterOnSearchListener(OnSearchListener listener) {
         return mController.unregisterOnSearchListener(listener);
     }
 
     /** Registers a new {@link OnSearchCompletedListener} to the list of listeners. */
+    @Override
     public void registerOnSearchCompletedListener(OnSearchCompletedListener listener) {
         mController.registerOnSearchCompletedListener(listener);
     }
 
     /** Unregisters an existing {@link OnSearchCompletedListener} from the list of listeners. */
+    @Override
     public boolean unregisterOnSearchCompletedListener(OnSearchCompletedListener listener) {
         return mController.unregisterOnSearchCompletedListener(listener);
     }
 
     /** Registers a new {@link OnBackListener} to the list of listeners. */
+    @Override
     public void registerOnBackListener(OnBackListener listener) {
         mController.registerOnBackListener(listener);
     }
 
     /** Unregisters an existing {@link OnBackListener} from the list of listeners. */
+    @Override
     public boolean unregisterOnBackListener(OnBackListener listener) {
         return mController.unregisterOnBackListener(listener);
     }
 
-    /** Shows the progress bar */
-    public void showProgressBar() {
-        mController.showProgressBar();
-    }
-
-    /** Hides the progress bar */
-    public void hideProgressBar() {
-        mController.hideProgressBar();
-    }
-
     /** Returns the progress bar */
-    public ProgressBar getProgressBar() {
+    @Override
+    public ProgressBarController getProgressBar() {
         return mController.getProgressBar();
     }
 }
diff --git a/car-ui-lib/src/com/android/car/ui/toolbar/ToolbarController.java b/car-ui-lib/src/com/android/car/ui/toolbar/ToolbarController.java
index 2f70ab5..4eb009d 100644
--- a/car-ui-lib/src/com/android/car/ui/toolbar/ToolbarController.java
+++ b/car-ui-lib/src/com/android/car/ui/toolbar/ToolbarController.java
@@ -17,7 +17,6 @@
 package com.android.car.ui.toolbar;
 
 import android.graphics.drawable.Drawable;
-import android.widget.ProgressBar;
 
 import androidx.annotation.DrawableRes;
 import androidx.annotation.NonNull;
@@ -58,6 +57,25 @@
     CharSequence getTitle();
 
     /**
+     * Sets the subtitle of the toolbar to a string resource.
+     *
+     * <p>The title may not always be shown, for example with one row layout with tabs.
+     */
+    void setSubtitle(@StringRes int title);
+
+    /**
+     * Sets the subtitle of the toolbar to a CharSequence.
+     *
+     * <p>The title may not always be shown, for example with one row layout with tabs.
+     */
+    void setSubtitle(CharSequence title);
+
+    /**
+     * Gets the current toolbar subtitle.
+     */
+    CharSequence getSubtitle();
+
+    /**
      * Gets the {@link TabLayout} for this toolbar.
      */
     TabLayout getTabLayout();
@@ -253,12 +271,6 @@
     /** Unregisters an existing {@link Toolbar.OnBackListener} from the list of listeners. */
     boolean unregisterOnBackListener(Toolbar.OnBackListener listener);
 
-    /** Shows the progress bar */
-    void showProgressBar();
-
-    /** Hides the progress bar */
-    void hideProgressBar();
-
-    /** Returns the progress bar */
-    ProgressBar getProgressBar();
+    /** Gets a {@link ProgressBarController} */
+    ProgressBarController getProgressBar();
 }
diff --git a/car-ui-lib/src/com/android/car/ui/toolbar/ToolbarControllerImpl.java b/car-ui-lib/src/com/android/car/ui/toolbar/ToolbarControllerImpl.java
index eb49186..1ef9f4a 100644
--- a/car-ui-lib/src/com/android/car/ui/toolbar/ToolbarControllerImpl.java
+++ b/car-ui-lib/src/com/android/car/ui/toolbar/ToolbarControllerImpl.java
@@ -26,12 +26,12 @@
 import android.app.AlertDialog;
 import android.content.Context;
 import android.graphics.drawable.Drawable;
+import android.text.TextUtils;
 import android.util.Log;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.FrameLayout;
 import android.widget.ImageView;
-import android.widget.ProgressBar;
 import android.widget.TextView;
 
 import androidx.annotation.DrawableRes;
@@ -40,7 +40,11 @@
 import androidx.annotation.StringRes;
 import androidx.annotation.XmlRes;
 
+import com.android.car.ui.AlertDialogBuilder;
 import com.android.car.ui.R;
+import com.android.car.ui.recyclerview.CarUiContentListItem;
+import com.android.car.ui.recyclerview.CarUiListItem;
+import com.android.car.ui.recyclerview.CarUiListItemAdapter;
 import com.android.car.ui.utils.CarUiUtils;
 import com.android.car.ui.utils.CarUxRestrictionsUtil;
 
@@ -63,7 +67,9 @@
     private ImageView mNavIcon;
     private ImageView mLogoInNavIconSpace;
     private ViewGroup mNavIconContainer;
+    private ViewGroup mTitleContainer;
     private TextView mTitle;
+    private TextView mSubtitle;
     private ImageView mTitleLogo;
     private ViewGroup mTitleLogoContainer;
     private TabLayout mTabLayout;
@@ -95,6 +101,8 @@
     @NonNull
     private List<MenuItem> mMenuItems = Collections.emptyList();
     private List<MenuItem> mOverflowItems = new ArrayList<>();
+    private final List<CarUiListItem> mUiOverflowItems = new ArrayList<>();
+    private final CarUiListItemAdapter mOverflowAdapter;
     private final List<MenuItemRenderer> mMenuItemRenderers = new ArrayList<>();
     private View[] mMenuItemViews;
     private int mMenuItemsXmlId = 0;
@@ -102,11 +110,12 @@
     private boolean mNavIconSpaceReserved;
     private boolean mLogoFillsNavIconSpace;
     private boolean mShowLogo;
-    private ProgressBar mProgressBar;
-    private MenuItem.Listener mOverflowItemListener = () -> {
-        createOverflowDialog();
+    private final ProgressBarController mProgressBar;
+    private final MenuItem.Listener mOverflowItemListener = item -> {
+        updateOverflowDialog(item);
         setState(getState());
     };
+
     // Despite the warning, this has to be a field so it's not garbage-collected.
     // The only other reference to it is a weak reference
     private final CarUxRestrictionsUtil.OnUxRestrictionsChangedListener
@@ -116,6 +125,7 @@
                 }
             };
 
+
     public ToolbarControllerImpl(View view) {
         mContext = view.getContext();
         mOverflowButton = MenuItem.builder(getContext())
@@ -140,6 +150,7 @@
                 R.bool.car_ui_toolbar_logo_fills_nav_icon_space);
         mShowLogo = getContext().getResources().getBoolean(
                 R.bool.car_ui_toolbar_show_logo);
+        mSearchHint = getContext().getString(R.string.car_ui_toolbar_default_search_hint);
 
         mBackground = requireViewByRefId(view, R.id.car_ui_toolbar_background);
         mTabLayout = requireViewByRefId(view, R.id.car_ui_toolbar_tabs);
@@ -147,11 +158,14 @@
         mLogoInNavIconSpace = requireViewByRefId(view, R.id.car_ui_toolbar_logo);
         mNavIconContainer = requireViewByRefId(view, R.id.car_ui_toolbar_nav_icon_container);
         mMenuItemsContainer = requireViewByRefId(view, R.id.car_ui_toolbar_menu_items_container);
+        mTitleContainer = requireViewByRefId(view, R.id.car_ui_toolbar_title_container);
+        mSubtitle = requireViewByRefId(view, R.id.car_ui_toolbar_subtitle);
         mTitle = requireViewByRefId(view, R.id.car_ui_toolbar_title);
         mTitleLogoContainer = requireViewByRefId(view, R.id.car_ui_toolbar_title_logo_container);
         mTitleLogo = requireViewByRefId(view, R.id.car_ui_toolbar_title_logo);
         mSearchViewContainer = requireViewByRefId(view, R.id.car_ui_toolbar_search_view_container);
-        mProgressBar = requireViewByRefId(view, R.id.car_ui_toolbar_progress_bar);
+        mProgressBar = new ProgressBarControllerImpl(
+                requireViewByRefId(view, R.id.car_ui_toolbar_progress_bar));
 
         mTabLayout.addListener(new TabLayout.Listener() {
             @Override
@@ -173,6 +187,8 @@
 
         setBackgroundShown(true);
 
+        mOverflowAdapter = new CarUiListItemAdapter(mUiOverflowItems);
+
         // This holds weak references so we don't need to unregister later
         CarUxRestrictionsUtil.getInstance(getContext())
                 .register(mOnUxRestrictionsChangedListener);
@@ -185,6 +201,7 @@
     /**
      * Returns {@code true} if a two row layout in enabled for the toolbar.
      */
+    @Override
     public boolean isTabsInSecondRow() {
         return mIsTabsInSecondRow;
     }
@@ -194,6 +211,7 @@
      *
      * <p>The title may not always be shown, for example with one row layout with tabs.
      */
+    @Override
     public void setTitle(@StringRes int title) {
         mTitle.setText(title);
         setState(getState());
@@ -204,18 +222,48 @@
      *
      * <p>The title may not always be shown, for example with one row layout with tabs.
      */
+    @Override
     public void setTitle(CharSequence title) {
         mTitle.setText(title);
         setState(getState());
     }
 
+    @Override
     public CharSequence getTitle() {
         return mTitle.getText();
     }
 
     /**
+     * Sets the subtitle of the toolbar to a string resource.
+     *
+     * <p>The title may not always be shown, for example with one row layout with tabs.
+     */
+    @Override
+    public void setSubtitle(@StringRes int title) {
+        mSubtitle.setText(title);
+        setState(getState());
+    }
+
+    /**
+     * Sets the subtitle of the toolbar to a CharSequence.
+     *
+     * <p>The title may not always be shown, for example with one row layout with tabs.
+     */
+    @Override
+    public void setSubtitle(CharSequence title) {
+        mSubtitle.setText(title);
+        setState(getState());
+    }
+
+    @Override
+    public CharSequence getSubtitle() {
+        return mSubtitle.getText();
+    }
+
+    /**
      * Gets the {@link TabLayout} for this toolbar.
      */
+    @Override
     public TabLayout getTabLayout() {
         return mTabLayout;
     }
@@ -224,12 +272,14 @@
      * Adds a tab to this toolbar. You can listen for when it is selected via
      * {@link #registerOnTabSelectedListener(Toolbar.OnTabSelectedListener)}.
      */
+    @Override
     public void addTab(TabLayout.Tab tab) {
         mTabLayout.addTab(tab);
         setState(getState());
     }
 
     /** Removes all the tabs. */
+    @Override
     public void clearAllTabs() {
         mTabLayout.clearAllTabs();
         setState(getState());
@@ -239,6 +289,7 @@
      * Gets a tab added to this toolbar. See
      * {@link #addTab(TabLayout.Tab)}.
      */
+    @Override
     public TabLayout.Tab getTab(int position) {
         return mTabLayout.get(position);
     }
@@ -247,6 +298,7 @@
      * Selects a tab added to this toolbar. See
      * {@link #addTab(TabLayout.Tab)}.
      */
+    @Override
     public void selectTab(int position) {
         mTabLayout.selectTab(position);
     }
@@ -254,6 +306,7 @@
     /**
      * Sets whether or not tabs should also be shown in the SUBPAGE {@link Toolbar.State}.
      */
+    @Override
     public void setShowTabsInSubpage(boolean showTabs) {
         if (showTabs != mShowTabsInSubpage) {
             mShowTabsInSubpage = showTabs;
@@ -264,6 +317,7 @@
     /**
      * Gets whether or not tabs should also be shown in the SUBPAGE {@link Toolbar.State}.
      */
+    @Override
     public boolean getShowTabsInSubpage() {
         return mShowTabsInSubpage;
     }
@@ -272,6 +326,7 @@
      * Sets the logo to display in this toolbar. If navigation icon is being displayed, this logo
      * will be displayed next to the title.
      */
+    @Override
     public void setLogo(@DrawableRes int resId) {
         setLogo(resId != 0 ? getContext().getDrawable(resId) : null);
     }
@@ -280,6 +335,7 @@
      * Sets the logo to display in this toolbar. If navigation icon is being displayed, this logo
      * will be displayed next to the title.
      */
+    @Override
     public void setLogo(Drawable drawable) {
         if (!mShowLogo) {
             // If no logo should be shown then we act as if we never received one.
@@ -296,6 +352,7 @@
     }
 
     /** Sets the hint for the search bar. */
+    @Override
     public void setSearchHint(@StringRes int resId) {
         setSearchHint(getContext().getString(resId));
     }
@@ -309,6 +366,7 @@
     }
 
     /** Gets the search hint */
+    @Override
     public CharSequence getSearchHint() {
         return mSearchHint;
     }
@@ -319,6 +377,7 @@
      * <p>The icon will be lost on configuration change, make sure to set it in onCreate() or
      * a similar place.
      */
+    @Override
     public void setSearchIcon(@DrawableRes int resId) {
         setSearchIcon(getContext().getDrawable(resId));
     }
@@ -329,6 +388,7 @@
      * <p>The icon will be lost on configuration change, make sure to set it in onCreate() or
      * a similar place.
      */
+    @Override
     public void setSearchIcon(Drawable d) {
         if (!Objects.equals(d, mSearchIcon)) {
             mSearchIcon = d;
@@ -340,6 +400,7 @@
 
 
     /** Sets the {@link Toolbar.NavButtonMode} */
+    @Override
     public void setNavButtonMode(Toolbar.NavButtonMode style) {
         if (style != mNavButtonMode) {
             mNavButtonMode = style;
@@ -348,11 +409,13 @@
     }
 
     /** Gets the {@link Toolbar.NavButtonMode} */
+    @Override
     public Toolbar.NavButtonMode getNavButtonMode() {
         return mNavButtonMode;
     }
 
     /** Show/hide the background. When hidden, the toolbar is completely transparent. */
+    @Override
     public void setBackgroundShown(boolean shown) {
         if (shown) {
             mBackground.setBackground(
@@ -363,6 +426,7 @@
     }
 
     /** Returns true is the toolbar background is shown */
+    @Override
     public boolean getBackgroundShown() {
         return mBackground.getBackground() != null;
     }
@@ -433,6 +497,7 @@
     /**
      * Sets the {@link MenuItem Menuitems} to display.
      */
+    @Override
     public void setMenuItems(@Nullable List<MenuItem> items) {
         mMenuItemsXmlId = 0;
         setMenuItemsInternal(items);
@@ -467,6 +532,7 @@
      * @return The MenuItems that were loaded from XML.
      * @see #setMenuItems(List)
      */
+    @Override
     public List<MenuItem> setMenuItems(@XmlRes int resId) {
         if (mMenuItemsXmlId != 0 && mMenuItemsXmlId == resId) {
             return mMenuItems;
@@ -479,12 +545,14 @@
     }
 
     /** Gets the {@link MenuItem MenuItems} currently displayed */
+    @Override
     @NonNull
     public List<MenuItem> getMenuItems() {
         return Collections.unmodifiableList(mMenuItems);
     }
 
     /** Gets a {@link MenuItem} by id. */
+    @Override
     @Nullable
     public MenuItem findMenuItemById(int id) {
         for (MenuItem item : mMenuItems) {
@@ -496,6 +564,7 @@
     }
 
     /** Gets a {@link MenuItem} by id. Will throw an IllegalArgumentException if not found. */
+    @Override
     @NonNull
     public MenuItem requireMenuItemById(int id) {
         MenuItem result = findMenuItemById(id);
@@ -518,40 +587,60 @@
     }
 
     private void createOverflowDialog() {
-        // TODO(b/140564530) Use a carui alert with a (car ui)recyclerview here
-        // TODO(b/140563930) Support enabled/disabled overflow items
-
-        CharSequence[] itemTitles = new CharSequence[countVisibleOverflowItems()];
-        int i = 0;
-        for (MenuItem item : mOverflowItems) {
-            if (item.isVisible()) {
-                itemTitles[i++] = item.getTitle();
+        mUiOverflowItems.clear();
+        for (MenuItem menuItem : mOverflowItems) {
+            if (menuItem.isVisible()) {
+                mUiOverflowItems.add(toCarUiContentListItem(menuItem));
             }
         }
 
-        mOverflowDialog = new AlertDialog.Builder(getContext())
-                .setItems(itemTitles, (dialog, which) -> {
-                    MenuItem item = mOverflowItems.get(which);
-                    MenuItem.OnClickListener listener = item.getOnClickListener();
-                    if (listener != null) {
-                        listener.onClick(item);
-                    }
-                })
+        mOverflowDialog = new AlertDialogBuilder(getContext())
+                .setAdapter(mOverflowAdapter)
                 .create();
     }
 
+    private void updateOverflowDialog(MenuItem changedItem) {
+        int itemIndex = mOverflowItems.indexOf(changedItem);
+        if (itemIndex >= 0) {
+            mUiOverflowItems.set(itemIndex, toCarUiContentListItem(changedItem));
+            mOverflowAdapter.notifyItemChanged(itemIndex);
+        } else {
+            createOverflowDialog();
+        }
+    }
+
+    private CarUiContentListItem toCarUiContentListItem(MenuItem menuItem) {
+        CarUiContentListItem carUiItem;
+        if (menuItem.isCheckable()) {
+            carUiItem = new CarUiContentListItem(CarUiContentListItem.Action.SWITCH);
+        } else {
+            carUiItem = new CarUiContentListItem(CarUiContentListItem.Action.NONE);
+        }
+        carUiItem.setIcon(menuItem.getIcon());
+        carUiItem.setActivated(menuItem.isActivated());
+        carUiItem.setChecked(menuItem.isChecked());
+        carUiItem.setEnabled(menuItem.isEnabled());
+        carUiItem.setTitle(menuItem.getTitle());
+        carUiItem.setOnItemClickedListener(item -> {
+            menuItem.performClick();
+            mOverflowDialog.hide();
+        });
+        return carUiItem;
+    }
 
     /**
      * Set whether or not to show the {@link MenuItem MenuItems} while searching. Default false.
      * Even if this is set to true, the {@link MenuItem} created by
      * {@link MenuItem.Builder#setToSearch()} will still be hidden.
      */
+    @Override
     public void setShowMenuItemsWhileSearching(boolean showMenuItems) {
         mShowMenuItemsWhileSearching = showMenuItems;
         setState(mState);
     }
 
     /** Returns if {@link MenuItem MenuItems} are shown while searching */
+    @Override
     public boolean getShowMenuItemsWhileSearching() {
         return mShowMenuItemsWhileSearching;
     }
@@ -559,6 +648,7 @@
     /**
      * Sets the search query.
      */
+    @Override
     public void setSearchQuery(String query) {
         if (mSearchView != null) {
             mSearchView.setSearchQuery(query);
@@ -574,6 +664,7 @@
      * Sets the state of the toolbar. This will show/hide the appropriate elements of the toolbar
      * for the desired state.
      */
+    @Override
     public void setState(Toolbar.State state) {
         mState = state;
 
@@ -654,15 +745,22 @@
         mNavIconContainer.setOnClickListener(
                 state != Toolbar.State.HOME ? backClickListener : null);
         mNavIconContainer.setClickable(state != Toolbar.State.HOME);
+        mNavIconContainer.setContentDescription(state != Toolbar.State.HOME
+                ? mContext.getString(R.string.car_ui_toolbar_nav_icon_content_description)
+                : null);
 
         boolean hasTabs = mTabLayout.getTabCount() > 0
                 && (state == Toolbar.State.HOME
                 || (state == Toolbar.State.SUBPAGE && mShowTabsInSubpage));
         // Show the title if we're in the subpage state, or in the home state with no tabs or tabs
         // on the second row
-        mTitle.setVisibility((state == Toolbar.State.SUBPAGE || state == Toolbar.State.HOME)
+        int visibility = (state == Toolbar.State.SUBPAGE || state == Toolbar.State.HOME)
                 && (!hasTabs || mIsTabsInSecondRow)
-                ? VISIBLE : GONE);
+                ? VISIBLE : GONE;
+        mTitleContainer.setVisibility(visibility);
+        mSubtitle.setVisibility(
+                TextUtils.isEmpty(mSubtitle.getText()) ? GONE : VISIBLE);
+
         mTabLayout.setVisibility(hasTabs ? VISIBLE : GONE);
 
         if (mSearchView != null) {
@@ -681,6 +779,7 @@
     }
 
     /** Gets the current {@link Toolbar.State} of the toolbar. */
+    @Override
     public Toolbar.State getState() {
         return mState;
     }
@@ -693,6 +792,7 @@
      * nothing else. {@link com.android.car.ui.recyclerview.CarUiRecyclerView} will
      * automatically adjust its height according to the height of the Toolbar.
      */
+    @Override
     public void registerToolbarHeightChangeListener(
             Toolbar.OnHeightChangedListener listener) {
         mOnHeightChangedListeners.add(listener);
@@ -702,32 +802,38 @@
      * Unregisters an existing {@link Toolbar.OnHeightChangedListener} from the list of
      * listeners.
      */
+    @Override
     public boolean unregisterToolbarHeightChangeListener(
             Toolbar.OnHeightChangedListener listener) {
         return mOnHeightChangedListeners.remove(listener);
     }
 
     /** Registers a new {@link Toolbar.OnTabSelectedListener} to the list of listeners. */
+    @Override
     public void registerOnTabSelectedListener(Toolbar.OnTabSelectedListener listener) {
         mOnTabSelectedListeners.add(listener);
     }
 
     /** Unregisters an existing {@link Toolbar.OnTabSelectedListener} from the list of listeners. */
+    @Override
     public boolean unregisterOnTabSelectedListener(Toolbar.OnTabSelectedListener listener) {
         return mOnTabSelectedListeners.remove(listener);
     }
 
     /** Registers a new {@link Toolbar.OnSearchListener} to the list of listeners. */
+    @Override
     public void registerOnSearchListener(Toolbar.OnSearchListener listener) {
         mOnSearchListeners.add(listener);
     }
 
     /** Unregisters an existing {@link Toolbar.OnSearchListener} from the list of listeners. */
+    @Override
     public boolean unregisterOnSearchListener(Toolbar.OnSearchListener listener) {
         return mOnSearchListeners.remove(listener);
     }
 
     /** Registers a new {@link Toolbar.OnSearchCompletedListener} to the list of listeners. */
+    @Override
     public void registerOnSearchCompletedListener(Toolbar.OnSearchCompletedListener listener) {
         mOnSearchCompletedListeners.add(listener);
     }
@@ -736,32 +842,26 @@
      * Unregisters an existing {@link Toolbar.OnSearchCompletedListener} from the list of
      * listeners.
      */
+    @Override
     public boolean unregisterOnSearchCompletedListener(Toolbar.OnSearchCompletedListener listener) {
         return mOnSearchCompletedListeners.remove(listener);
     }
 
     /** Registers a new {@link Toolbar.OnBackListener} to the list of listeners. */
+    @Override
     public void registerOnBackListener(Toolbar.OnBackListener listener) {
         mOnBackListeners.add(listener);
     }
 
     /** Unregisters an existing {@link Toolbar.OnBackListener} from the list of listeners. */
+    @Override
     public boolean unregisterOnBackListener(Toolbar.OnBackListener listener) {
         return mOnBackListeners.remove(listener);
     }
 
-    /** Shows the progress bar */
-    public void showProgressBar() {
-        mProgressBar.setVisibility(View.VISIBLE);
-    }
-
-    /** Hides the progress bar */
-    public void hideProgressBar() {
-        mProgressBar.setVisibility(View.GONE);
-    }
-
     /** Returns the progress bar */
-    public ProgressBar getProgressBar() {
+    @Override
+    public ProgressBarController getProgressBar() {
         return mProgressBar;
     }
 }
diff --git a/car-ui-lib/src/com/android/car/ui/utils/CarUiUtils.java b/car-ui-lib/src/com/android/car/ui/utils/CarUiUtils.java
index 54d64f1..93cf868 100644
--- a/car-ui-lib/src/com/android/car/ui/utils/CarUiUtils.java
+++ b/car-ui-lib/src/com/android/car/ui/utils/CarUiUtils.java
@@ -20,8 +20,10 @@
 import android.content.ContextWrapper;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
+import android.graphics.drawable.Drawable;
 import android.util.TypedValue;
 import android.view.View;
+import android.view.ViewGroup;
 
 import androidx.annotation.DimenRes;
 import androidx.annotation.IdRes;
@@ -29,13 +31,15 @@
 import androidx.annotation.Nullable;
 import androidx.annotation.StyleRes;
 import androidx.annotation.UiThread;
+import androidx.core.view.ViewCompat;
 
 /**
  * Collection of utility methods
  */
 public final class CarUiUtils {
     /** This is a utility class */
-    private CarUiUtils() {}
+    private CarUiUtils() {
+    }
 
     /**
      * Reads a float value from a dimens resource. This is necessary as {@link Resources#getFloat}
@@ -84,6 +88,70 @@
     }
 
     /**
+     * Updates the preference view enabled state. If the view is disabled we just disable the child
+     * of preference like TextView, ImageView. The preference itself is always enabled to get the
+     * click events. Ripple effect in background is also removed by default. If the ripple is
+     * needed see
+     * {@link IDisabledPreferenceCallback#setShouldShowRippleOnDisabledPreference(boolean)}
+     */
+    public static Drawable setPreferenceViewEnabled(boolean viewEnabled, View itemView,
+            Drawable background, boolean shouldShowRippleOnDisabledPreference) {
+        if (viewEnabled) {
+            if (background != null) {
+                ViewCompat.setBackground(itemView, background);
+            }
+            setChildViewsEnabled(itemView, true, false);
+        } else {
+            itemView.setEnabled(true);
+            if (background == null) {
+                // store the original background.
+                background = itemView.getBackground();
+            }
+            updateRippleStateOnDisabledPreference(false, shouldShowRippleOnDisabledPreference,
+                    background, itemView);
+            setChildViewsEnabled(itemView, false, true);
+        }
+        return background;
+    }
+
+    /**
+     * Sets the enabled state on the views of the preference. If the view is being disabled we want
+     * only child views of preference to be disabled.
+     */
+    private static void setChildViewsEnabled(View view, boolean enabled, boolean isRootView) {
+        if (!isRootView) {
+            view.setEnabled(enabled);
+        }
+        if (view instanceof ViewGroup) {
+            ViewGroup grp = (ViewGroup) view;
+            for (int index = 0; index < grp.getChildCount(); index++) {
+                setChildViewsEnabled(grp.getChildAt(index), enabled, false);
+            }
+        }
+    }
+
+    /**
+     * Updates the ripple state on the given preference.
+     *
+     * @param isEnabled whether the preference is enabled or not
+     * @param shouldShowRippleOnDisabledPreference should ripple be displayed when the preference is
+     * clicked
+     * @param background drawable that represents the ripple
+     * @param preference preference on which drawable will be applied
+     */
+    public static void updateRippleStateOnDisabledPreference(boolean isEnabled,
+            boolean shouldShowRippleOnDisabledPreference, Drawable background, View preference) {
+        if (isEnabled || preference == null) {
+            return;
+        }
+        if (shouldShowRippleOnDisabledPreference && background != null) {
+            ViewCompat.setBackground(preference, background);
+        } else {
+            ViewCompat.setBackground(preference, null);
+        }
+    }
+
+    /**
      * It behaves similar to @see View#findViewById, except it resolves the ID reference first.
      *
      * @param id the ID to search for
@@ -114,7 +182,9 @@
     public static <T extends View> T requireViewByRefId(@NonNull View root, @IdRes int id) {
         T view = findViewByRefId(root, id);
         if (view == null) {
-            throw new IllegalArgumentException("ID does not reference a View inside this View");
+            throw new IllegalArgumentException("ID "
+                    + root.getResources().getResourceName(id)
+                    + " does not reference a View inside this View");
         }
         return view;
     }
diff --git a/car-ui-lib/src/com/android/car/ui/utils/CarUxRestrictionsUtil.java b/car-ui-lib/src/com/android/car/ui/utils/CarUxRestrictionsUtil.java
index 31ac24a..e5c7fc9 100644
--- a/car-ui-lib/src/com/android/car/ui/utils/CarUxRestrictionsUtil.java
+++ b/car-ui-lib/src/com/android/car/ui/utils/CarUxRestrictionsUtil.java
@@ -18,7 +18,6 @@
 import static android.car.drivingstate.CarUxRestrictions.UX_RESTRICTIONS_LIMIT_STRING_LENGTH;
 
 import android.car.Car;
-import android.car.CarNotConnectedException;
 import android.car.drivingstate.CarUxRestrictions;
 import android.car.drivingstate.CarUxRestrictions.CarUxRestrictionsInfo;
 import android.car.drivingstate.CarUxRestrictionsManager;
@@ -35,6 +34,10 @@
 import java.util.Set;
 import java.util.WeakHashMap;
 
+// This can't be in the middle of the rest of the imports on gerrit or it will
+// fail our style checks
+// copybara:insert import android.car.CarNotConnectedException;
+
 /**
  * Utility class to access Car Restriction Manager.
  *
@@ -45,12 +48,15 @@
 public class CarUxRestrictionsUtil {
     private static final String TAG = "CarUxRestrictionsUtil";
 
+    /* copybara:insert
     private final Car mCarApi;
     private CarUxRestrictionsManager mCarUxRestrictionsManager;
+    */
     @NonNull
     private CarUxRestrictions mCarUxRestrictions = getDefaultRestrictions();
 
-    private Set<OnUxRestrictionsChangedListener> mObservers;
+    private final Set<OnUxRestrictionsChangedListener> mObservers =
+            Collections.newSetFromMap(new WeakHashMap<>());
     private static CarUxRestrictionsUtil sInstance = null;
 
     private CarUxRestrictionsUtil(Context context) {
@@ -67,8 +73,23 @@
                     }
                 };
 
+        // copybara:strip_begin
+        Car.createCar(context.getApplicationContext(), null, Car.CAR_WAIT_TIMEOUT_DO_NOT_WAIT,
+                (Car car, boolean ready) -> {
+                    if (ready) {
+                        CarUxRestrictionsManager carUxRestrictionsManager =
+                                (CarUxRestrictionsManager) car.getCarManager(
+                                        Car.CAR_UX_RESTRICTION_SERVICE);
+                        carUxRestrictionsManager.registerListener(listener);
+                        listener.onUxRestrictionsChanged(
+                                carUxRestrictionsManager.getCurrentCarUxRestrictions());
+                    } else {
+                        Log.w(TAG, "Car service disconnected, assuming fully restricted uxr");
+                        listener.onUxRestrictionsChanged(null);
+                    }
+                });
+        /* copybara:strip_end_and_replace
         mCarApi = Car.createCar(context.getApplicationContext());
-        mObservers = Collections.newSetFromMap(new WeakHashMap<>());
 
         try {
             mCarUxRestrictionsManager =
@@ -81,6 +102,7 @@
             Log.e(TAG, "Car not connected", e);
             // mCarUxRestrictions will be the default
         }
+        */
     }
 
     @NonNull
diff --git a/car-ui-lib/src/com/android/car/ui/utils/DirectManipulationHelper.java b/car-ui-lib/src/com/android/car/ui/utils/DirectManipulationHelper.java
new file mode 100644
index 0000000..24a32d1
--- /dev/null
+++ b/car-ui-lib/src/com/android/car/ui/utils/DirectManipulationHelper.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.car.ui.utils;
+
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.text.TextUtils;
+import android.view.View;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityManager;
+import android.view.accessibility.AccessibilityNodeInfo;
+
+import androidx.annotation.NonNull;
+
+import java.lang.reflect.Method;
+
+/** Helper class to toggle direct manipulation mode. */
+public final class DirectManipulationHelper {
+
+    /**
+     * StateDescription for a {@link View} to support direct manipulation mode. It's also used as
+     * class name of {@link AccessibilityEvent} to indicate that the AccessibilityEvent represents
+     * a request to toggle direct manipulation mode.
+     */
+    private static final String DIRECT_MANIPULATION =
+            "com.android.car.ui.utils.DIRECT_MANIPULATION";
+
+    /** This is a utility class. */
+    private DirectManipulationHelper() {
+    }
+
+    /**
+     * Enables or disables direct manipulation mode. This method sends an {@link AccessibilityEvent}
+     * to tell {@link com.android.car.rotary.RotaryService} to enter or exit direct manipulation
+     * mode. Typically pressing the center button of the rotary controller with a direct
+     * manipulation view focused will enter direct manipulation mode, while pressing the Back button
+     * will exit direct manipulation mode.
+     *
+     * @param view   the direct manipulation view
+     * @param enable true to enter direct manipulation mode, false to exit direct manipulation mode
+     * @return whether the AccessibilityEvent was sent
+     */
+    public static boolean enableDirectManipulationMode(@NonNull View view, boolean enable) {
+        AccessibilityManager accessibilityManager = (AccessibilityManager)
+                view.getContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
+        if (accessibilityManager == null || !accessibilityManager.isEnabled()) {
+            return false;
+        }
+        AccessibilityEvent event = AccessibilityEvent.obtain();
+        event.setClassName(DIRECT_MANIPULATION);
+        event.setSource(view);
+        event.setEventType(enable
+                ? AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
+                : AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
+        accessibilityManager.sendAccessibilityEvent(event);
+        return true;
+    }
+
+    /** Returns whether the given {@code event} is for direct manipulation. */
+    public static boolean isDirectManipulation(@NonNull AccessibilityEvent event) {
+        return TextUtils.equals(DIRECT_MANIPULATION, event.getClassName());
+    }
+
+    /** Returns whether the given {@code node} supports direct manipulation. */
+    @TargetApi(30)
+    public static boolean supportDirectManipulation(@NonNull AccessibilityNodeInfo node) {
+        try {
+            // TODO(b/156115044): remove the reflection once Android R sdk is publicly released.
+            Method getStateDescription =
+                    AccessibilityNodeInfo.class.getMethod("getStateDescription");
+            CharSequence stateDescription = (CharSequence) getStateDescription.invoke(node);
+            return TextUtils.equals(DIRECT_MANIPULATION, stateDescription);
+        } catch (ReflectiveOperationException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /** Sets whether the given {@code view} supports direct manipulation. */
+    @TargetApi(30)
+    public static void setSupportsDirectManipulation(@NonNull View view, boolean enable) {
+        try {
+            // TODO(b/156115044): remove the reflection once Android R sdk is publicly released.
+            Method setStateDescription =
+                    View.class.getMethod("setStateDescription", CharSequence.class);
+            CharSequence stateDescription = enable ? DIRECT_MANIPULATION : null;
+            setStateDescription.invoke(view, stateDescription);
+        } catch (ReflectiveOperationException e) {
+            throw new RuntimeException(e);
+        }
+    }
+}
diff --git a/car-ui-lib/src/com/android/car/ui/utils/RotaryConstants.java b/car-ui-lib/src/com/android/car/ui/utils/RotaryConstants.java
new file mode 100644
index 0000000..cb418bb
--- /dev/null
+++ b/car-ui-lib/src/com/android/car/ui/utils/RotaryConstants.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.car.ui.utils;
+
+/** Constants for the rotary controller. */
+public final class RotaryConstants {
+    /**
+     * Content description indicating that the rotary controller should scroll this view
+     * horizontally.
+     */
+    public static final String ROTARY_HORIZONTALLY_SCROLLABLE =
+            "android.rotary.HORIZONTALLY_SCROLLABLE";
+
+    /**
+     * Content description indicating that the rotary controller should scroll this view
+     * vertically.
+     */
+    public static final String ROTARY_VERTICALLY_SCROLLABLE =
+            "android.rotary.VERTICALLY_SCROLLABLE";
+
+    /** Prevent instantiation. */
+    private RotaryConstants() {}
+}
diff --git a/car-ui-lib/tests/apitest/auto-generate-resources.py b/car-ui-lib/tests/apitest/auto-generate-resources.py
index 9645ef5..1fcd866 100755
--- a/car-ui-lib/tests/apitest/auto-generate-resources.py
+++ b/car-ui-lib/tests/apitest/auto-generate-resources.py
@@ -17,7 +17,7 @@
 import argparse
 import os
 import sys
-from resource_utils import get_all_resources, get_resources_from_single_file, remove_layout_resources
+from resource_utils import get_all_resources, get_resources_from_single_file, add_resource_to_set, Resource
 from git_utils import has_chassis_changes
 
 # path to 'packages/apps/Car/libs/car-ui-lib/'
@@ -50,7 +50,7 @@
         generate_current_file(ROOT_FOLDER+'/res', output_file)
 
 def generate_current_file(res_folder, output_file='current.xml'):
-    resources = remove_layout_resources(get_all_resources(res_folder))
+    resources = get_all_resources(res_folder)
     resources = sorted(resources, key=lambda x: x.type + x.name)
 
     # defer importing lxml to here so that people who aren't editing chassis don't have to have
@@ -70,10 +70,68 @@
     with open(OUTPUT_FILE_PATH + output_file, 'w') as f:
         data.write(f, pretty_print=True, xml_declaration=True, encoding='utf-8')
 
+def generate_overlayable_file(res_folder):
+    resources = get_all_resources(res_folder)
+    # We need these to be able to use base layouts in RROs
+    # This should become unnecessary in S
+    add_resource_to_set(resources, Resource('layout_constraintGuide_begin', 'attr'))
+    add_resource_to_set(resources, Resource('layout_constraintGuide_end', 'attr'))
+    add_resource_to_set(resources, Resource('layout_constraintHorizontal_bias', 'attr'))
+    add_resource_to_set(resources, Resource('layout_constraintTop_toTopOf', 'attr'))
+    add_resource_to_set(resources, Resource('layout_constraintTop_toBottomOf', 'attr'))
+    add_resource_to_set(resources, Resource('layout_constraintBottom_toBottomOf', 'attr'))
+    add_resource_to_set(resources, Resource('layout_constraintBottom_toTopOf', 'attr'))
+    add_resource_to_set(resources, Resource('layout_constraintStart_toStartOf', 'attr'))
+    add_resource_to_set(resources, Resource('layout_constraintStart_toEndOf', 'attr'))
+    add_resource_to_set(resources, Resource('layout_constraintEnd_toEndOf', 'attr'))
+    add_resource_to_set(resources, Resource('layout_constraintEnd_toStartOf', 'attr'))
+    add_resource_to_set(resources, Resource('layout_constraintLeft_toLeftOf', 'attr'))
+    add_resource_to_set(resources, Resource('layout_constraintLeft_toRightOf', 'attr'))
+    add_resource_to_set(resources, Resource('layout_constraintRight_toRightOf', 'attr'))
+    add_resource_to_set(resources, Resource('layout_constraintRight_toLeftOf', 'attr'))
+    resources = sorted(resources, key=lambda x: x.type + x.name)
+
+    # defer importing lxml to here so that people who aren't editing chassis don't have to have
+    # lxml installed
+    import lxml.etree as etree
+
+    root = etree.Element('resources')
+
+    root.addprevious(etree.Comment(' Copyright (C) 2020 The Android Open Source Project\n\n' +
+
+                                   '     Licensed under the Apache License, Version 2.0 (the "License");\n' +
+                                   '     you may not use this file except in compliance with the License.\n' +
+                                   '     You may obtain a copy of the License at\n\n' +
+
+                                   '     http://www.apache.org/licenses/LICENSE-2.0\n\n'
+
+                                   '     Unless required by applicable law or agreed to in writing, software\n'
+                                   '     distributed under the License is distributed on an "AS IS" BASIS,\n'
+                                   '     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n'
+                                   '     See the License for the specific language governing permissions and\n'
+                                   '     limitations under the License.\n'))
+
+    overlayable = etree.SubElement(root, 'overlayable')
+    overlayable.set('name', 'CarUiLibOverlayableResources')
+
+    policy = etree.SubElement(overlayable, 'policy')
+    policy.set('type', 'public')
+
+    for resource in resources:
+        item = etree.SubElement(policy, 'item')
+        item.set('type', resource.type)
+        item.set('name', resource.name)
+
+    data = etree.ElementTree(root)
+
+    output_file=ROOT_FOLDER+'/res/values/overlayable.xml'
+    with open(output_file, 'w') as f:
+        data.write(f, pretty_print=True, xml_declaration=True, encoding='utf-8')
+
 def compare_resources(res_folder, res_public_file):
     old_mapping = get_resources_from_single_file(res_public_file)
 
-    new_mapping = remove_layout_resources(get_all_resources(res_folder))
+    new_mapping = get_all_resources(res_folder)
 
     removed = old_mapping.difference(new_mapping)
     added = new_mapping.difference(old_mapping)
diff --git a/car-ui-lib/tests/apitest/current.xml b/car-ui-lib/tests/apitest/current.xml
index 3856c54..0731374 100644
--- a/car-ui-lib/tests/apitest/current.xml
+++ b/car-ui-lib/tests/apitest/current.xml
@@ -5,6 +5,8 @@
   <public type="attr" name="carUiPreferenceStyle"/>
   <public type="attr" name="carUiRecyclerViewStyle"/>
   <public type="attr" name="state_ux_restricted"/>
+  <public type="bool" name="car_ui_enable_focus_area_background_highlight"/>
+  <public type="bool" name="car_ui_enable_focus_area_foreground_highlight"/>
   <public type="bool" name="car_ui_list_item_single_line_title"/>
   <public type="bool" name="car_ui_preference_list_show_full_screen"/>
   <public type="bool" name="car_ui_preference_show_chevron"/>
@@ -16,18 +18,13 @@
   <public type="bool" name="car_ui_toolbar_tabs_on_second_row"/>
   <public type="color" name="car_ui_activity_background_color"/>
   <public type="color" name="car_ui_color_accent"/>
-  <public type="color" name="car_ui_list_item_body_text_color"/>
+  <public type="color" name="car_ui_dialog_icon_color"/>
   <public type="color" name="car_ui_list_item_divider"/>
-  <public type="color" name="car_ui_list_item_header_text_color"/>
-  <public type="color" name="car_ui_list_item_title_text_color"/>
-  <public type="color" name="car_ui_preference_category_title_text_color"/>
-  <public type="color" name="car_ui_preference_edit_text_dialog_message_text_color"/>
   <public type="color" name="car_ui_preference_icon_color"/>
-  <public type="color" name="car_ui_preference_summary_text_color"/>
-  <public type="color" name="car_ui_preference_switch_track_text_color"/>
-  <public type="color" name="car_ui_preference_title_text_color"/>
+  <public type="color" name="car_ui_preference_two_action_divider_color"/>
   <public type="color" name="car_ui_recyclerview_divider_color"/>
   <public type="color" name="car_ui_ripple_color"/>
+  <public type="color" name="car_ui_rotary_focus_color"/>
   <public type="color" name="car_ui_scrollbar_thumb"/>
   <public type="color" name="car_ui_text_color_hint"/>
   <public type="color" name="car_ui_text_color_primary"/>
@@ -50,17 +47,12 @@
   <public type="dimen" name="car_ui_dialog_edittext_margin_top"/>
   <public type="dimen" name="car_ui_dialog_icon_size"/>
   <public type="dimen" name="car_ui_dialog_title_margin"/>
-  <public type="dimen" name="car_ui_keyline_1"/>
-  <public type="dimen" name="car_ui_keyline_2"/>
-  <public type="dimen" name="car_ui_keyline_3"/>
-  <public type="dimen" name="car_ui_keyline_4"/>
-  <public type="dimen" name="car_ui_letter_spacing_body1"/>
-  <public type="dimen" name="car_ui_letter_spacing_body3"/>
+  <public type="dimen" name="car_ui_divider_width"/>
+  <public type="dimen" name="car_ui_header_list_item_text_start_margin"/>
   <public type="dimen" name="car_ui_list_item_action_divider_height"/>
   <public type="dimen" name="car_ui_list_item_action_divider_width"/>
   <public type="dimen" name="car_ui_list_item_avatar_icon_height"/>
   <public type="dimen" name="car_ui_list_item_avatar_icon_width"/>
-  <public type="dimen" name="car_ui_list_item_body_text_size"/>
   <public type="dimen" name="car_ui_list_item_check_box_end_inset"/>
   <public type="dimen" name="car_ui_list_item_check_box_height"/>
   <public type="dimen" name="car_ui_list_item_check_box_icon_container_width"/>
@@ -70,7 +62,6 @@
   <public type="dimen" name="car_ui_list_item_end_inset"/>
   <public type="dimen" name="car_ui_list_item_header_height"/>
   <public type="dimen" name="car_ui_list_item_header_start_inset"/>
-  <public type="dimen" name="car_ui_list_item_header_text_size"/>
   <public type="dimen" name="car_ui_list_item_height"/>
   <public type="dimen" name="car_ui_list_item_icon_container_width"/>
   <public type="dimen" name="car_ui_list_item_icon_size"/>
@@ -82,7 +73,6 @@
   <public type="dimen" name="car_ui_list_item_supplemental_icon_size"/>
   <public type="dimen" name="car_ui_list_item_text_no_icon_start_margin"/>
   <public type="dimen" name="car_ui_list_item_text_start_margin"/>
-  <public type="dimen" name="car_ui_list_item_title_text_size"/>
   <public type="dimen" name="car_ui_margin"/>
   <public type="dimen" name="car_ui_padding_0"/>
   <public type="dimen" name="car_ui_padding_1"/>
@@ -94,7 +84,6 @@
   <public type="dimen" name="car_ui_preference_category_icon_margin_end"/>
   <public type="dimen" name="car_ui_preference_category_icon_size"/>
   <public type="dimen" name="car_ui_preference_category_min_height"/>
-  <public type="dimen" name="car_ui_preference_category_text_size"/>
   <public type="dimen" name="car_ui_preference_content_margin_bottom"/>
   <public type="dimen" name="car_ui_preference_content_margin_top"/>
   <public type="dimen" name="car_ui_preference_dropdown_padding_start"/>
@@ -103,17 +92,10 @@
   <public type="dimen" name="car_ui_preference_edit_text_dialog_message_margin_bottom"/>
   <public type="dimen" name="car_ui_preference_edit_text_dialog_message_margin_end"/>
   <public type="dimen" name="car_ui_preference_edit_text_dialog_message_margin_start"/>
-  <public type="dimen" name="car_ui_preference_edit_text_dialog_message_text_size"/>
   <public type="dimen" name="car_ui_preference_edit_text_dialog_text_margin_end"/>
   <public type="dimen" name="car_ui_preference_edit_text_dialog_text_margin_start"/>
   <public type="dimen" name="car_ui_preference_icon_margin_end"/>
   <public type="dimen" name="car_ui_preference_icon_size"/>
-  <public type="dimen" name="car_ui_preference_summary_text_size"/>
-  <public type="dimen" name="car_ui_preference_switch_height"/>
-  <public type="dimen" name="car_ui_preference_switch_text_size"/>
-  <public type="dimen" name="car_ui_preference_switch_width"/>
-  <public type="dimen" name="car_ui_preference_switch_width_half"/>
-  <public type="dimen" name="car_ui_preference_title_text_size"/>
   <public type="dimen" name="car_ui_primary_icon_size"/>
   <public type="dimen" name="car_ui_recyclerview_divider_bottom_margin"/>
   <public type="dimen" name="car_ui_recyclerview_divider_end_margin"/>
@@ -126,11 +108,14 @@
   <public type="dimen" name="car_ui_scrollbar_deceleration_times_divisor"/>
   <public type="dimen" name="car_ui_scrollbar_margin"/>
   <public type="dimen" name="car_ui_scrollbar_milliseconds_per_inch"/>
-  <public type="dimen" name="car_ui_scrollbar_padding_end"/>
-  <public type="dimen" name="car_ui_scrollbar_padding_start"/>
+  <public type="dimen" name="car_ui_scrollbar_padding_bottom"/>
+  <public type="dimen" name="car_ui_scrollbar_padding_top"/>
   <public type="dimen" name="car_ui_scrollbar_separator_margin"/>
   <public type="dimen" name="car_ui_scrollbar_thumb_radius"/>
   <public type="dimen" name="car_ui_scrollbar_thumb_width"/>
+  <public type="dimen" name="car_ui_sub1_size"/>
+  <public type="dimen" name="car_ui_sub2_size"/>
+  <public type="dimen" name="car_ui_sub3_size"/>
   <public type="dimen" name="car_ui_toolbar_bottom_inset"/>
   <public type="dimen" name="car_ui_toolbar_bottom_view_height"/>
   <public type="dimen" name="car_ui_toolbar_end_inset"/>
@@ -157,16 +142,24 @@
   <public type="dimen" name="car_ui_toolbar_tab_text_width"/>
   <public type="dimen" name="car_ui_toolbar_title_logo_padding"/>
   <public type="dimen" name="car_ui_toolbar_title_margin_start"/>
+  <public type="dimen" name="car_ui_toolbar_title_no_logo_margin_start"/>
   <public type="dimen" name="car_ui_toolbar_top_inset"/>
   <public type="dimen" name="car_ui_touch_target_height"/>
+  <public type="dimen" name="car_ui_touch_target_size"/>
   <public type="dimen" name="car_ui_touch_target_width"/>
   <public type="dimen" name="wrap_content"/>
   <public type="drawable" name="car_ui_activity_background"/>
   <public type="drawable" name="car_ui_divider"/>
+  <public type="drawable" name="car_ui_focus_area_background_highlight"/>
+  <public type="drawable" name="car_ui_focus_area_foreground_highlight"/>
+  <public type="drawable" name="car_ui_icon_add"/>
   <public type="drawable" name="car_ui_icon_arrow_back"/>
   <public type="drawable" name="car_ui_icon_close"/>
+  <public type="drawable" name="car_ui_icon_delete"/>
   <public type="drawable" name="car_ui_icon_down"/>
+  <public type="drawable" name="car_ui_icon_edit"/>
   <public type="drawable" name="car_ui_icon_overflow_menu"/>
+  <public type="drawable" name="car_ui_icon_save"/>
   <public type="drawable" name="car_ui_icon_search"/>
   <public type="drawable" name="car_ui_icon_search_nav_icon"/>
   <public type="drawable" name="car_ui_icon_settings"/>
@@ -188,14 +181,130 @@
   <public type="drawable" name="car_ui_toolbar_menu_item_icon_ripple"/>
   <public type="drawable" name="car_ui_toolbar_search_close_icon"/>
   <public type="drawable" name="car_ui_toolbar_search_search_icon"/>
+  <public type="id" name="action_container"/>
+  <public type="id" name="action_container_touch_interceptor"/>
+  <public type="id" name="action_divider"/>
+  <public type="id" name="action_widget_container"/>
+  <public type="id" name="avatar_icon"/>
+  <public type="id" name="body"/>
+  <public type="id" name="car_ui_alert_icon"/>
+  <public type="id" name="car_ui_alert_subtitle"/>
+  <public type="id" name="car_ui_alert_title"/>
+  <public type="id" name="car_ui_check_box_end_guideline"/>
+  <public type="id" name="car_ui_check_box_start_guideline"/>
+  <public type="id" name="car_ui_list_item_end_guideline"/>
+  <public type="id" name="car_ui_list_item_start_guideline"/>
+  <public type="id" name="car_ui_preference_fragment_container"/>
+  <public type="id" name="car_ui_recycler_view"/>
+  <public type="id" name="car_ui_scroll_bar"/>
+  <public type="id" name="car_ui_scrollbar_page_down"/>
+  <public type="id" name="car_ui_scrollbar_page_up"/>
+  <public type="id" name="car_ui_scrollbar_thumb"/>
+  <public type="id" name="car_ui_scrollbar_track"/>
+  <public type="id" name="car_ui_toolbar"/>
+  <public type="id" name="car_ui_toolbar_background"/>
+  <public type="id" name="car_ui_toolbar_bottom_guideline"/>
+  <public type="id" name="car_ui_toolbar_bottom_styleable"/>
+  <public type="id" name="car_ui_toolbar_end_guideline"/>
+  <public type="id" name="car_ui_toolbar_logo"/>
+  <public type="id" name="car_ui_toolbar_menu_item_icon"/>
+  <public type="id" name="car_ui_toolbar_menu_item_icon_container"/>
+  <public type="id" name="car_ui_toolbar_menu_item_switch"/>
+  <public type="id" name="car_ui_toolbar_menu_item_text"/>
+  <public type="id" name="car_ui_toolbar_menu_item_text_with_icon"/>
+  <public type="id" name="car_ui_toolbar_menu_items_container"/>
+  <public type="id" name="car_ui_toolbar_nav_icon"/>
+  <public type="id" name="car_ui_toolbar_nav_icon_container"/>
+  <public type="id" name="car_ui_toolbar_progress_bar"/>
+  <public type="id" name="car_ui_toolbar_row_separator"/>
+  <public type="id" name="car_ui_toolbar_row_separator_guideline"/>
+  <public type="id" name="car_ui_toolbar_search_bar"/>
+  <public type="id" name="car_ui_toolbar_search_close"/>
+  <public type="id" name="car_ui_toolbar_search_icon"/>
+  <public type="id" name="car_ui_toolbar_search_view_container"/>
+  <public type="id" name="car_ui_toolbar_start_guideline"/>
+  <public type="id" name="car_ui_toolbar_subtitle"/>
+  <public type="id" name="car_ui_toolbar_tab_item_icon"/>
+  <public type="id" name="car_ui_toolbar_tab_item_text"/>
+  <public type="id" name="car_ui_toolbar_tabs"/>
+  <public type="id" name="car_ui_toolbar_title"/>
+  <public type="id" name="car_ui_toolbar_title_container"/>
+  <public type="id" name="car_ui_toolbar_title_logo"/>
+  <public type="id" name="car_ui_toolbar_title_logo_container"/>
+  <public type="id" name="car_ui_toolbar_top_guideline"/>
+  <public type="id" name="check_box_container"/>
+  <public type="id" name="checkbox"/>
+  <public type="id" name="checkbox_widget"/>
+  <public type="id" name="container"/>
+  <public type="id" name="content"/>
+  <public type="id" name="content_icon"/>
+  <public type="id" name="icon"/>
+  <public type="id" name="icon_container"/>
+  <public type="id" name="list"/>
+  <public type="id" name="nested_recycler_view_layout"/>
+  <public type="id" name="radio_button"/>
+  <public type="id" name="radio_button_widget"/>
+  <public type="id" name="recycler_view"/>
+  <public type="id" name="reduced_touch_interceptor"/>
   <public type="id" name="search"/>
+  <public type="id" name="seek_bar"/>
+  <public type="id" name="seek_bar_text_left"/>
+  <public type="id" name="seek_bar_text_right"/>
+  <public type="id" name="seek_bar_text_top"/>
+  <public type="id" name="seekbar"/>
+  <public type="id" name="seekbar_value"/>
+  <public type="id" name="spinner"/>
+  <public type="id" name="supplemental_icon"/>
+  <public type="id" name="switch_widget"/>
+  <public type="id" name="text"/>
+  <public type="id" name="textbox"/>
+  <public type="id" name="title"/>
+  <public type="id" name="title_template"/>
+  <public type="id" name="toolbar"/>
+  <public type="id" name="touch_interceptor"/>
   <public type="integer" name="car_ui_default_max_string_length"/>
+  <public type="integer" name="car_ui_scrollbar_longpress_initial_delay"/>
+  <public type="integer" name="car_ui_scrollbar_longpress_repeat_interval"/>
+  <public type="layout" name="car_ui_alert_dialog_edit_text"/>
+  <public type="layout" name="car_ui_alert_dialog_list"/>
+  <public type="layout" name="car_ui_alert_dialog_title_with_subtitle"/>
+  <public type="layout" name="car_ui_base_layout"/>
+  <public type="layout" name="car_ui_base_layout_toolbar"/>
+  <public type="layout" name="car_ui_base_layout_toolbar_legacy"/>
+  <public type="layout" name="car_ui_check_box_list_item"/>
+  <public type="layout" name="car_ui_header_list_item"/>
+  <public type="layout" name="car_ui_list_item"/>
+  <public type="layout" name="car_ui_list_preference"/>
+  <public type="layout" name="car_ui_list_preference_with_toolbar"/>
+  <public type="layout" name="car_ui_preference"/>
+  <public type="layout" name="car_ui_preference_category"/>
+  <public type="layout" name="car_ui_preference_chevron"/>
+  <public type="layout" name="car_ui_preference_dialog_edittext"/>
+  <public type="layout" name="car_ui_preference_dropdown"/>
+  <public type="layout" name="car_ui_preference_fragment"/>
+  <public type="layout" name="car_ui_preference_fragment_with_toolbar"/>
+  <public type="layout" name="car_ui_preference_widget_checkbox"/>
+  <public type="layout" name="car_ui_preference_widget_seekbar"/>
+  <public type="layout" name="car_ui_preference_widget_switch"/>
+  <public type="layout" name="car_ui_radio_button_preference_widget"/>
+  <public type="layout" name="car_ui_recycler_view"/>
+  <public type="layout" name="car_ui_recycler_view_item"/>
+  <public type="layout" name="car_ui_recyclerview_scrollbar"/>
+  <public type="layout" name="car_ui_seekbar_dialog"/>
+  <public type="layout" name="car_ui_toolbar"/>
+  <public type="layout" name="car_ui_toolbar_menu_item"/>
+  <public type="layout" name="car_ui_toolbar_search_view"/>
+  <public type="layout" name="car_ui_toolbar_tab_item"/>
+  <public type="layout" name="car_ui_toolbar_tab_item_flexible"/>
+  <public type="layout" name="car_ui_toolbar_tab_item_layout"/>
+  <public type="layout" name="car_ui_toolbar_tab_item_layout_flexible"/>
+  <public type="layout" name="car_ui_toolbar_two_row"/>
+  <public type="layout" name="car_ui_two_action_preference"/>
   <public type="string" name="car_ui_alert_dialog_default_button"/>
   <public type="string" name="car_ui_dialog_preference_negative"/>
   <public type="string" name="car_ui_dialog_preference_positive"/>
   <public type="string" name="car_ui_ellipsis"/>
-  <public type="string" name="car_ui_list_item_header_font_family"/>
-  <public type="string" name="car_ui_preference_category_title_font_family"/>
+  <public type="string" name="car_ui_installer_process_name"/>
   <public type="string" name="car_ui_preference_switch_off"/>
   <public type="string" name="car_ui_preference_switch_on"/>
   <public type="string" name="car_ui_restricted_while_driving"/>
@@ -206,6 +315,7 @@
   <public type="string" name="car_ui_toolbar_menu_item_overflow_title"/>
   <public type="string" name="car_ui_toolbar_menu_item_search_title"/>
   <public type="string" name="car_ui_toolbar_menu_item_settings_title"/>
+  <public type="string" name="car_ui_toolbar_nav_icon_content_description"/>
   <public type="style" name="CarUiPreferenceTheme"/>
   <public type="style" name="CarUiPreferenceTheme.WithToolbar"/>
   <public type="style" name="Preference.CarUi"/>
@@ -213,6 +323,12 @@
   <public type="style" name="Preference.CarUi.CheckBoxPreference"/>
   <public type="style" name="Preference.CarUi.DialogPreference"/>
   <public type="style" name="Preference.CarUi.DialogPreference.EditTextPreference"/>
+  <public type="style" name="Preference.CarUi.DialogSeekBarPreference"/>
+  <public type="style" name="Preference.CarUi.DialogSeekBarPreference.LeftText"/>
+  <public type="style" name="Preference.CarUi.DialogSeekBarPreference.RightText"/>
+  <public type="style" name="Preference.CarUi.DialogSeekBarPreference.Seekbar"/>
+  <public type="style" name="Preference.CarUi.DialogSeekBarPreference.TopText"/>
+  <public type="style" name="Preference.CarUi.Divider"/>
   <public type="style" name="Preference.CarUi.DropDown"/>
   <public type="style" name="Preference.CarUi.Icon"/>
   <public type="style" name="Preference.CarUi.Information"/>
@@ -225,6 +341,7 @@
   <public type="style" name="PreferenceFragmentList.CarUi"/>
   <public type="style" name="TextAppearance.CarUi"/>
   <public type="style" name="TextAppearance.CarUi.AlertDialog.Subtitle"/>
+  <public type="style" name="TextAppearance.CarUi.AlertDialog.Title"/>
   <public type="style" name="TextAppearance.CarUi.Body1"/>
   <public type="style" name="TextAppearance.CarUi.Body2"/>
   <public type="style" name="TextAppearance.CarUi.Body3"/>
@@ -235,6 +352,9 @@
   <public type="style" name="TextAppearance.CarUi.PreferenceEditTextDialogMessage"/>
   <public type="style" name="TextAppearance.CarUi.PreferenceSummary"/>
   <public type="style" name="TextAppearance.CarUi.PreferenceTitle"/>
+  <public type="style" name="TextAppearance.CarUi.Sub1"/>
+  <public type="style" name="TextAppearance.CarUi.Sub2"/>
+  <public type="style" name="TextAppearance.CarUi.Sub3"/>
   <public type="style" name="TextAppearance.CarUi.Widget"/>
   <public type="style" name="TextAppearance.CarUi.Widget.Toolbar"/>
   <public type="style" name="TextAppearance.CarUi.Widget.Toolbar.Tab"/>
@@ -268,6 +388,7 @@
   <public type="style" name="Widget.CarUi.Toolbar.Search.EditText"/>
   <public type="style" name="Widget.CarUi.Toolbar.Search.SearchIcon"/>
   <public type="style" name="Widget.CarUi.Toolbar.SeparatorView"/>
+  <public type="style" name="Widget.CarUi.Toolbar.Subtitle"/>
   <public type="style" name="Widget.CarUi.Toolbar.Tab"/>
   <public type="style" name="Widget.CarUi.Toolbar.Tab.Container"/>
   <public type="style" name="Widget.CarUi.Toolbar.Tab.Icon"/>
diff --git a/car-ui-lib/tests/apitest/resource_utils.py b/car-ui-lib/tests/apitest/resource_utils.py
index ab0de6d..8429d33 100755
--- a/car-ui-lib/tests/apitest/resource_utils.py
+++ b/car-ui-lib/tests/apitest/resource_utils.py
@@ -15,6 +15,7 @@
 # limitations under the License.
 
 import os
+import re
 
 class ResourceLocation:
     def __init__(self, file, line=None):
@@ -74,6 +75,9 @@
                 add_resource_to_set(resources,
                                     Resource(file[:-4], type,
                                              ResourceLocation(os.path.join(resDir, dir, file))))
+                if dir.startswith("layout"):
+                    for resource in get_ids_from_layout_file(os.path.join(resDir, dir, file)):
+                        add_resource_to_set(resources, resource)
 
     for dir in valuesDirs:
         for file in os.listdir(os.path.join(resDir, dir)):
@@ -83,6 +87,14 @@
 
     return resources
 
+def get_ids_from_layout_file(filename):
+    result = set()
+    with open(filename, 'r') as file:
+        r = re.compile("@\+id/([a-zA-Z0-9_]+)")
+        for i in r.findall(file.read()):
+            add_resource_to_set(result, Resource(i, 'id', ResourceLocation(filename)))
+    return result
+
 def get_resources_from_single_file(filename):
     # defer importing lxml to here so that people who aren't editing chassis don't have to have
     # lxml installed
@@ -94,19 +106,15 @@
         if resource.tag == 'declare-styleable' or resource.tag is etree.Comment:
             continue
 
+        resName = resource.get('name')
+        resType = resource.tag
         if resource.tag == 'item' or resource.tag == 'public':
-            add_resource_to_set(result, Resource(resource.get('name'), resource.get('type'),
-                                                 ResourceLocation(filename, resource.sourceline)))
-        else:
-            add_resource_to_set(result, Resource(resource.get('name'), resource.tag,
-                                                 ResourceLocation(filename, resource.sourceline)))
-    return result
+            resType = resource.get('type')
 
-def remove_layout_resources(resourceSet):
-    result = set()
-    for resource in resourceSet:
-        if resource.type != 'layout':
-            result.add(resource)
+        if resType != 'overlayable':
+            add_resource_to_set(result, Resource(resName, resType,
+                                                 ResourceLocation(filename, resource.sourceline)))
+
     return result
 
 # Used to get objects out of sets
diff --git a/car-ui-lib/tests/baselayouttests/src/com/android/car/ui/core/testsupport/CarUiInstallerRobolectric.java b/car-ui-lib/tests/baselayouttests/src/com/android/car/ui/core/testsupport/CarUiInstallerRobolectric.java
new file mode 100644
index 0000000..652819f
--- /dev/null
+++ b/car-ui-lib/tests/baselayouttests/src/com/android/car/ui/core/testsupport/CarUiInstallerRobolectric.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.car.ui.core.testsupport;
+
+import android.content.pm.ProviderInfo;
+
+import com.android.car.ui.core.CarUiInstaller;
+
+import org.robolectric.Robolectric;
+
+/**
+ * A helper class that can be used to install the base layout into robolectric test activities.
+ */
+public class CarUiInstallerRobolectric {
+
+    public static void install() {
+        ProviderInfo info = new ProviderInfo();
+        Class carUiInstallerClass = CarUiInstaller.class;
+        info.authority = carUiInstallerClass.getName();
+        Robolectric.buildContentProvider(carUiInstallerClass).create(info);
+    }
+}
diff --git a/car-ui-lib/tests/paintbooth/Android.bp b/car-ui-lib/tests/paintbooth/Android.bp
new file mode 100644
index 0000000..e303d83
--- /dev/null
+++ b/car-ui-lib/tests/paintbooth/Android.bp
@@ -0,0 +1,56 @@
+//
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+android_app {
+    name: "PaintBooth",
+
+    srcs: [
+    	"src/**/*.java",
+    	"src/**/*.kt",
+    ],
+
+    required: ["privapp_whitelist_com.android.car.ui.paintbooth"],
+
+    resource_dirs: ["res", "res-public"],
+
+    platform_apis: true,
+
+    certificate: "platform",
+
+    privileged: true,
+
+    static_libs: [
+        "car-ui-lib",
+        "android.car.userlib",
+		"guava",
+		"gson-prebuilt-jar",
+    ],
+
+    optimize: {
+        enabled: false,
+    },
+
+    dex_preopt: {
+        enabled: false,
+    },
+
+    product_variables: {
+        pdk: {
+            enabled: false,
+        },
+    },
+    export_package_resources: true,
+}
diff --git a/car-ui-lib/tests/paintbooth/Android.mk b/car-ui-lib/tests/paintbooth/Android.mk
deleted file mode 100644
index fca93f1..0000000
--- a/car-ui-lib/tests/paintbooth/Android.mk
+++ /dev/null
@@ -1,49 +0,0 @@
-#
-# Copyright (C) 2019 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-ifneq ($(TARGET_BUILD_PDK), true)
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-
-LOCAL_PACKAGE_NAME := PaintBooth
-
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_CERTIFICATE := platform
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_STATIC_ANDROID_LIBRARIES := \
-        car-ui-lib
-
-LOCAL_STATIC_JAVA_LIBRARIES += \
-    android.car.userlib \
-
-LOCAL_USE_AAPT2 := true
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-LOCAL_DEX_PREOPT := false
-
-include $(BUILD_PACKAGE)
-
-endif
diff --git a/car-ui-lib/tests/paintbooth/AndroidManifest-gradle.xml b/car-ui-lib/tests/paintbooth/AndroidManifest-gradle.xml
index 61ca559..3184bd7 100644
--- a/car-ui-lib/tests/paintbooth/AndroidManifest-gradle.xml
+++ b/car-ui-lib/tests/paintbooth/AndroidManifest-gradle.xml
@@ -19,6 +19,7 @@
     package="com.android.car.ui.paintbooth">
 
   <application
+      android:supportsRtl="true"
       android:icon="@drawable/ic_launcher"
       android:label="@string/app_name"
       android:theme="@style/Theme.CarUi.WithToolbar">
@@ -54,6 +55,13 @@
       <meta-data android:name="distractionOptimized" android:value="true"/>
     </activity>
     <activity
+        android:name=".toolbar.OldToolbarActivity"
+        android:exported="false"
+        android:parentActivityName=".MainActivity"
+        android:theme="@style/Theme.CarUi">
+      <meta-data android:name="distractionOptimized" android:value="true"/>
+    </activity>
+    <activity
         android:name=".overlays.OverlayActivity"
         android:exported="false"
         android:parentActivityName=".MainActivity">
@@ -68,10 +76,13 @@
         android:exported="false"
         android:parentActivityName=".MainActivity"/>
 
-    <!-- Remove this on R, it's to workaround a bug in the Qt manifest merger -->
-    <provider
-        android:name="com.android.car.ui.core.CarUiInstaller"
-        android:authorities="${applicationId}.CarUiInstaller"
-        android:exported="false"/>
+    <service
+        android:label="Current Activity Service"
+        android:exported="false"
+        android:name=".currentactivity.CurrentActivityService"/>
+    <service
+        android:label="Visible Bounds Simulator"
+        android:exported="false"
+        android:name=".VisibleBoundsSimulator"/>
   </application>
 </manifest>
diff --git a/car-ui-lib/tests/paintbooth/AndroidManifest.xml b/car-ui-lib/tests/paintbooth/AndroidManifest.xml
index ba222d2..c277ff5 100644
--- a/car-ui-lib/tests/paintbooth/AndroidManifest.xml
+++ b/car-ui-lib/tests/paintbooth/AndroidManifest.xml
@@ -26,8 +26,23 @@
   <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL"/>
   <uses-permission android:name="android.permission.CHANGE_OVERLAY_PACKAGES"/>
   <uses-permission android:name="android.permission.MANAGE_USERS"/>
+  <!-- Required to use the TYPE_DISPLAY_OVERLAY layout param for the current activity overlay -->
+  <uses-permission android:name="android.permission.INTERNAL_SYSTEM_WINDOW" />
+  <!-- Required for listening to android task stack changes -->
+  <uses-permission android:name="android.permission.MANAGE_ACTIVITY_STACKS" />
+  <uses-permission android:name="android.permission.REAL_GET_TASKS" />
+  <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
+  <!-- Required for using TYPE_APPLICATION_OVERLAY to display overlays -->
+  <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
+  <!-- Required to test permission dialogs -->
+  <uses-permission android:name="android.permission.CAMERA"/>
+  <uses-permission android:name="android.permission.READ_CONTACTS"/>
+  <uses-permission android:name="android.permission.SEND_SMS"/>
+  <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
+  <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>
 
   <application
+      android:supportsRtl="true"
       android:icon="@drawable/ic_launcher"
       android:label="@string/app_name"
       android:theme="@style/Theme.CarUi.WithToolbar">
@@ -63,6 +78,16 @@
       <meta-data android:name="distractionOptimized" android:value="true"/>
     </activity>
     <activity
+        android:name=".toolbar.NoCarUiToolbarActivity"
+        android:exported="false"
+        android:parentActivityName=".MainActivity"
+        android:theme="@style/Theme.AppCompat.Light.NoActionBar"/>
+    <activity
+        android:name=".toolbar.OldToolbarActivity"
+        android:exported="false"
+        android:parentActivityName=".MainActivity"
+        android:theme="@style/Theme.CarUi"/>
+    <activity
         android:name=".overlays.OverlayActivity"
         android:exported="false"
         android:parentActivityName=".MainActivity">
@@ -77,10 +102,13 @@
         android:exported="false"
         android:parentActivityName=".MainActivity"/>
 
-    <!-- Remove this on R, it's to workaround a bug in the Qt manifest merger -->
-    <provider
-        android:name="com.android.car.ui.core.CarUiInstaller"
-        android:authorities="${applicationId}.CarUiInstaller"
-        android:exported="false"/>
+    <service
+        android:label="Current Activity Service"
+        android:exported="false"
+        android:name=".currentactivity.CurrentActivityService"/>
+    <service
+        android:label="Visible Bounds Simulator"
+        android:exported="false"
+        android:name=".VisibleBoundsSimulator"/>
   </application>
 </manifest>
diff --git a/car-ui-lib/tests/paintbooth/build.gradle b/car-ui-lib/tests/paintbooth/build.gradle
index 0ef3514..e85a629 100644
--- a/car-ui-lib/tests/paintbooth/build.gradle
+++ b/car-ui-lib/tests/paintbooth/build.gradle
@@ -17,11 +17,11 @@
 apply plugin: 'com.android.application'
 
 android {
-    compileSdkVersion 28
+    compileSdkVersion 29
     defaultConfig {
         applicationId "com.android.car.ui.paintbooth"
         minSdkVersion 28
-        targetSdkVersion 28
+        targetSdkVersion 29
         versionCode 1
         versionName "1.0"
     }
@@ -36,9 +36,12 @@
             manifest.srcFile 'AndroidManifest-gradle.xml'
             java {
                 srcDirs = ['src']
-                filter.excludes = ["com/android/car/ui/paintbooth/overlays/OverlayManagerImpl.java"]
+                filter.excludes = [
+                        "com/android/car/ui/paintbooth/overlays/OverlayManagerImpl.java",
+                        "com/android/car/ui/paintbooth/currentactivity/ActivityTaskManagerImpl.java",
+                ]
             }
-            res.srcDirs = ['res']
+            res.srcDirs = ['res', 'res-public']
         }
     }
 }
diff --git a/car-ui-lib/tests/paintbooth/res-public/values/public.xml b/car-ui-lib/tests/paintbooth/res-public/values/public.xml
new file mode 100644
index 0000000..792aa8f
--- /dev/null
+++ b/car-ui-lib/tests/paintbooth/res-public/values/public.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <public type="color" name="dialog_activity_background_color" id="0x7f050040" />
+</resources>
diff --git a/car-ui-lib/tests/paintbooth/res/drawable/ic_settings_gear.xml b/car-ui-lib/tests/paintbooth/res/drawable/ic_settings_gear.xml
new file mode 100644
index 0000000..d1557f4
--- /dev/null
+++ b/car-ui-lib/tests/paintbooth/res/drawable/ic_settings_gear.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright 2017 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+
+<vector
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="48dp"
+    android:height="48dp"
+    android:viewportHeight="48.0"
+    android:viewportWidth="48.0">
+    <path
+        android:fillColor="#fff"
+        android:pathData="M38.86,25.95c0.08,-0.64 0.14,-1.29 0.14,-1.95s-0.06,-1.31 -0.14,-1.95l4.23,-3.31c0.38,-0.3 0.49,-0.84 0.24,-1.28l-4,-6.93c-0.25,-0.43 -0.77,-0.61 -1.22,-0.43l-4.98,2.01c-1.03,-0.79 -2.16,-1.46 -3.38,-1.97L29,4.84c-0.09,-0.47 -0.5,-0.84 -1,-0.84h-8c-0.5,0 -0.91,0.37 -0.99,0.84l-0.75,5.3c-1.22,0.51 -2.35,1.17 -3.38,1.97L9.9,10.1c-0.45,-0.17 -0.97,0 -1.22,0.43l-4,6.93c-0.25,0.43 -0.14,0.97 0.24,1.28l4.22,3.31C9.06,22.69 9,23.34 9,24s0.06,1.31 0.14,1.95l-4.22,3.31c-0.38,0.3 -0.49,0.84 -0.24,1.28l4,6.93c0.25,0.43 0.77,0.61 1.22,0.43l4.98,-2.01c1.03,0.79 2.16,1.46 3.38,1.97l0.75,5.3c0.08,0.47 0.49,0.84 0.99,0.84h8c0.5,0 0.91,-0.37 0.99,-0.84l0.75,-5.3c1.22,-0.51 2.35,-1.17 3.38,-1.97l4.98,2.01c0.45,0.17 0.97,0 1.22,-0.43l4,-6.93c0.25,-0.43 0.14,-0.97 -0.24,-1.28l-4.22,-3.31zM24,31c-3.87,0 -7,-3.13 -7,-7s3.13,-7 7,-7 7,3.13 7,7 -3.13,7 -7,7z"/>
+</vector>
diff --git a/car-ui-lib/tests/paintbooth/res/drawable/simulated_screen_shape.xml b/car-ui-lib/tests/paintbooth/res/drawable/simulated_screen_shape.xml
new file mode 100644
index 0000000..569f098
--- /dev/null
+++ b/car-ui-lib/tests/paintbooth/res/drawable/simulated_screen_shape.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2020 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:height="100dp"
+        android:width="100dp"
+        android:viewportHeight="100"
+        android:viewportWidth="100">
+
+    <path
+        android:strokeWidth="1"
+        android:strokeColor="#0f0"
+        android:pathData="M 0,0 L 100,0 100,100 0,100 z" />
+
+</vector>
diff --git a/car-ui-lib/tests/paintbooth/res/layout/car_ui_recycler_view_activity.xml b/car-ui-lib/tests/paintbooth/res/layout/car_ui_recycler_view_activity.xml
index 15b6fe6..5ae7e7f 100644
--- a/car-ui-lib/tests/paintbooth/res/layout/car_ui_recycler_view_activity.xml
+++ b/car-ui-lib/tests/paintbooth/res/layout/car_ui_recycler_view_activity.xml
@@ -19,4 +19,4 @@
     android:id="@+id/list"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:background="@drawable/car_ui_activity_background"/>
\ No newline at end of file
+    android:background="@drawable/car_ui_activity_background"/>
diff --git a/car-ui-lib/tests/paintbooth/res/layout/car_ui_recycler_view_activity_with_old_toolbar.xml b/car-ui-lib/tests/paintbooth/res/layout/car_ui_recycler_view_activity_with_old_toolbar.xml
new file mode 100644
index 0000000..cce0cde
--- /dev/null
+++ b/car-ui-lib/tests/paintbooth/res/layout/car_ui_recycler_view_activity_with_old_toolbar.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright 2020 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<androidx.constraintlayout.widget.ConstraintLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="@drawable/car_ui_activity_background">
+
+    <com.android.car.ui.recyclerview.CarUiRecyclerView
+        android:id="@+id/list"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:clipToPadding="false"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"/>
+
+    <com.android.car.ui.toolbar.Toolbar
+        android:id="@+id/toolbar"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintTop_toTopOf="parent"/>
+
+</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/car-ui-lib/tests/paintbooth/res/layout/car_ui_recycler_view_list_item.xml b/car-ui-lib/tests/paintbooth/res/layout/car_ui_recycler_view_list_item.xml
index a9d45ad..597ebcc 100644
--- a/car-ui-lib/tests/paintbooth/res/layout/car_ui_recycler_view_list_item.xml
+++ b/car-ui-lib/tests/paintbooth/res/layout/car_ui_recycler_view_list_item.xml
@@ -28,4 +28,4 @@
         android:id="@+id/textTitle"
         android:text="TESTING"/>
 
-</LinearLayout>
\ No newline at end of file
+</LinearLayout>
diff --git a/car-ui-lib/tests/paintbooth/res/layout/details_preference_widget.xml b/car-ui-lib/tests/paintbooth/res/layout/details_preference_widget.xml
new file mode 100644
index 0000000..4f9fc41
--- /dev/null
+++ b/car-ui-lib/tests/paintbooth/res/layout/details_preference_widget.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright 2018 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+
+<ImageView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:layout_gravity="center"
+    android:src="@drawable/ic_settings_gear"/>
diff --git a/car-ui-lib/tests/paintbooth/res/layout/grid_car_ui_recycler_view_activity.xml b/car-ui-lib/tests/paintbooth/res/layout/grid_car_ui_recycler_view_activity.xml
index 5c97fde..2b0d1a4 100644
--- a/car-ui-lib/tests/paintbooth/res/layout/grid_car_ui_recycler_view_activity.xml
+++ b/car-ui-lib/tests/paintbooth/res/layout/grid_car_ui_recycler_view_activity.xml
@@ -22,4 +22,4 @@
     app:numOfColumns="4"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:background="@drawable/car_ui_activity_background" />
\ No newline at end of file
+    android:background="@drawable/car_ui_activity_background" />
diff --git a/car-ui-lib/tests/paintbooth/res/layout/list_item_switch.xml b/car-ui-lib/tests/paintbooth/res/layout/list_item_switch.xml
new file mode 100644
index 0000000..499f3e4
--- /dev/null
+++ b/car-ui-lib/tests/paintbooth/res/layout/list_item_switch.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright 2019 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content">
+
+  <Switch
+      android:id="@+id/button"
+      android:layout_width="wrap_content"
+      android:layout_height="wrap_content"
+      android:layout_centerHorizontal="true"
+      android:textSize="25sp"
+      android:layout_marginTop="20dp"/>
+</RelativeLayout>
diff --git a/car-ui-lib/tests/paintbooth/res/layout/no_car_ui_toolbar_activity.xml b/car-ui-lib/tests/paintbooth/res/layout/no_car_ui_toolbar_activity.xml
new file mode 100644
index 0000000..ce2acb4
--- /dev/null
+++ b/car-ui-lib/tests/paintbooth/res/layout/no_car_ui_toolbar_activity.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+~ Copyright (C) 2020 The Android Open Source Project
+~
+~ Licensed under the Apache License, Version 2.0 (the "License");
+~ you may not use this file except in compliance with the License.
+~ You may obtain a copy of the License at
+~
+~      http://www.apache.org/licenses/LICENSE-2.0
+~
+~ Unless required by applicable law or agreed to in writing, software
+~ distributed under the License is distributed on an "AS IS" BASIS,
+~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+~ See the License for the specific language governing permissions and
+~ limitations under the License.
+-->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="@drawable/car_ui_activity_background"
+    android:orientation="vertical">
+    <androidx.appcompat.widget.Toolbar
+        android:id="@+id/my_toolbar"
+        android:layout_width="match_parent"
+        android:layout_height="?attr/actionBarSize"
+        android:background="?attr/colorPrimary"
+        android:elevation="4dp"
+        android:theme="@style/ThemeOverlay.AppCompat.ActionBar"/>
+</LinearLayout>
diff --git a/car-ui-lib/tests/paintbooth/res/layout/simulated_screen_shape_container.xml b/car-ui-lib/tests/paintbooth/res/layout/simulated_screen_shape_container.xml
new file mode 100644
index 0000000..96387b1
--- /dev/null
+++ b/car-ui-lib/tests/paintbooth/res/layout/simulated_screen_shape_container.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2020 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:focusableInTouchMode="false"
+                android:focusable="false"
+                android:background="@drawable/simulated_screen_shape">
+
+</RelativeLayout>
diff --git a/car-ui-lib/tests/paintbooth/res/values/dimens.xml b/car-ui-lib/tests/paintbooth/res/values/dimens.xml
new file mode 100644
index 0000000..35dfeec
--- /dev/null
+++ b/car-ui-lib/tests/paintbooth/res/values/dimens.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2020 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<resources>
+    <!-- Width of the overlay container. Setting to 0 will use full width of the screen  -->
+    <dimen name="screen_shape_container_width">0dp</dimen>
+    <!-- Height of the overlay container. Setting to 0 will use full height of the screen  -->
+    <dimen name="screen_shape_container_height">0dp</dimen>
+</resources>
diff --git a/car-ui-lib/tests/paintbooth/res/values/strings.xml b/car-ui-lib/tests/paintbooth/res/values/strings.xml
index cd45f77..f347784 100644
--- a/car-ui-lib/tests/paintbooth/res/values/strings.xml
+++ b/car-ui-lib/tests/paintbooth/res/values/strings.xml
@@ -18,6 +18,9 @@
   <!-- Application name [CHAR LIMIT=30] -->
   <string name="app_name" translatable="false">Paint Booth (Gerrit)</string>
 
+  <!-- Description of the CurrentActivityService. [CHAR_LIMIT=200] -->
+  <string name="current_activity_service_description">Shows the current activity</string>
+
   <!-- Strings for Preference Samples -->
   <eat-comment/>
 
@@ -56,6 +59,11 @@
   <!-- Category title for preferences with widgets [CHAR_LIMIT=12]-->
   <string name="widgets">Widgets</string>
 
+  <!-- Title of a two action preference [CHAR_LIMIT=31]-->
+  <string name="title_twoaction_preference">TwoAction preference</string>
+  <!-- Summary of a two action preference [CHAR_LIMIT=70]-->
+  <string name="summary_twoaction_preference">A widget should be visible on the right</string>
+
   <!-- Title of a checkbox preference [CHAR_LIMIT=31]-->
   <string name="title_checkbox_preference">Checkbox preference</string>
   <!-- Summary of a checkbox preference [CHAR_LIMIT=78]-->
@@ -71,6 +79,8 @@
 
   <!-- Title of a seekbar preference [CHAR_LIMIT=30]-->
   <string name="title_seekbar_preference">Seekbar preference</string>
+  <!-- Summary of an seekbar preference [CHAR_LIMIT=32]-->
+  <string name="summary_seekbar_preference">Seekbar summary</string>
 
   <!--This section is for preferences that launch a dialog to edit the preference -->
   <eat-comment/>
@@ -153,7 +163,13 @@
   <string name="toolbar_add_untined_icon">MenuItem: Add untinted icon</string>
 
   <!-- Text for add overflow button [CHAR_LIMIT=36]-->
-  <string name="toolbar_add_overflow">MenuItem: Add Overflow</string>
+  <string name="toolbar_add_overflow">Overflow MenuItem: Add Simple</string>
+
+  <!-- Text for add overflow button [CHAR_LIMIT=36]-->
+  <string name="toolbar_add_overflow_switch">Overflow MenuItem: Add switchable</string>
+
+  <!-- Text for add icon text overflow button [CHAR_LIMIT=45]-->
+  <string name="toolbar_add_icon_text_overflow">Overflow MenuItem: Add icon and text</string>
 
   <!-- Text for add switch button [CHAR_LIMIT=33]-->
   <string name="toolbar_add_switch">MenuItem: Add Switch</string>
@@ -248,14 +264,29 @@
   <!-- Button that shows a dialog with a subtitle and icon [CHAR_LIMIT=50]-->
   <string name="dialog_show_subtitle_and_icon">Show Dialog with title, subtitle, and icon</string>
 
+  <!-- Button that shows a dialog with a long title, subtitle and icon [CHAR_LIMIT=500]-->
+  <string name="dialog_show_long_subtitle_and_icon">Show Dialog with a long title, subtitle, and icon</string>
+
   <!-- Text to show Dialog with single choice items-->
   <string name="dialog_show_single_choice">Show with single choice items</string>
 
+  <!-- Text to show a permission Dialog [CHAR_LIMIT=50] -->
+  <string name="dialog_show_permission_dialog">Show permission dialog</string>
+
+  <!-- Text to show a permission Dialog for multiple permissions [CHAR_LIMIT=50] -->
+  <string name="dialog_show_multi_permission_dialog">Show multiple permissions dialog</string>
+
+  <!-- Text on button to show a permission dialog asking for the users location. [CHAR_LIMIT=100] -->
+  <string name="dialog_show_foreground_permission_dialog">Show foreground permission dialog</string>
+
+  <!-- Text on button to show a permission dialog asking for the users location in the background [CHAR_LIMIT=100] -->
+  <string name="dialog_show_background_permission_dialog">Show background permission dialog</string>
+
   <!--This section is for widget attributes -->
   <eat-comment/>
   <!-- Text for checkbox [CHAR_LIMIT=16]-->
   <string name="widget_checkbox_text">I\'m a check box</string>
   <!-- Text for switch [CHAR_LIMIT=25]-->
   <string name="widget_switch_text">I\'m a switch</string>
-  
+
 </resources>
diff --git a/car-ui-lib/tests/paintbooth/res/xml/current_activity_service.xml b/car-ui-lib/tests/paintbooth/res/xml/current_activity_service.xml
new file mode 100644
index 0000000..f6143cd
--- /dev/null
+++ b/car-ui-lib/tests/paintbooth/res/xml/current_activity_service.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<accessibility-service
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:accessibilityEventTypes="typeWindowStateChanged"
+    android:accessibilityFeedbackType="feedbackGeneric"
+    android:accessibilityFlags="flagIncludeNotImportantViews"
+    android:description="@string/current_activity_service_description"/>
diff --git a/car-ui-lib/tests/paintbooth/res/xml/preference_overlays.xml b/car-ui-lib/tests/paintbooth/res/xml/preference_overlays.xml
index 27ef049..f96b2a4 100644
--- a/car-ui-lib/tests/paintbooth/res/xml/preference_overlays.xml
+++ b/car-ui-lib/tests/paintbooth/res/xml/preference_overlays.xml
@@ -17,4 +17,4 @@
 <PreferenceScreen
     xmlns:app="http://schemas.android.com/apk/res-auto"
     app:title="Overlays">
-</PreferenceScreen>
\ No newline at end of file
+</PreferenceScreen>
diff --git a/car-ui-lib/tests/paintbooth/res/xml/preference_samples.xml b/car-ui-lib/tests/paintbooth/res/xml/preference_samples.xml
index b49dd0d..d9a891c 100644
--- a/car-ui-lib/tests/paintbooth/res/xml/preference_samples.xml
+++ b/car-ui-lib/tests/paintbooth/res/xml/preference_samples.xml
@@ -19,132 +19,155 @@
     xmlns:app="http://schemas.android.com/apk/res-auto"
     app:title="@string/preferences_screen_title">
 
-  <PreferenceCategory
-      android:title="@string/basic_preferences">
+    <PreferenceCategory
+        android:title="@string/basic_preferences">
 
-    <Preference
-        android:key="preference"
-        android:title="@string/title_basic_preference"
-        android:summary="@string/summary_basic_preference"/>
+        <Preference
+            android:key="preference"
+            android:summary="@string/summary_basic_preference"
+            android:title="@string/title_basic_preference"/>
 
-    <Preference
-        android:key="stylized"
-        android:title="@string/title_stylish_preference"
-        android:summary="@string/summary_stylish_preference"/>
+        <Preference
+            android:key="preference_disabled_without_ripple"
+            android:summary="Without ripple"
+            android:title="@string/title_basic_preference"/>
 
-    <Preference
-        android:key="icon"
-        android:title="@string/title_icon_preference"
-        android:summary="@string/summary_icon_preference"
-        android:icon="@drawable/ic_settings_wifi"/>
+        <Preference
+            android:key="preference_disabled_with_ripple"
+            android:summary="With ripple"
+            android:title="@string/title_basic_preference"/>
 
-    <Preference
-        android:key="single_line_title"
-        android:title="@string/title_single_line_title_preference"
-        android:summary="@string/summary_single_line_title_preference"
-        app:singleLineTitle="true"/>
+        <Preference
+            android:key="stylized"
+            android:dependency="preference"
+            android:summary="@string/summary_stylish_preference"
+            android:title="@string/title_stylish_preference"/>
 
-    <Preference
-        android:key="single_line_no_summary"
-        android:title="@string/title_single_line_no_summary"
-        app:singleLineTitle="true"/>
-  </PreferenceCategory>
+        <Preference
+            android:icon="@drawable/ic_settings_wifi"
+            android:key="icon"
+            android:summary="@string/summary_icon_preference"
+            android:title="@string/title_icon_preference"/>
 
-  <PreferenceCategory
-      android:title="@string/widgets">
+        <Preference
+            android:key="single_line_title"
+            android:summary="@string/summary_single_line_title_preference"
+            android:title="@string/title_single_line_title_preference"
+            app:singleLineTitle="true"/>
 
-    <CheckBoxPreference
-        android:key="checkbox"
-        android:title="@string/title_checkbox_preference"
-        android:summary="@string/summary_checkbox_preference"/>
+        <Preference
+            android:key="single_line_no_summary"
+            android:title="@string/title_single_line_no_summary"
+            app:singleLineTitle="true"/>
+    </PreferenceCategory>
 
-    <SwitchPreference
-        android:key="switch"
-        android:title="@string/title_switch_preference"
-        android:summary="@string/summary_switch_preference"/>
+    <PreferenceCategory
+        android:title="@string/widgets">
 
-    <DropDownPreference
-        android:key="dropdown"
-        android:title="@string/title_dropdown_preference"
-        android:entries="@array/entries"
-        app:useSimpleSummaryProvider="true"
-        android:entryValues="@array/entry_values"/>
+        <CheckBoxPreference
+            android:key="checkbox"
+            android:summary="@string/summary_checkbox_preference"
+            android:title="@string/title_checkbox_preference"/>
 
-    <SeekBarPreference
-        android:key="seekbar"
-        android:title="@string/title_seekbar_preference"
-        android:max="10"
-        android:defaultValue="5"/>
-  </PreferenceCategory>
+        <DropDownPreference
+            android:entries="@array/entries"
+            android:entryValues="@array/entry_values"
+            android:key="dropdown"
+            android:title="@string/title_dropdown_preference"
+            app:useSimpleSummaryProvider="true"/>
 
-  <PreferenceCategory
-      android:title="@string/dialogs">
+        <SeekBarPreference
+            android:defaultValue="5"
+            android:key="seekbar"
+            android:max="10"
+            android:title="@string/title_seekbar_preference"/>
 
-    <EditTextPreference
-        android:key="edittext"
-        android:title="@string/title_edittext_preference"
-        app:useSimpleSummaryProvider="true"
-        android:dialogTitle="@string/dialog_title_edittext_preference"/>
+        <SwitchPreference
+            android:key="switch"
+            android:summary="@string/summary_switch_preference"
+            android:title="@string/title_switch_preference"/>
 
-    <ListPreference
-        android:key="list"
-        android:title="@string/title_list_preference"
-        app:useSimpleSummaryProvider="true"
-        android:entries="@array/entries"
-        android:entryValues="@array/entry_values"
-        android:dialogTitle="@string/dialog_title_list_preference"/>
+        <com.android.car.ui.preference.CarUiTwoActionPreference
+            android:key="twoaction"
+            android:summary="@string/summary_twoaction_preference"
+            android:title="@string/title_twoaction_preference"
+            android:widgetLayout="@layout/details_preference_widget"/>
+    </PreferenceCategory>
 
-    <MultiSelectListPreference
-        android:key="multi_select_list"
-        android:title="@string/title_multi_list_preference"
-        android:summary="@string/summary_multi_list_preference"
-        android:entries="@array/entries"
-        android:entryValues="@array/entry_values"
-        android:dialogTitle="@string/dialog_title_multi_list_preference"/>
-  </PreferenceCategory>
+    <PreferenceCategory
+        android:title="@string/dialogs">
 
-  <PreferenceCategory
-      android:key="@string/advanced_preference"
-      android:title="@string/advanced_attributes"
-      app:initialExpandedChildrenCount="1">
+        <EditTextPreference
+            android:dialogTitle="@string/dialog_title_edittext_preference"
+            android:key="edittext"
+            android:title="@string/title_edittext_preference"
+            app:useSimpleSummaryProvider="true"/>
 
-    <Preference
-        android:key="expandable"
-        android:title="@string/title_expandable_preference"
-        android:summary="@string/summary_expandable_preference"/>
+        <ListPreference
+            android:dialogTitle="@string/dialog_title_list_preference"
+            android:entries="@array/entries"
+            android:entryValues="@array/entry_values"
+            android:key="list"
+            android:title="@string/title_list_preference"
+            app:useSimpleSummaryProvider="true"/>
 
-    <Preference
-        android:title="@string/title_intent_preference"
-        android:summary="@string/summary_intent_preference">
+        <MultiSelectListPreference
+            android:dialogTitle="@string/dialog_title_multi_list_preference"
+            android:entries="@array/entries"
+            android:entryValues="@array/entry_values"
+            android:key="multi_select_list"
+            android:summary="@string/summary_multi_list_preference"
+            android:title="@string/title_multi_list_preference"/>
 
-      <intent android:action="android.intent.action.VIEW"
-          android:data="http://www.android.com"/>
+        <com.android.car.ui.preference.CarUiSeekBarDialogPreference
+            android:dialogTitle="Seekbar Dialog"
+            android:key="seekbarDialog"
+            android:summary="@string/summary_seekbar_preference"
+            android:title="@string/title_seekbar_preference"/>
+    </PreferenceCategory>
 
-    </Preference>
+    <PreferenceCategory
+        android:key="@string/advanced_preference"
+        android:title="@string/advanced_attributes"
+        app:initialExpandedChildrenCount="1">
 
-    <SwitchPreference
-        android:key="parent"
-        android:title="@string/title_parent_preference"
-        android:summary="@string/summary_parent_preference"/>
+        <Preference
+            android:key="expandable"
+            android:summary="@string/summary_expandable_preference"
+            android:title="@string/title_expandable_preference"/>
 
-    <SwitchPreference
-        android:key="child"
-        android:dependency="parent"
-        android:title="@string/title_child_preference"
-        android:summary="@string/summary_child_preference"/>
+        <Preference
+            android:summary="@string/summary_intent_preference"
+            android:title="@string/title_intent_preference">
 
-    <SwitchPreference
-        android:key="toggle_summary"
-        android:title="@string/title_toggle_summary_preference"
-        android:summaryOn="@string/summary_on_toggle_summary_preference"
-        android:summaryOff="@string/summary_off_toggle_summary_preference"/>
+            <intent android:action="android.intent.action.VIEW"
+                    android:data="http://www.android.com"/>
 
-    <Preference
-        android:key="copyable"
-        android:title="@string/title_copyable_preference"
-        android:summary="@string/summary_copyable_preference"
-        android:selectable="false"
-        app:enableCopying="true"/>
-  </PreferenceCategory>
+        </Preference>
 
-</PreferenceScreen>
\ No newline at end of file
+        <Preference
+            android:key="copyable"
+            android:selectable="false"
+            android:summary="@string/summary_copyable_preference"
+            android:title="@string/title_copyable_preference"
+            app:enableCopying="true"/>
+
+        <SwitchPreference
+            android:dependency="parent"
+            android:key="child"
+            android:summary="@string/summary_child_preference"
+            android:title="@string/title_child_preference"/>
+
+        <SwitchPreference
+            android:key="toggle_summary"
+            android:summaryOff="@string/summary_off_toggle_summary_preference"
+            android:summaryOn="@string/summary_on_toggle_summary_preference"
+            android:title="@string/title_toggle_summary_preference"/>
+
+        <SwitchPreference
+            android:key="parent"
+            android:summary="@string/summary_parent_preference"
+            android:title="@string/title_parent_preference"/>
+    </PreferenceCategory>
+
+</PreferenceScreen>
diff --git a/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/MainActivity.java b/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/MainActivity.java
index 3cf2b9f..02b8088 100644
--- a/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/MainActivity.java
+++ b/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/MainActivity.java
@@ -17,14 +17,17 @@
 package com.android.car.ui.paintbooth;
 
 import android.app.Activity;
+import android.app.ActivityManager;
+import android.app.Service;
+import android.content.Context;
 import android.content.Intent;
 import android.os.Bundle;
 import android.util.Log;
-import android.util.Pair;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.Button;
+import android.widget.Switch;
 import android.widget.Toast;
 
 import androidx.annotation.NonNull;
@@ -36,9 +39,12 @@
 import com.android.car.ui.paintbooth.caruirecyclerview.CarUiListItemActivity;
 import com.android.car.ui.paintbooth.caruirecyclerview.CarUiRecyclerViewActivity;
 import com.android.car.ui.paintbooth.caruirecyclerview.GridCarUiRecyclerViewActivity;
+import com.android.car.ui.paintbooth.currentactivity.CurrentActivityService;
 import com.android.car.ui.paintbooth.dialogs.DialogsActivity;
 import com.android.car.ui.paintbooth.overlays.OverlayActivity;
 import com.android.car.ui.paintbooth.preferences.PreferenceActivity;
+import com.android.car.ui.paintbooth.toolbar.NoCarUiToolbarActivity;
+import com.android.car.ui.paintbooth.toolbar.OldToolbarActivity;
 import com.android.car.ui.paintbooth.toolbar.ToolbarActivity;
 import com.android.car.ui.paintbooth.widgets.WidgetActivity;
 import com.android.car.ui.recyclerview.CarUiRecyclerView;
@@ -53,58 +59,112 @@
  */
 public class MainActivity extends Activity implements InsetsChangedListener {
 
+    public static final String STOP_SERVICE = "com.android.car.ui.paintbooth.StopService";
+
     /**
      * List of all sample activities.
      */
-    private final List<Pair<String, Class<? extends Activity>>> mActivities = Arrays.asList(
-            Pair.create("Dialogs sample", DialogsActivity.class),
-            Pair.create("List sample", CarUiRecyclerViewActivity.class),
-            Pair.create("Grid sample", GridCarUiRecyclerViewActivity.class),
-            Pair.create("Preferences sample", PreferenceActivity.class),
-            Pair.create("Overlays", OverlayActivity.class),
-            Pair.create("Toolbar sample", ToolbarActivity.class),
-            Pair.create("Widget sample", WidgetActivity.class),
-            Pair.create("ListItem sample", CarUiListItemActivity.class)
-    );
+    private final List<ListElement> mActivities = Arrays.asList(
+            new ServiceElement("Show foreground activities", CurrentActivityService.class),
+            new ServiceElement("Simulate Screen Bounds", VisibleBoundsSimulator.class),
+            new ActivityElement("Dialogs sample", DialogsActivity.class),
+            new ActivityElement("List sample", CarUiRecyclerViewActivity.class),
+            new ActivityElement("Grid sample", GridCarUiRecyclerViewActivity.class),
+            new ActivityElement("Preferences sample", PreferenceActivity.class),
+            new ActivityElement("Overlays", OverlayActivity.class),
+            new ActivityElement("Toolbar sample", ToolbarActivity.class),
+            new ActivityElement("Old toolbar sample", OldToolbarActivity.class),
+            new ActivityElement("No CarUiToolbar sample", NoCarUiToolbarActivity.class),
+            new ActivityElement("Widget sample", WidgetActivity.class),
+            new ActivityElement("ListItem sample", CarUiListItemActivity.class));
 
-    private class ViewHolder extends RecyclerView.ViewHolder {
-        private Button mButton;
+    private abstract static class ViewHolder extends RecyclerView.ViewHolder {
 
         ViewHolder(@NonNull View itemView) {
             super(itemView);
-            mButton = itemView.findViewById(R.id.button);
         }
 
-        void update(String title, Class<? extends Activity> activityClass) {
-            mButton.setText(title);
-            mButton.setOnClickListener(e -> {
-                Intent intent = new Intent(mButton.getContext(), activityClass);
-                startActivity(intent);
+        public abstract void bind(ListElement element);
+    }
+
+    private class ActivityViewHolder extends ViewHolder {
+        private final Button mButton;
+
+        ActivityViewHolder(@NonNull View itemView) {
+            super(itemView);
+            mButton = itemView.requireViewById(R.id.button);
+        }
+
+        @Override
+        public void bind(ListElement e) {
+            if (!(e instanceof ActivityElement)) {
+                throw new IllegalArgumentException("Expected an ActivityElement");
+            }
+            ActivityElement element = (ActivityElement) e;
+            mButton.setText(element.getText());
+            mButton.setOnClickListener(v ->
+                    startActivity(new Intent(itemView.getContext(), element.getActivity())));
+        }
+    }
+
+    private class ServiceViewHolder extends ViewHolder {
+        private final Switch mSwitch;
+
+        ServiceViewHolder(@NonNull View itemView) {
+            super(itemView);
+            mSwitch = itemView.requireViewById(R.id.button);
+        }
+
+        @Override
+        public void bind(ListElement e) {
+            if (!(e instanceof ServiceElement)) {
+                throw new IllegalArgumentException("Expected an ActivityElement");
+            }
+            ServiceElement element = (ServiceElement) e;
+            mSwitch.setChecked(isServiceRunning(element.getService()));
+            mSwitch.setText(element.getText());
+            mSwitch.setOnClickListener(v -> {
+                Intent intent = new Intent(itemView.getContext(), element.getService());
+                if (isServiceRunning(element.getService())) {
+                    intent.setAction(STOP_SERVICE);
+                }
+                startForegroundService(intent);
             });
         }
     }
 
     private final RecyclerView.Adapter<ViewHolder> mAdapter =
             new RecyclerView.Adapter<ViewHolder>() {
-        @NonNull
-        @Override
-        public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
-            View item = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item, parent,
-                    false);
-            return new ViewHolder(item);
-        }
+                @NonNull
+                @Override
+                public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+                    LayoutInflater inflater = LayoutInflater.from(parent.getContext());
+                    if (viewType == ListElement.TYPE_ACTIVITY) {
+                        return new ActivityViewHolder(
+                                inflater.inflate(R.layout.list_item, parent, false));
+                    } else if (viewType == ListElement.TYPE_SERVICE) {
+                        return new ServiceViewHolder(
+                                inflater.inflate(R.layout.list_item_switch, parent, false));
+                    } else {
+                        throw new IllegalArgumentException("Unknown viewType: " + viewType);
+                    }
+                }
 
-        @Override
-        public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
-            Pair<String, Class<? extends Activity>> item = mActivities.get(position);
-            holder.update(item.first, item.second);
-        }
+                @Override
+                public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
+                    holder.bind(mActivities.get(position));
+                }
 
-        @Override
-        public int getItemCount() {
-            return mActivities.size();
-        }
-    };
+                @Override
+                public int getItemCount() {
+                    return mActivities.size();
+                }
+
+                @Override
+                public int getItemViewType(int position) {
+                    return mActivities.get(position).getType();
+                }
+            };
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
@@ -198,11 +258,75 @@
         }
     }
 
+    private boolean isServiceRunning(Class<? extends Service> serviceClazz) {
+        ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
+        for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(
+                Integer.MAX_VALUE)) {
+            if (serviceClazz.getName().equals(service.service.getClassName())) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     @Override
-    public void onCarUiInsetsChanged(Insets insets) {
+    public void onCarUiInsetsChanged(@NonNull Insets insets) {
         requireViewById(R.id.list)
                 .setPadding(0, insets.getTop(), 0, insets.getBottom());
         requireViewById(android.R.id.content)
                 .setPadding(insets.getLeft(), 0, insets.getRight(), 0);
     }
+
+    private abstract static class ListElement {
+        static final int TYPE_ACTIVITY = 0;
+        static final int TYPE_SERVICE = 1;
+
+        private final String mText;
+
+        ListElement(String text) {
+            mText = text;
+        }
+
+        String getText() {
+            return mText;
+        }
+
+        abstract int getType();
+    }
+
+    private static class ActivityElement extends ListElement {
+        private final Class<? extends Activity> mActivityClass;
+
+        ActivityElement(String text, Class<? extends Activity> activityClass) {
+            super(text);
+            mActivityClass = activityClass;
+        }
+
+        Class<? extends Activity> getActivity() {
+            return mActivityClass;
+        }
+
+        @Override
+        int getType() {
+            return TYPE_ACTIVITY;
+        }
+    }
+
+    private static class ServiceElement extends ListElement {
+        private final Class<? extends Service> mServiceClass;
+
+        ServiceElement(String text, Class<? extends Service> serviceClass) {
+            super(text);
+            mServiceClass = serviceClass;
+        }
+
+        Class<? extends Service> getService() {
+            return mServiceClass;
+        }
+
+        @Override
+        int getType() {
+            return TYPE_SERVICE;
+        }
+    }
 }
diff --git a/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/VisibleBoundsSimulator.java b/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/VisibleBoundsSimulator.java
new file mode 100644
index 0000000..63a2aed
--- /dev/null
+++ b/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/VisibleBoundsSimulator.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.car.ui.paintbooth;
+
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.PixelFormat;
+import android.graphics.Point;
+import android.os.IBinder;
+import android.util.DisplayMetrics;
+import android.view.Display;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.WindowManager;
+
+import androidx.core.app.NotificationCompat;
+
+/**
+ * To start the service:
+ * adb shell am start-foreground-service com.android.car.ui.paintbooth/.DisplayService
+ *
+ * To stop the service:
+ * adb shell am stopservice com.android.car.ui.paintbooth/.DisplayService
+ *
+ * When the service is started it will draw a overlay view on top of the screen displayed. This
+ * overlay comes from a SVG file that can be modified to take different shapes. This service will be
+ * used to display different screen styles from OEMs.
+ */
+public class VisibleBoundsSimulator extends Service {
+    private static final int FOREGROUND_SERVICE_ID = 222;
+    private View mContainer;
+
+    private WindowManager mWindowManager;
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        throw new UnsupportedOperationException("Not yet implemented.");
+    }
+
+    @Override
+    public int onStartCommand(Intent intent, int flags, int startId) {
+        if (MainActivity.STOP_SERVICE.equals(intent.getAction())) {
+            stopSelf();
+        }
+
+        return START_STICKY;
+    }
+
+    @Override
+    public void onCreate() {
+
+        Intent notificationIntent = new Intent(this, VisibleBoundsSimulator.class);
+
+        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
+                notificationIntent, 0);
+
+        NotificationChannel channel = new NotificationChannel("DisplayService",
+                "Show overlay screen",
+                NotificationManager.IMPORTANCE_DEFAULT);
+        NotificationManager notificationManager =
+                (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
+        notificationManager.createNotificationChannel(channel);
+
+        Notification notification =
+                new NotificationCompat.Builder(this, "DisplayService")
+                        .setSmallIcon(R.drawable.ic_launcher)
+                        .setContentTitle("DisplayService")
+                        .setContentText("Show overlay screen")
+                        .setContentIntent(pendingIntent).build();
+
+        startForeground(FOREGROUND_SERVICE_ID, notification);
+        applyDisplayOverlay();
+    }
+
+    /**
+     * Creates a view overlay on top of a new window. The overlay gravity is set to left and
+     * bottom. If the width and height is not provided then the default is to take up the entire
+     * screen. Overlay will show bounds around the view and we can still click through the window.
+     */
+    private void applyDisplayOverlay() {
+        mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
+
+        DisplayMetrics displayMetrics = new DisplayMetrics();
+
+        mWindowManager.getDefaultDisplay().getRealMetrics(displayMetrics);
+        int screenHeight = displayMetrics.heightPixels;
+        int screenWidth = displayMetrics.widthPixels;
+        LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
+        WindowManager.LayoutParams params = new WindowManager.LayoutParams(
+                WindowManager.LayoutParams.WRAP_CONTENT,
+                WindowManager.LayoutParams.WRAP_CONTENT,
+                // WindowManager.LayoutParams.TYPE_DISPLAY_OVERLAY is a hidden api, so
+                // use its value here so we can still compile on gradle / google3
+                WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW + 26,
+                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+                        | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
+                        | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS,
+                PixelFormat.TRANSLUCENT);
+
+        params.packageName = this.getPackageName();
+        params.gravity = Gravity.BOTTOM | Gravity.LEFT;
+
+        Display display = mWindowManager.getDefaultDisplay();
+        Point size = new Point();
+        display.getSize(size);
+        int height = size.y;
+
+        params.x = 0;
+        // If the sysUI is showing and nav bar is taking up some space at the bottom we want to
+        // offset the height of the navBar so that the overlay starts from the bottom left.
+        params.y = -(screenHeight - height);
+
+        float overlayWidth = getApplicationContext().getResources().getDimension(
+                R.dimen.screen_shape_container_width);
+        float overlayHeight = getApplicationContext().getResources().getDimension(
+                R.dimen.screen_shape_container_height);
+
+
+        params.width = (int) (overlayWidth == 0 ? screenWidth : overlayHeight);
+        params.height = (int) (overlayHeight == 0 ? screenHeight : overlayHeight);
+        params.setTitle("Simulated display bound");
+
+        mContainer = inflater.inflate(R.layout.simulated_screen_shape_container, null);
+        mContainer.setLayoutParams(params);
+
+        mWindowManager.addView(mContainer, params);
+    }
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+        mWindowManager.removeView(mContainer);
+        stopSelf();
+    }
+}
diff --git a/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/caruirecyclerview/CarUiListItemActivity.java b/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/caruirecyclerview/CarUiListItemActivity.java
index 927b3f4..f6db6d3 100644
--- a/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/caruirecyclerview/CarUiListItemActivity.java
+++ b/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/caruirecyclerview/CarUiListItemActivity.java
@@ -21,6 +21,8 @@
 import android.os.Bundle;
 import android.widget.Toast;
 
+import androidx.annotation.NonNull;
+
 import com.android.car.ui.baselayout.Insets;
 import com.android.car.ui.baselayout.InsetsChangedListener;
 import com.android.car.ui.core.CarUi;
@@ -199,7 +201,7 @@
     }
 
     @Override
-    public void onCarUiInsetsChanged(Insets insets) {
+    public void onCarUiInsetsChanged(@NonNull Insets insets) {
         requireViewById(R.id.list)
                 .setPadding(0, insets.getTop(), 0, insets.getBottom());
         requireViewById(android.R.id.content)
diff --git a/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/caruirecyclerview/CarUiRecyclerViewActivity.java b/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/caruirecyclerview/CarUiRecyclerViewActivity.java
index a3ac9c2..810b10c 100644
--- a/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/caruirecyclerview/CarUiRecyclerViewActivity.java
+++ b/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/caruirecyclerview/CarUiRecyclerViewActivity.java
@@ -19,6 +19,7 @@
 import android.app.Activity;
 import android.os.Bundle;
 
+import androidx.annotation.NonNull;
 import androidx.recyclerview.widget.LinearLayoutManager;
 
 import com.android.car.ui.baselayout.Insets;
@@ -62,7 +63,7 @@
     }
 
     @Override
-    public void onCarUiInsetsChanged(Insets insets) {
+    public void onCarUiInsetsChanged(@NonNull Insets insets) {
         requireViewById(R.id.list)
                 .setPadding(0, insets.getTop(), 0, insets.getBottom());
         requireViewById(android.R.id.content)
diff --git a/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/caruirecyclerview/GridCarUiRecyclerViewActivity.java b/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/caruirecyclerview/GridCarUiRecyclerViewActivity.java
index 586b633..7d98a1e 100644
--- a/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/caruirecyclerview/GridCarUiRecyclerViewActivity.java
+++ b/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/caruirecyclerview/GridCarUiRecyclerViewActivity.java
@@ -19,6 +19,8 @@
 import android.app.Activity;
 import android.os.Bundle;
 
+import androidx.annotation.NonNull;
+
 import com.android.car.ui.baselayout.Insets;
 import com.android.car.ui.baselayout.InsetsChangedListener;
 import com.android.car.ui.core.CarUi;
@@ -58,7 +60,7 @@
     }
 
     @Override
-    public void onCarUiInsetsChanged(Insets insets) {
+    public void onCarUiInsetsChanged(@NonNull Insets insets) {
         requireViewById(R.id.list)
                 .setPadding(0, insets.getTop(), 0, insets.getBottom());
         requireViewById(android.R.id.content)
diff --git a/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/caruirecyclerview/RecyclerViewAdapter.java b/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/caruirecyclerview/RecyclerViewAdapter.java
index 652a7a8..07dea21 100644
--- a/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/caruirecyclerview/RecyclerViewAdapter.java
+++ b/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/caruirecyclerview/RecyclerViewAdapter.java
@@ -36,7 +36,7 @@
 
     private ArrayList<String> mData;
 
-    RecyclerViewAdapter(ArrayList<String> data) {
+    public RecyclerViewAdapter(ArrayList<String> data) {
         this.mData = data;
     }
 
diff --git a/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/currentactivity/ActivityTaskManager.java b/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/currentactivity/ActivityTaskManager.java
new file mode 100644
index 0000000..e05fab8
--- /dev/null
+++ b/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/currentactivity/ActivityTaskManager.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.car.ui.paintbooth.currentactivity;
+
+import android.app.ActivityManager;
+import android.app.ActivityManager.RunningTaskInfo;
+import android.content.ComponentName;
+import android.os.RemoteException;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.List;
+
+/**
+ * Interface for wrappers around {@link android.app.ActivityTaskManager} so that we can exclude them
+ * from non-system builds like gradle and google3.
+ */
+interface ActivityTaskManager {
+
+    interface TaskStackListener {
+        void onTaskCreated(int taskId, ComponentName componentName);
+
+        void onTaskRemoved(int taskId);
+
+        void onTaskDescriptionChanged(ActivityManager.RunningTaskInfo taskInfo);
+
+        void onTaskMovedToFront(ActivityManager.RunningTaskInfo taskInfo);
+    }
+
+    List<RunningTaskInfo> getTasks(int maxNum) throws RemoteException;
+
+    void registerTaskStackListener(TaskStackListener listener) throws RemoteException;
+
+    void unregisterTaskStackListener(TaskStackListener listener) throws RemoteException;
+
+    final class ActivityTaskManagerStub implements ActivityTaskManager {
+        @Override
+        public List<RunningTaskInfo> getTasks(int num) throws RemoteException {
+            throw new RemoteException("ActivityTaskManager is not available");
+        }
+
+        @Override
+        public void registerTaskStackListener(TaskStackListener listener) throws RemoteException {
+            throw new RemoteException("ActivityTaskManager is not available");
+        }
+
+        @Override
+        public void unregisterTaskStackListener(TaskStackListener listener) throws RemoteException {
+            throw new RemoteException("ActivityTaskManager is not available");
+        }
+    }
+
+    @NonNull
+    static ActivityTaskManager getService() {
+        try {
+            Class<?> clazz = Class.forName(
+                    "com.android.car.ui.paintbooth.currentactivity.ActivityTaskManagerImpl");
+            Constructor<?> constructor = clazz.getDeclaredConstructor();
+            constructor.setAccessible(true);
+            return (ActivityTaskManager) constructor.newInstance();
+        } catch (ClassNotFoundException | IllegalAccessException | InstantiationException
+                | NoSuchMethodException | InvocationTargetException e) {
+            Log.e("paintbooth", "ActivityTaskManager is not available", e);
+            return new ActivityTaskManagerStub();
+        }
+    }
+}
diff --git a/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/currentactivity/ActivityTaskManagerImpl.java b/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/currentactivity/ActivityTaskManagerImpl.java
new file mode 100644
index 0000000..8adbdad
--- /dev/null
+++ b/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/currentactivity/ActivityTaskManagerImpl.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.car.ui.paintbooth.currentactivity;
+
+import android.app.ActivityManager;
+import android.app.ActivityManager.RunningTaskInfo;
+import android.app.IActivityTaskManager;
+import android.content.ComponentName;
+import android.os.RemoteException;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * This class is a wrapper around {@link android.app.ActivityTaskManager} that is excluded from
+ * the gradle and google3 builds.
+ */
+class ActivityTaskManagerImpl implements ActivityTaskManager {
+
+    IActivityTaskManager mActivityTaskManager = android.app.ActivityTaskManager.getService();
+
+    Map<TaskStackListener, android.app.TaskStackListener> mListenerMapping = new HashMap<>();
+
+    @Override
+    public List<RunningTaskInfo> getTasks(int maxNum) throws RemoteException {
+        return mActivityTaskManager.getTasks(maxNum);
+    }
+
+    @Override
+    public void registerTaskStackListener(TaskStackListener listener) throws RemoteException {
+        mListenerMapping.put(listener, new android.app.TaskStackListener() {
+            @Override
+            public void onTaskCreated(int taskId, ComponentName componentName) {
+                listener.onTaskCreated(taskId, componentName);
+            }
+
+            @Override
+            public void onTaskRemoved(int taskId) {
+                listener.onTaskRemoved(taskId);
+            }
+
+            @Override
+            public void onTaskDescriptionChanged(ActivityManager.RunningTaskInfo taskInfo) {
+                listener.onTaskDescriptionChanged(taskInfo);
+            }
+
+            @Override
+            public void onTaskMovedToFront(ActivityManager.RunningTaskInfo taskInfo) {
+                listener.onTaskMovedToFront(taskInfo);
+            }
+        });
+
+        mActivityTaskManager.registerTaskStackListener(mListenerMapping.get(listener));
+    }
+
+    @Override
+    public void unregisterTaskStackListener(TaskStackListener listener) throws RemoteException {
+        mActivityTaskManager.unregisterTaskStackListener(mListenerMapping.get(listener));
+        mListenerMapping.remove(listener);
+    }
+
+}
diff --git a/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/currentactivity/CurrentActivityService.java b/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/currentactivity/CurrentActivityService.java
new file mode 100644
index 0000000..3c87f62
--- /dev/null
+++ b/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/currentactivity/CurrentActivityService.java
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.car.ui.paintbooth.currentactivity;
+
+import android.app.ActivityManager;
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.app.Service;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.graphics.Color;
+import android.graphics.PixelFormat;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.RemoteException;
+import android.view.Gravity;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.WindowManager;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import androidx.core.app.NotificationCompat;
+import androidx.core.content.ContextCompat;
+
+import com.android.car.ui.paintbooth.MainActivity;
+import com.android.car.ui.paintbooth.R;
+import com.android.car.ui.paintbooth.currentactivity.ActivityTaskManager.TaskStackListener;
+
+import java.util.List;
+
+/**
+ * To start the service:
+ * adb shell am start-foreground-service -n com.android.car.ui.paintbooth/.CurrentActivityService
+ *
+ * To stop the service:
+ * adb shell am start-foreground-service -n com.android.car.ui.paintbooth/.CurrentActivityService -a
+ * com.android.car.ui.paintbooth.StopService
+ */
+public class CurrentActivityService extends Service {
+    private static final int FOREGROUND_SERVICE_ID = 111;
+
+    private WindowManager mWindowManager;
+    private TextView mTextView;
+    private Handler mHandler;
+
+    @Override
+    public void onCreate() {
+        mHandler = new Handler(Looper.getMainLooper());
+
+        if (ContextCompat.checkSelfPermission(this, "android.permission.REAL_GET_TASKS")
+                != PackageManager.PERMISSION_GRANTED) {
+            Toast.makeText(this, "android.permission.REAL_GET_TASKS is not granted!",
+                    Toast.LENGTH_LONG).show();
+        }
+
+        Intent notificationIntent = new Intent(this, CurrentActivityService.class);
+
+        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
+                notificationIntent, 0);
+
+        NotificationChannel channel = new NotificationChannel("CurrentActivityService",
+                "Show current activity",
+                NotificationManager.IMPORTANCE_DEFAULT);
+        NotificationManager notificationManager =
+                (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
+        notificationManager.createNotificationChannel(channel);
+
+        Notification notification =
+                new NotificationCompat.Builder(this, "CurrentActivityService")
+                        .setSmallIcon(R.drawable.ic_launcher)
+                        .setContentTitle("CurrentActivityService")
+                        .setContentText("Show current activity")
+                        .setContentIntent(pendingIntent).build();
+
+        startForeground(FOREGROUND_SERVICE_ID, notification);
+
+        try {
+            ActivityTaskManager.getService().registerTaskStackListener(mTaskStackListener);
+        } catch (RemoteException e) {
+            Toast.makeText(this, e.getLocalizedMessage(), Toast.LENGTH_LONG).show();
+        }
+
+        mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
+        final WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(
+                WindowManager.LayoutParams.WRAP_CONTENT,
+                WindowManager.LayoutParams.WRAP_CONTENT,
+                WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
+                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+                        | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,
+                PixelFormat.TRANSLUCENT);
+
+        mTextView = new TextView(this);
+        layoutParams.gravity = Gravity.TOP | Gravity.LEFT;
+        layoutParams.x = 0;
+        layoutParams.y = 100;
+        mTextView.setLayoutParams(layoutParams);
+        mTextView.setBackgroundColor(Color.argb(50, 0, 255, 0));
+
+        mTextView.setOnTouchListener(new View.OnTouchListener() {
+
+            private int mInitialX = 0;
+            private int mInitialY = 0;
+            private float mInitialTouchX;
+            private float mInitialTouchY;
+
+            @Override
+            public boolean onTouch(View view, MotionEvent event) {
+                switch (event.getAction() & MotionEvent.ACTION_MASK) {
+                    case MotionEvent.ACTION_DOWN:
+                        mInitialX = layoutParams.x;
+                        mInitialY = layoutParams.y;
+                        mInitialTouchX = event.getRawX();
+                        mInitialTouchY = event.getRawY();
+                        break;
+                    case MotionEvent.ACTION_MOVE:
+                        WindowManager.LayoutParams layoutParams =
+                                (WindowManager.LayoutParams) view.getLayoutParams();
+                        layoutParams.x = mInitialX + (int) (event.getRawX() - mInitialTouchX);
+                        layoutParams.y = mInitialY + (int) (event.getRawY() - mInitialTouchY);
+                        mWindowManager.updateViewLayout(view, layoutParams);
+                        return true;
+                    default:
+                        break;
+                }
+
+                return false;
+            }
+        });
+
+        try {
+            mWindowManager.addView(mTextView, layoutParams);
+        } catch (RuntimeException e) {
+            Toast.makeText(this, "Couldn't display overlay", Toast.LENGTH_SHORT)
+                .show();
+        }
+
+        showCurrentTask();
+    }
+
+    @Override
+    public int onStartCommand(Intent intent, int flags, int startId) {
+        if (MainActivity.STOP_SERVICE.equals(intent.getAction())) {
+            stopSelf();
+        }
+
+        return START_STICKY;
+    }
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        return null;
+    }
+
+    @Override
+    public void onDestroy() {
+        mHandler.removeCallbacksAndMessages(null);
+        mWindowManager.removeView(mTextView);
+        try {
+            ActivityTaskManager.getService().unregisterTaskStackListener(mTaskStackListener);
+        } catch (RemoteException e) {
+            Toast.makeText(this, e.getLocalizedMessage(), Toast.LENGTH_LONG).show();
+        }
+    }
+
+    /**
+     * This requires system permissions or else it will only fetch the current app and the launcher
+     * app
+     */
+    private void showCurrentTask() {
+        try {
+            List<ActivityManager.RunningTaskInfo> tasks =
+                    ActivityTaskManager.getService().getTasks(1);
+            if (!tasks.isEmpty()) {
+                updateComponentName(tasks.get(0).topActivity);
+            }
+        } catch (RemoteException e) {
+            Toast.makeText(this, e.getLocalizedMessage(), Toast.LENGTH_LONG).show();
+        }
+    }
+
+    private void updateComponentName(ComponentName componentName) {
+        mHandler.post(() -> {
+            if (mTextView != null && componentName != null) {
+                mTextView.setText(componentName.flattenToShortString().replace('/', '\n'));
+            }
+        });
+    }
+
+    private final TaskStackListener mTaskStackListener = new TaskStackListener() {
+        @Override
+        public void onTaskCreated(int taskId, ComponentName componentName) {
+            updateComponentName(componentName);
+        }
+
+        @Override
+        public void onTaskRemoved(int taskId) {
+            showCurrentTask();
+        }
+
+        @Override
+        public void onTaskDescriptionChanged(ActivityManager.RunningTaskInfo taskInfo) {
+            updateComponentName(taskInfo.topActivity);
+        }
+
+        @Override
+        public void onTaskMovedToFront(ActivityManager.RunningTaskInfo taskInfo) {
+            updateComponentName(taskInfo.topActivity);
+        }
+    };
+}
diff --git a/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/dialogs/DialogsActivity.java b/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/dialogs/DialogsActivity.java
index 1f5f26a..7cf1cce 100644
--- a/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/dialogs/DialogsActivity.java
+++ b/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/dialogs/DialogsActivity.java
@@ -16,7 +16,9 @@
 
 package com.android.car.ui.paintbooth.dialogs;
 
+import android.Manifest;
 import android.app.Activity;
+import android.content.pm.PackageManager;
 import android.os.Bundle;
 import android.util.Pair;
 import android.view.LayoutInflater;
@@ -26,6 +28,7 @@
 import android.widget.Toast;
 
 import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.RecyclerView;
 
 import com.android.car.ui.AlertDialogBuilder;
 import com.android.car.ui.baselayout.Insets;
@@ -76,9 +79,18 @@
                 v -> showDialogWithSubtitle()));
         mButtons.add(Pair.create(R.string.dialog_show_subtitle_and_icon,
                 v -> showDialogWithSubtitleAndIcon()));
+        mButtons.add(Pair.create(R.string.dialog_show_long_subtitle_and_icon,
+                v -> showDialogWithLongSubtitleAndIcon()));
         mButtons.add(Pair.create(R.string.dialog_show_single_choice,
                 v -> showDialogWithSingleChoiceItems()));
-
+        mButtons.add(Pair.create(R.string.dialog_show_permission_dialog,
+                v -> showPermissionDialog()));
+        mButtons.add(Pair.create(R.string.dialog_show_multi_permission_dialog,
+                v -> showMultiPermissionDialog()));
+        mButtons.add(Pair.create(R.string.dialog_show_foreground_permission_dialog,
+                v -> showForegroundPermissionDialog()));
+        mButtons.add(Pair.create(R.string.dialog_show_background_permission_dialog,
+                v -> showBackgroundPermissionDialog()));
 
         CarUiRecyclerView recyclerView = requireViewById(R.id.list);
         recyclerView.setAdapter(mAdapter);
@@ -196,7 +208,64 @@
                 .show();
     }
 
-    private static class ViewHolder extends CarUiRecyclerView.ViewHolder {
+    private void showDialogWithLongSubtitleAndIcon() {
+        new AlertDialogBuilder(this)
+                .setTitle("This is a very long title. It should likely span across "
+                            + "multiple lines or something. It shouldn't get cut off.")
+                .setSubtitle("This is a very long subtitle. It should likely span across "
+                        + "multiple lines or something. It shouldn't get cut off.")
+                .setMessage("My Message!")
+                .setIcon(R.drawable.ic_tracklist)
+                .show();
+    }
+
+    private void showPermissionDialog() {
+        if (checkSelfPermission(Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) {
+            Toast.makeText(this, "Permission already granted. Remove CAMERA permission from "
+                    + "Settings > All apps > PaintBooth", Toast.LENGTH_SHORT).show();
+            return;
+        }
+        requestPermissions(new String[]{Manifest.permission.CAMERA}, 1);
+    }
+
+    private void showMultiPermissionDialog() {
+        if (checkSelfPermission(Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED
+                && checkSelfPermission(Manifest.permission.SEND_SMS)
+                    == PackageManager.PERMISSION_GRANTED
+                && checkSelfPermission(Manifest.permission.READ_CONTACTS)
+                    == PackageManager.PERMISSION_GRANTED) {
+            Toast.makeText(this, "Permissions are already granted. Remove CAMERA, SEND_SMS or "
+                    + "READ_CONTACTS permission from Settings > All apps > PaintBooth",
+                    Toast.LENGTH_SHORT).show();
+            return;
+        }
+        requestPermissions(new String[]{Manifest.permission.CAMERA,
+                Manifest.permission.READ_CONTACTS, Manifest.permission.SEND_SMS}, 1);
+    }
+
+    private void showForegroundPermissionDialog() {
+        requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 1);
+    }
+
+    private void showBackgroundPermissionDialog() {
+        requestPermissions(new String[]{Manifest.permission.ACCESS_BACKGROUND_LOCATION}, 1);
+    }
+
+    @Override
+    public void onRequestPermissionsResult(int requestCode, String[] permissions,
+            int[] grantResults) {
+        StringBuilder sb = new StringBuilder();
+        sb.append("Permission ");
+        for (int i = 0; i < permissions.length; i++) {
+            sb.append(permissions[i]);
+            sb.append("=");
+            sb.append(grantResults[i] == PackageManager.PERMISSION_GRANTED ? "granted" : "denied");
+            sb.append("\n");
+        }
+        Toast.makeText(this, sb.toString(), Toast.LENGTH_SHORT).show();
+    }
+
+    private static class ViewHolder extends RecyclerView.ViewHolder {
 
         private final Button mButton;
 
@@ -211,8 +280,8 @@
         }
     }
 
-    private final CarUiRecyclerView.Adapter<ViewHolder> mAdapter =
-            new CarUiRecyclerView.Adapter<ViewHolder>() {
+    private final RecyclerView.Adapter<ViewHolder> mAdapter =
+            new RecyclerView.Adapter<ViewHolder>() {
                 @Override
                 public int getItemCount() {
                     return mButtons.size();
@@ -234,7 +303,7 @@
             };
 
     @Override
-    public void onCarUiInsetsChanged(Insets insets) {
+    public void onCarUiInsetsChanged(@NonNull Insets insets) {
         requireViewById(R.id.list)
                 .setPadding(0, insets.getTop(), 0, insets.getBottom());
         requireViewById(android.R.id.content)
diff --git a/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/overlays/OverlayManagerImpl.java b/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/overlays/OverlayManagerImpl.java
index 32fcbc9..3a27534 100644
--- a/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/overlays/OverlayManagerImpl.java
+++ b/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/overlays/OverlayManagerImpl.java
@@ -16,7 +16,7 @@
 
 package com.android.car.ui.paintbooth.overlays;
 
-import android.car.userlib.CarUserManagerHelper;
+import android.app.ActivityManager;
 import android.content.Context;
 import android.content.om.IOverlayManager;
 import android.os.RemoteException;
@@ -35,11 +35,9 @@
  * image.
  */
 public class OverlayManagerImpl implements OverlayManager {
-    private final CarUserManagerHelper mCarUserManagerHelper;
     private final IOverlayManager mOverlayManager;
 
     public OverlayManagerImpl(Context context) {
-        mCarUserManagerHelper = new CarUserManagerHelper(context);
         mOverlayManager = IOverlayManager.Stub.asInterface(
                 ServiceManager.getService(Context.OVERLAY_SERVICE));
     }
@@ -62,8 +60,8 @@
     @Override
     @NonNull
     public Map<String, List<OverlayManager.OverlayInfo>> getOverlays() throws RemoteException {
-        Map<String, List<android.content.om.OverlayInfo>> overlays = mOverlayManager
-                .getAllOverlays(mCarUserManagerHelper.getCurrentForegroundUserId());
+        Map<String, List<android.content.om.OverlayInfo>> overlays =
+                mOverlayManager.getAllOverlays(ActivityManager.getCurrentUser());
         return overlays.entrySet()
                 .stream()
                 .collect(toMap(Map.Entry::getKey, e -> e.getValue()
@@ -74,7 +72,6 @@
 
     @Override
     public void applyOverlay(@NonNull String packageName, boolean enable) throws RemoteException {
-        mOverlayManager.setEnabled(packageName, enable,
-                mCarUserManagerHelper.getCurrentForegroundUserId());
+        mOverlayManager.setEnabled(packageName, enable, ActivityManager.getCurrentUser());
     }
 }
diff --git a/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/preferences/PreferenceDemoFragment.java b/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/preferences/PreferenceDemoFragment.java
index ccd21ef..233c873 100644
--- a/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/preferences/PreferenceDemoFragment.java
+++ b/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/preferences/PreferenceDemoFragment.java
@@ -19,6 +19,8 @@
 import android.os.Bundle;
 
 import com.android.car.ui.paintbooth.R;
+import com.android.car.ui.preference.CarUiPreference;
+import com.android.car.ui.preference.CarUiSwitchPreference;
 import com.android.car.ui.preference.PreferenceFragment;
 
 /**
@@ -30,5 +32,23 @@
     public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
         // Load the preferences from an XML resource
         setPreferencesFromResource(R.xml.preference_samples, rootKey);
+        CarUiPreference preferenceDisabledWithoutRipple = findPreference(
+                "preference_disabled_without_ripple");
+        preferenceDisabledWithoutRipple.setEnabled(false);
+        preferenceDisabledWithoutRipple.setMessageToShowWhenDisabledPreferenceClicked(
+                "I am disabled because...");
+        preferenceDisabledWithoutRipple.setShouldShowRippleOnDisabledPreference(false);
+
+        CarUiPreference preferenceDisabledWithRipple = findPreference(
+                "preference_disabled_with_ripple");
+        preferenceDisabledWithRipple.setEnabled(false);
+        preferenceDisabledWithRipple.setMessageToShowWhenDisabledPreferenceClicked(
+                "I am disabled because...");
+        preferenceDisabledWithRipple.setShouldShowRippleOnDisabledPreference(true);
+
+        CarUiSwitchPreference carUiSwitchPreference = findPreference("switch");
+        carUiSwitchPreference.setEnabled(false);
+        carUiSwitchPreference.setMessageToShowWhenDisabledPreferenceClicked(
+                "I am disabled because...");
     }
 }
diff --git a/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/toolbar/NoCarUiToolbarActivity.java b/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/toolbar/NoCarUiToolbarActivity.java
new file mode 100644
index 0000000..39e1a18
--- /dev/null
+++ b/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/toolbar/NoCarUiToolbarActivity.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.car.ui.paintbooth.toolbar;
+
+import android.os.Bundle;
+
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.appcompat.widget.Toolbar;
+
+import com.android.car.ui.paintbooth.R;
+
+/**
+ * Activity that uses androidX toolbar. This is a blank activity used for testing.
+ */
+public class NoCarUiToolbarActivity extends AppCompatActivity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.no_car_ui_toolbar_activity);
+        Toolbar myToolbar = (Toolbar) findViewById(R.id.my_toolbar);
+        setSupportActionBar(myToolbar);
+        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+        getSupportActionBar().setDisplayShowHomeEnabled(true);
+    }
+}
diff --git a/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/toolbar/OldToolbarActivity.java b/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/toolbar/OldToolbarActivity.java
new file mode 100644
index 0000000..f427990
--- /dev/null
+++ b/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/toolbar/OldToolbarActivity.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.car.ui.paintbooth.toolbar;
+
+import android.os.Bundle;
+
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.android.car.ui.paintbooth.R;
+import com.android.car.ui.toolbar.Toolbar;
+
+public class OldToolbarActivity extends ToolbarActivity {
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        Toolbar toolbar = requireViewById(R.id.toolbar);
+        RecyclerView rv = requireViewById(R.id.list);
+        toolbar.registerToolbarHeightChangeListener(height -> {
+            rv.setPadding(0, height, 0, 0);
+        });
+    }
+
+    @Override
+    protected int getLayout() {
+        return R.layout.car_ui_recycler_view_activity_with_old_toolbar;
+    }
+}
diff --git a/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/toolbar/ToolbarActivity.java b/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/toolbar/ToolbarActivity.java
index cb1fdc2..938f448 100644
--- a/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/toolbar/ToolbarActivity.java
+++ b/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/toolbar/ToolbarActivity.java
@@ -19,6 +19,7 @@
 import android.os.Bundle;
 import android.text.Editable;
 import android.text.InputType;
+import android.text.TextUtils;
 import android.text.TextWatcher;
 import android.util.Pair;
 import android.view.LayoutInflater;
@@ -55,9 +56,13 @@
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-        setContentView(R.layout.car_ui_recycler_view_activity);
+        setContentView(getLayout());
 
-        ToolbarController toolbar = CarUi.requireToolbar(this);
+        ToolbarController toolbarNonFinal = CarUi.getToolbar(this);
+        if (toolbarNonFinal == null) {
+            toolbarNonFinal = requireViewById(R.id.toolbar);
+        }
+        ToolbarController toolbar = toolbarNonFinal;
         toolbar.setTitle(getTitle());
         toolbar.setState(Toolbar.State.SUBPAGE);
         toolbar.setLogo(R.drawable.ic_launcher);
@@ -79,18 +84,21 @@
         toolbar.setMenuItems(mMenuItems);
 
         mButtons.add(Pair.create("Toggle progress bar", v -> {
-            if (toolbar.getProgressBar().getVisibility() == View.GONE) {
-                toolbar.showProgressBar();
-                Toast.makeText(this, "showing progress bar", Toast.LENGTH_SHORT).show();
-            } else {
-                toolbar.hideProgressBar();
-                Toast.makeText(this, "hiding progress bar", Toast.LENGTH_SHORT).show();
-            }
+            toolbar.getProgressBar().setVisible(!toolbar.getProgressBar().isVisible());
         }));
 
         mButtons.add(Pair.create("Change title", v ->
                 toolbar.setTitle(toolbar.getTitle() + " X")));
 
+        mButtons.add(Pair.create("Add/Change subtitle", v -> {
+            CharSequence subtitle = toolbar.getSubtitle();
+            if (TextUtils.isEmpty(subtitle)) {
+                toolbar.setSubtitle("Subtitle");
+            } else {
+                toolbar.setSubtitle(subtitle + " X");
+            }
+        }));
+
         mButtons.add(Pair.create(getString(R.string.toolbar_set_xml_resource), v -> {
             mMenuItems.clear();
             toolbar.setMenuItems(R.xml.menuitems);
@@ -116,19 +124,6 @@
             toolbar.setMenuItems(mMenuItems);
         }));
 
-        Mutable<Integer> overflowCounter = new Mutable<>(1);
-        mButtons.add(Pair.create(getString(R.string.toolbar_add_overflow), v -> {
-            mMenuItems.add(MenuItem.builder(this)
-                    .setTitle("Foo " + overflowCounter.value)
-                    .setOnClickListener(
-                            i -> Toast.makeText(this, "Clicked",
-                                    Toast.LENGTH_SHORT).show())
-                    .setDisplayBehavior(MenuItem.DisplayBehavior.NEVER)
-                    .build());
-            toolbar.setMenuItems(mMenuItems);
-            overflowCounter.value++;
-        }));
-
         mButtons.add(Pair.create(getString(R.string.toolbar_add_switch), v -> {
             mMenuItems.add(MenuItem.builder(this)
                     .setCheckable()
@@ -197,6 +192,47 @@
             toolbar.setMenuItems(mMenuItems);
         }));
 
+        Mutable<Integer> overflowCounter = new Mutable<>(1);
+        mButtons.add(Pair.create(getString(R.string.toolbar_add_overflow), v -> {
+            mMenuItems.add(MenuItem.builder(this)
+                    .setTitle("Foo " + overflowCounter.value)
+                    .setOnClickListener(
+                            i -> Toast.makeText(this, "Clicked",
+                                    Toast.LENGTH_SHORT).show())
+                    .setDisplayBehavior(MenuItem.DisplayBehavior.NEVER)
+                    .build());
+            toolbar.setMenuItems(mMenuItems);
+            overflowCounter.value++;
+        }));
+
+        mButtons.add(Pair.create(getString(R.string.toolbar_add_overflow_switch), v -> {
+            mMenuItems.add(MenuItem.builder(this)
+                    .setTitle("Foo " + overflowCounter.value)
+                    .setOnClickListener(
+                            i -> Toast.makeText(this,
+                                    i.isChecked() ? "Checked" : "Unchecked",
+                                    Toast.LENGTH_SHORT)
+                                    .show())
+                    .setDisplayBehavior(MenuItem.DisplayBehavior.NEVER)
+                    .setCheckable()
+                    .build());
+            toolbar.setMenuItems(mMenuItems);
+            overflowCounter.value++;
+        }));
+
+        mButtons.add(Pair.create(getString(R.string.toolbar_add_icon_text_overflow), v -> {
+            mMenuItems.add(MenuItem.builder(this)
+                    .setIcon(R.drawable.ic_tracklist)
+                    .setTitle("Bar")
+                    .setShowIconAndTitle(true)
+                    .setOnClickListener(
+                            i -> Toast.makeText(this, "Clicked",
+                                    Toast.LENGTH_SHORT).show())
+                    .setDisplayBehavior(MenuItem.DisplayBehavior.NEVER)
+                    .build());
+            toolbar.setMenuItems(mMenuItems);
+        }));
+
         mButtons.add(Pair.create(getString(R.string.toolbar_toggle_visibility),
                 v -> getMenuItem(item -> item.setVisible(!item.isVisible()))));
 
@@ -295,8 +331,13 @@
         prv.setAdapter(mAdapter);
     }
 
+    /** Override in subclasses to change the layout */
+    protected int getLayout() {
+        return R.layout.car_ui_recycler_view_activity;
+    }
+
     @Override
-    public void onCarUiInsetsChanged(Insets insets) {
+    public void onCarUiInsetsChanged(@NonNull Insets insets) {
         requireViewById(R.id.list)
                 .setPadding(0, insets.getTop(), 0, insets.getBottom());
         requireViewById(android.R.id.content)
diff --git a/car-ui-lib/tests/robotests/Android.bp b/car-ui-lib/tests/robotests/Android.bp
new file mode 100644
index 0000000..20e67ef
--- /dev/null
+++ b/car-ui-lib/tests/robotests/Android.bp
@@ -0,0 +1,53 @@
+//
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+//###########################################################
+// CarUi lib just for Robolectric test target.     #
+//###########################################################
+android_app {
+    name: "CarUi",
+
+    resource_dirs: [
+        "res",
+    ],
+
+    platform_apis: true,
+
+    privileged: true,
+
+    libs: ["android.car"],
+
+    static_libs: ["car-ui-lib"],
+
+}
+
+//###############################################
+// Car Ui Robolectric test target. #
+//###############################################
+android_robolectric_test {
+    name: "CarUiRoboTests",
+
+    srcs: ["src/**/*.java"],
+
+    java_resource_dirs: ["config"],
+
+    libs: [
+        "android.car",
+        "testng",
+    ],
+
+    instrumentation_for: "CarUi",
+}
diff --git a/car-ui-lib/tests/robotests/Android.mk b/car-ui-lib/tests/robotests/Android.mk
deleted file mode 100644
index a532bc9..0000000
--- a/car-ui-lib/tests/robotests/Android.mk
+++ /dev/null
@@ -1,90 +0,0 @@
-#
-# Copyright (C) 2019 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-LOCAL_PATH := $(call my-dir)
-
-############################################################
-# CarUi lib just for Robolectric test target.     #
-############################################################
-include $(CLEAR_VARS)
-
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res \
-    $(LOCAL_PATH)/tests/robotests/res \
-
-LOCAL_PACKAGE_NAME := CarUi
-LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_USE_AAPT2 := true
-
-LOCAL_PRIVILEGED_MODULE := true
-
-LOCAL_JAVA_LIBRARIES := android.car
-
-LOCAL_STATIC_ANDROID_LIBRARIES := \
-    car-ui-lib
-
-include $(BUILD_PACKAGE)
-
-################################################
-# Car Ui Robolectric test target. #
-################################################
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := CarUiRoboTests
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_JAVA_RESOURCE_DIRS := config
-
-# Include the testing libraries
-LOCAL_JAVA_LIBRARIES := \
-    android.car \
-    robolectric_android-all-stub \
-    Robolectric_all-target \
-    mockito-robolectric-prebuilt \
-    testng \
-    truth-prebuilt
-
-LOCAL_INSTRUMENTATION_FOR := CarUi
-
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
-##################################################################
-# Car Ui runner target to run the previous target. #
-##################################################################
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := RunCarUiRoboTests
-
-LOCAL_JAVA_LIBRARIES := \
-    android.car \
-    CarUiRoboTests \
-    robolectric_android-all-stub \
-    Robolectric_all-target \
-    mockito-robolectric-prebuilt \
-    testng \
-    truth-prebuilt
-
-LOCAL_TEST_PACKAGE := CarUi
-
-LOCAL_ROBOTEST_FILES := $(filter-out %/BaseRobolectricTest.java,\
-    $(call find-files-in-subdirs,$(LOCAL_PATH)/src,*Test.java,.))
-
-LOCAL_INSTRUMENT_SOURCE_DIRS := $(dir $(LOCAL_PATH))../src
-
-include external/robolectric-shadows/run_robotests.mk
diff --git a/car-ui-lib/tests/robotests/build.gradle b/car-ui-lib/tests/robotests/build.gradle
index b5876a3..88387b8 100644
--- a/car-ui-lib/tests/robotests/build.gradle
+++ b/car-ui-lib/tests/robotests/build.gradle
@@ -42,11 +42,11 @@
 apply plugin: 'com.android.library'
 
 android {
-    compileSdkVersion 28
+    compileSdkVersion 29
 
     defaultConfig {
         minSdkVersion 28
-        targetSdkVersion 28
+        targetSdkVersion 29
         versionCode 1
         versionName "1.0"
     }
@@ -77,7 +77,7 @@
 dependencies {
     implementation project(':')
     testImplementation "androidx.test.ext:junit:1.1.1"
-    testImplementation "org.robolectric:robolectric:4.0-alpha-3"
+    testImplementation 'org.robolectric:robolectric:4.2'
     testImplementation "org.mockito:mockito-core:2.19.0"
     testImplementation "com.google.truth:truth:0.29"
     testImplementation "org.testng:testng:6.9.9"
diff --git a/car-ui-lib/tests/robotests/config/robolectric.properties b/car-ui-lib/tests/robotests/config/robolectric.properties
index 8768f6b..849e07f 100644
--- a/car-ui-lib/tests/robotests/config/robolectric.properties
+++ b/car-ui-lib/tests/robotests/config/robolectric.properties
@@ -13,5 +13,4 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
-manifest=packages/apps/Car/libs/car-ui-lib/tests/robotests/AndroidManifest.xml
 sdk=NEWEST_SDK
diff --git a/car-ui-lib/tests/robotests/res/layout/test_grid_car_ui_recycler_view.xml b/car-ui-lib/tests/robotests/res/layout/test_grid_car_ui_recycler_view.xml
index c09d1c7..e5bf7a3 100644
--- a/car-ui-lib/tests/robotests/res/layout/test_grid_car_ui_recycler_view.xml
+++ b/car-ui-lib/tests/robotests/res/layout/test_grid_car_ui_recycler_view.xml
@@ -25,4 +25,4 @@
         app:numOfColumns="4"
         android:layout_width="match_parent"
         android:layout_height="match_parent"/>
-</FrameLayout>
\ No newline at end of file
+</FrameLayout>
diff --git a/car-ui-lib/tests/robotests/res/layout/test_linear_car_ui_recycler_view.xml b/car-ui-lib/tests/robotests/res/layout/test_linear_car_ui_recycler_view.xml
index e3b8218..8f7f2ad 100644
--- a/car-ui-lib/tests/robotests/res/layout/test_linear_car_ui_recycler_view.xml
+++ b/car-ui-lib/tests/robotests/res/layout/test_linear_car_ui_recycler_view.xml
@@ -22,4 +22,4 @@
         android:id="@+id/test_prv"
         android:layout_width="match_parent"
         android:layout_height="match_parent"/>
-</FrameLayout>
\ No newline at end of file
+</FrameLayout>
diff --git a/car-ui-lib/tests/robotests/res/layout/test_toolbar.xml b/car-ui-lib/tests/robotests/res/layout/test_toolbar.xml
new file mode 100644
index 0000000..19a1111
--- /dev/null
+++ b/car-ui-lib/tests/robotests/res/layout/test_toolbar.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2019 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+    <com.android.car.ui.toolbar.Toolbar
+        android:id="@+id/toolbar"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"/>
+</FrameLayout>
diff --git a/car-ui-lib/tests/robotests/src/com/android/car/ui/CarUiRobolectricTestRunner.java b/car-ui-lib/tests/robotests/src/com/android/car/ui/CarUiRobolectricTestRunner.java
deleted file mode 100644
index 20561f2..0000000
--- a/car-ui-lib/tests/robotests/src/com/android/car/ui/CarUiRobolectricTestRunner.java
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.car.ui;
-
-import androidx.annotation.NonNull;
-
-import org.junit.runners.model.InitializationError;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.annotation.Config;
-import org.robolectric.manifest.AndroidManifest;
-import org.robolectric.res.Fs;
-import org.robolectric.res.ResourcePath;
-
-import java.io.File;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Custom test runner for CarUi. This is needed because the default behavior for
- * robolectric is just to grab the resource directory in the target package.
- * We want to override this to add several spanning different projects.
- */
-public class CarUiRobolectricTestRunner extends RobolectricTestRunner {
-    private static final Map<String, String> AAR_VERSIONS;
-    private static final String SUPPORT_RESOURCE_PATH_TEMPLATE =
-            "jar:file:%3$s/prebuilts/sdk/current/androidx/m2repository/androidx/"
-                    + "%1$s/%1$s/%2$s/%1$s-%2$s.aar!/res";
-    // contraint-layout aar lives in separate path.
-    // Note its path contains a hyphen.
-    private static final String CONSTRAINT_LAYOUT_RESOURCE_PATH_TEMPLATE =
-            "jar:file:%3$s/prebuilts/sdk/current/extras/constraint-layout-x/"
-                    + "%1$s/%2$s/%1$s-%2$s.aar!/res";
-
-    static {
-        AAR_VERSIONS = new HashMap<>();
-        AAR_VERSIONS.put("appcompat", "1.1.0-alpha06");
-        AAR_VERSIONS.put("constraintlayout", "1.1.2");
-        AAR_VERSIONS.put("preference", "1.1.0-alpha06");
-    }
-
-    public CarUiRobolectricTestRunner(Class<?> testClass) throws InitializationError {
-        super(testClass);
-    }
-
-    private static ResourcePath createResourcePath(@NonNull String filePath) {
-        try {
-            return new ResourcePath(null, Fs.fromURL(new URL(filePath)), null);
-        } catch (MalformedURLException e) {
-            throw new RuntimeException("CarUiRobolectricTestRunner failure", e);
-        }
-    }
-
-    /**
-     * Create the resource path for a support library component's JAR.
-     */
-    private static String createSupportResourcePathFromJar(@NonNull String pathRoot,
-            @NonNull String componentId) {
-        if (!AAR_VERSIONS.containsKey(componentId)) {
-            throw new IllegalArgumentException("Unknown component " + componentId
-                    + ". Update test with appropriate component name and version.");
-        }
-        if (componentId.equals("constraintlayout")) {
-            return String.format(CONSTRAINT_LAYOUT_RESOURCE_PATH_TEMPLATE, componentId,
-                    AAR_VERSIONS.get(componentId), pathRoot);
-        }
-        return String.format(SUPPORT_RESOURCE_PATH_TEMPLATE, componentId,
-                AAR_VERSIONS.get(componentId), pathRoot);
-    }
-
-    /**
-     * We modify the AndroidManifest such that we can add required resources.
-     */
-    @Override
-    protected AndroidManifest getAppManifest(Config config) {
-        try {
-            final URL appRoot;
-            final String rootRelativePath;
-            // Root path is workspace root when run from command line and module root when run from
-            // Android Studio.
-            if (new File(System.getProperty("user.dir")).getName().equals("robotests")) {
-                rootRelativePath = "../../../../../../../.";
-                appRoot = new File("../../.").toURI().toURL();
-            } else {
-                appRoot = new URL("file:packages/apps/Car/libs/car-ui-lib/");
-                rootRelativePath = "./";
-            }
-
-            // Using the manifest file's relative path, we can figure out the application directory.
-            URL manifestPath = new URL(appRoot, "AndroidManifest.xml");
-            URL resDir = new URL(appRoot, "tests/robotests/res");
-            URL assetsDir = new URL(appRoot, config.assetDir());
-
-            // By adding any resources from libraries we need to the AndroidManifest, we can access
-            // them from within the parallel universe's resource loader.
-            return new AndroidManifest(Fs.fromURL(manifestPath), Fs.fromURL(resDir),
-                    Fs.fromURL(assetsDir)) {
-                @Override
-                public List<ResourcePath> getIncludedResourcePaths() {
-                    List<ResourcePath> paths = super.getIncludedResourcePaths();
-                    paths.add(createResourcePath(
-                            String.format("file:%s/packages/apps/Car/libs/car-ui-lib/res",
-                                    rootRelativePath)));
-
-                    // Support library resources. These need to point to the prebuilts of support
-                    // library and not the source.
-                    paths.add(createResourcePath(
-                            createSupportResourcePathFromJar(rootRelativePath, "appcompat")));
-                    paths.add(createResourcePath(createSupportResourcePathFromJar(rootRelativePath,
-                            "constraintlayout")));
-                    paths.add(createResourcePath(
-                            createSupportResourcePathFromJar(rootRelativePath, "preference")));
-
-                    return paths;
-                }
-            };
-        } catch (MalformedURLException e) {
-            throw new RuntimeException("CarUiRobolectricTestRunner failure", e);
-        }
-    }
-}
diff --git a/car-ui-lib/tests/robotests/src/com/android/car/ui/CarUiTestUtil.java b/car-ui-lib/tests/robotests/src/com/android/car/ui/CarUiTestUtil.java
deleted file mode 100644
index 407e3ef..0000000
--- a/car-ui-lib/tests/robotests/src/com/android/car/ui/CarUiTestUtil.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.car.ui;
-
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.isA;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.util.TypedValue;
-import android.view.LayoutInflater;
-
-import org.robolectric.RuntimeEnvironment;
-
-/**
- * Collection of test utility methods
- */
-public class CarUiTestUtil {
-
-    /**
-     * Returns a mocked {@link Context} to be used in Robolectric tests.
-     */
-    public static Context getMockContext() {
-        Context context = spy(RuntimeEnvironment.application);
-        Resources mResources = spy(context.getResources());
-
-        when(context.getResources()).thenReturn(mResources);
-
-        // Temporarily create a layout inflater that will be used to clone a new one.
-        LayoutInflater tempInflater = LayoutInflater.from(context);
-        // Force layout inflater to use spied context
-        doAnswer(invocation -> tempInflater.cloneInContext(context))
-                .when(context).getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-
-        // Older versions of Robolectric do not correctly handle the Resources#getValue() method.
-        // This breaks CarUtils.findViewByRefId() functionality in tests. To workaround this issue,
-        // use a spy to rely on findViewById() functionality instead.
-        doAnswer(invocation -> {
-            Object[] args = invocation.getArguments();
-            ((TypedValue) args[1]).resourceId = (int) args[0];
-            return null; // void method, so return null
-        }).when(mResources).getValue(anyInt(), isA(TypedValue.class), isA(Boolean.class));
-        return context;
-    }
-}
diff --git a/car-ui-lib/tests/robotests/src/com/android/car/ui/TestConfig.java b/car-ui-lib/tests/robotests/src/com/android/car/ui/TestConfig.java
deleted file mode 100644
index 46a9d0c..0000000
--- a/car-ui-lib/tests/robotests/src/com/android/car/ui/TestConfig.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.car.ui;
-
-public class TestConfig {
-    public static final int SDK_VERSION = 28;
-    public static final String MANIFEST_PATH =
-            "packages/apps/Car/car-ui-lib/AndroidManifest.xml";
-}
diff --git a/car-ui-lib/tests/robotests/src/com/android/car/ui/recyclerview/CarUiListItemTest.java b/car-ui-lib/tests/robotests/src/com/android/car/ui/recyclerview/CarUiListItemTest.java
index f404f6c..cf28632 100644
--- a/car-ui-lib/tests/robotests/src/com/android/car/ui/recyclerview/CarUiListItemTest.java
+++ b/car-ui-lib/tests/robotests/src/com/android/car/ui/recyclerview/CarUiListItemTest.java
@@ -27,23 +27,20 @@
 import android.widget.Switch;
 import android.widget.TextView;
 
-import com.android.car.ui.CarUiRobolectricTestRunner;
-import com.android.car.ui.CarUiTestUtil;
 import com.android.car.ui.R;
-import com.android.car.ui.TestConfig;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
 
 import java.util.ArrayList;
 import java.util.List;
 
-@RunWith(CarUiRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+@RunWith(RobolectricTestRunner.class)
 public class CarUiListItemTest {
 
     private CarUiRecyclerView mListView;
@@ -55,7 +52,7 @@
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
-        mContext = CarUiTestUtil.getMockContext();
+        mContext = RuntimeEnvironment.application;
         mListView = new CarUiRecyclerView(mContext);
     }
 
diff --git a/car-ui-lib/tests/robotests/src/com/android/car/ui/recyclerview/CarUiRecyclerViewAdapterTest.java b/car-ui-lib/tests/robotests/src/com/android/car/ui/recyclerview/CarUiRecyclerViewAdapterTest.java
index 6c8954c..4d21851 100644
--- a/car-ui-lib/tests/robotests/src/com/android/car/ui/recyclerview/CarUiRecyclerViewAdapterTest.java
+++ b/car-ui-lib/tests/robotests/src/com/android/car/ui/recyclerview/CarUiRecyclerViewAdapterTest.java
@@ -24,19 +24,15 @@
 import android.content.Context;
 import android.view.ViewGroup;
 
-import com.android.car.ui.CarUiRobolectricTestRunner;
-import com.android.car.ui.CarUiTestUtil;
-import com.android.car.ui.TestConfig;
-
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
 
-@RunWith(CarUiRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+@RunWith(RobolectricTestRunner.class)
 public class CarUiRecyclerViewAdapterTest {
 
     private Context mContext;
@@ -50,7 +46,8 @@
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
-        mContext = CarUiTestUtil.getMockContext();
+
+        mContext = RuntimeEnvironment.application;
         mCarUiRecyclerViewAdapter = new CarUiRecyclerViewAdapter();
     }
 
diff --git a/car-ui-lib/tests/robotests/src/com/android/car/ui/recyclerview/CarUiRecyclerViewTest.java b/car-ui-lib/tests/robotests/src/com/android/car/ui/recyclerview/CarUiRecyclerViewTest.java
index f4d98f7..c0b87de 100644
--- a/car-ui-lib/tests/robotests/src/com/android/car/ui/recyclerview/CarUiRecyclerViewTest.java
+++ b/car-ui-lib/tests/robotests/src/com/android/car/ui/recyclerview/CarUiRecyclerViewTest.java
@@ -25,20 +25,17 @@
 import androidx.recyclerview.widget.GridLayoutManager;
 import androidx.recyclerview.widget.LinearLayoutManager;
 
-import com.android.car.ui.CarUiRobolectricTestRunner;
 import com.android.car.ui.R;
-import com.android.car.ui.TestConfig;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.MockitoAnnotations;
 import org.robolectric.Robolectric;
+import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
 
-@RunWith(CarUiRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+@RunWith(RobolectricTestRunner.class)
 public class CarUiRecyclerViewTest {
 
     private Context mContext;
@@ -79,7 +76,7 @@
 
         mCarUiRecyclerView = mView.findViewById(R.id.test_prv);
 
-        assertThat(mCarUiRecyclerView.getEffectiveLayoutManager()).isInstanceOf(
+        assertThat(mCarUiRecyclerView.getLayoutManager()).isInstanceOf(
                 LinearLayoutManager.class);
     }
 
@@ -90,7 +87,7 @@
 
         mCarUiRecyclerView = mView.findViewById(R.id.test_prv);
 
-        assertThat(mCarUiRecyclerView.getEffectiveLayoutManager()).isInstanceOf(
+        assertThat(mCarUiRecyclerView.getLayoutManager()).isInstanceOf(
                 GridLayoutManager.class);
     }
 
@@ -108,7 +105,7 @@
     public void init_shouldHaveGridLayout() {
         mCarUiRecyclerView = new CarUiRecyclerView(mContext,
                 Robolectric.buildAttributeSet().addAttribute(R.attr.layoutStyle, "grid").build());
-        assertThat(mCarUiRecyclerView.getEffectiveLayoutManager()).isInstanceOf(
+        assertThat(mCarUiRecyclerView.getLayoutManager()).isInstanceOf(
                 GridLayoutManager.class);
     }
 }
diff --git a/car-ui-lib/tests/robotests/src/com/android/car/ui/recyclerview/CarUiSmoothScrollerTest.java b/car-ui-lib/tests/robotests/src/com/android/car/ui/recyclerview/CarUiSmoothScrollerTest.java
index 052304c..c5dc78b 100644
--- a/car-ui-lib/tests/robotests/src/com/android/car/ui/recyclerview/CarUiSmoothScrollerTest.java
+++ b/car-ui-lib/tests/robotests/src/com/android/car/ui/recyclerview/CarUiSmoothScrollerTest.java
@@ -22,17 +22,13 @@
 
 import android.content.Context;
 
-import com.android.car.ui.CarUiRobolectricTestRunner;
-import com.android.car.ui.TestConfig;
-
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
 
-@RunWith(CarUiRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+@RunWith(RobolectricTestRunner.class)
 public class CarUiSmoothScrollerTest {
 
     private Context mContext;
diff --git a/car-ui-lib/tests/robotests/src/com/android/car/ui/recyclerview/CarUiSnapHelperTest.java b/car-ui-lib/tests/robotests/src/com/android/car/ui/recyclerview/CarUiSnapHelperTest.java
index b846103..62edd3d 100644
--- a/car-ui-lib/tests/robotests/src/com/android/car/ui/recyclerview/CarUiSnapHelperTest.java
+++ b/car-ui-lib/tests/robotests/src/com/android/car/ui/recyclerview/CarUiSnapHelperTest.java
@@ -66,6 +66,7 @@
     @Test
     public void calculateDistanceToFinalSnap_shouldReturnTopMarginDifference() {
         when(mRecyclerView.getLayoutManager()).thenReturn(mLayoutManager);
+        when(mRecyclerView.isInTouchMode()).thenReturn(true);
         when(mLayoutManager.getItemCount()).thenReturn(1);
         when(mLayoutManager.canScrollVertically()).thenReturn(true);
         when(mLayoutManager.getChildCount()).thenReturn(1);
diff --git a/car-ui-lib/tests/robotests/src/com/android/car/ui/recyclerview/DefaultScrollBarTest.java b/car-ui-lib/tests/robotests/src/com/android/car/ui/recyclerview/DefaultScrollBarTest.java
index 612f463..1cd59df 100644
--- a/car-ui-lib/tests/robotests/src/com/android/car/ui/recyclerview/DefaultScrollBarTest.java
+++ b/car-ui-lib/tests/robotests/src/com/android/car/ui/recyclerview/DefaultScrollBarTest.java
@@ -31,20 +31,17 @@
 
 import androidx.recyclerview.widget.RecyclerView;
 
-import com.android.car.ui.CarUiRobolectricTestRunner;
-import com.android.car.ui.CarUiTestUtil;
 import com.android.car.ui.R;
-import com.android.car.ui.TestConfig;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
 
-@RunWith(CarUiRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+@RunWith(RobolectricTestRunner.class)
 public class DefaultScrollBarTest {
 
     private Context mContext;
@@ -62,7 +59,8 @@
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
-        mContext = CarUiTestUtil.getMockContext();
+        mContext = RuntimeEnvironment.application;
+
         mScrollBar = new DefaultScrollBar();
     }
 
@@ -123,10 +121,8 @@
         mScrollBar.initialize(mRecyclerView, scrollView);
         mScrollBar.setPadding(10, 20);
 
-        DefaultScrollBar defaultScrollBar = (DefaultScrollBar) mScrollBar;
-
-        assertThat(defaultScrollBar.mPaddingStart).isEqualTo(10);
-        assertThat(defaultScrollBar.mPaddingEnd).isEqualTo(20);
+        assertThat(scrollView.getPaddingTop()).isEqualTo(10);
+        assertThat(scrollView.getPaddingBottom()).isEqualTo(20);
     }
 
     @Test
diff --git a/car-ui-lib/tests/robotests/src/com/android/car/ui/toolbar/TestActivity.java b/car-ui-lib/tests/robotests/src/com/android/car/ui/toolbar/TestActivity.java
new file mode 100644
index 0000000..dcbe1cd
--- /dev/null
+++ b/car-ui-lib/tests/robotests/src/com/android/car/ui/toolbar/TestActivity.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.car.ui.toolbar;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+import com.android.car.ui.R;
+
+/** An activity to use in the Toolbar tests */
+public class TestActivity extends Activity {
+
+    private int mTimesBackPressed = 0;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.test_toolbar);
+    }
+
+    @Override
+    public void onBackPressed() {
+        mTimesBackPressed++;
+        super.onBackPressed();
+    }
+
+    public int getTimesBackPressed() {
+        return mTimesBackPressed;
+    }
+}
diff --git a/car-ui-lib/tests/robotests/src/com/android/car/ui/toolbar/ToolbarTest.java b/car-ui-lib/tests/robotests/src/com/android/car/ui/toolbar/ToolbarTest.java
index 78aab7d..6cd127b 100644
--- a/car-ui-lib/tests/robotests/src/com/android/car/ui/toolbar/ToolbarTest.java
+++ b/car-ui-lib/tests/robotests/src/com/android/car/ui/toolbar/ToolbarTest.java
@@ -18,40 +18,49 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
 import android.content.res.Resources;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.ViewParent;
 
-import com.android.car.ui.CarUiRobolectricTestRunner;
-import com.android.car.ui.CarUiTestUtil;
 import com.android.car.ui.R;
-import com.android.car.ui.TestConfig;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.robolectric.Robolectric;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.android.controller.ActivityController;
 import org.robolectric.annotation.Config;
 
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
 
-@RunWith(CarUiRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION,
-        shadows = {ExtendedShadowTypeface.class, ShadowAsyncLayoutInflater.class})
+@RunWith(RobolectricTestRunner.class)
+@Config(shadows = {ExtendedShadowTypeface.class, ShadowAsyncLayoutInflater.class},
+        qualifiers = "land")
 public class ToolbarTest {
+
     private Context mContext;
     private Resources mResources;
+    private ActivityController<TestActivity> mActivityController;
+    private TestActivity mActivity;
     private Toolbar mToolbar;
 
     @Before
     public void setUp() {
-        mContext = CarUiTestUtil.getMockContext();
+        mContext = RuntimeEnvironment.application;
         mResources = mContext.getResources();
-        mToolbar = new Toolbar(mContext);
+        mActivityController = Robolectric.buildActivity(TestActivity.class);
+        mActivityController.setup();
+        mActivity = mActivityController.get();
+        mToolbar = mActivity.findViewById(R.id.toolbar);
     }
 
     @Test
@@ -93,26 +102,21 @@
         mToolbar.setState(Toolbar.State.HOME);
         mToolbar.setLogo(R.drawable.test_ic_launcher);
 
-        assertThat(mToolbar.findViewById(R.id.car_ui_toolbar_nav_icon_container).getVisibility())
-                .isEqualTo(View.VISIBLE);
-        assertThat(mToolbar.findViewById(R.id.car_ui_toolbar_logo).getVisibility())
-                .isEqualTo(View.VISIBLE);
-        assertThat(mToolbar.findViewById(R.id.car_ui_toolbar_title_logo_container).getVisibility())
-                .isNotEqualTo(View.VISIBLE);
+        assertThat(mToolbar.findViewById(R.id.car_ui_toolbar_logo).isShown()).isTrue();
+        assertThat(mToolbar.findViewById(R.id.car_ui_toolbar_title_logo).isShown()).isFalse();
     }
 
     @Test
     public void hideLogo_andTitleLogo_whenSet_andStateIsHome_andLogoIsDisabled() {
+        mockResources();
         when(mResources.getBoolean(R.bool.car_ui_toolbar_show_logo)).thenReturn(false);
 
         Toolbar toolbar = new Toolbar(mContext);
         toolbar.setState(Toolbar.State.HOME);
         toolbar.setLogo(R.drawable.test_ic_launcher);
 
-        assertThat(mToolbar.findViewById(R.id.car_ui_toolbar_nav_icon_container).getVisibility())
-                .isNotEqualTo(View.VISIBLE);
-        assertThat(mToolbar.findViewById(R.id.car_ui_toolbar_title_logo_container).getVisibility())
-                .isNotEqualTo(View.VISIBLE);
+        assertThat(isViewInToolbarShown(toolbar, R.id.car_ui_toolbar_logo)).isFalse();
+        assertThat(isViewInToolbarShown(toolbar, R.id.car_ui_toolbar_title_logo)).isFalse();
     }
 
     @Test
@@ -120,12 +124,8 @@
         mToolbar.setState(Toolbar.State.SUBPAGE);
         mToolbar.setLogo(R.drawable.test_ic_launcher);
 
-        assertThat(mToolbar.findViewById(R.id.car_ui_toolbar_nav_icon_container).getVisibility())
-                .isEqualTo(View.VISIBLE);
-        assertThat(mToolbar.findViewById(R.id.car_ui_toolbar_title_logo_container).getVisibility())
-                .isEqualTo(View.VISIBLE);
-        assertThat(mToolbar.findViewById(R.id.car_ui_toolbar_title_logo).getVisibility())
-                .isEqualTo(View.VISIBLE);
+        assertThat(mToolbar.findViewById(R.id.car_ui_toolbar_logo).isShown()).isFalse();
+        assertThat(mToolbar.findViewById(R.id.car_ui_toolbar_title_logo).isShown()).isTrue();
     }
 
     @Test
@@ -133,20 +133,17 @@
         mToolbar.setState(Toolbar.State.HOME);
         mToolbar.setLogo(0);
 
-        assertThat(mToolbar.findViewById(R.id.car_ui_toolbar_nav_icon_container).getVisibility())
-                .isNotEqualTo(View.VISIBLE);
-        assertThat(mToolbar.findViewById(R.id.car_ui_toolbar_title_logo_container).getVisibility())
-                .isNotEqualTo(View.VISIBLE);    }
+        assertThat(mToolbar.findViewById(R.id.car_ui_toolbar_logo).isShown()).isFalse();
+        assertThat(mToolbar.findViewById(R.id.car_ui_toolbar_title_logo).isShown()).isFalse();
+    }
 
     @Test
     public void hideLogo_andTitleLogo_whenNotSet_andStateIsNotHome() {
         mToolbar.setState(Toolbar.State.SUBPAGE);
         mToolbar.setLogo(0);
 
-        assertThat(mToolbar.findViewById(R.id.car_ui_toolbar_logo).getVisibility())
-                .isNotEqualTo(View.VISIBLE);
-        assertThat(mToolbar.findViewById(R.id.car_ui_toolbar_title_logo_container).getVisibility())
-                .isNotEqualTo(View.VISIBLE);
+        assertThat(mToolbar.findViewById(R.id.car_ui_toolbar_logo).isShown()).isFalse();
+        assertThat(mToolbar.findViewById(R.id.car_ui_toolbar_title_logo).isShown()).isFalse();
     }
 
     @Test
@@ -162,10 +159,24 @@
         pressBack();
 
         assertThat(timesBackPressed.value).isEqualTo(1);
+        assertThat(mActivity.getTimesBackPressed()).isEqualTo(1);
+    }
+
+    @Test
+    public void registerOnBackListener_whenAListenerReturnsTrue_shouldSuppressBack() {
+        mToolbar.setState(Toolbar.State.SUBPAGE);
+
+        mToolbar.registerOnBackListener(() -> true);
+        pressBack();
+        mToolbar.registerOnBackListener(() -> false);
+        pressBack();
+
+        assertThat(mActivity.getTimesBackPressed()).isEqualTo(0);
     }
 
     @Test
     public void testState_twoRow_withTitle_withTabs() {
+        mockResources();
         when(mResources.getBoolean(R.bool.car_ui_toolbar_tabs_on_second_row)).thenReturn(true);
 
         Toolbar toolbar = new Toolbar(mContext);
@@ -177,14 +188,13 @@
         toolbar.addTab(new TabLayout.Tab(mContext.getDrawable(R.drawable.test_ic_launcher), "Foo"));
 
         // Toolbar should display two rows, showing both title and tabs.
-        assertThat(toolbar.findViewById(R.id.car_ui_toolbar_tabs).getVisibility()).isEqualTo(
-                View.VISIBLE);
-        assertThat(toolbar.findViewById(R.id.car_ui_toolbar_title).getVisibility()).isEqualTo(
-                View.VISIBLE);
+        assertThat(isViewInToolbarShown(toolbar, R.id.car_ui_toolbar_tabs)).isTrue();
+        assertThat(isViewInToolbarShown(toolbar, R.id.car_ui_toolbar_title)).isTrue();
     }
 
     @Test
-    public void testState_twoRow_withTitle() {
+    public void testState_twoRow_withTitle()  {
+        mockResources();
         when(mResources.getBoolean(R.bool.car_ui_toolbar_tabs_on_second_row)).thenReturn(true);
 
         Toolbar toolbar = new Toolbar(mContext);
@@ -193,14 +203,13 @@
         toolbar.setTitle("Test title");
 
         // Toolbar should display two rows, but no tabs are set so they should not be visible.
-        assertThat(toolbar.findViewById(R.id.car_ui_toolbar_title).getVisibility()).isEqualTo(
-                View.VISIBLE);
-        assertThat(toolbar.findViewById(R.id.car_ui_toolbar_tabs).getVisibility()).isNotEqualTo(
-                View.VISIBLE);
+        assertThat(isViewInToolbarShown(toolbar, R.id.car_ui_toolbar_title)).isTrue();
+        assertThat(isViewInToolbarShown(toolbar, R.id.car_ui_toolbar_tabs)).isFalse();
     }
 
     @Test
     public void testState_twoRow_withTabs() {
+        mockResources();
         when(mResources.getBoolean(R.bool.car_ui_toolbar_tabs_on_second_row)).thenReturn(true);
 
         Toolbar toolbar = new Toolbar(mContext);
@@ -209,14 +218,13 @@
         toolbar.addTab(new TabLayout.Tab(mContext.getDrawable(R.drawable.test_ic_launcher), "Foo"));
 
         // Toolbar should display two rows with an empty title and tabs.
-        assertThat(toolbar.findViewById(R.id.car_ui_toolbar_tabs).getVisibility()).isEqualTo(
-                View.VISIBLE);
-        assertThat(toolbar.findViewById(R.id.car_ui_toolbar_title).getVisibility()).isEqualTo(
-                View.VISIBLE);
+        assertThat(isViewInToolbarShown(toolbar, R.id.car_ui_toolbar_tabs)).isTrue();
+        assertThat(isViewInToolbarShown(toolbar, R.id.car_ui_toolbar_title)).isTrue();
     }
 
     @Test
     public void testState_oneRow_withTitle_withTabs() {
+        mockResources();
         when(mResources.getBoolean(R.bool.car_ui_toolbar_tabs_on_second_row)).thenReturn(false);
 
         Toolbar toolbar = new Toolbar(mContext);
@@ -228,30 +236,29 @@
         toolbar.addTab(new TabLayout.Tab(mContext.getDrawable(R.drawable.test_ic_launcher), "Foo"));
 
         // With only one row available, toolbar will only show tabs and not the title.
-        assertThat(toolbar.findViewById(R.id.car_ui_toolbar_tabs).getVisibility()).isEqualTo(
-                View.VISIBLE);
-        assertThat(toolbar.findViewById(R.id.car_ui_toolbar_title).getVisibility()).isNotEqualTo(
-                View.VISIBLE);
+        assertThat(isViewInToolbarShown(toolbar, R.id.car_ui_toolbar_tabs)).isTrue();
+        assertThat(isViewInToolbarShown(toolbar, R.id.car_ui_toolbar_title)).isFalse();
     }
 
     @Test
     public void testState_oneRow_withTitle() {
+        mockResources();
         when(mResources.getBoolean(R.bool.car_ui_toolbar_tabs_on_second_row)).thenReturn(false);
 
+
         Toolbar toolbar = new Toolbar(mContext);
         assertThat(toolbar.isTabsInSecondRow()).isFalse();
 
         toolbar.setTitle("Test title");
 
         // Toolbar should display one row with the title and no tabs.
-        assertThat(toolbar.findViewById(R.id.car_ui_toolbar_tabs).getVisibility()).isNotEqualTo(
-                View.VISIBLE);
-        assertThat(toolbar.findViewById(R.id.car_ui_toolbar_title).getVisibility()).isEqualTo(
-                View.VISIBLE);
+        assertThat(isViewInToolbarShown(toolbar, R.id.car_ui_toolbar_tabs)).isFalse();
+        assertThat(isViewInToolbarShown(toolbar, R.id.car_ui_toolbar_title)).isTrue();
     }
 
     @Test
     public void testState_oneRow_withTabs() {
+        mockResources();
         when(mResources.getBoolean(R.bool.car_ui_toolbar_tabs_on_second_row)).thenReturn(false);
 
 
@@ -262,10 +269,8 @@
         toolbar.addTab(new TabLayout.Tab(mContext.getDrawable(R.drawable.test_ic_launcher), "Foo"));
 
         // Toolbar should display one row with only tabs.
-        assertThat(toolbar.findViewById(R.id.car_ui_toolbar_tabs).getVisibility()).isEqualTo(
-                View.VISIBLE);
-        assertThat(toolbar.findViewById(R.id.car_ui_toolbar_title).getVisibility()).isNotEqualTo(
-                View.VISIBLE);
+        assertThat(isViewInToolbarShown(toolbar, R.id.car_ui_toolbar_tabs)).isTrue();
+        assertThat(isViewInToolbarShown(toolbar, R.id.car_ui_toolbar_title)).isFalse();
     }
 
     @Test
@@ -363,7 +368,7 @@
         });
         mToolbar.setMenuItems(Collections.singletonList(item));
 
-        assertThat(getMenuItemView(0).getVisibility()).isEqualTo(View.VISIBLE);
+        assertThat(getMenuItemView(0).isShown()).isTrue();
     }
 
     @Test
@@ -373,7 +378,7 @@
         mToolbar.setMenuItems(Collections.singletonList(item));
 
         item.setVisible(false);
-        assertThat(getMenuItemView(0).getVisibility()).isNotEqualTo(View.VISIBLE);
+        assertThat(getMenuItemView(0).isShown()).isFalse();
     }
 
     @Test
@@ -384,7 +389,7 @@
 
         item.setVisible(false);
         item.setVisible(true);
-        assertThat(getMenuItemView(0).getVisibility()).isEqualTo(View.VISIBLE);
+        assertThat(getMenuItemView(0).isShown()).isTrue();
     }
 
     @Test
@@ -415,8 +420,8 @@
         mToolbar.setShowMenuItemsWhileSearching(false);
         mToolbar.setState(Toolbar.State.SEARCH);
 
-        assertThat(mToolbar.findViewById(R.id.car_ui_toolbar_menu_items_container).getVisibility())
-                .isNotEqualTo(View.VISIBLE);
+        assertThat(getMenuItemView(0).isShown()).isFalse();
+        assertThat(getMenuItemView(1).isShown()).isFalse();
     }
 
     @Test
@@ -429,10 +434,8 @@
         mToolbar.setShowMenuItemsWhileSearching(true);
         mToolbar.setState(Toolbar.State.SEARCH);
 
-        assertThat(mToolbar.findViewById(R.id.car_ui_toolbar_menu_items_container).getVisibility())
-                .isEqualTo(View.VISIBLE);
-        assertThat(getMenuItemView(0).getVisibility()).isNotEqualTo(View.VISIBLE);
-        assertThat(getMenuItemView(1).getVisibility()).isEqualTo(View.VISIBLE);
+        assertThat(getMenuItemView(0).isShown()).isFalse();
+        assertThat(getMenuItemView(1).isShown()).isTrue();
     }
 
     private MenuItem createMenuItem(MenuItem.OnClickListener listener) {
@@ -442,10 +445,42 @@
                 .build();
     }
 
+    private void mockResources() {
+        mContext = spy(RuntimeEnvironment.application);
+        mResources = spy(mContext.getResources());
+        when(mContext.getResources()).thenReturn(mResources);
+    }
+
     private int getMenuItemCount() {
         return mToolbar.getMenuItems().size();
     }
 
+    /**
+     * IsShown() will return false for views that are not attached to an activity.
+     * This altered version will return true for that case.
+     */
+    private boolean isViewInToolbarShown(Toolbar toolbar, int id) {
+        View current = toolbar.findViewById(id);
+        //noinspection ConstantConditions
+        do {
+            if (current.getVisibility() != View.VISIBLE) {
+                return false;
+            }
+            ViewParent parent = current.getParent();
+            if (parent == null) {
+                return false; // We are not attached to the view root
+            }
+            if (parent == toolbar || !(parent instanceof View)) {
+                // Return true if we hit the toolbar, or this parent isn't a view.
+                // The parent wouldn't be a view if it was a ViewRootImpl, the parent
+                // of a whole view hierarchy
+                return true;
+            }
+            current = (View) parent;
+        } while (current != null);
+        return false;
+    }
+
     private View getMenuItemView(int index) {
         return ((ViewGroup) mToolbar
                 .findViewById(R.id.car_ui_toolbar_menu_items_container))
diff --git a/car-ui-lib/tests/robotests/src/com/android/car/ui/utils/CarUxRestrictionsUtilTest.java b/car-ui-lib/tests/robotests/src/com/android/car/ui/utils/CarUxRestrictionsUtilTest.java
index fe6f80c..ea62ee5 100644
--- a/car-ui-lib/tests/robotests/src/com/android/car/ui/utils/CarUxRestrictionsUtilTest.java
+++ b/car-ui-lib/tests/robotests/src/com/android/car/ui/utils/CarUxRestrictionsUtilTest.java
@@ -20,17 +20,13 @@
 
 import android.car.drivingstate.CarUxRestrictions;
 
-import com.android.car.ui.TestConfig;
-
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RobolectricTestRunner;
-import org.robolectric.annotation.Config;
 
 @RunWith(RobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class CarUxRestrictionsUtilTest {
     private int[] mRestrictionsArray;
 
diff --git a/car-ui-lib/tests/tools/quick_rro.py b/car-ui-lib/tests/tools/quick_rro.py
index 3d7d9ea..aaf186b 100755
--- a/car-ui-lib/tests/tools/quick_rro.py
+++ b/car-ui-lib/tests/tools/quick_rro.py
@@ -142,11 +142,11 @@
     if len(packages) == 0:
         print('No quick RROs to uninstall')
 
-def delete_arsc_flat_files(path):
-    """Deletes all .arsc.flat files under `path`"""
+def delete_flat_files(path):
+    """Deletes all .flat files under `path`"""
     for filename in os.listdir(path):
-        if filename.endswith('.arsc.flat'):
-            run_command(['rm', os.path.join(path, filename)])
+        if filename.endswith('.flat'):
+            os.remove(os.path.join(path, filename))
 
 def build(args, package_name):
     """Builds the RRO apk"""
@@ -200,7 +200,7 @@
     run_command(['aapt2', 'compile', '-o', os.path.join(root_folder, 'compiled.zip'),
                  '--dir', resource_folder])
 
-    delete_arsc_flat_files(root_folder)
+    delete_flat_files(root_folder)
 
     run_command(['unzip', os.path.join(root_folder, 'compiled.zip'),
                  '-d', root_folder])
@@ -209,14 +209,14 @@
                     '-o', unsigned_apk, '--manifest', manifest_file,
                     '-I', android_jar_path]
     for filename in os.listdir(root_folder):
-        if filename.endswith('.arsc.flat'):
+        if filename.endswith('.flat'):
             link_command.extend(['-R', os.path.join(root_folder, filename)])
     run_command(link_command)
 
-    # For some reason signapk.jar requires a relative path to out/host/linux-x86/lib64
+    # For some reason signapk.jar requires a relative path to out/soong/host/linux-x86/lib64
     os.chdir(os.environ['ANDROID_BUILD_TOP'])
-    run_command(['java', '-Djava.library.path=out/host/linux-x86/lib64',
-                 '-jar', 'out/host/linux-x86/framework/signapk.jar',
+    run_command(['java', '-Djava.library.path=out/soong/host/linux-x86/lib64',
+                 '-jar', 'out/soong/host/linux-x86/framework/signapk.jar',
                  'build/target/product/security/platform.x509.pem',
                  'build/target/product/security/platform.pk8',
                  unsigned_apk, signed_apk])
@@ -281,8 +281,8 @@
         sys.exit(1)
 
     if not os.path.isfile(os.path.join(
-            os.environ['ANDROID_BUILD_TOP'], 'out/host/linux-x86/framework/signapk.jar')):
-        print('out/host/linux-x86/framework/signapk.jar missing, please do an android build first')
+            os.environ['ANDROID_BUILD_TOP'], 'out/soong/host/linux-x86/framework/signapk.jar')):
+        print('out/soong/host/linux-x86/framework/signapk.jar missing, please do an android build first')
         sys.exit(1)
 
     package_name = get_package_name(args)
@@ -299,7 +299,7 @@
     print('Enabling...')
     # Enabling RROs sometimes fails shortly after installing them
     time.sleep(1)
-    run_command(['adb', 'shell', 'cmd', 'overlay', 'enable', '--user', '10', package_name])
+    run_command(['adb', 'shell', 'cmd', 'overlay', 'enable', '--user', 'current', package_name])
 
     print('Done!')
 
diff --git a/car-ui-lib/tests/unit/Android.bp b/car-ui-lib/tests/unit/Android.bp
new file mode 100644
index 0000000..da5f41d
--- /dev/null
+++ b/car-ui-lib/tests/unit/Android.bp
@@ -0,0 +1,48 @@
+//
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+android_test {
+    name: "CarUILibUnitTests",
+    certificate: "platform",
+    libs: [
+        "android.test.runner",
+        "android.test.base",
+        "android.car"
+    ],
+    resource_dirs: [
+        "res",
+    ],
+    static_libs: [
+        "androidx.test.rules",
+        "androidx.test.espresso.core",
+	"androidx.test.espresso.contrib",
+        "car-ui-lib",
+        "platform-test-annotations",
+        "mockito-target-inline-minus-junit4",
+        "truth-prebuilt",
+    ],
+
+    jni_libs: [
+        // For mockito extended
+        "libdexmakerjvmtiagent",
+        "libstaticjvmtiagent",
+    ],
+
+    // Include all test java files.
+    srcs: ["src/**/*.java"],
+
+    platform_apis: true,
+    test_suites: ["device-tests"],
+}
diff --git a/car-ui-lib/tests/unit/AndroidManifest.xml b/car-ui-lib/tests/unit/AndroidManifest.xml
new file mode 100644
index 0000000..e499db5
--- /dev/null
+++ b/car-ui-lib/tests/unit/AndroidManifest.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2020 Google Inc.
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.android.car.ui.tests.unit">
+    <application android:debuggable="true">
+        <uses-library android:name="android.test.runner" />
+        <activity android:name="com.android.car.ui.TestActivity" />
+        <activity android:name="com.android.car.ui.recyclerview.CarUiRecyclerViewTestActivity" />
+        <activity android:name="com.android.car.ui.FocusAreaTestActivity" />
+        <activity android:name="com.android.car.ui.FocusParkingViewTestActivity" />
+        <activity
+            android:name="com.android.car.ui.toolbar.ToolbarTestActivity"
+            android:theme="@style/Theme.CarUi.WithToolbar"/>
+    </application>
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+        android:targetPackage="com.android.car.ui.tests.unit"
+        android:label="Chassis Test Cases">
+    </instrumentation>
+</manifest>
diff --git a/car-ui-lib/tests/unit/build.gradle b/car-ui-lib/tests/unit/build.gradle
new file mode 100644
index 0000000..2a80132
--- /dev/null
+++ b/car-ui-lib/tests/unit/build.gradle
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+
+buildscript {
+    repositories {
+        google()
+        jcenter()
+    }
+
+    dependencies {
+        classpath 'com.android.tools.build:gradle:3.5.3'
+
+        // NOTE: Do not place your application dependencies here; they belong
+        // in the individual module build.gradle files
+    }
+}
+
+allprojects {
+    repositories {
+        google()
+        jcenter()
+    }
+}
+
+// Library-level build file
+
+apply plugin: 'com.android.library'
+
+android {
+    compileSdkVersion 29
+
+    defaultConfig {
+        minSdkVersion 28
+        targetSdkVersion 29
+        versionCode 1
+        versionName "1.0"
+        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+    }
+
+    compileOptions {
+        sourceCompatibility JavaVersion.VERSION_1_8
+        targetCompatibility JavaVersion.VERSION_1_8
+    }
+
+    sourceSets {
+        main {
+            manifest.srcFile 'AndroidManifest.xml'
+            res.srcDirs = ['res']
+        }
+
+        androidTest {
+            java.srcDirs = ['src']
+        }
+    }
+
+    testOptions {
+        unitTests {
+            includeAndroidResources = true
+        }
+    }
+}
+
+dependencies {
+    implementation project(':')
+
+    androidTestImplementation 'org.hamcrest:hamcrest-library:1.3'
+    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
+    androidTestImplementation 'androidx.test.espresso:espresso-contrib:3.2.0'
+    androidTestImplementation "com.google.truth:truth:0.29"
+    androidTestImplementation "androidx.test.ext:junit:1.1.1"
+    androidTestImplementation "org.mockito:mockito-core:2.19.0"
+    androidTestImplementation 'androidx.test:runner:1.1.0'
+    androidTestImplementation 'androidx.test:rules:1.1.0'
+
+    // This is needed to be able to spy certain classes with Mockito
+    // It's major/minor version must match Mockito's.
+    androidTestImplementation 'com.linkedin.dexmaker:dexmaker-mockito:2.19.0'
+
+    // This is the gradle equivalent of linking to android.car in our Android.mk
+    implementation files('../../../../../../../out/target/common/obj/JAVA_LIBRARIES/android.car_intermediates/classes.jar')
+}
diff --git a/car-ui-lib/tests/unit/res/drawable/ic_launcher.png b/car-ui-lib/tests/unit/res/drawable/ic_launcher.png
new file mode 100644
index 0000000..2af53a4
--- /dev/null
+++ b/car-ui-lib/tests/unit/res/drawable/ic_launcher.png
Binary files differ
diff --git a/car-ui-lib/tests/unit/res/layout/car_ui_recycler_view_gone_test_activity.xml b/car-ui-lib/tests/unit/res/layout/car_ui_recycler_view_gone_test_activity.xml
new file mode 100644
index 0000000..4ba25eb
--- /dev/null
+++ b/car-ui-lib/tests/unit/res/layout/car_ui_recycler_view_gone_test_activity.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2020 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+    <com.android.car.ui.recyclerview.CarUiRecyclerView
+        android:id="@+id/list"
+        android:visibility="gone"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"/>
+</FrameLayout>
diff --git a/car-ui-lib/tests/unit/res/layout/car_ui_recycler_view_invisible_test_activity.xml b/car-ui-lib/tests/unit/res/layout/car_ui_recycler_view_invisible_test_activity.xml
new file mode 100644
index 0000000..647c79b
--- /dev/null
+++ b/car-ui-lib/tests/unit/res/layout/car_ui_recycler_view_invisible_test_activity.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2020 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+    <com.android.car.ui.recyclerview.CarUiRecyclerView
+        android:id="@+id/list"
+        android:visibility="invisible"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"/>
+</FrameLayout>
diff --git a/car-ui-lib/tests/unit/res/layout/car_ui_recycler_view_test_activity.xml b/car-ui-lib/tests/unit/res/layout/car_ui_recycler_view_test_activity.xml
new file mode 100644
index 0000000..891a56f
--- /dev/null
+++ b/car-ui-lib/tests/unit/res/layout/car_ui_recycler_view_test_activity.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2020 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+    <com.android.car.ui.recyclerview.CarUiRecyclerView
+        android:id="@+id/list"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"/>
+</FrameLayout>
diff --git a/car-ui-lib/tests/unit/res/layout/empty_test_activity.xml b/car-ui-lib/tests/unit/res/layout/empty_test_activity.xml
new file mode 100644
index 0000000..899fb3d
--- /dev/null
+++ b/car-ui-lib/tests/unit/res/layout/empty_test_activity.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2020 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/test_container"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+</FrameLayout>
diff --git a/car-ui-lib/tests/unit/res/layout/focus_area_test_activity.xml b/car-ui-lib/tests/unit/res/layout/focus_area_test_activity.xml
new file mode 100644
index 0000000..405bbfe
--- /dev/null
+++ b/car-ui-lib/tests/unit/res/layout/focus_area_test_activity.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2020 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+    <com.android.car.ui.TestFocusArea
+        android:id="@+id/focus_area"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content">
+        <View
+            android:id="@+id/child"
+            android:focusable="true"
+            android:layout_width="10dp"
+            android:layout_height="10dp"/>
+    </com.android.car.ui.TestFocusArea>
+    <View
+        android:id="@+id/non_child"
+        android:focusable="true"
+        android:layout_width="10dp"
+        android:layout_height="10dp"/>
+</LinearLayout>
diff --git a/car-ui-lib/tests/unit/res/layout/focus_parking_view_test_activity.xml b/car-ui-lib/tests/unit/res/layout/focus_parking_view_test_activity.xml
new file mode 100644
index 0000000..f3f623d
--- /dev/null
+++ b/car-ui-lib/tests/unit/res/layout/focus_parking_view_test_activity.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2020 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+    <!-- In some cases Android will focus the first focusable view automatically. To prevent the
+         FocusParkingView getting focused unintentionally, we put a focusable Button above the
+         FocusParkingView. -->
+    <Button
+        android:layout_width="100dp"
+        android:layout_height="40dp"/>
+    <com.android.car.ui.FocusParkingView
+        android:id="@+id/focus_parking"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"/>
+</FrameLayout>
diff --git a/car-ui-lib/tests/unit/res/layout/test_list_item.xml b/car-ui-lib/tests/unit/res/layout/test_list_item.xml
new file mode 100644
index 0000000..e789145
--- /dev/null
+++ b/car-ui-lib/tests/unit/res/layout/test_list_item.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright 2020 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="horizontal">
+
+    <TextView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="10dp"
+        android:layout_marginBottom="10dp"
+        android:textAppearance="@style/TextAppearance.CarUi.ListItem.Body"
+        android:id="@+id/text" />
+
+</LinearLayout>
diff --git a/car-ui-lib/tests/unit/src/com/android/car/ui/FocusAreaTest.java b/car-ui-lib/tests/unit/src/com/android/car/ui/FocusAreaTest.java
new file mode 100644
index 0000000..8b2ddc1
--- /dev/null
+++ b/car-ui-lib/tests/unit/src/com/android/car/ui/FocusAreaTest.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.car.ui;
+
+import static org.junit.Assert.assertTrue;
+
+import android.view.View;
+
+import androidx.test.rule.ActivityTestRule;
+
+import com.android.car.ui.tests.unit.R;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/** Unit tests for {@link FocusArea}. */
+public class FocusAreaTest {
+    private static final long WAIT_TIME_MS = 3000;
+
+    @Rule
+    public ActivityTestRule<FocusAreaTestActivity> mActivityRule =
+            new ActivityTestRule<>(FocusAreaTestActivity.class);
+
+    private FocusAreaTestActivity mActivity;
+    private TestFocusArea mFocusArea;
+    private View mChild;
+    private View mNonChild;
+
+    @Before
+    public void setUp() {
+        mActivity = mActivityRule.getActivity();
+        mFocusArea = mActivity.findViewById(R.id.focus_area);
+        mChild = mActivity.findViewById(R.id.child);
+        mNonChild = mActivity.findViewById(R.id.non_child);
+    }
+
+    @Test
+    public void testLoseFocus() throws Exception {
+        mChild.post(() -> {
+            mChild.requestFocus();
+        });
+        mFocusArea.setOnDrawCalled(false);
+        mFocusArea.setDrawCalled(false);
+
+        // FocusArea lost focus.
+        CountDownLatch latch = new CountDownLatch(1);
+        mNonChild.post(() -> {
+            mNonChild.requestFocus();
+            mNonChild.post(() -> {
+                latch.countDown();
+            });
+        });
+        assertDrawMethodsCalled(latch);
+    }
+
+    @Test
+    public void testGetFocus() throws Exception {
+        mNonChild.post(() -> {
+            mNonChild.requestFocus();
+        });
+        mFocusArea.setOnDrawCalled(false);
+        mFocusArea.setDrawCalled(false);
+
+        // FocusArea got focus.
+        CountDownLatch latch = new CountDownLatch(1);
+        mChild.post(() -> {
+            mChild.requestFocus();
+            mChild.post(() -> {
+                latch.countDown();
+            });
+        });
+        assertDrawMethodsCalled(latch);
+    }
+
+    private void assertDrawMethodsCalled(CountDownLatch latch) throws Exception {
+        latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS);
+        assertTrue(mFocusArea.onDrawCalled());
+        assertTrue(mFocusArea.drawCalled());
+    }
+}
diff --git a/car-ui-lib/tests/unit/src/com/android/car/ui/FocusAreaTestActivity.java b/car-ui-lib/tests/unit/src/com/android/car/ui/FocusAreaTestActivity.java
new file mode 100644
index 0000000..f027db6
--- /dev/null
+++ b/car-ui-lib/tests/unit/src/com/android/car/ui/FocusAreaTestActivity.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.car.ui;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+import com.android.car.ui.tests.unit.R;
+
+/** An activity used for testing {@link FocusArea}. */
+public class FocusAreaTestActivity extends Activity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.focus_area_test_activity);
+    }
+}
diff --git a/car-ui-lib/tests/unit/src/com/android/car/ui/FocusParkingViewTest.java b/car-ui-lib/tests/unit/src/com/android/car/ui/FocusParkingViewTest.java
new file mode 100644
index 0000000..52236bd
--- /dev/null
+++ b/car-ui-lib/tests/unit/src/com/android/car/ui/FocusParkingViewTest.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.car.ui;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import androidx.test.rule.ActivityTestRule;
+
+import com.android.car.ui.tests.unit.R;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/** Unit test for {@link FocusParkingView}. */
+public class FocusParkingViewTest {
+
+    private static final long WAIT_TIME_MS = 3000;
+
+    @Rule
+    public ActivityTestRule<FocusParkingViewTestActivity> mActivityRule =
+            new ActivityTestRule<>(FocusParkingViewTestActivity.class);
+
+    private FocusParkingViewTestActivity mActivity;
+
+    @Before
+    public void setUp() {
+        mActivity = mActivityRule.getActivity();
+    }
+
+    @Test
+    public void testFocusParkingViewCanTakeFocus() throws Exception {
+        FocusParkingView focusParkingView = mActivity.findViewById(R.id.focus_parking);
+
+        CountDownLatch latch = new CountDownLatch(1);
+        focusParkingView.post(() -> {
+            focusParkingView.requestFocus();
+            focusParkingView.post(() -> {
+                latch.countDown();
+            });
+        });
+        latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS);
+
+        assertThat(focusParkingView.isFocused()).isTrue();
+    }
+    @Test
+    public void testFocusParkingViewFocusedWhenWindowLostFocus() throws Exception {
+        FocusParkingView focusParkingView = mActivity.findViewById(R.id.focus_parking);
+        assertThat(focusParkingView.isFocused()).isFalse();
+
+        CountDownLatch latch = new CountDownLatch(1);
+        focusParkingView.post(() -> {
+            focusParkingView.onWindowFocusChanged(false);
+            focusParkingView.post(() -> {
+                latch.countDown();
+            });
+        });
+        latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS);
+
+        assertThat(focusParkingView.isFocused()).isTrue();
+    }
+}
diff --git a/car-ui-lib/tests/unit/src/com/android/car/ui/FocusParkingViewTestActivity.java b/car-ui-lib/tests/unit/src/com/android/car/ui/FocusParkingViewTestActivity.java
new file mode 100644
index 0000000..9357ca6
--- /dev/null
+++ b/car-ui-lib/tests/unit/src/com/android/car/ui/FocusParkingViewTestActivity.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.car.ui;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+import com.android.car.ui.tests.unit.R;
+
+
+/** An Activity used for testing {@link FocusParkingView}. */
+public class FocusParkingViewTestActivity extends Activity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.focus_parking_view_test_activity);
+    }
+}
diff --git a/car-ui-lib/tests/unit/src/com/android/car/ui/TestActivity.java b/car-ui-lib/tests/unit/src/com/android/car/ui/TestActivity.java
new file mode 100644
index 0000000..db8c560
--- /dev/null
+++ b/car-ui-lib/tests/unit/src/com/android/car/ui/TestActivity.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.car.ui;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+import com.android.car.ui.tests.unit.R;
+
+/**
+ * An empty activity to be used for testing.
+ */
+public class TestActivity extends Activity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.empty_test_activity);
+    }
+}
diff --git a/car-ui-lib/tests/unit/src/com/android/car/ui/TestFocusArea.java b/car-ui-lib/tests/unit/src/com/android/car/ui/TestFocusArea.java
new file mode 100644
index 0000000..092624f
--- /dev/null
+++ b/car-ui-lib/tests/unit/src/com/android/car/ui/TestFocusArea.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.car.ui;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.util.AttributeSet;
+
+import androidx.annotation.Nullable;
+
+/** A {@link FocusArea} used for testing. */
+public class TestFocusArea extends FocusArea {
+
+    /** Whether {@link #onDraw(Canvas)} was called. */
+    private boolean mOnDrawCalled;
+
+    /** Whether {@link #draw(Canvas)} was called. */
+    private boolean mDrawCalled;
+
+    public TestFocusArea(Context context) {
+        super(context);
+    }
+
+    public TestFocusArea(Context context, @Nullable AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public TestFocusArea(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+    }
+
+    public TestFocusArea(Context context, @Nullable AttributeSet attrs, int defStyleAttr,
+            int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+    }
+
+    @Override
+    public void onDraw(Canvas canvas) {
+        mOnDrawCalled = true;
+        super.onDraw(canvas);
+    }
+
+    @Override
+    public void draw(Canvas canvas) {
+        mDrawCalled = true;
+        super.draw(canvas);
+    }
+
+    public boolean onDrawCalled() {
+        return mOnDrawCalled;
+    }
+
+    public void setOnDrawCalled(boolean onDrawCalled) {
+        mOnDrawCalled = onDrawCalled;
+    }
+
+    public boolean drawCalled() {
+        return mDrawCalled;
+    }
+
+    public void setDrawCalled(boolean drawCalled) {
+        mDrawCalled = drawCalled;
+    }
+}
diff --git a/car-ui-lib/tests/unit/src/com/android/car/ui/actions/LowLevelActions.java b/car-ui-lib/tests/unit/src/com/android/car/ui/actions/LowLevelActions.java
new file mode 100644
index 0000000..ea8e681
--- /dev/null
+++ b/car-ui-lib/tests/unit/src/com/android/car/ui/actions/LowLevelActions.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.car.ui.actions;
+
+import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static androidx.test.espresso.matcher.ViewMatchers.isDisplayingAtLeast;
+
+import android.view.MotionEvent;
+import android.view.View;
+
+import androidx.test.espresso.UiController;
+import androidx.test.espresso.ViewAction;
+import androidx.test.espresso.action.GeneralLocation;
+import androidx.test.espresso.action.MotionEvents;
+import androidx.test.espresso.action.Press;
+
+import org.hamcrest.Matcher;
+
+public class LowLevelActions {
+    static MotionEvent sMotionEventDownHeldView = null;
+
+    public static PressAndHoldAction pressAndHold() {
+        return new PressAndHoldAction();
+    }
+
+    public static ReleaseAction release() {
+        return new ReleaseAction();
+    }
+
+    public static void tearDown() {
+        sMotionEventDownHeldView = null;
+    }
+
+    static class PressAndHoldAction implements ViewAction {
+        @Override
+        public Matcher<View> getConstraints() {
+            return isDisplayingAtLeast(90);
+        }
+
+        @Override
+        public String getDescription() {
+            return "Press and hold action";
+        }
+
+        @Override
+        public void perform(final UiController uiController, final View view) {
+            if (sMotionEventDownHeldView != null) {
+                throw new AssertionError("Only one view can be held at a time");
+            }
+
+            float[] precision = Press.FINGER.describePrecision();
+            float[] coords = GeneralLocation.CENTER.calculateCoordinates(view);
+            sMotionEventDownHeldView = MotionEvents.sendDown(uiController, coords, precision).down;
+        }
+    }
+
+    static class ReleaseAction implements ViewAction {
+        @Override
+        public Matcher<View> getConstraints() {
+            return isDisplayingAtLeast(90);
+        }
+
+        @Override
+        public String getDescription() {
+            return "Release action";
+        }
+
+        @Override
+        public void perform(final UiController uiController, final View view) {
+            if (sMotionEventDownHeldView == null) {
+                throw new AssertionError(
+                        "Before calling release(), you must call pressAndHold() on a view");
+            }
+
+            float[] coords = GeneralLocation.CENTER.calculateCoordinates(view);
+            MotionEvents.sendUp(uiController, sMotionEventDownHeldView, coords);
+        }
+    }
+
+    public static ViewAction touchDownAndUp(final float x, final float y) {
+        return new ViewAction() {
+            @Override
+            public Matcher<View> getConstraints() {
+                return isDisplayed();
+            }
+
+            @Override
+            public String getDescription() {
+                return "Send touch events.";
+            }
+
+            @Override
+            public void perform(UiController uiController, final View view) {
+                // Get view absolute position
+                int[] location = new int[2];
+                view.getLocationOnScreen(location);
+
+                // Offset coordinates by view position
+                float[] coordinates = new float[]{x + location[0], y + location[1]};
+                float[] precision = new float[]{1f, 1f};
+
+                // Send down event, pause, and send up
+                MotionEvent down = MotionEvents.sendDown(uiController, coordinates, precision).down;
+                uiController.loopMainThreadForAtLeast(200);
+                MotionEvents.sendUp(uiController, down, coordinates);
+            }
+        };
+    }
+
+    /**
+     * Performs the down, move and up touch actions for the given coordinates. deltaX and deltaY
+     * coordinates are used for moving the view from the downX and downY position. The interval
+     * defines the number of time the value should be increased via delta. Also, limitY or limitX
+     * can be provided to stop the movement if that value is reached.
+     */
+    public static ViewAction performDrag(final float downX, final float downY,
+            final float deltaX, final float deltaY, final float interval, final float limitX,
+            final float limitY) {
+        return new ViewAction() {
+            @Override
+            public Matcher<View> getConstraints() {
+                return isDisplayed();
+            }
+
+            @Override
+            public String getDescription() {
+                return "Send touch events.";
+            }
+
+            @Override
+            public void perform(UiController uiController, final View view) {
+                // Get view absolute position
+                int[] location = new int[2];
+                view.getLocationOnScreen(location);
+
+                // Offset coordinates by view position
+                float[] coordinatesDown = new float[]{downX + location[0], downY + location[1]};
+                float[] coordinatesMove = new float[]{downX + location[0], downY + location[1]};
+                float[] precision = new float[]{1f, 1f};
+                // Send down event, pause, and send up
+                MotionEvent down = MotionEvents.sendDown(uiController, coordinatesDown,
+                        precision).down;
+                uiController.loopMainThreadForAtLeast(200);
+                for (int i = 0; i < interval; i++) {
+                    MotionEvents.sendMovement(uiController, down, coordinatesMove);
+                    uiController.loopMainThreadForAtLeast(100);
+
+                    coordinatesMove[0] = coordinatesMove[0] + deltaX;
+                    coordinatesMove[1] = coordinatesMove[1] + deltaY;
+                    if (coordinatesMove[1] > limitY + location[1]
+                            || coordinatesMove[0] > limitX + location[0]) {
+                        break;
+                    }
+                }
+                MotionEvents.sendUp(uiController, down, coordinatesMove);
+            }
+        };
+    }
+}
diff --git a/car-ui-lib/tests/unit/src/com/android/car/ui/actions/ViewActions.java b/car-ui-lib/tests/unit/src/com/android/car/ui/actions/ViewActions.java
new file mode 100644
index 0000000..8640a02
--- /dev/null
+++ b/car-ui-lib/tests/unit/src/com/android/car/ui/actions/ViewActions.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.car.ui.actions;
+
+import android.view.View;
+
+import androidx.test.espresso.ViewAction;
+
+import org.hamcrest.Matcher;
+
+public class ViewActions {
+
+    public static ViewAction waitForView(Matcher<View> matcher, long waitTimeMillis) {
+        return new WaitForViewAction(matcher, waitTimeMillis);
+    }
+}
diff --git a/car-ui-lib/tests/unit/src/com/android/car/ui/actions/WaitForViewAction.java b/car-ui-lib/tests/unit/src/com/android/car/ui/actions/WaitForViewAction.java
new file mode 100644
index 0000000..7ce2bf6
--- /dev/null
+++ b/car-ui-lib/tests/unit/src/com/android/car/ui/actions/WaitForViewAction.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.car.ui.actions;
+
+import static androidx.test.espresso.matcher.ViewMatchers.isRoot;
+
+import android.view.View;
+
+import androidx.test.espresso.PerformException;
+import androidx.test.espresso.UiController;
+import androidx.test.espresso.ViewAction;
+import androidx.test.espresso.util.HumanReadables;
+import androidx.test.espresso.util.TreeIterables;
+
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.hamcrest.StringDescription;
+
+import java.util.concurrent.TimeoutException;
+
+public class WaitForViewAction implements ViewAction {
+
+    private Matcher<View> mMatcher;
+    private long mWaitTimeMillis;
+
+    public WaitForViewAction(Matcher<View> matcher, long waitTimeMillis) {
+        mMatcher = matcher;
+        mWaitTimeMillis = waitTimeMillis;
+    }
+
+    @Override
+    public Matcher<View> getConstraints() {
+        return isRoot();
+    }
+
+    @Override
+    public String getDescription() {
+        Description description = new StringDescription();
+        mMatcher.describeTo(description);
+        return "wait at most " + mWaitTimeMillis + " milliseconds for view "
+                + description.toString();
+    }
+
+    @Override
+    public void perform(UiController uiController, View view) {
+        uiController.loopMainThreadUntilIdle();
+        final long startTime = System.currentTimeMillis();
+        final long endTime = startTime + mWaitTimeMillis;
+
+        do {
+            for (View child : TreeIterables.breadthFirstViewTraversal(view)) {
+                if (mMatcher.matches(child)) {
+                    return;
+                }
+            }
+
+            uiController.loopMainThreadForAtLeast(50);
+        }
+        while (System.currentTimeMillis() < endTime);
+
+        throw new PerformException.Builder()
+                .withActionDescription(this.getDescription())
+                .withViewDescription(HumanReadables.describe(view))
+                .withCause(new TimeoutException())
+                .build();
+    }
+}
diff --git a/car-ui-lib/tests/unit/src/com/android/car/ui/matchers/DrawableMatcher.java b/car-ui-lib/tests/unit/src/com/android/car/ui/matchers/DrawableMatcher.java
new file mode 100644
index 0000000..4c0d9bb
--- /dev/null
+++ b/car-ui-lib/tests/unit/src/com/android/car/ui/matchers/DrawableMatcher.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.car.ui.matchers;
+
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.drawable.Drawable;
+import android.view.View;
+import android.widget.ImageView;
+
+import org.hamcrest.Description;
+import org.hamcrest.TypeSafeMatcher;
+
+/* package */ class DrawableMatcher extends TypeSafeMatcher<View> {
+
+    private final int mDrawableId;
+
+    DrawableMatcher(int drawableId) {
+        mDrawableId = drawableId;
+    }
+
+    @Override
+    protected boolean matchesSafely(View item) {
+        if (!(item instanceof ImageView) || !item.isShown()) {
+            return false;
+        }
+
+        ImageView imageView = (ImageView) item;
+
+        Bitmap bitmap = drawableToBitmap(imageView.getDrawable());
+        Bitmap otherBitmap = drawableToBitmap(imageView.getContext().getDrawable(mDrawableId));
+
+        if (bitmap == null && otherBitmap == null) {
+            return true;
+        } else if ((bitmap == null) != (otherBitmap == null)) {
+            return false;
+        }
+
+        return bitmap.sameAs(otherBitmap);
+    }
+
+    private Bitmap drawableToBitmap(Drawable drawable) {
+        if (drawable == null) {
+            return null;
+        }
+
+        Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(),
+                drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
+        Canvas canvas = new Canvas(bitmap);
+        drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
+        drawable.draw(canvas);
+        return bitmap;
+    }
+
+    @Override
+    public void describeTo(Description description) {
+        description.appendText("has drawable with id " + mDrawableId);
+    }
+}
diff --git a/car-ui-lib/tests/unit/src/com/android/car/ui/matchers/NthChildMatcher.java b/car-ui-lib/tests/unit/src/com/android/car/ui/matchers/NthChildMatcher.java
new file mode 100644
index 0000000..996cf63
--- /dev/null
+++ b/car-ui-lib/tests/unit/src/com/android/car/ui/matchers/NthChildMatcher.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.car.ui.matchers;
+
+import android.view.View;
+import android.view.ViewGroup;
+
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.hamcrest.TypeSafeMatcher;
+
+public class NthChildMatcher extends TypeSafeMatcher<View> {
+
+    private Matcher<View> mParentMatcher;
+    private int mPosition;
+
+    public NthChildMatcher(Matcher<View> parentMatcher, int position) {
+        mParentMatcher = parentMatcher;
+        mPosition = position;
+    }
+
+    @Override
+    public void describeTo(Description description) {
+        description.appendText("position " + mPosition + " of parent ");
+        mParentMatcher.describeTo(description);
+    }
+
+    @Override
+    public boolean matchesSafely(View view) {
+        if (!(view.getParent() instanceof ViewGroup)) {
+            return false;
+        }
+
+        ViewGroup parent = (ViewGroup) view.getParent();
+
+        return mParentMatcher.matches(parent)
+                && parent.getChildCount() > mPosition
+                && view.equals(parent.getChildAt(mPosition));
+    }
+}
diff --git a/car-ui-lib/tests/unit/src/com/android/car/ui/matchers/ViewMatchers.java b/car-ui-lib/tests/unit/src/com/android/car/ui/matchers/ViewMatchers.java
new file mode 100644
index 0000000..1bee2e0
--- /dev/null
+++ b/car-ui-lib/tests/unit/src/com/android/car/ui/matchers/ViewMatchers.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.car.ui.matchers;
+
+import android.view.View;
+
+import org.hamcrest.Matcher;
+
+public class ViewMatchers {
+    public static Matcher<View> withDrawable(int drawableId) {
+        return new DrawableMatcher(drawableId);
+    }
+
+    public static Matcher<View> nthChildOfView(Matcher<View> parentMatcher, int n) {
+        return new NthChildMatcher(parentMatcher, n);
+    }
+}
diff --git a/car-ui-lib/tests/unit/src/com/android/car/ui/recyclerview/CarUiListItemTest.java b/car-ui-lib/tests/unit/src/com/android/car/ui/recyclerview/CarUiListItemTest.java
new file mode 100644
index 0000000..d5f5d13
--- /dev/null
+++ b/car-ui-lib/tests/unit/src/com/android/car/ui/recyclerview/CarUiListItemTest.java
@@ -0,0 +1,317 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.car.ui.recyclerview;
+
+import static androidx.test.espresso.Espresso.onView;
+import static androidx.test.espresso.action.ViewActions.click;
+import static androidx.test.espresso.assertion.ViewAssertions.matches;
+import static androidx.test.espresso.matcher.ViewMatchers.isChecked;
+import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static androidx.test.espresso.matcher.ViewMatchers.isNotChecked;
+import static androidx.test.espresso.matcher.ViewMatchers.withId;
+import static androidx.test.espresso.matcher.ViewMatchers.withText;
+
+import static org.hamcrest.Matchers.not;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.view.View;
+
+import androidx.test.rule.ActivityTestRule;
+
+import com.android.car.ui.tests.unit.R;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.ArgumentMatchers;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/** Unit tests for {@link CarUiListItem}. */
+public class CarUiListItemTest {
+
+    private CarUiRecyclerView mCarUiRecyclerView;
+
+    @Rule
+    public ActivityTestRule<CarUiRecyclerViewTestActivity> mActivityRule =
+            new ActivityTestRule<>(CarUiRecyclerViewTestActivity.class);
+
+    @Before
+    public void setUp() {
+        mCarUiRecyclerView = mActivityRule.getActivity().requireViewById(R.id.list);
+    }
+
+    @Test
+    public void testItemVisibility_withTitle() {
+        List<CarUiListItem> items = new ArrayList<>();
+
+        CarUiContentListItem item = new CarUiContentListItem(CarUiContentListItem.Action.NONE);
+        item.setTitle("Test title");
+        items.add(item);
+
+        mCarUiRecyclerView.post(
+                () -> mCarUiRecyclerView.setAdapter(new CarUiListItemAdapter(items)));
+
+        onView(withId(R.id.title)).check(matches(isDisplayed()));
+        onView(withId(R.id.body)).check(matches(not(isDisplayed())));
+        onView(withId(R.id.icon_container)).check(matches(not(isDisplayed())));
+        onView(withId(R.id.action_container)).check(matches(not(isDisplayed())));
+    }
+
+    @Test
+    public void testItemVisibility_withBody() {
+        List<CarUiListItem> items = new ArrayList<>();
+
+        CarUiContentListItem item = new CarUiContentListItem(CarUiContentListItem.Action.NONE);
+        item.setBody("Test body");
+        items.add(item);
+
+        mCarUiRecyclerView.post(
+                () -> mCarUiRecyclerView.setAdapter(new CarUiListItemAdapter(items)));
+
+        onView(withId(R.id.body)).check(matches(isDisplayed()));
+        onView(withId(R.id.title)).check(matches(not(isDisplayed())));
+        onView(withId(R.id.icon_container)).check(matches(not(isDisplayed())));
+        onView(withId(R.id.action_container)).check(matches(not(isDisplayed())));
+    }
+
+    @Test
+    public void testItemVisibility_withTitle_withBodyAndIcon() {
+        List<CarUiListItem> items = new ArrayList<>();
+
+        CarUiContentListItem item = new CarUiContentListItem(CarUiContentListItem.Action.NONE);
+        item.setTitle("Test title");
+        item.setBody("Test body");
+        item.setIcon(mActivityRule.getActivity().getDrawable(R.drawable.car_ui_icon_close));
+        items.add(item);
+
+        mCarUiRecyclerView.post(
+                () -> mCarUiRecyclerView.setAdapter(new CarUiListItemAdapter(items)));
+
+        onView(withId(R.id.title)).check(matches(isDisplayed()));
+        onView(withId(R.id.body)).check(matches(isDisplayed()));
+        onView(withId(R.id.icon_container)).check(matches(isDisplayed()));
+        onView(withId(R.id.action_container)).check(matches(not(isDisplayed())));
+    }
+
+    @Test
+    public void testItem_withCheckbox() {
+        List<CarUiListItem> items = new ArrayList<>();
+
+        CarUiContentListItem.OnCheckedChangeListener mockOnCheckedChangeListener = mock(
+                CarUiContentListItem.OnCheckedChangeListener.class);
+
+        CarUiContentListItem item = new CarUiContentListItem(CarUiContentListItem.Action.CHECK_BOX);
+        item.setTitle("Test item with checkbox");
+        item.setOnCheckedChangeListener(mockOnCheckedChangeListener);
+        items.add(item);
+
+        mCarUiRecyclerView.post(
+                () -> mCarUiRecyclerView.setAdapter(new CarUiListItemAdapter(items)));
+
+        onView(withId(R.id.title)).check(matches(isDisplayed()));
+        onView(withId(R.id.checkbox_widget)).check(matches(isDisplayed()));
+        onView(withId(R.id.action_divider)).check(matches(not(isDisplayed())));
+
+        // List item with checkbox should be initially unchecked.
+        onView(withId(R.id.checkbox_widget)).check(matches(isNotChecked()));
+        // Clicks anywhere on the item should toggle the checkbox
+        onView(withId(R.id.title)).perform(click());
+        onView(withId(R.id.checkbox_widget)).check(matches(isChecked()));
+        // Check that onCheckChangedListener was invoked.
+        verify(mockOnCheckedChangeListener, times(1)).onCheckedChanged(item, true);
+
+        // Uncheck checkbox with click on the action container
+        onView(withId(R.id.action_container)).perform(click());
+        onView(withId(R.id.checkbox_widget)).check(matches(isNotChecked()));
+        // Check that onCheckChangedListener was invoked.
+        verify(mockOnCheckedChangeListener, times(1)).onCheckedChanged(item, false);
+    }
+
+    @Test
+    public void testItem_withSwitch() {
+        List<CarUiListItem> items = new ArrayList<>();
+
+        CarUiContentListItem item = new CarUiContentListItem(CarUiContentListItem.Action.SWITCH);
+        item.setBody("Test item with switch");
+        item.setChecked(true);
+        item.setActionDividerVisible(true);
+        items.add(item);
+
+        mCarUiRecyclerView.post(
+                () -> mCarUiRecyclerView.setAdapter(new CarUiListItemAdapter(items)));
+
+        onView(withId(R.id.body)).check(matches(isDisplayed()));
+        onView(withId(R.id.switch_widget)).check(matches(isDisplayed()));
+        onView(withId(R.id.action_divider)).check(matches(isDisplayed()));
+
+        // List item with checkbox should be initially checked.
+        onView(withId(R.id.switch_widget)).check(matches(isChecked()));
+        // Clicks anywhere on the item should toggle the switch
+        onView(withId(R.id.switch_widget)).perform(click());
+        onView(withId(R.id.switch_widget)).check(matches(isNotChecked()));
+        // Uncheck checkbox with click on the action container
+        onView(withId(R.id.body)).perform(click());
+        onView(withId(R.id.switch_widget)).check(matches(isChecked()));
+    }
+
+    @Test
+    public void testItem_withRadioButton() {
+        List<CarUiListItem> items = new ArrayList<>();
+
+        CarUiContentListItem item = new CarUiContentListItem(
+                CarUiContentListItem.Action.RADIO_BUTTON);
+        item.setTitle("Test item with radio button");
+        item.setChecked(false);
+        items.add(item);
+
+        mCarUiRecyclerView.post(
+                () -> mCarUiRecyclerView.setAdapter(new CarUiListItemAdapter(items)));
+
+        onView(withId(R.id.title)).check(matches(isDisplayed()));
+        onView(withId(R.id.radio_button_widget)).check(matches(isDisplayed()));
+
+        // List item with checkbox should be initially not checked.
+        onView(withId(R.id.radio_button_widget)).check(matches(isNotChecked()));
+        // Clicks anywhere on the item should toggle the radio button.
+        onView(withId(R.id.radio_button_widget)).perform(click());
+        onView(withId(R.id.radio_button_widget)).check(matches(isChecked()));
+
+        // Repeated clicks on a selected radio button should not toggle the element once checked.
+        onView(withId(R.id.title)).perform(click());
+        onView(withId(R.id.radio_button_widget)).check(matches(isChecked()));
+    }
+
+    @Test
+    public void testItem_withListener() {
+        List<CarUiListItem> items = new ArrayList<>();
+
+        CarUiContentListItem.OnClickListener mockOnCheckedChangeListener = mock(
+                CarUiContentListItem.OnClickListener.class);
+
+        CarUiContentListItem item = new CarUiContentListItem(
+                CarUiContentListItem.Action.NONE);
+        item.setIcon(mActivityRule.getActivity().getDrawable(R.drawable.car_ui_icon_close));
+        item.setTitle("Test item with listener");
+        item.setBody("Body text");
+        item.setOnItemClickedListener(mockOnCheckedChangeListener);
+        items.add(item);
+
+        mCarUiRecyclerView.post(
+                () -> mCarUiRecyclerView.setAdapter(new CarUiListItemAdapter(items)));
+
+        onView(withId(R.id.title)).check(matches(isDisplayed()));
+
+        // Clicks anywhere on the item should toggle the listener
+        onView(withId(R.id.title)).perform(click());
+        verify(mockOnCheckedChangeListener, times(1)).onClick(item);
+
+        onView(withId(R.id.body)).perform(click());
+        verify(mockOnCheckedChangeListener, times(2)).onClick(item);
+
+        onView(withId(R.id.icon_container)).perform(click());
+        verify(mockOnCheckedChangeListener, times(3)).onClick(item);
+    }
+
+    @Test
+    public void testItem_withSupplementalIconAndIconOnClickListener() {
+        List<CarUiListItem> items = new ArrayList<>();
+
+        CarUiContentListItem.OnClickListener mockedItemOnClickListener = mock(
+                CarUiContentListItem.OnClickListener.class);
+        View.OnClickListener mockedIconListener = mock(View.OnClickListener.class);
+
+        CarUiContentListItem item = new CarUiContentListItem(
+                CarUiContentListItem.Action.ICON);
+        item.setSupplementalIcon(
+                mActivityRule.getActivity().getDrawable(R.drawable.car_ui_icon_close),
+                mockedIconListener);
+        item.setOnItemClickedListener(mockedItemOnClickListener);
+        item.setTitle("Test item with listeners");
+        items.add(item);
+
+        mCarUiRecyclerView.post(
+                () -> mCarUiRecyclerView.setAdapter(new CarUiListItemAdapter(items)));
+
+        onView(withId(R.id.title)).check(matches(isDisplayed()));
+
+        // Clicks anywhere on the item (outside of the icon) should only invoke the item click
+        // listener.
+        onView(withId(R.id.title)).perform(click());
+        verify(mockedItemOnClickListener, times(1)).onClick(item);
+
+        // Clicks anywhere on the icon should invoke both listeners.
+        onView(withId(R.id.action_container)).perform(click());
+        verify(mockedItemOnClickListener, times(2)).onClick(item);
+        verify(mockedIconListener, times(1)).onClick(ArgumentMatchers.any(View.class));
+    }
+
+    @Test
+    public void testRadioButtonListItemAdapter() {
+        List<CarUiRadioButtonListItem> items = new ArrayList<>();
+
+        CarUiRadioButtonListItem itemOne = new CarUiRadioButtonListItem();
+        String itemOneTitle = "Item 1";
+        itemOne.setTitle(itemOneTitle);
+        items.add(itemOne);
+
+        CarUiRadioButtonListItem itemTwo = new CarUiRadioButtonListItem();
+        String itemTwoTitle = "Item 2";
+        itemTwo.setTitle(itemTwoTitle);
+        items.add(itemTwo);
+
+        CarUiRadioButtonListItem itemThree = new CarUiRadioButtonListItem();
+        String itemThreeTitle = "Item 3";
+        itemThree.setTitle(itemThreeTitle);
+        items.add(itemThree);
+
+        mCarUiRecyclerView.post(
+                () -> mCarUiRecyclerView.setAdapter(new CarUiRadioButtonListItemAdapter(items)));
+
+        onView(withText(itemOneTitle)).check(matches(isDisplayed()));
+        onView(withText(itemTwoTitle)).check(matches(isDisplayed()));
+        onView(withText(itemThreeTitle)).check(matches(isDisplayed()));
+
+        // All items are initially unchecked.
+        assertFalse(itemOne.isChecked());
+        assertFalse(itemTwo.isChecked());
+        assertFalse(itemThree.isChecked());
+
+        // Select first item.
+        onView(withText(itemOneTitle)).perform(click());
+        assertTrue(itemOne.isChecked());
+        assertFalse(itemTwo.isChecked());
+        assertFalse(itemThree.isChecked());
+
+        // Select second item.
+        onView(withText(itemTwoTitle)).perform(click());
+        assertFalse(itemOne.isChecked());
+        assertTrue(itemTwo.isChecked());
+        assertFalse(itemThree.isChecked());
+
+        // Select third item.
+        onView(withText(itemThreeTitle)).perform(click());
+        assertFalse(itemOne.isChecked());
+        assertFalse(itemTwo.isChecked());
+        assertTrue(itemThree.isChecked());
+    }
+}
diff --git a/car-ui-lib/tests/unit/src/com/android/car/ui/recyclerview/CarUiRecyclerViewTest.java b/car-ui-lib/tests/unit/src/com/android/car/ui/recyclerview/CarUiRecyclerViewTest.java
new file mode 100644
index 0000000..568395d
--- /dev/null
+++ b/car-ui-lib/tests/unit/src/com/android/car/ui/recyclerview/CarUiRecyclerViewTest.java
@@ -0,0 +1,864 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.car.ui.recyclerview;
+
+import static androidx.test.espresso.Espresso.onView;
+import static androidx.test.espresso.action.ViewActions.click;
+import static androidx.test.espresso.assertion.PositionAssertions.isBottomAlignedWith;
+import static androidx.test.espresso.assertion.PositionAssertions.isCompletelyAbove;
+import static androidx.test.espresso.assertion.PositionAssertions.isLeftAlignedWith;
+import static androidx.test.espresso.assertion.PositionAssertions.isRightAlignedWith;
+import static androidx.test.espresso.assertion.PositionAssertions.isTopAlignedWith;
+import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist;
+import static androidx.test.espresso.assertion.ViewAssertions.matches;
+import static androidx.test.espresso.contrib.RecyclerViewActions.scrollToPosition;
+import static androidx.test.espresso.matcher.ViewMatchers.assertThat;
+import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static androidx.test.espresso.matcher.ViewMatchers.isEnabled;
+import static androidx.test.espresso.matcher.ViewMatchers.isRoot;
+import static androidx.test.espresso.matcher.ViewMatchers.withId;
+import static androidx.test.espresso.matcher.ViewMatchers.withText;
+
+import static com.android.car.ui.actions.LowLevelActions.performDrag;
+import static com.android.car.ui.actions.LowLevelActions.pressAndHold;
+import static com.android.car.ui.actions.LowLevelActions.release;
+import static com.android.car.ui.actions.LowLevelActions.touchDownAndUp;
+import static com.android.car.ui.actions.ViewActions.waitForView;
+
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.greaterThan;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.lessThan;
+import static org.hamcrest.Matchers.not;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.GridLayoutManager;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.OrientationHelper;
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.test.espresso.IdlingRegistry;
+import androidx.test.espresso.IdlingResource;
+import androidx.test.rule.ActivityTestRule;
+
+import com.android.car.ui.TestActivity;
+import com.android.car.ui.tests.unit.R;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/** Unit tests for {@link CarUiRecyclerView}. */
+public class CarUiRecyclerViewTest {
+
+    @Rule
+    public ActivityTestRule<TestActivity> mActivityRule =
+            new ActivityTestRule<>(TestActivity.class);
+
+    private TestActivity mActivity;
+    private Context mTestableContext;
+    private Resources mTestableResources;
+
+    @Before
+    public void setUp() {
+        mActivity = mActivityRule.getActivity();
+        mTestableContext = spy(mActivity);
+        mTestableResources = spy(mActivity.getResources());
+        when(mTestableContext.getResources()).thenReturn(mTestableResources);
+    }
+
+    @After
+    public void tearDown() {
+        for (IdlingResource idlingResource : IdlingRegistry.getInstance().getResources()) {
+            IdlingRegistry.getInstance().unregister(idlingResource);
+        }
+    }
+
+    @Test
+    public void testIsScrollbarPresent_scrollbarEnabled() {
+        doReturn(true).when(mTestableResources).getBoolean(R.bool.car_ui_scrollbar_enable);
+        CarUiRecyclerView carUiRecyclerView = new CarUiRecyclerView(mTestableContext);
+        ViewGroup container = mActivity.findViewById(R.id.test_container);
+        container.post(() -> {
+            container.addView(carUiRecyclerView);
+            carUiRecyclerView.setAdapter(new TestAdapter(100));
+        });
+
+        onView(withId(R.id.car_ui_scroll_bar)).check(matches(isDisplayed()));
+    }
+
+    @Test
+    public void testIsScrollbarPresent_scrollbarDisabled() {
+        doReturn(false).when(mTestableResources).getBoolean(R.bool.car_ui_scrollbar_enable);
+        CarUiRecyclerView carUiRecyclerView = new CarUiRecyclerView(mTestableContext);
+        ViewGroup container = mActivity.findViewById(R.id.test_container);
+        container.post(() -> {
+            container.addView(carUiRecyclerView);
+            carUiRecyclerView.setAdapter(new TestAdapter(100));
+        });
+
+        onView(withId(R.id.car_ui_scroll_bar)).check(doesNotExist());
+    }
+
+    @Test
+    public void testGridLayout() {
+        TypedArray typedArray = spy(mActivity.getBaseContext().obtainStyledAttributes(
+                null, R.styleable.CarUiRecyclerView));
+
+        doReturn(typedArray).when(mTestableContext).obtainStyledAttributes(
+                any(),
+                eq(R.styleable.CarUiRecyclerView),
+                anyInt(),
+                anyInt());
+        when(typedArray.getInt(eq(R.styleable.CarUiRecyclerView_layoutStyle), anyInt()))
+                .thenReturn(CarUiRecyclerView.CarUiRecyclerViewLayout.GRID);
+        when(typedArray.getInt(eq(R.styleable.CarUiRecyclerView_numOfColumns), anyInt()))
+                .thenReturn(3);
+
+        CarUiRecyclerView carUiRecyclerView = new CarUiRecyclerView(mTestableContext);
+        ViewGroup container = mActivity.findViewById(R.id.test_container);
+        TestAdapter adapter = new TestAdapter(4);
+        container.post(() -> {
+            container.addView(carUiRecyclerView);
+            carUiRecyclerView.setAdapter(adapter);
+        });
+
+        assertTrue(carUiRecyclerView.getLayoutManager() instanceof GridLayoutManager);
+
+        // Check that all items in the first row are top-aligned.
+        onView(withText(adapter.getItemText(0))).check(
+                isTopAlignedWith(withText(adapter.getItemText(1))));
+        onView(withText(adapter.getItemText(1))).check(
+                isTopAlignedWith(withText(adapter.getItemText(2))));
+
+        // Check that all items in the first row are bottom-aligned.
+        onView(withText(adapter.getItemText(0))).check(
+                isBottomAlignedWith(withText(adapter.getItemText(1))));
+        onView(withText(adapter.getItemText(1))).check(
+                isBottomAlignedWith(withText(adapter.getItemText(2))));
+
+        // Check that items in second row are rendered correctly below the first row.
+        onView(withText(adapter.getItemText(0))).check(
+                isCompletelyAbove(withText(adapter.getItemText(3))));
+        onView(withText(adapter.getItemText(0))).check(
+                isLeftAlignedWith(withText(adapter.getItemText(3))));
+        onView(withText(adapter.getItemText(0))).check(
+                isRightAlignedWith(withText(adapter.getItemText(3))));
+    }
+
+    @Test
+    public void testLinearLayout() {
+        TypedArray typedArray = spy(mActivity.getBaseContext().obtainStyledAttributes(
+                null, R.styleable.CarUiRecyclerView));
+
+        doReturn(typedArray).when(mTestableContext).obtainStyledAttributes(
+                any(),
+                eq(R.styleable.CarUiRecyclerView),
+                anyInt(),
+                anyInt());
+        when(typedArray.getInt(eq(R.styleable.CarUiRecyclerView_layoutStyle), anyInt()))
+                .thenReturn(CarUiRecyclerView.CarUiRecyclerViewLayout.LINEAR);
+
+        CarUiRecyclerView carUiRecyclerView = new CarUiRecyclerView(mTestableContext);
+        ViewGroup container = mActivity.findViewById(R.id.test_container);
+        TestAdapter adapter = new TestAdapter(4);
+        container.post(() -> {
+            container.addView(carUiRecyclerView);
+            carUiRecyclerView.setAdapter(adapter);
+        });
+
+        assertTrue(carUiRecyclerView.getLayoutManager() instanceof LinearLayoutManager);
+
+        // Check that item views are laid out linearly.
+        onView(withText(adapter.getItemText(0))).check(
+                isCompletelyAbove(withText(adapter.getItemText(1))));
+        onView(withText(adapter.getItemText(1))).check(
+                isCompletelyAbove(withText(adapter.getItemText(2))));
+        onView(withText(adapter.getItemText(2))).check(
+                isCompletelyAbove(withText(adapter.getItemText(3))));
+    }
+
+    @Test
+    public void testOnHeightChanged_shouldAddTheValueToInitialTopValue() {
+        mActivity.runOnUiThread(
+                () -> mActivity.setContentView(R.layout.car_ui_recycler_view_test_activity));
+
+        onView(withId(R.id.list)).check(matches(isDisplayed()));
+
+        CarUiRecyclerView carUiRecyclerView = mActivity.findViewById(R.id.list);
+
+        assertEquals(carUiRecyclerView.getPaddingBottom(), 0);
+        assertEquals(carUiRecyclerView.getPaddingTop(), 0);
+        assertEquals(carUiRecyclerView.getPaddingStart(), 0);
+        assertEquals(carUiRecyclerView.getPaddingEnd(), 0);
+
+        mActivity.runOnUiThread(() -> carUiRecyclerView.onHeightChanged(10));
+        onView(withId(R.id.list)).check(matches(isDisplayed()));
+
+        assertEquals(carUiRecyclerView.getPaddingTop(), 10);
+        assertEquals(carUiRecyclerView.getPaddingBottom(), 0);
+        assertEquals(carUiRecyclerView.getPaddingStart(), 0);
+        assertEquals(carUiRecyclerView.getPaddingEnd(), 0);
+    }
+
+    @Test
+    public void testVisibility_goneAtInflationWithChangeToVisible() {
+        mActivity.runOnUiThread(
+                () -> mActivity.setContentView(
+                        R.layout.car_ui_recycler_view_gone_test_activity));
+
+        onView(withId(R.id.list)).check(matches(not(isDisplayed())));
+
+        CarUiRecyclerView carUiRecyclerView = mActivity.requireViewById(R.id.list);
+        TestAdapter adapter = new TestAdapter(3);
+        mActivity.runOnUiThread(() -> {
+            carUiRecyclerView.setAdapter(adapter);
+            carUiRecyclerView.setVisibility(View.VISIBLE);
+        });
+
+        // Check that items in are displayed.
+        onView(withText(adapter.getItemText(0))).check(matches(isDisplayed()));
+        onView(withText(adapter.getItemText(1))).check(matches(isDisplayed()));
+        onView(withText(adapter.getItemText(2))).check(matches(isDisplayed()));
+    }
+
+    @Test
+    public void testVisibility_invisibleAtInflationWithChangeToVisible() {
+        mActivity.runOnUiThread(
+                () -> mActivity.setContentView(
+                        R.layout.car_ui_recycler_view_invisible_test_activity));
+
+        onView(withId(R.id.list)).check(matches(not(isDisplayed())));
+
+        CarUiRecyclerView carUiRecyclerView = mActivity.requireViewById(R.id.list);
+        TestAdapter adapter = new TestAdapter(3);
+        mActivity.runOnUiThread(() -> {
+            carUiRecyclerView.setAdapter(adapter);
+            carUiRecyclerView.setVisibility(View.VISIBLE);
+        });
+
+        // Check that items in are displayed.
+        onView(withText(adapter.getItemText(0))).check(matches(isDisplayed()));
+        onView(withText(adapter.getItemText(1))).check(matches(isDisplayed()));
+        onView(withText(adapter.getItemText(2))).check(matches(isDisplayed()));
+    }
+
+    @Test
+    public void testFirstItemAtTop_onInitialLoad() {
+        mActivity.runOnUiThread(
+                () -> mActivity.setContentView(R.layout.car_ui_recycler_view_test_activity));
+
+        onView(withId(R.id.list)).check(matches(isDisplayed()));
+
+        CarUiRecyclerView carUiRecyclerView = mActivity.requireViewById(R.id.list);
+        TestAdapter adapter = new TestAdapter(25);
+        mActivity.runOnUiThread(() -> {
+            carUiRecyclerView.setAdapter(adapter);
+        });
+
+        onView(withText(adapter.getItemText(0))).check(matches(isDisplayed()));
+
+        LinearLayoutManager layoutManager =
+                (LinearLayoutManager) carUiRecyclerView.getLayoutManager();
+        assertEquals(layoutManager.findFirstVisibleItemPosition(), 0);
+    }
+
+    @Test
+    public void testPageUpAndDownMoveSameDistance() {
+        mActivity.runOnUiThread(
+                () -> mActivity.setContentView(R.layout.car_ui_recycler_view_test_activity));
+
+        onView(withId(R.id.list)).check(matches(isDisplayed()));
+
+        CarUiRecyclerView carUiRecyclerView = mActivity.requireViewById(R.id.list);
+        TestAdapter adapter = new TestAdapter(50);
+        mActivity.runOnUiThread(() -> {
+            carUiRecyclerView.setAdapter(adapter);
+        });
+
+        IdlingRegistry.getInstance().register(new ScrollIdlingResource(carUiRecyclerView));
+        onView(withText(adapter.getItemText(0))).check(matches(isDisplayed()));
+
+        LinearLayoutManager layoutManager =
+                (LinearLayoutManager) carUiRecyclerView.getLayoutManager();
+
+        // Move down one page so there will be sufficient pages for up and downs.
+        onView(withId(R.id.car_ui_scrollbar_page_down)).perform(click());
+
+        int topPosition = layoutManager.findFirstVisibleItemPosition();
+
+        for (int i = 0; i < 3; i++) {
+            onView(withId(R.id.car_ui_scrollbar_page_down)).perform(click());
+            onView(withId(R.id.car_ui_scrollbar_page_up)).perform(click());
+        }
+
+        assertEquals(layoutManager.findFirstVisibleItemPosition(), topPosition);
+    }
+
+    @Test
+    public void testContinuousScroll() {
+        mActivity.runOnUiThread(
+                () -> mActivity.setContentView(R.layout.car_ui_recycler_view_test_activity));
+
+        onView(withId(R.id.list)).check(matches(isDisplayed()));
+
+        CarUiRecyclerView carUiRecyclerView = mActivity.requireViewById(R.id.list);
+        TestAdapter adapter = new TestAdapter(50);
+        mActivity.runOnUiThread(() -> {
+            carUiRecyclerView.setAdapter(adapter);
+        });
+
+        IdlingRegistry.getInstance().register(new ScrollIdlingResource(carUiRecyclerView));
+        onView(withText(adapter.getItemText(0))).check(matches(isDisplayed()));
+
+        LinearLayoutManager layoutManager =
+                (LinearLayoutManager) carUiRecyclerView.getLayoutManager();
+
+        // Press and hold the down button for 2 seconds to scroll the list to bottom.
+        onView(withId(R.id.car_ui_scrollbar_page_down)).perform(pressAndHold());
+        onView(isRoot()).perform(waitForView(withText("Sample item #49"), 3000));
+        onView(withId(R.id.car_ui_scrollbar_page_down)).perform(release());
+
+        assertEquals(layoutManager.findLastCompletelyVisibleItemPosition(), 49);
+    }
+
+    @Test
+    public void testAlphaJumpToMiddleForThumbWhenTrackClicked() {
+        mActivity.runOnUiThread(
+                () -> mActivity.setContentView(R.layout.car_ui_recycler_view_test_activity));
+
+        onView(withId(R.id.list)).check(matches(isDisplayed()));
+
+        CarUiRecyclerView carUiRecyclerView = mActivity.requireViewById(R.id.list);
+        TestAdapter adapter = new TestAdapter(50);
+        mActivity.runOnUiThread(() -> {
+            carUiRecyclerView.setAdapter(adapter);
+        });
+
+        IdlingRegistry.getInstance().register(new ScrollIdlingResource(carUiRecyclerView));
+        onView(withText(adapter.getItemText(0))).check(matches(isDisplayed()));
+
+        View trackView = mActivity.requireViewById(R.id.car_ui_scrollbar_track);
+        // scroll to the middle
+        onView(withId(R.id.car_ui_scrollbar_track)).perform(
+                touchDownAndUp(0f, (trackView.getHeight() / 2f)));
+        onView(withText(adapter.getItemText(25))).check(matches(isDisplayed()));
+    }
+
+    @Test
+    public void testAlphaJumpToEndAndStartForThumbWhenTrackClicked() {
+        mActivity.runOnUiThread(
+                () -> mActivity.setContentView(R.layout.car_ui_recycler_view_test_activity));
+
+        onView(withId(R.id.list)).check(matches(isDisplayed()));
+
+        CarUiRecyclerView carUiRecyclerView = mActivity.requireViewById(R.id.list);
+        TestAdapter adapter = new TestAdapter(50);
+        mActivity.runOnUiThread(() -> {
+            carUiRecyclerView.setAdapter(adapter);
+        });
+
+        IdlingRegistry.getInstance().register(new ScrollIdlingResource(carUiRecyclerView));
+        onView(withText(adapter.getItemText(0))).check(matches(isDisplayed()));
+
+        View trackView = mActivity.requireViewById(R.id.car_ui_scrollbar_track);
+        View thumbView = mActivity.requireViewById(R.id.car_ui_scrollbar_thumb);
+        // scroll to the end
+        onView(withId(R.id.car_ui_scrollbar_track)).perform(
+                touchDownAndUp(0f, trackView.getHeight() - 1));
+        onView(withText(adapter.getItemText(49))).check(matches(isDisplayed()));
+
+        // scroll to the start
+        onView(withId(R.id.car_ui_scrollbar_track)).perform(
+                touchDownAndUp(0f, (thumbView.getHeight() / 2f) + 1));
+        onView(withText(adapter.getItemText(0))).check(matches(isDisplayed()));
+    }
+
+    @Test
+    public void testThumbDragToCenter() {
+        mActivity.runOnUiThread(
+                () -> mActivity.setContentView(R.layout.car_ui_recycler_view_test_activity));
+
+        onView(withId(R.id.list)).check(matches(isDisplayed()));
+
+        CarUiRecyclerView carUiRecyclerView = mActivity.requireViewById(R.id.list);
+        TestAdapter adapter = new TestAdapter(50);
+        mActivity.runOnUiThread(() -> {
+            carUiRecyclerView.setAdapter(adapter);
+        });
+
+        IdlingRegistry.getInstance().register(new ScrollIdlingResource(carUiRecyclerView));
+        onView(withText(adapter.getItemText(0))).check(matches(isDisplayed()));
+
+        View trackView = mActivity.requireViewById(R.id.car_ui_scrollbar_track);
+        View thumbView = mActivity.requireViewById(R.id.car_ui_scrollbar_thumb);
+        // drag and scroll to the middle
+        onView(withId(R.id.car_ui_scrollbar_track)).perform(
+                performDrag(0f, (thumbView.getHeight() / 2f), 0,
+                        (thumbView.getHeight() / 2f) - 1, 10, Float.MAX_VALUE,
+                        trackView.getHeight() / 2f));
+        onView(withText(adapter.getItemText(25))).check(matches(isDisplayed()));
+    }
+
+    @Test
+    public void testPageUpButtonDisabledAtTop() {
+        mActivity.runOnUiThread(
+                () -> mActivity.setContentView(R.layout.car_ui_recycler_view_test_activity));
+
+        onView(withId(R.id.list)).check(matches(isDisplayed()));
+
+        CarUiRecyclerView carUiRecyclerView = mActivity.requireViewById(R.id.list);
+        TestAdapter adapter = new TestAdapter(15);
+        mActivity.runOnUiThread(() -> {
+            carUiRecyclerView.setAdapter(adapter);
+        });
+
+        IdlingRegistry.getInstance().register(new ScrollIdlingResource(carUiRecyclerView));
+
+        // Initially page_up button is disabled.
+        onView(withId(R.id.car_ui_scrollbar_page_up)).check(matches(not(isEnabled())));
+
+        // Moving down, should enable the up bottom.
+        onView(withId(R.id.car_ui_scrollbar_page_down)).perform(click());
+        onView(withId(R.id.car_ui_scrollbar_page_up)).check(matches(isEnabled()));
+
+        // Move back up; this should disable the up button again.
+        onView(withId(R.id.car_ui_scrollbar_page_up)).perform(click()).check(
+                matches(not(isEnabled())));
+    }
+
+    @Test
+    public void testPageDownScrollsOverLongItem() {
+        mActivity.runOnUiThread(
+                () -> mActivity.setContentView(R.layout.car_ui_recycler_view_test_activity));
+
+        onView(withId(R.id.list)).check(matches(isDisplayed()));
+
+        int itemCount = 100;
+        // Position the long item in the middle.
+        int longItemPosition = itemCount / 2;
+
+        Map<Integer, TestAdapter.ItemHeight> heightOverrides = new HashMap<>();
+        heightOverrides.put(longItemPosition, TestAdapter.ItemHeight.TALL);
+        TestAdapter adapter = new TestAdapter(itemCount, heightOverrides);
+
+        CarUiRecyclerView carUiRecyclerView = mActivity.requireViewById(R.id.list);
+        mActivity.runOnUiThread(() -> {
+            carUiRecyclerView.setAdapter(adapter);
+        });
+
+        IdlingRegistry.getInstance().register(new ScrollIdlingResource(carUiRecyclerView));
+
+        OrientationHelper orientationHelper =
+                OrientationHelper.createVerticalHelper(carUiRecyclerView.getLayoutManager());
+
+        int screenHeight = Resources.getSystem().getDisplayMetrics().heightPixels;
+        // Scroll to a position where long item is partially visible.
+        // Scrolling from top, scrollToPosition() aligns the pos-1 item to bottom.
+        onView(withId(R.id.list)).perform(scrollToPosition(longItemPosition - 1));
+        // Scroll by half the height of the screen so the long item is partially visible.
+        mActivity.runOnUiThread(() -> carUiRecyclerView.scrollBy(0, screenHeight / 2));
+
+        onView(withText(adapter.getItemText(longItemPosition))).check(matches(isDisplayed()));
+
+        // Verify long item is partially shown.
+        View longItem = getLongItem(carUiRecyclerView);
+        assertThat(
+                orientationHelper.getDecoratedStart(longItem),
+                is(greaterThan(carUiRecyclerView.getTop())));
+
+        onView(withId(R.id.car_ui_scrollbar_page_down)).perform(click());
+
+        // Verify long item is snapped to top.
+        assertThat(orientationHelper.getDecoratedStart(longItem), is(equalTo(0)));
+        assertThat(orientationHelper.getDecoratedEnd(longItem),
+                is(greaterThan(carUiRecyclerView.getBottom())));
+
+        // Set a limit to avoid test stuck in non-moving state.
+        while (orientationHelper.getDecoratedEnd(longItem) > carUiRecyclerView.getBottom()) {
+            onView(withId(R.id.car_ui_scrollbar_page_down)).perform(click());
+        }
+
+        // Verify long item end is aligned to bottom.
+        assertThat(orientationHelper.getDecoratedEnd(longItem),
+                is(equalTo(carUiRecyclerView.getHeight())));
+
+        onView(withId(R.id.car_ui_scrollbar_page_down)).perform(click());
+        // Verify that the long item is no longer visible; Should be on the next child
+        assertThat(
+                orientationHelper.getDecoratedStart(longItem),
+                is(lessThan(carUiRecyclerView.getTop())));
+    }
+
+    @Test
+    public void testPageUpScrollsOverLongItem() {
+        mActivity.runOnUiThread(
+                () -> mActivity.setContentView(R.layout.car_ui_recycler_view_test_activity));
+
+        onView(withId(R.id.list)).check(matches(isDisplayed()));
+
+        int itemCount = 100;
+        // Position the long item in the middle.
+        int longItemPosition = itemCount / 2;
+
+        Map<Integer, TestAdapter.ItemHeight> heightOverrides = new HashMap<>();
+        heightOverrides.put(longItemPosition, TestAdapter.ItemHeight.TALL);
+        TestAdapter adapter = new TestAdapter(itemCount, heightOverrides);
+
+        CarUiRecyclerView carUiRecyclerView = mActivity.requireViewById(R.id.list);
+        mActivity.runOnUiThread(() -> {
+            carUiRecyclerView.setAdapter(adapter);
+        });
+
+        IdlingRegistry.getInstance().register(new ScrollIdlingResource(carUiRecyclerView));
+
+        OrientationHelper orientationHelper =
+                OrientationHelper.createVerticalHelper(carUiRecyclerView.getLayoutManager());
+
+        // Scroll to a position just below the long item.
+        onView(withId(R.id.list)).perform(scrollToPosition(longItemPosition + 1));
+
+        // Verify long item is off-screen.
+        View longItem = getLongItem(carUiRecyclerView);
+        assertThat(
+                orientationHelper.getDecoratedEnd(longItem),
+                is(greaterThan(carUiRecyclerView.getTop())));
+
+        onView(withId(R.id.car_ui_scrollbar_page_up)).perform(click());
+
+        // Verify long item is snapped to bottom.
+        assertThat(orientationHelper.getDecoratedEnd(longItem),
+                is(equalTo(carUiRecyclerView.getHeight())));
+        assertThat(orientationHelper.getDecoratedStart(longItem), is(lessThan(0)));
+
+
+        int decoratedStart = orientationHelper.getDecoratedStart(longItem);
+
+        while (decoratedStart < 0) {
+            onView(withId(R.id.car_ui_scrollbar_page_up)).perform(click());
+            decoratedStart = orientationHelper.getDecoratedStart(longItem);
+        }
+
+        // Verify long item top is aligned to top.
+        assertThat(orientationHelper.getDecoratedStart(longItem), is(equalTo(0)));
+    }
+
+    @Test
+    public void testPageDownScrollsOverVeryLongItem() {
+        mActivity.runOnUiThread(
+                () -> mActivity.setContentView(R.layout.car_ui_recycler_view_test_activity));
+
+        onView(withId(R.id.list)).check(matches(isDisplayed()));
+
+        int itemCount = 100;
+        // Position the long item in the middle.
+        int longItemPosition = itemCount / 2;
+
+        Map<Integer, TestAdapter.ItemHeight> heightOverrides = new HashMap<>();
+        heightOverrides.put(longItemPosition, TestAdapter.ItemHeight.EXTRA_TALL);
+        TestAdapter adapter = new TestAdapter(itemCount, heightOverrides);
+
+        CarUiRecyclerView carUiRecyclerView = mActivity.requireViewById(R.id.list);
+        mActivity.runOnUiThread(() -> {
+            carUiRecyclerView.setAdapter(adapter);
+        });
+
+        IdlingRegistry.getInstance().register(new ScrollIdlingResource(carUiRecyclerView));
+
+        OrientationHelper orientationHelper =
+                OrientationHelper.createVerticalHelper(carUiRecyclerView.getLayoutManager());
+
+        int screenHeight = Resources.getSystem().getDisplayMetrics().heightPixels;
+        // Scroll to a position where long item is partially visible.
+        // Scrolling from top, scrollToPosition() aligns the pos-1 item to bottom.
+        onView(withId(R.id.list)).perform(scrollToPosition(longItemPosition - 1));
+        // Scroll by half the height of the screen so the long item is partially visible.
+        mActivity.runOnUiThread(() -> carUiRecyclerView.scrollBy(0, screenHeight / 2));
+
+        onView(withText(adapter.getItemText(longItemPosition))).check(matches(isDisplayed()));
+
+        // Verify long item is partially shown.
+        View longItem = getLongItem(carUiRecyclerView);
+        assertThat(
+                orientationHelper.getDecoratedStart(longItem),
+                is(greaterThan(carUiRecyclerView.getTop())));
+
+        onView(withId(R.id.car_ui_scrollbar_page_down)).perform(click());
+
+        // Verify long item is snapped to top.
+        assertThat(orientationHelper.getDecoratedStart(longItem), is(equalTo(0)));
+        assertThat(orientationHelper.getDecoratedEnd(longItem),
+                is(greaterThan(carUiRecyclerView.getBottom())));
+
+        onView(withId(R.id.car_ui_scrollbar_page_down)).perform(click());
+
+        // Verify long item does not snap to bottom.
+        assertThat(orientationHelper.getDecoratedEnd(longItem),
+                not(equalTo(carUiRecyclerView.getHeight())));
+    }
+
+
+    @Test
+    public void testSetPaddingToRecyclerViewContainerWithScrollbar() {
+        doReturn(true).when(mTestableResources).getBoolean(R.bool.car_ui_scrollbar_enable);
+
+        CarUiRecyclerView mCarUiRecyclerView = new CarUiRecyclerView(mTestableContext);
+
+        assertThat(mCarUiRecyclerView.getPaddingBottom(), is(equalTo(0)));
+        assertThat(mCarUiRecyclerView.getPaddingTop(), is(equalTo(0)));
+        assertThat(mCarUiRecyclerView.getPaddingStart(), is(equalTo(0)));
+        assertThat(mCarUiRecyclerView.getPaddingEnd(), is(equalTo(0)));
+
+        mCarUiRecyclerView.setPadding(10, 10, 10, 10);
+
+        assertThat(mCarUiRecyclerView.getPaddingTop(), is(equalTo(10)));
+        assertThat(mCarUiRecyclerView.getPaddingBottom(), is(equalTo(10)));
+        assertThat(mCarUiRecyclerView.getPaddingStart(), is(equalTo(0)));
+        assertThat(mCarUiRecyclerView.getPaddingEnd(), is(equalTo(0)));
+    }
+
+    @Test
+    public void testSetPaddingToRecyclerViewContainerWithoutScrollbar() {
+        doReturn(false).when(mTestableResources).getBoolean(R.bool.car_ui_scrollbar_enable);
+
+        CarUiRecyclerView mCarUiRecyclerView = new CarUiRecyclerView(mTestableContext);
+
+        assertThat(mCarUiRecyclerView.getPaddingBottom(), is(equalTo(0)));
+        assertThat(mCarUiRecyclerView.getPaddingTop(), is(equalTo(0)));
+        assertThat(mCarUiRecyclerView.getPaddingStart(), is(equalTo(0)));
+        assertThat(mCarUiRecyclerView.getPaddingEnd(), is(equalTo(0)));
+
+        mCarUiRecyclerView.setPadding(10, 10, 10, 10);
+
+        assertThat(mCarUiRecyclerView.getPaddingTop(), is(equalTo(10)));
+        assertThat(mCarUiRecyclerView.getPaddingBottom(), is(equalTo(10)));
+        assertThat(mCarUiRecyclerView.getPaddingStart(), is(equalTo(10)));
+        assertThat(mCarUiRecyclerView.getPaddingEnd(), is(equalTo(10)));
+    }
+
+    @Test
+    public void testSetPaddingRelativeToRecyclerViewContainerWithScrollbar() {
+        doReturn(true).when(mTestableResources).getBoolean(R.bool.car_ui_scrollbar_enable);
+
+        CarUiRecyclerView mCarUiRecyclerView = new CarUiRecyclerView(mTestableContext);
+
+        assertThat(mCarUiRecyclerView.getPaddingBottom(), is(equalTo(0)));
+        assertThat(mCarUiRecyclerView.getPaddingTop(), is(equalTo(0)));
+        assertThat(mCarUiRecyclerView.getPaddingStart(), is(equalTo(0)));
+        assertThat(mCarUiRecyclerView.getPaddingEnd(), is(equalTo(0)));
+
+        mCarUiRecyclerView.setPaddingRelative(10, 10, 10, 10);
+
+        assertThat(mCarUiRecyclerView.getPaddingTop(), is(equalTo(10)));
+        assertThat(mCarUiRecyclerView.getPaddingBottom(), is(equalTo(10)));
+        assertThat(mCarUiRecyclerView.getPaddingStart(), is(equalTo(0)));
+        assertThat(mCarUiRecyclerView.getPaddingEnd(), is(equalTo(0)));
+    }
+
+    @Test
+    public void testSetPaddingRelativeToRecyclerViewContainerWithoutScrollbar() {
+        doReturn(false).when(mTestableResources).getBoolean(R.bool.car_ui_scrollbar_enable);
+
+        CarUiRecyclerView mCarUiRecyclerView = new CarUiRecyclerView(mTestableContext);
+
+        assertThat(mCarUiRecyclerView.getPaddingBottom(), is(equalTo(0)));
+        assertThat(mCarUiRecyclerView.getPaddingTop(), is(equalTo(0)));
+        assertThat(mCarUiRecyclerView.getPaddingStart(), is(equalTo(0)));
+        assertThat(mCarUiRecyclerView.getPaddingEnd(), is(equalTo(0)));
+
+        mCarUiRecyclerView.setPaddingRelative(10, 10, 10, 10);
+
+        assertThat(mCarUiRecyclerView.getPaddingTop(), is(equalTo(10)));
+        assertThat(mCarUiRecyclerView.getPaddingBottom(), is(equalTo(10)));
+        assertThat(mCarUiRecyclerView.getPaddingStart(), is(equalTo(10)));
+        assertThat(mCarUiRecyclerView.getPaddingEnd(), is(equalTo(10)));
+    }
+
+    /**
+     * Returns an item in the current list view whose height is taller than that of
+     * the CarUiRecyclerView. If that item exists, then it is returned; otherwise an {@link
+     * IllegalStateException} is thrown.
+     *
+     * @return An item that is taller than the CarUiRecyclerView.
+     */
+    private View getLongItem(CarUiRecyclerView recyclerView) {
+        for (int i = 0; i < recyclerView.getChildCount(); i++) {
+            View item = recyclerView.getChildAt(i);
+
+            if (item.getHeight() > recyclerView.getHeight()) {
+                return item;
+            }
+        }
+
+        throw new IllegalStateException(
+                "No item found that is longer than the height of the CarUiRecyclerView.");
+    }
+
+    /** A test adapter that handles inflating test views and binding data to it. */
+    private static class TestAdapter extends RecyclerView.Adapter<TestViewHolder> {
+
+        public enum ItemHeight {
+            STANDARD,
+            TALL,
+            EXTRA_TALL
+        }
+
+        private final List<String> mData;
+        private final Map<Integer, ItemHeight> mHeightOverrides;
+
+        TestAdapter(int itemCount, Map<Integer, ItemHeight> overrides) {
+            mHeightOverrides = overrides;
+            mData = new ArrayList<>(itemCount);
+
+            for (int i = 0; i < itemCount; i++) {
+                mData.add(getItemText(i));
+            }
+        }
+
+        TestAdapter(int itemCount) {
+            this(itemCount, new HashMap<>());
+        }
+
+        String getItemText(int position) {
+            if (position > mData.size()) {
+                return null;
+            }
+
+            return String.format("Sample item #%d", position);
+        }
+
+        @NonNull
+        @Override
+        public TestViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+            LayoutInflater inflater = LayoutInflater.from(parent.getContext());
+            return new TestViewHolder(inflater, parent);
+        }
+
+        @Override
+        public void onBindViewHolder(@NonNull TestViewHolder holder, int position) {
+            ItemHeight height = ItemHeight.STANDARD;
+
+            if (mHeightOverrides.containsKey(position)) {
+                height = mHeightOverrides.get(position);
+            }
+
+            int screenHeight = Resources.getSystem().getDisplayMetrics().heightPixels;
+
+            switch (height) {
+                case STANDARD:
+                    break;
+                case TALL:
+                    holder.itemView.setMinimumHeight(screenHeight);
+                    break;
+                case EXTRA_TALL:
+                    holder.itemView.setMinimumHeight(screenHeight * 2);
+                    break;
+                default:
+                    throw new IllegalStateException("Unexpected value: " + height);
+            }
+
+            holder.bind(mData.get(position));
+        }
+
+        @Override
+        public int getItemCount() {
+            return mData.size();
+        }
+    }
+
+    private static class TestViewHolder extends RecyclerView.ViewHolder {
+        private TextView mTextView;
+
+        TestViewHolder(LayoutInflater inflater, ViewGroup parent) {
+            super(inflater.inflate(R.layout.test_list_item, parent, false));
+            mTextView = itemView.findViewById(R.id.text);
+        }
+
+        void bind(String text) {
+            mTextView.setText(text);
+        }
+    }
+
+    /**
+     * An {@link IdlingResource} that will prevent assertions from running while the {@link
+     * CarUiRecyclerView} is scrolling.
+     */
+    private static class ScrollIdlingResource implements IdlingResource {
+        private boolean mIdle = true;
+        private ResourceCallback mResourceCallback;
+
+        ScrollIdlingResource(CarUiRecyclerView carUiRecyclerView) {
+            carUiRecyclerView
+                    .addOnScrollListener(
+                            new RecyclerView.OnScrollListener() {
+                                @Override
+                                public void onScrollStateChanged(@NonNull RecyclerView recyclerView,
+                                        int newState) {
+                                    super.onScrollStateChanged(recyclerView, newState);
+                                    mIdle = (newState == RecyclerView.SCROLL_STATE_IDLE
+                                            // Treat dragging as idle, or Espresso will
+                                            // block itself when swiping.
+                                            || newState == RecyclerView.SCROLL_STATE_DRAGGING);
+                                    if (mIdle && mResourceCallback != null) {
+                                        mResourceCallback.onTransitionToIdle();
+                                    }
+                                }
+
+                                @Override
+                                public void onScrolled(@NonNull RecyclerView recyclerView, int dx,
+                                        int dy) {
+                                }
+                            });
+        }
+
+        @Override
+        public String getName() {
+            return ScrollIdlingResource.class.getName();
+        }
+
+        @Override
+        public boolean isIdleNow() {
+            return mIdle;
+        }
+
+        @Override
+        public void registerIdleTransitionCallback(ResourceCallback callback) {
+            mResourceCallback = callback;
+        }
+    }
+}
diff --git a/car-ui-lib/tests/unit/src/com/android/car/ui/recyclerview/CarUiRecyclerViewTestActivity.java b/car-ui-lib/tests/unit/src/com/android/car/ui/recyclerview/CarUiRecyclerViewTestActivity.java
new file mode 100644
index 0000000..6fb5746
--- /dev/null
+++ b/car-ui-lib/tests/unit/src/com/android/car/ui/recyclerview/CarUiRecyclerViewTestActivity.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.car.ui.recyclerview;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+import com.android.car.ui.tests.unit.R;
+
+/**
+ * An {@link Activity} that contains only an empty {@link CarUiRecyclerView}.
+ */
+public class CarUiRecyclerViewTestActivity extends Activity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.car_ui_recycler_view_test_activity);
+    }
+}
diff --git a/car-ui-lib/tests/unit/src/com/android/car/ui/toolbar/ToolbarTest.java b/car-ui-lib/tests/unit/src/com/android/car/ui/toolbar/ToolbarTest.java
new file mode 100644
index 0000000..9d5af2c
--- /dev/null
+++ b/car-ui-lib/tests/unit/src/com/android/car/ui/toolbar/ToolbarTest.java
@@ -0,0 +1,267 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.car.ui.toolbar;
+
+import static androidx.test.espresso.Espresso.onView;
+import static androidx.test.espresso.action.ViewActions.click;
+import static androidx.test.espresso.assertion.ViewAssertions.matches;
+import static androidx.test.espresso.matcher.ViewMatchers.hasChildCount;
+import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static androidx.test.espresso.matcher.ViewMatchers.isRoot;
+import static androidx.test.espresso.matcher.ViewMatchers.withHint;
+import static androidx.test.espresso.matcher.ViewMatchers.withId;
+import static androidx.test.espresso.matcher.ViewMatchers.withText;
+
+import static com.android.car.ui.actions.ViewActions.waitForView;
+import static com.android.car.ui.matchers.ViewMatchers.nthChildOfView;
+import static com.android.car.ui.matchers.ViewMatchers.withDrawable;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.assertFalse;
+import static junit.framework.TestCase.assertTrue;
+
+import static org.hamcrest.core.IsNot.not;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+import android.app.Activity;
+import android.view.View;
+
+import androidx.test.rule.ActivityTestRule;
+
+import com.android.car.ui.core.CarUi;
+import com.android.car.ui.tests.unit.R;
+
+import org.hamcrest.Matcher;
+import org.junit.Rule;
+import org.junit.Test;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.function.Consumer;
+
+/** Unit test for {@link ToolbarController}. */
+public class ToolbarTest {
+
+    @Rule
+    public ActivityTestRule<ToolbarTestActivity> mActivityRule =
+            new ActivityTestRule<>(ToolbarTestActivity.class);
+
+    @Test
+    public void test_setTitle_displaysTitle() throws Throwable {
+        runWithToolbar((toolbar) -> toolbar.setTitle("Test title"));
+
+        onView(withText("Test title")).check(matches(isDisplayed()));
+    }
+
+    @Test
+    public void test_setSubtitle_displaysSubtitle() throws Throwable {
+        runWithToolbar((toolbar) -> toolbar.setSubtitle("Test subtitle"));
+
+        onView(withText("Test subtitle")).check(matches(isDisplayed()));
+    }
+
+    @Test
+    public void test_setSearchHint_isDisplayed() throws Throwable {
+        runWithToolbar((toolbar) -> {
+            toolbar.setSearchHint("Test search hint");
+            toolbar.setState(Toolbar.State.SEARCH);
+        });
+
+        onView(withHint("Test search hint")).check(matches(isDisplayed()));
+    }
+
+    @Test
+    public void setters_and_getters_test() throws Throwable {
+        runWithToolbar((toolbar) -> {
+            toolbar.setTitle("Foo");
+            toolbar.setSearchHint("Foo2");
+            toolbar.setShowMenuItemsWhileSearching(true);
+            toolbar.setState(Toolbar.State.SUBPAGE);
+            toolbar.setNavButtonMode(Toolbar.NavButtonMode.CLOSE);
+
+            assertThat(toolbar.getTitle().toString()).isEqualTo("Foo");
+            assertThat(toolbar.getSearchHint().toString()).isEqualTo("Foo2");
+            assertThat(toolbar.getShowMenuItemsWhileSearching()).isEqualTo(true);
+            assertThat(toolbar.getState()).isEquivalentAccordingToCompareTo(Toolbar.State.SUBPAGE);
+            assertThat(toolbar.getNavButtonMode()).isEquivalentAccordingToCompareTo(
+                    Toolbar.NavButtonMode.CLOSE);
+        });
+    }
+
+    @Test
+    public void test_setLogo_displaysLogo() throws Throwable {
+        runWithToolbar((toolbar) -> toolbar.setLogo(R.drawable.ic_launcher));
+
+        onView(withDrawable(R.drawable.ic_launcher)).check(matches(isDisplayed()));
+    }
+
+    @Test
+    public void pressBack_withoutListener_callsActivityOnBack() throws Throwable {
+        runWithToolbar((toolbar) -> toolbar.setState(Toolbar.State.SUBPAGE));
+
+        onView(withId(R.id.car_ui_toolbar_nav_icon_container)).perform(click());
+
+        assertTrue(mActivityRule.getActivity().isFinishing());
+        assertEquals(mActivityRule.getActivityResult().getResultCode(), Activity.RESULT_CANCELED);
+    }
+
+    @Test
+    public void pressBack_withListenerThatReturnsFalse_callsActivityOnBack() throws Throwable {
+        runWithToolbar((toolbar) -> {
+            toolbar.setState(Toolbar.State.SUBPAGE);
+            toolbar.registerOnBackListener(() -> false);
+        });
+
+        onView(withId(R.id.car_ui_toolbar_nav_icon_container)).perform(click());
+
+        assertTrue(mActivityRule.getActivity().isFinishing());
+        assertEquals(mActivityRule.getActivityResult().getResultCode(), Activity.RESULT_CANCELED);
+    }
+
+    @Test
+    public void pressBack_withListenerThatReturnsTrue_doesntCallActivityOnBack() throws Throwable {
+        runWithToolbar((toolbar) -> {
+            toolbar.setState(Toolbar.State.SUBPAGE);
+            toolbar.registerOnBackListener(() -> true);
+        });
+
+        onView(withId(R.id.car_ui_toolbar_nav_icon_container)).perform(click());
+
+        assertFalse(mActivityRule.getActivity().isFinishing());
+    }
+
+    @Test
+    public void pressBack_withUnregisteredListener_doesntCallActivityOnBack() throws Throwable {
+        runWithToolbar((toolbar) -> {
+            toolbar.setState(Toolbar.State.SUBPAGE);
+            Toolbar.OnBackListener listener = () -> true;
+            toolbar.registerOnBackListener(listener);
+            toolbar.registerOnBackListener(listener);
+            toolbar.unregisterOnBackListener(listener);
+        });
+
+        onView(withId(R.id.car_ui_toolbar_nav_icon_container)).perform(click());
+
+        assertTrue(mActivityRule.getActivity().isFinishing());
+    }
+
+    @Test
+    public void menuItems_setId_shouldWork() {
+        MenuItem item = MenuItem.builder(mActivityRule.getActivity()).build();
+
+        assertThat(item.getId()).isEqualTo(View.NO_ID);
+
+        item.setId(7);
+
+        assertThat(item.getId()).isEqualTo(7);
+    }
+
+    @Test
+    public void menuItems_whenClicked_shouldCallListener() throws Throwable {
+        MenuItem.OnClickListener callback = mock(MenuItem.OnClickListener.class);
+        MenuItem menuItem = MenuItem.builder(mActivityRule.getActivity())
+                .setTitle("Button!")
+                .setOnClickListener(callback)
+                .build();
+        runWithToolbar((toolbar) -> toolbar.setMenuItems(Collections.singletonList(menuItem)));
+
+        waitForMenuItems();
+
+        onView(firstMenuItem()).perform(click());
+
+        verify(callback).onClick(menuItem);
+    }
+
+    @Test
+    public void menuItems_null_shouldRemoveExistingMenuItems() throws Throwable {
+        runWithToolbar((toolbar) ->
+                toolbar.setMenuItems(Arrays.asList(
+                        MenuItem.builder(mActivityRule.getActivity())
+                                .setTitle("Button!")
+                                .build(),
+                        MenuItem.builder(mActivityRule.getActivity())
+                                .setTitle("Button2!")
+                                .build()
+                )));
+        waitForMenuItems();
+
+        onView(withId(R.id.car_ui_toolbar_menu_items_container)).check(matches(hasChildCount(2)));
+
+        runWithToolbar((toolbar) -> toolbar.setMenuItems(null));
+
+        onView(withId(R.id.car_ui_toolbar_menu_items_container)).check(matches(hasChildCount(0)));
+    }
+
+    @Test
+    public void menuItems_setVisibility_shouldHide() throws Throwable {
+        MenuItem menuItem = MenuItem.builder(mActivityRule.getActivity())
+                .setTitle("Button!")
+                .build();
+        runWithToolbar((toolbar) -> toolbar.setMenuItems(Collections.singletonList(menuItem)));
+        waitForMenuItems();
+
+        onView(withText("Button!")).check(matches(isDisplayed()));
+
+        runWithToolbar((toolbar) -> menuItem.setVisible(false));
+
+        onView(withText("Button!")).check(matches(not(isDisplayed())));
+    }
+
+    @Test
+    public void menuItems_searchScreen_shouldHideMenuItems() throws Throwable {
+        runWithToolbar((toolbar) -> {
+            toolbar.setMenuItems(Arrays.asList(
+                    MenuItem.builder(mActivityRule.getActivity())
+                            .setToSearch()
+                            .build(),
+                    MenuItem.builder(mActivityRule.getActivity())
+                            .setTitle("Button!")
+                            .build()));
+            toolbar.setShowMenuItemsWhileSearching(false);
+            toolbar.setState(Toolbar.State.SEARCH);
+        });
+        waitForMenuItems();
+
+        // All menuitems should be hidden if we're hiding menuitems while searching
+        onView(withText("Button!")).check(matches(not(isDisplayed())));
+        onView(firstMenuItem()).check(matches(not(isDisplayed())));
+
+        runWithToolbar((toolbar) -> toolbar.setShowMenuItemsWhileSearching(true));
+
+        // Even if not hiding MenuItems while searching, the search MenuItem should still be hidden
+        onView(withText("Button!")).check(matches(isDisplayed()));
+        onView(firstMenuItem()).check(matches(not(isDisplayed())));
+    }
+
+    private void runWithToolbar(Consumer<ToolbarController> toRun) throws Throwable {
+        mActivityRule.runOnUiThread(() -> {
+            ToolbarController toolbar = CarUi.requireToolbar(mActivityRule.getActivity());
+            toRun.accept(toolbar);
+        });
+    }
+
+    private Matcher<View> firstMenuItem() {
+        return nthChildOfView(withId(R.id.car_ui_toolbar_menu_items_container), 0);
+    }
+
+    private void waitForMenuItems() {
+        onView(isRoot()).perform(waitForView(firstMenuItem(), 500));
+    }
+}
diff --git a/car-ui-lib/tests/unit/src/com/android/car/ui/toolbar/ToolbarTestActivity.java b/car-ui-lib/tests/unit/src/com/android/car/ui/toolbar/ToolbarTestActivity.java
new file mode 100644
index 0000000..e54ac83
--- /dev/null
+++ b/car-ui-lib/tests/unit/src/com/android/car/ui/toolbar/ToolbarTestActivity.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.car.ui.toolbar;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+import com.android.car.ui.tests.unit.R;
+
+/** An Activity used for testing {@link ToolbarController}. */
+public class ToolbarTestActivity extends Activity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.empty_test_activity);
+    }
+}
diff --git a/car-ui-lib/trailing-blank-line-hook.sh b/car-ui-lib/trailing-blank-line-hook.sh
new file mode 100755
index 0000000..d69489d
--- /dev/null
+++ b/car-ui-lib/trailing-blank-line-hook.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+
+result=$(find car-ui-lib/ -type f \( -iname \*.java -o -iname \*.xml \) -a \( ! -wholename \*/.idea/\* \) -print0 | xargs -0 -L1 bash -c 'test "$(tail -c 1 "$0")" && echo "No new line at end of $0"')
+if [ \( ! -z "$result" \)  -o \( $(echo "$result" | wc -l) -gt 1 \) ]
+then
+    echo "$result" && false;
+fi
diff --git a/connected-device-lib/Android.bp b/connected-device-lib/Android.bp
index 85490be..55ee640 100644
--- a/connected-device-lib/Android.bp
+++ b/connected-device-lib/Android.bp
@@ -30,13 +30,14 @@
     libs: ["android.car"],
 
     static_libs: [
-        "EncryptionRunner-lib",
         "androidx.room_room-runtime",
         "connected-device-protos",
+        "encryption-runner",
+        "guava",
     ],
 
     plugins: [
-        "car-androidx-room-compiler",
+        "androidx.room_room-compiler-plugin",
     ],
 
     platform_apis: true,
diff --git a/connected-device-lib/lib/kotlin-reflect-sources.jar b/connected-device-lib/lib/kotlin-reflect-sources.jar
deleted file mode 100644
index 917a722..0000000
--- a/connected-device-lib/lib/kotlin-reflect-sources.jar
+++ /dev/null
Binary files differ
diff --git a/connected-device-lib/lib/kotlin-reflect.jar b/connected-device-lib/lib/kotlin-reflect.jar
deleted file mode 100644
index e872351..0000000
--- a/connected-device-lib/lib/kotlin-reflect.jar
+++ /dev/null
Binary files differ
diff --git a/connected-device-lib/lib/kotlin-stdlib-jdk7-sources.jar b/connected-device-lib/lib/kotlin-stdlib-jdk7-sources.jar
deleted file mode 100644
index 551568d..0000000
--- a/connected-device-lib/lib/kotlin-stdlib-jdk7-sources.jar
+++ /dev/null
Binary files differ
diff --git a/connected-device-lib/lib/kotlin-stdlib-jdk7.jar b/connected-device-lib/lib/kotlin-stdlib-jdk7.jar
deleted file mode 100644
index d80ae96..0000000
--- a/connected-device-lib/lib/kotlin-stdlib-jdk7.jar
+++ /dev/null
Binary files differ
diff --git a/connected-device-lib/lib/kotlin-stdlib-jdk8-sources.jar b/connected-device-lib/lib/kotlin-stdlib-jdk8-sources.jar
deleted file mode 100644
index 3538660..0000000
--- a/connected-device-lib/lib/kotlin-stdlib-jdk8-sources.jar
+++ /dev/null
Binary files differ
diff --git a/connected-device-lib/lib/kotlin-stdlib-jdk8.jar b/connected-device-lib/lib/kotlin-stdlib-jdk8.jar
deleted file mode 100644
index 08101a3..0000000
--- a/connected-device-lib/lib/kotlin-stdlib-jdk8.jar
+++ /dev/null
Binary files differ
diff --git a/connected-device-lib/lib/kotlin-stdlib-sources.jar b/connected-device-lib/lib/kotlin-stdlib-sources.jar
deleted file mode 100644
index 2bdaf9e..0000000
--- a/connected-device-lib/lib/kotlin-stdlib-sources.jar
+++ /dev/null
Binary files differ
diff --git a/connected-device-lib/lib/kotlin-stdlib.jar b/connected-device-lib/lib/kotlin-stdlib.jar
deleted file mode 100644
index 2bd7644..0000000
--- a/connected-device-lib/lib/kotlin-stdlib.jar
+++ /dev/null
Binary files differ
diff --git a/connected-device-lib/lib/kotlin-test-sources.jar b/connected-device-lib/lib/kotlin-test-sources.jar
deleted file mode 100644
index 7bd21ce..0000000
--- a/connected-device-lib/lib/kotlin-test-sources.jar
+++ /dev/null
Binary files differ
diff --git a/connected-device-lib/lib/kotlin-test.jar b/connected-device-lib/lib/kotlin-test.jar
deleted file mode 100644
index ede1d8b..0000000
--- a/connected-device-lib/lib/kotlin-test.jar
+++ /dev/null
Binary files differ
diff --git a/connected-device-lib/res/values/config.xml b/connected-device-lib/res/values/config.xml
index 0f88ddc..b090b92 100644
--- a/connected-device-lib/res/values/config.xml
+++ b/connected-device-lib/res/values/config.xml
@@ -16,9 +16,11 @@
   -->
 
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
-    <string name="car_service_uuid" translatable="false">5e2a68a8-27be-43f9-8d1e-4546976fabd7</string>
-    <string name="car_association_service_uuid" translatable="false">5e2a68a4-27be-43f9-8d1e-4546976fabd7</string>
+    <!-- These values must be modified for the connected device lib to function properly.-->
+    <string name="car_service_uuid" translatable="false">00000000-0000-0000-0000-000000000000</string>
+    <string name="car_association_service_uuid" translatable="false">00000000-0000-0000-0000-000000000000</string>
+    <string name="car_reconnect_service_uuid" translatable="false">00000000-0000-0000-0000-000000000000</string>
+    <string name="car_reconnect_data_uuid" translatable="false">00000000-0000-0000-0000-000000000000</string>
     <string name="car_bg_mask" translatable="false">00000000000000000000000000000000</string>
 
     <string name="car_secure_read_uuid" translatable="false">5e2a68a6-27be-43f9-8d1e-4546976fabd7</string>
@@ -26,5 +28,10 @@
 
     <string name="connected_device_shared_preferences" translatable="false">com.android.car.connecteddevice</string>
 
-    <integer name="car_reconnect_timeout_sec">60</integer>
+    <!--
+    This value must be between 23 and 185. 23 is the default MTU size for Android, and 185 is
+    the max MTU size supported for iOS. Verify your device and target companion devices support a
+    larger MTU prior to modifying.
+    -->
+    <integer name="car_default_mtu_size">23</integer>
 </resources>
diff --git a/connected-device-lib/src/com/android/car/connecteddevice/ConnectedDeviceManager.java b/connected-device-lib/src/com/android/car/connecteddevice/ConnectedDeviceManager.java
index f8805a1..4add85e 100644
--- a/connected-device-lib/src/com/android/car/connecteddevice/ConnectedDeviceManager.java
+++ b/connected-device-lib/src/com/android/car/connecteddevice/ConnectedDeviceManager.java
@@ -44,6 +44,7 @@
 import com.android.internal.annotations.VisibleForTesting;
 
 import java.lang.annotation.Retention;
+import java.time.Duration;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -72,6 +73,10 @@
     // Subtracting 2 bytes used by header, we have 8 bytes for device name.
     private static final int DEVICE_NAME_LENGTH_LIMIT = 8;
 
+    // The mac address randomly rotates every 7-15 minutes. To be safe, we will rotate our
+    // reconnect advertisement every 6 minutes to avoid crossing a rotation.
+    private static final Duration MAX_ADVERTISEMENT_DURATION = Duration.ofMinutes(6);
+
     private final ConnectedDeviceStorage mStorage;
 
     private final CarBleCentralManager mCentralManager;
@@ -96,7 +101,7 @@
             new ConcurrentHashMap<>();
 
     // recipientId -> (deviceId -> message bytes)
-    private final Map<UUID, Map<String, byte[]>> mRecipientMissedMessages =
+    private final Map<UUID, Map<String, List<byte[]>>> mRecipientMissedMessages =
             new ConcurrentHashMap<>();
 
     // Recipient ids that received multiple callback registrations indicate that the recipient id
@@ -109,8 +114,6 @@
 
     private final AtomicBoolean mHasStarted = new AtomicBoolean(false);
 
-    private final int mReconnectTimeoutSeconds;
-
     private String mNameForAssociation;
 
     private AssociationCallback mAssociationCallback;
@@ -149,10 +152,12 @@
                 new BlePeripheralManager(context),
                 UUID.fromString(context.getString(R.string.car_service_uuid)),
                 UUID.fromString(context.getString(R.string.car_association_service_uuid)),
+                UUID.fromString(context.getString(R.string.car_reconnect_service_uuid)),
+                UUID.fromString(context.getString(R.string.car_reconnect_data_uuid)),
                 context.getString(R.string.car_bg_mask),
                 UUID.fromString(context.getString(R.string.car_secure_write_uuid)),
                 UUID.fromString(context.getString(R.string.car_secure_read_uuid)),
-                context.getResources().getInteger(R.integer.car_reconnect_timeout_sec));
+                context.getResources().getInteger(R.integer.car_default_mtu_size));
     }
 
     private ConnectedDeviceManager(
@@ -162,23 +167,25 @@
             @NonNull BlePeripheralManager blePeripheralManager,
             @NonNull UUID serviceUuid,
             @NonNull UUID associationServiceUuid,
+            @NonNull UUID reconnectServiceUuid,
+            @NonNull UUID reconnectDataUuid,
             @NonNull String bgMask,
             @NonNull UUID writeCharacteristicUuid,
             @NonNull UUID readCharacteristicUuid,
-            int reconnectTimeoutSeconds) {
+            int defaultMtuSize) {
         this(storage,
                 new CarBleCentralManager(context, bleCentralManager, storage, serviceUuid, bgMask,
                         writeCharacteristicUuid, readCharacteristicUuid),
                 new CarBlePeripheralManager(blePeripheralManager, storage, associationServiceUuid,
-                        writeCharacteristicUuid, readCharacteristicUuid), reconnectTimeoutSeconds);
+                        reconnectServiceUuid, reconnectDataUuid, writeCharacteristicUuid,
+                        readCharacteristicUuid, MAX_ADVERTISEMENT_DURATION, defaultMtuSize));
     }
 
     @VisibleForTesting
     ConnectedDeviceManager(
             @NonNull ConnectedDeviceStorage storage,
             @NonNull CarBleCentralManager centralManager,
-            @NonNull CarBlePeripheralManager peripheralManager,
-            int reconnectTimeoutSeconds) {
+            @NonNull CarBlePeripheralManager peripheralManager) {
         Executor callbackExecutor = Executors.newSingleThreadExecutor();
         mStorage = storage;
         mCentralManager = centralManager;
@@ -187,7 +194,6 @@
         mPeripheralManager.registerCallback(generateCarBleCallback(peripheralManager),
                 callbackExecutor);
         mStorage.setAssociatedDeviceCallback(mAssociatedDeviceCallback);
-        mReconnectTimeoutSeconds = reconnectTimeoutSeconds;
     }
 
     /**
@@ -308,8 +314,7 @@
             }
             EventLog.onStartDeviceSearchStarted();
             mIsConnectingToUserDevice.set(true);
-            mPeripheralManager.connectToDevice(UUID.fromString(userDevice.getDeviceId()),
-                    mReconnectTimeoutSeconds);
+            mPeripheralManager.connectToDevice(UUID.fromString(userDevice.getDeviceId()));
         } catch (Exception e) {
             loge(TAG, "Exception while attempting connection with active user's device.", e);
         }
@@ -372,7 +377,7 @@
     public void enableAssociatedDeviceConnection(@NonNull String deviceId) {
         logd(TAG, "enableAssociatedDeviceConnection() called on " + deviceId);
         mStorage.updateAssociatedDeviceConnectionEnabled(deviceId,
-                /* isConnectionEnabled = */ true);
+                /* isConnectionEnabled= */ true);
         connectToActiveUserDevice();
     }
 
@@ -384,7 +389,7 @@
     public void disableAssociatedDeviceConnection(@NonNull String deviceId) {
         logd(TAG, "disableAssociatedDeviceConnection() called on " + deviceId);
         mStorage.updateAssociatedDeviceConnectionEnabled(deviceId,
-                /* isConnectionEnabled = */ false);
+                /* isConnectionEnabled= */ false);
         disconnectDevice(deviceId);
     }
 
@@ -429,10 +434,12 @@
         newCallbacks.add(callback, executor);
         recipientCallbacks.put(recipientId, newCallbacks);
 
-        byte[] message = popMissedMessage(recipientId, device.getDeviceId());
-        if (message != null) {
-            newCallbacks.invoke(deviceCallback ->
-                    deviceCallback.onMessageReceived(device, message));
+        List<byte[]> messages = popMissedMessages(recipientId, device.getDeviceId());
+        if (messages != null) {
+            for (byte[] message : messages) {
+                newCallbacks.invoke(deviceCallback ->
+                        deviceCallback.onMessageReceived(device, message));
+            }
         }
     }
 
@@ -458,8 +465,8 @@
         // Store last message in case recipient registers callbacks in the future.
         logd(TAG, "No recipient registered for device " + deviceId + " and recipient "
                 + recipientId + " combination. Saving message.");
-        mRecipientMissedMessages.putIfAbsent(recipientId, new HashMap<>());
-        mRecipientMissedMessages.get(recipientId).putIfAbsent(deviceId, message);
+        mRecipientMissedMessages.computeIfAbsent(recipientId, __ -> new HashMap<>())
+                .computeIfAbsent(deviceId, __ -> new ArrayList<>()).add(message);
     }
 
     /**
@@ -468,12 +475,12 @@
      *
      * @param recipientId Recipient's id
      * @param deviceId Device id
-     * @return The last missed {@code byte[]} of the message, or {@code null} if no messages were
+     * @return The missed {@code byte[]} messages, or {@code null} if no messages were
      *         missed.
      */
     @Nullable
-    private byte[] popMissedMessage(@NonNull UUID recipientId, @NonNull String deviceId) {
-        Map<String, byte[]> missedMessages = mRecipientMissedMessages.get(recipientId);
+    private List<byte[]> popMissedMessages(@NonNull UUID recipientId, @NonNull String deviceId) {
+        Map<String, List<byte[]>> missedMessages = mRecipientMissedMessages.get(recipientId);
         if (missedMessages == null) {
             return null;
         }
@@ -519,7 +526,7 @@
      */
     public void sendMessageSecurely(@NonNull ConnectedDevice device, @NonNull UUID recipientId,
             @NonNull byte[] message) throws IllegalStateException {
-        sendMessage(device, recipientId, message, /* isEncrypted = */ true);
+        sendMessage(device, recipientId, message, /* isEncrypted= */ true);
     }
 
     /**
@@ -531,7 +538,7 @@
      */
     public void sendMessageUnsecurely(@NonNull ConnectedDevice device, @NonNull UUID recipientId,
             @NonNull byte[] message) {
-        sendMessage(device, recipientId, message, /* isEncrypted = */ false);
+        sendMessage(device, recipientId, message, /* isEncrypted= */ false);
     }
 
     private void sendMessage(@NonNull ConnectedDevice device, @NonNull UUID recipientId,
@@ -596,9 +603,9 @@
         logd(TAG, "New device with id " + deviceId + " connected.");
         ConnectedDevice connectedDevice = new ConnectedDevice(
                 deviceId,
-                /* deviceName = */ null,
+                /* deviceName= */ null,
                 mStorage.getActiveUserAssociatedDeviceIds().contains(deviceId),
-                /* hasSecureChannel = */ false
+                /* hasSecureChannel= */ false
         );
 
         mConnectedDevices.put(deviceId, new InternalConnectedDevice(connectedDevice, bleManager));
@@ -642,7 +649,7 @@
         ConnectedDevice connectedDevice = mConnectedDevices.get(deviceId).mConnectedDevice;
         ConnectedDevice updatedConnectedDevice = new ConnectedDevice(connectedDevice.getDeviceId(),
                 connectedDevice.getDeviceName(), connectedDevice.isAssociatedWithActiveUser(),
-                /* hasSecureChannel = */ true);
+                /* hasSecureChannel= */ true);
 
         boolean notifyCallbacks = getConnectedDeviceForManager(deviceId, bleManager) != null;
 
diff --git a/connected-device-lib/src/com/android/car/connecteddevice/ble/AssociationSecureChannel.java b/connected-device-lib/src/com/android/car/connecteddevice/ble/AssociationSecureChannel.java
new file mode 100644
index 0000000..349af9e
--- /dev/null
+++ b/connected-device-lib/src/com/android/car/connecteddevice/ble/AssociationSecureChannel.java
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.car.connecteddevice.ble;
+
+import static android.car.encryptionrunner.EncryptionRunnerFactory.EncryptionRunnerType;
+import static android.car.encryptionrunner.EncryptionRunnerFactory.newRunner;
+import static android.car.encryptionrunner.HandshakeMessage.HandshakeState;
+
+import static com.android.car.connecteddevice.util.SafeLog.logd;
+import static com.android.car.connecteddevice.util.SafeLog.loge;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.car.encryptionrunner.EncryptionRunner;
+import android.car.encryptionrunner.HandshakeException;
+import android.car.encryptionrunner.HandshakeMessage;
+import android.car.encryptionrunner.Key;
+
+import com.android.car.connecteddevice.storage.ConnectedDeviceStorage;
+import com.android.car.connecteddevice.util.ByteUtils;
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.security.InvalidParameterException;
+import java.util.Arrays;
+import java.util.UUID;
+
+/**
+ * A secure channel established with the association flow.
+ */
+class AssociationSecureChannel extends SecureBleChannel {
+
+    private static final String TAG = "AssociationSecureChannel";
+
+    private static final int DEVICE_ID_BYTES = 16;
+
+    private final ConnectedDeviceStorage mStorage;
+
+    private ShowVerificationCodeListener mShowVerificationCodeListener;
+
+    @HandshakeState
+    private int mState = HandshakeState.UNKNOWN;
+
+    private Key mPendingKey;
+
+    private String mDeviceId;
+
+    AssociationSecureChannel(BleDeviceMessageStream stream, ConnectedDeviceStorage storage) {
+        this(stream, storage, newRunner(EncryptionRunnerType.UKEY2));
+    }
+
+    AssociationSecureChannel(BleDeviceMessageStream stream, ConnectedDeviceStorage storage,
+            EncryptionRunner encryptionRunner) {
+        super(stream, encryptionRunner);
+        encryptionRunner.setIsReconnect(false);
+        mStorage = storage;
+    }
+
+    @Override
+    void processHandshake(@NonNull byte[] message) throws HandshakeException {
+        switch (mState) {
+            case HandshakeState.UNKNOWN:
+                processHandshakeUnknown(message);
+                break;
+            case HandshakeState.IN_PROGRESS:
+                processHandshakeInProgress(message);
+                break;
+            case HandshakeState.FINISHED:
+                processHandshakeDeviceIdAndSecret(message);
+                break;
+            default:
+                loge(TAG, "Encountered unexpected handshake state: " + mState + ".");
+                notifySecureChannelFailure(CHANNEL_ERROR_INVALID_STATE);
+        }
+    }
+
+    private void processHandshakeUnknown(@NonNull byte[] message) throws HandshakeException {
+        logd(TAG, "Responding to handshake init request.");
+        HandshakeMessage handshakeMessage = getEncryptionRunner().respondToInitRequest(message);
+        mState = handshakeMessage.getHandshakeState();
+        sendHandshakeMessage(handshakeMessage.getNextMessage(), /* isEncrypted= */ false);
+    }
+
+    private void processHandshakeInProgress(@NonNull byte[] message) throws HandshakeException {
+        logd(TAG, "Continuing handshake.");
+        HandshakeMessage handshakeMessage = getEncryptionRunner().continueHandshake(message);
+        mState = handshakeMessage.getHandshakeState();
+
+        if (mState != HandshakeState.VERIFICATION_NEEDED) {
+            loge(TAG, "processHandshakeInProgress: Encountered unexpected handshake state: "
+                    + mState + ".");
+            notifySecureChannelFailure(CHANNEL_ERROR_INVALID_STATE);
+            return;
+        }
+
+        String code = handshakeMessage.getVerificationCode();
+        if (code == null) {
+            loge(TAG, "Unable to get verification code.");
+            notifySecureChannelFailure(CHANNEL_ERROR_INVALID_VERIFICATION);
+            return;
+        }
+
+        if (mShowVerificationCodeListener == null) {
+            loge(TAG, "No verification code listener has been set. Unable to display verification "
+                    + "code to user.");
+            notifySecureChannelFailure(CHANNEL_ERROR_INVALID_STATE);
+            return;
+        }
+
+        logd(TAG, "Showing pairing code: " + code);
+        mShowVerificationCodeListener.showVerificationCode(code);
+    }
+
+    private void processHandshakeDeviceIdAndSecret(@NonNull byte[] message) {
+        UUID deviceId = ByteUtils.bytesToUUID(Arrays.copyOf(message, DEVICE_ID_BYTES));
+        if (deviceId == null) {
+            loge(TAG, "Received invalid device id. Aborting.");
+            notifySecureChannelFailure(CHANNEL_ERROR_INVALID_DEVICE_ID);
+            return;
+        }
+        mDeviceId = deviceId.toString();
+        notifyCallback(callback -> callback.onDeviceIdReceived(mDeviceId));
+
+        mStorage.saveEncryptionKey(mDeviceId, mPendingKey.asBytes());
+        mPendingKey = null;
+        try {
+            mStorage.saveChallengeSecret(mDeviceId,
+                    Arrays.copyOfRange(message, DEVICE_ID_BYTES, message.length));
+        } catch (InvalidParameterException e) {
+            loge(TAG, "Error saving challenge secret.", e);
+            notifySecureChannelFailure(CHANNEL_ERROR_STORAGE_ERROR);
+            return;
+        }
+
+        notifyCallback(Callback::onSecureChannelEstablished);
+    }
+
+    /** Set the listener that notifies to show verification code. {@code null} to clear. */
+    void setShowVerificationCodeListener(@Nullable ShowVerificationCodeListener listener) {
+        mShowVerificationCodeListener = listener;
+    }
+
+    @VisibleForTesting
+    @Nullable
+    ShowVerificationCodeListener getShowVerificationCodeListener() {
+        return mShowVerificationCodeListener;
+    }
+
+    /**
+     * Called by the client to notify that the user has accepted a pairing code or any out-of-band
+     * confirmation, and send confirmation signals to remote bluetooth device.
+     */
+    void notifyOutOfBandAccepted() {
+        HandshakeMessage message;
+        try {
+            message = getEncryptionRunner().verifyPin();
+        } catch (HandshakeException e) {
+            loge(TAG, "Error during PIN verification", e);
+            notifySecureChannelFailure(CHANNEL_ERROR_INVALID_VERIFICATION);
+            return;
+        }
+        if (message.getHandshakeState() != HandshakeState.FINISHED) {
+            loge(TAG, "Handshake not finished after calling verify PIN. Instead got "
+                    + "state: " + message.getHandshakeState() + ".");
+            notifySecureChannelFailure(CHANNEL_ERROR_INVALID_STATE);
+            return;
+        }
+
+        Key localKey = message.getKey();
+        if (localKey == null) {
+            loge(TAG, "Unable to finish association, generated key is null.");
+            notifySecureChannelFailure(CHANNEL_ERROR_INVALID_ENCRYPTION_KEY);
+            return;
+        }
+        mState = message.getHandshakeState();
+        setEncryptionKey(localKey);
+        mPendingKey = localKey;
+        logd(TAG, "Pairing code successfully verified.");
+        sendUniqueIdToClient();
+    }
+
+    private void sendUniqueIdToClient() {
+        UUID uniqueId = mStorage.getUniqueId();
+        DeviceMessage deviceMessage = new DeviceMessage(/* recipient= */ null,
+                /* isMessageEncrypted= */ true, ByteUtils.uuidToBytes(uniqueId));
+        logd(TAG, "Sending car's device id of " + uniqueId + " to device.");
+        sendHandshakeMessage(ByteUtils.uuidToBytes(uniqueId), /* isEncrypted= */ true);
+    }
+
+    /** Listener that will be invoked to display verification code. */
+    interface ShowVerificationCodeListener {
+        /**
+         * Invoke when a verification need to be displayed during device association.
+         *
+         * @param code The verification code to show.
+         */
+        void showVerificationCode(@NonNull String code);
+    }
+}
diff --git a/connected-device-lib/src/com/android/car/connecteddevice/ble/BleDeviceMessageStream.java b/connected-device-lib/src/com/android/car/connecteddevice/ble/BleDeviceMessageStream.java
index f91693b..7ff3959 100644
--- a/connected-device-lib/src/com/android/car/connecteddevice/ble/BleDeviceMessageStream.java
+++ b/connected-device-lib/src/com/android/car/connecteddevice/ble/BleDeviceMessageStream.java
@@ -41,6 +41,7 @@
 import java.util.ArrayDeque;
 import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.UUID;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
@@ -51,9 +52,9 @@
 
     private static final String TAG = "BleDeviceMessageStream";
 
-    // Only version 2 of the messaging and version 1 of the security supported.
+    // Only version 2 of the messaging and version 2 of the security supported.
     private static final int MESSAGING_VERSION = 2;
-    private static final int SECURITY_VERSION = 1;
+    private static final int SECURITY_VERSION = 2;
 
     /*
      * During bandwidth testing, it was discovered that allowing the stream to send as fast as it
@@ -66,8 +67,10 @@
 
     private final ArrayDeque<BlePacket> mPacketQueue = new ArrayDeque<>();
 
-    private final HashMap<Integer, ByteArrayOutputStream> mPendingData =
-            new HashMap<>();
+    private final Map<Integer, ByteArrayOutputStream> mPendingData = new HashMap<>();
+
+    // messageId -> nextExpectedPacketNumber
+    private final Map<Integer, Integer> mPendingPacketNumber = new HashMap<>();
 
     private final MessageIdGenerator mMessageIdGenerator = new MessageIdGenerator();
 
@@ -91,22 +94,20 @@
 
     private MessageReceivedErrorListener mMessageReceivedErrorListener;
 
-    /*
-     * This initial value is 20 because BLE has a default write of 23 bytes. However, 3 bytes are
-     * subtracted due to bytes being reserved for the command type and attribute ID.
-     */
-    private int mMaxWriteSize = 20;
+    private int mMaxWriteSize;
 
     BleDeviceMessageStream(@NonNull BlePeripheralManager blePeripheralManager,
             @NonNull BluetoothDevice device,
             @NonNull BluetoothGattCharacteristic writeCharacteristic,
-            @NonNull BluetoothGattCharacteristic readCharacteristic) {
+            @NonNull BluetoothGattCharacteristic readCharacteristic,
+            int defaultMaxWriteSize) {
         mBlePeripheralManager = blePeripheralManager;
         mDevice = device;
         mWriteCharacteristic = writeCharacteristic;
         mReadCharacteristic = readCharacteristic;
         mBlePeripheralManager.addOnCharacteristicWriteListener(this::onCharacteristicWrite);
         mBlePeripheralManager.addOnCharacteristicReadListener(this::onCharacteristicRead);
+        mMaxWriteSize = defaultMaxWriteSize;
     }
 
     /**
@@ -132,7 +133,8 @@
      * @param operationType The {@link OperationType} of this message.
      */
     void writeMessage(@NonNull DeviceMessage deviceMessage, OperationType operationType) {
-        logd(TAG, "Writing message to device: " + mDevice.getAddress() + ".");
+        logd(TAG, "Writing message with " + deviceMessage.getMessage().length + " bytes to device: "
+                + mDevice.getAddress() + ".");
         BleDeviceMessage.Builder builder = BleDeviceMessage.newBuilder()
                 .setOperation(operationType)
                 .setIsPayloadEncrypted(deviceMessage.isMessageEncrypted())
@@ -174,7 +176,7 @@
                     + packet.getTotalPackets() + " for " + packet.getMessageId() + ".");
             mWriteCharacteristic.setValue(packet.toByteArray());
             mBlePeripheralManager.notifyCharacteristicChanged(mDevice, mWriteCharacteristic,
-                    /* confirm = */ false);
+                    /* confirm= */ false);
         }, mThrottleDelay.get());
     }
 
@@ -261,7 +263,7 @@
                 .build();
         mWriteCharacteristic.setValue(headunitVersion.toByteArray());
         mBlePeripheralManager.notifyCharacteristicChanged(device, mWriteCharacteristic,
-                /* confirm = */ false);
+                /* confirm= */ false);
         mIsVersionExchanged.set(true);
         logd(TAG, "Sent supported version to the phone.");
     }
@@ -273,6 +275,24 @@
         mThrottleDelay.set(THROTTLE_WAIT_MS);
 
         int messageId = packet.getMessageId();
+        int packetNumber = packet.getPacketNumber();
+        int expectedPacket = mPendingPacketNumber.getOrDefault(messageId, 1);
+        if (packetNumber == expectedPacket - 1) {
+            logw(TAG, "Received duplicate packet " + packet.getPacketNumber() + " for message "
+                    + messageId + ". Ignoring.");
+            return;
+        }
+        if (packetNumber != expectedPacket) {
+            loge(TAG, "Received unexpected packet " + packetNumber + " for message "
+                    + messageId + ".");
+            if (mMessageReceivedErrorListener != null) {
+                mMessageReceivedErrorListener.onMessageReceivedError(
+                        new IllegalStateException("Packet received out of order."));
+            }
+            return;
+        }
+        mPendingPacketNumber.put(messageId, packetNumber + 1);
+
         ByteArrayOutputStream currentPayloadStream =
                 mPendingData.getOrDefault(messageId, new ByteArrayOutputStream());
         mPendingData.putIfAbsent(messageId, currentPayloadStream);
@@ -325,6 +345,9 @@
 
     /** The maximum amount of bytes that can be written over BLE. */
     void setMaxWriteSize(int maxWriteSize) {
+        if (maxWriteSize <= 0) {
+            return;
+        }
         mMaxWriteSize = maxWriteSize;
     }
 
diff --git a/connected-device-lib/src/com/android/car/connecteddevice/ble/BlePeripheralManager.java b/connected-device-lib/src/com/android/car/connecteddevice/ble/BlePeripheralManager.java
index 6d50f63..51da3d7 100644
--- a/connected-device-lib/src/com/android/car/connecteddevice/ble/BlePeripheralManager.java
+++ b/connected-device-lib/src/com/android/car/connecteddevice/ble/BlePeripheralManager.java
@@ -242,11 +242,13 @@
             return;
         }
 
-        logd(TAG, "stopGattServer");
+        logd(TAG, "Stopping gatt server.");
         BluetoothGatt bluetoothGatt = mBluetoothGatt.getAndSet(null);
         if (bluetoothGatt != null) {
             gattServer.cancelConnection(bluetoothGatt.getDevice());
+            logd(TAG, "Disconnecting gatt.");
             bluetoothGatt.disconnect();
+            bluetoothGatt.close();
         }
         gattServer.clearServices();
         gattServer.close();
@@ -306,6 +308,11 @@
                     logd(TAG, "BLE Connection State Change: " + newState);
                     switch (newState) {
                         case BluetoothProfile.STATE_CONNECTED:
+                            BluetoothGattServer gattServer = mGattServer.get();
+                            if (gattServer == null) {
+                                return;
+                            }
+                            gattServer.connect(device, /* autoConnect= */ false);
                             for (Callback callback : mCallbacks) {
                                 callback.onRemoteDeviceConnected(device);
                             }
diff --git a/connected-device-lib/src/com/android/car/connecteddevice/ble/CarBleCentralManager.java b/connected-device-lib/src/com/android/car/connecteddevice/ble/CarBleCentralManager.java
index a9168a8..b95458d 100644
--- a/connected-device-lib/src/com/android/car/connecteddevice/ble/CarBleCentralManager.java
+++ b/connected-device-lib/src/com/android/car/connecteddevice/ble/CarBleCentralManager.java
@@ -110,7 +110,7 @@
     @Override
     public void start() {
         super.start();
-        mBleCentralManager.startScanning(/* filters = */ null, mScanSettings, mScanCallback);
+        mBleCentralManager.startScanning(/* filters= */ null, mScanSettings, mScanCallback);
     }
 
     @Override
@@ -199,7 +199,7 @@
     }
 
     private void startDeviceConnection(@NonNull BluetoothDevice device) {
-        BluetoothGatt gatt = device.connectGatt(mContext, /* autoConnect = */ false,
+        BluetoothGatt gatt = device.connectGatt(mContext, /* autoConnect= */ false,
                 mConnectionCallback, BluetoothDevice.TRANSPORT_LE);
         if (gatt == null) {
             return;
@@ -322,7 +322,7 @@
                 return;
             }
 
-            if (!gatt.setCharacteristicNotification(readCharacteristic, /* enable = */ true)) {
+            if (!gatt.setCharacteristicNotification(readCharacteristic, /* enable= */ true)) {
                 loge(TAG, "Set notifications to read characteristic failed.");
                 gatt.disconnect();
                 return;
diff --git a/connected-device-lib/src/com/android/car/connecteddevice/ble/CarBleManager.java b/connected-device-lib/src/com/android/car/connecteddevice/ble/CarBleManager.java
index 0b05906..2c32beb 100644
--- a/connected-device-lib/src/com/android/car/connecteddevice/ble/CarBleManager.java
+++ b/connected-device-lib/src/com/android/car/connecteddevice/ble/CarBleManager.java
@@ -111,13 +111,7 @@
         }
 
         logd(TAG, "Writing " + message.getMessage().length + " bytes to " + deviceId + ".");
-
-
-        if (message.isMessageEncrypted()) {
-            device.mSecureChannel.sendEncryptedMessage(message);
-        } else {
-            device.mSecureChannel.getStream().writeMessage(message);
-        }
+        device.mSecureChannel.sendClientMessage(message);
     }
 
     /**
diff --git a/connected-device-lib/src/com/android/car/connecteddevice/ble/CarBlePeripheralManager.java b/connected-device-lib/src/com/android/car/connecteddevice/ble/CarBlePeripheralManager.java
index 6f279dd..3fe8e3b 100644
--- a/connected-device-lib/src/com/android/car/connecteddevice/ble/CarBlePeripheralManager.java
+++ b/connected-device-lib/src/com/android/car/connecteddevice/ble/CarBlePeripheralManager.java
@@ -16,6 +16,7 @@
 
 package com.android.car.connecteddevice.ble;
 
+import static com.android.car.connecteddevice.ConnectedDeviceManager.DEVICE_ERROR_INVALID_HANDSHAKE;
 import static com.android.car.connecteddevice.ConnectedDeviceManager.DEVICE_ERROR_UNEXPECTED_DISCONNECTION;
 import static com.android.car.connecteddevice.util.SafeLog.logd;
 import static com.android.car.connecteddevice.util.SafeLog.loge;
@@ -31,7 +32,6 @@
 import android.bluetooth.le.AdvertiseCallback;
 import android.bluetooth.le.AdvertiseData;
 import android.bluetooth.le.AdvertiseSettings;
-import android.car.encryptionrunner.EncryptionRunnerFactory;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.ParcelUuid;
@@ -39,9 +39,12 @@
 import com.android.car.connecteddevice.AssociationCallback;
 import com.android.car.connecteddevice.model.AssociatedDevice;
 import com.android.car.connecteddevice.storage.ConnectedDeviceStorage;
+import com.android.car.connecteddevice.util.ByteUtils;
 import com.android.car.connecteddevice.util.EventLog;
 import com.android.internal.annotations.VisibleForTesting;
 
+import java.time.Duration;
+import java.util.Arrays;
 import java.util.UUID;
 import java.util.concurrent.Executors;
 import java.util.concurrent.ScheduledExecutorService;
@@ -66,6 +69,12 @@
     private static final UUID CLIENT_CHARACTERISTIC_CONFIG =
             UUID.fromString("00002902-0000-1000-8000-00805f9b34fb");
 
+    private static final int SALT_BYTES = 8;
+
+    private static final int TOTAL_AD_DATA_BYTES = 16;
+
+    private static final int TRUNCATED_BYTES = 3;
+
     private final BluetoothGattDescriptor mDescriptor =
             new BluetoothGattDescriptor(CLIENT_CHARACTERISTIC_CONFIG,
                     BluetoothGattDescriptor.PERMISSION_READ
@@ -78,14 +87,19 @@
 
     private final UUID mAssociationServiceUuid;
 
+    private final UUID mReconnectServiceUuid;
+
+    private final UUID mReconnectDataUuid;
+
     private final BluetoothGattCharacteristic mWriteCharacteristic;
 
     private final BluetoothGattCharacteristic mReadCharacteristic;
 
     private final Handler mTimeoutHandler;
 
-    // BLE default is 23, minus 3 bytes for ATT_PROTOCOL.
-    private int mWriteSize = 20;
+    private final Duration mMaxReconnectAdvertisementDuration;
+
+    private final int mDefaultMtuSize;
 
     private String mOriginalBluetoothName;
 
@@ -93,6 +107,10 @@
 
     private String mClientDeviceAddress;
 
+    private String mReconnectDeviceId;
+
+    private byte[] mReconnectChallenge;
+
     private AssociationCallback mAssociationCallback;
 
     private AdvertiseCallback mAdvertiseCallback;
@@ -100,19 +118,31 @@
     /**
      * Initialize a new instance of manager.
      *
-     * @param blePeripheralManager {@link BlePeripheralManager} for establishing connection.
-     * @param connectedDeviceStorage Shared {@link ConnectedDeviceStorage} for companion features.
-     * @param associationServiceUuid {@link UUID} of association service.
+     * @param blePeripheralManager    {@link BlePeripheralManager} for establishing connection.
+     * @param connectedDeviceStorage  Shared {@link ConnectedDeviceStorage} for companion features.
+     * @param associationServiceUuid  {@link UUID} of association service.
+     * @param reconnectServiceUuid    {@link UUID} of reconnect service.
+     * @param reconnectDataUuid       {@link UUID} key of reconnect advertisement data.
      * @param writeCharacteristicUuid {@link UUID} of characteristic the car will write to.
-     * @param readCharacteristicUuid {@link UUID} of characteristic the device will write to.
+     * @param readCharacteristicUuid  {@link UUID} of characteristic the device will write to.
+     * @param maxReconnectAdvertisementDuration Maximum duration to advertise for reconnect before
+     *                                          restarting.
+     * @param defaultMtuSize          Default MTU size for new channels.
      */
     public CarBlePeripheralManager(@NonNull BlePeripheralManager blePeripheralManager,
             @NonNull ConnectedDeviceStorage connectedDeviceStorage,
-            @NonNull UUID associationServiceUuid, @NonNull UUID writeCharacteristicUuid,
-            @NonNull UUID readCharacteristicUuid) {
+            @NonNull UUID associationServiceUuid,
+            @NonNull UUID reconnectServiceUuid,
+            @NonNull UUID reconnectDataUuid,
+            @NonNull UUID writeCharacteristicUuid,
+            @NonNull UUID readCharacteristicUuid,
+            @NonNull Duration maxReconnectAdvertisementDuration,
+            int defaultMtuSize) {
         super(connectedDeviceStorage);
         mBlePeripheralManager = blePeripheralManager;
         mAssociationServiceUuid = associationServiceUuid;
+        mReconnectServiceUuid = reconnectServiceUuid;
+        mReconnectDataUuid = reconnectDataUuid;
         mDescriptor.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);
         mWriteCharacteristic = new BluetoothGattCharacteristic(writeCharacteristicUuid,
                 BluetoothGattCharacteristic.PROPERTY_NOTIFY,
@@ -123,6 +153,8 @@
                 BluetoothGattCharacteristic.PERMISSION_WRITE);
         mReadCharacteristic.addDescriptor(mDescriptor);
         mTimeoutHandler = new Handler(Looper.getMainLooper());
+        mMaxReconnectAdvertisementDuration = maxReconnectAdvertisementDuration;
+        mDefaultMtuSize = defaultMtuSize;
     }
 
     @Override
@@ -171,10 +203,12 @@
         mAssociationCallback = null;
         mBlePeripheralManager.cleanup();
         mConnectedDevices.clear();
+        mReconnectDeviceId = null;
+        mReconnectChallenge = null;
     }
 
-    /** Attempt to connect to device with provided id within set timeout period. */
-    public void connectToDevice(@NonNull UUID deviceId, int timeoutSeconds) {
+    /** Attempt to connect to device with provided id. */
+    public void connectToDevice(@NonNull UUID deviceId) {
         for (BleDevice device : mConnectedDevices) {
             if (UUID.fromString(device.mDeviceId).equals(deviceId)) {
                 logd(TAG, "Already connected to device " + deviceId + ".");
@@ -185,21 +219,51 @@
 
         // Clear any previous session before starting a new one.
         reset();
-
+        mReconnectDeviceId = deviceId.toString();
         mAdvertiseCallback = new AdvertiseCallback() {
             @Override
             public void onStartSuccess(AdvertiseSettings settingsInEffect) {
                 super.onStartSuccess(settingsInEffect);
                 mTimeoutHandler.postDelayed(mTimeoutRunnable,
-                        TimeUnit.SECONDS.toMillis(timeoutSeconds));
-                logd(TAG, "Successfully started advertising for device " + deviceId
-                        + " for " + timeoutSeconds + " seconds.");
+                        mMaxReconnectAdvertisementDuration.toMillis());
+                logd(TAG, "Successfully started advertising for device " + deviceId + ".");
             }
         };
         mBlePeripheralManager.unregisterCallback(mAssociationPeripheralCallback);
         mBlePeripheralManager.registerCallback(mReconnectPeripheralCallback);
         mTimeoutHandler.removeCallbacks(mTimeoutRunnable);
-        startAdvertising(deviceId, mAdvertiseCallback, /* includeDeviceName = */ false);
+        byte[] advertiseData = createReconnectData(mReconnectDeviceId);
+        if (advertiseData == null) {
+            loge(TAG, "Unable to create advertisement data. Aborting reconnect.");
+            return;
+        }
+        startAdvertising(mReconnectServiceUuid, mAdvertiseCallback, /* includeDeviceName= */ false,
+                advertiseData, mReconnectDataUuid);
+    }
+
+    /**
+     * Create data for reconnection advertisement.
+     *
+     * <p></p><p>Process:</p>
+     * <ol>
+     * <li>Generate random {@value SALT_BYTES} byte salt and zero-pad to
+     * {@value TOTAL_AD_DATA_BYTES} bytes.
+     * <li>Hash with stored challenge secret and truncate to {@value TRUNCATED_BYTES} bytes.
+     * <li>Concatenate hashed {@value TRUNCATED_BYTES} bytes with salt and return.
+     * </ol>
+     */
+    @Nullable
+    private byte[] createReconnectData(String deviceId) {
+        byte[] salt = ByteUtils.randomBytes(SALT_BYTES);
+        byte[] zeroPadded = ByteUtils.concatByteArrays(salt,
+                new byte[TOTAL_AD_DATA_BYTES - SALT_BYTES]);
+        mReconnectChallenge = mStorage.hashWithChallengeSecret(deviceId, zeroPadded);
+        if (mReconnectChallenge == null) {
+            return null;
+        }
+        return ByteUtils.concatByteArrays(Arrays.copyOf(mReconnectChallenge, TRUNCATED_BYTES),
+                salt);
+
     }
 
     @Nullable
@@ -261,7 +325,8 @@
         if (mOriginalBluetoothName != null
                 && adapterName.equals(BluetoothAdapter.getDefaultAdapter().getName())) {
             startAdvertising(mAssociationServiceUuid, mAdvertiseCallback,
-                    /* includeDeviceName = */ true);
+                    /* includeDeviceName= */ true, /* serviceData= */ null,
+                    /* serviceDataUuid= */ null);
             return;
         }
 
@@ -278,17 +343,26 @@
     }
 
     private void startAdvertising(@NonNull UUID serviceUuid, @NonNull AdvertiseCallback callback,
-            boolean includeDeviceName) {
+            boolean includeDeviceName, @Nullable byte[] serviceData,
+            @Nullable UUID serviceDataUuid) {
         BluetoothGattService gattService = new BluetoothGattService(serviceUuid,
                 BluetoothGattService.SERVICE_TYPE_PRIMARY);
         gattService.addCharacteristic(mWriteCharacteristic);
         gattService.addCharacteristic(mReadCharacteristic);
 
-        AdvertiseData advertiseData = new AdvertiseData.Builder()
-                .setIncludeDeviceName(includeDeviceName)
-                .addServiceUuid(new ParcelUuid(serviceUuid))
-                .build();
-        mBlePeripheralManager.startAdvertising(gattService, advertiseData, callback);
+        AdvertiseData.Builder builder = new AdvertiseData.Builder()
+                .setIncludeDeviceName(includeDeviceName);
+        ParcelUuid uuid = new ParcelUuid(serviceUuid);
+        builder.addServiceUuid(uuid);
+        if (serviceData != null) {
+            ParcelUuid dataUuid = uuid;
+            if (serviceDataUuid != null) {
+                dataUuid = new ParcelUuid(serviceDataUuid);
+            }
+            builder.addServiceData(dataUuid, serviceData);
+        }
+
+        mBlePeripheralManager.startAdvertising(gattService, builder.build(), callback);
     }
 
     /** Notify that the user has accepted a pairing code or other out-of-band confirmation. */
@@ -299,7 +373,8 @@
             return;
         }
 
-        SecureBleChannel secureChannel = getConnectedDevice().mSecureChannel;
+        AssociationSecureChannel secureChannel =
+                (AssociationSecureChannel) getConnectedDevice().mSecureChannel;
         if (secureChannel == null) {
             disconnectWithError("Null SecureBleChannel found for the current connected device "
                     + "when out-of-band confirmation received.");
@@ -334,6 +409,9 @@
 
     private void disconnectWithError(@NonNull String errorMessage) {
         loge(TAG, errorMessage);
+        if (isAssociating()) {
+            mAssociationCallback.onAssociationError(DEVICE_ERROR_INVALID_HANDSHAKE);
+        }
         reset();
     }
 
@@ -374,23 +452,37 @@
         }
 
         BleDeviceMessageStream secureStream = new BleDeviceMessageStream(mBlePeripheralManager,
-                device, mWriteCharacteristic, mReadCharacteristic);
-        secureStream.setMaxWriteSize(mWriteSize);
-        SecureBleChannel secureChannel = new SecureBleChannel(secureStream, mStorage, isReconnect,
-                EncryptionRunnerFactory.newRunner());
+                device, mWriteCharacteristic, mReadCharacteristic,
+                mDefaultMtuSize - ATT_PROTOCOL_BYTES);
+        secureStream.setMessageReceivedErrorListener(
+                exception -> {
+                    disconnectWithError("Error occurred in stream: " + exception.getMessage());
+                });
+        SecureBleChannel secureChannel;
+        if (isReconnect) {
+            secureChannel = new ReconnectSecureChannel(secureStream, mStorage, mReconnectDeviceId,
+                    mReconnectChallenge);
+        } else {
+            secureChannel = new AssociationSecureChannel(secureStream, mStorage);
+        }
         secureChannel.registerCallback(mSecureChannelCallback);
-        BleDevice bleDevice = new BleDevice(device, /* gatt = */ null);
+        BleDevice bleDevice = new BleDevice(device, /* gatt= */ null);
         bleDevice.mSecureChannel = secureChannel;
         addConnectedDevice(bleDevice);
+        if (isReconnect) {
+            setDeviceId(mReconnectDeviceId);
+            mReconnectDeviceId = null;
+            mReconnectChallenge = null;
+        }
     }
 
     private void setMtuSize(int mtuSize) {
-        mWriteSize = mtuSize - ATT_PROTOCOL_BYTES;
         BleDevice connectedDevice = getConnectedDevice();
         if (connectedDevice != null
                 && connectedDevice.mSecureChannel != null
                 && connectedDevice.mSecureChannel.getStream() != null) {
-            connectedDevice.mSecureChannel.getStream().setMaxWriteSize(mWriteSize);
+            connectedDevice.mSecureChannel.getStream()
+                    .setMaxWriteSize(mtuSize - ATT_PROTOCOL_BYTES);
         }
     }
 
@@ -418,7 +510,7 @@
 
                 @Override
                 public void onRemoteDeviceDisconnected(BluetoothDevice device) {
-                    String deviceId = null;
+                    String deviceId = mReconnectDeviceId;
                     BleDevice connectedDevice = getConnectedDevice(device);
                     // Reset before invoking callbacks to avoid a race condition with reconnect
                     // logic.
@@ -457,19 +549,20 @@
                 @Override
                 public void onRemoteDeviceConnected(BluetoothDevice device) {
                     resetBluetoothAdapterName();
-                    addConnectedDevice(device, /* isReconnect = */ false);
+                    addConnectedDevice(device, /* isReconnect= */ false);
                     BleDevice connectedDevice = getConnectedDevice();
                     if (connectedDevice == null || connectedDevice.mSecureChannel == null) {
                         return;
                     }
-                    connectedDevice.mSecureChannel.setShowVerificationCodeListener(
-                            code -> {
-                                if (!isAssociating()) {
-                                    loge(TAG, "No valid callback for association.");
-                                    return;
-                                }
-                                mAssociationCallback.onVerificationCodeAvailable(code);
-                            });
+                    ((AssociationSecureChannel) connectedDevice.mSecureChannel)
+                            .setShowVerificationCodeListener(
+                                    code -> {
+                                        if (!isAssociating()) {
+                                            loge(TAG, "No valid callback for association.");
+                                            return;
+                                        }
+                                        mAssociationCallback.onVerificationCodeAvailable(code);
+                                    });
                 }
 
                 @Override
@@ -510,7 +603,7 @@
                                 + "association of that device for current user.");
                         mStorage.addAssociatedDeviceForActiveUser(
                                 new AssociatedDevice(deviceId, mClientDeviceAddress,
-                                        mClientDeviceName, /* isConnectionEnabled = */ true));
+                                        mClientDeviceName, /* isConnectionEnabled= */ true));
                         if (mAssociationCallback != null) {
                             mAssociationCallback.onAssociationCompleted(deviceId);
                             mAssociationCallback = null;
@@ -532,8 +625,9 @@
 
                     if (isAssociating()) {
                         mAssociationCallback.onAssociationError(error);
-                        disconnectWithError("Error while establishing secure connection.");
                     }
+
+                    disconnectWithError("Error while establishing secure connection.");
                 }
 
                 @Override
@@ -548,7 +642,7 @@
                             + " with " + deviceMessage.getMessage().length + " bytes in its "
                             + "payload. Notifying " + mCallbacks.size() + " callbacks.");
                     mCallbacks.invoke(
-                            callback ->callback.onMessageReceived(connectedDevice.mDeviceId,
+                            callback -> callback.onMessageReceived(connectedDevice.mDeviceId,
                                     deviceMessage));
                 }
 
@@ -556,6 +650,7 @@
                 public void onMessageReceivedError(Exception exception) {
                     // TODO(b/143879960) Extend the message error from here to continue up the
                     // chain.
+                    disconnectWithError("Error while receiving message.");
                 }
 
                 @Override
@@ -567,8 +662,9 @@
     private final Runnable mTimeoutRunnable = new Runnable() {
         @Override
         public void run() {
-            logd(TAG, "Timeout period expired without a connection. Stopping advertisement.");
+            logd(TAG, "Timeout period expired without a connection. Restarting advertisement.");
             mBlePeripheralManager.stopAdvertising(mAdvertiseCallback);
+            connectToDevice(UUID.fromString(mReconnectDeviceId));
         }
     };
 }
diff --git a/connected-device-lib/src/com/android/car/connecteddevice/ble/ReconnectSecureChannel.java b/connected-device-lib/src/com/android/car/connecteddevice/ble/ReconnectSecureChannel.java
new file mode 100644
index 0000000..56eff5c
--- /dev/null
+++ b/connected-device-lib/src/com/android/car/connecteddevice/ble/ReconnectSecureChannel.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.car.connecteddevice.ble;
+
+import static com.android.car.connecteddevice.util.SafeLog.logd;
+import static com.android.car.connecteddevice.util.SafeLog.loge;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.car.encryptionrunner.EncryptionRunner;
+import android.car.encryptionrunner.EncryptionRunnerFactory;
+import android.car.encryptionrunner.HandshakeException;
+import android.car.encryptionrunner.HandshakeMessage;
+import android.car.encryptionrunner.HandshakeMessage.HandshakeState;
+import android.car.encryptionrunner.Key;
+
+import com.android.car.connecteddevice.storage.ConnectedDeviceStorage;
+import com.android.car.connecteddevice.util.ByteUtils;
+
+import java.util.Arrays;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * A secure channel established with the reconnection flow.
+ */
+class ReconnectSecureChannel extends SecureBleChannel {
+
+    private static final String TAG = "ReconnectSecureChannel";
+
+    private final ConnectedDeviceStorage mStorage;
+
+    private final String mDeviceId;
+
+    private final byte[] mExpectedChallengeResponse;
+
+    @HandshakeState
+    private int mState = HandshakeState.UNKNOWN;
+
+    private AtomicBoolean mHasVerifiedDevice = new AtomicBoolean(false);
+
+    /**
+     * Create a new secure reconnection channel.
+     *
+     * @param stream The {@link BleDeviceMessageStream} for communication with the device.
+     * @param storage {@link ConnectedDeviceStorage} for secure storage.
+     * @param deviceId Id of the device being reconnected.
+     * @param expectedChallengeResponse Expected response to challenge issued in reconnect.
+     */
+    ReconnectSecureChannel(@NonNull BleDeviceMessageStream stream,
+            @NonNull ConnectedDeviceStorage storage, @NonNull String deviceId,
+            @NonNull byte[] expectedChallengeResponse) {
+        super(stream, newReconnectRunner());
+        mStorage = storage;
+        mDeviceId = deviceId;
+        mExpectedChallengeResponse = expectedChallengeResponse;
+    }
+
+    private static EncryptionRunner newReconnectRunner() {
+        EncryptionRunner encryptionRunner = EncryptionRunnerFactory.newRunner();
+        encryptionRunner.setIsReconnect(true);
+        return encryptionRunner;
+    }
+
+    @Override
+    void processHandshake(byte[] message) throws HandshakeException {
+        switch (mState) {
+            case HandshakeState.UNKNOWN:
+                if (!mHasVerifiedDevice.get()) {
+                    processHandshakeDeviceVerification(message);
+                } else {
+                    processHandshakeInitialization(message);
+                }
+                break;
+            case HandshakeState.IN_PROGRESS:
+                processHandshakeInProgress(message);
+                break;
+            case HandshakeState.RESUMING_SESSION:
+                processHandshakeResumingSession(message);
+                break;
+            default:
+                loge(TAG, "Encountered unexpected handshake state: " + mState + ".");
+                notifySecureChannelFailure(CHANNEL_ERROR_INVALID_STATE);
+        }
+    }
+
+    private void processHandshakeDeviceVerification(byte[] message) {
+        byte[] challengeResponse = Arrays.copyOf(message,
+                mExpectedChallengeResponse.length);
+        byte[] deviceChallenge = Arrays.copyOfRange(message,
+                mExpectedChallengeResponse.length, message.length);
+        if (!Arrays.equals(mExpectedChallengeResponse, challengeResponse)) {
+            notifySecureChannelFailure(CHANNEL_ERROR_INVALID_ENCRYPTION_KEY);
+            return;
+        }
+        logd(TAG, "Responding to challenge " + ByteUtils.byteArrayToHexString(deviceChallenge)
+                + ".");
+        byte[] deviceChallengeResponse = mStorage.hashWithChallengeSecret(mDeviceId,
+                deviceChallenge);
+        if (deviceChallengeResponse == null) {
+            notifySecureChannelFailure(CHANNEL_ERROR_STORAGE_ERROR);
+        }
+        sendHandshakeMessage(deviceChallengeResponse, /* isEncrypted= */ false);
+        mHasVerifiedDevice.set(true);
+    }
+
+    private void processHandshakeInitialization(byte[] message) throws HandshakeException {
+        logd(TAG, "Responding to handshake init request.");
+        HandshakeMessage handshakeMessage = getEncryptionRunner().respondToInitRequest(message);
+        mState = handshakeMessage.getHandshakeState();
+        sendHandshakeMessage(handshakeMessage.getNextMessage(), /* isEncrypted= */ false);
+    }
+
+    private void processHandshakeInProgress(@NonNull byte[] message) throws HandshakeException {
+        logd(TAG, "Continuing handshake.");
+        HandshakeMessage handshakeMessage = getEncryptionRunner().continueHandshake(message);
+        mState = handshakeMessage.getHandshakeState();
+    }
+
+    private void processHandshakeResumingSession(@NonNull byte[] message)
+            throws HandshakeException {
+        logd(TAG, "Start reconnection authentication.");
+
+        byte[] previousKey = mStorage.getEncryptionKey(mDeviceId);
+        if (previousKey == null) {
+            loge(TAG, "Unable to resume session, previous key is null.");
+            notifySecureChannelFailure(CHANNEL_ERROR_INVALID_ENCRYPTION_KEY);
+            return;
+        }
+
+        HandshakeMessage handshakeMessage = getEncryptionRunner().authenticateReconnection(message,
+                previousKey);
+        mState = handshakeMessage.getHandshakeState();
+        if (mState != HandshakeState.FINISHED) {
+            loge(TAG, "Unable to resume session, unexpected next handshake state: " + mState + ".");
+            notifySecureChannelFailure(CHANNEL_ERROR_INVALID_STATE);
+            return;
+        }
+
+        Key newKey = handshakeMessage.getKey();
+        if (newKey == null) {
+            loge(TAG, "Unable to resume session, new key is null.");
+            notifySecureChannelFailure(CHANNEL_ERROR_INVALID_ENCRYPTION_KEY);
+            return;
+        }
+
+        logd(TAG, "Saved new key for reconnection.");
+        mStorage.saveEncryptionKey(mDeviceId, newKey.asBytes());
+        setEncryptionKey(newKey);
+        sendServerAuthToClient(handshakeMessage.getNextMessage());
+        notifyCallback(Callback::onSecureChannelEstablished);
+    }
+
+    private void sendServerAuthToClient(@Nullable byte[] message) {
+        if (message == null) {
+            loge(TAG, "Unable to send server authentication message to client, message is null.");
+            notifySecureChannelFailure(CHANNEL_ERROR_INVALID_MSG);
+            return;
+        }
+
+        sendHandshakeMessage(message, /* isEncrypted= */ false);
+    }
+}
diff --git a/connected-device-lib/src/com/android/car/connecteddevice/ble/SecureBleChannel.java b/connected-device-lib/src/com/android/car/connecteddevice/ble/SecureBleChannel.java
index a821186..858d7c8 100644
--- a/connected-device-lib/src/com/android/car/connecteddevice/ble/SecureBleChannel.java
+++ b/connected-device-lib/src/com/android/car/connecteddevice/ble/SecureBleChannel.java
@@ -23,21 +23,15 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.car.encryptionrunner.EncryptionRunner;
-import android.car.encryptionrunner.EncryptionRunnerFactory;
 import android.car.encryptionrunner.HandshakeException;
-import android.car.encryptionrunner.HandshakeMessage;
-import android.car.encryptionrunner.HandshakeMessage.HandshakeState;
 import android.car.encryptionrunner.Key;
 
 import com.android.car.connecteddevice.BleStreamProtos.BleOperationProto.OperationType;
-import com.android.car.connecteddevice.storage.ConnectedDeviceStorage;
-import com.android.car.connecteddevice.util.ByteUtils;
 import com.android.internal.annotations.VisibleForTesting;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.security.SignatureException;
-import java.util.UUID;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.function.Consumer;
 
@@ -45,7 +39,9 @@
  * Establishes a secure channel with {@link EncryptionRunner} over {@link BleDeviceMessageStream} as
  * server side, sends and receives messages securely after the secure channel has been established.
  */
-class SecureBleChannel {
+abstract class SecureBleChannel {
+
+    private static final String TAG = "SecureBleChannel";
 
     @Retention(RetentionPolicy.SOURCE)
     @IntDef(prefix = { "CHANNEL_ERROR" },
@@ -71,211 +67,67 @@
     static final int CHANNEL_ERROR_INVALID_VERIFICATION = 3;
     /** Encountered an unexpected handshake state. */
     static final int CHANNEL_ERROR_INVALID_STATE = 4;
-    /** Failed to get a valid previous/new encryption key.*/
+    /** Failed to get a valid previous/new encryption key. */
     static final int CHANNEL_ERROR_INVALID_ENCRYPTION_KEY = 5;
-    /** Failed to save the encryption key*/
+    /** Failed to save or retrieve security keys. */
     static final int CHANNEL_ERROR_STORAGE_ERROR = 6;
 
-    @VisibleForTesting
-    static final byte[] CONFIRMATION_SIGNAL = "True".getBytes();
-
-    private static final String TAG = "SecureBleChannel";
 
     private final BleDeviceMessageStream mStream;
 
-    private final ConnectedDeviceStorage mStorage;
-
-    private final boolean mIsReconnect;
-
     private final EncryptionRunner mEncryptionRunner;
 
     private final AtomicReference<Key> mEncryptionKey = new AtomicReference<>();
 
-    private @HandshakeState int mState = HandshakeState.UNKNOWN;
-
-    private String mDeviceId;
-
     private Callback mCallback;
 
-    private ShowVerificationCodeListener mShowVerificationCodeListener;
-
     SecureBleChannel(@NonNull BleDeviceMessageStream stream,
-            @NonNull ConnectedDeviceStorage storage) {
-        this(stream, storage, /* isReconnect = */ true, EncryptionRunnerFactory.newRunner());
-    }
-
-    SecureBleChannel(@NonNull BleDeviceMessageStream stream,
-            @NonNull ConnectedDeviceStorage storage, boolean isReconnect,
             @NonNull EncryptionRunner encryptionRunner) {
         mStream = stream;
-        mStorage = storage;
-        mIsReconnect = isReconnect;
         mEncryptionRunner = encryptionRunner;
-        mEncryptionRunner.setIsReconnect(isReconnect);
-        mStream.setMessageReceivedListener(mStreamListener);
+        mStream.setMessageReceivedListener(this::onMessageReceived);
     }
 
-    private void processHandshake(@NonNull byte[] message) throws HandshakeException {
-        switch (mState) {
-            case HandshakeState.UNKNOWN:
-                processHandshakeUnknown(message);
-                break;
-            case HandshakeState.IN_PROGRESS:
-                processHandshakeInProgress(message);
-                break;
-            case HandshakeState.RESUMING_SESSION:
-                processHandshakeResumingSession(message);
-                break;
-            default:
-                loge(TAG, "Encountered unexpected handshake state: " + mState + ". Received "
-                        + "message: " + ByteUtils.byteArrayToHexString(message) + ".");
-                notifySecureChannelFailure(CHANNEL_ERROR_INVALID_STATE);
-        }
-    }
+    /** Logic for processing a handshake message from device. */
+    abstract void processHandshake(byte[] message) throws HandshakeException;
 
-    private void processHandshakeUnknown(@NonNull byte[] message) throws HandshakeException {
-        if (mDeviceId != null) {
-            logd(TAG, "Responding to handshake init request.");
-            HandshakeMessage handshakeMessage = mEncryptionRunner.respondToInitRequest(message);
-            mState = handshakeMessage.getHandshakeState();
-            sendHandshakeMessage(handshakeMessage.getNextMessage());
-            return;
-        }
-        UUID deviceId = ByteUtils.bytesToUUID(message);
-        if (deviceId == null) {
-            loge(TAG, "Received invalid device id. Ignoring.");
-            return;
-        }
-        mDeviceId = deviceId.toString();
-        if (mIsReconnect && !hasEncryptionKey(mDeviceId)) {
-            loge(TAG, "Attempted to reconnect device but no key found. Aborting secure channel.");
-            notifySecureChannelFailure(CHANNEL_ERROR_INVALID_DEVICE_ID);
-            return;
-        }
-        notifyCallback(callback -> callback.onDeviceIdReceived(mDeviceId));
-        sendUniqueIdToClient();
-    }
-
-    private void processHandshakeInProgress(@NonNull byte[] message) throws HandshakeException {
-        logd(TAG, "Continuing handshake.");
-        HandshakeMessage handshakeMessage = mEncryptionRunner.continueHandshake(message);
-        mState = handshakeMessage.getHandshakeState();
-
-        boolean isValidStateForAssociation = !mIsReconnect
-                && mState == HandshakeState.VERIFICATION_NEEDED;
-        boolean isValidStateForReconnect = mIsReconnect
-                && mState == HandshakeState.RESUMING_SESSION;
-        if (!isValidStateForAssociation && !isValidStateForReconnect) {
-            loge(TAG, "processHandshakeInProgress: Encountered unexpected handshake state: "
-                    + mState + ".");
-            notifySecureChannelFailure(CHANNEL_ERROR_INVALID_STATE);
-            return;
-        }
-
-        if (!isValidStateForAssociation) {
-            return;
-        }
-
-        String code = handshakeMessage.getVerificationCode();
-        if (code == null) {
-            loge(TAG, "Unable to get verification code.");
-            notifySecureChannelFailure(CHANNEL_ERROR_INVALID_VERIFICATION);
-            return;
-        }
-
-        if (mShowVerificationCodeListener != null) {
-            logd(TAG, "Showing pairing code: " + code);
-            mShowVerificationCodeListener.showVerificationCode(code);
-        }
-    }
-
-    private void processHandshakeResumingSession(@NonNull byte[] message)
-            throws HandshakeException {
-        logd(TAG, "Start reconnection authentication.");
-        if (mDeviceId == null) {
-            loge(TAG, "processHandshakeResumingSession: Unable to resume session, device id is "
-                    + "null.");
-            notifySecureChannelFailure(CHANNEL_ERROR_INVALID_DEVICE_ID);
-            return;
-        }
-
-        byte[] previousKey = mStorage.getEncryptionKey(mDeviceId);
-        if (previousKey == null) {
-            loge(TAG, "Unable to resume session, previous key is null.");
-            notifySecureChannelFailure(CHANNEL_ERROR_INVALID_ENCRYPTION_KEY);
-            return;
-        }
-
-        HandshakeMessage handshakeMessage = mEncryptionRunner.authenticateReconnection(message,
-                previousKey);
-        mState = handshakeMessage.getHandshakeState();
-        if (mState != HandshakeState.FINISHED) {
-            loge(TAG, "Unable to resume session, unexpected next handshake state: " + mState + ".");
-            notifySecureChannelFailure(CHANNEL_ERROR_INVALID_STATE);
-            return;
-        }
-
-        Key newKey = handshakeMessage.getKey();
-        if (newKey == null) {
-            loge(TAG, "Unable to resume session, new key is null.");
-            notifySecureChannelFailure(CHANNEL_ERROR_INVALID_ENCRYPTION_KEY);
-            return;
-        }
-
-        logd(TAG, "Saved new key for reconnection.");
-        mStorage.saveEncryptionKey(mDeviceId, newKey.asBytes());
-        mEncryptionKey.set(newKey);
-        sendServerAuthToClient(handshakeMessage.getNextMessage());
-        notifyCallback(callback -> callback.onSecureChannelEstablished());
-    }
-
-    private void sendUniqueIdToClient() {
-        UUID uniqueId = mStorage.getUniqueId();
-        DeviceMessage deviceMessage = new DeviceMessage(/* recipient = */ null,
-                /* isMessageEncrypted = */ false, ByteUtils.uuidToBytes(uniqueId));
-        logd(TAG, "Sending car's device id of " + uniqueId + " to device.");
-        mStream.writeMessage(deviceMessage, OperationType.ENCRYPTION_HANDSHAKE);
-    }
-
-    private boolean hasEncryptionKey(@NonNull String id) {
-        return mStorage.getEncryptionKey(id) != null;
-    }
-
-    private void sendHandshakeMessage(@Nullable byte[] message) {
+    void sendHandshakeMessage(@Nullable byte[] message, boolean isEncrypted) {
         if (message == null) {
             loge(TAG, "Unable to send next handshake message, message is null.");
             notifySecureChannelFailure(CHANNEL_ERROR_INVALID_MSG);
             return;
         }
 
-        logd(TAG, "Send handshake message: " + ByteUtils.byteArrayToHexString(message) + ".");
-        DeviceMessage deviceMessage = new DeviceMessage(/* recipient = */ null,
-                /* isMessageEncrypted = */ false, message);
+        logd(TAG, "Sending handshake message.");
+        DeviceMessage deviceMessage = new DeviceMessage(/* recipient= */ null,
+                isEncrypted, message);
+        if (deviceMessage.isMessageEncrypted()) {
+            encryptMessage(deviceMessage);
+        }
         mStream.writeMessage(deviceMessage, OperationType.ENCRYPTION_HANDSHAKE);
     }
 
-    private void sendServerAuthToClient(@Nullable byte[] message) {
-        if (message == null) {
-            loge(TAG, "Unable to send server authentication message to client, message is null.");
-            notifySecureChannelFailure(CHANNEL_ERROR_INVALID_MSG);
-            return;
-        }
-        DeviceMessage deviceMessage = new DeviceMessage(/* recipient = */ null,
-                /* isMessageEncrypted = */ false, message);
-        mStream.writeMessage(deviceMessage, OperationType.ENCRYPTION_HANDSHAKE);
+    /** Set the encryption key that secures this channel. */
+    void setEncryptionKey(@Nullable Key encryptionKey) {
+        mEncryptionKey.set(encryptionKey);
     }
 
     /**
-     * Send an encrypted message.
-     * <p>Note: This should be called only after the secure channel has been established.</p>
+     * Send a client message.
+     * <p>Note: This should be called with an encrypted message only after the secure channel has
+     * been established.</p>
      *
-     * @param deviceMessage The {@link DeviceMessage} to encrypt and send.
+     * @param deviceMessage The {@link DeviceMessage} to send.
      */
-    void sendEncryptedMessage(@NonNull DeviceMessage deviceMessage) throws IllegalStateException {
-        if (!deviceMessage.isMessageEncrypted()) {
-            loge(TAG, "Encryption not required for this message " + deviceMessage + ".");
-            return;
+    void sendClientMessage(@NonNull DeviceMessage deviceMessage)
+            throws IllegalStateException {
+        if (deviceMessage.isMessageEncrypted()) {
+            encryptMessage(deviceMessage);
         }
+        mStream.writeMessage(deviceMessage, OperationType.CLIENT_MESSAGE);
+    }
+
+    private void encryptMessage(@NonNull DeviceMessage deviceMessage) {
         Key key = mEncryptionKey.get();
         if (key == null) {
             throw new IllegalStateException("Secure channel has not been established.");
@@ -283,50 +135,6 @@
 
         byte[] encryptedMessage = key.encryptData(deviceMessage.getMessage());
         deviceMessage.setMessage(encryptedMessage);
-        mStream.writeMessage(deviceMessage, OperationType.CLIENT_MESSAGE);
-    }
-
-    /**
-     * Called by the client to notify that the user has accepted a pairing code or any out-of-band
-     * confirmation, and send confirmation signals to remote bluetooth device.
-     */
-    void notifyOutOfBandAccepted() {
-        HandshakeMessage message;
-        try {
-            message = mEncryptionRunner.verifyPin();
-        } catch (HandshakeException e) {
-            loge(TAG, "Error during PIN verification", e);
-            notifySecureChannelFailure(CHANNEL_ERROR_INVALID_VERIFICATION);
-            return;
-        }
-        if (message.getHandshakeState() != HandshakeState.FINISHED) {
-            loge(TAG, "Handshake not finished after calling verify PIN. Instead got "
-                    + "state: " + message.getHandshakeState() + ".");
-            notifySecureChannelFailure(CHANNEL_ERROR_INVALID_STATE);
-            return;
-        }
-
-        Key localKey = message.getKey();
-        if (localKey == null) {
-            loge(TAG, "Unable to finish association, generated key is null.");
-            notifySecureChannelFailure(CHANNEL_ERROR_INVALID_ENCRYPTION_KEY);
-            return;
-        }
-
-        mState = message.getHandshakeState();
-        mStorage.saveEncryptionKey(mDeviceId, localKey.asBytes());
-        mEncryptionKey.set(localKey);
-        if (mDeviceId == null) {
-            loge(TAG, "Unable to finish association, device id is null.");
-            notifySecureChannelFailure(CHANNEL_ERROR_INVALID_DEVICE_ID);
-            return;
-        }
-        logd(TAG, "Pairing code successfully verified and encryption key saved. Sending "
-                + "confirmation to device.");
-        notifyCallback(Callback::onSecureChannelEstablished);
-        DeviceMessage deviceMessage = new DeviceMessage(/* recipient = */ null,
-                /* isMessageEncrypted = */ false, CONFIRMATION_SIGNAL);
-        mStream.writeMessage(deviceMessage, OperationType.ENCRYPTION_HANDSHAKE);
     }
 
     /** Get the BLE stream backing this channel. */
@@ -335,17 +143,6 @@
         return mStream;
     }
 
-    /**Set the listener that notifies to show verification code. {@code null} to clear.*/
-    void setShowVerificationCodeListener(@Nullable ShowVerificationCodeListener listener) {
-        mShowVerificationCodeListener = listener;
-    }
-
-    @VisibleForTesting
-    @Nullable
-    ShowVerificationCodeListener getShowVerificationCodeListener() {
-        return mShowVerificationCodeListener;
-    }
-
     /** Register a callback that notifies secure channel events. */
     void registerCallback(Callback callback) {
         mCallback = callback;
@@ -364,64 +161,92 @@
         return mCallback;
     }
 
-    private void notifyCallback(Consumer<Callback> notification) {
+    void notifyCallback(@NonNull Consumer<Callback> notification) {
         if (mCallback != null) {
             notification.accept(mCallback);
         }
     }
 
-    private void notifySecureChannelFailure(@ChannelError int error) {
+    /** Notify callbacks that an error has occurred. */
+    void notifySecureChannelFailure(@ChannelError int error) {
         loge(TAG, "Secure channel error: " + error);
         notifyCallback(callback -> callback.onEstablishSecureChannelFailure(error));
     }
 
-    private final BleDeviceMessageStream.MessageReceivedListener mStreamListener =
-            new BleDeviceMessageStream.MessageReceivedListener() {
-                @Override
-                public void onMessageReceived(DeviceMessage deviceMessage,
-                        OperationType operationType) {
-                    byte[] message = deviceMessage.getMessage();
-                    switch(operationType) {
-                        case ENCRYPTION_HANDSHAKE:
-                            logd(TAG, "Message received and handed off to handshake.");
-                            try {
-                                processHandshake(message);
-                            } catch (HandshakeException e) {
-                                loge(TAG, "Handshake failed.", e);
-                                notifyCallback(callback -> callback.onEstablishSecureChannelFailure(
-                                        CHANNEL_ERROR_INVALID_HANDSHAKE));
-                            }
-                            break;
-                        case CLIENT_MESSAGE:
-                            logd(TAG, "Received client message.");
-                            if (!deviceMessage.isMessageEncrypted()) {
-                                notifyCallback(callback -> callback.onMessageReceived(
-                                        deviceMessage));
-                                return;
-                            }
-                            Key key = mEncryptionKey.get();
-                            if (key == null) {
-                                loge(TAG, "Received encrypted message before secure channel has "
-                                        + "been established.");
-                                notifyCallback(callback -> callback.onMessageReceivedError(null));
-                                return;
-                            }
-                            try {
-                                byte[] decryptedPayload =
-                                        key.decryptData(deviceMessage.getMessage());
-                                deviceMessage.setMessage(decryptedPayload);
-                                notifyCallback(
-                                        callback -> callback.onMessageReceived(deviceMessage));
-                            } catch (SignatureException e) {
-                                loge(TAG, "Could not decrypt client credentials.", e);
-                                notifyCallback(callback -> callback.onMessageReceivedError(e));
-                            }
-                            break;
-                        default:
-                            loge(TAG, "Received unexpected operation type: " + operationType + ".");
-                    }
+    /** Return the {@link EncryptionRunner} for this channel. */
+    @NonNull
+    EncryptionRunner getEncryptionRunner() {
+        return mEncryptionRunner;
+    }
+
+    /**
+     * Process the inner message and replace with decrypted value if necessary. If an error occurs
+     * the inner message will be replaced with {@code null} and call
+     * {@link Callback#onMessageReceivedError(Exception)} on the registered callback.
+     *
+     * @param deviceMessage The message to process.
+     * @return {@code true} if message was successfully processed. {@code false} if an error
+     * occurred.
+     */
+    @VisibleForTesting
+    boolean processMessage(@NonNull DeviceMessage deviceMessage) {
+        if (!deviceMessage.isMessageEncrypted()) {
+            logd(TAG, "Message was not decrypted. No further action necessary.");
+            return true;
+        }
+        Key key = mEncryptionKey.get();
+        if (key == null) {
+            loge(TAG, "Received encrypted message before secure channel has "
+                    + "been established.");
+            notifyCallback(callback -> callback.onMessageReceivedError(null));
+            deviceMessage.setMessage(null);
+            return false;
+        }
+        try {
+            byte[] decryptedMessage = key.decryptData(deviceMessage.getMessage());
+            deviceMessage.setMessage(decryptedMessage);
+            logd(TAG, "Decrypted secure message.");
+            return true;
+        } catch (SignatureException e) {
+            loge(TAG, "Could not decrypt client credentials.", e);
+            notifyCallback(callback -> callback.onMessageReceivedError(e));
+            deviceMessage.setMessage(null);
+
+            return false;
+        }
+    }
+
+    @VisibleForTesting
+    void onMessageReceived(@NonNull DeviceMessage deviceMessage, OperationType operationType) {
+        boolean success = processMessage(deviceMessage);
+        switch(operationType) {
+            case ENCRYPTION_HANDSHAKE:
+                if (!success) {
+                    notifyCallback(callback -> callback.onEstablishSecureChannelFailure(
+                            CHANNEL_ERROR_INVALID_HANDSHAKE));
+                    break;
                 }
-            };
+                logd(TAG, "Received handshake message.");
+                try {
+                    processHandshake(deviceMessage.getMessage());
+                } catch (HandshakeException e) {
+                    loge(TAG, "Handshake failed.", e);
+                    notifyCallback(callback -> callback.onEstablishSecureChannelFailure(
+                            CHANNEL_ERROR_INVALID_HANDSHAKE));
+                }
+                break;
+            case CLIENT_MESSAGE:
+                if (!success || deviceMessage.getMessage() == null) {
+                    break;
+                }
+                logd(TAG, "Received client message.");
+                notifyCallback(
+                        callback -> callback.onMessageReceived(deviceMessage));
+                break;
+            default:
+                loge(TAG, "Received unexpected operation type: " + operationType + ".");
+        }
+    }
 
     /**
      * Callbacks that will be invoked during establishing secure channel, sending and receiving
@@ -431,7 +256,7 @@
         /**
          * Invoked when secure channel has been established successfully.
          */
-        void onSecureChannelEstablished();
+        default void onSecureChannelEstablished() { }
 
         /**
          * Invoked when a {@link ChannelError} has been encountered in attempting to establish
@@ -439,39 +264,27 @@
          *
          * @param error The failure indication.
          */
-        void onEstablishSecureChannelFailure(@SecureBleChannel.ChannelError int error);
+        default void onEstablishSecureChannelFailure(@SecureBleChannel.ChannelError int error) { }
 
         /**
          * Invoked when a complete message is received securely from the client and decrypted.
          *
          * @param deviceMessage The {@link DeviceMessage} with decrypted message.
          */
-        void onMessageReceived(@NonNull DeviceMessage deviceMessage);
+        default void onMessageReceived(@NonNull DeviceMessage deviceMessage) { }
 
         /**
          * Invoked when there was an error during a processing or decrypting of a client message.
          *
          * @param exception The error.
          */
-        void onMessageReceivedError(@Nullable Exception exception);
+        default void onMessageReceivedError(@Nullable Exception exception) { }
 
         /**
          * Invoked when the device id was received from the client.
          *
          * @param deviceId The unique device id of client.
          */
-        void onDeviceIdReceived(@NonNull String deviceId);
-    }
-
-    /**
-     * Listener that will be invoked to display verification code.
-     */
-    interface ShowVerificationCodeListener {
-        /**
-         * Invoke when a verification need to be displayed during device association.
-         *
-         * @param code The verification code to show.
-         */
-        void showVerificationCode(@NonNull String code);
+        default void onDeviceIdReceived(@NonNull String deviceId) { }
     }
 }
diff --git a/connected-device-lib/src/com/android/car/connecteddevice/storage/AssociatedDeviceChallengeSecretEntity.java b/connected-device-lib/src/com/android/car/connecteddevice/storage/AssociatedDeviceChallengeSecretEntity.java
new file mode 100644
index 0000000..ab802e6
--- /dev/null
+++ b/connected-device-lib/src/com/android/car/connecteddevice/storage/AssociatedDeviceChallengeSecretEntity.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.car.connecteddevice.storage;
+
+import androidx.annotation.NonNull;
+import androidx.room.Entity;
+import androidx.room.PrimaryKey;
+
+/**
+ * Table entity representing an challenge key for an associated device reconnection advertisement.
+ */
+@Entity(tableName = "associated_devices_challenge_secrets")
+public class AssociatedDeviceChallengeSecretEntity {
+
+    /** Id of the device. */
+    @PrimaryKey
+    @NonNull
+    public String id;
+
+    /** Encrypted challenge key. */
+    @NonNull
+    public String encryptedChallengeSecret;
+
+    public AssociatedDeviceChallengeSecretEntity(String id, String encryptedChallengeSecret) {
+        this.id = id;
+        this.encryptedChallengeSecret = encryptedChallengeSecret;
+    }
+}
diff --git a/connected-device-lib/src/com/android/car/connecteddevice/storage/AssociatedDeviceDao.java b/connected-device-lib/src/com/android/car/connecteddevice/storage/AssociatedDeviceDao.java
index c041d58..2a1e023 100644
--- a/connected-device-lib/src/com/android/car/connecteddevice/storage/AssociatedDeviceDao.java
+++ b/connected-device-lib/src/com/android/car/connecteddevice/storage/AssociatedDeviceDao.java
@@ -63,4 +63,21 @@
     /** Remove a {@link AssociatedDeviceKeyEntity}. */
     @Delete
     void removeAssociatedDeviceKey(AssociatedDeviceKeyEntity keyEntity);
+
+    /** Get the challenge secret associated with a device id. */
+    @Query("SELECT * FROM associated_devices_challenge_secrets WHERE id LIKE :deviceId LIMIT 1")
+    AssociatedDeviceChallengeSecretEntity getAssociatedDeviceChallengeSecret(String deviceId);
+
+    /**
+     * Add a {@link AssociatedDeviceChallengeSecretEntity}. Replace if a secret already exists with
+     * the same device id.
+     */
+    @Insert(onConflict = OnConflictStrategy.REPLACE)
+    void addOrReplaceAssociatedDeviceChallengeSecret(
+            AssociatedDeviceChallengeSecretEntity challengeSecretEntity);
+
+    /** Remove a {@link AssociatedDeviceChallengeSecretEntity}. */
+    @Delete
+    void removeAssociatedDeviceChallengeSecret(
+            AssociatedDeviceChallengeSecretEntity challengeSecretEntity);
 }
diff --git a/connected-device-lib/src/com/android/car/connecteddevice/storage/ConnectedDeviceDatabase.java b/connected-device-lib/src/com/android/car/connecteddevice/storage/ConnectedDeviceDatabase.java
index 3671440..98a7b0a 100644
--- a/connected-device-lib/src/com/android/car/connecteddevice/storage/ConnectedDeviceDatabase.java
+++ b/connected-device-lib/src/com/android/car/connecteddevice/storage/ConnectedDeviceDatabase.java
@@ -20,9 +20,12 @@
 import androidx.room.RoomDatabase;
 
 /** Database for connected devices. */
-@Database(entities = { AssociatedDeviceEntity.class, AssociatedDeviceKeyEntity.class }, version = 1,
+@Database(entities = { AssociatedDeviceEntity.class, AssociatedDeviceKeyEntity.class,
+        AssociatedDeviceChallengeSecretEntity.class },
+        version = 2,
         exportSchema = false)
 public abstract class ConnectedDeviceDatabase extends RoomDatabase {
+
     /** Return the DAO for the associated device table. */
     public abstract AssociatedDeviceDao associatedDeviceDao();
 }
diff --git a/connected-device-lib/src/com/android/car/connecteddevice/storage/ConnectedDeviceStorage.java b/connected-device-lib/src/com/android/car/connecteddevice/storage/ConnectedDeviceStorage.java
index 433ee1d..19d894e 100644
--- a/connected-device-lib/src/com/android/car/connecteddevice/storage/ConnectedDeviceStorage.java
+++ b/connected-device-lib/src/com/android/car/connecteddevice/storage/ConnectedDeviceStorage.java
@@ -33,10 +33,12 @@
 
 import com.android.car.connecteddevice.R;
 import com.android.car.connecteddevice.model.AssociatedDevice;
+import com.android.internal.annotations.VisibleForTesting;
 
 import java.io.IOException;
 import java.security.InvalidAlgorithmParameterException;
 import java.security.InvalidKeyException;
+import java.security.InvalidParameterException;
 import java.security.Key;
 import java.security.KeyStore;
 import java.security.KeyStoreException;
@@ -52,8 +54,10 @@
 import javax.crypto.Cipher;
 import javax.crypto.IllegalBlockSizeException;
 import javax.crypto.KeyGenerator;
+import javax.crypto.Mac;
 import javax.crypto.NoSuchPaddingException;
 import javax.crypto.spec.GCMParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
 
 /** Storage for connected devices in a car. */
 public class ConnectedDeviceStorage {
@@ -66,6 +70,8 @@
     private static final String KEYSTORE_PROVIDER = "AndroidKeyStore";
     private static final String DATABASE_NAME = "connected-device-database";
     private static final String IV_SPEC_SEPARATOR = ";";
+
+    private static final String CHALLENGE_HASHING_ALGORITHM = "HmacSHA256";
     // This delimiter separates deviceId and deviceInfo, so it has to differ from the
     // TrustedDeviceInfo delimiter. Once new API can be added, deviceId will be added to
     // TrustedDeviceInfo and this delimiter will be removed.
@@ -75,6 +81,9 @@
     // possible value.
     private static final int GCM_AUTHENTICATION_TAG_LENGTH = 128;
 
+    @VisibleForTesting
+    static final int CHALLENGE_SECRET_BYTES = 32;
+
     private final Context mContext;
 
     private SharedPreferences mSharedPreferences;
@@ -110,7 +119,7 @@
     }
 
     /**
-     * Get communication encryption key for the given device
+     * Get communication encryption key for the given device.
      *
      * @param deviceId id of trusted device
      * @return encryption key, null if device id is not recognized
@@ -136,9 +145,9 @@
     }
 
     /**
-     * Save encryption key for the given device
+     * Save encryption key for the given device.
      *
-     * @param deviceId      did of trusted device
+     * @param deviceId id of the device
      * @param encryptionKey encryption key
      */
     public void saveEncryptionKey(@NonNull String deviceId, @NonNull byte[] encryptionKey) {
@@ -149,6 +158,78 @@
     }
 
     /**
+     * Save challenge secret for the given device.
+     *
+     * @param deviceId id of the device
+     * @param secret   Secret associated with this device. Note: must be
+     *                 {@value CHALLENGE_SECRET_BYTES} bytes in length or an
+     *                 {@link InvalidParameterException} will be thrown.
+     */
+    public void saveChallengeSecret(@NonNull String deviceId, @NonNull byte[] secret) {
+        if (secret.length != CHALLENGE_SECRET_BYTES) {
+            throw new InvalidParameterException("Secrets must be " + CHALLENGE_SECRET_BYTES
+                    + " bytes in length.");
+        }
+
+        String encryptedKey = encryptWithKeyStore(KEY_ALIAS, secret);
+        AssociatedDeviceChallengeSecretEntity entity = new AssociatedDeviceChallengeSecretEntity(
+                deviceId, encryptedKey);
+        mAssociatedDeviceDatabase.addOrReplaceAssociatedDeviceChallengeSecret(entity);
+        logd(TAG, "Successfully wrote challenge secret.");
+    }
+
+    /** Get the challenge secret associated with a device. */
+    public byte[] getChallengeSecret(@NonNull String deviceId) {
+        AssociatedDeviceChallengeSecretEntity entity =
+                mAssociatedDeviceDatabase.getAssociatedDeviceChallengeSecret(deviceId);
+        if (entity == null) {
+            logd(TAG, "Challenge secret not found!");
+            return null;
+        }
+        String[] values = entity.encryptedChallengeSecret.split(IV_SPEC_SEPARATOR, -1);
+
+        if (values.length != 2) {
+            logd(TAG, "Stored encryption key had the wrong length.");
+            return null;
+        }
+
+        byte[] encryptedSecret = Base64.decode(values[0], Base64.DEFAULT);
+        byte[] ivSpec = Base64.decode(values[1], Base64.DEFAULT);
+        return decryptWithKeyStore(KEY_ALIAS, encryptedSecret, ivSpec);
+    }
+
+    /**
+     * Hash provided value with device's challenge secret and return result. Returns {@code null} if
+     * unsuccessful.
+     */
+    @Nullable
+    public byte[] hashWithChallengeSecret(@NonNull String deviceId, @NonNull byte[] value) {
+        byte[] challengeSecret = getChallengeSecret(deviceId);
+        if (challengeSecret == null) {
+            loge(TAG, "Unable to find challenge secret for device " + deviceId + ".");
+            return null;
+        }
+
+        Mac mac;
+        try {
+            mac = Mac.getInstance(CHALLENGE_HASHING_ALGORITHM);
+        } catch (NoSuchAlgorithmException e) {
+            loge(TAG, "Unable to find hashing algorithm " + CHALLENGE_HASHING_ALGORITHM + ".", e);
+            return null;
+        }
+
+        SecretKeySpec keySpec = new SecretKeySpec(challengeSecret, CHALLENGE_HASHING_ALGORITHM);
+        try {
+            mac.init(keySpec);
+        } catch (InvalidKeyException e) {
+            loge(TAG, "Exception while initializing HMAC.", e);
+            return null;
+        }
+
+        return mac.doFinal(value);
+    }
+
+    /**
      * Encrypt value with designated key
      *
      * <p>The encrypted value is of the form:
diff --git a/connected-device-lib/src/com/android/car/connecteddevice/util/SafeLog.java b/connected-device-lib/src/com/android/car/connecteddevice/util/SafeLog.java
index 6ab18ce..1efae3e 100644
--- a/connected-device-lib/src/com/android/car/connecteddevice/util/SafeLog.java
+++ b/connected-device-lib/src/com/android/car/connecteddevice/util/SafeLog.java
@@ -57,7 +57,7 @@
 
     /** Log message if tag is whitelisted for {@code Log.ERROR}. */
     public static void loge(@NonNull String tag, @NonNull String message) {
-        loge(tag, message, /* exception = */ null);
+        loge(tag, message, /* exception= */ null);
     }
 
     /** Log message and optional exception if tag is whitelisted for {@code Log.ERROR}. */
diff --git a/connected-device-lib/tests/unit/Android.bp b/connected-device-lib/tests/unit/Android.bp
index 9cf29ba..e550b54 100644
--- a/connected-device-lib/tests/unit/Android.bp
+++ b/connected-device-lib/tests/unit/Android.bp
@@ -33,6 +33,9 @@
         "connected-device-lib",
         "mockito-target-extended-minus-junit4",
         "testables",
+        // TODO: remove once Android migrates to JUnit 4.13,
+        // which provides assertThrows
+        "testng",
         "truth-prebuilt",
     ],
 
diff --git a/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/ConnectedDeviceManagerTest.java b/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/ConnectedDeviceManagerTest.java
index 579fe7d..3e345c2 100644
--- a/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/ConnectedDeviceManagerTest.java
+++ b/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/ConnectedDeviceManagerTest.java
@@ -22,8 +22,8 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.clearInvocations;
 import static org.mockito.Mockito.mockitoSession;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.timeout;
@@ -58,6 +58,7 @@
 import org.mockito.MockitoSession;
 import org.mockito.quality.Strictness;
 
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import java.util.UUID;
@@ -73,12 +74,15 @@
 
     private static final String TEST_DEVICE_NAME = "TEST_DEVICE_NAME";
 
-    private static final int DEFAULT_RECONNECT_TIMEOUT = 5;
 
     private final Executor mCallbackExecutor = Executors.newSingleThreadExecutor();
 
     private final UUID mRecipientId = UUID.randomUUID();
 
+    private final List<String> mUserDeviceIds = new ArrayList<>();
+
+    private final List<AssociatedDevice> mUserDevices = new ArrayList<>();
+
     @Mock
     private ConnectedDeviceStorage mMockStorage;
 
@@ -98,13 +102,15 @@
     public void setUp() {
         mMockingSession = mockitoSession()
                 .initMocks(this)
-                .strictness(Strictness.LENIENT)
+                .strictness(Strictness.WARN)
                 .startMocking();
         ArgumentCaptor<AssociatedDeviceCallback> callbackCaptor = ArgumentCaptor
                 .forClass(AssociatedDeviceCallback.class);
         mConnectedDeviceManager = new ConnectedDeviceManager(mMockStorage, mMockCentralManager,
-            mMockPeripheralManager, DEFAULT_RECONNECT_TIMEOUT);
+            mMockPeripheralManager);
         verify(mMockStorage).setAssociatedDeviceCallback(callbackCaptor.capture());
+        when(mMockStorage.getActiveUserAssociatedDevices()).thenReturn(mUserDevices);
+        when(mMockStorage.getActiveUserAssociatedDeviceIds()).thenReturn(mUserDeviceIds);
         mAssociatedDeviceCallback = callbackCaptor.getValue();
         mConnectedDeviceManager.start();
     }
@@ -126,8 +132,8 @@
         String deviceId = connectNewDevice(mMockCentralManager);
         List<ConnectedDevice> activeUserDevices =
                 mConnectedDeviceManager.getActiveUserConnectedDevices();
-        ConnectedDevice expectedDevice = new ConnectedDevice(deviceId, /* deviceName = */ null,
-                /* belongsToActiveUser = */ true, /* hasSecureChannel = */ false);
+        ConnectedDevice expectedDevice = new ConnectedDevice(deviceId, /* deviceName= */ null,
+                /* belongsToActiveUser= */ true, /* hasSecureChannel= */ false);
         assertThat(activeUserDevices).containsExactly(expectedDevice);
     }
 
@@ -451,6 +457,27 @@
     }
 
     @Test
+    public void registerDeviceCallback_sendsMultipleMissedMessagesAfterRegistration()
+            throws InterruptedException {
+        Semaphore semaphore = new Semaphore(0);
+        connectNewDevice(mMockCentralManager);
+        ConnectedDevice connectedDevice =
+                mConnectedDeviceManager.getActiveUserConnectedDevices().get(0);
+        byte[] payload1 = ByteUtils.randomBytes(10);
+        byte[] payload2 = ByteUtils.randomBytes(10);
+        DeviceMessage message1 = new DeviceMessage(mRecipientId, false, payload1);
+        DeviceMessage message2 = new DeviceMessage(mRecipientId, false, payload2);
+        mConnectedDeviceManager.onMessageReceived(connectedDevice.getDeviceId(), message1);
+        mConnectedDeviceManager.onMessageReceived(connectedDevice.getDeviceId(), message2);
+        DeviceCallback deviceCallback = createDeviceCallback(semaphore);
+        mConnectedDeviceManager.registerDeviceCallback(connectedDevice, mRecipientId,
+                deviceCallback, mCallbackExecutor);
+        assertThat(tryAcquire(semaphore)).isTrue();
+        verify(deviceCallback).onMessageReceived(connectedDevice, payload1);
+        verify(deviceCallback, timeout(1000)).onMessageReceived(connectedDevice, payload2);
+    }
+
+    @Test
     public void registerDeviceCallback_doesNotSendMissedMessageForDifferentRecipient()
             throws InterruptedException {
         Semaphore semaphore = new Semaphore(0);
@@ -511,7 +538,7 @@
         mConnectedDeviceManager.registerDeviceAssociationCallback(callback, mCallbackExecutor);
         String deviceId = UUID.randomUUID().toString();
         AssociatedDevice testDevice = new AssociatedDevice(deviceId, TEST_DEVICE_ADDRESS,
-                TEST_DEVICE_NAME, /* isConnectionEnabled = */ true);
+                TEST_DEVICE_NAME, /* isConnectionEnabled= */ true);
         mAssociatedDeviceCallback.onAssociatedDeviceAdded(testDevice);
         assertThat(tryAcquire(semaphore)).isTrue();
         verify(callback).onAssociatedDeviceAdded(eq(testDevice));
@@ -524,7 +551,7 @@
         mConnectedDeviceManager.registerDeviceAssociationCallback(callback, mCallbackExecutor);
         String deviceId = UUID.randomUUID().toString();
         AssociatedDevice testDevice = new AssociatedDevice(deviceId, TEST_DEVICE_ADDRESS,
-                TEST_DEVICE_NAME, /* isConnectionEnabled = */ true);
+                TEST_DEVICE_NAME, /* isConnectionEnabled= */ true);
         mAssociatedDeviceCallback.onAssociatedDeviceRemoved(testDevice);
         assertThat(tryAcquire(semaphore)).isTrue();
         verify(callback).onAssociatedDeviceRemoved(eq(testDevice));
@@ -537,7 +564,7 @@
         mConnectedDeviceManager.registerDeviceAssociationCallback(callback, mCallbackExecutor);
         String deviceId = UUID.randomUUID().toString();
         AssociatedDevice testDevice = new AssociatedDevice(deviceId, TEST_DEVICE_ADDRESS,
-                TEST_DEVICE_NAME, /* isConnectionEnabled = */ true);
+                TEST_DEVICE_NAME, /* isConnectionEnabled= */ true);
         mAssociatedDeviceCallback.onAssociatedDeviceUpdated(testDevice);
         assertThat(tryAcquire(semaphore)).isTrue();
         verify(callback).onAssociatedDeviceUpdated(eq(testDevice));
@@ -549,13 +576,14 @@
         when(mMockStorage.getActiveUserAssociatedDeviceIds()).thenReturn(
                 Collections.singletonList(deviceId));
         AssociatedDevice device = new AssociatedDevice(deviceId, TEST_DEVICE_ADDRESS,
-                TEST_DEVICE_NAME, /* isConnectionEnabled = */ true);
+                TEST_DEVICE_NAME, /* isConnectionEnabled= */ true);
         when(mMockStorage.getActiveUserAssociatedDevices()).thenReturn(
                 Collections.singletonList(device));
+        clearInvocations(mMockPeripheralManager);
         mConnectedDeviceManager.addConnectedDevice(deviceId, mMockPeripheralManager);
         mConnectedDeviceManager.removeConnectedDevice(deviceId, mMockPeripheralManager);
         verify(mMockPeripheralManager, timeout(1000))
-                .connectToDevice(eq(UUID.fromString(deviceId)), anyInt());
+                .connectToDevice(eq(UUID.fromString(deviceId)));
     }
 
     @Test
@@ -565,13 +593,14 @@
         when(mMockStorage.getActiveUserAssociatedDeviceIds()).thenReturn(
                 Collections.singletonList(userDeviceId));
         AssociatedDevice userDevice = new AssociatedDevice(userDeviceId, TEST_DEVICE_ADDRESS,
-                TEST_DEVICE_NAME, /* isConnectionEnabled = */ true);
+                TEST_DEVICE_NAME, /* isConnectionEnabled= */ true);
         when(mMockStorage.getActiveUserAssociatedDevices()).thenReturn(
                 Collections.singletonList(userDevice));
         mConnectedDeviceManager.addConnectedDevice(deviceId, mMockPeripheralManager);
+        clearInvocations(mMockPeripheralManager);
         mConnectedDeviceManager.removeConnectedDevice(deviceId, mMockPeripheralManager);
         verify(mMockPeripheralManager, timeout(1000))
-                .connectToDevice(eq(UUID.fromString(userDeviceId)), anyInt());
+                .connectToDevice(eq(UUID.fromString(userDeviceId)));
     }
 
     @Test
@@ -581,14 +610,15 @@
         when(mMockStorage.getActiveUserAssociatedDeviceIds()).thenReturn(
                 Collections.singletonList(userDeviceId));
         AssociatedDevice userDevice = new AssociatedDevice(userDeviceId, TEST_DEVICE_ADDRESS,
-                TEST_DEVICE_NAME, /* isConnectionEnabled = */ true);
+                TEST_DEVICE_NAME, /* isConnectionEnabled= */ true);
         when(mMockStorage.getActiveUserAssociatedDevices()).thenReturn(
                 Collections.singletonList(userDevice));
+        clearInvocations(mMockPeripheralManager);
         mConnectedDeviceManager.addConnectedDevice(deviceId, mMockPeripheralManager);
         mConnectedDeviceManager.addConnectedDevice(userDeviceId, mMockCentralManager);
         mConnectedDeviceManager.removeConnectedDevice(deviceId, mMockPeripheralManager);
         verify(mMockPeripheralManager, timeout(1000).times(0))
-                .connectToDevice(eq(UUID.fromString(userDeviceId)), anyInt());
+                .connectToDevice(any());
     }
 
     @Test
@@ -678,11 +708,9 @@
     private String connectNewDevice(@NonNull CarBleManager carBleManager) {
         String deviceId = UUID.randomUUID().toString();
         AssociatedDevice device = new AssociatedDevice(deviceId, TEST_DEVICE_ADDRESS,
-                TEST_DEVICE_NAME, /* isConnectionEnabled = */ true);
-        when(mMockStorage.getActiveUserAssociatedDevices()).thenReturn(
-                Collections.singletonList(device));
-        when(mMockStorage.getActiveUserAssociatedDeviceIds()).thenReturn(
-                Collections.singletonList(deviceId));
+                TEST_DEVICE_NAME, /* isConnectionEnabled= */ true);
+        mUserDeviceIds.add(deviceId);
+        mUserDevices.add(device);
         mConnectedDeviceManager.addConnectedDevice(deviceId, carBleManager);
         return deviceId;
     }
diff --git a/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/ble/AssociationSecureChannelTest.java b/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/ble/AssociationSecureChannelTest.java
new file mode 100644
index 0000000..1a4941c
--- /dev/null
+++ b/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/ble/AssociationSecureChannelTest.java
@@ -0,0 +1,236 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.car.connecteddevice.ble;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.anyString;
+import static org.mockito.Mockito.mockitoSession;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.car.encryptionrunner.DummyEncryptionRunner;
+import android.car.encryptionrunner.EncryptionRunner;
+import android.car.encryptionrunner.EncryptionRunnerFactory;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import com.android.car.connecteddevice.BleStreamProtos.BleOperationProto.OperationType;
+import com.android.car.connecteddevice.ble.BleDeviceMessageStream.MessageReceivedListener;
+import com.android.car.connecteddevice.storage.ConnectedDeviceStorage;
+import com.android.car.connecteddevice.util.ByteUtils;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoSession;
+import org.mockito.quality.Strictness;
+
+import java.util.UUID;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+
+@RunWith(AndroidJUnit4.class)
+public final class AssociationSecureChannelTest {
+    private static final UUID CLIENT_DEVICE_ID =
+            UUID.fromString("a5645523-3280-410a-90c1-582a6c6f4969");
+    private static final UUID SERVER_DEVICE_ID =
+            UUID.fromString("a29f0c74-2014-4b14-ac02-be6ed15b545a");
+    private static final byte[] CLIENT_SECRET = ByteUtils.randomBytes(32);
+
+    @Mock
+    private BleDeviceMessageStream mStreamMock;
+    @Mock
+    private ConnectedDeviceStorage mStorageMock;
+    @Mock
+    private AssociationSecureChannel.ShowVerificationCodeListener mShowVerificationCodeListenerMock;
+    private MockitoSession mMockitoSession;
+
+    private AssociationSecureChannel mChannel;
+    private MessageReceivedListener mMessageReceivedListener;
+
+    @Before
+    public void setUp() {
+        mMockitoSession = mockitoSession()
+                .initMocks(this)
+                .strictness(Strictness.WARN)
+                .startMocking();
+        when(mStorageMock.getUniqueId()).thenReturn(SERVER_DEVICE_ID);
+    }
+
+    @After
+    public void tearDown() {
+        if (mMockitoSession != null) {
+            mMockitoSession.finishMocking();
+        }
+    }
+
+    @Test
+    public void testEncryptionHandshake_Association() throws InterruptedException {
+        Semaphore semaphore = new Semaphore(0);
+        ChannelCallback callbackSpy = spy(new ChannelCallback(semaphore));
+        setupAssociationSecureChannel(callbackSpy, EncryptionRunnerFactory::newDummyRunner);
+        ArgumentCaptor<String> deviceIdCaptor = ArgumentCaptor.forClass(String.class);
+        ArgumentCaptor<DeviceMessage> messageCaptor =
+                ArgumentCaptor.forClass(DeviceMessage.class);
+
+        initHandshakeMessage();
+        verify(mStreamMock).writeMessage(messageCaptor.capture(), any());
+        byte[] response = messageCaptor.getValue().getMessage();
+        assertThat(response).isEqualTo(DummyEncryptionRunner.INIT_RESPONSE.getBytes());
+
+        respondToContinueMessage();
+        verify(mShowVerificationCodeListenerMock).showVerificationCode(anyString());
+
+        mChannel.notifyOutOfBandAccepted();
+        sendDeviceId();
+        assertThat(semaphore.tryAcquire(100, TimeUnit.MILLISECONDS)).isTrue();
+        verify(callbackSpy).onDeviceIdReceived(deviceIdCaptor.capture());
+        verify(mStreamMock, times(2)).writeMessage(messageCaptor.capture(), any());
+        byte[] deviceIdMessage = messageCaptor.getValue().getMessage();
+        assertThat(deviceIdMessage).isEqualTo(ByteUtils.uuidToBytes(SERVER_DEVICE_ID));
+        assertThat(deviceIdCaptor.getValue()).isEqualTo(CLIENT_DEVICE_ID.toString());
+        verify(mStorageMock).saveEncryptionKey(eq(CLIENT_DEVICE_ID.toString()), any());
+        verify(mStorageMock).saveChallengeSecret(CLIENT_DEVICE_ID.toString(), CLIENT_SECRET);
+
+        assertThat(semaphore.tryAcquire(100, TimeUnit.MILLISECONDS)).isTrue();
+        verify(callbackSpy).onSecureChannelEstablished();
+    }
+
+    @Test
+    public void testEncryptionHandshake_Association_wrongInitHandshakeMessage()
+            throws InterruptedException {
+        Semaphore semaphore = new Semaphore(0);
+        ChannelCallback callbackSpy = spy(new ChannelCallback(semaphore));
+        setupAssociationSecureChannel(callbackSpy, EncryptionRunnerFactory::newDummyRunner);
+
+        // Wrong init handshake message
+        respondToContinueMessage();
+        assertThat(semaphore.tryAcquire(100, TimeUnit.MILLISECONDS)).isTrue();
+        verify(callbackSpy).onEstablishSecureChannelFailure(
+                eq(SecureBleChannel.CHANNEL_ERROR_INVALID_HANDSHAKE)
+        );
+    }
+
+    @Test
+    public void testEncryptionHandshake_Association_wrongRespondToContinueMessage()
+            throws InterruptedException {
+        Semaphore semaphore = new Semaphore(0);
+        ChannelCallback callbackSpy = spy(new ChannelCallback(semaphore));
+        setupAssociationSecureChannel(callbackSpy, EncryptionRunnerFactory::newDummyRunner);
+
+        initHandshakeMessage();
+
+        // Wrong respond to continue message
+        initHandshakeMessage();
+        assertThat(semaphore.tryAcquire(100, TimeUnit.MILLISECONDS)).isTrue();
+        verify(callbackSpy).onEstablishSecureChannelFailure(
+                eq(SecureBleChannel.CHANNEL_ERROR_INVALID_HANDSHAKE)
+        );
+    }
+
+    private void setupAssociationSecureChannel(ChannelCallback callback,
+            EncryptionRunnerProvider encryptionRunnerProvider) {
+        mChannel = new AssociationSecureChannel(mStreamMock, mStorageMock,
+                encryptionRunnerProvider.getEncryptionRunner());
+        mChannel.registerCallback(callback);
+        mChannel.setShowVerificationCodeListener(mShowVerificationCodeListenerMock);
+        ArgumentCaptor<MessageReceivedListener> listenerCaptor =
+                ArgumentCaptor.forClass(MessageReceivedListener.class);
+        verify(mStreamMock).setMessageReceivedListener(listenerCaptor.capture());
+        mMessageReceivedListener = listenerCaptor.getValue();
+    }
+
+    private void sendDeviceId() {
+        DeviceMessage message = new DeviceMessage(
+                /* recipient= */ null,
+                /* isMessageEncrypted= */ true,
+                ByteUtils.concatByteArrays(ByteUtils.uuidToBytes(CLIENT_DEVICE_ID), CLIENT_SECRET)
+        );
+        mMessageReceivedListener.onMessageReceived(message, OperationType.ENCRYPTION_HANDSHAKE);
+    }
+
+    private void initHandshakeMessage() {
+        DeviceMessage message = new DeviceMessage(
+                /* recipient= */ null,
+                /* isMessageEncrypted= */ false,
+                DummyEncryptionRunner.INIT.getBytes()
+        );
+        mMessageReceivedListener.onMessageReceived(message, OperationType.ENCRYPTION_HANDSHAKE);
+    }
+
+    private void respondToContinueMessage() {
+        DeviceMessage message = new DeviceMessage(
+                /* recipient= */ null,
+                /* isMessageEncrypted= */ false,
+                DummyEncryptionRunner.CLIENT_RESPONSE.getBytes()
+        );
+        mMessageReceivedListener.onMessageReceived(message, OperationType.ENCRYPTION_HANDSHAKE);
+    }
+
+    /**
+     * Add the thread control logic into {@link SecureBleChannel.Callback} only for spy purpose.
+     *
+     * <p>The callback will release the semaphore which hold by one test when this callback
+     * is called, telling the test that it can verify certain behaviors which will only occurred
+     * after the callback is notified. This is needed mainly because of the callback is notified
+     * in a different thread.
+     */
+    private static class ChannelCallback implements SecureBleChannel.Callback {
+        private final Semaphore mSemaphore;
+
+        ChannelCallback(Semaphore semaphore) {
+            mSemaphore = semaphore;
+        }
+
+        @Override
+        public void onSecureChannelEstablished() {
+            mSemaphore.release();
+        }
+
+        @Override
+        public void onEstablishSecureChannelFailure(int error) {
+            mSemaphore.release();
+        }
+
+        @Override
+        public void onMessageReceived(DeviceMessage deviceMessage) {
+            mSemaphore.release();
+        }
+
+        @Override
+        public void onMessageReceivedError(Exception exception) {
+            mSemaphore.release();
+        }
+
+        @Override
+        public void onDeviceIdReceived(String deviceId) {
+            mSemaphore.release();
+        }
+    }
+
+    interface EncryptionRunnerProvider {
+        EncryptionRunner getEncryptionRunner();
+    }
+}
diff --git a/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/ble/BleDeviceMessageStreamTest.java b/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/ble/BleDeviceMessageStreamTest.java
index b45b6f2..ed6fb44 100644
--- a/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/ble/BleDeviceMessageStreamTest.java
+++ b/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/ble/BleDeviceMessageStreamTest.java
@@ -19,6 +19,7 @@
 import static com.android.car.connecteddevice.BleStreamProtos.BleDeviceMessageProto.BleDeviceMessage;
 import static com.android.car.connecteddevice.BleStreamProtos.BleOperationProto.OperationType;
 import static com.android.car.connecteddevice.BleStreamProtos.BlePacketProto.BlePacket;
+import static com.android.car.connecteddevice.ble.BleDeviceMessageStream.MessageReceivedErrorListener;
 import static com.android.car.connecteddevice.ble.BleDeviceMessageStream.MessageReceivedListener;
 
 import static com.google.common.truth.Truth.assertThat;
@@ -57,7 +58,7 @@
 @RunWith(AndroidJUnit4.class)
 public class BleDeviceMessageStreamTest {
 
-    private static final String TAG = "BleDeviceMessageStreamTest";
+    private static final int PACKET_SIZE = 500;
 
     private BleDeviceMessageStream mStream;
 
@@ -83,7 +84,7 @@
                 .startMocking();
 
         mStream = new BleDeviceMessageStream(mMockBlePeripheralManager, mMockBluetoothDevice,
-                mMockWriteCharacteristic, mMockReadCharacteristic);
+                mMockWriteCharacteristic, mMockReadCharacteristic, PACKET_SIZE);
     }
 
     @After
@@ -126,7 +127,7 @@
         Semaphore semaphore = new Semaphore(0);
         MessageReceivedListener listener = createMessageReceivedListener(semaphore);
         mStream.setMessageReceivedListener(listener);
-        byte[] data = ByteUtils.randomBytes(750);
+        byte[] data = ByteUtils.randomBytes((int) (PACKET_SIZE * 1.5));
         List<BlePacket> packets1 = createPackets(data);
         List<BlePacket> packets2 = createPackets(data);
 
@@ -154,9 +155,9 @@
     public void processPacket_doesNotNotifyOfNewMessageIfNotAllPacketsReceived()
             throws InterruptedException {
         Semaphore semaphore = new Semaphore(0);
-        MessageReceivedListener listener = createMessageReceivedListener(semaphore);
-        mStream.setMessageReceivedListener(listener);
-        byte[] data = ByteUtils.randomBytes(750);
+        mStream.setMessageReceivedListener(createMessageReceivedListener(semaphore));
+        mStream.setMessageReceivedErrorListener(createMessageReceivedErrorListener(semaphore));
+        byte[] data = ByteUtils.randomBytes((int) (PACKET_SIZE * 1.5));
         List<BlePacket> packets = createPackets(data);
         for (int i = 0; i < packets.size() - 1; i++) {
             mStream.processPacket(packets.get(i));
@@ -164,6 +165,44 @@
         assertThat(tryAcquire(semaphore)).isFalse();
     }
 
+    @Test
+    public void processPacket_ignoresDuplicatePacket() {
+        Semaphore semaphore = new Semaphore(0);
+        byte[] data = ByteUtils.randomBytes((int) (PACKET_SIZE * 2.5));
+        MessageReceivedListener listener = createMessageReceivedListener(semaphore);
+        mStream.setMessageReceivedListener(listener);
+        ArgumentCaptor<DeviceMessage> messageCaptor = ArgumentCaptor.forClass(DeviceMessage.class);
+        List<BlePacket> packets = createPackets(data);
+        for (int i = 0; i < packets.size(); i++) {
+            mStream.processPacket(packets.get(i));
+            mStream.processPacket(packets.get(i)); // Process each packet twice.
+        }
+        verify(listener).onMessageReceived(messageCaptor.capture(), any());
+        assertThat(Arrays.equals(data, messageCaptor.getValue().getMessage())).isTrue();
+    }
+
+    @Test
+    public void processPacket_packetBeforeExpectedRangeNotifiesMessageError()
+            throws InterruptedException {
+        Semaphore semaphore = new Semaphore(0);
+        mStream.setMessageReceivedErrorListener(createMessageReceivedErrorListener(semaphore));
+        List<BlePacket> packets = createPackets(ByteUtils.randomBytes((int) (PACKET_SIZE * 2.5)));
+        mStream.processPacket(packets.get(0));
+        mStream.processPacket(packets.get(1));
+        mStream.processPacket(packets.get(0));
+        assertThat(tryAcquire(semaphore)).isTrue();
+    }
+
+    @Test
+    public void processPacket_packetAfterExpectedNotifiesMessageError()
+            throws InterruptedException {
+        Semaphore semaphore = new Semaphore(0);
+        mStream.setMessageReceivedErrorListener(createMessageReceivedErrorListener(semaphore));
+        List<BlePacket> packets = createPackets(ByteUtils.randomBytes((int) (PACKET_SIZE * 1.5)));
+        mStream.processPacket(packets.get(1));
+        assertThat(tryAcquire(semaphore)).isTrue();
+    }
+
     @NonNull
     private List<BlePacket> createPackets(byte[] data) {
         try {
@@ -172,7 +211,7 @@
                     .setOperation(OperationType.CLIENT_MESSAGE)
                     .build();
             return BlePacketFactory.makeBlePackets(message.toByteArray(),
-                    ThreadLocalRandom.current().nextInt(), 500);
+                    ThreadLocalRandom.current().nextInt(), PACKET_SIZE);
         } catch (Exception e) {
             assertWithMessage("Uncaught exception while making packets.").fail();
             return new ArrayList<>();
@@ -186,14 +225,18 @@
         }
     }
 
-    private boolean tryAcquire(Semaphore semaphore) throws InterruptedException {
+    private boolean tryAcquire(@NonNull Semaphore semaphore) throws InterruptedException {
         return semaphore.tryAcquire(100, TimeUnit.MILLISECONDS);
     }
 
     @NonNull
-    private MessageReceivedListener createMessageReceivedListener(
-            Semaphore semaphore) {
+    private MessageReceivedListener createMessageReceivedListener(@NonNull Semaphore semaphore) {
         return spy((deviceMessage, operationType) -> semaphore.release());
     }
 
+    @NonNull
+    private MessageReceivedErrorListener createMessageReceivedErrorListener(
+            @NonNull Semaphore semaphore) {
+        return exception -> semaphore.release();
+    }
 }
diff --git a/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/ble/CarBlePeripheralManagerTest.java b/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/ble/CarBlePeripheralManagerTest.java
index 986f11e..ac58a97 100644
--- a/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/ble/CarBlePeripheralManagerTest.java
+++ b/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/ble/CarBlePeripheralManagerTest.java
@@ -24,6 +24,7 @@
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.timeout;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 import android.annotation.NonNull;
 import android.bluetooth.BluetoothAdapter;
@@ -53,6 +54,7 @@
 import org.mockito.MockitoSession;
 import org.mockito.quality.Strictness;
 
+import java.time.Duration;
 import java.util.UUID;
 import java.util.concurrent.Semaphore;
 import java.util.concurrent.TimeUnit;
@@ -60,6 +62,8 @@
 @RunWith(AndroidJUnit4.class)
 public class CarBlePeripheralManagerTest {
     private static final UUID ASSOCIATION_SERVICE_UUID = UUID.randomUUID();
+    private static final UUID RECONNECT_SERVICE_UUID = UUID.randomUUID();
+    private static final UUID RECONNECT_DATA_UUID = UUID.randomUUID();
     private static final UUID WRITE_UUID = UUID.randomUUID();
     private static final UUID READ_UUID = UUID.randomUUID();
     private static final int DEVICE_NAME_LENGTH_LIMIT = 8;
@@ -67,10 +71,15 @@
     private static final UUID TEST_REMOTE_DEVICE_ID = UUID.randomUUID();
     private static final String TEST_VERIFICATION_CODE = "000000";
     private static final byte[] TEST_KEY = "Key".getBytes();
+    private static final Duration RECONNECT_ADVERTISEMENT_DURATION = Duration.ofSeconds(2);
+    private static final int DEFAULT_MTU_SIZE = 23;
+
     private static String sAdapterName;
 
-    @Mock private BlePeripheralManager mMockPeripheralManager;
-    @Mock private ConnectedDeviceStorage mMockStorage;
+    @Mock
+    private BlePeripheralManager mMockPeripheralManager;
+    @Mock
+    private ConnectedDeviceStorage mMockStorage;
 
     private CarBlePeripheralManager mCarBlePeripheralManager;
 
@@ -80,14 +89,16 @@
     public static void beforeSetUp() {
         sAdapterName = BluetoothAdapter.getDefaultAdapter().getName();
     }
+
     @Before
-    public void setUp() {
+    public void setUp() throws Exception {
         mMockitoSession = mockitoSession()
                 .initMocks(this)
-                .strictness(Strictness.LENIENT)
+                .strictness(Strictness.WARN)
                 .startMocking();
         mCarBlePeripheralManager = new CarBlePeripheralManager(mMockPeripheralManager, mMockStorage,
-                ASSOCIATION_SERVICE_UUID, WRITE_UUID, READ_UUID);
+                ASSOCIATION_SERVICE_UUID, RECONNECT_SERVICE_UUID, RECONNECT_DATA_UUID,
+                WRITE_UUID, READ_UUID, RECONNECT_ADVERTISEMENT_DURATION, DEFAULT_MTU_SIZE);
     }
 
     @After
@@ -158,7 +169,7 @@
     public void testShowVerificationCode() throws InterruptedException {
         Semaphore semaphore = new Semaphore(0);
         AssociationCallback callback = createAssociationCallback(semaphore);
-        SecureBleChannel channel = getChannelForAssociation(callback);
+        AssociationSecureChannel channel = getChannelForAssociation(callback);
         channel.getShowVerificationCodeListener().showVerificationCode(TEST_VERIFICATION_CODE);
         assertThat(tryAcquire(semaphore)).isTrue();
         verify(callback).onVerificationCodeAvailable(eq(TEST_VERIFICATION_CODE));
@@ -199,13 +210,15 @@
 
     @Test
     public void connectToDevice_stopsAdvertisingAfterTimeout() {
-        int timeoutSeconds = 2;
-        mCarBlePeripheralManager.connectToDevice(UUID.randomUUID(), timeoutSeconds);
+        when(mMockStorage.hashWithChallengeSecret(any(), any()))
+                .thenReturn(ByteUtils.randomBytes(32));
+        mCarBlePeripheralManager.connectToDevice(UUID.randomUUID());
         ArgumentCaptor<AdvertiseCallback> callbackCaptor =
                 ArgumentCaptor.forClass(AdvertiseCallback.class);
         verify(mMockPeripheralManager).startAdvertising(any(), any(), callbackCaptor.capture());
         callbackCaptor.getValue().onStartSuccess(null);
-        verify(mMockPeripheralManager, timeout(TimeUnit.SECONDS.toMillis(timeoutSeconds + 1)))
+        verify(mMockPeripheralManager,
+                timeout(RECONNECT_ADVERTISEMENT_DURATION.plusSeconds(1).toMillis()))
                 .stopAdvertising(any(AdvertiseCallback.class));
     }
 
@@ -218,13 +231,13 @@
         return callbackCaptor.getValue();
     }
 
-    private SecureBleChannel getChannelForAssociation(AssociationCallback callback) {
+    private AssociationSecureChannel getChannelForAssociation(AssociationCallback callback) {
         BlePeripheralManager.Callback bleManagerCallback = startAssociation(callback,
                 getNameForAssociation());
         BluetoothDevice bluetoothDevice = BluetoothAdapter.getDefaultAdapter()
                 .getRemoteDevice(TEST_REMOTE_DEVICE_ADDRESS);
         bleManagerCallback.onRemoteDeviceConnected(bluetoothDevice);
-        return mCarBlePeripheralManager.getConnectedDeviceChannel();
+        return (AssociationSecureChannel) mCarBlePeripheralManager.getConnectedDeviceChannel();
     }
 
     private boolean tryAcquire(Semaphore semaphore) throws InterruptedException {
@@ -243,6 +256,7 @@
             public void onAssociationStartSuccess(String deviceName) {
                 semaphore.release();
             }
+
             @Override
             public void onAssociationStartFailure() {
                 semaphore.release();
diff --git a/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/ble/SecureBleChannelTest.java b/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/ble/SecureBleChannelTest.java
index 2960e49..e8f4da4 100644
--- a/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/ble/SecureBleChannelTest.java
+++ b/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/ble/SecureBleChannelTest.java
@@ -16,206 +16,194 @@
 
 package com.android.car.connecteddevice.ble;
 
+import static com.android.car.connecteddevice.BleStreamProtos.BleOperationProto.OperationType.CLIENT_MESSAGE;
+import static com.android.car.connecteddevice.BleStreamProtos.BleOperationProto.OperationType.ENCRYPTION_HANDSHAKE;
+import static com.android.car.connecteddevice.ble.SecureBleChannel.CHANNEL_ERROR_INVALID_HANDSHAKE;
+import static com.android.car.connecteddevice.ble.SecureBleChannel.Callback;
+
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.anyString;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mockitoSession;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
 
 import android.car.encryptionrunner.DummyEncryptionRunner;
 import android.car.encryptionrunner.EncryptionRunnerFactory;
+import android.car.encryptionrunner.HandshakeException;
+import android.car.encryptionrunner.Key;
 
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 
-import com.android.car.connecteddevice.BleStreamProtos.BleOperationProto.OperationType;
-import com.android.car.connecteddevice.ble.BleDeviceMessageStream.MessageReceivedListener;
-import com.android.car.connecteddevice.storage.ConnectedDeviceStorage;
 import com.android.car.connecteddevice.util.ByteUtils;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
+import org.mockito.MockitoSession;
+import org.mockito.quality.Strictness;
 
+import java.security.NoSuchAlgorithmException;
+import java.security.SignatureException;
 import java.util.UUID;
 import java.util.concurrent.Semaphore;
 import java.util.concurrent.TimeUnit;
 
 @RunWith(AndroidJUnit4.class)
-public final class SecureBleChannelTest {
-    private static final UUID CLIENT_DEVICE_ID =
-            UUID.fromString("a5645523-3280-410a-90c1-582a6c6f4969");
-    private static final UUID SERVER_DEVICE_ID =
-            UUID.fromString("a29f0c74-2014-4b14-ac02-be6ed15b545a");
+public class SecureBleChannelTest {
 
-    private SecureBleChannel mChannel;
-    private MessageReceivedListener mMessageReceivedListener;
+    @Mock private BleDeviceMessageStream mMockStream;
 
-    @Mock private BleDeviceMessageStream mStreamMock;
-    @Mock private ConnectedDeviceStorage mStorageMock;
-    @Mock private SecureBleChannel.ShowVerificationCodeListener mShowVerificationCodeListenerMock;
+    @Mock private Key mKey = spy(new Key() {
+        @Override
+        public byte[] asBytes() {
+            return new byte[0];
+        }
+
+        @Override
+        public byte[] encryptData(byte[] data) {
+            return data;
+        }
+
+        @Override
+        public byte[] decryptData(byte[] encryptedData) throws SignatureException {
+            return encryptedData;
+        }
+
+        @Override
+        public byte[] getUniqueSession() throws NoSuchAlgorithmException {
+            return new byte[0];
+        }
+    });
+
+    private MockitoSession mMockitoSession;
+
+    private SecureBleChannel mSecureBleChannel;
 
     @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        when(mStorageMock.getUniqueId()).thenReturn(SERVER_DEVICE_ID);
+    public void setUp() throws SignatureException {
+        mMockitoSession = mockitoSession()
+                .initMocks(this)
+                .strictness(Strictness.WARN)
+                .startMocking();
+
+        mSecureBleChannel = new SecureBleChannel(mMockStream,
+                EncryptionRunnerFactory.newDummyRunner()) {
+            @Override
+            void processHandshake(byte[] message) { }
+        };
+        mSecureBleChannel.setEncryptionKey(mKey);
+    }
+
+    @After
+    public void tearDown() {
+        if (mMockitoSession != null) {
+            mMockitoSession.finishMocking();
+        }
     }
 
     @Test
-    public void testEncryptionHandshake_Association() throws InterruptedException {
-        Semaphore semaphore = new Semaphore(0);
-        ChannelCallback callbackSpy = spy(new ChannelCallback(semaphore));
-        setUpSecureBleChannel_Association(callbackSpy);
-        ArgumentCaptor<String> deviceIdCaptor = ArgumentCaptor.forClass(String.class);
-        ArgumentCaptor<DeviceMessage> messageCaptor =
-                ArgumentCaptor.forClass(DeviceMessage.class);
-
-        sendDeviceId();
-        assertThat(semaphore.tryAcquire(100, TimeUnit.MILLISECONDS)).isTrue();
-        verify(callbackSpy).onDeviceIdReceived(deviceIdCaptor.capture());
-        verify(mStreamMock).writeMessage(messageCaptor.capture(), any());
-        byte[] deviceIdMessage = messageCaptor.getValue().getMessage();
-        assertThat(deviceIdMessage).isEqualTo(ByteUtils.uuidToBytes(SERVER_DEVICE_ID));
-        assertThat(deviceIdCaptor.getValue()).isEqualTo(CLIENT_DEVICE_ID.toString());
-
-        initHandshakeMessage();
-        verify(mStreamMock, times(2)).writeMessage(messageCaptor.capture(), any());
-        byte[] response = messageCaptor.getValue().getMessage();
-        assertThat(response).isEqualTo(DummyEncryptionRunner.INIT_RESPONSE.getBytes());
-
-        respondToContinueMessage();
-        verify(mShowVerificationCodeListenerMock).showVerificationCode(anyString());
-
-        mChannel.notifyOutOfBandAccepted();
-        verify(mStreamMock, times(3)).writeMessage(messageCaptor.capture(), any());
-        byte[] confirmMessage = messageCaptor.getValue().getMessage();
-        assertThat(confirmMessage).isEqualTo(SecureBleChannel.CONFIRMATION_SIGNAL);
-        assertThat(semaphore.tryAcquire(100, TimeUnit.MILLISECONDS)).isTrue();
-        verify(callbackSpy).onSecureChannelEstablished();
+    public void processMessage_doesNothingForUnencryptedMessage() throws SignatureException {
+        byte[] payload = ByteUtils.randomBytes(10);
+        DeviceMessage message = new DeviceMessage(UUID.randomUUID(), /* isEncrypted= */ false,
+                payload);
+        mSecureBleChannel.processMessage(message);
+        assertThat(message.getMessage()).isEqualTo(payload);
+        verify(mKey, times(0)).decryptData(any());
     }
 
     @Test
-    public void testEncryptionHandshake_Association_wrongInitHandshakeMessage()
+    public void processMessage_decryptsEncryptedMessage() throws SignatureException {
+        byte[] payload = ByteUtils.randomBytes(10);
+        DeviceMessage message = new DeviceMessage(UUID.randomUUID(), /* isEncrypted= */ true,
+                payload);
+        mSecureBleChannel.processMessage(message);
+        verify(mKey).decryptData(any());
+    }
+
+    @Test
+    public void processMessage_onMessageReceivedErrorForEncryptedMessageWithNoKey()
             throws InterruptedException {
         Semaphore semaphore = new Semaphore(0);
-        ChannelCallback callbackSpy = spy(new ChannelCallback(semaphore));
-        setUpSecureBleChannel_Association(callbackSpy);
+        DeviceMessage message = new DeviceMessage(UUID.randomUUID(), /* isEncrypted= */ true,
+                ByteUtils.randomBytes(10));
 
-        sendDeviceId();
-        assertThat(semaphore.tryAcquire(100, TimeUnit.MILLISECONDS)).isTrue();
-
-        // Wrong init handshake message
-        respondToContinueMessage();
-        assertThat(semaphore.tryAcquire(100, TimeUnit.MILLISECONDS)).isTrue();
-        verify(callbackSpy).onEstablishSecureChannelFailure(
-                eq(SecureBleChannel.CHANNEL_ERROR_INVALID_HANDSHAKE)
-        );
+        mSecureBleChannel.setEncryptionKey(null);
+        mSecureBleChannel.registerCallback(new Callback() {
+            @Override
+            public void onMessageReceivedError(Exception exception) {
+                semaphore.release();
+            }
+        });
+        mSecureBleChannel.processMessage(message);
+        assertThat(tryAcquire(semaphore)).isTrue();
+        assertThat(message.getMessage()).isNull();
     }
 
     @Test
-    public void testEncryptionHandshake_Association_wrongRespondToContinueMessage()
+    public void onMessageReceived_onEstablishSecureChannelFailureBadHandshakeMessage()
             throws InterruptedException {
         Semaphore semaphore = new Semaphore(0);
-        ChannelCallback callbackSpy = spy(new ChannelCallback(semaphore));
-        setUpSecureBleChannel_Association(callbackSpy);
+        DeviceMessage message = new DeviceMessage(UUID.randomUUID(), /* isEncrypted= */ true,
+                ByteUtils.randomBytes(10));
 
-        sendDeviceId();
-        assertThat(semaphore.tryAcquire(100, TimeUnit.MILLISECONDS)).isTrue();
-
-        initHandshakeMessage();
-
-        // Wrong respond to continue message
-        initHandshakeMessage();
-        assertThat(semaphore.tryAcquire(100, TimeUnit.MILLISECONDS)).isTrue();
-        verify(callbackSpy).onEstablishSecureChannelFailure(
-                eq(SecureBleChannel.CHANNEL_ERROR_INVALID_HANDSHAKE)
-        );
+        mSecureBleChannel.setEncryptionKey(null);
+        mSecureBleChannel.registerCallback(new Callback() {
+            @Override
+            public void onEstablishSecureChannelFailure(int error) {
+                assertThat(error).isEqualTo(CHANNEL_ERROR_INVALID_HANDSHAKE);
+                semaphore.release();
+            }
+        });
+        mSecureBleChannel.onMessageReceived(message, ENCRYPTION_HANDSHAKE);
+        assertThat(tryAcquire(semaphore)).isTrue();
     }
 
-    private void setUpSecureBleChannel_Association(ChannelCallback callback) {
-        mChannel = new SecureBleChannel(
-                mStreamMock,
-                mStorageMock,
-                /* isReconnect = */ false,
-                EncryptionRunnerFactory.newDummyRunner()
-        );
-        mChannel.registerCallback(callback);
-        mChannel.setShowVerificationCodeListener(mShowVerificationCodeListenerMock);
-        ArgumentCaptor<MessageReceivedListener> listenerCaptor =
-                ArgumentCaptor.forClass(MessageReceivedListener.class);
-        verify(mStreamMock).setMessageReceivedListener(listenerCaptor.capture());
-        mMessageReceivedListener = listenerCaptor.getValue();
+    @Test
+    public void onMessageReceived_onMessageReceivedNotIssuedForNullMessage()
+            throws InterruptedException {
+        Semaphore semaphore = new Semaphore(0);
+        DeviceMessage message = new DeviceMessage(UUID.randomUUID(), /* isEncrypted= */ false,
+                /* message= */ null);
+
+        mSecureBleChannel.registerCallback(new Callback() {
+            @Override
+            public void onMessageReceived(DeviceMessage message) {
+                semaphore.release();
+            }
+        });
+        mSecureBleChannel.onMessageReceived(message, CLIENT_MESSAGE);
+        assertThat(tryAcquire(semaphore)).isFalse();
     }
 
-    private void sendDeviceId() {
-        DeviceMessage message = new DeviceMessage(
-                /* recipient = */ null,
-                /* isMessageEncrypted = */ false,
-                ByteUtils.uuidToBytes(CLIENT_DEVICE_ID)
-        );
-        mMessageReceivedListener.onMessageReceived(message, OperationType.ENCRYPTION_HANDSHAKE);
+    @Test
+    public void onMessageReceived_processHandshakeExceptionIssuesSecureChannelFailureCallback()
+            throws InterruptedException {
+        SecureBleChannel secureChannel = new SecureBleChannel(mMockStream,
+                EncryptionRunnerFactory.newDummyRunner()) {
+            @Override
+            void processHandshake(byte[] message) throws HandshakeException {
+                DummyEncryptionRunner.throwHandshakeException("test");
+            }
+        };
+        Semaphore semaphore = new Semaphore(0);
+        secureChannel.registerCallback(new Callback() {
+            @Override
+            public void onEstablishSecureChannelFailure(int error) {
+                semaphore.release();
+            }
+        });
+        DeviceMessage message = new DeviceMessage(UUID.randomUUID(), /* isEncrypted= */ true,
+                /* message= */ ByteUtils.randomBytes(10));
+
+        secureChannel.onMessageReceived(message, ENCRYPTION_HANDSHAKE);
+        assertThat(tryAcquire(semaphore)).isTrue();
     }
 
-    private void initHandshakeMessage() {
-        DeviceMessage message = new DeviceMessage(
-                /* recipient = */ null,
-                /* isMessageEncrypted = */ false,
-                DummyEncryptionRunner.INIT.getBytes()
-        );
-        mMessageReceivedListener.onMessageReceived(message, OperationType.ENCRYPTION_HANDSHAKE);
-    }
-
-    private void respondToContinueMessage() {
-        DeviceMessage message = new DeviceMessage(
-                /* recipient = */ null,
-                /* isMessageEncrypted = */ false,
-                DummyEncryptionRunner.CLIENT_RESPONSE.getBytes()
-        );
-        mMessageReceivedListener.onMessageReceived(message, OperationType.ENCRYPTION_HANDSHAKE);
-    }
-
-    /**
-     * Add the thread control logic into {@link SecureBleChannel.Callback} only for spy purpose.
-     *
-     * <p>The callback will release the semaphore which hold by one test when this callback
-     * is called, telling the test that it can verify certain behaviors which will only occurred
-     * after the callback is notified. This is needed mainly because of the callback is notified
-     * in a different thread.
-     */
-    class ChannelCallback implements SecureBleChannel.Callback {
-        private final Semaphore mSemaphore;
-        ChannelCallback(Semaphore semaphore) {
-            mSemaphore = semaphore;
-        }
-        @Override
-        public void onSecureChannelEstablished() {
-            mSemaphore.release();
-        }
-
-        @Override
-        public void onEstablishSecureChannelFailure(int error) {
-            mSemaphore.release();
-        }
-
-        @Override
-        public void onMessageReceived(DeviceMessage deviceMessage) {
-            mSemaphore.release();
-        }
-
-        @Override
-        public void onMessageReceivedError(Exception exception) {
-            mSemaphore.release();
-        }
-
-        @Override
-        public void onDeviceIdReceived(String deviceId) {
-            mSemaphore.release();
-        }
+    private boolean tryAcquire(Semaphore semaphore) throws InterruptedException {
+        return semaphore.tryAcquire(100, TimeUnit.MILLISECONDS);
     }
 }
diff --git a/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/storage/ConnectedDeviceStorageTest.java b/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/storage/ConnectedDeviceStorageTest.java
index 9547bfb..755ce64 100644
--- a/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/storage/ConnectedDeviceStorageTest.java
+++ b/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/storage/ConnectedDeviceStorageTest.java
@@ -18,6 +18,8 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.testng.Assert.assertThrows;
+
 import android.content.Context;
 import android.util.Pair;
 
@@ -32,6 +34,7 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.security.InvalidParameterException;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.UUID;
@@ -126,6 +129,15 @@
         assertThat(mConnectedDeviceStorage.getEncryptionKey(UUID.randomUUID().toString())).isNull();
     }
 
+    @Test
+    public void saveChallengeSecret_throwsForInvalidLengthSecret() {
+        byte[] invalidSecret =
+                ByteUtils.randomBytes(ConnectedDeviceStorage.CHALLENGE_SECRET_BYTES - 1);
+        assertThrows(InvalidParameterException.class,
+                () -> mConnectedDeviceStorage.saveChallengeSecret(UUID.randomUUID().toString(),
+                        invalidSecret));
+    }
+
     private AssociatedDevice addRandomAssociatedDevice(int userId) {
         AssociatedDevice device = new AssociatedDevice(UUID.randomUUID().toString(),
                 "00:00:00:00:00:00", "Test Device", true);
diff --git a/encryption-runner/Android.bp b/encryption-runner/Android.bp
new file mode 100644
index 0000000..2522d2d
--- /dev/null
+++ b/encryption-runner/Android.bp
@@ -0,0 +1,31 @@
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+android_library {
+    name: "encryption-runner",
+    min_sdk_version: "23",
+    product_variables: {
+        pdk: {
+            enabled: false,
+        },
+    },
+    static_libs: [
+      "ukey2",
+    ],
+    srcs: [
+        "src/**/*.java",
+    ],
+    installable: true,
+}
+
diff --git a/encryption-runner/AndroidManifest.xml b/encryption-runner/AndroidManifest.xml
new file mode 100644
index 0000000..0d2f71e
--- /dev/null
+++ b/encryption-runner/AndroidManifest.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+        package="android.car.encryptionrunner" >
+    <uses-sdk android:minSdkVersion="23" android:targetSdkVersion="23" />
+</manifest>
diff --git a/encryption-runner/src/android/car/encryptionrunner/DummyEncryptionRunner.java b/encryption-runner/src/android/car/encryptionrunner/DummyEncryptionRunner.java
new file mode 100644
index 0000000..d247967
--- /dev/null
+++ b/encryption-runner/src/android/car/encryptionrunner/DummyEncryptionRunner.java
@@ -0,0 +1,204 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.car.encryptionrunner;
+
+import android.annotation.IntDef;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * An encryption runner that doesn't actually do encryption. Useful for debugging. Do not use in
+ * production environments.
+ */
+@VisibleForTesting
+public class DummyEncryptionRunner implements EncryptionRunner {
+
+    private static final String KEY = "key";
+    private static final byte[] DUMMY_MESSAGE = "Dummy Message".getBytes();
+    @VisibleForTesting
+    public static final String INIT = "init";
+    @VisibleForTesting
+    public static final String INIT_RESPONSE = "initResponse";
+    @VisibleForTesting
+    public static final String CLIENT_RESPONSE = "clientResponse";
+    public static final String VERIFICATION_CODE = "1234";
+
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({Mode.UNKNOWN, Mode.CLIENT, Mode.SERVER})
+    private @interface Mode {
+
+        int UNKNOWN = 0;
+        int CLIENT = 1;
+        int SERVER = 2;
+    }
+
+    private boolean mIsReconnect;
+    private boolean mInitReconnectVerification;
+    private Key mCurrentDummyKey;
+    @Mode
+    private int mMode;
+    @HandshakeMessage.HandshakeState
+    private int mState;
+
+    @Override
+    public HandshakeMessage initHandshake() {
+        checkRunnerIsNew();
+        mMode = Mode.CLIENT;
+        mState = HandshakeMessage.HandshakeState.IN_PROGRESS;
+        return HandshakeMessage.newBuilder()
+                .setHandshakeState(mState)
+                .setNextMessage(INIT.getBytes())
+                .build();
+    }
+
+    @Override
+    public HandshakeMessage respondToInitRequest(byte[] initializationRequest)
+            throws HandshakeException {
+        checkRunnerIsNew();
+        mMode = Mode.SERVER;
+        if (!new String(initializationRequest).equals(INIT)) {
+            throw new HandshakeException("Unexpected initialization request");
+        }
+        mState = HandshakeMessage.HandshakeState.IN_PROGRESS;
+        return HandshakeMessage.newBuilder()
+                .setHandshakeState(HandshakeMessage.HandshakeState.IN_PROGRESS)
+                .setNextMessage(INIT_RESPONSE.getBytes())
+                .build();
+    }
+
+    private void checkRunnerIsNew() {
+        if (mState != HandshakeMessage.HandshakeState.UNKNOWN) {
+            throw new IllegalStateException("runner already initialized.");
+        }
+    }
+
+    @Override
+    public HandshakeMessage continueHandshake(byte[] response) throws HandshakeException {
+        if (mState != HandshakeMessage.HandshakeState.IN_PROGRESS) {
+            throw new HandshakeException("not waiting for response but got one");
+        }
+        switch (mMode) {
+            case Mode.SERVER:
+                if (!CLIENT_RESPONSE.equals(new String(response))) {
+                    throw new HandshakeException("unexpected response: " + new String(response));
+                }
+                mState = HandshakeMessage.HandshakeState.VERIFICATION_NEEDED;
+                if (mIsReconnect) {
+                    verifyPin();
+                    mState = HandshakeMessage.HandshakeState.RESUMING_SESSION;
+                }
+                return HandshakeMessage.newBuilder()
+                        .setVerificationCode(VERIFICATION_CODE)
+                        .setHandshakeState(mState)
+                        .build();
+            case Mode.CLIENT:
+                if (!INIT_RESPONSE.equals(new String(response))) {
+                    throw new HandshakeException("unexpected response: " + new String(response));
+                }
+                mState = HandshakeMessage.HandshakeState.VERIFICATION_NEEDED;
+                if (mIsReconnect) {
+                    verifyPin();
+                    mState = HandshakeMessage.HandshakeState.RESUMING_SESSION;
+                }
+                return HandshakeMessage.newBuilder()
+                        .setHandshakeState(mState)
+                        .setNextMessage(CLIENT_RESPONSE.getBytes())
+                        .setVerificationCode(VERIFICATION_CODE)
+                        .build();
+            default:
+                throw new IllegalStateException("unexpected role: " + mMode);
+        }
+    }
+
+    @Override
+    public HandshakeMessage authenticateReconnection(byte[] message, byte[] previousKey)
+            throws HandshakeException {
+        mCurrentDummyKey = new DummyKey();
+        // Blindly verify the reconnection because this is a dummy encryption runner.
+        return HandshakeMessage.newBuilder()
+                .setHandshakeState(HandshakeMessage.HandshakeState.FINISHED)
+                .setKey(mCurrentDummyKey)
+                .setNextMessage(mInitReconnectVerification ? null : DUMMY_MESSAGE)
+                .build();
+    }
+
+    @Override
+    public HandshakeMessage initReconnectAuthentication(byte[] previousKey)
+            throws HandshakeException {
+        mInitReconnectVerification = true;
+        mState = HandshakeMessage.HandshakeState.RESUMING_SESSION;
+        return HandshakeMessage.newBuilder()
+                .setHandshakeState(mState)
+                .setNextMessage(DUMMY_MESSAGE)
+                .build();
+    }
+
+    @Override
+    public Key keyOf(byte[] serialized) {
+        return new DummyKey();
+    }
+
+    @Override
+    public HandshakeMessage verifyPin() throws HandshakeException {
+        if (mState != HandshakeMessage.HandshakeState.VERIFICATION_NEEDED) {
+            throw new IllegalStateException("asking to verify pin, state = " + mState);
+        }
+        mState = HandshakeMessage.HandshakeState.FINISHED;
+        return HandshakeMessage.newBuilder().setKey(new DummyKey()).setHandshakeState(
+                mState).build();
+    }
+
+    @Override
+    public void invalidPin() {
+        mState = HandshakeMessage.HandshakeState.INVALID;
+    }
+
+    @Override
+    public void setIsReconnect(boolean isReconnect) {
+        mIsReconnect = isReconnect;
+    }
+
+    /** Method to throw a HandshakeException for testing. */
+    public static void throwHandshakeException(String message) throws HandshakeException {
+        throw new HandshakeException(message);
+    }
+
+    private class DummyKey implements Key {
+        @Override
+        public byte[] asBytes() {
+            return KEY.getBytes();
+        }
+
+        @Override
+        public byte[] encryptData(byte[] data) {
+            return data;
+        }
+
+        @Override
+        public byte[] decryptData(byte[] encryptedData) {
+            return encryptedData;
+        }
+
+        @Override
+        public byte[] getUniqueSession() {
+            return KEY.getBytes();
+        }
+    }
+}
diff --git a/encryption-runner/src/android/car/encryptionrunner/EncryptionRunner.java b/encryption-runner/src/android/car/encryptionrunner/EncryptionRunner.java
new file mode 100644
index 0000000..5721218
--- /dev/null
+++ b/encryption-runner/src/android/car/encryptionrunner/EncryptionRunner.java
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.car.encryptionrunner;
+
+import android.annotation.NonNull;
+
+/**
+ * A generalized interface that allows for generating shared secrets as well as encrypting
+ * messages.
+ *
+ * To use this interface:
+ *
+ * <p>1. As a client.
+ *
+ * {@code
+ * HandshakeMessage initialClientMessage = clientRunner.initHandshake();
+ * sendToServer(initialClientMessage.getNextMessage());
+ * byte message = getServerResponse();
+ * HandshakeMessage message = clientRunner.continueHandshake(message);
+ * }
+ *
+ * <p>If it is a first-time connection,
+ *
+ * {@code message.getHandshakeState()} should be VERIFICATION_NEEDED, show user the verification
+ * code and ask to verify.
+ * After user confirmed, {@code HandshakeMessage lastMessage = clientRunner.verifyPin();} otherwise
+ * {@code clientRunner.invalidPin(); }
+ *
+ * Use {@code lastMessage.getKey()} to get the key for encryption.
+ *
+ * <p>If it is a reconnection,
+ *
+ * {@code message.getHandshakeState()} should be RESUMING_SESSION, PIN has been verified blindly,
+ * send the authentication message over to server, then authenticate the message from server.
+ *
+ * {@code
+ * clientMessage = clientRunner.initReconnectAuthentication(previousKey)
+ * sendToServer(clientMessage.getNextMessage());
+ * HandshakeMessage lastMessage = clientRunner.authenticateReconnection(previousKey, message)
+ * }
+ *
+ * {@code lastMessage.getHandshakeState()} should be FINISHED if reconnection handshake is done.
+ *
+ * <p>2. As a server.
+ *
+ * {@code
+ * byte[] initialMessage = getClientMessageBytes();
+ * HandshakeMessage message = serverRunner.respondToInitRequest(initialMessage);
+ * sendToClient(message.getNextMessage());
+ * byte[] clientMessage = getClientResponse();
+ * HandshakeMessage message = serverRunner.continueHandshake(clientMessage);}
+ *
+ * <p>if it is a first-time connection,
+ *
+ * {@code message.getHandshakeState()} should be VERIFICATION_NEEDED, show user the verification
+ * code and ask to verify.
+ * After PIN is confirmed, {@code HandshakeMessage lastMessage = serverRunner.verifyPin}, otherwise
+ * {@code clientRunner.invalidPin(); }
+ * Use {@code lastMessage.getKey()} to get the key for encryption.
+ *
+ * <p>If it is a reconnection,
+ *
+ * {@code message.getHandshakeState()} should be RESUMING_SESSION,PIN has been verified blindly,
+ * waiting for client message.
+ * After client message been received,
+ * {@code serverMessage = serverRunner.authenticateReconnection(previousKey, message);
+ * sendToClient(serverMessage.getNextMessage());}
+ * {@code serverMessage.getHandshakeState()} should be FINISHED if reconnection handshake is done.
+ *
+ * Also see {@link EncryptionRunnerTest} for examples.
+ */
+public interface EncryptionRunner {
+
+    String TAG = "EncryptionRunner";
+
+    /**
+     * Starts an encryption handshake.
+     *
+     * @return A handshake message with information about the handshake that is started.
+     */
+    @NonNull
+    HandshakeMessage initHandshake();
+
+    /**
+     * Starts an encryption handshake where the device that is being communicated with already
+     * initiated the request.
+     *
+     * @param initializationRequest the bytes that the other device sent over.
+     * @return a handshake message with information about the handshake.
+     * @throws HandshakeException if initialization request is invalid.
+     */
+    @NonNull
+    HandshakeMessage respondToInitRequest(@NonNull byte[] initializationRequest)
+            throws HandshakeException;
+
+    /**
+     * Continues a handshake after receiving another response from the connected device.
+     *
+     * @param response the response from the other device.
+     * @return a message that can be used to continue the handshake.
+     * @throws HandshakeException if unexpected bytes in response.
+     */
+    @NonNull
+    HandshakeMessage continueHandshake(@NonNull byte[] response) throws HandshakeException;
+
+    /**
+     * Verifies the pin shown to the user. The result is the next handshake message and will
+     * typically contain an encryption key.
+     *
+     * @throws HandshakeException if not in state to verify pin.
+     */
+    @NonNull
+    HandshakeMessage verifyPin() throws HandshakeException;
+
+    /**
+     * Notifies the encryption runner that the user failed to validate the pin. After calling this
+     * method the runner should not be used, and will throw exceptions.
+     */
+    void invalidPin();
+
+    /**
+     * Verifies the reconnection message.
+     *
+     * <p>The message passed to this method should have been generated by
+     * {@link #initReconnectAuthentication(byte[] previousKey)}.
+     *
+     * <p>If the message is valid, then a {@link HandshakeMessage} will be returned that contains
+     * the encryption key and a handshake message which can be used to verify the other side of the
+     * connection.
+     *
+     * @param previousKey previously stored key.
+     * @param message     message from the client
+     * @return a handshake message with an encryption key if verification succeed.
+     * @throws HandshakeException if the message does not match.
+     */
+    @NonNull
+    HandshakeMessage authenticateReconnection(@NonNull byte[] message, @NonNull byte[] previousKey)
+            throws HandshakeException;
+
+    /**
+     * Initiates the reconnection verification by generating a message that should be sent to the
+     * device that is being reconnected to.
+     *
+     * @param previousKey previously stored key.
+     * @return a handshake message with client's message which will be sent to server.
+     * @throws HandshakeException when get encryption key's unique session fail.
+     */
+    @NonNull
+    HandshakeMessage initReconnectAuthentication(@NonNull byte[] previousKey)
+            throws HandshakeException;
+
+    /**
+     * De-serializes a previously serialized key generated by an instance of this encryption runner.
+     *
+     * @param serialized the serialized bytes of the key.
+     * @return the Key object used for encryption.
+     */
+    @NonNull
+    Key keyOf(@NonNull byte[] serialized);
+
+    /**
+     * Set the signal if it is a reconnection process.
+     *
+     * @param isReconnect {@code true} if it is a reconnect.
+     */
+    void setIsReconnect(boolean isReconnect);
+}
diff --git a/encryption-runner/src/android/car/encryptionrunner/EncryptionRunnerFactory.java b/encryption-runner/src/android/car/encryptionrunner/EncryptionRunnerFactory.java
new file mode 100644
index 0000000..d11ed4e
--- /dev/null
+++ b/encryption-runner/src/android/car/encryptionrunner/EncryptionRunnerFactory.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.car.encryptionrunner;
+
+import android.annotation.IntDef;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+/**
+ * Factory that creates encryption runner.
+ */
+public class EncryptionRunnerFactory {
+
+    private EncryptionRunnerFactory() {
+        // prevent instantiation.
+    }
+
+    @IntDef({EncryptionRunnerType.UKEY2})
+    public @interface EncryptionRunnerType {
+        /** Use Ukey2 as underlying key exchange. */
+        int UKEY2 = 0;
+    }
+
+    /**
+     * Creates a new {@link EncryptionRunner} based on {@param type}.
+     */
+    public static EncryptionRunner newRunner(@EncryptionRunnerType int type) {
+        switch (type) {
+            case EncryptionRunnerType.UKEY2:
+                return new Ukey2EncryptionRunner();
+            default:
+                throw new IllegalArgumentException("Unknown EncryptionRunnerType: " + type);
+        }
+    }
+
+    /**
+     * Creates a new {@link EncryptionRunner}.
+     *
+     * @deprecated Use {@link #newRunner(int)} instead.
+     */
+    @Deprecated
+    public static EncryptionRunner newRunner() {
+        return newRunner(EncryptionRunnerType.UKEY2);
+    }
+
+    /**
+     * Creates a new {@link EncryptionRunner} that doesn't actually do encryption but is useful
+     * for testing.
+     */
+    @VisibleForTesting
+    public static EncryptionRunner newDummyRunner() {
+        return new DummyEncryptionRunner();
+    }
+}
diff --git a/encryption-runner/src/android/car/encryptionrunner/HandshakeException.java b/encryption-runner/src/android/car/encryptionrunner/HandshakeException.java
new file mode 100644
index 0000000..934a83a
--- /dev/null
+++ b/encryption-runner/src/android/car/encryptionrunner/HandshakeException.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.car.encryptionrunner;
+
+/**
+ * Exception indicating an error during a Handshake of EncryptionRunner.
+ */
+public class HandshakeException extends Exception {
+
+    HandshakeException(String message) {
+        super(message);
+    }
+
+    HandshakeException(Exception e) {
+        super(e);
+    }
+}
diff --git a/encryption-runner/src/android/car/encryptionrunner/HandshakeMessage.java b/encryption-runner/src/android/car/encryptionrunner/HandshakeMessage.java
new file mode 100644
index 0000000..d7c9765
--- /dev/null
+++ b/encryption-runner/src/android/car/encryptionrunner/HandshakeMessage.java
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.car.encryptionrunner;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.text.TextUtils;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * During an {@link EncryptionRunner} handshake process, these are the messages returned as part
+ * of each step.
+ */
+public class HandshakeMessage {
+
+    /**
+     * States for handshake progress.
+     */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({HandshakeState.UNKNOWN, HandshakeState.IN_PROGRESS, HandshakeState.VERIFICATION_NEEDED,
+            HandshakeState.FINISHED, HandshakeState.INVALID, HandshakeState.RESUMING_SESSION,
+            HandshakeState.OOB_VERIFICATION_NEEDED})
+    public @interface HandshakeState {
+        /**
+         * The initial state, this value is not expected to be returned.
+         */
+        int UNKNOWN = 0;
+        /**
+         * The handshake is in progress.
+         */
+        int IN_PROGRESS = 1;
+        /**
+         * The handshake is complete, but verification of the code is needed.
+         */
+        int VERIFICATION_NEEDED = 2;
+        /**
+         * The handshake is complete.
+         */
+        int FINISHED = 3;
+        /**
+         * The handshake is complete and not successful.
+         */
+        int INVALID = 4;
+        /**
+         * The handshake is complete, but extra verification is needed.
+         */
+        int RESUMING_SESSION = 5;
+        /**
+         * The handshake is complete, but out of band verification of the code is needed.
+         */
+        int OOB_VERIFICATION_NEEDED = 6;
+    }
+
+    @HandshakeState
+    private final int mHandshakeState;
+    private final Key mKey;
+    private final byte[] mNextMessage;
+    private final String mVerificationCode;
+    private final byte[] mOobVerificationCode;
+
+    /**
+     * @return Returns a builder for {@link HandshakeMessage}.
+     */
+    public static Builder newBuilder() {
+        return new Builder();
+    }
+
+    /**
+     * Use the builder;
+     */
+    private HandshakeMessage(
+            @HandshakeState int handshakeState,
+            @Nullable Key key,
+            @Nullable byte[] nextMessage,
+            @Nullable String verificationCode,
+            @Nullable byte[] oobVerificationCode) {
+        mHandshakeState = handshakeState;
+        mKey = key;
+        mNextMessage = nextMessage;
+        mVerificationCode = verificationCode;
+        mOobVerificationCode = oobVerificationCode;
+    }
+
+    /**
+     * Returns the next message to send in a handshake.
+     */
+    @Nullable
+    public byte[] getNextMessage() {
+        return mNextMessage == null ? null : mNextMessage.clone();
+    }
+
+    /**
+     * Returns the state of the handshake.
+     */
+    @HandshakeState
+    public int getHandshakeState() {
+        return mHandshakeState;
+    }
+
+    /**
+     * Returns the encryption key that can be used to encrypt data.
+     */
+    @Nullable
+    public Key getKey() {
+        return mKey;
+    }
+
+    /**
+     * Returns a verification code to show to the user.
+     */
+    @Nullable
+    public String getVerificationCode() {
+        return mVerificationCode;
+    }
+
+    /**
+     * Returns a verification code to be encrypted using an out-of-band key and sent to the remote
+     * device.
+     */
+    @Nullable
+    public byte[] getOobVerificationCode() {
+        return mOobVerificationCode;
+    }
+
+    static class Builder {
+        @HandshakeState
+        int mHandshakeState;
+        Key mKey;
+        byte[] mNextMessage;
+        String mVerificationCode;
+        byte[] mOobVerificationCode;
+
+        Builder setHandshakeState(@HandshakeState int handshakeState) {
+            mHandshakeState = handshakeState;
+            return this;
+        }
+
+        Builder setKey(@Nullable Key key) {
+            mKey = key;
+            return this;
+        }
+
+        Builder setNextMessage(@Nullable byte[] nextMessage) {
+            mNextMessage = nextMessage == null ? null : nextMessage.clone();
+            return this;
+        }
+
+        Builder setVerificationCode(@Nullable String verificationCode) {
+            mVerificationCode = verificationCode;
+            return this;
+        }
+
+        Builder setOobVerificationCode(@NonNull byte[] oobVerificationCode) {
+            mOobVerificationCode = oobVerificationCode;
+            return this;
+        }
+
+        HandshakeMessage build() {
+            if (mHandshakeState == HandshakeState.UNKNOWN) {
+                throw new IllegalStateException("must set handshake state before calling build");
+            }
+            if (mHandshakeState == HandshakeState.VERIFICATION_NEEDED
+                    && TextUtils.isEmpty(mVerificationCode)) {
+                throw new IllegalStateException(
+                        "State is verification needed, but verification code null.");
+            }
+            if (mHandshakeState == HandshakeState.OOB_VERIFICATION_NEEDED
+                    && (mOobVerificationCode == null || mOobVerificationCode.length == 0)) {
+                throw new IllegalStateException(
+                        "State is OOB verification needed, but OOB verification code null.");
+            }
+            return new HandshakeMessage(mHandshakeState, mKey, mNextMessage, mVerificationCode,
+                    mOobVerificationCode);
+        }
+
+    }
+}
diff --git a/encryption-runner/src/android/car/encryptionrunner/Key.java b/encryption-runner/src/android/car/encryptionrunner/Key.java
new file mode 100644
index 0000000..e13585f
--- /dev/null
+++ b/encryption-runner/src/android/car/encryptionrunner/Key.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.car.encryptionrunner;
+
+import android.annotation.NonNull;
+
+import java.security.NoSuchAlgorithmException;
+import java.security.SignatureException;
+
+/**
+ * Represents a serializable encryption key.
+ */
+public interface Key {
+    /**
+     * Returns a serialized encryption key.
+     */
+    @NonNull
+    byte[] asBytes();
+
+    /**
+     * Encrypts data using this key.
+     *
+     * @param data the data to be encrypted
+     * @return the encrypted data.
+     */
+    @NonNull
+    byte[] encryptData(@NonNull byte[] data);
+
+    /**
+     * Decrypts data using this key.
+     *
+     * @param encryptedData The encrypted data.
+     * @return decrypted data.
+     * @throws SignatureException if encrypted data is not properly signed.
+     */
+    @NonNull
+    byte[] decryptData(@NonNull byte[] encryptedData) throws SignatureException;
+
+    /**
+     * Returns a cryptographic digest of the key.
+     *
+     * @throws NoSuchAlgorithmException when a unique session can not be created.
+     */
+    @NonNull
+    byte[] getUniqueSession() throws NoSuchAlgorithmException;
+}
diff --git a/encryption-runner/src/android/car/encryptionrunner/Ukey2EncryptionRunner.java b/encryption-runner/src/android/car/encryptionrunner/Ukey2EncryptionRunner.java
new file mode 100644
index 0000000..f4ee5a7
--- /dev/null
+++ b/encryption-runner/src/android/car/encryptionrunner/Ukey2EncryptionRunner.java
@@ -0,0 +1,405 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.car.encryptionrunner;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.util.Log;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import com.google.security.cryptauth.lib.securegcm.D2DConnectionContext;
+import com.google.security.cryptauth.lib.securegcm.Ukey2Handshake;
+import com.google.security.cryptauth.lib.securemessage.CryptoOps;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.security.InvalidKeyException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.SignatureException;
+
+import javax.crypto.spec.SecretKeySpec;
+
+/**
+ * An {@link EncryptionRunner} that uses Ukey2 as the underlying implementation.
+ */
+public class Ukey2EncryptionRunner implements EncryptionRunner {
+
+    private static final Ukey2Handshake.HandshakeCipher CIPHER =
+            Ukey2Handshake.HandshakeCipher.P256_SHA512;
+    private static final int RESUME_HMAC_LENGTH = 32;
+    private static final byte[] RESUME = "RESUME".getBytes();
+    private static final byte[] SERVER = "SERVER".getBytes();
+    private static final byte[] CLIENT = "CLIENT".getBytes();
+    private static final int AUTH_STRING_LENGTH = 6;
+
+    @IntDef({Mode.UNKNOWN, Mode.CLIENT, Mode.SERVER})
+    private @interface Mode {
+        int UNKNOWN = 0;
+        int CLIENT = 1;
+        int SERVER = 2;
+    }
+
+    private Ukey2Handshake mUkey2client;
+    private boolean mRunnerIsInvalid;
+    private Key mCurrentKey;
+    private byte[] mCurrentUniqueSesion;
+    private byte[] mPrevUniqueSesion;
+    private boolean mIsReconnect;
+    private boolean mInitReconnectionVerification;
+    @Mode
+    private int mMode = Mode.UNKNOWN;
+
+    @Override
+    public HandshakeMessage initHandshake() {
+        checkRunnerIsNew();
+        mMode = Mode.CLIENT;
+        try {
+            mUkey2client = Ukey2Handshake.forInitiator(CIPHER);
+            return HandshakeMessage.newBuilder()
+                    .setHandshakeState(getHandshakeState())
+                    .setNextMessage(mUkey2client.getNextHandshakeMessage())
+                    .build();
+        } catch (com.google.security.cryptauth.lib.securegcm.HandshakeException e) {
+            Log.e(TAG, "unexpected exception", e);
+            throw new RuntimeException(e);
+        }
+
+    }
+
+    @Override
+    public void setIsReconnect(boolean isReconnect) {
+        mIsReconnect = isReconnect;
+    }
+
+    @Override
+    public HandshakeMessage respondToInitRequest(byte[] initializationRequest)
+            throws HandshakeException {
+        checkRunnerIsNew();
+        mMode = Mode.SERVER;
+        try {
+            if (mUkey2client != null) {
+                throw new IllegalStateException("Cannot reuse encryption runners, "
+                        + "this one is already initialized");
+            }
+            mUkey2client = Ukey2Handshake.forResponder(CIPHER);
+            mUkey2client.parseHandshakeMessage(initializationRequest);
+            return HandshakeMessage.newBuilder()
+                    .setHandshakeState(getHandshakeState())
+                    .setNextMessage(mUkey2client.getNextHandshakeMessage())
+                    .build();
+
+        } catch (com.google.security.cryptauth.lib.securegcm.HandshakeException
+                | Ukey2Handshake.AlertException e) {
+            throw new HandshakeException(e);
+        }
+    }
+
+    private void checkRunnerIsNew() {
+        if (mUkey2client != null) {
+            throw new IllegalStateException("This runner is already initialized.");
+        }
+    }
+
+
+    @Override
+    public HandshakeMessage continueHandshake(byte[] response) throws HandshakeException {
+        checkInitialized();
+        try {
+            if (mUkey2client.getHandshakeState() != Ukey2Handshake.State.IN_PROGRESS) {
+                throw new IllegalStateException("handshake is not in progress, state ="
+                        + mUkey2client.getHandshakeState());
+            }
+            mUkey2client.parseHandshakeMessage(response);
+
+            // Not obvious from ukey2 api, but getting the next message can change the state.
+            // calling getNext message might go from in progress to verification needed, on
+            // the assumption that we already send this message to the peer.
+            byte[] nextMessage = null;
+            if (mUkey2client.getHandshakeState() == Ukey2Handshake.State.IN_PROGRESS) {
+                nextMessage = mUkey2client.getNextHandshakeMessage();
+            }
+            String verificationCode = null;
+            if (mUkey2client.getHandshakeState() == Ukey2Handshake.State.VERIFICATION_NEEDED) {
+                // getVerificationString() needs to be called before verifyPin().
+                verificationCode = generateReadablePairingCode(
+                        mUkey2client.getVerificationString(AUTH_STRING_LENGTH));
+                if (mIsReconnect) {
+                    HandshakeMessage handshakeMessage = verifyPin();
+                    return HandshakeMessage.newBuilder()
+                            .setHandshakeState(handshakeMessage.getHandshakeState())
+                            .setNextMessage(nextMessage)
+                            .build();
+                }
+            }
+            return HandshakeMessage.newBuilder()
+                    .setHandshakeState(getHandshakeState())
+                    .setNextMessage(nextMessage)
+                    .setVerificationCode(verificationCode)
+                    .build();
+        } catch (com.google.security.cryptauth.lib.securegcm.HandshakeException
+                | Ukey2Handshake.AlertException e) {
+            throw new HandshakeException(e);
+        }
+    }
+
+    /**
+     * Returns a human-readable pairing code string generated from the verification bytes. Converts
+     * each byte into a digit with a simple modulo.
+     *
+     * <p>This should match the implementation in the iOS and Android client libraries.
+     */
+    @VisibleForTesting
+    String generateReadablePairingCode(byte[] verificationCode) {
+        StringBuilder outString = new StringBuilder();
+        for (byte b : verificationCode) {
+            int unsignedInt = Byte.toUnsignedInt(b);
+            int digit = unsignedInt % 10;
+            outString.append(digit);
+        }
+
+        return outString.toString();
+    }
+
+    private static class UKey2Key implements Key {
+
+        private final D2DConnectionContext mConnectionContext;
+
+        UKey2Key(@NonNull D2DConnectionContext connectionContext) {
+            this.mConnectionContext = connectionContext;
+        }
+
+        @Override
+        public byte[] asBytes() {
+            return mConnectionContext.saveSession();
+        }
+
+        @Override
+        public byte[] encryptData(byte[] data) {
+            return mConnectionContext.encodeMessageToPeer(data);
+        }
+
+        @Override
+        public byte[] decryptData(byte[] encryptedData) throws SignatureException {
+            return mConnectionContext.decodeMessageFromPeer(encryptedData);
+        }
+
+        @Override
+        public byte[] getUniqueSession() throws NoSuchAlgorithmException {
+            return mConnectionContext.getSessionUnique();
+        }
+    }
+
+    @Override
+    public HandshakeMessage verifyPin() throws HandshakeException {
+        checkInitialized();
+        mUkey2client.verifyHandshake();
+        int state = getHandshakeState();
+        try {
+            mCurrentKey = new UKey2Key(mUkey2client.toConnectionContext());
+        } catch (com.google.security.cryptauth.lib.securegcm.HandshakeException e) {
+            throw new HandshakeException(e);
+        }
+        return HandshakeMessage.newBuilder()
+                .setHandshakeState(state)
+                .setKey(mCurrentKey)
+                .build();
+    }
+
+    /**
+     * <p>After getting message from the other device, authenticate the message with the previous
+     * stored key.
+     *
+     * If current device inits the reconnection authentication by calling {@code
+     * initReconnectAuthentication} and sends the message to the other device, the other device
+     * will call {@code authenticateReconnection()} with the received message and send its own
+     * message back to the init device. The init device will call {@code
+     * authenticateReconnection()} on the received message, but do not need to set the next
+     * message.
+     */
+    @Override
+    public HandshakeMessage authenticateReconnection(byte[] message, byte[] previousKey)
+            throws HandshakeException {
+        if (!mIsReconnect) {
+            throw new HandshakeException(
+                    "Reconnection authentication requires setIsReconnect(true)");
+        }
+        if (mCurrentKey == null) {
+            throw new HandshakeException("Current key is null, make sure verifyPin() is called.");
+        }
+        if (message.length != RESUME_HMAC_LENGTH) {
+            mRunnerIsInvalid = true;
+            throw new HandshakeException("Failing because (message.length =" + message.length
+                    + ") is not equal to " + RESUME_HMAC_LENGTH);
+        }
+        try {
+            mCurrentUniqueSesion = mCurrentKey.getUniqueSession();
+            mPrevUniqueSesion = keyOf(previousKey).getUniqueSession();
+        } catch (NoSuchAlgorithmException e) {
+            throw new HandshakeException(e);
+        }
+        switch (mMode) {
+            case Mode.SERVER:
+                if (!MessageDigest.isEqual(
+                        message, computeMAC(mPrevUniqueSesion, mCurrentUniqueSesion, CLIENT))) {
+                    mRunnerIsInvalid = true;
+                    throw new HandshakeException("Reconnection authentication failed.");
+                }
+                return HandshakeMessage.newBuilder()
+                        .setHandshakeState(HandshakeMessage.HandshakeState.FINISHED)
+                        .setKey(mCurrentKey)
+                        .setNextMessage(mInitReconnectionVerification ? null
+                                : computeMAC(mPrevUniqueSesion, mCurrentUniqueSesion, SERVER))
+                        .build();
+            case Mode.CLIENT:
+                if (!MessageDigest.isEqual(
+                        message, computeMAC(mPrevUniqueSesion, mCurrentUniqueSesion, SERVER))) {
+                    mRunnerIsInvalid = true;
+                    throw new HandshakeException("Reconnection authentication failed.");
+                }
+                return HandshakeMessage.newBuilder()
+                        .setHandshakeState(HandshakeMessage.HandshakeState.FINISHED)
+                        .setKey(mCurrentKey)
+                        .setNextMessage(mInitReconnectionVerification ? null
+                                : computeMAC(mPrevUniqueSesion, mCurrentUniqueSesion, CLIENT))
+                        .build();
+            default:
+                throw new IllegalStateException(
+                        "Encountered unexpected role during authenticateReconnection: " + mMode);
+        }
+    }
+
+    /**
+     * Both client and server can call this method to send authentication message to the other
+     * device.
+     */
+    @Override
+    public HandshakeMessage initReconnectAuthentication(byte[] previousKey)
+            throws HandshakeException {
+        if (!mIsReconnect) {
+            throw new HandshakeException(
+                    "Reconnection authentication requires setIsReconnect(true).");
+        }
+        if (mCurrentKey == null) {
+            throw new HandshakeException("Current key is null, make sure verifyPin() is called.");
+        }
+        mInitReconnectionVerification = true;
+        try {
+            mCurrentUniqueSesion = mCurrentKey.getUniqueSession();
+            mPrevUniqueSesion = keyOf(previousKey).getUniqueSession();
+        } catch (NoSuchAlgorithmException e) {
+            throw new HandshakeException(e);
+        }
+        switch (mMode) {
+            case Mode.SERVER:
+                return HandshakeMessage.newBuilder()
+                        .setHandshakeState(HandshakeMessage.HandshakeState.RESUMING_SESSION)
+                        .setNextMessage(computeMAC(mPrevUniqueSesion, mCurrentUniqueSesion, SERVER))
+                        .build();
+            case Mode.CLIENT:
+                return HandshakeMessage.newBuilder()
+                        .setHandshakeState(HandshakeMessage.HandshakeState.RESUMING_SESSION)
+                        .setNextMessage(computeMAC(mPrevUniqueSesion, mCurrentUniqueSesion, CLIENT))
+                        .build();
+            default:
+                throw new IllegalStateException(
+                        "Encountered unexpected role during authenticateReconnection: " + mMode);
+        }
+    }
+
+    protected final Ukey2Handshake getUkey2Client() {
+        return mUkey2client;
+    }
+
+    protected final boolean isReconnect() {
+        return mIsReconnect;
+    }
+
+    @HandshakeMessage.HandshakeState
+    private int getHandshakeState() {
+        checkInitialized();
+        switch (mUkey2client.getHandshakeState()) {
+            case ALREADY_USED:
+            case ERROR:
+                throw new IllegalStateException("unexpected error state");
+            case FINISHED:
+                if (mIsReconnect) {
+                    return HandshakeMessage.HandshakeState.RESUMING_SESSION;
+                }
+                return HandshakeMessage.HandshakeState.FINISHED;
+            case IN_PROGRESS:
+                return HandshakeMessage.HandshakeState.IN_PROGRESS;
+            case VERIFICATION_IN_PROGRESS:
+            case VERIFICATION_NEEDED:
+                return HandshakeMessage.HandshakeState.VERIFICATION_NEEDED;
+            default:
+                throw new IllegalStateException("unexpected handshake state");
+        }
+    }
+
+    @Override
+    public Key keyOf(byte[] serialized) {
+        return new UKey2Key(D2DConnectionContext.fromSavedSession(serialized));
+    }
+
+    @Override
+    public void invalidPin() {
+        mRunnerIsInvalid = true;
+    }
+
+    private UKey2Key checkIsUkey2Key(Key key) {
+        if (!(key instanceof UKey2Key)) {
+            throw new IllegalArgumentException("wrong key type");
+        }
+        return (UKey2Key) key;
+    }
+
+    protected void checkInitialized() {
+        if (mUkey2client == null) {
+            throw new IllegalStateException("runner not initialized");
+        }
+        if (mRunnerIsInvalid) {
+            throw new IllegalStateException("runner has been invalidated");
+        }
+    }
+
+    @Nullable
+    private byte[] computeMAC(byte[] previous, byte[] next, byte[] info) {
+        try {
+            SecretKeySpec inputKeyMaterial = new SecretKeySpec(
+                    concatByteArrays(previous, next), "" /* key type is just plain raw bytes */);
+            return CryptoOps.hkdf(inputKeyMaterial, RESUME, info);
+        } catch (NoSuchAlgorithmException | InvalidKeyException e) {
+            // Does not happen in practice
+            Log.e(TAG, "Compute MAC failed");
+            return null;
+        }
+    }
+
+    private static byte[] concatByteArrays(@NonNull byte[] a, @NonNull byte[] b) {
+        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+        try {
+            outputStream.write(a);
+            outputStream.write(b);
+        } catch (IOException e) {
+            return new byte[0];
+        }
+        return outputStream.toByteArray();
+    }
+}
diff --git a/glide/Android.mk b/glide/Android.mk
deleted file mode 100644
index 41e3937..0000000
--- a/glide/Android.mk
+++ /dev/null
@@ -1,52 +0,0 @@
-#
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_CLASS := JAVA_LIBRARIES
-LOCAL_MODULE := car-glide-disklrucache
-LOCAL_SDK_VERSION := current
-LOCAL_SRC_FILES := ../../../../../prebuilts/maven_repo/bumptech/com/github/bumptech/glide/disklrucache/SNAPSHOT/disklrucache-SNAPSHOT$(COMMON_JAVA_PACKAGE_SUFFIX)
-LOCAL_NOTICE_FILE := prebuilts/maven_repo/bumptech/LICENSE
-LOCAL_JETIFIER_ENABLED := true
-LOCAL_UNINSTALLABLE_MODULE := true
-
-include $(BUILD_PREBUILT)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_CLASS := JAVA_LIBRARIES
-LOCAL_MODULE := car-gifdecoder
-LOCAL_SDK_VERSION := current
-LOCAL_SRC_FILES := ../../../../../prebuilts/maven_repo/bumptech/com/github/bumptech/glide/gifdecoder/SNAPSHOT/gifdecoder-SNAPSHOT$(COMMON_JAVA_PACKAGE_SUFFIX)
-LOCAL_NOTICE_FILE := prebuilts/maven_repo/bumptech/LICENSE
-LOCAL_JETIFIER_ENABLED := true
-LOCAL_UNINSTALLABLE_MODULE := true
-
-include $(BUILD_PREBUILT)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_CLASS := JAVA_LIBRARIES
-LOCAL_MODULE := car-glide
-LOCAL_SDK_VERSION := current
-LOCAL_SRC_FILES := ../../../../../prebuilts/maven_repo/bumptech/com/github/bumptech/glide/glide/SNAPSHOT/glide-SNAPSHOT$(COMMON_JAVA_PACKAGE_SUFFIX)
-LOCAL_NOTICE_FILE := prebuilts/maven_repo/bumptech/LICENSE
-LOCAL_JETIFIER_ENABLED := true
-LOCAL_UNINSTALLABLE_MODULE := true
-
-include $(BUILD_PREBUILT)
\ No newline at end of file