Replace useCanSockets hack with flexible per-process domain selection

Bug: 158011272
Test: manual
Change-Id: I29d88a42e2309483a740cde9f9a463d83c7a560c
diff --git a/automotive/can/1.0/default/libnetdevice/common.cpp b/automotive/can/1.0/default/libnetdevice/common.cpp
index 387c91f..f2968fc 100644
--- a/automotive/can/1.0/default/libnetdevice/common.cpp
+++ b/automotive/can/1.0/default/libnetdevice/common.cpp
@@ -22,8 +22,6 @@
 
 namespace android::netdevice {
 
-socketparams::Params socketparams::current = general;
-
 unsigned int nametoindex(const std::string& ifname) {
     const auto ifidx = if_nametoindex(ifname.c_str());
     if (ifidx != 0) return ifidx;
diff --git a/automotive/can/1.0/default/libnetdevice/common.h b/automotive/can/1.0/default/libnetdevice/common.h
index b4f91bd..1e0d5b7 100644
--- a/automotive/can/1.0/default/libnetdevice/common.h
+++ b/automotive/can/1.0/default/libnetdevice/common.h
@@ -25,21 +25,6 @@
 
 namespace android::netdevice {
 
-namespace socketparams {
-
-struct Params {
-    int domain;
-    int type;
-    int protocol;
-};
-
-constexpr Params general = {AF_INET, SOCK_DGRAM, 0};
-constexpr Params can = {PF_CAN, SOCK_RAW, CAN_RAW};
-
-extern Params current;
-
-}  // namespace socketparams
-
 /**
  * Returns the index of a given network interface.
  *
diff --git a/automotive/can/1.0/default/libnetdevice/ifreqs.cpp b/automotive/can/1.0/default/libnetdevice/ifreqs.cpp
index 9335021..8df6434 100644
--- a/automotive/can/1.0/default/libnetdevice/ifreqs.cpp
+++ b/automotive/can/1.0/default/libnetdevice/ifreqs.cpp
@@ -21,11 +21,35 @@
 #include <android-base/logging.h>
 #include <android-base/unique_fd.h>
 
+#include <map>
+
 namespace android::netdevice::ifreqs {
 
+static constexpr int defaultSocketDomain = AF_INET;
+std::atomic_int socketDomain = defaultSocketDomain;
+
+struct SocketParams {
+    int domain;
+    int type;
+    int protocol;
+};
+
+static const std::map<int, SocketParams> socketParams = {
+        {AF_INET, {AF_INET, SOCK_DGRAM, 0}},
+        {AF_CAN, {AF_CAN, SOCK_RAW, CAN_RAW}},
+};
+
+static SocketParams getSocketParams(int domain) {
+    if (socketParams.count(domain)) return socketParams.find(domain)->second;
+
+    auto params = socketParams.find(defaultSocketDomain)->second;
+    params.domain = domain;
+    return params;
+}
+
 bool send(unsigned long request, struct ifreq& ifr) {
-    base::unique_fd sock(socket(socketparams::current.domain, socketparams::current.type,
-                                socketparams::current.protocol));
+    const auto sp = getSocketParams(socketDomain);
+    base::unique_fd sock(socket(sp.domain, sp.type, sp.protocol));
     if (!sock.ok()) {
         LOG(ERROR) << "Can't create socket";
         return false;
diff --git a/automotive/can/1.0/default/libnetdevice/ifreqs.h b/automotive/can/1.0/default/libnetdevice/ifreqs.h
index 25a40a6..74e5877 100644
--- a/automotive/can/1.0/default/libnetdevice/ifreqs.h
+++ b/automotive/can/1.0/default/libnetdevice/ifreqs.h
@@ -23,6 +23,11 @@
 namespace android::netdevice::ifreqs {
 
 /**
+ * \see useSocketDomain()
+ */
+extern std::atomic_int socketDomain;
+
+/**
  * Sends ioctl interface request.
  *
  * \param request Request type (such as SIOCGIFFLAGS)
diff --git a/automotive/can/1.0/default/libnetdevice/include/libnetdevice/libnetdevice.h b/automotive/can/1.0/default/libnetdevice/include/libnetdevice/libnetdevice.h
index 037618a..9a26ff1 100644
--- a/automotive/can/1.0/default/libnetdevice/include/libnetdevice/libnetdevice.h
+++ b/automotive/can/1.0/default/libnetdevice/include/libnetdevice/libnetdevice.h
@@ -27,15 +27,14 @@
 typedef std::array<uint8_t, ETH_ALEN> hwaddr_t;
 
 /**
- * Configures libnetdevice to use PF_CAN sockets instead of AF_INET,
+ * Configures libnetdevice to use other socket domain than AF_INET,
  * what requires less permissive SEPolicy rules for a given process.
  *
- * In such case, the process would only be able to control CAN interfaces.
- *
- * TODO(b/158011272): consider less hacky solution
- * \param yes true to use CAN sockets, false for general sockets
+ * In such case, the process would only be able to control interfaces of a given kind.
+
+ * \param domain Socket domain to use (e.g. AF_CAN), see socket(2) for details
  */
-void useCanSockets(bool yes);
+void useSocketDomain(int domain);
 
 /**
  * Checks, if the network interface exists.
diff --git a/automotive/can/1.0/default/libnetdevice/libnetdevice.cpp b/automotive/can/1.0/default/libnetdevice/libnetdevice.cpp
index 4bba5f6..4293cad 100644
--- a/automotive/can/1.0/default/libnetdevice/libnetdevice.cpp
+++ b/automotive/can/1.0/default/libnetdevice/libnetdevice.cpp
@@ -28,8 +28,8 @@
 
 namespace android::netdevice {
 
-void useCanSockets(bool yes) {
-    socketparams::current = yes ? socketparams::can : socketparams::general;
+void useSocketDomain(int domain) {
+    ifreqs::socketDomain = domain;
 }
 
 bool exists(std::string ifname) {
diff --git a/automotive/can/1.0/default/service.cpp b/automotive/can/1.0/default/service.cpp
index b5801c0..9a9d322 100644
--- a/automotive/can/1.0/default/service.cpp
+++ b/automotive/can/1.0/default/service.cpp
@@ -28,7 +28,7 @@
     configureRpcThreadpool(16, true);
     LOG(DEBUG) << "CAN controller service starting...";
 
-    netdevice::useCanSockets(true);
+    netdevice::useSocketDomain(AF_CAN);
 
     sp<CanController> canController(new CanController);
     if (canController->registerAsService("socketcan") != OK) {