Merge "Break out Features from fb data stream; add dist_coeffs; name cleanup"
diff --git a/aos/BUILD b/aos/BUILD
index 12d25b2..1d6d388 100644
--- a/aos/BUILD
+++ b/aos/BUILD
@@ -477,6 +477,7 @@
         "testdata/config2_multinode.json",
         "testdata/config3.json",
         "testdata/expected.json",
+        "testdata/expected_merge_with.json",
         "testdata/expected_multinode.json",
         "testdata/good_multinode.json",
         "testdata/good_multinode_hostnames.json",
diff --git a/aos/configuration.cc b/aos/configuration.cc
index ac897bf..d6d276e 100644
--- a/aos/configuration.cc
+++ b/aos/configuration.cc
@@ -417,6 +417,14 @@
   return MergeConfiguration(ReadConfig(path, &visited_paths));
 }
 
+FlatbufferDetachedBuffer<Configuration> MergeWithConfig(
+    const Configuration *config, std::string_view json) {
+  FlatbufferDetachedBuffer<Configuration> addition =
+      JsonToFlatbuffer(json, Configuration::MiniReflectTypeTable());
+
+  return MergeConfiguration(MergeFlatBuffers(config, &addition.message()));
+}
+
 const Channel *GetChannel(const Configuration *config, std::string_view name,
                           std::string_view type,
                           std::string_view application_name, const Node *node) {
diff --git a/aos/configuration.h b/aos/configuration.h
index bf2ec6c..9193fd5 100644
--- a/aos/configuration.h
+++ b/aos/configuration.h
@@ -32,6 +32,11 @@
     const Flatbuffer<Configuration> &config,
     const std::vector<aos::FlatbufferString<reflection::Schema>> &schemas);
 
+// Merges a configuration json snippet into the provided configuration and
+// returns the modified config.
+FlatbufferDetachedBuffer<Configuration> MergeWithConfig(
+    const Configuration *config, std::string_view json);
+
 // Returns the resolved location for a name, type, and application name. Returns
 // nullptr if none is found.
 //
