Merge "camera: Correct 'availableSessionKeys' version"
diff --git a/authsecret/1.0/Android.bp b/authsecret/1.0/Android.bp
new file mode 100644
index 0000000..9cde99a
--- /dev/null
+++ b/authsecret/1.0/Android.bp
@@ -0,0 +1,17 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.authsecret@1.0",
+    root: "android.hardware",
+    vndk: {
+        enabled: true,
+    },
+    srcs: [
+        "IAuthSecret.hal",
+    ],
+    interfaces: [
+        "android.hidl.base@1.0",
+    ],
+    gen_java: true,
+}
+
diff --git a/authsecret/1.0/IAuthSecret.hal b/authsecret/1.0/IAuthSecret.hal
new file mode 100644
index 0000000..d2cb5da
--- /dev/null
+++ b/authsecret/1.0/IAuthSecret.hal
@@ -0,0 +1,48 @@
+/*
+ * 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 android.hardware.authsecret@1.0;
+
+/**
+ * This security HAL allows vendor components to be cryptographically tied to
+ * the primary user's credential. For example, security hardware could require
+ * proof that the credential is known before applying updates.
+ *
+ * This HAL is optional so does not require an implementation on device.
+ */
+interface IAuthSecret {
+    /**
+     * When the primary user correctly enters their credential, this method is
+     * passed a secret derived from that credential to prove that their
+     * credential is known.
+     *
+     * The first time this is called, the secret must be used to provision state
+     * that depends on the primary user's credential. The same secret is passed
+     * on each call until a factory reset after which there must be a new
+     * secret.
+     *
+     * The secret must be at lesat 16 bytes.
+     *
+     * @param secret blob derived from the primary user's credential.
+     */
+    primaryUserCredential(vec<uint8_t> secret);
+
+    /**
+     * Called from recovery during factory reset. The secret is now lost and can
+     * no longer be derived. Any data linked to the secret must be destroyed and
+     * any dependence on the secret must be removed.
+     */
+    factoryReset();
+};
diff --git a/authsecret/1.0/default/Android.bp b/authsecret/1.0/default/Android.bp
new file mode 100644
index 0000000..5c3234f
--- /dev/null
+++ b/authsecret/1.0/default/Android.bp
@@ -0,0 +1,21 @@
+cc_binary {
+    name: "android.hardware.authsecret@1.0-service",
+    init_rc: ["android.hardware.authsecret@1.0-service.rc"],
+    relative_install_path: "hw",
+    vendor: true,
+    srcs: [
+        "service.cpp",
+        "AuthSecret.cpp",
+    ],
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "liblog",
+        "libutils",
+        "android.hardware.authsecret@1.0",
+    ],
+}
diff --git a/authsecret/1.0/default/AuthSecret.cpp b/authsecret/1.0/default/AuthSecret.cpp
new file mode 100644
index 0000000..46a3ec1
--- /dev/null
+++ b/authsecret/1.0/default/AuthSecret.cpp
@@ -0,0 +1,47 @@
+#include "AuthSecret.h"
+
+namespace android {
+namespace hardware {
+namespace authsecret {
+namespace V1_0 {
+namespace implementation {
+
+// Methods from ::android::hardware::authsecret::V1_0::IAuthSecret follow.
+Return<void> AuthSecret::primaryUserCredential(const hidl_vec<uint8_t>& secret) {
+    (void)secret;
+
+    // To create a dependency on the credential, it is recommended to derive a
+    // different value from the provided secret for each purpose e.g.
+    //
+    //     purpose1_secret = hash( "purpose1" || secret )
+    //     purpose2_secret = hash( "purpose2" || secret )
+    //
+    // The derived values can then be used as cryptographic keys or stored
+    // securely for comparison in a future call.
+    //
+    // For example, a security module might require that the credential has been
+    // entered before it applies any updates. This can be achieved by storing a
+    // derived value in the module and only applying updates when the same
+    // derived value is presented again.
+    //
+    // This implementation does nothing.
+
+    return Void();
+}
+
+Return<void> AuthSecret::factoryReset() {
+    // Clear all dependency on the secret.
+    //
+    // With the example of updating a security module, the stored value must be
+    // cleared so that the new primary user enrolled as the approver of updates.
+    //
+    // This implementation does nothing as there is no dependence on the secret.
+
+    return Void();
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace authsecret
+}  // namespace hardware
+}  // namespace android
diff --git a/authsecret/1.0/default/AuthSecret.h b/authsecret/1.0/default/AuthSecret.h
new file mode 100644
index 0000000..edb49b8
--- /dev/null
+++ b/authsecret/1.0/default/AuthSecret.h
@@ -0,0 +1,36 @@
+#ifndef ANDROID_HARDWARE_AUTHSECRET_V1_0_AUTHSECRET_H
+#define ANDROID_HARDWARE_AUTHSECRET_V1_0_AUTHSECRET_H
+
+#include <android/hardware/authsecret/1.0/IAuthSecret.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace authsecret {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+struct AuthSecret : public IAuthSecret {
+    // Methods from ::android::hardware::authsecret::V1_0::IAuthSecret follow.
+    Return<void> primaryUserCredential(const hidl_vec<uint8_t>& secret) override;
+    Return<void> factoryReset() override;
+
+    // Methods from ::android::hidl::base::V1_0::IBase follow.
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace authsecret
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_AUTHSECRET_V1_0_AUTHSECRET_H
diff --git a/authsecret/1.0/default/android.hardware.authsecret@1.0-service.rc b/authsecret/1.0/default/android.hardware.authsecret@1.0-service.rc
new file mode 100644
index 0000000..e82da7e
--- /dev/null
+++ b/authsecret/1.0/default/android.hardware.authsecret@1.0-service.rc
@@ -0,0 +1,4 @@
+service vendor.authsecret-1-0 /vendor/bin/hw/android.hardware.authsecret@1.0-service
+    class hal
+    user system
+    group system
diff --git a/authsecret/1.0/default/service.cpp b/authsecret/1.0/default/service.cpp
new file mode 100644
index 0000000..4acd16c
--- /dev/null
+++ b/authsecret/1.0/default/service.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.1 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.1
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "android.hardware.authsecret@1.0-service"
+
+#include <android/hardware/authsecret/1.0/IAuthSecret.h>
+#include <hidl/HidlTransportSupport.h>
+
+#include "AuthSecret.h"
+
+using android::hardware::configureRpcThreadpool;
+using android::hardware::joinRpcThreadpool;
+using android::hardware::authsecret::V1_0::IAuthSecret;
+using android::hardware::authsecret::V1_0::implementation::AuthSecret;
+using android::sp;
+using android::status_t;
+using android::OK;
+
+int main() {
+    configureRpcThreadpool(1, true);
+
+    sp<IAuthSecret> authSecret = new AuthSecret;
+    status_t status = authSecret->registerAsService();
+    LOG_ALWAYS_FATAL_IF(status != OK, "Could not register IAuthSecret");
+
+    joinRpcThreadpool();
+    return 0;
+}
diff --git a/authsecret/1.0/vts/functional/Android.bp b/authsecret/1.0/vts/functional/Android.bp
new file mode 100644
index 0000000..de9f560
--- /dev/null
+++ b/authsecret/1.0/vts/functional/Android.bp
@@ -0,0 +1,22 @@
+//
+// 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.
+//
+
+cc_test {
+    name: "VtsHalAuthSecretV1_0TargetTest",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: ["VtsHalAuthSecretV1_0TargetTest.cpp"],
+    static_libs: ["android.hardware.authsecret@1.0"],
+}
diff --git a/authsecret/1.0/vts/functional/VtsHalAuthSecretV1_0TargetTest.cpp b/authsecret/1.0/vts/functional/VtsHalAuthSecretV1_0TargetTest.cpp
new file mode 100644
index 0000000..b0cbd91
--- /dev/null
+++ b/authsecret/1.0/vts/functional/VtsHalAuthSecretV1_0TargetTest.cpp
@@ -0,0 +1,97 @@
+/*
+ * 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.
+ */
+
+#include <android/hardware/authsecret/1.0/IAuthSecret.h>
+
+#include <VtsHalHidlTargetTestBase.h>
+
+using ::android::hardware::hidl_vec;
+using ::android::hardware::authsecret::V1_0::IAuthSecret;
+using ::android::sp;
+
+/**
+ * There is no expected behaviour that can be tested so these tests check the
+ * HAL doesn't crash with different execution orders.
+ */
+struct AuthSecretHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+    virtual void SetUp() override {
+        authsecret = ::testing::VtsHalHidlTargetTestBase::getService<IAuthSecret>();
+        ASSERT_NE(authsecret, nullptr);
+        authsecret->factoryReset();
+    }
+
+    sp<IAuthSecret> authsecret;
+};
+
+/* Provision the primary user with a secret. */
+TEST_F(AuthSecretHidlTest, provisionPrimaryUserCredential) {
+    hidl_vec<uint8_t> secret{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
+    authsecret->primaryUserCredential(secret);
+}
+
+/* Provision the primary user with a large secret. */
+TEST_F(AuthSecretHidlTest, provisionPrimaryUserCredentialWithLargeSecret) {
+    hidl_vec<uint8_t> secret{89,  233, 52,  29,  130, 210, 229, 170, 124, 102, 56,  238, 198,
+                             199, 246, 152, 185, 123, 155, 215, 29,  252, 30,  70,  118, 29,
+                             149, 36,  222, 203, 163, 7,   72,  56,  247, 19,  198, 76,  71,
+                             37,  120, 201, 220, 70,  150, 18,  23,  22,  236, 57,  184, 86,
+                             190, 122, 210, 207, 74,  51,  222, 157, 74,  196, 86,  208};
+    authsecret->primaryUserCredential(secret);
+}
+
+/* Provision the primary user with a secret and pass the secret again. */
+TEST_F(AuthSecretHidlTest, provisionPrimaryUserCredentialAndPassAgain) {
+    hidl_vec<uint8_t> secret{64, 2, 3, 0, 5, 6, 7, 172, 9, 10, 11, 255, 13, 14, 15, 83};
+    authsecret->primaryUserCredential(secret);
+    authsecret->primaryUserCredential(secret);
+}
+
+/* Provision the primary user with a secret and pass the secret again repeatedly. */
+TEST_F(AuthSecretHidlTest, provisionPrimaryUserCredentialAndPassAgainMultipleTimes) {
+    hidl_vec<uint8_t> secret{1, 2, 34, 4, 5, 6, 7, 8, 9, 105, 11, 12, 13, 184, 15, 16};
+    authsecret->primaryUserCredential(secret);
+    constexpr int N = 5;
+    for (int i = 0; i < N; ++i) {
+        authsecret->primaryUserCredential(secret);
+    }
+}
+
+/* Factory reset before provisioning the primary user with a secret. */
+TEST_F(AuthSecretHidlTest, factoryResetWithoutProvisioningPrimaryUserCredential) {
+    authsecret->factoryReset();
+}
+
+/* Provision the primary user with a secret then factory reset. */
+TEST_F(AuthSecretHidlTest, provisionPrimaryUserCredentialAndFactoryReset) {
+    hidl_vec<uint8_t> secret{1, 24, 124, 240, 5, 6, 7, 8, 9, 13, 11, 12, 189, 14, 195, 16};
+    authsecret->primaryUserCredential(secret);
+    authsecret->factoryReset();
+}
+
+/* Provision the primary differently after factory reset. */
+TEST_F(AuthSecretHidlTest, provisionPrimaryUserCredentialDifferentlyAfterFactoryReset) {
+    {
+        hidl_vec<uint8_t> secret1{19, 0, 65, 20, 65, 12, 7, 8, 9, 13, 29, 12, 189, 32, 195, 16};
+        authsecret->primaryUserCredential(secret1);
+    }
+
+    authsecret->factoryReset();
+
+    {
+        hidl_vec<uint8_t> secret2{61, 93, 124, 240, 5, 0, 7, 201, 9, 129, 11, 12, 0, 14, 0, 16};
+        authsecret->primaryUserCredential(secret2);
+    }
+}
diff --git a/automotive/audiocontrol/1.0/Android.bp b/automotive/audiocontrol/1.0/Android.bp
new file mode 100644
index 0000000..a967049
--- /dev/null
+++ b/automotive/audiocontrol/1.0/Android.bp
@@ -0,0 +1,23 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.automotive.audiocontrol@1.0",
+    root: "android.hardware",
+    vndk: {
+        enabled: true,
+    },
+    srcs: [
+        "types.hal",
+        "IAudioControl.hal",
+        "IAudioControlCallback.hal",
+    ],
+    interfaces: [
+        "android.hidl.base@1.0",
+    ],
+    types: [
+        "AudioResult",
+        "ContextNumber",
+    ],
+    gen_java: true,
+}
+
diff --git a/automotive/audiocontrol/1.0/IAudioControl.hal b/automotive/audiocontrol/1.0/IAudioControl.hal
new file mode 100644
index 0000000..fe9ea8e
--- /dev/null
+++ b/automotive/audiocontrol/1.0/IAudioControl.hal
@@ -0,0 +1,73 @@
+/*
+ * 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.
+ */
+
+package android.hardware.automotive.audiocontrol@1.0;
+
+import IAudioControlCallback;
+
+
+/**
+ * Interacts with the car's audio subsystem to manage audio sources and volumes
+ */
+interface IAudioControl {
+
+    /**
+     * Registers the required callback object so that we can be notified when the state
+     * of the car's audio system changes. This call must be made when the interface is
+     * initialized.
+     */
+    setCallback(IAudioControlCallback notificationObject)
+        generates (AudioResult result);
+
+
+    /**
+     * Called at startup once per context to get the mapping from ContextNumber to
+     * busAddress. This lets the car tell the framework to which physical output stream
+     * each context should be routed.
+     *
+     * For every context, a valid bus number (0 - num busses-1) must be returned. If an
+     * unrecognized contextNumber is encountered, then -1 shall be returned.
+     *
+     * Any context for which an invalid busNumber is returned must be routed to bus 0.
+     */
+    getBusForContext(uint32_t contextNumber)
+        generates (int32_t busNumber);
+
+
+    /**
+     * Control the right/left balance setting of the car speakers.
+     *
+     * This is intended to shift the speaker volume toward the right (+) or left (-) side of
+     * the car. 0.0 means "centered". +1.0 means fully right. -1.0 means fully left.
+     *
+     * A value outside the range -1 to 1 must be clamped by the implementation to the -1 to 1
+     * range.
+     */
+    oneway setBalanceTowardRight(float value);
+
+
+    /**
+     * Control the fore/aft fade setting of the car speakers.
+     *
+     * This is intended to shift the speaker volume toward the front (+) or back (-) of the car.
+     * 0.0 means "centered". +1.0 means fully forward. -1.0 means fully rearward.
+     *
+     * A value outside the range -1 to 1 must be clamped by the implementation to the -1 to 1
+     * range.
+     */
+    oneway setFadeTowardFront(float value);
+};
+
diff --git a/automotive/audiocontrol/1.0/IAudioControlCallback.hal b/automotive/audiocontrol/1.0/IAudioControlCallback.hal
new file mode 100644
index 0000000..f5c227e
--- /dev/null
+++ b/automotive/audiocontrol/1.0/IAudioControlCallback.hal
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+
+package android.hardware.automotive.audiocontrol@1.0;
+
+
+/**
+ * Implemented on client (framework) side to receive asynchronous updates from the car.
+ */
+interface IAudioControlCallback {
+
+    /**
+     * When the HAL makes this call, any apps currently playing must be asked to
+     * temporarily suspend playback (via an AudioManager::AUDIOFOCUS_LOSS_TRANSIENT event).
+     *
+     * This is only a suggestion. Apps may be slow to react or even ignore this message
+     * entirely. Enforcement, if necessary, must be done at the AudioHAL level as the
+     * samples are delivered. In most instances, this is the way a car should ask for
+     * quiet if it needs it for some important situation, such as warning alarms or chimes.
+     */
+    oneway suggestPausePlayers();
+
+
+    /**
+     * When the HAL makes this case, any apps currently playing must be asked to stop
+     * playing (via an AudioManager::AUDIOFOCUS_LOSS event). Once stopped, the apps must
+     * not resume their playback.
+     *
+     * It should be noted that not all apps or sound sources honor this request, but this
+     * at least gives an app the chance to do the right thing.
+     * Because it premanently stops media, this call is expected to be used only rarely.
+     * Perhaps in the event of an E-call, where resuming music might be undesirable assuming
+     * the driver is now dealing with whatever the emergency is?
+     */
+    oneway suggestStopPlayers();
+
+
+    /**
+     * Receives calls from the HAL when Android should resume normal operations. If the previous
+     * action was a requestPausePlayers, then things that were paused must be told they may
+     * resume.
+     */
+    oneway resumePlayers();
+};
diff --git a/automotive/audiocontrol/1.0/default/Android.bp b/automotive/audiocontrol/1.0/default/Android.bp
new file mode 100644
index 0000000..614c58b
--- /dev/null
+++ b/automotive/audiocontrol/1.0/default/Android.bp
@@ -0,0 +1,40 @@
+// 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.
+
+cc_binary {
+    name: "android.hardware.automotive.audiocontrol@1.0-service",
+    defaults: ["hidl_defaults"],
+    vendor: true,
+    relative_install_path: "hw",
+    srcs: [
+        "AudioControl.cpp",
+        "AudioControlCallback.cpp",
+        "service.cpp"
+    ],
+    init_rc: ["android.hardware.automotive.audiocontrol@1.0-service.rc"],
+
+    shared_libs: [
+        "android.hardware.automotive.audiocontrol@1.0",
+        "libhidlbase",
+        "libhidltransport",
+        "liblog",
+        "libutils",
+    ],
+
+    cflags: [
+        "-DLOG_TAG=\"AudCntrlDrv\"",
+        "-O0",
+        "-g",
+    ],
+}
diff --git a/automotive/audiocontrol/1.0/default/AudioControl.cpp b/automotive/audiocontrol/1.0/default/AudioControl.cpp
new file mode 100644
index 0000000..419225d
--- /dev/null
+++ b/automotive/audiocontrol/1.0/default/AudioControl.cpp
@@ -0,0 +1,86 @@
+#include "AudioControl.h"
+
+#include <hidl/HidlTransportSupport.h>
+#include <log/log.h>
+
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace audiocontrol {
+namespace V1_0 {
+namespace implementation {
+
+
+// This is the static map we're using to associate a ContextNumber with a
+// bus number from the audio_policy_configuration.xml setup.  Every valid context needs
+// to be mapped to a bus address that actually exists in the platforms configuration.
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof(*a))  // Would be nice if this were common...
+static int sContextToBusMap[] = {
+    -1,     // INVALID
+     0,     // MUSIC_CONTEXT
+     1,     // NAVIGATION_CONTEXT
+     2,     // VOICE_COMMAND_CONTEXT
+     3,     // CALL_RING_CONTEXT
+     4,     // CALL_CONTEXT
+     5,     // ALARM_CONTEXT
+     6,     // NOTIFICATION_CONTEXT
+     7,     // SYSTEM_SOUND_CONTEXT
+};
+static const unsigned sContextMapSize = ARRAY_SIZE(sContextToBusMap);
+static const unsigned sContextCount = sContextMapSize - 1;  // Less one for the INVALID entry
+static const unsigned sContextNumberMax = sContextCount;    // contextNumber is counted from 1
+
+
+AudioControl::AudioControl() {
+};
+
+
+// Methods from ::android::hardware::automotive::audiocontrol::V1_0::IAudioControl follow.
+Return<AudioResult> AudioControl::setCallback(const sp<IAudioControlCallback>& notificationObject) {
+    // Hang onto the provided callback object for future use
+    callback = notificationObject;
+
+    return AudioResult::OK;
+}
+
+
+Return<int32_t> AudioControl::getBusForContext(uint32_t contextNumber) {
+    if (contextNumber > sContextNumberMax) {
+        ALOGE("Unexpected context number %d (max expected is %d)", contextNumber, sContextCount);
+        return -1;
+    } else {
+        return sContextToBusMap[contextNumber];
+    }
+}
+
+
+Return<void> AudioControl::setBalanceTowardRight(float value) {
+    // For completeness, lets bounds check the input...
+    if ((value > 1.0f) || (value < -1.0f)) {
+        ALOGE("Balance value out of range -1 to 1 at %0.2f", value);
+    } else {
+        // Just log in this default mock implementation
+        ALOGI("Balance set to %0.2f", value);
+    }
+    return Void();
+}
+
+
+Return<void> AudioControl::setFadeTowardFront(float value) {
+    // For completeness, lets bounds check the input...
+    if ((value > 1.0f) || (value < -1.0f)) {
+        ALOGE("Fader value out of range -1 to 1 at %0.2f", value);
+    } else {
+        // Just log in this default mock implementation
+        ALOGI("Fader set to %0.2f", value);
+    }
+    return Void();
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace audiocontrol
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
diff --git a/automotive/audiocontrol/1.0/default/AudioControl.h b/automotive/audiocontrol/1.0/default/AudioControl.h
new file mode 100644
index 0000000..3383875
--- /dev/null
+++ b/automotive/audiocontrol/1.0/default/AudioControl.h
@@ -0,0 +1,45 @@
+#ifndef ANDROID_HARDWARE_AUTOMOTIVE_AUDIOCONTROL_V1_0_AUDIOCONTROL_H
+#define ANDROID_HARDWARE_AUTOMOTIVE_AUDIOCONTROL_V1_0_AUDIOCONTROL_H
+
+#include <android/hardware/automotive/audiocontrol/1.0/IAudioControl.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace audiocontrol {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+struct AudioControl : public IAudioControl {
+public:
+    // Methods from ::android::hardware::automotive::audiocontrol::V1_0::IAudioControl follow.
+    Return<AudioResult> setCallback(const sp<IAudioControlCallback>& notificationObject) override;
+    Return<int32_t> getBusForContext(uint32_t contextNumber) override;
+    Return<void> setBalanceTowardRight(float value) override;
+    Return<void> setFadeTowardFront(float value) override;
+
+    // Implementation details
+    AudioControl();
+
+private:
+    sp<IAudioControlCallback> callback;
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace audiocontrol
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_AUTOMOTIVE_AUDIOCONTROL_V1_0_AUDIOCONTROL_H
diff --git a/automotive/audiocontrol/1.0/default/AudioControlCallback.cpp b/automotive/audiocontrol/1.0/default/AudioControlCallback.cpp
new file mode 100644
index 0000000..ea79cad
--- /dev/null
+++ b/automotive/audiocontrol/1.0/default/AudioControlCallback.cpp
@@ -0,0 +1,31 @@
+#include "AudioControlCallback.h"
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace audiocontrol {
+namespace V1_0 {
+namespace implementation {
+
+// Methods from ::android::hardware::automotive::audiocontrol::V1_0::IAudioControlCallback follow.
+Return<void> AudioControlCallback::suggestPausePlayers() {
+    // TODO implement in framework (this is called by the HAL implementation when needed)
+    return Void();
+}
+
+Return<void> AudioControlCallback::suggestStopPlayers() {
+    // TODO implement in framework (this is called by the HAL implementation when needed)
+    return Void();
+}
+
+Return<void> AudioControlCallback::resumePlayers() {
+    // TODO implement in framework (this is called by the HAL implementation when needed)
+    return Void();
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace audiocontrol
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
diff --git a/automotive/audiocontrol/1.0/default/AudioControlCallback.h b/automotive/audiocontrol/1.0/default/AudioControlCallback.h
new file mode 100644
index 0000000..1054548
--- /dev/null
+++ b/automotive/audiocontrol/1.0/default/AudioControlCallback.h
@@ -0,0 +1,41 @@
+#ifndef ANDROID_HARDWARE_AUTOMOTIVE_AUDIOCONTROL_V1_0_AUDIOCONTROLCALLBACK_H
+#define ANDROID_HARDWARE_AUTOMOTIVE_AUDIOCONTROL_V1_0_AUDIOCONTROLCALLBACK_H
+
+#include <android/hardware/automotive/audiocontrol/1.0/IAudioControlCallback.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace audiocontrol {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+// TODO:  Move this into packages/services/Car...
+struct AudioControlCallback : public IAudioControlCallback {
+    // Methods from ::android::hardware::automotive::audiocontrol::V1_0::IAudioControlCallback follow.
+    Return<void> suggestPausePlayers() override;
+    Return<void> suggestStopPlayers() override;
+    Return<void> resumePlayers() override;
+
+    // Methods from ::android::hidl::base::V1_0::IBase follow.
+
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace audiocontrol
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_AUTOMOTIVE_AUDIOCONTROL_V1_0_AUDIOCONTROLCALLBACK_H
diff --git a/automotive/audiocontrol/1.0/default/android.hardware.automotive.audiocontrol@1.0-service.rc b/automotive/audiocontrol/1.0/default/android.hardware.automotive.audiocontrol@1.0-service.rc
new file mode 100644
index 0000000..79edad6
--- /dev/null
+++ b/automotive/audiocontrol/1.0/default/android.hardware.automotive.audiocontrol@1.0-service.rc
@@ -0,0 +1,4 @@
+service vendor.evs-hal-mock /vendor/bin/hw/android.hardware.automotive.audiocontrol@1.0-service
+    class hal
+    user audioserver
+    group system
diff --git a/automotive/audiocontrol/1.0/default/service.cpp b/automotive/audiocontrol/1.0/default/service.cpp
new file mode 100644
index 0000000..a033fd9
--- /dev/null
+++ b/automotive/audiocontrol/1.0/default/service.cpp
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+#include <unistd.h>
+
+#include <hidl/HidlTransportSupport.h>
+#include <log/log.h>
+#include <utils/Errors.h>
+#include <utils/StrongPointer.h>
+
+#include "AudioControl.h"
+
+
+// libhidl:
+using android::hardware::configureRpcThreadpool;
+using android::hardware::joinRpcThreadpool;
+
+// Generated HIDL files
+using android::hardware::automotive::audiocontrol::V1_0::IAudioControl;
+
+// The namespace in which all our implementation code lives
+using namespace android::hardware::automotive::audiocontrol::V1_0::implementation;
+using namespace android;
+
+
+// Main service entry point
+int main() {
+    // Create an instance of our service class
+    android::sp<IAudioControl> service = new AudioControl();
+    configureRpcThreadpool(1, true /*callerWillJoin*/);
+
+    if (service->registerAsService() != OK) {
+        ALOGE("registerAsService failed");
+        return 1;
+    }
+
+    // Join (forever) the thread pool we created for the service above
+    joinRpcThreadpool();
+
+    // We don't ever actually expect to return, so return an error if we do get here
+    return 2;
+}
\ No newline at end of file
diff --git a/automotive/audiocontrol/1.0/types.hal b/automotive/audiocontrol/1.0/types.hal
new file mode 100644
index 0000000..6301d3a
--- /dev/null
+++ b/automotive/audiocontrol/1.0/types.hal
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+
+package android.hardware.automotive.audiocontrol@1.0;
+
+
+/**
+ * Predefined flags to identifying audio contexts
+ */
+enum ContextNumber : uint32_t {
+    INVALID = 0,    /* Shouldn't be used */
+
+    // Sounds from Android (counting from 1 coincidentally lets us match AudioAttributes usages)
+    MUSIC,          /* Music playback */
+    NAVIGATION,     /* Navigation directions */
+    VOICE_COMMAND,  /* Voice command session */
+    CALL_RING,      /* Voice call ringing */
+    CALL,           /* Voice call */
+    ALARM,          /* Alarm sound from Android */
+    NOTIFICATION,   /* Notifications */
+    SYSTEM_SOUND,   /* User interaction sounds (button clicks, etc) */
+};
+
+
+/** Error codes used in AudioControl HAL interface. */
+enum AudioResult : uint32_t {
+    OK = 0,
+    NOT_AVAILABLE,
+    INVALID_ARGUMENT,
+    UNDERLYING_SERVICE_ERROR,
+};
diff --git a/automotive/evs/1.0/default/Android.bp b/automotive/evs/1.0/default/Android.bp
index 2574e86..7286478 100644
--- a/automotive/evs/1.0/default/Android.bp
+++ b/automotive/evs/1.0/default/Android.bp
@@ -13,7 +13,6 @@
 
     shared_libs: [
         "android.hardware.automotive.evs@1.0",
-        "libui",
         "libbase",
         "libbinder",
         "libcutils",
@@ -21,6 +20,7 @@
         "libhidlbase",
         "libhidltransport",
         "liblog",
+        "libui",
         "libutils",
     ],
 
diff --git a/automotive/vehicle/2.0/Android.bp b/automotive/vehicle/2.0/Android.bp
index 7ab2387..ffe012e 100644
--- a/automotive/vehicle/2.0/Android.bp
+++ b/automotive/vehicle/2.0/Android.bp
@@ -42,19 +42,6 @@
         "VehicleAreaSeat",
         "VehicleAreaWindow",
         "VehicleAreaZone",
-        "VehicleAudioContextFlag",
-        "VehicleAudioExtFocusFlag",
-        "VehicleAudioFocusIndex",
-        "VehicleAudioFocusRequest",
-        "VehicleAudioFocusState",
-        "VehicleAudioHwVariantConfigFlag",
-        "VehicleAudioRoutingPolicyIndex",
-        "VehicleAudioStream",
-        "VehicleAudioStreamFlag",
-        "VehicleAudioVolumeCapabilityFlag",
-        "VehicleAudioVolumeIndex",
-        "VehicleAudioVolumeLimitIndex",
-        "VehicleAudioVolumeState",
         "VehicleDisplay",
         "VehicleDrivingStatus",
         "VehicleGear",
diff --git a/automotive/vehicle/2.0/default/Android.bp b/automotive/vehicle/2.0/default/Android.bp
index 1690163..6a254a5 100644
--- a/automotive/vehicle/2.0/default/Android.bp
+++ b/automotive/vehicle/2.0/default/Android.bp
@@ -46,6 +46,7 @@
         "common/src/VehicleObjectPool.cpp",
         "common/src/VehiclePropertyStore.cpp",
         "common/src/VehicleUtils.cpp",
+        "common/src/VmsUtils.cpp",
     ],
     local_include_dirs: ["common/include/vhal_v2_0"],
     export_include_dirs: ["common/include"],
@@ -93,6 +94,7 @@
         "tests/VehicleHalManager_test.cpp",
         "tests/VehicleObjectPool_test.cpp",
         "tests/VehiclePropConfigIndex_test.cpp",
+        "tests/VmsUtils_test.cpp",
     ],
     header_libs: ["libbase_headers"],
 }
diff --git a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VmsUtils.h b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VmsUtils.h
new file mode 100644
index 0000000..9e32bb5
--- /dev/null
+++ b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VmsUtils.h
@@ -0,0 +1,156 @@
+/*
+ * 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.
+ */
+
+#ifndef android_hardware_automotive_vehicle_V2_0_VmsUtils_H_
+#define android_hardware_automotive_vehicle_V2_0_VmsUtils_H_
+
+#include <memory>
+#include <string>
+
+#include <android/hardware/automotive/vehicle/2.0/types.h>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
+namespace vms {
+
+// VmsUtils are a set of abstractions for creating and parsing Vehicle Property
+// updates to VehicleProperty::VEHICLE_MAP_SERVICE. The format for parsing a
+// VehiclePropValue update with a VMS message is specified in the Vehicle HIDL.
+//
+// This interface is meant for use by HAL clients of VMS; corresponding
+// functionality is also provided by VMS in the embedded car service.
+
+// A VmsLayer is comprised of a type, subtype, and version.
+struct VmsLayer {
+    VmsLayer(int type, int subtype, int version) : type(type), subtype(subtype), version(version) {}
+    int type;
+    int subtype;
+    int version;
+};
+
+struct VmsLayerAndPublisher {
+    VmsLayer layer;
+    int publisher_id;
+};
+
+// A VmsAssociatedLayer is used by subscribers to specify which publisher IDs
+// are acceptable for a given layer.
+struct VmsAssociatedLayer {
+    VmsLayer layer;
+    std::vector<int> publisher_ids;
+};
+
+// A VmsLayerOffering refers to a single layer that can be published, along with
+// its dependencies. Dependencies can be empty.
+struct VmsLayerOffering {
+    VmsLayerOffering(VmsLayer layer, std::vector<VmsLayer> dependencies)
+        : layer(layer), dependencies(dependencies) {}
+    VmsLayerOffering(VmsLayer layer) : layer(layer), dependencies() {}
+    VmsLayer layer;
+    std::vector<VmsLayer> dependencies;
+};
+
+// A VmsSubscriptionsState is delivered in response to a
+// VmsMessageType.SUBSCRIPTIONS_REQUEST or on the first SUBSCRIBE or last
+// UNSUBSCRIBE for a layer. It indicates which layers or associated_layers are
+// currently being subscribed to in the system.
+struct VmsSubscriptionsState {
+    int sequence_number;
+    std::vector<VmsLayer> layers;
+    std::vector<VmsAssociatedLayer> associated_layers;
+};
+
+struct VmsAvailabilityState {
+    int sequence_number;
+    std::vector<VmsAssociatedLayer> associated_layers;
+};
+
+// Creates a VehiclePropValue containing a message of type
+// VmsMessageType.SUBSCRIBE, specifying to the VMS service
+// which layer to subscribe to.
+std::unique_ptr<VehiclePropValue> createSubscribeMessage(const VmsLayer& layer);
+
+// Creates a VehiclePropValue containing a message of type
+// VmsMessageType.SUBSCRIBE_TO_PUBLISHER, specifying to the VMS service
+// which layer and publisher_id to subscribe to.
+std::unique_ptr<VehiclePropValue> createSubscribeToPublisherMessage(
+    const VmsLayerAndPublisher& layer);
+
+// Creates a VehiclePropValue containing a message of type
+// VmsMessageType.UNSUBSCRIBE, specifying to the VMS service
+// which layer to unsubscribe from.
+std::unique_ptr<VehiclePropValue> createUnsubscribeMessage(const VmsLayer& layer);
+
+// Creates a VehiclePropValue containing a message of type
+// VmsMessageType.UNSUBSCRIBE_TO_PUBLISHER, specifying to the VMS service
+// which layer and publisher_id to unsubscribe from.
+std::unique_ptr<VehiclePropValue> createUnsubscribeToPublisherMessage(
+    const VmsLayerAndPublisher& layer);
+
+// Creates a VehiclePropValue containing a message of type
+// VmsMessageType.OFFERING, specifying to the VMS service which layers are being
+// offered and their dependencies, if any.
+std::unique_ptr<VehiclePropValue> createOfferingMessage(
+    const std::vector<VmsLayerOffering>& offering);
+
+// Creates a VehiclePropValue containing a message of type
+// VmsMessageType.AVAILABILITY_REQUEST.
+std::unique_ptr<VehiclePropValue> createAvailabilityRequest();
+
+// Creates a VehiclePropValue containing a message of type
+// VmsMessageType.AVAILABILITY_REQUEST.
+std::unique_ptr<VehiclePropValue> createSubscriptionsRequest();
+
+// Creates a VehiclePropValue containing a message of type VmsMessageType.DATA.
+// Returns a nullptr if the byte string in bytes is empty.
+//
+// For example, to build a VehiclePropMessage containing a proto, the caller
+// should convert the proto to a byte string using the SerializeToString proto
+// API, then use this inteface to build the VehicleProperty.
+std::unique_ptr<VehiclePropValue> createDataMessage(const std::string& bytes);
+
+// Returns true if the VehiclePropValue pointed to by value contains a valid Vms
+// message, i.e. the VehicleProperty, VehicleArea, and VmsMessageType are all
+// valid. Note: If the VmsMessageType enum is extended, this function will
+// return false for any new message types added.
+bool isValidVmsMessage(const VehiclePropValue& value);
+
+// Returns the message type. Expects that the VehiclePropValue contains a valid
+// Vms message, as verified by isValidVmsMessage.
+VmsMessageType parseMessageType(const VehiclePropValue& value);
+
+// Constructs a string byte array from a message of type VmsMessageType.DATA.
+// Returns an empty string if the message type doesn't match or if the
+// VehiclePropValue does not contain a byte array.
+//
+// A proto message can then be constructed by passing the result of this
+// function to ParseFromString.
+std::string parseData(const VehiclePropValue& value);
+
+// TODO(aditin): Need to implement additional parsing functions per message
+// type.
+
+}  // namespace vms
+}  // namespace V2_0
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_automotive_vehicle_V2_0_VmsUtils_H_
diff --git a/automotive/vehicle/2.0/default/common/src/VmsUtils.cpp b/automotive/vehicle/2.0/default/common/src/VmsUtils.cpp
new file mode 100644
index 0000000..abf425f
--- /dev/null
+++ b/automotive/vehicle/2.0/default/common/src/VmsUtils.cpp
@@ -0,0 +1,162 @@
+/*
+ * 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.
+ */
+
+#include "VmsUtils.h"
+
+#include <common/include/vhal_v2_0/VehicleUtils.h>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
+namespace vms {
+
+static constexpr int kMessageIndex = toInt(VmsBaseMessageIntegerValuesIndex::MESSAGE_TYPE);
+static constexpr int kMessageTypeSize = 1;
+static constexpr int kLayerNumberSize = 1;
+static constexpr int kLayerSize = 3;
+static constexpr int kLayerAndPublisherSize = 4;
+
+// TODO(aditin): We should extend the VmsMessageType enum to include a first and
+// last, which would prevent breakages in this API. However, for all of the
+// functions in this module, we only need to guarantee that the message type is
+// between SUBSCRIBE and DATA.
+static constexpr int kFirstMessageType = toInt(VmsMessageType::SUBSCRIBE);
+static constexpr int kLastMessageType = toInt(VmsMessageType::DATA);
+
+std::unique_ptr<VehiclePropValue> createBaseVmsMessage(size_t message_size) {
+    auto result = createVehiclePropValue(VehiclePropertyType::INT32, message_size);
+    result->prop = toInt(VehicleProperty::VEHICLE_MAP_SERVICE);
+    result->areaId = toInt(VehicleArea::GLOBAL);
+    return result;
+}
+
+std::unique_ptr<VehiclePropValue> createSubscribeMessage(const VmsLayer& layer) {
+    auto result = createBaseVmsMessage(kMessageTypeSize + kLayerSize);
+    result->value.int32Values = hidl_vec<int32_t>{toInt(VmsMessageType::SUBSCRIBE), layer.type,
+                                                  layer.subtype, layer.version};
+    return result;
+}
+
+std::unique_ptr<VehiclePropValue> createSubscribeToPublisherMessage(
+    const VmsLayerAndPublisher& layer_publisher) {
+    auto result = createBaseVmsMessage(kMessageTypeSize + kLayerAndPublisherSize);
+    result->value.int32Values = hidl_vec<int32_t>{
+        toInt(VmsMessageType::SUBSCRIBE_TO_PUBLISHER), layer_publisher.layer.type,
+        layer_publisher.layer.subtype, layer_publisher.layer.version, layer_publisher.publisher_id};
+    return result;
+}
+
+std::unique_ptr<VehiclePropValue> createUnsubscribeMessage(const VmsLayer& layer) {
+    auto result = createBaseVmsMessage(kMessageTypeSize + kLayerSize);
+    result->value.int32Values = hidl_vec<int32_t>{toInt(VmsMessageType::UNSUBSCRIBE), layer.type,
+                                                  layer.subtype, layer.version};
+    return result;
+}
+
+std::unique_ptr<VehiclePropValue> createUnsubscribeToPublisherMessage(
+    const VmsLayerAndPublisher& layer_publisher) {
+    auto result = createBaseVmsMessage(kMessageTypeSize + kLayerAndPublisherSize);
+    result->value.int32Values = hidl_vec<int32_t>{
+        toInt(VmsMessageType::UNSUBSCRIBE_TO_PUBLISHER), layer_publisher.layer.type,
+        layer_publisher.layer.subtype, layer_publisher.layer.version, layer_publisher.publisher_id};
+    return result;
+}
+
+std::unique_ptr<VehiclePropValue> createOfferingMessage(
+    const std::vector<VmsLayerOffering>& offering) {
+    int message_size = kMessageTypeSize + kLayerNumberSize;
+    for (const auto& offer : offering) {
+        message_size += kLayerNumberSize + (1 + offer.dependencies.size()) * kLayerSize;
+    }
+    auto result = createBaseVmsMessage(message_size);
+
+    std::vector<int32_t> offers = {toInt(VmsMessageType::OFFERING),
+                                   static_cast<int>(offering.size())};
+    for (const auto& offer : offering) {
+        std::vector<int32_t> layer_vector = {offer.layer.type, offer.layer.subtype,
+                                             offer.layer.version,
+                                             static_cast<int32_t>(offer.dependencies.size())};
+        for (const auto& dependency : offer.dependencies) {
+            std::vector<int32_t> dependency_layer = {dependency.type, dependency.subtype,
+                                                     dependency.version};
+            layer_vector.insert(layer_vector.end(), dependency_layer.begin(),
+                                dependency_layer.end());
+        }
+        offers.insert(offers.end(), layer_vector.begin(), layer_vector.end());
+    }
+    result->value.int32Values = offers;
+    return result;
+}
+
+std::unique_ptr<VehiclePropValue> createAvailabilityRequest() {
+    auto result = createBaseVmsMessage(kMessageTypeSize);
+    result->value.int32Values = hidl_vec<int32_t>{
+        toInt(VmsMessageType::AVAILABILITY_REQUEST),
+    };
+    return result;
+}
+
+std::unique_ptr<VehiclePropValue> createSubscriptionsRequest() {
+    auto result = createBaseVmsMessage(kMessageTypeSize);
+    result->value.int32Values = hidl_vec<int32_t>{
+        toInt(VmsMessageType::SUBSCRIPTIONS_REQUEST),
+    };
+    return result;
+}
+
+std::unique_ptr<VehiclePropValue> createDataMessage(const std::string& bytes) {
+    auto result = createBaseVmsMessage(kMessageTypeSize);
+    result->value.int32Values = hidl_vec<int32_t>{toInt(VmsMessageType::DATA)};
+    result->value.bytes = std::vector<uint8_t>(bytes.begin(), bytes.end());
+    return result;
+}
+
+bool verifyPropertyAndArea(const VehiclePropValue& value) {
+    return (value.prop == toInt(VehicleProperty::VEHICLE_MAP_SERVICE) &&
+            value.areaId == toInt(VehicleArea::GLOBAL));
+}
+
+bool verifyMessageType(const VehiclePropValue& value) {
+    return (value.value.int32Values.size() > 0 &&
+            value.value.int32Values[kMessageIndex] >= kFirstMessageType &&
+            value.value.int32Values[kMessageIndex] <= kLastMessageType);
+}
+
+bool isValidVmsMessage(const VehiclePropValue& value) {
+    return (verifyPropertyAndArea(value) && verifyMessageType(value));
+}
+
+VmsMessageType parseMessageType(const VehiclePropValue& value) {
+    return static_cast<VmsMessageType>(value.value.int32Values[kMessageIndex]);
+}
+
+std::string parseData(const VehiclePropValue& value) {
+    if (isValidVmsMessage(value) && parseMessageType(value) == VmsMessageType::DATA &&
+        value.value.bytes.size() > 0) {
+        return std::string(value.value.bytes.begin(), value.value.bytes.end());
+    } else {
+        return std::string();
+    }
+}
+
+}  // namespace vms
+}  // namespace V2_0
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
diff --git a/automotive/vehicle/2.0/default/tests/VmsUtils_test.cpp b/automotive/vehicle/2.0/default/tests/VmsUtils_test.cpp
new file mode 100644
index 0000000..c102ce8
--- /dev/null
+++ b/automotive/vehicle/2.0/default/tests/VmsUtils_test.cpp
@@ -0,0 +1,183 @@
+/*
+ * 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.
+ */
+
+#include <android/hardware/automotive/vehicle/2.0/IVehicle.h>
+#include <gtest/gtest.h>
+
+#include "VehicleHalTestUtils.h"
+#include "vhal_v2_0/VmsUtils.h"
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
+namespace vms {
+
+namespace {
+
+TEST(VmsUtilsTest, subscribeMessage) {
+    VmsLayer layer(1, 0, 2);
+    auto message = createSubscribeMessage(layer);
+    ASSERT_NE(message, nullptr);
+    EXPECT_TRUE(isValidVmsMessage(*message));
+    EXPECT_EQ(message->prop, toInt(VehicleProperty::VEHICLE_MAP_SERVICE));
+    EXPECT_EQ(message->areaId, toInt(VehicleArea::GLOBAL));
+    EXPECT_EQ(message->value.int32Values.size(), 0x4ul);
+    EXPECT_EQ(parseMessageType(*message), VmsMessageType::SUBSCRIBE);
+
+    // Layer
+    EXPECT_EQ(message->value.int32Values[1], 1);
+    EXPECT_EQ(message->value.int32Values[2], 0);
+    EXPECT_EQ(message->value.int32Values[3], 2);
+}
+
+TEST(VmsUtilsTest, unsubscribeMessage) {
+    VmsLayer layer(1, 0, 2);
+    auto message = createUnsubscribeMessage(layer);
+    ASSERT_NE(message, nullptr);
+    EXPECT_TRUE(isValidVmsMessage(*message));
+    EXPECT_EQ(message->prop, toInt(VehicleProperty::VEHICLE_MAP_SERVICE));
+    EXPECT_EQ(message->areaId, toInt(VehicleArea::GLOBAL));
+    EXPECT_EQ(message->value.int32Values.size(), 0x4ul);
+    EXPECT_EQ(parseMessageType(*message), VmsMessageType::UNSUBSCRIBE);
+
+    // Layer
+    EXPECT_EQ(message->value.int32Values[1], 1);
+    EXPECT_EQ(message->value.int32Values[2], 0);
+    EXPECT_EQ(message->value.int32Values[3], 2);
+}
+
+TEST(VmsUtilsTest, singleOfferingMessage) {
+    std::vector<VmsLayerOffering> offering = {VmsLayerOffering(VmsLayer(1, 0, 2))};
+    auto message = createOfferingMessage(offering);
+    ASSERT_NE(message, nullptr);
+    EXPECT_TRUE(isValidVmsMessage(*message));
+    EXPECT_EQ(message->prop, toInt(VehicleProperty::VEHICLE_MAP_SERVICE));
+    EXPECT_EQ(message->areaId, toInt(VehicleArea::GLOBAL));
+    EXPECT_EQ(message->value.int32Values.size(), 0x6ul);
+    EXPECT_EQ(parseMessageType(*message), VmsMessageType::OFFERING);
+
+    // Number of layer offerings
+    EXPECT_EQ(message->value.int32Values[1], 1);
+
+    // Layer
+    EXPECT_EQ(message->value.int32Values[2], 1);
+    EXPECT_EQ(message->value.int32Values[3], 0);
+    EXPECT_EQ(message->value.int32Values[4], 2);
+
+    // Number of dependencies
+    EXPECT_EQ(message->value.int32Values[5], 0);
+}
+
+TEST(VmsUtilsTest, offeringWithDependencies) {
+    VmsLayer layer(1, 0, 2);
+    std::vector<VmsLayer> dependencies = {VmsLayer(2, 0, 2)};
+    std::vector<VmsLayerOffering> offering = {VmsLayerOffering(layer, dependencies)};
+    auto message = createOfferingMessage(offering);
+    ASSERT_NE(message, nullptr);
+    EXPECT_TRUE(isValidVmsMessage(*message));
+    EXPECT_EQ(message->prop, toInt(VehicleProperty::VEHICLE_MAP_SERVICE));
+    EXPECT_EQ(message->areaId, toInt(VehicleArea::GLOBAL));
+    EXPECT_EQ(message->value.int32Values.size(), 0x9ul);
+    EXPECT_EQ(parseMessageType(*message), VmsMessageType::OFFERING);
+
+    // Number of layer offerings
+    EXPECT_EQ(message->value.int32Values[1], 1);
+
+    // Layer
+    EXPECT_EQ(message->value.int32Values[2], 1);
+    EXPECT_EQ(message->value.int32Values[3], 0);
+    EXPECT_EQ(message->value.int32Values[4], 2);
+
+    // Number of dependencies
+    EXPECT_EQ(message->value.int32Values[5], 1);
+
+    // Dependency 1
+    EXPECT_EQ(message->value.int32Values[6], 2);
+    EXPECT_EQ(message->value.int32Values[7], 0);
+    EXPECT_EQ(message->value.int32Values[8], 2);
+}
+
+TEST(VmsUtilsTest, availabilityMessage) {
+    auto message = createAvailabilityRequest();
+    ASSERT_NE(message, nullptr);
+    EXPECT_TRUE(isValidVmsMessage(*message));
+    EXPECT_EQ(message->prop, toInt(VehicleProperty::VEHICLE_MAP_SERVICE));
+    EXPECT_EQ(message->areaId, toInt(VehicleArea::GLOBAL));
+    EXPECT_EQ(message->value.int32Values.size(), 0x1ul);
+    EXPECT_EQ(parseMessageType(*message), VmsMessageType::AVAILABILITY_REQUEST);
+}
+
+TEST(VmsUtilsTest, subscriptionsMessage) {
+    auto message = createSubscriptionsRequest();
+    ASSERT_NE(message, nullptr);
+    EXPECT_TRUE(isValidVmsMessage(*message));
+    EXPECT_EQ(message->prop, toInt(VehicleProperty::VEHICLE_MAP_SERVICE));
+    EXPECT_EQ(message->areaId, toInt(VehicleArea::GLOBAL));
+    EXPECT_EQ(message->value.int32Values.size(), 0x1ul);
+    EXPECT_EQ(parseMessageType(*message), VmsMessageType::SUBSCRIPTIONS_REQUEST);
+}
+
+TEST(VmsUtilsTest, dataMessage) {
+    std::string bytes = "aaa";
+    auto message = createDataMessage(bytes);
+    ASSERT_NE(message, nullptr);
+    EXPECT_TRUE(isValidVmsMessage(*message));
+    EXPECT_EQ(message->prop, toInt(VehicleProperty::VEHICLE_MAP_SERVICE));
+    EXPECT_EQ(message->areaId, toInt(VehicleArea::GLOBAL));
+    EXPECT_EQ(message->value.int32Values.size(), 0x1ul);
+    EXPECT_EQ(parseMessageType(*message), VmsMessageType::DATA);
+    EXPECT_EQ(message->value.bytes.size(), bytes.size());
+    EXPECT_EQ(memcmp(message->value.bytes.data(), bytes.data(), bytes.size()), 0);
+}
+
+TEST(VmsUtilsTest, emptyMessageInvalid) {
+    VehiclePropValue empty_prop;
+    EXPECT_FALSE(isValidVmsMessage(empty_prop));
+}
+
+TEST(VmsUtilsTest, invalidMessageType) {
+    VmsLayer layer(1, 0, 2);
+    auto message = createSubscribeMessage(layer);
+    message->value.int32Values[0] = 0;
+
+    EXPECT_FALSE(isValidVmsMessage(*message));
+}
+
+TEST(VmsUtilsTest, parseDataMessage) {
+    std::string bytes = "aaa";
+    auto message = createDataMessage(bytes);
+    auto data_str = parseData(*message);
+    ASSERT_FALSE(data_str.empty());
+    EXPECT_EQ(data_str, bytes);
+}
+
+TEST(VmsUtilsTest, parseInvalidDataMessage) {
+    VmsLayer layer(1, 0, 2);
+    auto message = createSubscribeMessage(layer);
+    auto data_str = parseData(*message);
+    EXPECT_TRUE(data_str.empty());
+}
+
+}  // namespace
+
+}  // namespace vms
+}  // namespace V2_0
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
diff --git a/automotive/vehicle/2.0/types.hal b/automotive/vehicle/2.0/types.hal
index 8e1b164..7e42781 100644
--- a/automotive/vehicle/2.0/types.hal
+++ b/automotive/vehicle/2.0/types.hal
@@ -906,346 +906,6 @@
         | VehicleArea:GLOBAL),
 
     /**
-     * Represents audio focus state of Android side. Note that car's audio
-     * module must own audio focus and grant audio focus to Android side when
-     * requested by Android side. The focus has both per stream characteristics
-     * and global characteristics.
-     *
-     * Focus request (get of this property) must take the following form with indices defined
-     * by VehicleAudioFocusIndex:
-     *   int32Values[0]: VehicleAudioFocusRequest type
-     *   int32Values[1]: bit flags of streams requested by this focus request.
-     *                   There can be up to 32 streams.
-     *   int32Values[2]: External focus state flags. For request, only flag like
-     *                   VehicleAudioExtFocusFlag#PLAY_ONLY_FLAG or
-     *                   VehicleAudioExtFocusFlag#MUTE_MEDIA_FLAG can be
-     *                   used.
-     *                   VehicleAudioExtFocusFlag#PLAY_ONLY_FLAG is for case
-     *                   like radio where android side app still needs to hold
-     *                   focus but playback is done outside Android.
-     *                   VehicleAudioExtFocusFlag#MUTE_MEDIA_FLAG is for
-     *                   muting media channel including radio.
-     *                   VehicleAudioExtFocusFlag#PLAY_ONLY_FLAG can be set
-     *                   even if android side releases focus (request type
-     *                   REQUEST_RELEASE). In that case, audio module must
-     *                   maintain mute state until user's explicit action to
-     *                   play some media.
-     *   int32Values[3]: Audio contexts wishing to be active. Use combination of
-     *                   flags from VehicleAudioContextFlag.
-     *                   This can be used as a hint to adjust audio policy or
-     *                   other policy decision.
-     *                   Note that there can be multiple context active at the
-     *                   same time. And android can send the same focus request
-     *                   type gain due to change in audio contexts.
-     * Note that each focus request can request multiple streams that is
-     * expected to be used for the current request. But focus request itself
-     * is global behavior as GAIN or GAIN_TRANSIENT expects all sounds played
-     * by car's audio module to stop. Note that stream already allocated to
-     * android before this focus request must not be affected by focus
-     * request.
-     *
-     * Focus response (set and subscription callback for this property) must
-     * take the following form with indices defined by VehicleAudioFocusIndex:
-     *   int32Values[0]: VehicleAudioFocusState type
-     *   int32Values[1]: bit flags of streams allowed.
-     *   int32Values[2]: External focus state: bit flags of currently active
-     *                   audio focus in car side (outside Android). Active
-     *                   audio focus does not necessarily mean currently
-     *                   playing, but represents the state of having focus or
-     *                   waiting for focus (pause state).
-     *                   One or combination of flags from
-     *                   VehicleAudioExtFocusFlag.
-     *                   0 means no active audio focus holder outside Android.
-     *                   The state must have following values for each
-     *                   VehicleAudioFocusState:
-     *                   GAIN: VehicleAudioExtFocusFlag#PLAY_ONLY_FLAG
-     *                       when radio is active in Android side. Otherwise,
-     *                       VehicleAudioExtFocusFlag#NONE_FLAG.
-     *                   GAIN_TRANSIENT: Can be
-     *                       VehicleAudioExtFocusFlag#PERMANENT_FLAG or
-     *                       VehicleAudioExtFocusFlag#TRANSIENT_FLAG if android
-     *                       side has requested
-     *                       REQUEST_GAIN_TRANSIENT_MAY_DUCK and car side is
-     *                       ducking. Otherwise
-     *                       VehicleAudioExtFocusFlag#NONE_FLAG.
-     *                   LOSS: VehicleAudioExtFocusFlag#NONE_FLAG when no focus
-     *                       is active in car side.
-     *                       VehicleAudioExtFocusFlag#PERMANENT_FLAG when car
-     *                       side is playing something permanent.
-     *                   LOSS_TRANSIENT: must always be
-     *                       VehicleAudioExtFocusFlag#PERMANENT_FLAG
-     *   int32Values[3]: Audio context(s) allowed to be active. When responding positively to a
-     *                   focus request from Android, the request's original context must be
-     *                   repeated here. When taking focus away, or denying a request, the
-     *                   rejected or stopped context would have its corresponding bit cleared.
-     *
-     * A focus response must be sent per each focus request even if there is
-     * no change in focus state. This can happen in case like focus request
-     * only involving context change where android side still needs matching
-     * focus response to confirm that audio module has made necessary changes.
-     *
-     * If car does not support AUDIO_FOCUS, focus is assumed to be granted
-     * always.
-     *
-     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
-     * @access VehiclePropertyAccess:READ_WRITE
-     */
-    AUDIO_FOCUS = (
-        0x0900
-        | VehiclePropertyGroup:SYSTEM
-        | VehiclePropertyType:INT32_VEC
-        | VehicleArea:GLOBAL),
-
-    /**
-     * A property to allow external component to control audio focus. Depending on
-     * H/W architecture, audio HAL may need to control audio focus while vehicle
-     * HAL is still interacting with upper layer. In such case, audio HAL may set
-     * this property and vehicle HAL may use this property value to decide
-     * response sent through AUDIO_FOCUS property.
-     * Data format is the same as AUDIO_FOCUS property.
-     *
-     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
-     * @access VehiclePropertyAccess:READ_WRITE
-     */
-    AUDIO_FOCUS_EXT_SYNC = (
-        0x0910
-        | VehiclePropertyGroup:SYSTEM
-        | VehiclePropertyType:INT32_VEC
-        | VehicleArea:GLOBAL),
-
-    /**
-     * Property to control audio volume of each audio context.
-     *
-     * VehiclePropConfig
-     *   configArray[0] : bit flags of all supported audio contexts from
-     *                    VehicleAudioContextFlag. If this is 0, audio volume
-     *                    is controlled per physical stream.
-     *   configArray[1] : flags defined in VehicleAudioVolumeCapabilityFlag to
-     *                    represent audio module's capability.
-     *   configArray[2..3] : reserved
-     *   configArray[4..N+3] : maximum values for each audio context, where N is
-     *                         the number of audio contexts provided in
-     *                         configArray[0], minimum value is always 0 which
-     *                         indicates mute state.
-     *
-     * Data type looks like:
-     *   int32Values[0] : audio context as defined in VehicleAudioContextFlag.
-     *                    If only physical stream is supported
-     *                    (configArray[0] == 0), this must represent physical
-     *                    stream number.
-     *   int32Values[1] : volume level, valid range is 0 (mute) to max level
-     *                    defined in the config.
-     *   int32Values[2] : One of VehicleAudioVolumeState.
-     *
-     * HAL implementations must check the incoming value of audio context
-     * field in get call to return the right volume.
-     *
-     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
-     * @access VehiclePropertyAccess:READ_WRITE
-     * @config_flags all audio contexts supported.
-     */
-    AUDIO_VOLUME = (
-        0x0901
-        | VehiclePropertyGroup:SYSTEM
-        | VehiclePropertyType:INT32_VEC
-        | VehicleArea:GLOBAL),
-
-    /**
-     * Property to allow audio volume sync from external components like audio HAL.
-     * Some vehicle HAL implementation may get volume control from audio HAL and in such
-     * case, setting AUDIO_VOLUME_EXT_SYNC property may trigger event in AUDIO_VOLUME property.
-     * Data format for this property is the same as AUDIO_VOLUME property.
-     *
-     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
-     * @access VehiclePropertyAccess:READ_WRITE
-     * @config_flags all audio contexts supported.
-     */
-    AUDIO_VOLUME_EXT_SYNC = (
-        0x0911
-        | VehiclePropertyGroup:SYSTEM
-        | VehiclePropertyType:INT32_VEC
-        | VehicleArea:GLOBAL),
-
-    /**
-     * Property for handling volume limit set by user. This limits maximum
-     * volume that can be set per each context or physical stream.
-     *
-     * VehiclePropConfig
-     *   configArray[0] : bit flags of all supported audio contexts. If this is
-     *                    0, audio volume is controlled per physical stream.
-     *   configArray[1] : flags defined in VehicleAudioVolumeCapabilityFlag
-     *                    to represent audio module's capability.
-     *
-     * Data type looks like:
-     *   int32Values[0] : audio context as defined in VehicleAudioContextFlag.
-     *                    If only physical stream is supported
-     *                    (configArray[0] == 0), this must represent physical
-     *                    stream number.
-     *   int32Values[1] : maximum volume set to the stream. If there is no
-     *                    restriction, this value must be equal to
-     *                    AUDIO_VOLUME's max value.
-     *
-     * If car does not support this feature, this property must not be
-     * populated by HAL.
-     * HAL implementations must check the incoming value of audio context
-     * field in get call to return the right volume.
-     *
-     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
-     * @access VehiclePropertyAccess:READ_WRITE
-     * @config_flags all audio contexts supported.
-     */
-    AUDIO_VOLUME_LIMIT = (
-        0x0902
-        | VehiclePropertyGroup:SYSTEM
-        | VehiclePropertyType:INT32_VEC
-        | VehicleArea:GLOBAL),
-
-    /**
-     * Property to share audio routing policy of android side. This property is
-     * set at startup to pass audio policy in android side down to
-     * vehicle HAL and car audio module.
-     *
-     *   int32Values[0] : audio stream where the audio for the application
-     *                    context must be routed by default. Note that this is
-     *                    the default setting from system, but each app may
-     *                    still use different audio stream for whatever reason.
-     *   int32Values[1] : All audio contexts that must be sent through the
-     *                     physical stream. Flag is defined in
-     *                     VehicleAudioContextFlag.
-
-     * Setting of this property must be done for all available physical streams
-     * based on audio H/W variant information acquired from AUDIO_HW_VARIANT
-     * property.
-     *
-     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
-     * @access VehiclePropertyAccess:WRITE
-     */
-    AUDIO_ROUTING_POLICY = (
-        0x0903
-        | VehiclePropertyGroup:SYSTEM
-        | VehiclePropertyType:INT32_VEC
-        | VehicleArea:GLOBAL),
-
-    /**
-     * Property to return audio H/W variant type used in this car. This is a
-     * zero based index into the set of audio routing policies defined in
-     * R.array.audioRoutingPolicy on CarService, which  may be overlaid to
-     * support multiple variants. If this property does not exist, the default
-     * audio policy must be used.
-     *
-     * @change_mode VehiclePropertyChangeMode:STATIC
-     * @access VehiclePropertyAccess:READ
-     * @config_flags Additional info on audio H/W. Must use
-     *               VehicleAudioHwVariantConfigFlag for this.
-     */
-    AUDIO_HW_VARIANT = (
-        0x0904
-        | VehiclePropertyGroup:SYSTEM
-        | VehiclePropertyType:INT32
-        | VehicleArea:GLOBAL),
-
-    /**
-     * Property to pass hint on external audio routing. When android side
-     * request focus with VehicleAudioExtFocusflag, this
-     * property must be set before setting AUDIO_FOCUS property as a hint for
-     * external audio source routing.
-     * Note that setting this property alone must not trigger any change.
-     * Audio routing must be changed only when AUDIO_FOCUS property is set.
-     * Note that this property allows passing custom value as long as it is
-     * defined in VehiclePropConfig#configString. This allows supporting
-     * non-standard routing options through this property.
-     * It is recommended to use separate name space for custom property to
-     * prevent conflict in future android releases.
-     * Enabling each external routing option is done by enabling each bit flag
-     * for the routing.
-     * This property can support up to 128 external routings.
-     * To give full flexibility, there is no standard definition for each bit
-     * flag and assigning each bit flag to specific routing type is decided by
-     * VehiclePropConfig#configString.  VehiclePropConfig#configString has
-     * format of each entry separated by ',' and each entry has format of
-     * bitFlagPositon:typeString[:physicalStreamNumber].
-     *  bitFlagPosition: represents which bit flag will be set to enable this
-     *    routing. 0 means LSB in int32Values[0]. 31 will be MSB in
-     *    int32Values[0]. 127 will MSB in int32Values[3].
-     *  typeString: string representation of external routing. Some types are
-     *    already defined in AUDIO_EXT_ROUTING_SOURCE_* and use them first
-     *    before adding something custom. Applications will find each routing
-     *    using this string.
-     *  physicalStreamNumber: This part is optional and represents physical
-     *    stream to android which will be disabled when this routing is enabled.
-     *    If not specified, this routing must not affect physical streams to
-     *    android.
-     * As an example, let's assume a system with two physical streams, 0 for
-     * media and 1 for nav guidance. And let's assume external routing option
-     * of am fm radio, external navigation guidance, satellite radio, and one
-     * custom. Let's assume that radio and satellite replaces physical stream 0
-     * and external navigation replaces physical stream 1. And bit flag will be
-     * assigned in the order listed above. This configuration will look like
-     * this in config_string:
-     *  "0:RADIO_AM_FM:0,1:EXT_NAV_GUIDANCE:1,2:RADIO_SATELLITE:0,3:com.test.SOMETHING_CUSTOM"
-     * When android requests RADIO_AM_FM, int32Values[0] will be set to 0x1.
-     * When android requests RADIO_SATELLITE + EXT_NAV_GUIDANCE, int32Values[0]
-     * will be set to 0x2|0x4.
-     *
-     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
-     * @access VehiclePropertyAccess:READ_WRITE
-     * @config_string List of all avaiable external source in the system.
-     */
-    AUDIO_EXT_ROUTING_HINT = (
-        0x0905
-        | VehiclePropertyGroup:SYSTEM
-        | VehiclePropertyType:INT32_VEC
-        | VehicleArea:GLOBAL),
-
-    /**
-     * Represents state of audio stream. Audio HAL should set this when a stream is starting or
-     * ending. Car service can request focus for audio played without focus. If such feature
-     * is not required, this property does not need to be implemented.
-     * Car service only monitors setting of this property. It is up to each vehicle HAL
-     * implementation to add necessary action but default implementation will be doing nothing on
-     * this propery's set from audio HAL.
-     * Actual streaming of data should be done only after getting focus for the given stream from
-     * car audio module. Focus can be already granted when stream is started. Focus state can be
-     * monitored by monitoring AUDIO_FOCUS property. If car does not support
-     * AUDIO_FOCUS property, there is no need to monitor focus as focus is assumed to be
-     * granted always.
-     * Data has the following format:
-     *   int32_array[0] : vehicle_audio_stream_state, 0: stopped, 1: started
-     *   int32_array[1] : stream number like 0, 1, 2, ...
-     *
-     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
-     * @access VehiclePropertyAccess:READ_WRITE
-     */
-    AUDIO_STREAM_STATE  = (
-        0x0906
-        | VehiclePropertyGroup:SYSTEM
-        | VehiclePropertyType:INT32_VEC
-        | VehicleArea:GLOBAL),
-
-    /**
-     * Property to control car specific audio parameters. Each parameter is defined as string key-
-     * value pair.
-     * set and event notification can pass multiple parameters using the
-     * following format:
-     *   key1=value1;key2=value2;...
-     * get call can request multiple parameters using the following format:
-     *   key1;key2;...
-     * Response for get call has the same format as set.
-     *
-     * VehiclePropConfig
-     *   configString: give list of all supported keys with ; as separator. For example:
-     *     key1;key2;...
-     *
-     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
-     * @access VehiclePropertyAccess:READ_WRITE
-     */
-    AUDIO_PARAMETERS = (
-        0x907
-        | VehiclePropertyGroup:SYSTEM
-        | VehiclePropertyType:STRING
-        | VehicleArea:GLOBAL),
-
-    /**
      * Property to control power state of application processor
      *
      * It is assumed that AP's power state is controller by separate power
@@ -2243,256 +1903,6 @@
     VEHICLE_RADIO_PRESET_MIN_VALUE = 1,
 };
 
-enum VehicleAudioFocusRequest : int32_t {
-    REQUEST_GAIN = 0x1,
-    REQUEST_GAIN_TRANSIENT = 0x2,
-    REQUEST_GAIN_TRANSIENT_MAY_DUCK = 0x3,
-    /**
-     * This is for the case where android side plays sound like UI feedback
-     * and car side does not need to duck existing playback as long as
-     * requested stream is available.
-     */
-    REQUEST_GAIN_TRANSIENT_NO_DUCK = 0x4,
-    REQUEST_RELEASE = 0x5,
-};
-
-enum VehicleAudioFocusState : int32_t {
-    /**
-     * Android side has permanent focus and can play allowed streams.
-     */
-    STATE_GAIN = 0x1,
-
-    /**
-     * Android side has transient focus and can play allowed streams.
-     */
-    STATE_GAIN_TRANSIENT = 0x2,
-
-    /**
-     * Car audio module is playing guidance kind of sound outside Android.
-     * Android side can still play through allowed streams with ducking.
-     */
-    STATE_LOSS_TRANSIENT_CAN_DUCK = 0x3,
-
-    /**
-     * Car audio module is playing transient sound outside Android. Android side
-     * must stop playing any sounds.
-     */
-    STATE_LOSS_TRANSIENT = 0x4,
-
-    /**
-     * Android side has lost focus and cannot play any sound.
-     */
-    STATE_LOSS = 0x5,
-
-    /**
-     * car audio module is playing safety critical sound, and Android side cannot
-     * request focus until the current state is finished. car audio module
-     * restore it to the previous state when it can allow Android to play.
-     */
-    STATE_LOSS_TRANSIENT_EXLCUSIVE = 0x6,
-};
-
-/**
- * Flags to represent multiple streams by combining these.
- */
-enum VehicleAudioStreamFlag : int32_t {
-    STREAM0_FLAG = (0x1 << 0),
-    STREAM1_FLAG = (0x1 << 1),
-    STREAM2_FLAG = (0x1 << 2),
-};
-
-/**
- * Represents stream number (always 0 to N -1 where N is max number of streams).
- * Can be used for audio related property expecting one stream.
- */
-enum VehicleAudioStream : int32_t {
-    STREAM0 = 0,
-    STREAM1 = 1,
-};
-
-/**
- * Flag to represent external focus state (outside Android).
- */
-enum VehicleAudioExtFocusFlag : int32_t {
-    /**
-     * No external focus holder.
-     */
-    NONE_FLAG = 0x0,
-
-    /**
-     * Car side (outside Android) has component holding GAIN kind of focus state.
-     */
-    PERMANENT_FLAG = 0x1,
-
-    /**
-     * Car side (outside Android) has component holding GAIN_TRANSIENT kind of
-     * focus state.
-     */
-    TRANSIENT_FLAG = 0x2,
-
-    /**
-     * Car side is expected to play something while focus is held by Android side.
-     * One example can be radio attached in car side. But Android's radio app
-     * still must have focus, and Android side must be in GAIN state, but
-     * media stream will not be allocated to Android side and car side can play
-     * radio any time while this flag is active.
-     */
-    PLAY_ONLY_FLAG = 0x4,
-
-    /**
-     * Car side must mute any media including radio. This can be used with any
-     * focus request including GAIN* and RELEASE.
-     */
-    MUTE_MEDIA_FLAG = 0x8,
-};
-
-/**
- * Index in int32Values for VehicleProperty#AUDIO_FOCUS property.
- */
-enum VehicleAudioFocusIndex : int32_t {
-    FOCUS = 0,
-    STREAMS = 1,
-    EXTERNAL_FOCUS_STATE = 2,
-    AUDIO_CONTEXTS = 3,
-};
-
-/**
- * Flags to tell the current audio context.
- */
-enum VehicleAudioContextFlag : int32_t {
-    /** Music playback is currently active. */
-    MUSIC_FLAG = 0x1,
-
-    /** Navigation is currently running. */
-    NAVIGATION_FLAG = 0x2,
-
-    /** Voice command session is currently running. */
-    VOICE_COMMAND_FLAG = 0x4,
-
-    /** Voice call is currently active. */
-    CALL_FLAG = 0x8,
-
-    /**
-     * Alarm is active.
-     * This must be only used in VehicleProperty#AUDIO_ROUTING_POLICY.
-     */
-    ALARM_FLAG = 0x10,
-
-    /**
-     * Notification sound is active.
-     * This must be only used in VehicleProperty#AUDIO_ROUTING_POLICY.
-     */
-    NOTIFICATION_FLAG = 0x20,
-
-    /**
-     * Context unknown. Only used for VehicleProperty#AUDIO_ROUTING_POLICY to
-     * represent default stream for unknown contents.
-     */
-    UNKNOWN_FLAG = 0x40,
-
-    /** Safety alert / warning is played. */
-    SAFETY_ALERT_FLAG = 0x80,
-
-    /** CD / DVD kind of audio is played */
-    CD_ROM_FLAG = 0x100,
-
-    /** Aux audio input is played */
-    AUX_AUDIO_FLAG = 0x200,
-
-    /** system sound like UI feedback */
-    SYSTEM_SOUND_FLAG = 0x400,
-
-    /** Radio is played */
-    RADIO_FLAG = 0x800,
-
-    /** Ext source is played. This is for tagging generic ext sources. */
-    EXT_SOURCE_FLAG = 0x1000,
-
-    /** The phone ring tone is played */
-    RINGTONE_FLAG = 0x2000
-};
-
-/**
- * flags to represent capability of audio volume property.
- * used in configArray[1] of VehiclePropConfig.
- */
-enum VehicleAudioVolumeCapabilityFlag : int32_t {
-    /**
-     * External audio module or vehicle hal has persistent storage to keep the
-     * volume level. When this is set, the audio volume level for each context
-     * will be retrieved from the property when the system starts up.
-     * And external audio module is also expected to adjust volume automatically
-     * whenever there is an audio context change.
-     * When this flag is not set, android side will assume that there is no
-     * persistent storage and the value stored in the android side will be used to
-     * initialize the volume level, and android side will set volume level
-     * of each physical stream whenever there is an audio context change.
-     */
-    PERSISTENT_STORAGE = 0x1,
-
-    /**
-     * [DEPRECATED]
-     * When this flag is set, the H/W can support only single master volume for
-     * all streams. There is no way to set volume level differently for each stream
-     * or context.
-     */
-    MASTER_VOLUME_ONLY = 0x2,
-};
-
-/**
- * enum to represent audio volume state.
- */
-enum VehicleAudioVolumeState : int32_t {
-    STATE_OK = 0,
-
-    /**
-     * Audio volume has reached volume limit set in
-     * VehicleProperty#AUDIO_VOLUME_LIMIT and user's request to increase volume
-     * further is not allowed.
-     */
-    STATE_LIMIT_REACHED = 1,
-};
-
-/**
- * Index in int32Values for VehicleProperty#AUDIO_VOLUME property.
- */
-enum VehicleAudioVolumeIndex : int32_t {
-    STREAM = 0,
-    VOLUME = 1,
-    STATE = 2,
-};
-
-/**
- * Index in int32Values for VehicleProperty#AUDIO_VOLUME_LIMIT property.
- */
-enum VehicleAudioVolumeLimitIndex : int32_t {
-    STREAM = 0,
-    MAX_VOLUME = 1,
-};
-
-/**
- * Index in int32Values for VehicleProperty#AUDIO_ROUTING_POLICY property.
- */
-enum VehicleAudioRoutingPolicyIndex : int32_t {
-    STREAM = 0,
-    CONTEXTS = 1,
-};
-
-/**
- * Flag to be used in VehiclePropConfig#configFlags for
- * VehicleProperty#AUDIO_HW_VARIANT.
- */
-enum VehicleAudioHwVariantConfigFlag : int32_t {
-  /**
-   * Flag to tell that radio is internal to android and radio must
-   * be treated like other android stream like media.
-   * When this flag is not set or AUDIO_HW_VARIANT does not exist,
-   * radio is treated as external module. This may affect audio focus
-   * handling as well.
-   */
-  INTERNAL_RADIO_FLAG = 0x1,
-};
-
 enum VehicleApPowerStateConfigFlag : int32_t /* NOTE: type is guessed */ {
     /**
      * AP can enter deep sleep state. If not set, AP will always shutdown from
diff --git a/broadcastradio/1.2/default/BroadcastRadio.cpp b/broadcastradio/1.2/default/BroadcastRadio.cpp
index 5164e47..74f6589 100644
--- a/broadcastradio/1.2/default/BroadcastRadio.cpp
+++ b/broadcastradio/1.2/default/BroadcastRadio.cpp
@@ -107,7 +107,7 @@
     prop10.numTuners = 1;
     prop10.numAudioSources = 1;
     prop10.supportsCapture = false;
-    prop11.supportsBackgroundScanning = false;
+    prop11.supportsBackgroundScanning = true;
     prop11.supportedProgramTypes = hidl_vec<uint32_t>({
         static_cast<uint32_t>(ProgramType::AM), static_cast<uint32_t>(ProgramType::FM),
         static_cast<uint32_t>(ProgramType::AM_HD), static_cast<uint32_t>(ProgramType::FM_HD),
diff --git a/broadcastradio/2.0/Android.bp b/broadcastradio/2.0/Android.bp
index 7409005..2434fdc 100644
--- a/broadcastradio/2.0/Android.bp
+++ b/broadcastradio/2.0/Android.bp
@@ -8,7 +8,7 @@
     },
     srcs: [
         "types.hal",
-        "IAnnouncementObserver.hal",
+        "IAnnouncementListener.hal",
         "IBroadcastRadio.hal",
         "ICloseHandle.hal",
         "ITunerCallback.hal",
diff --git a/broadcastradio/2.0/IAnnouncementObserver.hal b/broadcastradio/2.0/IAnnouncementListener.hal
similarity index 85%
rename from broadcastradio/2.0/IAnnouncementObserver.hal
rename to broadcastradio/2.0/IAnnouncementListener.hal
index c91e29a..1b4960c 100644
--- a/broadcastradio/2.0/IAnnouncementObserver.hal
+++ b/broadcastradio/2.0/IAnnouncementListener.hal
@@ -16,11 +16,11 @@
 package android.hardware.broadcastradio@2.0;
 
 /**
- * Callback interface for announcement observer.
+ * Callback interface for announcement listener.
  *
- * For typical configuration, the observer is a broadcast radio service.
+ * For typical configuration, the listener is a broadcast radio service.
  */
-interface IAnnouncementObserver {
+interface IAnnouncementListener {
     /**
      * Called whenever announcement list has changed.
      *
diff --git a/broadcastradio/2.0/IBroadcastRadio.hal b/broadcastradio/2.0/IBroadcastRadio.hal
index 7578f44..bedc362 100644
--- a/broadcastradio/2.0/IBroadcastRadio.hal
+++ b/broadcastradio/2.0/IBroadcastRadio.hal
@@ -15,7 +15,7 @@
 
 package android.hardware.broadcastradio@2.0;
 
-import IAnnouncementObserver;
+import IAnnouncementListener;
 import ICloseHandle;
 import ITunerCallback;
 import ITunerSession;
@@ -104,7 +104,7 @@
     getImage(uint32_t id) generates (vec<uint8_t> image);
 
     /**
-     * Registers announcement observer.
+     * Registers announcement listener.
      *
      * If there is at least one observer registered, HAL implementation must
      * notify about announcements even if no sessions are active.
@@ -113,15 +113,15 @@
      * automatically.
      *
      * @param enabled The list of announcement types to watch for.
-     * @param cb The callback interface.
+     * @param listener The listener interface.
      * @return result OK in case of success.
      *                NOT_SUPPORTED if the tuner doesn't support announcements.
      * @return closeHandle A handle to unregister observer,
      *                     nullptr if result was not OK.
      */
-    registerAnnouncementObserver(
+    registerAnnouncementListener(
             vec<AnnouncementType> enabled,
-            IAnnouncementObserver cb
+            IAnnouncementListener listener
         ) generates (
             Result result,
             ICloseHandle closeHandle
diff --git a/broadcastradio/2.0/default/BroadcastRadio.cpp b/broadcastradio/2.0/default/BroadcastRadio.cpp
index d16aaff..aa5afad 100644
--- a/broadcastradio/2.0/default/BroadcastRadio.cpp
+++ b/broadcastradio/2.0/default/BroadcastRadio.cpp
@@ -141,9 +141,9 @@
     return {};
 }
 
-Return<void> BroadcastRadio::registerAnnouncementObserver(
-    const hidl_vec<AnnouncementType>& enabled, const sp<IAnnouncementObserver>& /* cb */,
-    registerAnnouncementObserver_cb _hidl_cb) {
+Return<void> BroadcastRadio::registerAnnouncementListener(
+    const hidl_vec<AnnouncementType>& enabled, const sp<IAnnouncementListener>& /* listener */,
+    registerAnnouncementListener_cb _hidl_cb) {
     ALOGV("%s(%s)", __func__, toString(enabled).c_str());
 
     _hidl_cb(Result::NOT_SUPPORTED, nullptr);
diff --git a/broadcastradio/2.0/default/BroadcastRadio.h b/broadcastradio/2.0/default/BroadcastRadio.h
index 7904946..8c14d9e 100644
--- a/broadcastradio/2.0/default/BroadcastRadio.h
+++ b/broadcastradio/2.0/default/BroadcastRadio.h
@@ -36,9 +36,9 @@
     Return<void> getDabRegionConfig(getDabRegionConfig_cb _hidl_cb);
     Return<void> openSession(const sp<ITunerCallback>& callback, openSession_cb _hidl_cb) override;
     Return<void> getImage(uint32_t id, getImage_cb _hidl_cb);
-    Return<void> registerAnnouncementObserver(const hidl_vec<AnnouncementType>& enabled,
-                                              const sp<IAnnouncementObserver>& cb,
-                                              registerAnnouncementObserver_cb _hidl_cb);
+    Return<void> registerAnnouncementListener(const hidl_vec<AnnouncementType>& enabled,
+                                              const sp<IAnnouncementListener>& listener,
+                                              registerAnnouncementListener_cb _hidl_cb);
 
     std::reference_wrapper<const VirtualRadio> mVirtualRadio;
     Properties mProperties;
diff --git a/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp b/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp
index 1111478..8d9d622 100644
--- a/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp
+++ b/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp
@@ -90,7 +90,7 @@
     utils::ProgramInfoSet mProgramList;
 };
 
-struct AnnouncementObserverMock : public IAnnouncementObserver {
+struct AnnouncementListenerMock : public IAnnouncementListener {
     MOCK_METHOD1(onListUpdated, Return<void>(const hidl_vec<Announcement>&));
 };
 
@@ -702,15 +702,15 @@
 }
 
 /**
- * Test announcement observer registration.
+ * Test announcement listener registration.
  *
  * Verifies that:
- *  - registerAnnouncementObserver either succeeds or returns NOT_SUPPORTED;
+ *  - registerAnnouncementListener either succeeds or returns NOT_SUPPORTED;
  *  - if it succeeds, it returns a valid close handle (which is a nullptr otherwise);
  *  - closing handle does not crash.
  */
-TEST_F(BroadcastRadioHalTest, AnnouncementObserverRegistration) {
-    sp<AnnouncementObserverMock> observer = new AnnouncementObserverMock();
+TEST_F(BroadcastRadioHalTest, AnnouncementListenerRegistration) {
+    sp<AnnouncementListenerMock> listener = new AnnouncementListenerMock();
 
     Result halResult = Result::UNKNOWN_ERROR;
     sp<ICloseHandle> closeHandle = nullptr;
@@ -720,7 +720,7 @@
     };
 
     auto hidlResult =
-        mModule->registerAnnouncementObserver({AnnouncementType::EMERGENCY}, observer, cb);
+        mModule->registerAnnouncementListener({AnnouncementType::EMERGENCY}, listener, cb);
     ASSERT_TRUE(hidlResult.isOk());
 
     if (halResult == Result::NOT_SUPPORTED) {
diff --git a/compatibility_matrices/Android.mk b/compatibility_matrices/Android.mk
new file mode 100644
index 0000000..2a01480
--- /dev/null
+++ b/compatibility_matrices/Android.mk
@@ -0,0 +1,138 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+# Install all compatibility_matrix.*.xml to /system/etc/vintf
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := framework_compatibility_matrix.legacy.xml
+LOCAL_MODULE_STEM := compatibility_matrix.legacy.xml
+LOCAL_SRC_FILES := $(LOCAL_MODULE_STEM)
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH := $(TARGET_OUT)/etc/vintf
+include $(BUILD_PREBUILT)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := framework_compatibility_matrix.1.xml
+LOCAL_MODULE_STEM := compatibility_matrix.1.xml
+LOCAL_SRC_FILES := $(LOCAL_MODULE_STEM)
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH := $(TARGET_OUT)/etc/vintf
+include $(BUILD_PREBUILT)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := framework_compatibility_matrix.2.xml
+LOCAL_MODULE_STEM := compatibility_matrix.2.xml
+LOCAL_SRC_FILES := $(LOCAL_MODULE_STEM)
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH := $(TARGET_OUT)/etc/vintf
+include $(BUILD_PREBUILT)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := framework_compatibility_matrix.current.xml
+LOCAL_MODULE_STEM := compatibility_matrix.current.xml
+LOCAL_SRC_FILES := $(LOCAL_MODULE_STEM)
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH := $(TARGET_OUT)/etc/vintf
+include $(BUILD_PREBUILT)
+
+# Framework Compatibility Matrix without HALs
+include $(CLEAR_VARS)
+LOCAL_MODULE        := framework_compatibility_matrix.empty.xml
+LOCAL_MODULE_STEM   := compatibility_matrix.empty.xml
+LOCAL_MODULE_CLASS  := ETC
+LOCAL_MODULE_PATH   := $(TARGET_OUT)/etc/vintf
+
+GEN := $(local-generated-sources-dir)/$(LOCAL_MODULE_STEM)
+
+$(GEN): PRIVATE_FLAGS :=
+
+ifeq (true,$(BOARD_AVB_ENABLE))
+$(GEN): $(AVBTOOL)
+# INTERNAL_AVB_SYSTEM_SIGNING_ARGS consists of BOARD_AVB_SYSTEM_KEY_PATH and
+# BOARD_AVB_SYSTEM_ALGORITHM. We should add the dependency of key path, which
+# is a file, here.
+$(GEN): $(BOARD_AVB_SYSTEM_KEY_PATH)
+# Use deferred assignment (=) instead of immediate assignment (:=).
+# Otherwise, cannot get INTERNAL_AVB_SYSTEM_SIGNING_ARGS.
+$(GEN): FRAMEWORK_VBMETA_VERSION = $$("$(AVBTOOL)" add_hashtree_footer \
+                           --print_required_libavb_version \
+                           $(INTERNAL_AVB_SYSTEM_SIGNING_ARGS) \
+                           $(BOARD_AVB_SYSTEM_ADD_HASHTREE_FOOTER_ARGS))
+else
+$(GEN): FRAMEWORK_VBMETA_VERSION := 0.0
+endif
+
+# Specify kernel versions that the current framework supports. These versions,
+# along with kernel configurations, are written to the framework compatibility
+# matrix.
+$(GEN): KERNEL_VERSIONS := 3.18 4.4 4.9
+
+# Specify the location of android-base*.cfg files.
+$(GEN): KERNEL_CONFIG_DATA := kernel/configs
+
+$(GEN): $(foreach version,$(KERNEL_VERSIONS),\
+	$(wildcard $(KERNEL_CONFIG_DATA)/android-$(version)/android-base*.cfg))
+$(GEN): PRIVATE_FLAGS += $(foreach version,$(KERNEL_VERSIONS),\
+	--kernel=$(version):$(call normalize-path-list,\
+		$(wildcard $(KERNEL_CONFIG_DATA)/android-$(version)/android-base*.cfg)))
+
+$(GEN): $(LOCAL_PATH)/compatibility_matrix.empty.xml $(HOST_OUT_EXECUTABLES)/assemble_vintf
+	POLICYVERS=$(POLICYVERS) \
+		BOARD_SEPOLICY_VERS=$(BOARD_SEPOLICY_VERS) \
+		FRAMEWORK_VBMETA_VERSION=$(FRAMEWORK_VBMETA_VERSION) \
+		$(HOST_OUT_EXECUTABLES)/assemble_vintf \
+		-i $< -o $@ $(PRIVATE_FLAGS)
+LOCAL_PREBUILT_MODULE_FILE := $(GEN)
+include $(BUILD_PREBUILT)
+
+# Framework Compatibility Matrix
+include $(CLEAR_VARS)
+LOCAL_MODULE        := framework_compatibility_matrix.xml
+LOCAL_MODULE_STEM   := compatibility_matrix.xml
+LOCAL_MODULE_CLASS  := ETC
+LOCAL_MODULE_PATH   := $(TARGET_OUT)
+
+LOCAL_REQUIRED_MODULES := \
+    framework_compatibility_matrix.legacy.xml \
+    framework_compatibility_matrix.1.xml \
+    framework_compatibility_matrix.2.xml \
+    framework_compatibility_matrix.current.xml \
+    framework_compatibility_matrix.empty.xml
+
+GEN := $(local-generated-sources-dir)/compatibility_matrix.xml
+
+$(GEN): PRIVATE_FLAGS :=
+
+ifdef BUILT_VENDOR_MANIFEST
+$(GEN): $(BUILT_VENDOR_MANIFEST)
+$(GEN): PRIVATE_FLAGS += -c "$(BUILT_VENDOR_MANIFEST)"
+endif
+
+MATRIX_SRC_FILES := $(call module-installed-files,$(LOCAL_REQUIRED_MODULES))
+$(GEN): PRIVATE_MATRIX_SRC_FILES := $(MATRIX_SRC_FILES)
+$(GEN): $(MATRIX_SRC_FILES) $(HOST_OUT_EXECUTABLES)/assemble_vintf
+	PRODUCT_ENFORCE_VINTF_MANIFEST=$(PRODUCT_ENFORCE_VINTF_MANIFEST) \
+		$(HOST_OUT_EXECUTABLES)/assemble_vintf \
+		-i $(call normalize-path-list,$(PRIVATE_MATRIX_SRC_FILES)) \
+		-o $@ $(PRIVATE_FLAGS)
+
+MATRIX_SRC_FILES :=
+
+LOCAL_PREBUILT_MODULE_FILE := $(GEN)
+include $(BUILD_PREBUILT)
+BUILT_SYSTEM_COMPATIBILITY_MATRIX := $(LOCAL_BUILT_MODULE)
diff --git a/compatibility_matrix.1.xml b/compatibility_matrices/compatibility_matrix.1.xml
similarity index 100%
rename from compatibility_matrix.1.xml
rename to compatibility_matrices/compatibility_matrix.1.xml
diff --git a/compatibility_matrix.2.xml b/compatibility_matrices/compatibility_matrix.2.xml
similarity index 100%
rename from compatibility_matrix.2.xml
rename to compatibility_matrices/compatibility_matrix.2.xml
diff --git a/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
similarity index 97%
rename from compatibility_matrix.current.xml
rename to compatibility_matrices/compatibility_matrix.current.xml
index 9287d67..1aaef1e 100644
--- a/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -16,6 +16,14 @@
         </interface>
     </hal>
     <hal format="hidl" optional="true">
+        <name>android.hardware.authsecret</name>
+        <version>1.0</version>
+        <interface>
+            <name>IAuthSecret</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
         <name>android.hardware.automotive.evs</name>
         <version>1.0</version>
         <interface>
diff --git a/compatibility_matrices/compatibility_matrix.empty.xml b/compatibility_matrices/compatibility_matrix.empty.xml
new file mode 100644
index 0000000..216f5f1
--- /dev/null
+++ b/compatibility_matrices/compatibility_matrix.empty.xml
@@ -0,0 +1 @@
+<compatibility-matrix version="1.0" type="framework" />
diff --git a/compatibility_matrix.legacy.xml b/compatibility_matrices/compatibility_matrix.legacy.xml
similarity index 100%
rename from compatibility_matrix.legacy.xml
rename to compatibility_matrices/compatibility_matrix.legacy.xml
diff --git a/graphics/allocator/2.0/default/Android.bp b/graphics/allocator/2.0/default/Android.bp
index 9968f41..ed2ecbb 100644
--- a/graphics/allocator/2.0/default/Android.bp
+++ b/graphics/allocator/2.0/default/Android.bp
@@ -1,10 +1,15 @@
 cc_library_shared {
     name: "android.hardware.graphics.allocator@2.0-impl",
     defaults: ["hidl_defaults"],
-    proprietary: true,
+    vendor: true,
     relative_install_path: "hw",
-    srcs: ["Gralloc.cpp", "Gralloc0Allocator.cpp", "Gralloc1Allocator.cpp"],
-    cppflags: ["-Wall", "-Wextra"],
+    srcs: ["passthrough.cpp"],
+    static_libs: [
+        "android.hardware.graphics.allocator@2.0-passthrough",
+    ],
+    header_libs: [
+        "android.hardware.graphics.allocator@2.0-hal",
+    ],
     shared_libs: [
         "android.hardware.graphics.allocator@2.0",
         "libbase",
@@ -15,9 +20,6 @@
         "liblog",
         "libutils",
     ],
-    header_libs: [
-        "libgrallocmapperincludes",
-    ],
 }
 
 cc_binary {
@@ -36,13 +38,3 @@
         "libutils",
     ],
 }
-
-cc_library_static {
-    name: "libgralloc1-adapter",
-    defaults: ["hidl_defaults"],
-    srcs: ["gralloc1-adapter.cpp", "Gralloc1On0Adapter.cpp"],
-    include_dirs: ["system/core/libsync/include"],
-    cflags: ["-Wall", "-Wextra"],
-    export_include_dirs: ["."],
-    whole_static_libs: ["libgrallocusage"],
-}
diff --git a/graphics/allocator/2.0/default/Gralloc.cpp b/graphics/allocator/2.0/default/Gralloc.cpp
deleted file mode 100644
index 273d3f5..0000000
--- a/graphics/allocator/2.0/default/Gralloc.cpp
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright 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.
- */
-
-#define LOG_TAG "GrallocPassthrough"
-
-#include "Gralloc.h"
-#include "Gralloc0Allocator.h"
-#include "Gralloc1Allocator.h"
-
-#include <log/log.h>
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace allocator {
-namespace V2_0 {
-namespace implementation {
-
-IAllocator* HIDL_FETCH_IAllocator(const char* /* name */) {
-    const hw_module_t* module = nullptr;
-    int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
-    if (err) {
-        ALOGE("failed to get gralloc module");
-        return nullptr;
-    }
-
-    uint8_t major = (module->module_api_version >> 8) & 0xff;
-    switch (major) {
-        case 1:
-            return new Gralloc1Allocator(module);
-        case 0:
-            return new Gralloc0Allocator(module);
-        default:
-            ALOGE("unknown gralloc module major version %d", major);
-            return nullptr;
-    }
-}
-
-} // namespace implementation
-} // namespace V2_0
-} // namespace allocator
-} // namespace graphics
-} // namespace hardware
-} // namespace android
diff --git a/graphics/allocator/2.0/default/Gralloc.h b/graphics/allocator/2.0/default/Gralloc.h
deleted file mode 100644
index c79eeaa..0000000
--- a/graphics/allocator/2.0/default/Gralloc.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright 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.
- */
-
-#ifndef ANDROID_HARDWARE_GRAPHICS_ALLOCATOR_V2_0_GRALLOC_H
-#define ANDROID_HARDWARE_GRAPHICS_ALLOCATOR_V2_0_GRALLOC_H
-
-#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace allocator {
-namespace V2_0 {
-namespace implementation {
-
-extern "C" IAllocator* HIDL_FETCH_IAllocator(const char* name);
-
-} // namespace implementation
-} // namespace V2_0
-} // namespace allocator
-} // namespace graphics
-} // namespace hardware
-} // namespace android
-
-#endif // ANDROID_HARDWARE_GRAPHICS_ALLOCATOR_V2_0_GRALLOC_H
diff --git a/graphics/allocator/2.0/default/Gralloc0Allocator.cpp b/graphics/allocator/2.0/default/Gralloc0Allocator.cpp
deleted file mode 100644
index 3b62bb3..0000000
--- a/graphics/allocator/2.0/default/Gralloc0Allocator.cpp
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright 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.
- */
-
-#define LOG_TAG "Gralloc0Allocator"
-
-#include "Gralloc0Allocator.h"
-#include "GrallocBufferDescriptor.h"
-
-#include <vector>
-
-#include <string.h>
-
-#include <log/log.h>
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace allocator {
-namespace V2_0 {
-namespace implementation {
-
-using android::hardware::graphics::mapper::V2_0::implementation::
-    grallocDecodeBufferDescriptor;
-
-Gralloc0Allocator::Gralloc0Allocator(const hw_module_t* module) {
-    int result = gralloc_open(module, &mDevice);
-    if (result) {
-        LOG_ALWAYS_FATAL("failed to open gralloc0 device: %s",
-                         strerror(-result));
-    }
-}
-
-Gralloc0Allocator::~Gralloc0Allocator() {
-    gralloc_close(mDevice);
-}
-
-Return<void> Gralloc0Allocator::dumpDebugInfo(dumpDebugInfo_cb hidl_cb) {
-    char buf[4096] = {};
-    if (mDevice->dump) {
-        mDevice->dump(mDevice, buf, sizeof(buf));
-        buf[sizeof(buf) - 1] = '\0';
-    }
-
-    hidl_cb(hidl_string(buf));
-
-    return Void();
-}
-
-Return<void> Gralloc0Allocator::allocate(const BufferDescriptor& descriptor,
-                                         uint32_t count, allocate_cb hidl_cb) {
-    IMapper::BufferDescriptorInfo descriptorInfo;
-    if (!grallocDecodeBufferDescriptor(descriptor, &descriptorInfo)) {
-        hidl_cb(Error::BAD_DESCRIPTOR, 0, hidl_vec<hidl_handle>());
-        return Void();
-    }
-
-    Error error = Error::NONE;
-    uint32_t stride = 0;
-    std::vector<hidl_handle> buffers;
-    buffers.reserve(count);
-
-    // allocate the buffers
-    for (uint32_t i = 0; i < count; i++) {
-        buffer_handle_t tmpBuffer;
-        uint32_t tmpStride;
-        error = allocateOne(descriptorInfo, &tmpBuffer, &tmpStride);
-        if (error != Error::NONE) {
-            break;
-        }
-
-        if (stride == 0) {
-            stride = tmpStride;
-        } else if (stride != tmpStride) {
-            // non-uniform strides
-            mDevice->free(mDevice, tmpBuffer);
-            stride = 0;
-            error = Error::UNSUPPORTED;
-            break;
-        }
-
-        buffers.emplace_back(hidl_handle(tmpBuffer));
-    }
-
-    // return the buffers
-    hidl_vec<hidl_handle> hidl_buffers;
-    if (error == Error::NONE) {
-        hidl_buffers.setToExternal(buffers.data(), buffers.size());
-    }
-    hidl_cb(error, stride, hidl_buffers);
-
-    // free the buffers
-    for (const auto& buffer : buffers) {
-        mDevice->free(mDevice, buffer.getNativeHandle());
-    }
-
-    return Void();
-}
-
-Error Gralloc0Allocator::allocateOne(const IMapper::BufferDescriptorInfo& info,
-                                     buffer_handle_t* outBuffer,
-                                     uint32_t* outStride) {
-    if (info.layerCount > 1 || (info.usage >> 32) != 0) {
-        return Error::BAD_VALUE;
-    }
-
-    buffer_handle_t buffer = nullptr;
-    int stride = 0;
-    int result = mDevice->alloc(mDevice, info.width, info.height,
-                                static_cast<int>(info.format), info.usage,
-                                &buffer, &stride);
-    if (result) {
-        switch (result) {
-            case -EINVAL:
-                return Error::BAD_VALUE;
-            default:
-                return Error::NO_RESOURCES;
-        }
-    }
-
-    *outBuffer = buffer;
-    *outStride = stride;
-
-    return Error::NONE;
-}
-
-}  // namespace implementation
-}  // namespace V2_0
-}  // namespace allocator
-}  // namespace graphics
-}  // namespace hardware
-}  // namespace android
diff --git a/graphics/allocator/2.0/default/Gralloc0Allocator.h b/graphics/allocator/2.0/default/Gralloc0Allocator.h
deleted file mode 100644
index 0e90527..0000000
--- a/graphics/allocator/2.0/default/Gralloc0Allocator.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 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.
- */
-
-#ifndef ANDROID_HARDWARE_GRAPHICS_ALLOCATOR_V2_0_GRALLOC0ALLOCATOR_H
-#define ANDROID_HARDWARE_GRAPHICS_ALLOCATOR_V2_0_GRALLOC0ALLOCATOR_H
-
-#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
-#include <android/hardware/graphics/mapper/2.0/IMapper.h>
-#include <hardware/gralloc.h>
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace allocator {
-namespace V2_0 {
-namespace implementation {
-
-using android::hardware::graphics::mapper::V2_0::IMapper;
-using android::hardware::graphics::mapper::V2_0::BufferDescriptor;
-using android::hardware::graphics::mapper::V2_0::Error;
-
-class Gralloc0Allocator : public IAllocator {
-   public:
-    Gralloc0Allocator(const hw_module_t* module);
-    virtual ~Gralloc0Allocator();
-
-    // IAllocator interface
-    Return<void> dumpDebugInfo(dumpDebugInfo_cb hidl_cb) override;
-    Return<void> allocate(const BufferDescriptor& descriptor, uint32_t count,
-                          allocate_cb hidl_cb) override;
-
-   private:
-    Error allocateOne(const IMapper::BufferDescriptorInfo& info,
-                      buffer_handle_t* outBuffer, uint32_t* outStride);
-
-    alloc_device_t* mDevice;
-};
-
-}  // namespace implementation
-}  // namespace V2_0
-}  // namespace allocator
-}  // namespace graphics
-}  // namespace hardware
-}  // namespace android
-
-#endif  // ANDROID_HARDWARE_GRAPHICS_ALLOCATOR_V2_0_GRALLOC0ALLOCATOR_H
diff --git a/graphics/allocator/2.0/default/Gralloc1Allocator.cpp b/graphics/allocator/2.0/default/Gralloc1Allocator.cpp
deleted file mode 100644
index 6cbb791..0000000
--- a/graphics/allocator/2.0/default/Gralloc1Allocator.cpp
+++ /dev/null
@@ -1,329 +0,0 @@
-/*
- * Copyright 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.
- */
-
-#define LOG_TAG "Gralloc1Allocator"
-
-#include "Gralloc1Allocator.h"
-#include "GrallocBufferDescriptor.h"
-
-#include <vector>
-
-#include <string.h>
-
-#include <log/log.h>
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace allocator {
-namespace V2_0 {
-namespace implementation {
-
-using android::hardware::graphics::common::V1_0::BufferUsage;
-using android::hardware::graphics::mapper::V2_0::implementation::
-    grallocDecodeBufferDescriptor;
-
-Gralloc1Allocator::Gralloc1Allocator(const hw_module_t* module)
-    : mDevice(nullptr), mCapabilities(), mDispatch() {
-    int result = gralloc1_open(module, &mDevice);
-    if (result) {
-        LOG_ALWAYS_FATAL("failed to open gralloc1 device: %s",
-                         strerror(-result));
-    }
-
-    initCapabilities();
-    initDispatch();
-}
-
-Gralloc1Allocator::~Gralloc1Allocator() {
-    gralloc1_close(mDevice);
-}
-
-void Gralloc1Allocator::initCapabilities() {
-    uint32_t count = 0;
-    mDevice->getCapabilities(mDevice, &count, nullptr);
-
-    std::vector<int32_t> capabilities(count);
-    mDevice->getCapabilities(mDevice, &count, capabilities.data());
-    capabilities.resize(count);
-
-    for (auto capability : capabilities) {
-        if (capability == GRALLOC1_CAPABILITY_LAYERED_BUFFERS) {
-            mCapabilities.layeredBuffers = true;
-            break;
-        }
-    }
-}
-
-template <typename T>
-void Gralloc1Allocator::initDispatch(gralloc1_function_descriptor_t desc,
-                                     T* outPfn) {
-    auto pfn = mDevice->getFunction(mDevice, desc);
-    if (!pfn) {
-        LOG_ALWAYS_FATAL("failed to get gralloc1 function %d", desc);
-    }
-
-    *outPfn = reinterpret_cast<T>(pfn);
-}
-
-void Gralloc1Allocator::initDispatch() {
-    initDispatch(GRALLOC1_FUNCTION_DUMP, &mDispatch.dump);
-    initDispatch(GRALLOC1_FUNCTION_CREATE_DESCRIPTOR,
-                 &mDispatch.createDescriptor);
-    initDispatch(GRALLOC1_FUNCTION_DESTROY_DESCRIPTOR,
-                 &mDispatch.destroyDescriptor);
-    initDispatch(GRALLOC1_FUNCTION_SET_DIMENSIONS, &mDispatch.setDimensions);
-    initDispatch(GRALLOC1_FUNCTION_SET_FORMAT, &mDispatch.setFormat);
-    if (mCapabilities.layeredBuffers) {
-        initDispatch(GRALLOC1_FUNCTION_SET_LAYER_COUNT,
-                     &mDispatch.setLayerCount);
-    }
-    initDispatch(GRALLOC1_FUNCTION_SET_CONSUMER_USAGE,
-                 &mDispatch.setConsumerUsage);
-    initDispatch(GRALLOC1_FUNCTION_SET_PRODUCER_USAGE,
-                 &mDispatch.setProducerUsage);
-    initDispatch(GRALLOC1_FUNCTION_GET_STRIDE, &mDispatch.getStride);
-    initDispatch(GRALLOC1_FUNCTION_ALLOCATE, &mDispatch.allocate);
-    initDispatch(GRALLOC1_FUNCTION_RELEASE, &mDispatch.release);
-}
-
-Return<void> Gralloc1Allocator::dumpDebugInfo(dumpDebugInfo_cb hidl_cb) {
-    uint32_t len = 0;
-    mDispatch.dump(mDevice, &len, nullptr);
-
-    std::vector<char> buf(len + 1);
-    mDispatch.dump(mDevice, &len, buf.data());
-    buf.resize(len + 1);
-    buf[len] = '\0';
-
-    hidl_string reply;
-    reply.setToExternal(buf.data(), len);
-    hidl_cb(reply);
-
-    return Void();
-}
-
-Return<void> Gralloc1Allocator::allocate(const BufferDescriptor& descriptor,
-                                         uint32_t count, allocate_cb hidl_cb) {
-    IMapper::BufferDescriptorInfo descriptorInfo;
-    if (!grallocDecodeBufferDescriptor(descriptor, &descriptorInfo)) {
-        hidl_cb(Error::BAD_DESCRIPTOR, 0, hidl_vec<hidl_handle>());
-        return Void();
-    }
-
-    gralloc1_buffer_descriptor_t desc;
-    Error error = createDescriptor(descriptorInfo, &desc);
-    if (error != Error::NONE) {
-        hidl_cb(error, 0, hidl_vec<hidl_handle>());
-        return Void();
-    }
-
-    uint32_t stride = 0;
-    std::vector<hidl_handle> buffers;
-    buffers.reserve(count);
-
-    // allocate the buffers
-    for (uint32_t i = 0; i < count; i++) {
-        buffer_handle_t tmpBuffer;
-        uint32_t tmpStride;
-        error = allocateOne(desc, &tmpBuffer, &tmpStride);
-        if (error != Error::NONE) {
-            break;
-        }
-
-        if (stride == 0) {
-            stride = tmpStride;
-        } else if (stride != tmpStride) {
-            // non-uniform strides
-            mDispatch.release(mDevice, tmpBuffer);
-            stride = 0;
-            error = Error::UNSUPPORTED;
-            break;
-        }
-
-        buffers.emplace_back(hidl_handle(tmpBuffer));
-    }
-
-    mDispatch.destroyDescriptor(mDevice, desc);
-
-    // return the buffers
-    hidl_vec<hidl_handle> hidl_buffers;
-    if (error == Error::NONE) {
-        hidl_buffers.setToExternal(buffers.data(), buffers.size());
-    }
-    hidl_cb(error, stride, hidl_buffers);
-
-    // free the buffers
-    for (const auto& buffer : buffers) {
-        mDispatch.release(mDevice, buffer.getNativeHandle());
-    }
-
-    return Void();
-}
-
-Error Gralloc1Allocator::toError(int32_t error) {
-    switch (error) {
-        case GRALLOC1_ERROR_NONE:
-            return Error::NONE;
-        case GRALLOC1_ERROR_BAD_DESCRIPTOR:
-            return Error::BAD_DESCRIPTOR;
-        case GRALLOC1_ERROR_BAD_HANDLE:
-            return Error::BAD_BUFFER;
-        case GRALLOC1_ERROR_BAD_VALUE:
-            return Error::BAD_VALUE;
-        case GRALLOC1_ERROR_NOT_SHARED:
-            return Error::NONE;  // this is fine
-        case GRALLOC1_ERROR_NO_RESOURCES:
-            return Error::NO_RESOURCES;
-        case GRALLOC1_ERROR_UNDEFINED:
-        case GRALLOC1_ERROR_UNSUPPORTED:
-        default:
-            return Error::UNSUPPORTED;
-    }
-}
-
-uint64_t Gralloc1Allocator::toProducerUsage(uint64_t usage) {
-    // this is potentially broken as we have no idea which private flags
-    // should be filtered out
-    uint64_t producerUsage =
-        usage &
-        ~static_cast<uint64_t>(BufferUsage::CPU_READ_MASK | BufferUsage::CPU_WRITE_MASK |
-                               BufferUsage::GPU_DATA_BUFFER);
-
-    switch (usage & BufferUsage::CPU_WRITE_MASK) {
-        case static_cast<uint64_t>(BufferUsage::CPU_WRITE_RARELY):
-            producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_WRITE;
-            break;
-        case static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN):
-            producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN;
-            break;
-        default:
-            break;
-    }
-
-    switch (usage & BufferUsage::CPU_READ_MASK) {
-        case static_cast<uint64_t>(BufferUsage::CPU_READ_RARELY):
-            producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_READ;
-            break;
-        case static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN):
-            producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_READ_OFTEN;
-            break;
-        default:
-            break;
-    }
-
-    // BufferUsage::GPU_DATA_BUFFER is always filtered out
-
-    return producerUsage;
-}
-
-uint64_t Gralloc1Allocator::toConsumerUsage(uint64_t usage) {
-    // this is potentially broken as we have no idea which private flags
-    // should be filtered out
-    uint64_t consumerUsage =
-        usage &
-        ~static_cast<uint64_t>(BufferUsage::CPU_READ_MASK | BufferUsage::CPU_WRITE_MASK |
-                               BufferUsage::SENSOR_DIRECT_DATA | BufferUsage::GPU_DATA_BUFFER);
-
-    switch (usage & BufferUsage::CPU_READ_MASK) {
-        case static_cast<uint64_t>(BufferUsage::CPU_READ_RARELY):
-            consumerUsage |= GRALLOC1_CONSUMER_USAGE_CPU_READ;
-            break;
-        case static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN):
-            consumerUsage |= GRALLOC1_CONSUMER_USAGE_CPU_READ_OFTEN;
-            break;
-        default:
-            break;
-    }
-
-    // BufferUsage::SENSOR_DIRECT_DATA is always filtered out
-
-    if (usage & BufferUsage::GPU_DATA_BUFFER) {
-        consumerUsage |= GRALLOC1_CONSUMER_USAGE_GPU_DATA_BUFFER;
-    }
-
-    return consumerUsage;
-}
-
-Error Gralloc1Allocator::createDescriptor(
-    const IMapper::BufferDescriptorInfo& info,
-    gralloc1_buffer_descriptor_t* outDescriptor) {
-    gralloc1_buffer_descriptor_t descriptor;
-
-    int32_t error = mDispatch.createDescriptor(mDevice, &descriptor);
-
-    if (error == GRALLOC1_ERROR_NONE) {
-        error = mDispatch.setDimensions(mDevice, descriptor, info.width,
-                                        info.height);
-    }
-    if (error == GRALLOC1_ERROR_NONE) {
-        error = mDispatch.setFormat(mDevice, descriptor,
-                                    static_cast<int32_t>(info.format));
-    }
-    if (error == GRALLOC1_ERROR_NONE) {
-        if (mCapabilities.layeredBuffers) {
-            error =
-                mDispatch.setLayerCount(mDevice, descriptor, info.layerCount);
-        } else if (info.layerCount > 1) {
-            error = GRALLOC1_ERROR_UNSUPPORTED;
-        }
-    }
-    if (error == GRALLOC1_ERROR_NONE) {
-        error = mDispatch.setProducerUsage(mDevice, descriptor,
-                                           toProducerUsage(info.usage));
-    }
-    if (error == GRALLOC1_ERROR_NONE) {
-        error = mDispatch.setConsumerUsage(mDevice, descriptor,
-                                           toConsumerUsage(info.usage));
-    }
-
-    if (error == GRALLOC1_ERROR_NONE) {
-        *outDescriptor = descriptor;
-    } else {
-        mDispatch.destroyDescriptor(mDevice, descriptor);
-    }
-
-    return toError(error);
-}
-
-Error Gralloc1Allocator::allocateOne(gralloc1_buffer_descriptor_t descriptor,
-                                     buffer_handle_t* outBuffer,
-                                     uint32_t* outStride) {
-    buffer_handle_t buffer = nullptr;
-    int32_t error = mDispatch.allocate(mDevice, 1, &descriptor, &buffer);
-    if (error != GRALLOC1_ERROR_NONE && error != GRALLOC1_ERROR_NOT_SHARED) {
-        return toError(error);
-    }
-
-    uint32_t stride = 0;
-    error = mDispatch.getStride(mDevice, buffer, &stride);
-    if (error != GRALLOC1_ERROR_NONE && error != GRALLOC1_ERROR_UNDEFINED) {
-        mDispatch.release(mDevice, buffer);
-        return toError(error);
-    }
-
-    *outBuffer = buffer;
-    *outStride = stride;
-
-    return Error::NONE;
-}
-
-}  // namespace implementation
-}  // namespace V2_0
-}  // namespace allocator
-}  // namespace graphics
-}  // namespace hardware
-}  // namespace android
diff --git a/graphics/allocator/2.0/default/Gralloc1Allocator.h b/graphics/allocator/2.0/default/Gralloc1Allocator.h
deleted file mode 100644
index 7b5a966..0000000
--- a/graphics/allocator/2.0/default/Gralloc1Allocator.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright 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.
- */
-
-#ifndef ANDROID_HARDWARE_GRAPHICS_ALLOCATOR_V2_0_GRALLOC1ALLOCATOR_H
-#define ANDROID_HARDWARE_GRAPHICS_ALLOCATOR_V2_0_GRALLOC1ALLOCATOR_H
-
-#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
-#include <android/hardware/graphics/mapper/2.0/IMapper.h>
-#include <hardware/gralloc1.h>
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace allocator {
-namespace V2_0 {
-namespace implementation {
-
-using android::hardware::graphics::mapper::V2_0::IMapper;
-using android::hardware::graphics::mapper::V2_0::BufferDescriptor;
-using android::hardware::graphics::mapper::V2_0::Error;
-
-class Gralloc1Allocator : public IAllocator {
-   public:
-    Gralloc1Allocator(const hw_module_t* module);
-    virtual ~Gralloc1Allocator();
-
-    // IAllocator interface
-    Return<void> dumpDebugInfo(dumpDebugInfo_cb hidl_cb) override;
-    Return<void> allocate(const BufferDescriptor& descriptor, uint32_t count,
-                          allocate_cb hidl_cb) override;
-
-   private:
-    void initCapabilities();
-
-    template <typename T>
-    void initDispatch(gralloc1_function_descriptor_t desc, T* outPfn);
-    void initDispatch();
-
-    static Error toError(int32_t error);
-    static uint64_t toProducerUsage(uint64_t usage);
-    static uint64_t toConsumerUsage(uint64_t usage);
-
-    Error createDescriptor(const IMapper::BufferDescriptorInfo& info,
-                           gralloc1_buffer_descriptor_t* outDescriptor);
-    Error allocateOne(gralloc1_buffer_descriptor_t descriptor,
-                      buffer_handle_t* outBuffer, uint32_t* outStride);
-
-    gralloc1_device_t* mDevice;
-
-    struct {
-        bool layeredBuffers;
-    } mCapabilities;
-
-    struct {
-        GRALLOC1_PFN_DUMP dump;
-        GRALLOC1_PFN_CREATE_DESCRIPTOR createDescriptor;
-        GRALLOC1_PFN_DESTROY_DESCRIPTOR destroyDescriptor;
-        GRALLOC1_PFN_SET_DIMENSIONS setDimensions;
-        GRALLOC1_PFN_SET_FORMAT setFormat;
-        GRALLOC1_PFN_SET_LAYER_COUNT setLayerCount;
-        GRALLOC1_PFN_SET_CONSUMER_USAGE setConsumerUsage;
-        GRALLOC1_PFN_SET_PRODUCER_USAGE setProducerUsage;
-        GRALLOC1_PFN_GET_STRIDE getStride;
-        GRALLOC1_PFN_ALLOCATE allocate;
-        GRALLOC1_PFN_RELEASE release;
-    } mDispatch;
-};
-
-}  // namespace implementation
-}  // namespace V2_0
-}  // namespace allocator
-}  // namespace graphics
-}  // namespace hardware
-}  // namespace android
-
-#endif  // ANDROID_HARDWARE_GRAPHICS_ALLOCATOR_V2_0_GRALLOC1ALLOCATOR_H
diff --git a/graphics/allocator/2.0/default/passthrough.cpp b/graphics/allocator/2.0/default/passthrough.cpp
new file mode 100644
index 0000000..132cab3
--- /dev/null
+++ b/graphics/allocator/2.0/default/passthrough.cpp
@@ -0,0 +1,25 @@
+/*
+ * Copyright 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.
+ */
+
+#include <allocator-passthrough/2.0/GrallocLoader.h>
+#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
+
+using android::hardware::graphics::allocator::V2_0::IAllocator;
+using android::hardware::graphics::allocator::V2_0::passthrough::GrallocLoader;
+
+extern "C" IAllocator* HIDL_FETCH_IAllocator(const char* /* name */) {
+    return GrallocLoader::load();
+}
diff --git a/graphics/allocator/2.0/default/service.cpp b/graphics/allocator/2.0/default/service.cpp
index 99f462c..bc0539a 100644
--- a/graphics/allocator/2.0/default/service.cpp
+++ b/graphics/allocator/2.0/default/service.cpp
@@ -20,8 +20,8 @@
 
 #include <hidl/LegacySupport.h>
 
