Merge remote-tracking branch 'goog/upstream-pixel18' into pi-dev-uaf-fix
am: 1536146973

Change-Id: I1a03abac2614c0a78fd63520bc022439c876f96e
diff --git a/.checkpatch.conf b/.checkpatch.conf
new file mode 100644
index 0000000..e8e9db6
--- /dev/null
+++ b/.checkpatch.conf
@@ -0,0 +1,7 @@
+# Not Linux, so don't expect a Linux tree.
+--no-tree
+
+# Ignore aspects we don't follow here.
+--ignore FILE_PATH_CHANGES
+--ignore GIT_COMMIT_ID
+--ignore SPLIT_STRING
diff --git a/.clang-format b/.clang-format
new file mode 100644
index 0000000..7453c4d
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1,11 @@
+BasedOnStyle: Google
+AccessModifierOffset: -2
+AllowShortFunctionsOnASingleLine: Inline
+ColumnLimit: 80
+CommentPragmas: NOLINT:.*
+DerivePointerAlignment: false
+IndentWidth: 4
+ContinuationIndentWidth: 8
+PointerAlignment: Left
+TabWidth: 4
+UseTab: Never
diff --git a/OWNERS b/OWNERS
new file mode 100644
index 0000000..34f5c36
--- /dev/null
+++ b/OWNERS
@@ -0,0 +1,7 @@
+# Default owners are top 3 or more active developers of the past 1 or 2 years
+# or people with more than 10 commits last year.
+# Please update this list if you find better owner candidates.
[email protected]
[email protected]
[email protected]
[email protected]
diff --git a/citadel/citadeld/Android.bp b/citadel/citadeld/Android.bp
index f57d672..835845e 100644
--- a/citadel/citadeld/Android.bp
+++ b/citadel/citadeld/Android.bp
@@ -28,6 +28,7 @@
         "libbinder",
         "libnos",
         "libutils",
+        "//hardware/google/pixel:pixelpowerstats_provider_aidl_interface-cpp",
     ],
 }
 
diff --git a/citadel/citadeld/aidl/android/hardware/citadel/ICitadeld.aidl b/citadel/citadeld/aidl/android/hardware/citadel/ICitadeld.aidl
index 2fc1a3b..ee59982 100644
--- a/citadel/citadeld/aidl/android/hardware/citadel/ICitadeld.aidl
+++ b/citadel/citadeld/aidl/android/hardware/citadel/ICitadeld.aidl
@@ -30,4 +30,7 @@
 
     /** Reset Citadel by pulling the reset line. */
     boolean reset();
+
+    /** Get cached low-power stats */
+    void getCachedStats(out byte[] response);
 }
diff --git a/citadel/citadeld/main.cpp b/citadel/citadeld/main.cpp
index 2afbdb6..d0d345f 100644
--- a/citadel/citadeld/main.cpp
+++ b/citadel/citadeld/main.cpp
@@ -14,27 +14,40 @@
  * limitations under the License.
  */
 
+#include <algorithm>
+#include <chrono>
+#include <condition_variable>
+#include <functional>
+#include <future>
+#include <iomanip>
 #include <limits>
-#include <thread>
 #include <mutex>
+#include <thread>
 
 #include <android-base/logging.h>
+#include <binder/IBinder.h>
 #include <binder/IPCThreadState.h>
 #include <binder/IServiceManager.h>
 
-#include <nos/device.h>
+#include <app_nugget.h>
+#include <citadel_events.h>
 #include <nos/NuggetClient.h>
+#include <nos/device.h>
 
 #include <android/hardware/citadel/BnCitadeld.h>
 
-using ::android::OK;
+#include <android/vendor/powerstats/BnPixelPowerStatsCallback.h>
+#include <android/vendor/powerstats/BnPixelPowerStatsProvider.h>
+#include <android/vendor/powerstats/StateResidencyData.h>
+
 using ::android::defaultServiceManager;
-using ::android::sp;
-using ::android::status_t;
 using ::android::IPCThreadState;
 using ::android::IServiceManager;
+using ::android::OK;
 using ::android::ProcessState;
-
+using ::android::sp;
+using ::android::status_t;
+using ::android::wp;
 using ::android::binder::Status;
 
 using ::nos::NuggetClient;