diff --git a/aos/configuration_test.cc b/aos/configuration_test.cc
index c36bd93..f069277 100644
--- a/aos/configuration_test.cc
+++ b/aos/configuration_test.cc
@@ -13,6 +13,8 @@
 namespace configuration {
 namespace testing {
 
+const std::string kConfigPrefix = "aos/testdata/";
+
 class ConfigurationTest : public ::testing::Test {
  public:
   ConfigurationTest() { ::aos::testing::EnableTestLogging(); }
@@ -30,19 +32,19 @@
 // Tests that we can read and merge a configuration.
 TEST_F(ConfigurationTest, ConfigMerge) {
   FlatbufferDetachedBuffer<Configuration> config =
-      ReadConfig("aos/testdata/config1.json");
+      ReadConfig(kConfigPrefix + "config1.json");
   LOG(INFO) << "Read: " << FlatbufferToJson(config, true);
 
   EXPECT_EQ(
       absl::StripSuffix(
-          util::ReadFileToStringOrDie("aos/testdata/expected.json"), "\n"),
+          util::ReadFileToStringOrDie(kConfigPrefix + "expected.json"), "\n"),
       FlatbufferToJson(config, true));
 }
 
 // Tests that we can get back a ChannelIndex.
 TEST_F(ConfigurationTest, ChannelIndex) {
   FlatbufferDetachedBuffer<Configuration> config =
-      ReadConfig("aos/testdata/config1.json");
+      ReadConfig(kConfigPrefix + "config1.json");
 
   EXPECT_EQ(
       ChannelIndex(&config.message(), config.message().channels()->Get(1u)),
@@ -52,12 +54,12 @@
 // Tests that we can read and merge a multinode configuration.
 TEST_F(ConfigurationTest, ConfigMergeMultinode) {
   FlatbufferDetachedBuffer<Configuration> config =
-      ReadConfig("aos/testdata/config1_multinode.json");
+      ReadConfig(kConfigPrefix + "config1_multinode.json");
   LOG(INFO) << "Read: " << FlatbufferToJson(config, true);
 
   EXPECT_EQ(
       std::string(absl::StripSuffix(
-          util::ReadFileToStringOrDie("aos/testdata/expected_multinode.json"),
+          util::ReadFileToStringOrDie(kConfigPrefix + "expected_multinode.json"),
           "\n")),
       FlatbufferToJson(config, true));
 }
@@ -65,7 +67,7 @@
 // Tests that we sort the entries in a config so we can look entries up.
 TEST_F(ConfigurationTest, UnsortedConfig) {
   FlatbufferDetachedBuffer<Configuration> config =
-      ReadConfig("aos/testdata/backwards.json");
+      ReadConfig(kConfigPrefix + "backwards.json");
 
   LOG(INFO) << "Read: " << FlatbufferToJson(config, true);
 
@@ -80,16 +82,41 @@
   EXPECT_DEATH(
       {
         FlatbufferDetachedBuffer<Configuration> config =
-            ReadConfig("aos/testdata/config1_bad.json");
+            ReadConfig(kConfigPrefix + "config1_bad.json");
       },
-      "aos/testdata/config1_bad.json");
+      kConfigPrefix + "config1_bad.json");
+}
+
+// Tests that we can modify a config with a json snippet.
+TEST_F(ConfigurationTest, MergeWithConfig) {
+  FlatbufferDetachedBuffer<Configuration> config =
+      ReadConfig(kConfigPrefix + "config1.json");
+  LOG(INFO) << "Read: " << FlatbufferToJson(config, true);
+
+  FlatbufferDetachedBuffer<Configuration> updated_config =
+      MergeWithConfig(&config.message(),
+                      R"channel({
+  "channels": [
+    {
+      "name": "/foo",
+      "type": ".aos.bar",
+      "max_size": 100
+    }
+  ]
+})channel");
+
+  EXPECT_EQ(
+      absl::StripSuffix(util::ReadFileToStringOrDie(
+                            kConfigPrefix + "expected_merge_with.json"),
+                        "\n"),
+      FlatbufferToJson(updated_config, true));
 }
 
 // Tests that we can lookup a location, complete with maps, from a merged
 // config.
 TEST_F(ConfigurationTest, GetChannel) {
   FlatbufferDetachedBuffer<Configuration> config =
-      ReadConfig("aos/testdata/config1.json");
+      ReadConfig(kConfigPrefix + "config1.json");
 
   // Test a basic lookup first.
   EXPECT_EQ(
@@ -123,7 +150,7 @@
 // Tests that we can lookup a location with node specific maps.
 TEST_F(ConfigurationTest, GetChannelMultinode) {
   FlatbufferDetachedBuffer<Configuration> config =
-      ReadConfig("aos/testdata/good_multinode.json");
+      ReadConfig(kConfigPrefix + "good_multinode.json");
   const Node *pi1 = GetNode(&config.message(), "pi1");
   const Node *pi2 = GetNode(&config.message(), "pi2");
 
@@ -159,7 +186,7 @@
 // Tests that we can lookup a location with type specific maps.
 TEST_F(ConfigurationTest, GetChannelTypedMultinode) {
   FlatbufferDetachedBuffer<Configuration> config =
-      ReadConfig("aos/testdata/good_multinode.json");
+      ReadConfig(kConfigPrefix + "good_multinode.json");
   const Node *pi1 = GetNode(&config.message(), "pi1");
 
   // Test a basic lookup first.
@@ -182,28 +209,28 @@
   EXPECT_DEATH(
       {
         FlatbufferDetachedBuffer<Configuration> config =
-            ReadConfig("aos/testdata/invalid_nodes.json");
+            ReadConfig(kConfigPrefix + "invalid_nodes.json");
       },
       "source_node");
 
   EXPECT_DEATH(
       {
         FlatbufferDetachedBuffer<Configuration> config =
-            ReadConfig("aos/testdata/invalid_source_node.json");
+            ReadConfig(kConfigPrefix + "invalid_source_node.json");
       },
       "source_node");
 
   EXPECT_DEATH(
       {
         FlatbufferDetachedBuffer<Configuration> config =
-            ReadConfig("aos/testdata/invalid_destination_node.json");
+            ReadConfig(kConfigPrefix + "invalid_destination_node.json");
       },
       "destination_nodes");
 
   EXPECT_DEATH(
       {
         FlatbufferDetachedBuffer<Configuration> config =
-            ReadConfig("aos/testdata/self_forward.json");
+            ReadConfig(kConfigPrefix + "self_forward.json");
       },
       "forwarding data to itself");
 }
@@ -582,7 +609,7 @@
 // Tests that we can deduce source nodes from a multinode config.
 TEST_F(ConfigurationTest, SourceNodeNames) {
   FlatbufferDetachedBuffer<Configuration> config =
-      ReadConfig("aos/testdata/config1_multinode.json");
+      ReadConfig(kConfigPrefix + "config1_multinode.json");
 
   // This is a bit simplistic in that it doesn't test deduplication, but it does
   // exercise a lot of the logic.
@@ -597,7 +624,7 @@
 // Tests that we can deduce destination nodes from a multinode config.
 TEST_F(ConfigurationTest, DestinationNodeNames) {
   FlatbufferDetachedBuffer<Configuration> config =
-      ReadConfig("aos/testdata/config1_multinode.json");
+      ReadConfig(kConfigPrefix + "config1_multinode.json");
 
   // This is a bit simplistic in that it doesn't test deduplication, but it does
   // exercise a lot of the logic.
@@ -613,7 +640,7 @@
 TEST_F(ConfigurationTest, GetNodes) {
   {
     FlatbufferDetachedBuffer<Configuration> config =
-        ReadConfig("aos/testdata/good_multinode.json");
+        ReadConfig(kConfigPrefix + "good_multinode.json");
     const Node *pi1 = GetNode(&config.message(), "pi1");
     const Node *pi2 = GetNode(&config.message(), "pi2");
 
@@ -622,7 +649,7 @@
 
   {
     FlatbufferDetachedBuffer<Configuration> config =
-        ReadConfig("aos/testdata/config1.json");
+        ReadConfig(kConfigPrefix + "config1.json");
     EXPECT_THAT(GetNodes(&config.message()), ::testing::ElementsAre(nullptr));
   }
 }
@@ -630,9 +657,9 @@
 // Tests that we can extract a node index from a config.
 TEST_F(ConfigurationTest, GetNodeIndex) {
   FlatbufferDetachedBuffer<Configuration> config =
-      ReadConfig("aos/testdata/good_multinode.json");
+      ReadConfig(kConfigPrefix + "good_multinode.json");
   FlatbufferDetachedBuffer<Configuration> config2 =
-      ReadConfig("aos/testdata/good_multinode.json");
+      ReadConfig(kConfigPrefix + "good_multinode.json");
   const Node *pi1 = GetNode(&config.message(), "pi1");
   const Node *pi2 = GetNode(&config.message(), "pi2");
 
@@ -653,13 +680,13 @@
 // valid nodes.
 TEST_F(ConfigurationDeathTest, GetNodeOrDie) {
   FlatbufferDetachedBuffer<Configuration> config =
-      ReadConfig("aos/testdata/good_multinode.json");
+      ReadConfig(kConfigPrefix + "good_multinode.json");
   FlatbufferDetachedBuffer<Configuration> config2 =
-      ReadConfig("aos/testdata/good_multinode.json");
+      ReadConfig(kConfigPrefix + "good_multinode.json");
   {
     // Simple case, nullptr -> nullptr
     FlatbufferDetachedBuffer<Configuration> single_node_config =
-        ReadConfig("aos/testdata/config1.json");
+        ReadConfig(kConfigPrefix + "config1.json");
     EXPECT_EQ(nullptr, GetNodeOrDie(&single_node_config.message(), nullptr));
 
     // Confirm that we die when a node is passed in.
@@ -679,7 +706,7 @@
 
 TEST_F(ConfigurationTest, GetNodeFromHostname) {
   FlatbufferDetachedBuffer<Configuration> config =
-      ReadConfig("aos/testdata/good_multinode.json");
+      ReadConfig(kConfigPrefix + "good_multinode.json");
   EXPECT_EQ("pi1",
             CHECK_NOTNULL(GetNodeFromHostname(&config.message(), "raspberrypi"))
                 ->name()
@@ -695,7 +722,7 @@
 
 TEST_F(ConfigurationTest, GetNodeFromHostnames) {
   FlatbufferDetachedBuffer<Configuration> config =
-      ReadConfig("aos/testdata/good_multinode_hostnames.json");
+      ReadConfig(kConfigPrefix + "good_multinode_hostnames.json");
   EXPECT_EQ("pi1",
             CHECK_NOTNULL(GetNodeFromHostname(&config.message(), "raspberrypi"))
                 ->name()
diff --git a/aos/events/shm_event_loop.cc b/aos/events/shm_event_loop.cc
index dad62cd..57bcb1c 100644
--- a/aos/events/shm_event_loop.cc
+++ b/aos/events/shm_event_loop.cc
@@ -58,7 +58,7 @@
 }
 std::string ShmPath(const Channel *channel) {
   CHECK(channel->has_type());
-  return ShmFolder(channel) + channel->type()->str() + ".v1";
+  return ShmFolder(channel) + channel->type()->str() + ".v2";
 }
 
 class MMapedQueue {
diff --git a/aos/events/shm_event_loop_test.cc b/aos/events/shm_event_loop_test.cc
index 87411d2..0c39704 100644
--- a/aos/events/shm_event_loop_test.cc
+++ b/aos/events/shm_event_loop_test.cc
@@ -27,12 +27,12 @@
     }
 
     // Clean up anything left there before.
-    unlink((FLAGS_shm_base + "/test/aos.TestMessage.v1").c_str());
-    unlink((FLAGS_shm_base + "/test1/aos.TestMessage.v1").c_str());
-    unlink((FLAGS_shm_base + "/test2/aos.TestMessage.v1").c_str());
-    unlink((FLAGS_shm_base + "/test2/aos.TestMessage.v1").c_str());
-    unlink((FLAGS_shm_base + "/aos/aos.timing.Report.v1").c_str());
-    unlink((FLAGS_shm_base + "/aos/aos.logging.LogMessageFbs.v1").c_str());
+    unlink((FLAGS_shm_base + "/test/aos.TestMessage.v2").c_str());
+    unlink((FLAGS_shm_base + "/test1/aos.TestMessage.v2").c_str());
+    unlink((FLAGS_shm_base + "/test2/aos.TestMessage.v2").c_str());
+    unlink((FLAGS_shm_base + "/test2/aos.TestMessage.v2").c_str());
+    unlink((FLAGS_shm_base + "/aos/aos.timing.Report.v2").c_str());
+    unlink((FLAGS_shm_base + "/aos/aos.logging.LogMessageFbs.v2").c_str());
   }
 
   ~ShmEventLoopTestFactory() { FLAGS_override_hostname = ""; }
diff --git a/aos/ipc_lib/lockless_queue.cc b/aos/ipc_lib/lockless_queue.cc
index c323b8b..7126ffd 100644
--- a/aos/ipc_lib/lockless_queue.cc
+++ b/aos/ipc_lib/lockless_queue.cc
@@ -306,6 +306,7 @@
     }
 
     memory->next_queue_index.Invalidate();
+    memory->uid = getuid();
 
     for (size_t i = 0; i < memory->num_senders(); ++i) {
       ::aos::ipc_lib::Sender *s = memory->GetSender(i);
@@ -319,6 +320,8 @@
     // Signal everything is done.  This needs to be done last, so if we die, we
     // redo initialization.
     memory->initialized = true;
+  } else {
+    CHECK_EQ(getuid(), memory->uid) << ": UIDs must match for all processes";
   }
 
   return memory;
@@ -871,6 +874,8 @@
               << memory->next_queue_index.Load(queue_size).DebugString()
               << ::std::endl;
 
+  ::std::cout << "    uid_t uid = " << memory->uid << ::std::endl;
+
   ::std::cout << "  }" << ::std::endl;
   ::std::cout << "  AtomicIndex queue[" << queue_size << "] {" << ::std::endl;
   for (size_t i = 0; i < queue_size; ++i) {
diff --git a/aos/ipc_lib/lockless_queue_memory.h b/aos/ipc_lib/lockless_queue_memory.h
index cbe76a7..a10609c 100644
--- a/aos/ipc_lib/lockless_queue_memory.h
+++ b/aos/ipc_lib/lockless_queue_memory.h
@@ -50,6 +50,11 @@
   // A message is valid iff its internal index matches the index in the queue.
   AtomicQueueIndex next_queue_index;
 
+  // All processes using a queue need to be able to send messages to each other.
+  // We're going to require they have matching UIDs, which is sufficient to do
+  // that.
+  uid_t uid;
+
   // There is then memory allocated after this structure.  That memory is used
   // to store the messages, queue, watchers, and senders.  This is equivalent to
   // writing:
diff --git a/aos/logging/BUILD b/aos/logging/BUILD
index 214df63..68a493b 100644
--- a/aos/logging/BUILD
+++ b/aos/logging/BUILD
@@ -156,6 +156,6 @@
 flatbuffer_cc_library(
     name = "log_message_fbs",
     srcs = ["log_message.fbs"],
-    visibility = ["//visibility:public"],
     gen_reflections = 1,
+    visibility = ["//visibility:public"],
 )
diff --git a/aos/network/www/BUILD b/aos/network/www/BUILD
index bab5198..67e54f8 100644
--- a/aos/network/www/BUILD
+++ b/aos/network/www/BUILD
@@ -7,7 +7,7 @@
         "**/*.html",
         "**/*.css",
     ]),
-    visibility=["//visibility:public"],
+    visibility = ["//visibility:public"],
 )
 
 ts_library(
@@ -16,12 +16,12 @@
         "config_handler.ts",
         "proxy.ts",
     ],
+    visibility = ["//visibility:public"],
     deps = [
-        "//aos/network:web_proxy_ts_fbs",
-        "//aos/network:connect_ts_fbs",
         "//aos:configuration_ts_fbs",
+        "//aos/network:connect_ts_fbs",
+        "//aos/network:web_proxy_ts_fbs",
     ],
-    visibility=["//visibility:public"],
 )
 
 ts_library(
@@ -39,10 +39,10 @@
 rollup_bundle(
     name = "main_bundle",
     entry_point = "aos/network/www/main",
+    visibility = ["//aos:__subpackages__"],
     deps = [
         "main",
     ],
-    visibility=["//aos:__subpackages__"],
 )
 
 genrule(
@@ -54,5 +54,5 @@
         "flatbuffers.js",
     ],
     cmd = "cp $(location @com_github_google_flatbuffers//:flatjs) $@",
-    visibility=["//aos:__subpackages__"],
+    visibility = ["//aos:__subpackages__"],
 )
diff --git a/aos/testdata/expected_merge_with.json b/aos/testdata/expected_merge_with.json
new file mode 100644
index 0000000..0ce2056
--- /dev/null
+++ b/aos/testdata/expected_merge_with.json
@@ -0,0 +1,64 @@
+{
+ "channels": [
+  {
+   "name": "/foo",
+   "type": ".aos.bar",
+   "max_size": 100
+  },
+  {
+   "name": "/foo2",
+   "type": ".aos.bar"
+  },
+  {
+   "name": "/foo3",
+   "type": ".aos.bar",
+   "max_size": 9
+  }
+ ],
+ "maps": [
+  {
+   "match": {
+    "name": "/batman"
+   },
+   "rename": {
+    "name": "/bar"
+   }
+  },
+  {
+   "match": {
+    "name": "/batman"
+   },
+   "rename": {
+    "name": "/foo"
+   }
+  }
+ ],
+ "applications": [
+  {
+   "name": "app1",
+   "maps": [
+    {
+     "match": {
+      "name": "/bar"
+     },
+     "rename": {
+      "name": "/foo"
+     }
+    }
+   ]
+  },
+  {
+   "name": "app2",
+   "maps": [
+    {
+     "match": {
+      "name": "/baz"
+     },
+     "rename": {
+      "name": "/foo"
+     }
+    }
+   ]
+  }
+ ]
+}
diff --git a/aos/testing/BUILD b/aos/testing/BUILD
index 9aa058d..8693f27 100644
--- a/aos/testing/BUILD
+++ b/aos/testing/BUILD
@@ -24,9 +24,9 @@
     visibility = ["//visibility:public"],
     deps = [
         ":googletest",
-        "@com_google_absl//absl/base",
         "//aos/logging:implementations",
         "//aos/mutex",
+        "@com_google_absl//absl/base",
     ],
 )
 
diff --git a/debian/webrtc.BUILD b/debian/webrtc.BUILD
index e90e268..23e029d 100644
--- a/debian/webrtc.BUILD
+++ b/debian/webrtc.BUILD
@@ -2,17 +2,17 @@
 
 cc_library(
     name = "webrtc",
-    visibility = ["//visibility:public"],
-    hdrs = glob(["include/**/*.h"]),
     srcs = cpu_select({
         "arm": ["lib/arm/Release/libwebrtc_full.a"],
         "else": ["lib/x64/Release/libwebrtc_full.a"],
     }),
+    hdrs = glob(["include/**/*.h"]),
     includes = ["include"],
+    visibility = ["//visibility:public"],
     deps = [
+        "@com_google_absl//absl/algorithm:container",
         "@com_google_absl//absl/strings",
         "@com_google_absl//absl/types:optional",
         "@com_google_absl//absl/types:variant",
-        "@com_google_absl//absl/algorithm:container",
     ],
 )
diff --git a/frc971/control_loops/python/BUILD b/frc971/control_loops/python/BUILD
index 1fae02b..7953474 100644
--- a/frc971/control_loops/python/BUILD
+++ b/frc971/control_loops/python/BUILD
@@ -167,22 +167,22 @@
     name = "spline_graph",
     srcs = [
         "color.py",
-        "spline_drawing.py",
-        "spline_writer.py",
+        "graph.py",
         "path_edit.py",
         "points.py",
-        "graph.py",
+        "spline_drawing.py",
         "spline_graph.py",
+        "spline_writer.py",
     ],
     legacy_create_init = False,
     restricted_to = ["//tools:k8"],
     visibility = ["//visibility:public"],
     deps = [
+        ":basic_window",
         ":libspline",
         ":python_init",
-        "@python_gtk",
         "@matplotlib_repo//:matplotlib2.7",
-        ":basic_window",
+        "@python_gtk",
     ],
 )
 
diff --git a/third_party/BUILD b/third_party/BUILD
index 13f015e..fd10d43 100644
--- a/third_party/BUILD
+++ b/third_party/BUILD
@@ -99,4 +99,3 @@
         "roborio": ["@webrtc_rio//:webrtc"],
     }),
 )
-
diff --git a/third_party/flatbuffers/build_defs.bzl b/third_party/flatbuffers/build_defs.bzl
index 6ac1d87..f4c1dc7 100644
--- a/third_party/flatbuffers/build_defs.bzl
+++ b/third_party/flatbuffers/build_defs.bzl
@@ -282,7 +282,7 @@
         been parsed. As such, we just force the user to manually specify
         things.
     """
-    python_files = ["%s/%s.py" % (namespace.replace('.', '/'), table) for table in tables]
+    python_files = ["%s/%s.py" % (namespace.replace(".", "/"), table) for table in tables]
 
     srcs_lib = "%s_srcs" % (name)
     flatbuffer_library_public(
diff --git a/third_party/gperftools/BUILD b/third_party/gperftools/BUILD
index 25a8740..7f5e9d6 100644
--- a/third_party/gperftools/BUILD
+++ b/third_party/gperftools/BUILD
@@ -86,7 +86,7 @@
     "-DPERFTOOLS_DLL_DECL=",
     "-DSTDC_HEADERS=1",
     "-DSTL_NAMESPACE=std",
-    "-DPACKAGE_STRING=\\\"gperftools\ 2.4\\\"",
+    "-DPACKAGE_STRING=\\\"gperftools\\ 2.4\\\"",
     "-DPACKAGE_BUGREPORT=\\\"http://www.frc971.org/contact\\\"",
     "-DPACKAGE_VERSION=\\\"2.4\\\"",
 ] + cpu_select({
@@ -141,7 +141,7 @@
         "-lrt",
         "-lpthread",
     ],
-    nocopts = "-std=gnu\+\+1y",
+    nocopts = "-std=gnu\\+\\+1y",
     visibility = ["//visibility:public"],
     deps = [
         "//third_party/empty_config_h",
diff --git a/third_party/libevent/BUILD b/third_party/libevent/BUILD
index da05f3c..347ec0b 100644
--- a/third_party/libevent/BUILD
+++ b/third_party/libevent/BUILD
@@ -148,7 +148,7 @@
         "_EVENT_STDC_HEADERS=1",
         "_EVENT_TIME_WITH_SYS_TIME=1",
         "_EVENT_NUMERIC_VERSION=0x02001600",
-        '_EVENT_VERSION=\\"2.0.22-stable\\"',
+        "_EVENT_VERSION=\\\"2.0.22-stable\\\"",
     ] + address_size_select({
         "32": [
             "_EVENT_SIZEOF_LONG_LONG=4",
diff --git a/y2020/control_loops/python/BUILD b/y2020/control_loops/python/BUILD
index 923d239..e218571 100644
--- a/y2020/control_loops/python/BUILD
+++ b/y2020/control_loops/python/BUILD
@@ -133,8 +133,8 @@
     legacy_create_init = False,
     restricted_to = ["//tools:k8"],
     deps = [
-        ":python_init",
         ":flywheel",
+        ":python_init",
         "//external:python-gflags",
         "//external:python-glog",
     ],
@@ -148,8 +148,8 @@
     legacy_create_init = False,
     restricted_to = ["//tools:k8"],
     deps = [
-        ":python_init",
         ":flywheel",
+        ":python_init",
         "//external:python-gflags",
         "//external:python-glog",
     ],
diff --git a/y2020/vision/rootfs/modify_rootfs.sh b/y2020/vision/rootfs/modify_rootfs.sh
index 4fb9f46..239db0a 100755
--- a/y2020/vision/rootfs/modify_rootfs.sh
+++ b/y2020/vision/rootfs/modify_rootfs.sh
@@ -3,6 +3,7 @@
 set -xe
 
 IMAGE="2020-02-13-raspbian-buster-lite.img"
+BOOT_PARTITION="2020-02-13-raspbian-buster-lite.img.boot_partition"
 PARTITION="2020-02-13-raspbian-buster-lite.img.partition"
 HOSTNAME="pi-8971-1"
 
@@ -16,6 +17,26 @@
 
 
 mkdir -p "${PARTITION}"
+mkdir -p "${BOOT_PARTITION}"
+
+if mount | grep "${BOOT_PARTITION}" >/dev/null ;
+then
+  echo "Already mounted"
+else
+  OFFSET="$(fdisk -lu "${IMAGE}" | grep "${IMAGE}1" | awk '{print 512*$2}')"
+  sudo mount -o loop,offset=${OFFSET} "${IMAGE}" "${BOOT_PARTITION}"
+fi
+
+# Enable the camera on boot.
+if ! grep "start_x=1" "${BOOT_PARTITION}/config.txt"; then
+  echo "start_x=1" | sudo tee -a "${BOOT_PARTITION}/config.txt"
+fi
+if ! grep "gpu_mem=128" "${BOOT_PARTITION}/config.txt"; then
+  echo "gpu_mem=128" | sudo tee -a "${BOOT_PARTITION}/config.txt"
+fi
+
+sudo umount "${BOOT_PARTITION}"
+rmdir "${BOOT_PARTITION}"
 
 if mount | grep "${PARTITION}" >/dev/null ;
 then
diff --git a/y2020/vision/sift/fast_gaussian.bzl b/y2020/vision/sift/fast_gaussian.bzl
index a1c3173..0905423 100644
--- a/y2020/vision/sift/fast_gaussian.bzl
+++ b/y2020/vision/sift/fast_gaussian.bzl
@@ -1,55 +1,55 @@
 def fast_gaussian(sigmas, sizes):
-  files = []
-  for _, sigma_name, _ in sigmas:
+    files = []
+    for _, sigma_name, _ in sigmas:
+        for cols, rows in sizes:
+            files.append("fast_gaussian_%dx%d_%s" % (cols, rows, sigma_name))
+    for _, sigma_name, _ in sigmas:
+        for cols, rows in sizes:
+            files.append("fast_gaussian_subtract_%dx%d_%s" % (cols, rows, sigma_name))
     for cols, rows in sizes:
-      files.append("fast_gaussian_%dx%d_%s" % (cols, rows, sigma_name))
-  for _, sigma_name, _ in sigmas:
-    for cols, rows in sizes:
-      files.append("fast_gaussian_subtract_%dx%d_%s" % (cols, rows, sigma_name))
-  for cols, rows in sizes:
-    files.append('fast_subtract_%dx%d' % (cols, rows))
+        files.append("fast_subtract_%dx%d" % (cols, rows))
 
-  params = struct(
-    sigmas = sigmas,
-    sizes = sizes,
-  )
+    params = struct(
+        sigmas = sigmas,
+        sizes = sizes,
+    )
 
-  headers = [f + '.h' for f in files] + [
-    'fast_gaussian_all.h',
-  ]
-  objects = [f + '.o' for f in files] + [
-    'fast_gaussian_runtime.o',
-  ]
-  htmls = [f + '.html' for f in files]
+    headers = [f + ".h" for f in files] + [
+        "fast_gaussian_all.h",
+    ]
+    objects = [f + ".o" for f in files] + [
+        "fast_gaussian_runtime.o",
+    ]
+    htmls = [f + ".html" for f in files]
 
-  native.genrule(
-    name = "generate_fast_gaussian",
-    tools = [
-        ":fast_gaussian_runner",
-    ],
-    cmd = ' '.join([
-      '$(location fast_gaussian_runner)',
-      "'" + params.to_json() + "'",
-      # TODO(Brian): This should be RULEDIR once we have support for that.
-      '$(@D)',
-      '$(TARGET_CPU)',
-    ]),
-    outs = headers + objects + htmls,
-    restricted_to = [
-      "//tools:k8",
-      "//tools:armhf-debian",
-    ],
-  )
+    native.genrule(
+        name = "generate_fast_gaussian",
+        tools = [
+            ":fast_gaussian_runner",
+        ],
+        cmd = " ".join([
+            "$(location fast_gaussian_runner)",
+            "'" + params.to_json() + "'",
+            # TODO(Brian): This should be RULEDIR once we have support for that.
+            "$(@D)",
+            "$(TARGET_CPU)",
+        ]),
+        outs = headers + objects + htmls,
+        restricted_to = [
+            "//tools:k8",
+            "//tools:armhf-debian",
+        ],
+    )
 
-  native.cc_library(
-    name = 'fast_gaussian_all',
-    hdrs = ['fast_gaussian_all.h'],
-    srcs = headers + objects,
-    deps = [
-      '//third_party:halide_runtime',
-    ],
-    restricted_to = [
-      "//tools:k8",
-      "//tools:armhf-debian",
-    ],
-  )
+    native.cc_library(
+        name = "fast_gaussian_all",
+        hdrs = ["fast_gaussian_all.h"],
+        srcs = headers + objects,
+        deps = [
+            "//third_party:halide_runtime",
+        ],
+        restricted_to = [
+            "//tools:k8",
+            "//tools:armhf-debian",
+        ],
+    )
diff --git a/y2020/www/BUILD b/y2020/www/BUILD
index c0daa07..c280e91 100644
--- a/y2020/www/BUILD
+++ b/y2020/www/BUILD
@@ -4,24 +4,24 @@
 ts_library(
     name = "main",
     srcs = [
-        "main.ts",
         "image_handler.ts",
+        "main.ts",
     ],
+    visibility = ["//y2020:__subpackages__"],
     deps = [
         "//aos/network/www:proxy",
         "//y2020/vision:vision_ts_fbs",
         "//y2020/vision/sift:sift_ts_fbs",
     ],
-    visibility = ["//y2020:__subpackages__"],
 )
 
 rollup_bundle(
     name = "main_bundle",
     entry_point = "y2020/www/main",
+    visibility = ["//y2020:__subpackages__"],
     deps = [
         "main",
     ],
-    visibility = ["//y2020:__subpackages__"],
 )
 
 filegroup(
@@ -30,7 +30,7 @@
         "**/*.html",
         "**/*.css",
     ]),
-    visibility=["//visibility:public"],
+    visibility = ["//visibility:public"],
 )
 
 genrule(
@@ -42,5 +42,5 @@
         "flatbuffers.js",
     ],
     cmd = "cp $(location @com_github_google_flatbuffers//:flatjs) $@",
-    visibility=["//y2020:__subpackages__"],
+    visibility = ["//y2020:__subpackages__"],
 )