-using android::hardware::graphics::allocator::V2_0::IAllocator;
 using android::hardware::defaultPassthroughServiceImplementation;
+using android::hardware::graphics::allocator::V2_0::IAllocator;
 
 int main() {
     return defaultPassthroughServiceImplementation<IAllocator>(4);
diff --git a/graphics/allocator/2.0/utils/OWNERS b/graphics/allocator/2.0/utils/OWNERS
new file mode 100644
index 0000000..3aa5fa1
--- /dev/null
+++ b/graphics/allocator/2.0/utils/OWNERS
@@ -0,0 +1,4 @@
+# Graphics team
+jessehall@google.com
+olv@google.com
+stoza@google.com
diff --git a/graphics/allocator/2.0/utils/gralloc1-adapter/Android.bp b/graphics/allocator/2.0/utils/gralloc1-adapter/Android.bp
new file mode 100644
index 0000000..9cb53e3
--- /dev/null
+++ b/graphics/allocator/2.0/utils/gralloc1-adapter/Android.bp
@@ -0,0 +1,10 @@
+cc_library_static {
+    name: "libgralloc1-adapter",
+    defaults: ["hidl_defaults"],
+    vendor: true,
+    srcs: ["gralloc1-adapter.cpp", "Gralloc1On0Adapter.cpp"],
+    include_dirs: ["system/core/libsync/include"],
+    export_include_dirs: ["."],
+    whole_static_libs: ["libgrallocusage"],
+    shared_libs: ["libhardware", "liblog"],
+}
diff --git a/graphics/allocator/2.0/default/Gralloc1On0Adapter.cpp b/graphics/allocator/2.0/utils/gralloc1-adapter/Gralloc1On0Adapter.cpp
similarity index 99%
rename from graphics/allocator/2.0/default/Gralloc1On0Adapter.cpp
rename to graphics/allocator/2.0/utils/gralloc1-adapter/Gralloc1On0Adapter.cpp
index 041ce77..b7ed58c 100644
--- a/graphics/allocator/2.0/default/Gralloc1On0Adapter.cpp
+++ b/graphics/allocator/2.0/utils/gralloc1-adapter/Gralloc1On0Adapter.cpp
@@ -29,6 +29,7 @@
 #include <sync/sync.h>
 
 #include <inttypes.h>
+#include <unistd.h>
 
 template <typename PFN, typename T>
 static gralloc1_function_pointer_t asFP(T function)
diff --git a/graphics/allocator/2.0/default/Gralloc1On0Adapter.h b/graphics/allocator/2.0/utils/gralloc1-adapter/Gralloc1On0Adapter.h
similarity index 100%
rename from graphics/allocator/2.0/default/Gralloc1On0Adapter.h
rename to graphics/allocator/2.0/utils/gralloc1-adapter/Gralloc1On0Adapter.h
diff --git a/graphics/allocator/2.0/default/gralloc1-adapter.cpp b/graphics/allocator/2.0/utils/gralloc1-adapter/gralloc1-adapter.cpp
similarity index 100%
rename from graphics/allocator/2.0/default/gralloc1-adapter.cpp
rename to graphics/allocator/2.0/utils/gralloc1-adapter/gralloc1-adapter.cpp
diff --git a/graphics/allocator/2.0/default/gralloc1-adapter.h b/graphics/allocator/2.0/utils/gralloc1-adapter/gralloc1-adapter.h
similarity index 100%
rename from graphics/allocator/2.0/default/gralloc1-adapter.h
rename to graphics/allocator/2.0/utils/gralloc1-adapter/gralloc1-adapter.h
diff --git a/graphics/allocator/2.0/utils/hal/Android.bp b/graphics/allocator/2.0/utils/hal/Android.bp
new file mode 100644
index 0000000..ac642ce
--- /dev/null
+++ b/graphics/allocator/2.0/utils/hal/Android.bp
@@ -0,0 +1,14 @@
+cc_library_headers {
+    name: "android.hardware.graphics.allocator@2.0-hal",
+    defaults: ["hidl_defaults"],
+    vendor: true,
+    shared_libs: [
+        "android.hardware.graphics.allocator@2.0",
+        "android.hardware.graphics.mapper@2.0",
+    ],
+    export_shared_lib_headers: [
+        "android.hardware.graphics.allocator@2.0",
+        "android.hardware.graphics.mapper@2.0",
+    ],
+    export_include_dirs: ["include"],
+}
diff --git a/graphics/allocator/2.0/utils/hal/include/allocator-hal/2.0/Allocator.h b/graphics/allocator/2.0/utils/hal/include/allocator-hal/2.0/Allocator.h
new file mode 100644
index 0000000..2f3022e
--- /dev/null
+++ b/graphics/allocator/2.0/utils/hal/include/allocator-hal/2.0/Allocator.h
@@ -0,0 +1,89 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#ifndef LOG_TAG
+#warning "Allocator.h included without LOG_TAG"
+#endif
+
+#include <memory>
+
+#include <allocator-hal/2.0/AllocatorHal.h>
+#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
+#include <android/hardware/graphics/mapper/2.0/IMapper.h>
+#include <log/log.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace allocator {
+namespace V2_0 {
+namespace hal {
+
+using mapper::V2_0::BufferDescriptor;
+using mapper::V2_0::Error;
+
+namespace detail {
+
+// AllocatorImpl implements IAllocator on top of AllocatorHal
+template <typename IALLOCATOR, typename ALLOCATOR_HAL>
+class AllocatorImpl : public IALLOCATOR {
+   public:
+    bool init(std::unique_ptr<ALLOCATOR_HAL> hal) {
+        mHal = std::move(hal);
+        return true;
+    }
+
+    // IAllocator 2.0 interface
+    Return<void> dumpDebugInfo(IAllocator::dumpDebugInfo_cb hidl_cb) override {
+        hidl_cb(mHal->dumpDebugInfo());
+        return Void();
+    }
+
+    Return<void> allocate(const BufferDescriptor& descriptor, uint32_t count,
+                          IAllocator::allocate_cb hidl_cb) override {
+        uint32_t stride;
+        std::vector<const native_handle_t*> buffers;
+        Error error = mHal->allocateBuffers(descriptor, count, &stride, &buffers);
+        if (error != Error::NONE) {
+            hidl_cb(error, 0, hidl_vec<hidl_handle>());
+            return Void();
+        }
+
+        hidl_vec<hidl_handle> hidlBuffers(buffers.cbegin(), buffers.cend());
+        hidl_cb(Error::NONE, stride, hidlBuffers);
+
+        // free the local handles
+        mHal->freeBuffers(buffers);
+
+        return Void();
+    }
+
+   protected:
+    std::unique_ptr<ALLOCATOR_HAL> mHal;
+};
+
+}  // namespace detail
+
+using Allocator = detail::AllocatorImpl<IAllocator, AllocatorHal>;
+
+}  // namespace hal
+}  // namespace V2_0
+}  // namespace allocator
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/allocator/2.0/utils/hal/include/allocator-hal/2.0/AllocatorHal.h b/graphics/allocator/2.0/utils/hal/include/allocator-hal/2.0/AllocatorHal.h
new file mode 100644
index 0000000..dec377a
--- /dev/null
+++ b/graphics/allocator/2.0/utils/hal/include/allocator-hal/2.0/AllocatorHal.h
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <string>
+#include <vector>
+
+#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
+#include <android/hardware/graphics/mapper/2.0/IMapper.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace allocator {
+namespace V2_0 {
+namespace hal {
+
+using mapper::V2_0::BufferDescriptor;
+using mapper::V2_0::Error;
+
+class AllocatorHal {
+   public:
+    virtual ~AllocatorHal() = default;
+
+    // dump the debug information
+    virtual std::string dumpDebugInfo() = 0;
+
+    // allocate buffers
+    virtual Error allocateBuffers(const BufferDescriptor& descriptor, uint32_t count,
+                                  uint32_t* outStride,
+                                  std::vector<const native_handle_t*>* outBuffers) = 0;
+
+    // free buffers
+    virtual void freeBuffers(const std::vector<const native_handle_t*>& buffers) = 0;
+};
+
+}  // namespace hal
+}  // namespace V2_0
+}  // namespace allocator
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/allocator/2.0/utils/passthrough/Android.bp b/graphics/allocator/2.0/utils/passthrough/Android.bp
new file mode 100644
index 0000000..b956565
--- /dev/null
+++ b/graphics/allocator/2.0/utils/passthrough/Android.bp
@@ -0,0 +1,29 @@
+cc_library_static {
+    name: "android.hardware.graphics.allocator@2.0-passthrough",
+    defaults: ["hidl_defaults"],
+    vendor: true,
+    srcs: [
+        "Gralloc0Hal.cpp",
+        "Gralloc1Hal.cpp",
+        "GrallocLoader.cpp",
+    ],
+    shared_libs: [
+        "android.hardware.graphics.allocator@2.0",
+        "android.hardware.graphics.mapper@2.0",
+        "libhardware",
+    ],
+    export_shared_lib_headers: [
+        "android.hardware.graphics.allocator@2.0",
+        "android.hardware.graphics.mapper@2.0",
+        "libhardware",
+    ],
+    header_libs: [
+        "android.hardware.graphics.allocator@2.0-hal",
+        "libgrallocmapperincludes",
+    ],
+    export_header_lib_headers: [
+        "android.hardware.graphics.allocator@2.0-hal",
+    ],
+    export_include_dirs: ["include"],
+    cflags: ["-DLOG_TAG=\"AllocatorHal\""],
+}
diff --git a/graphics/allocator/2.0/utils/passthrough/Gralloc0Hal.cpp b/graphics/allocator/2.0/utils/passthrough/Gralloc0Hal.cpp
new file mode 100644
index 0000000..8edb7dc
--- /dev/null
+++ b/graphics/allocator/2.0/utils/passthrough/Gralloc0Hal.cpp
@@ -0,0 +1,141 @@
+/*
+ * Copyright 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.
+ */
+
+#include <allocator-passthrough/2.0/Gralloc0Hal.h>
+
+#include <string.h>
+
+#include <GrallocBufferDescriptor.h>
+#include <hardware/gralloc.h>
+#include <log/log.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace allocator {
+namespace V2_0 {
+namespace passthrough {
+
+using mapper::V2_0::implementation::grallocDecodeBufferDescriptor;
+
+Gralloc0Hal::~Gralloc0Hal() {
+    if (mDevice) {
+        gralloc_close(mDevice);
+    }
+}
+
+bool Gralloc0Hal::initWithModule(const hw_module_t* module) {
+    int result = gralloc_open(module, &mDevice);
+    if (result) {
+        ALOGE("failed to open gralloc0 device: %s", strerror(-result));
+        mDevice = nullptr;
+        return false;
+    }
+
+    return true;
+}
+
+std::string Gralloc0Hal::dumpDebugInfo() {
+    char buf[4096] = {};
+    if (mDevice->dump) {
+        mDevice->dump(mDevice, buf, sizeof(buf));
+        buf[sizeof(buf) - 1] = '\0';
+    }
+
+    return buf;
+}
+
+Error Gralloc0Hal::allocateBuffers(const BufferDescriptor& descriptor, uint32_t count,
+                                   uint32_t* outStride,
+                                   std::vector<const native_handle_t*>* outBuffers) {
+    mapper::V2_0::IMapper::BufferDescriptorInfo descriptorInfo;
+    if (!grallocDecodeBufferDescriptor(descriptor, &descriptorInfo)) {
+        return Error::BAD_DESCRIPTOR;
+    }
+
+    Error error = Error::NONE;
+    uint32_t stride = 0;
+    std::vector<const native_handle_t*> buffers;
+    buffers.reserve(count);
+
+    // allocate the buffers
+    for (uint32_t i = 0; i < count; i++) {
+        const native_handle_t* tmpBuffer;
+        uint32_t tmpStride;
+        error = allocateOneBuffer(descriptorInfo, &tmpBuffer, &tmpStride);
+        if (error != Error::NONE) {
+            break;
+        }
+
+        buffers.push_back(tmpBuffer);
+
+        if (stride == 0) {
+            stride = tmpStride;
+        } else if (stride != tmpStride) {
+            // non-uniform strides
+            error = Error::UNSUPPORTED;
+            break;
+        }
+    }
+
+    if (error != Error::NONE) {
+        freeBuffers(buffers);
+        return error;
+    }
+
+    *outStride = stride;
+    *outBuffers = std::move(buffers);
+
+    return Error::NONE;
+}
+
+void Gralloc0Hal::freeBuffers(const std::vector<const native_handle_t*>& buffers) {
+    for (auto buffer : buffers) {
+        int result = mDevice->free(mDevice, buffer);
+        if (result != 0) {
+            ALOGE("failed to free buffer %p: %d", buffer, result);
+        }
+    }
+}
+
+Error Gralloc0Hal::allocateOneBuffer(const mapper::V2_0::IMapper::BufferDescriptorInfo& info,
+                                     const native_handle_t** outBuffer, uint32_t* outStride) {
+    if (info.layerCount > 1 || (info.usage >> 32) != 0) {
+        return Error::BAD_VALUE;
+    }
+
+    const native_handle_t* buffer = nullptr;
+    int stride = 0;
+    int result = mDevice->alloc(mDevice, info.width, info.height, static_cast<int>(info.format),
+                                info.usage, &buffer, &stride);
+    switch (result) {
+        case 0:
+            *outBuffer = buffer;
+            *outStride = stride;
+            return Error::NONE;
+        case -EINVAL:
+            return Error::BAD_VALUE;
+        default:
+            return Error::NO_RESOURCES;
+    }
+}
+
+}  // namespace passthrough
+}  // namespace V2_0
+}  // namespace allocator
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/allocator/2.0/utils/passthrough/Gralloc1Hal.cpp b/graphics/allocator/2.0/utils/passthrough/Gralloc1Hal.cpp
new file mode 100644
index 0000000..e343ecd
--- /dev/null
+++ b/graphics/allocator/2.0/utils/passthrough/Gralloc1Hal.cpp
@@ -0,0 +1,323 @@
+/*
+ * Copyright 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.
+ */
+
+#include <allocator-passthrough/2.0/Gralloc1Hal.h>
+
+#include <string.h>
+
+#include <GrallocBufferDescriptor.h>
+#include <log/log.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace allocator {
+namespace V2_0 {
+namespace passthrough {
+
+using android::hardware::graphics::common::V1_0::BufferUsage;
+using mapper::V2_0::implementation::grallocDecodeBufferDescriptor;
+
+Gralloc1Hal::~Gralloc1Hal() {
+    if (mDevice) {
+        gralloc1_close(mDevice);
+    }
+}
+
+bool Gralloc1Hal::initWithModule(const hw_module_t* module) {
+    int result = gralloc1_open(module, &mDevice);
+    if (result) {
+        ALOGE("failed to open gralloc1 device: %s", strerror(-result));
+        mDevice = nullptr;
+        return false;
+    }
+
+    initCapabilities();
+    if (!initDispatch()) {
+        gralloc1_close(mDevice);
+        mDevice = nullptr;
+        return false;
+    }
+
+    return true;
+}
+
+void Gralloc1Hal::initCapabilities() {
+    uint32_t count = 0;
+    mDevice->getCapabilities(mDevice, &count, nullptr);
+
+    std::vector<int32_t> capabilities(count);
+    mDevice->getCapabilities(mDevice, &count, capabilities.data());
+    capabilities.resize(count);
+
+    for (auto capability : capabilities) {
+        if (capability == GRALLOC1_CAPABILITY_LAYERED_BUFFERS) {
+            mCapabilities.layeredBuffers = true;
+            break;
+        }
+    }
+}
+
+gralloc1_function_pointer_t Gralloc1Hal::getDispatchFunction(
+    gralloc1_function_descriptor_t desc) const {
+    auto pfn = mDevice->getFunction(mDevice, desc);
+    if (!pfn) {
+        ALOGE("failed to get gralloc1 function %d", desc);
+        return nullptr;
+    }
+    return pfn;
+}
+
+bool Gralloc1Hal::initDispatch() {
+    if (!initDispatchFunction(GRALLOC1_FUNCTION_DUMP, &mDispatch.dump) ||
+        !initDispatchFunction(GRALLOC1_FUNCTION_CREATE_DESCRIPTOR, &mDispatch.createDescriptor) ||
+        !initDispatchFunction(GRALLOC1_FUNCTION_DESTROY_DESCRIPTOR, &mDispatch.destroyDescriptor) ||
+        !initDispatchFunction(GRALLOC1_FUNCTION_SET_DIMENSIONS, &mDispatch.setDimensions) ||
+        !initDispatchFunction(GRALLOC1_FUNCTION_SET_FORMAT, &mDispatch.setFormat) ||
+        !initDispatchFunction(GRALLOC1_FUNCTION_SET_CONSUMER_USAGE, &mDispatch.setConsumerUsage) ||
+        !initDispatchFunction(GRALLOC1_FUNCTION_SET_PRODUCER_USAGE, &mDispatch.setProducerUsage) ||
+        !initDispatchFunction(GRALLOC1_FUNCTION_GET_STRIDE, &mDispatch.getStride) ||
+        !initDispatchFunction(GRALLOC1_FUNCTION_ALLOCATE, &mDispatch.allocate) ||
+        !initDispatchFunction(GRALLOC1_FUNCTION_RELEASE, &mDispatch.release)) {
+        return false;
+    }
+
+    if (mCapabilities.layeredBuffers) {
+        if (!initDispatchFunction(GRALLOC1_FUNCTION_SET_LAYER_COUNT, &mDispatch.setLayerCount)) {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+std::string Gralloc1Hal::dumpDebugInfo() {
+    uint32_t len = 0;
+    mDispatch.dump(mDevice, &len, nullptr);
+
+    std::vector<char> buf(len + 1);
+    mDispatch.dump(mDevice, &len, buf.data());
+    buf.resize(len + 1);
+    buf[len] = '\0';
+
+    return buf.data();
+}
+
+Error Gralloc1Hal::allocateBuffers(const BufferDescriptor& descriptor, uint32_t count,
+                                   uint32_t* outStride,
+                                   std::vector<const native_handle_t*>* outBuffers) {
+    mapper::V2_0::IMapper::BufferDescriptorInfo descriptorInfo;
+    if (!grallocDecodeBufferDescriptor(descriptor, &descriptorInfo)) {
+        return Error::BAD_DESCRIPTOR;
+    }
+
+    gralloc1_buffer_descriptor_t desc;
+    Error error = createDescriptor(descriptorInfo, &desc);
+    if (error != Error::NONE) {
+        return error;
+    }
+
+    uint32_t stride = 0;
+    std::vector<const native_handle_t*> buffers;
+    buffers.reserve(count);
+
+    // allocate the buffers
+    for (uint32_t i = 0; i < count; i++) {
+        const native_handle_t* tmpBuffer;
+        uint32_t tmpStride;
+        error = allocateOneBuffer(desc, &tmpBuffer, &tmpStride);
+        if (error != Error::NONE) {
+            break;
+        }
+
+        buffers.push_back(tmpBuffer);
+
+        if (stride == 0) {
+            stride = tmpStride;
+        } else if (stride != tmpStride) {
+            // non-uniform strides
+            error = Error::UNSUPPORTED;
+            break;
+        }
+    }
+
+    mDispatch.destroyDescriptor(mDevice, desc);
+
+    if (error != Error::NONE) {
+        freeBuffers(buffers);
+        return error;
+    }
+
+    *outStride = stride;
+    *outBuffers = std::move(buffers);
+
+    return Error::NONE;
+}
+
+void Gralloc1Hal::freeBuffers(const std::vector<const native_handle_t*>& buffers) {
+    for (auto buffer : buffers) {
+        int32_t error = mDispatch.release(mDevice, buffer);
+        if (error != GRALLOC1_ERROR_NONE) {
+            ALOGE("failed to free buffer %p: %d", buffer, error);
+        }
+    }
+}
+
+Error Gralloc1Hal::toError(int32_t error) {
+    switch (error) {
+        case GRALLOC1_ERROR_NONE:
+            return Error::NONE;
+        case GRALLOC1_ERROR_BAD_DESCRIPTOR:
+            return Error::BAD_DESCRIPTOR;
+        case GRALLOC1_ERROR_BAD_HANDLE:
+            return Error::BAD_BUFFER;
+        case GRALLOC1_ERROR_BAD_VALUE:
+            return Error::BAD_VALUE;
+        case GRALLOC1_ERROR_NOT_SHARED:
+            return Error::NONE;  // this is fine
+        case GRALLOC1_ERROR_NO_RESOURCES:
+            return Error::NO_RESOURCES;
+        case GRALLOC1_ERROR_UNDEFINED:
+        case GRALLOC1_ERROR_UNSUPPORTED:
+        default:
+            return Error::UNSUPPORTED;
+    }
+}
+
+uint64_t Gralloc1Hal::toProducerUsage(uint64_t usage) {
+    // this is potentially broken as we have no idea which private flags
+    // should be filtered out
+    uint64_t producerUsage =
+        usage & ~static_cast<uint64_t>(BufferUsage::CPU_READ_MASK | BufferUsage::CPU_WRITE_MASK |
+                                       BufferUsage::GPU_DATA_BUFFER);
+
+    switch (usage & BufferUsage::CPU_WRITE_MASK) {
+        case static_cast<uint64_t>(BufferUsage::CPU_WRITE_RARELY):
+            producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_WRITE;
+            break;
+        case static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN):
+            producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN;
+            break;
+        default:
+            break;
+    }
+
+    switch (usage & BufferUsage::CPU_READ_MASK) {
+        case static_cast<uint64_t>(BufferUsage::CPU_READ_RARELY):
+            producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_READ;
+            break;
+        case static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN):
+            producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_READ_OFTEN;
+            break;
+        default:
+            break;
+    }
+
+    // BufferUsage::GPU_DATA_BUFFER is always filtered out
+
+    return producerUsage;
+}
+
+uint64_t Gralloc1Hal::toConsumerUsage(uint64_t usage) {
+    // this is potentially broken as we have no idea which private flags
+    // should be filtered out
+    uint64_t consumerUsage =
+        usage &
+        ~static_cast<uint64_t>(BufferUsage::CPU_READ_MASK | BufferUsage::CPU_WRITE_MASK |
+                               BufferUsage::SENSOR_DIRECT_DATA | BufferUsage::GPU_DATA_BUFFER);
+
+    switch (usage & BufferUsage::CPU_READ_MASK) {
+        case static_cast<uint64_t>(BufferUsage::CPU_READ_RARELY):
+            consumerUsage |= GRALLOC1_CONSUMER_USAGE_CPU_READ;
+            break;
+        case static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN):
+            consumerUsage |= GRALLOC1_CONSUMER_USAGE_CPU_READ_OFTEN;
+            break;
+        default:
+            break;
+    }
+
+    // BufferUsage::SENSOR_DIRECT_DATA is always filtered out
+
+    if (usage & BufferUsage::GPU_DATA_BUFFER) {
+        consumerUsage |= GRALLOC1_CONSUMER_USAGE_GPU_DATA_BUFFER;
+    }
+
+    return consumerUsage;
+}
+
+Error Gralloc1Hal::createDescriptor(const mapper::V2_0::IMapper::BufferDescriptorInfo& info,
+                                    gralloc1_buffer_descriptor_t* outDescriptor) {
+    gralloc1_buffer_descriptor_t descriptor;
+
+    int32_t error = mDispatch.createDescriptor(mDevice, &descriptor);
+
+    if (error == GRALLOC1_ERROR_NONE) {
+        error = mDispatch.setDimensions(mDevice, descriptor, info.width, info.height);
+    }
+    if (error == GRALLOC1_ERROR_NONE) {
+        error = mDispatch.setFormat(mDevice, descriptor, static_cast<int32_t>(info.format));
+    }
+    if (error == GRALLOC1_ERROR_NONE) {
+        if (mCapabilities.layeredBuffers) {
+            error = mDispatch.setLayerCount(mDevice, descriptor, info.layerCount);
+        } else if (info.layerCount > 1) {
+            error = GRALLOC1_ERROR_UNSUPPORTED;
+        }
+    }
+    if (error == GRALLOC1_ERROR_NONE) {
+        error = mDispatch.setProducerUsage(mDevice, descriptor, toProducerUsage(info.usage));
+    }
+    if (error == GRALLOC1_ERROR_NONE) {
+        error = mDispatch.setConsumerUsage(mDevice, descriptor, toConsumerUsage(info.usage));
+    }
+
+    if (error == GRALLOC1_ERROR_NONE) {
+        *outDescriptor = descriptor;
+    } else {
+        mDispatch.destroyDescriptor(mDevice, descriptor);
+    }
+
+    return toError(error);
+}
+
+Error Gralloc1Hal::allocateOneBuffer(gralloc1_buffer_descriptor_t descriptor,
+                                     const native_handle_t** outBuffer, uint32_t* outStride) {
+    const native_handle_t* buffer = nullptr;
+    int32_t error = mDispatch.allocate(mDevice, 1, &descriptor, &buffer);
+    if (error != GRALLOC1_ERROR_NONE && error != GRALLOC1_ERROR_NOT_SHARED) {
+        return toError(error);
+    }
+
+    uint32_t stride = 0;
+    error = mDispatch.getStride(mDevice, buffer, &stride);
+    if (error != GRALLOC1_ERROR_NONE && error != GRALLOC1_ERROR_UNDEFINED) {
+        mDispatch.release(mDevice, buffer);
+        return toError(error);
+    }
+
+    *outBuffer = buffer;
+    *outStride = stride;
+
+    return Error::NONE;
+}
+
+}  // namespace passthrough
+}  // namespace V2_0
+}  // namespace allocator
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/allocator/2.0/utils/passthrough/GrallocLoader.cpp b/graphics/allocator/2.0/utils/passthrough/GrallocLoader.cpp
new file mode 100644
index 0000000..dae7a78
--- /dev/null
+++ b/graphics/allocator/2.0/utils/passthrough/GrallocLoader.cpp
@@ -0,0 +1,76 @@
+/*
+ * 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.
+ */
+
+#include <allocator-passthrough/2.0/GrallocLoader.h>
+
+#include <allocator-hal/2.0/Allocator.h>
+#include <allocator-hal/2.0/AllocatorHal.h>
+#include <allocator-passthrough/2.0/Gralloc0Hal.h>
+#include <allocator-passthrough/2.0/Gralloc1Hal.h>
+#include <hardware/gralloc.h>
+#include <hardware/hardware.h>
+#include <log/log.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace allocator {
+namespace V2_0 {
+namespace passthrough {
+
+const hw_module_t* GrallocLoader::loadModule() {
+    const hw_module_t* module;
+    int error = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
+    if (error) {
+        ALOGE("failed to get gralloc module");
+        return nullptr;
+    }
+
+    return module;
+}
+
+int GrallocLoader::getModuleMajorApiVersion(const hw_module_t* module) {
+    return (module->module_api_version >> 8) & 0xff;
+}
+
+std::unique_ptr<hal::AllocatorHal> GrallocLoader::createHal(const hw_module_t* module) {
+    int major = getModuleMajorApiVersion(module);
+    switch (major) {
+        case 1: {
+            auto hal = std::make_unique<Gralloc1Hal>();
+            return hal->initWithModule(module) ? std::move(hal) : nullptr;
+        }
+        case 0: {
+            auto hal = std::make_unique<Gralloc0Hal>();
+            return hal->initWithModule(module) ? std::move(hal) : nullptr;
+        }
+        default:
+            ALOGE("unknown gralloc module major version %d", major);
+            return nullptr;
+    }
+}
+
+IAllocator* GrallocLoader::createAllocator(std::unique_ptr<hal::AllocatorHal> hal) {
+    auto allocator = std::make_unique<hal::Allocator>();
+    return allocator->init(std::move(hal)) ? allocator.release() : nullptr;
+}
+
+}  // namespace passthrough
+}  // namespace V2_0
+}  // namespace allocator
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/allocator/2.0/utils/passthrough/include/allocator-passthrough/2.0/Gralloc0Hal.h b/graphics/allocator/2.0/utils/passthrough/include/allocator-passthrough/2.0/Gralloc0Hal.h
new file mode 100644
index 0000000..8f433b0
--- /dev/null
+++ b/graphics/allocator/2.0/utils/passthrough/include/allocator-passthrough/2.0/Gralloc0Hal.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright 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.
+ */
+
+#pragma once
+
+#include <allocator-hal/2.0/AllocatorHal.h>
+
+struct alloc_device_t;
+struct hw_module_t;
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace allocator {
+namespace V2_0 {
+namespace passthrough {
+
+using mapper::V2_0::BufferDescriptor;
+using mapper::V2_0::Error;
+
+class Gralloc0Hal : public virtual hal::AllocatorHal {
+   public:
+    ~Gralloc0Hal();
+    bool initWithModule(const hw_module_t* module);
+
+    std::string dumpDebugInfo() override;
+
+    Error allocateBuffers(const BufferDescriptor& descriptor, uint32_t count, uint32_t* outStride,
+                          std::vector<const native_handle_t*>* outBuffers) override;
+
+    void freeBuffers(const std::vector<const native_handle_t*>& buffers) override;
+
+   protected:
+    Error allocateOneBuffer(const mapper::V2_0::IMapper::BufferDescriptorInfo& info,
+                            const native_handle_t** outBuffer, uint32_t* outStride);
+
+    alloc_device_t* mDevice = nullptr;
+};
+
+}  // namespace passthrough
+}  // namespace V2_0
+}  // namespace allocator
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/allocator/2.0/utils/passthrough/include/allocator-passthrough/2.0/Gralloc1Hal.h b/graphics/allocator/2.0/utils/passthrough/include/allocator-passthrough/2.0/Gralloc1Hal.h
new file mode 100644
index 0000000..3126e91
--- /dev/null
+++ b/graphics/allocator/2.0/utils/passthrough/include/allocator-passthrough/2.0/Gralloc1Hal.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright 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.
+ */
+
+#pragma once
+
+#include <allocator-hal/2.0/AllocatorHal.h>
+#include <hardware/gralloc1.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace allocator {
+namespace V2_0 {
+namespace passthrough {
+
+using mapper::V2_0::BufferDescriptor;
+using mapper::V2_0::Error;
+
+class Gralloc1Hal : public virtual hal::AllocatorHal {
+   public:
+    ~Gralloc1Hal();
+    bool initWithModule(const hw_module_t* module);
+
+    std::string dumpDebugInfo() override;
+
+    Error allocateBuffers(const BufferDescriptor& descriptor, uint32_t count, uint32_t* outStride,
+                          std::vector<const native_handle_t*>* outBuffers) override;
+
+    void freeBuffers(const std::vector<const native_handle_t*>& buffers) override;
+
+   protected:
+    template <typename T>
+    bool initDispatchFunction(gralloc1_function_descriptor_t desc, T* outPfn) {
+        auto pfn = getDispatchFunction(desc);
+        if (pfn) {
+            *outPfn = reinterpret_cast<T>(pfn);
+            return true;
+        } else {
+            return false;
+        }
+    }
+    gralloc1_function_pointer_t getDispatchFunction(gralloc1_function_descriptor_t desc) const;
+
+    virtual void initCapabilities();
+    virtual bool initDispatch();
+
+    static Error toError(int32_t error);
+    static uint64_t toProducerUsage(uint64_t usage);
+    static uint64_t toConsumerUsage(uint64_t usage);
+
+    Error createDescriptor(const mapper::V2_0::IMapper::BufferDescriptorInfo& info,
+                           gralloc1_buffer_descriptor_t* outDescriptor);
+
+    Error allocateOneBuffer(gralloc1_buffer_descriptor_t descriptor,
+                            const native_handle_t** outBuffer, uint32_t* outStride);
+
+    gralloc1_device_t* mDevice = nullptr;
+
+    struct {
+        bool layeredBuffers;
+    } mCapabilities = {};
+
+    struct {
+        GRALLOC1_PFN_DUMP dump;
+        GRALLOC1_PFN_CREATE_DESCRIPTOR createDescriptor;
+        GRALLOC1_PFN_DESTROY_DESCRIPTOR destroyDescriptor;
+        GRALLOC1_PFN_SET_DIMENSIONS setDimensions;
+        GRALLOC1_PFN_SET_FORMAT setFormat;
+        GRALLOC1_PFN_SET_LAYER_COUNT setLayerCount;
+        GRALLOC1_PFN_SET_CONSUMER_USAGE setConsumerUsage;
+        GRALLOC1_PFN_SET_PRODUCER_USAGE setProducerUsage;
+        GRALLOC1_PFN_GET_STRIDE getStride;
+        GRALLOC1_PFN_ALLOCATE allocate;
+        GRALLOC1_PFN_RELEASE release;
+    } mDispatch = {};
+};
+
+}  // namespace passthrough
+}  // namespace V2_0
+}  // namespace allocator
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/allocator/2.0/utils/passthrough/include/allocator-passthrough/2.0/GrallocLoader.h b/graphics/allocator/2.0/utils/passthrough/include/allocator-passthrough/2.0/GrallocLoader.h
new file mode 100644
index 0000000..a0b9503
--- /dev/null
+++ b/graphics/allocator/2.0/utils/passthrough/include/allocator-passthrough/2.0/GrallocLoader.h
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <memory>
+
+#include <allocator-hal/2.0/AllocatorHal.h>
+
+struct hw_module_t;
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace allocator {
+namespace V2_0 {
+namespace passthrough {
+
+class GrallocLoader {
+   public:
+    static IAllocator* load() {
+        const hw_module_t* module = loadModule();
+        if (!module) {
+            return nullptr;
+        }
+        auto hal = createHal(module);
+        if (!hal) {
+            return nullptr;
+        }
+        return createAllocator(std::move(hal));
+    }
+
+    // load the gralloc module
+    static const hw_module_t* loadModule();
+
+    // return the major api version of the module
+    static int getModuleMajorApiVersion(const hw_module_t* module);
+
+    // create an AllocatorHal instance
+    static std::unique_ptr<hal::AllocatorHal> createHal(const hw_module_t* module);
+
+    // create an IAllocator instance
+    static IAllocator* createAllocator(std::unique_ptr<hal::AllocatorHal> hal);
+};
+
+}  // namespace passthrough
+}  // namespace V2_0
+}  // namespace allocator
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/composer/2.1/default/ComposerClient.cpp b/graphics/composer/2.1/default/ComposerClient.cpp
index 4e6dd4f..8aa9af0 100644
--- a/graphics/composer/2.1/default/ComposerClient.cpp
+++ b/graphics/composer/2.1/default/ComposerClient.cpp
@@ -299,10 +299,17 @@
     Error err = mHal.createLayer(display, &layer);
     if (err == Error::NONE) {
         std::lock_guard<std::mutex> lock(mDisplayDataMutex);
-
         auto dpy = mDisplayData.find(display);
-        auto ly = dpy->second.Layers.emplace(layer, LayerBuffers()).first;
-        ly->second.Buffers.resize(bufferSlotCount);
+        // The display entry may have already been removed by onHotplug.
+        if (dpy != mDisplayData.end()) {
+            auto ly = dpy->second.Layers.emplace(layer, LayerBuffers()).first;
+            ly->second.Buffers.resize(bufferSlotCount);
+        } else {
+            err = Error::BAD_DISPLAY;
+            // Note: We do not destroy the layer on this error as the hotplug
+            // disconnect invalidates the display id. The implementation should
+            // ensure all layers for the display are destroyed.
+        }
     }
 
     hidl_cb(err, layer);