@@ -42,32 +55,170 @@
 using ::android::hardware::citadel::BnCitadeld;
 using ::android::hardware::citadel::ICitadeld;
 
+using android::IBinder;
+using android::vendor::powerstats::BnPixelPowerStatsCallback;
+using android::vendor::powerstats::IPixelPowerStatsProvider;
+using android::vendor::powerstats::StateResidencyData;
+
 namespace {
 
+using namespace std::chrono_literals;
+
+// This attaches a timer to a function call. Call .schedule() to start the
+// timer, and the function will be called (once) after the time has elapsed. If
+// you call .schedule() again before that happens, it just restarts the timer.
+// There's no way to cancel the function call after it's scheduled; you can only
+// postpone it.
+class DeferredCallback {
+  public:
+    DeferredCallback(std::chrono::milliseconds delay, std::function<void()> fn)
+        : _armed(false),
+          _delay(delay),
+          _func(fn),
+          _waiter_thread(std::bind(&DeferredCallback::waiter_task, this)) {}
+    ~DeferredCallback() {}
+
+    // [re]start the timer for the delayed call
+    void schedule() {
+        std::unique_lock<std::mutex> _lock(_cv_mutex);
+        _armed = true;
+        _cv.notify_one();
+    }
+
+  private:
+    void waiter_task(void) {
+        std::unique_lock<std::mutex> _lock(_cv_mutex);
+        while (true) {
+            if (!_armed) {
+                _cv.wait(_lock);
+            }
+            auto timeout = std::chrono::steady_clock::now() + _delay;
+            if (_cv.wait_until(_lock, timeout) == std::cv_status::timeout) {
+                _func();
+                _armed = false;
+            }
+        }
+    }
+
+    bool _armed;
+    const std::chrono::milliseconds _delay;
+    const std::function<void()> _func;
+    std::thread _waiter_thread;
+    std::mutex _cv_mutex;
+    std::condition_variable _cv;
+};
+
+// This provides a Binder interface for the powerstats service to fetch our
+// power stats info from. This is a secondary function of citadeld. Failures
+// here must not block or delay AP/Citadel communication.
+class StatsDelegate : public BnPixelPowerStatsCallback,
+                      public IBinder::DeathRecipient {
+  public:
+    StatsDelegate(std::function<Status(std::vector<StateResidencyData>*)> fn)
+        : func_(fn) {}
+
+    // methods from BnPixelPowerStatsCallback
+    virtual Status getStats(std::vector<StateResidencyData>* stats) override {
+        return func_(stats);
+    }
+
+    // methods from IBinder::DeathRecipient
+    virtual IBinder* onAsBinder() override { return this; }
+    virtual void binderDied(const wp<IBinder>& who) override {
+        LOG(INFO) << "powerstats service died";
+        const sp<IBinder>& service = who.promote();
+        if (service != nullptr) {
+            service->unlinkToDeath(this);
+        }
+        sp<IBinder> powerstats_service = WaitForPowerStatsService();
+        registerWithPowerStats(powerstats_service);
+    }
+
+    // post-creation init (Binder calls inside constructor are troublesome)
+    void registerWithPowerStats(sp<IBinder>& powerstats_service) {
+        sp<IPixelPowerStatsProvider> powerstats_provider =
+                android::interface_cast<IPixelPowerStatsProvider>(
+                        powerstats_service);
+
+        LOG(INFO) << "signing up for a notification if powerstats dies";
+        auto ret = asBinder(powerstats_provider)
+                           ->linkToDeath(this, 0u /* cookie */);
+        if (ret != android::OK) {
+            LOG(ERROR) << "linkToDeath() returned " << ret
+                       << " - we will NOT be notified on powerstats death";
+        }
+
+        LOG(INFO) << "registering our callback with powerstats service";
+        Status status = powerstats_provider->registerCallback("Citadel", this);
+        if (!status.isOk()) {
+            LOG(ERROR) << "failed to register callback: " << status.toString8();
+        }
+    }
+
+    // static helper function
+    static sp<IBinder> WaitForPowerStatsService() {
+        LOG(INFO) << "waiting for powerstats service to appear";
+        sp<IBinder> svc;
+        while (true) {
+            svc = defaultServiceManager()->checkService(
+                    android::String16("power.stats-vendor"));
+            if (svc != nullptr) {
+                LOG(INFO) << "A wild powerstats service has appeared!";
+                return svc;
+            }
+            sleep(1);
+        }
+    }
+
+    // Creates a new StatsDelegate only after a powerstats service becomes
+    // available for it to register with.
+    static sp<StatsDelegate> MakeOne(
+            std::function<Status(std::vector<StateResidencyData>*)> fn) {
+        sp<IBinder> powerstats_service =
+                StatsDelegate::WaitForPowerStatsService();
+        sp<StatsDelegate> sd = new StatsDelegate(fn);
+        sd->registerWithPowerStats(powerstats_service);
+        return sd;
+    }
+
+  private:
+    const std::function<Status(std::vector<StateResidencyData>*)> func_;
+};
+
 class CitadelProxy : public BnCitadeld {
-public:
-    CitadelProxy(NuggetClient& client) : _client{client} {}
+  public:
+    CitadelProxy(NuggetClient& client)
+        : _client{client},
+          _event_thread(std::bind(&CitadelProxy::dispatchEvents, this)),
+          _stats_collection(500ms, std::bind(&CitadelProxy::cacheStats, this)) {
+    }
     ~CitadelProxy() override = default;
 
-    Status callApp(const int32_t _appId, const int32_t _arg, const std::vector<uint8_t>& request,
-                   std::vector<uint8_t>* const response, int32_t* const _aidl_return) override {
-        // AIDL doesn't support integers less than 32-bit so validate it before casting
+    // methods from BnCitadeld
+
+    Status callApp(const int32_t _appId, const int32_t _arg,
+                   const std::vector<uint8_t>& request,
+                   std::vector<uint8_t>* const response,
+                   int32_t* const _aidl_return) override {
+        // AIDL doesn't support integers less than 32-bit so validate it before
+        // casting
         if (_appId < 0 || _appId > kMaxAppId) {
             LOG(ERROR) << "App ID " << _appId << " is outside the app ID range";
             return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
         }
         if (_arg < 0 || _arg > std::numeric_limits<uint16_t>::max()) {
-            LOG(ERROR) << "Argument " << _arg << " is outside the unsigned 16-bit range";
+            LOG(ERROR) << "Argument " << _arg
+                       << " is outside the unsigned 16-bit range";
             return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
         }
 
         const uint8_t appId = static_cast<uint32_t>(_appId);
-        const uint16_t arg =  static_cast<uint16_t>(_arg);
+        const uint16_t arg = static_cast<uint16_t>(_arg);
         uint32_t* const appStatus = reinterpret_cast<uint32_t*>(_aidl_return);
+        *appStatus = lockedCallApp(appId, arg, request, response);
 
-        // Make the call to the app while holding the lock for that app
-        std::unique_lock<std::mutex> lock(_appLocks[appId]);
-        *appStatus = _client.CallApp(appId, arg, request, response);
+        _stats_collection.schedule();
+
         return Status::ok();
     }
 
@@ -79,28 +230,133 @@
         return Status::ok();
     }
 
+    Status getCachedStats(std::vector<uint8_t>* const response) override {
+        std::unique_lock<std::mutex> lock(_stats_mutex);
+        response->resize(sizeof(_stats));
+        memcpy(response->data(), &_stats, sizeof(_stats));
+        return Status::ok();
+    }
+
+    // Interaction with the powerstats service is handled by the StatsDelegate
+    // class, but its getStats() method calls this to access our cached stats.
+    Status onGetStats(std::vector<StateResidencyData>* stats) {
+        std::unique_lock<std::mutex> lock(_stats_mutex);
+
+        StateResidencyData data1;
+        data1.state = "Last-Reset";
+        data1.totalTimeInStateMs = _stats.time_since_hard_reset / 1000;
+        data1.totalStateEntryCount = _stats.hard_reset_count;
+        data1.lastEntryTimestampMs = 0;
+        stats->emplace_back(data1);
+
+        StateResidencyData data2;
+        data2.state = "Active";
+        data2.totalTimeInStateMs = _stats.time_spent_awake / 1000;
+        data2.totalStateEntryCount = _stats.wake_count;
+        data2.lastEntryTimestampMs = _stats.time_at_last_wake / 1000;
+        stats->emplace_back(data2);
+
+        StateResidencyData data3;
+        data3.state = "Deep-Sleep";
+        data3.totalTimeInStateMs = _stats.time_spent_in_deep_sleep / 1000;
+        data3.totalStateEntryCount = _stats.deep_sleep_count;
+        data3.lastEntryTimestampMs = _stats.time_at_last_deep_sleep / 1000;
+        stats->emplace_back(data3);
+
+        return Status::ok();
+    }
+
 private:
     static constexpr auto kMaxAppId = std::numeric_limits<uint8_t>::max();
 
     NuggetClient& _client;
+    std::thread _event_thread;
     std::mutex _appLocks[kMaxAppId + 1];
-};
+    struct nugget_app_low_power_stats _stats;
+    DeferredCallback _stats_collection;
+    std::mutex _stats_mutex;
 
-[[noreturn]] void CitadelEventDispatcher(const nos_device& device) {
-    LOG(INFO) << "Event dispatcher startup.";
-    while(1) {
-        if (device.ops.wait_for_interrupt(device.ctx, -1) > 0) {
-            LOG(INFO) << "Citadel has dispatched an event";
-        } else {
-            LOG(INFO) << "Citadel did something unexpected";
-        }
-
-        // This is a placeholder for the message handling that gives citadel a
-        // chance to deassert CTLD_AP_IRQ, so this doesn't spam the logs.
-        // TODO(b/62713383) Replace this with the code to contact citadel.
-        sleep(1);
+    // Make the call to the app while holding the lock for that app
+    uint32_t lockedCallApp(uint32_t appId, uint16_t arg,
+                           const std::vector<uint8_t>& request,
+                           std::vector<uint8_t>* response) {
+        std::unique_lock<std::mutex> lock(_appLocks[appId]);
+        return _client.CallApp(appId, arg, request, response);
     }
-}
+
+    void cacheStats(void) {
+        std::vector<uint8_t> buffer;
+
+        buffer.reserve(sizeof(_stats));
+        uint32_t rv = lockedCallApp(APP_ID_NUGGET,
+                                    NUGGET_PARAM_GET_LOW_POWER_STATS, buffer,
+                                    &buffer);
+        if (rv == APP_SUCCESS) {
+            std::unique_lock<std::mutex> lock(_stats_mutex);
+            memcpy(&_stats, buffer.data(),
+                   std::min(sizeof(_stats), buffer.size()));
+        }
+    }
+
+    [[noreturn]] void dispatchEvents(void) {
+        LOG(INFO) << "Event dispatcher startup.";
+
+        const nos_device& device = *_client.Device();
+
+        while (true) {
+
+            const int wait_rv = device.ops.wait_for_interrupt(device.ctx, -1);
+            if (wait_rv <= 0) {
+                LOG(WARNING) << "device.ops.wait_for_interrupt: " << wait_rv;
+                continue;
+            }
+
+            // CTDL_AP_IRQ is asserted, fetch all the event_records from Citadel
+            while (true) {
+                struct event_record evt;
+                std::vector<uint8_t> buffer;
+                buffer.reserve(sizeof(evt));
+                const uint32_t rv = lockedCallApp(APP_ID_NUGGET,
+                                                  NUGGET_PARAM_GET_EVENT_RECORD,
+                                                  buffer, &buffer);
+                if (rv != APP_SUCCESS) {
+                    LOG(WARNING) << "failed to fetch event_record: " << rv;
+                    break;
+                }
+
+                if (buffer.size() == 0) {
+                    // Success but no data means we've fetched them all
+                    break;
+                }
+
+                // TODO(b/34946126): Do something more than just log it
+                memcpy(&evt, buffer.data(), sizeof(evt));
+                const uint64_t secs = evt.uptime_usecs / 1000000UL;
+                const uint64_t usecs = evt.uptime_usecs - (secs * 1000000UL);
+                LOG(INFO) << std::setfill('0') << std::internal
+                          << "event_record " << evt.reset_count << "/"
+                          << secs << "." << std::setw(6) << usecs
+                          << " " << evt.id
+                          << std::hex
+                          << " 0x" << std::setw(8) << evt.u.raw.w[0]
+                          << " 0x" << std::setw(8) << evt.u.raw.w[1]
+                          << " 0x" << std::setw(8) << evt.u.raw.w[2];
+            }
+
+            // TODO: Add a more intelligent back-off (and other action?) here
+            //
+            // When Citadel indicates that it has event_records for us, we fetch
+            // one at a time without delay until we've gotten them all (and then
+            // wait a bit to give it time to deassert CTDL_AP_IRQ).
+            //
+            // OTOH, if Citadel is just constantly asserting CTDL_AP_IRQ but
+            // doesn't actually have any events for us, then a) that's probably
+            // a bug, and b) we shouldn't spin madly here just querying it over
+            // and over.
+            sleep(1);
+        }
+    }
+};
 
 } // namespace
 
