1#ifndef ANDROID_PDX_DEFAULT_TRANSPORT_SERVICE_UTILITY_H_
2#define ANDROID_PDX_DEFAULT_TRANSPORT_SERVICE_UTILITY_H_
3
4#include <ftw.h>
5
6#include <pdx/client.h>
7#include <pdx/default_transport/client_channel_factory.h>
8#include <pdx/service.h>
9#include <pdx/status.h>
10
11namespace android {
12namespace pdx {
13namespace default_transport {
14
15class ServiceUtility : public ClientBase<ServiceUtility> {
16 public:
17  Status<int> ReloadSystemProperties() {
18    Transaction transaction{*this};
19    return ReturnStatusOrError(
20        transaction.Send<int>(opcodes::REPORT_SYSPROP_CHANGE));
21  }
22
23  static std::string GetRootEndpointPath() {
24    return ClientChannelFactory::GetRootEndpointPath();
25  }
26  static std::string GetEndpointPath(const std::string& endpoint_path) {
27    return ClientChannelFactory::GetEndpointPath(endpoint_path);
28  }
29
30  // Traverses the PDX service path space and sends a message to reload system
31  // properties to each service endpoint it finds along the way.
32  // NOTE: This method is used by atrace to poke PDX services. Please avoid
33  // unnecessary changes to this mechanism to minimize impact on atrace.
34  static bool PokeServices() {
35    const int kMaxDepth = 16;
36    const int result =
37        nftw(GetRootEndpointPath().c_str(), PokeService, kMaxDepth, FTW_PHYS);
38    return result == 0 ? true : false;
39  }
40
41 private:
42  friend BASE;
43
44  ServiceUtility(const std::string& endpoint_path, int* error = nullptr)
45      : BASE(ClientChannelFactory::Create(endpoint_path), 0) {
46    if (error)
47      *error = Client::error();
48  }
49
50  // Sends the sysprop_change message to the service at fpath, so it re-reads
51  // its system properties. Returns 0 on success or a negated errno code on
52  // failure.
53  // NOTE: This method is used by atrace to poke PDX services. Please avoid
54  // unnecessary changes to this mechanism to minimize impact on atrace.
55  static int PokeService(const char* fpath, const struct stat* /*sb*/,
56                         int typeflag, struct FTW* /*ftwbuf*/) {
57    const bool kIgnoreErrors = true;
58
59    if (typeflag == FTW_F) {
60      int error;
61      auto utility = ServiceUtility::Create(fpath, &error);
62      if (!utility) {
63        if (error != -ECONNREFUSED) {
64          ALOGE("ServiceUtility::PokeService: Failed to open %s: %s.", fpath,
65                strerror(-error));
66        }
67        return kIgnoreErrors ? 0 : error;
68      }
69
70      auto status = utility->ReloadSystemProperties();
71      if (!status) {
72        ALOGE(
73            "ServiceUtility::PokeService: Failed to send sysprop change to %s: "
74            "%s",
75            fpath, status.GetErrorMessage().c_str());
76        return kIgnoreErrors ? 0 : -status.error();
77      }
78    }
79
80    return 0;
81  }
82
83  ServiceUtility(const ServiceUtility&) = delete;
84  void operator=(const ServiceUtility&) = delete;
85};
86
87}  // namespace default_transport
88}  // namespace pdx
89}  // namespace android
90
91#endif  // ANDROID_PDX_DEFAULT_TRANSPORT_SERVICE_UTILITY_H_
92