Merge "Fix crash on hotplug disconnect"
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/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/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/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(