@@ -122,14 +378,23 @@
     const status_t status = defaultServiceManager()->addService(ICitadeld::descriptor, proxy);
     if (status != OK) {
         LOG(FATAL) << "Failed to register citadeld as a service (status " << status << ")";
+        return 1;
     }
 
-    // Handle interrupts triggered by Citadel and dispatch any events to
-    // registered listeners.
-    std::thread event_dispatcher(CitadelEventDispatcher, *citadel.Device());
+    // We'll create a StatsDelegate object to talk to the powerstats service,
+    // but it will need a function to access the stats we've cached in the
+    // CitadelProxy object.
+    std::function<Status(std::vector<StateResidencyData>*)> fn =
+            std::bind(&CitadelProxy::onGetStats, proxy, std::placeholders::_1);
+
+    // Use a separate thread to wait for the powerstats service to appear, so
+    // the Citadel proxy can start working ASAP.
+    std::future<sp<StatsDelegate>> sd =
+            std::async(std::launch::async, StatsDelegate::MakeOne, fn);
 
     // Start handling binder requests with multiple threads
     ProcessState::self()->startThreadPool();
     IPCThreadState::self()->joinThreadPool();
+
     return 0;
 }
diff --git a/citadel/libnos_datagram/citadel.c b/citadel/libnos_datagram/citadel.c
index f2ba9ba..026224d 100644
--- a/citadel/libnos_datagram/citadel.c
+++ b/citadel/libnos_datagram/citadel.c
@@ -34,7 +34,7 @@
 #include <unistd.h>
 
 /*****************************************************************************/
