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,
60                  dbus::ExportedObject::ResponseSender sender);
61 
62   // Main thread removes idle threads from the thread poll.
63   //
64   // No input message needed.
65   // Response:
66   //   dbus::Response, implying |CodecCleanUp| finished.
67   void CodecCleanUp(dbus::MethodCall* method_call,
68                     dbus::ExportedObject::ResponseSender sender);
69 
70   /* Thread Management*/
71   // Adds a thread to the thread pool and makes it listen on the socket fd.
72   bool StartWorkerThread(int fd, struct sockaddr_un addr,
73                          std::unique_ptr<MmcInterface> codec_server);
74 
75   // Removes idle threads from the thread pool.
76   void RemoveIdleThread();
77 
78   base::OnceClosure shutdown_callback_;
79 
80   scoped_refptr<dbus::Bus> bus_;
81   dbus::ExportedObject* exported_object_;  // Owned by the Bus object.
82 
83   std::vector<std::pair<std::unique_ptr<bluetooth::common::MessageLoopThread>,
84                         std::unique_ptr<std::future<void>>>>
85       thread_pool_;
86 
87   base::WeakPtrFactory<Service> weak_ptr_factory_;
88 };
89 
90 }  // namespace mmc
91 
92 #endif  // MMC_DAEMON_SERVICE_H_
93