@@ -316,7 +323,10 @@
         std::lock_guard<std::mutex> lock(mDisplayDataMutex);
 
         auto dpy = mDisplayData.find(display);
-        dpy->second.Layers.erase(layer);
+        // The display entry may have already been removed by onHotplug.
+        if (dpy != mDisplayData.end()) {
+            dpy->second.Layers.erase(layer);
+        }
     }
 
     return err;
diff --git a/health/2.0/Android.bp b/health/2.0/Android.bp
index 1080df1..97704bf 100644
--- a/health/2.0/Android.bp
+++ b/health/2.0/Android.bp
@@ -17,6 +17,9 @@
     ],
     types: [
         "Result",
+        "DiskStats",
+        "StorageAttribute",
+        "StorageInfo",
     ],
     gen_java: true,
 }
diff --git a/health/2.0/IHealth.hal b/health/2.0/IHealth.hal
index 3e10701..a33bb15 100644
--- a/health/2.0/IHealth.hal
+++ b/health/2.0/IHealth.hal
@@ -137,4 +137,27 @@
      * @return value charge status, or UNKNOWN if not successful.
      */
     getChargeStatus() generates (Result result, BatteryStatus value);
+
+    /**
+     * Get storage info.
+     *
+     * @return result SUCCESS if successful,
+     *                NOT_SUPPORTED if this property is not supported,
+     *                UNKNOWN other errors.
+     * @return value vector of StorageInfo structs, to be ignored if result is not
+     *               SUCCESS.
+     */
+    getStorageInfo() generates (Result result, vec<StorageInfo> value);
+
+    /**
+     * Gets disk statistics (number of reads/writes processed, number of I/O
+     * operations in flight etc).
+     *
+     * @return result SUCCESS if successful,
+     *                NOT_SUPPORTED if this property is not supported,
+     *                UNKNOWN other errors.
+     * @return value vector of disk statistics, to be ignored if result is not SUCCESS.
+     *               The mapping is index 0->sda, 1->sdb and so on.
+     */
+    getDiskStats() generates (Result result, vec<DiskStats> value);
 };