-/* TODO: #include <linux/citadel.h> */
+/* Ideally, this should be in <linux/citadel.h> */
 #define CITADEL_IOC_MAGIC               'c'
 struct citadel_ioc_tpm_datagram {
     __u64        buf;
diff --git a/citadel/validation/citadel_validation_tool.cpp b/citadel/validation/citadel_validation_tool.cpp
index 39c0338..5fddb44 100644
--- a/citadel/validation/citadel_validation_tool.cpp
+++ b/citadel/validation/citadel_validation_tool.cpp
@@ -156,7 +156,6 @@
  * The current implementation of the test writes random vales to registers and
  * reads them back. This lets us check the correct values were sent across the
  * channel.
- * TODO(b/65067435): Replace with less intrusive calls.
  */
 int CmdStressSpi(NuggetClientInterface& client, char** params) {
     std::random_device rd;
@@ -211,7 +210,6 @@
 /*
  * The current implementation directly reads some registers and checks they
  * contain valid values.
- * TODO(b/65067435): Replace with less intrusive calls.
  */
 int CmdHealthCheck(NuggetClientInterface& client) {
     int ret = EXIT_SUCCESS;
diff --git a/hals/keymaster/Android.bp b/hals/keymaster/Android.bp
index f9c4aa3..b956e20 100644
--- a/hals/keymaster/Android.bp
+++ b/hals/keymaster/Android.bp
@@ -28,6 +28,7 @@
     cflags: [
         // Needed for compiling BoringSSL.
         "-Wno-gnu-anonymous-struct",
+        "-Wno-implicit-fallthrough",  // in proto_utils.cpp:836
         "-Wno-nested-anon-types",
     ],
     shared_libs: [
diff --git a/hals/keymaster/buffer.cpp b/hals/keymaster/buffer.cpp
index 35a7d4f..89feadc 100644
--- a/hals/keymaster/buffer.cpp
+++ b/hals/keymaster/buffer.cpp
@@ -56,6 +56,7 @@
         case Algorithm::EC:
         case Algorithm::HMAC:
             _blockSize = 0;
+            break;
         default:
             break;
         }
diff --git a/hals/keymaster/citadel/Android.bp b/hals/keymaster/citadel/Android.bp
new file mode 100644
index 0000000..c62578a
--- /dev/null
+++ b/hals/keymaster/citadel/Android.bp
@@ -0,0 +1,51 @@
+//
+// 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_binary {
+    name: "[email protected]",
+    init_rc: ["[email protected]"],
+
+    srcs: ["service.cpp"],
+
+    required: ["citadeld"],
+    header_libs: ["nos_headers"],
+    shared_libs: [
+        "libbase",
+        "libhidlbase",
+        "libhidltransport",
+        "libnos",
+        "libnosprotos",
+        "libutils",
+        "libprotobuf-cpp-full",
+        "[email protected]",
+        "[email protected]",
+        "libnos_citadeld_proxy",
+        "nos_app_keymaster",
+    ],
+
+    relative_install_path: "hw",
+
+    cflags: [
+        "-pedantic",
+        "-Wall",
+        "-Wextra",
+        "-Werror",
+        "-Wno-zero-length-array",
+    ],
+    conlyflags: ["-std=c11"],
+    vendor: true,
+    owner: "google",
+
+}
diff --git a/hals/keymaster/citadel/Android.mk b/hals/keymaster/citadel/Android.mk
deleted file mode 100644
index 4eb1420..0000000
--- a/hals/keymaster/citadel/Android.mk
+++ /dev/null
@@ -1,80 +0,0 @@
-#
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := [email protected]
-LOCAL_INIT_RC := [email protected]
-
-LOCAL_SRC_FILES := service.cpp
-
-LOCAL_REQUIRED_MODULES := citadeld
-LOCAL_HEADER_LIBRARIES := nos_headers
-LOCAL_SHARED_LIBRARIES := \
-    libbase \
-    libhidlbase \
-    libhidltransport \
-    libnos \
-    libnosprotos \
-    libutils \
-    libprotobuf-cpp-full \
-    [email protected] \
-    [email protected] \
-    libnos_citadeld_proxy \
-    nos_app_keymaster
-
-
-LOCAL_MODULE_RELATIVE_PATH := hw
-
-LOCAL_CFLAGS := -pedantic -Wall -Wextra -Werror -Wno-zero-length-array
-LOCAL_CONLYFLAGS := -std=c11
-LOCAL_CLANG := true
-LOCAL_VENDOR_MODULE := true
-LOCAL_MODULE_OWNER := google
-
-ifneq ($(BUILD_WITHOUT_VENDOR),true)
-ifeq ($(call is-board-platform-in-list, sdm845),true)
-LOCAL_SHARED_LIBRARIES += \
-    libkeymasterprovision \
-    libkeymasterutils \
-    libkeymasterdeviceutils \
-    libQSEEComAPI
-
-LOCAL_CFLAGS += -DENABLE_QCOM_OTF_PROVISIONING=1
-endif
-endif
-
-include $(BUILD_EXECUTABLE)
-
-#cc_binary {
-#    name: "[email protected]",
-#    init_rc: ["[email protected]"],
-#    required: ["citadeld"],
-#    srcs: [
-#        "service.cpp",
-#    ],
-#    defaults: ["nos_hal_service_defaults"],
-#    shared_libs: [
-#        "[email protected]",
-#        "[email protected]",
-#        "libnos_citadeld_proxy",
-#        "nos_app_keymaster",
-#        "libkeymasterprovision",
-#        "libkeymasterutils",
-#        "libkeymasterdeviceutils",
-#        "libQSEEComAPI",
-#    ],
-#}
diff --git a/hals/keymaster/proto_utils.cpp b/hals/keymaster/proto_utils.cpp
index a1fbfb0..03c7b43 100644
--- a/hals/keymaster/proto_utils.cpp
+++ b/hals/keymaster/proto_utils.cpp
@@ -789,9 +789,11 @@
                 // Duplicates not allowed for these tags types.
                 return ErrorCode::INVALID_ARGUMENT;
             }
-            /* Fall-through! */
+            FALLTHROUGH_INTENDED;
         case TagType::ENUM_REP:
+            FALLTHROUGH_INTENDED;
         case TagType::UINT_REP:
+            FALLTHROUGH_INTENDED;
         case TagType::ULONG_REP:
             if (tag_map->find(params[i].tag) == tag_map->end()) {
                 vector<KeyParameter> v{params[i]};