1 /*
2  * Copyright 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef MMC_DAEMON_SERVICE_H_
18 #define MMC_DAEMON_SERVICE_H_
19 
20 #include <base/functional/callback.h>
21 #include <base/memory/ref_counted.h>
22 #include <base/memory/weak_ptr.h>
23 #include <dbus/bus.h>
24 #include <dbus/exported_object.h>
25 #include <dbus/message.h>
26 #include <sys/un.h>
27 
28 #include <future>
29 #include <map>
30 #include <memory>
31 
32 #include "common/message_loop_thread.h"
33 #include "mmc/mmc_interface/mmc_interface.h"
34 
35 namespace mmc {
36 
37 class Service final {
38 public:
39   explicit Service(base::OnceClosure shutdown_callback);
40 
41   // Service is neither copyable nor movable.
42   Service(const Service&) = delete;
43   Service& operator=(const Service&) = delete;
44 
45   // Connects to DBus and exports methods for client to call.
46   bool Init();
47 
48 private:
49   /* DBus Methods */
50   // Main thread creates a codec server instance and a socket,
51   // and calls |StartWorkerThread| to let one thread start listening on the
52   // socket.
53   //
54   // Expected input message:
55   //   |CodecInitRequest| with |ConfigParam| set.
56   // Response:
57   //   |CodecInitResponse|, if |CodecInit| succeeded.
58   //   ErrorResponse, otherwise.
59   void CodecInit(dbus::MethodCall* method_call, dbus::ExportedObject::ResponseSender sender);
60 
61   // Main thread removes idle threads from the thread poll.
62   //
63   // No input message needed.
64   // Response:
65   //   dbus::Response, implying |CodecCleanUp| finished.
66   void CodecCleanUp(dbus::MethodCall* method_call, dbus::ExportedObject::ResponseSender sender);
67 
68   /* Thread Management*/
69   // Adds a thread to the thread pool and makes it listen on the socket fd.
70   bool StartWorkerThread(int fd, struct sockaddr_un addr,
71                          std::unique_ptr<MmcInterface> codec_server);
72 
73   // Removes idle threads from the thread pool.
74   void RemoveIdleThread();
75 
76   base::OnceClosure shutdown_callback_;
77 
78   scoped_refptr<dbus::Bus> bus_;
79   dbus::ExportedObject* exported_object_;  // Owned by the Bus object.
80 
81   std::vector<std::pair<std::unique_ptr<bluetooth::common::MessageLoopThread>,
82                         std::unique_ptr<std::future<void>>>>
83           thread_pool_;
84 
85   base::WeakPtrFactory<Service> weak_ptr_factory_;
86 };
87 
88 }  // namespace mmc
89 
90 #endif  // MMC_DAEMON_SERVICE_H_
91