diff --git a/health/2.0/default/Health.cpp b/health/2.0/default/Health.cpp
index 4710c90..96f6d70 100644
--- a/health/2.0/default/Health.cpp
+++ b/health/2.0/default/Health.cpp
@@ -1,3 +1,18 @@
+/*
+ * 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.
+ */
 #define LOG_TAG "android.hardware.health@2.0-impl"
 #include <android-base/logging.h>
 
@@ -160,6 +175,30 @@
     return Void();
 }
 
+Return<void> Health::getStorageInfo(getStorageInfo_cb _hidl_cb) {
+    std::vector<struct StorageInfo> info;
+    get_storage_info(info);
+    hidl_vec<struct StorageInfo> info_vec(info);
+    if (!info.size()) {
+        _hidl_cb(Result::NOT_SUPPORTED, info_vec);
+    } else {
+        _hidl_cb(Result::SUCCESS, info_vec);
+    }
+    return Void();
+}
+
+Return<void> Health::getDiskStats(getDiskStats_cb _hidl_cb) {
+    std::vector<struct DiskStats> stats;
+    get_disk_stats(stats);
+    hidl_vec<struct DiskStats> stats_vec(stats);
+    if (!stats.size()) {
+        _hidl_cb(Result::NOT_SUPPORTED, stats_vec);
+    } else {
+        _hidl_cb(Result::SUCCESS, stats_vec);
+    }
+    return Void();
+}
+
 void Health::serviceDied(uint64_t /* cookie */, const wp<IBase>& who) {
     (void)unregisterCallbackInternal(who.promote());
 }
diff --git a/health/2.0/default/include/health2/Health.h b/health/2.0/default/include/health2/Health.h
index ab42ae7..41ba9e9 100644
--- a/health/2.0/default/include/health2/Health.h
+++ b/health/2.0/default/include/health2/Health.h
@@ -9,6 +9,12 @@
 #include <healthd/BatteryMonitor.h>
 #include <hidl/Status.h>
 
+using android::hardware::health::V2_0::StorageInfo;
+using android::hardware::health::V2_0::DiskStats;
+
+void get_storage_info(std::vector<struct StorageInfo>& info);
+void get_disk_stats(std::vector<struct DiskStats>& stats);
+
 namespace android {
 namespace hardware {
 namespace health {
@@ -44,6 +50,8 @@
     Return<void> getCapacity(getCapacity_cb _hidl_cb) override;
     Return<void> getEnergyCounter(getEnergyCounter_cb _hidl_cb) override;
     Return<void> getChargeStatus(getChargeStatus_cb _hidl_cb) override;
+    Return<void> getStorageInfo(getStorageInfo_cb _hidl_cb) override;
+    Return<void> getDiskStats(getDiskStats_cb _hidl_cb) override;
 
     // Methods from ::android::hidl::base::V1_0::IBase follow.
     Return<void> debug(const hidl_handle& fd, const hidl_vec<hidl_string>& args) override;
diff --git a/health/2.0/libstoragehealthdefault/Android.bp b/health/2.0/libstoragehealthdefault/Android.bp
new file mode 100644
index 0000000..986e1ef
--- /dev/null
+++ b/health/2.0/libstoragehealthdefault/Android.bp
@@ -0,0 +1,11 @@
+// Copyright 2018 The Android Open Source Project
+
+cc_library_static {
+    srcs: ["StorageHealthDefault.cpp"],
+    name: "libhealthstoragedefault",
+    vendor_available: true,
+    cflags: ["-Werror"],
+    shared_libs: [
+        "android.hardware.health@2.0",
+    ],
+}
diff --git a/health/2.0/libstoragehealthdefault/StorageHealthDefault.cpp b/health/2.0/libstoragehealthdefault/StorageHealthDefault.cpp
new file mode 100644
index 0000000..aba6cc3
--- /dev/null
+++ b/health/2.0/libstoragehealthdefault/StorageHealthDefault.cpp
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+#include "include/StorageHealthDefault.h"
+
+void get_storage_info(std::vector<struct StorageInfo>&) {
+    // Use defaults.
+}
+
+void get_disk_stats(std::vector<struct DiskStats>&) {
+    // Use defaults
+}
diff --git a/health/2.0/libstoragehealthdefault/include/StorageHealthDefault.h b/health/2.0/libstoragehealthdefault/include/StorageHealthDefault.h
new file mode 100644
index 0000000..85eb210
--- /dev/null
+++ b/health/2.0/libstoragehealthdefault/include/StorageHealthDefault.h
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+#ifndef ANDROID_HARDWARE_HEALTH_V2_0_STORAGE_HEALTH_H
+#define ANDROID_HARDWARE_HEALTH_V2_0_STORAGE_HEALTH_H
+
+#include <android/hardware/health/2.0/types.h>
+
+using android::hardware::health::V2_0::StorageInfo;
+using android::hardware::health::V2_0::DiskStats;
+
+/*
+ * Get storage information.
+ */
+void get_storage_info(std::vector<struct StorageInfo>& info);
+
+/*
+ * Get disk statistics.
+ */
+void get_disk_stats(std::vector<struct DiskStats>& stats);
+
+#endif  // ANDROID_HARDWARE_HEALTH_V2_0_STORAGE_HEALTH_H
diff --git a/health/2.0/types.hal b/health/2.0/types.hal
index 8c6d88f..4e7a081 100644
--- a/health/2.0/types.hal
+++ b/health/2.0/types.hal
@@ -26,3 +26,101 @@
     NOT_FOUND,
     CALLBACK_DIED,
 };
+
+/*
+ * Identification attributes for a storage device.
+ */
+struct StorageAttribute {
+    /**
+     * Set to true if internal storage
+     */
+    bool isInternal;
+    /**
+     * Set to true if this is the boot device.
+     */
+    bool isBootDevice;
+    /**
+     * Name of the storage device.
+     */
+    string name;
+};
+
+/*
+ * Information on storage device including life time estimates, end of life
+ * information and other attributes.
+ */
+struct StorageInfo {
+    /**
+     * Attributes of the storage device whose info is contained by the struct.
+     */
+    StorageAttribute attr;
+    /**
+     * pre-eol (end of life) information. Follows JEDEC standard No.84-B50.
+     */
+    uint16_t eol;
+    /**
+     * device life time estimation (type A). Follows JEDEC standard No.84-B50.
+     */
+    uint16_t lifetimeA;
+    /**
+     * device life time estimation (type B). Follows JEDEC standard No.84-B50.
+     */
+    uint16_t lifetimeB;
+    /**
+     * version string
+     */
+    string version;
+};
+/*
+ * Disk statistics since boot.
+ */
+struct DiskStats {
+    /**
+     * Number of reads processed.
+     */
+    uint64_t reads;
+    /**
+     * number of read I/Os merged with in-queue I/Os.
+     */
+    uint64_t readMerges;
+    /**
+     * number of sectors read.
+     */
+    uint64_t readSectors;
+    /**
+     * total wait time for read requests.
+     */
+    uint64_t readTicks;
+    /**
+     * number of writes processed.
+     */
+    uint64_t writes;
+    /**
+     * number of writes merged with in-queue I/Os.
+     */
+    uint64_t writeMerges;
+    /**
+     * number of sectors written.
+     */
+    uint64_t writeSectors;
+    /**
+     * total wait time for write requests.
+     */
+    uint64_t writeTicks;
+    /**
+     * number of I/Os currently in flight.
+     */
+    uint64_t ioInFlight;
+    /**
+     * total time this block device has been active.
+     */
+    uint64_t ioTicks;
+    /**
+     * total wait time for all requests.
+     */
+    uint64_t ioInQueue;
+    /**
+     * Attributes of the memory device.
+     */
+    StorageAttribute attr;
+};
diff --git a/health/2.0/vts/functional/VtsHalHealthV2_0TargetTest.cpp b/health/2.0/vts/functional/VtsHalHealthV2_0TargetTest.cpp
index bf8548c..b2c6160 100644
--- a/health/2.0/vts/functional/VtsHalHealthV2_0TargetTest.cpp
+++ b/health/2.0/vts/functional/VtsHalHealthV2_0TargetTest.cpp
@@ -180,6 +180,29 @@
     return AssertionFailure() << "Result is not SUCCESS or NOT_SUPPORTED: " << toString(res);
 }
 
+bool verifyStorageInfo(const hidl_vec<struct StorageInfo>& info) {
+    for (size_t i = 0; i < info.size(); i++) {
+        if (!(0 <= info[i].eol && info[i].eol <= 3 && 0 <= info[i].lifetimeA &&
+              info[i].lifetimeA <= 0x0B && 0 <= info[i].lifetimeB && info[i].lifetimeB <= 0x0B)) {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+bool verifyDiskStats(const hidl_vec<struct DiskStats>& stats) {
+    for (size_t i = 0; i < stats.size(); i++) {
+        if (!(stats[i].reads > 0 && stats[i].readMerges > 0 && stats[i].readSectors > 0 &&
+              stats[i].readTicks > 0 && stats[i].writes > 0 && stats[i].writeMerges > 0 &&
+              stats[i].writeSectors > 0 && stats[i].writeTicks > 0 && stats[i].ioTicks > 0)) {
+            return false;
+        }
+    }
+
+    return true;
+}
+
 TEST_F(HealthHidlTest, Properties) {
     EXPECT_OK(mHealth->getChargeCounter([](auto result, auto value) {
         EXPECT_VALID_OR_UNSUPPORTED_PROP(result, std::to_string(value), value > 0);
@@ -202,6 +225,12 @@
             value == BatteryStatus::CHARGING || value == BatteryStatus::DISCHARGING ||
                 value == BatteryStatus::NOT_CHARGING || value == BatteryStatus::FULL);
     }));
+    EXPECT_OK(mHealth->getStorageInfo([](auto result, auto& value) {
+        EXPECT_VALID_OR_UNSUPPORTED_PROP(result, toString(value), (verifyStorageInfo(value)));
+    }));
+    EXPECT_OK(mHealth->getDiskStats([](auto result, auto& value) {
+        EXPECT_VALID_OR_UNSUPPORTED_PROP(result, toString(value), verifyDiskStats(value));
+    }));
 }
 
 }  // namespace V2_0
diff --git a/keymaster/4.0/types.hal b/keymaster/4.0/types.hal
index 0c890bd..fcc51fd 100644
--- a/keymaster/4.0/types.hal
+++ b/keymaster/4.0/types.hal
@@ -136,6 +136,51 @@
                                                 * if device is still on-body (requires secure
                                                 * on-body sensor. */
 
+    /**
+     * TRUSTED_USER_PRESENCE_REQUIRED is an optional feature that specifies that this key must be
+     * unusable except when the user has provided proof of physical presence.  Proof of physical
+     * presence must be a signal that cannot be triggered by an attacker who doesn't have one of:
+     *
+     *    a) Physical control of the device or
+     *
+     *    b) Control of the secure environment that holds the key.
+     *
+     * For instance, proof of user identity may be considered proof of presence if it meets the
+     * requirements.  However, proof of identity established in one security domain (e.g. TEE) does
+     * not constitute proof of presence in another security domain (e.g. StrongBox), and no
+     * mechanism analogous to the authentication token is defined for communicating proof of
+     * presence across security domains.
+     *
+     * Some examples:
+     *
+     *     A hardware button hardwired to a pin on a StrongBox device in such a way that nothing
+     *     other than a button press can trigger the signal constitutes proof of physical presence
+     *     for StrongBox keys.
+     *
+     *     Fingerprint authentication provides proof of presence (and identity) for TEE keys if the
+     *     TEE has exclusive control of the fingerprint scanner and performs fingerprint matching.
+     *
+     *     Password authentication does not provide proof of presence to either TEE or StrongBox,
+     *     even if TEE or StrongBox does the password matching, because password input is handled by
+     *     the non-secure world, which means an attacker who has compromised Android can spoof
+     *     password authentication.
+     *
+     * Note that no mechanism is defined for delivering proof of presence to Keymaster,
+     * except perhaps as implied by an auth token.  This means that Keymaster must be able to check
+     * proof of presence some other way.  Further, the proof of presence must be performed between
+     * begin() and the first call to update() or finish().  If the first update() or the finish()
+     * call is made without proof of presence, the keymaster method must return
+     * ErrorCode::PROOF_OF_PRESENCE_REQUIRED and abort the operation.  The caller must delay the
+     * update() or finish() call until proof of presence has been provided, which means the caller
+     * must also have some mechanism for verifying that the proof has been provided.
+     *
+     * Only one operation requiring TUP may be in flight at a time.  If begin() has already been
+     * called on one key with TRUSTED_USER_PRESENCE_REQUIRED, and another begin() comes in for that
+     * key or another with TRUSTED_USER_PRESENCE_REQUIRED, Keymaster must return
+     * ErrorCode::CONCURRENT_PROOF_OF_PRESENCE_REQUESTED.
+     */
+    TRUSTED_USER_PRESENCE_REQUIRED = TagType:BOOL | 507,
+
     /* Application access control */
     APPLICATION_ID = TagType:BYTES | 601, /* Byte string identifying the authorized application. */
 
@@ -381,6 +426,8 @@
     CANNOT_ATTEST_IDS = -66,
     ROLLBACK_RESISTANCE_UNAVAILABLE = -67,
     HARDWARE_TYPE_UNAVAILABLE = -68,
+    PROOF_OF_PRESENCE_REQUIRED = -69,
+    CONCURRENT_PROOF_OF_PRESENCE_REQUESTED = -70,
 
     UNIMPLEMENTED = -100,
     VERSION_MISMATCH = -101,
diff --git a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
index c8858de..060d904 100644
--- a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
+++ b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
@@ -75,6 +75,7 @@
         case Tag::ALLOW_WHILE_ON_BODY:
         case Tag::ROLLBACK_RESISTANCE:
         case Tag::RESET_SINCE_ID_ROTATION:
+        case Tag::TRUSTED_USER_PRESENCE_REQUIRED:
             return true;
 
         /* Integer tags */
diff --git a/radio/1.2/IRadioIndication.hal b/radio/1.2/IRadioIndication.hal
index 4aae74d..e87bb5b 100644
--- a/radio/1.2/IRadioIndication.hal
+++ b/radio/1.2/IRadioIndication.hal
@@ -37,4 +37,13 @@
      *        the device
      */
     oneway simSlotsStatusChanged(RadioIndicationType type, vec<SimSlotStatus> slotStatus);
+
+    /**
+     * Request all of the current cell information known to the radio.
+     * Same information as returned by getCellInfoList() in 1.0::IRadio.
+     *
+     * @param type Type of radio indication
+     * @param records Current cell information known to radio
+     */
+     oneway cellInfoList_1_2(RadioIndicationType type, vec<CellInfo> records);
 };
diff --git a/wifi/1.2/default/wifi_chip.cpp b/wifi/1.2/default/wifi_chip.cpp
index adba054..8d9cfc6 100644
--- a/wifi/1.2/default/wifi_chip.cpp
+++ b/wifi/1.2/default/wifi_chip.cpp
@@ -387,7 +387,8 @@
     std::tie(legacy_status, legacy_logger_feature_set) =
         legacy_hal_.lock()->getLoggerSupportedFeatureSet(getWlan0IfaceName());
     if (legacy_status != legacy_hal::WIFI_SUCCESS) {
-        return {createWifiStatusFromLegacyError(legacy_status), 0};
+        // some devices don't support querying logger feature set
+        legacy_logger_feature_set = 0;
     }
     uint32_t hidl_caps;
     if (!hidl_struct_util::convertLegacyFeaturesToHidlChipCapabilities(