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 
11 namespace android {
12 namespace pdx {
13 namespace default_transport {
14 
15 class ServiceUtility : public ClientBase<ServiceUtility> {
16  public:
ReloadSystemProperties()17   Status<int> ReloadSystemProperties() {
18     Transaction transaction{*this};
19     return ReturnStatusOrError(
20         transaction.Send<int>(opcodes::REPORT_SYSPROP_CHANGE));
21   }
22 
GetRootEndpointPath()23   static std::string GetRootEndpointPath() {
24     return ClientChannelFactory::GetRootEndpointPath();
25   }
GetEndpointPath(const std::string & endpoint_path)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.
PokeServices()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   explicit ServiceUtility(const std::string& endpoint_path,
45                           int* error = nullptr)
46       : BASE(ClientChannelFactory::Create(endpoint_path), 0) {
47     if (error)
48       *error = Client::error();
49   }
50 
51   // Sends the sysprop_change message to the service at fpath, so it re-reads
52   // its system properties. Returns 0 on success or a negated errno code on
53   // failure.
54   // NOTE: This method is used by atrace to poke PDX services. Please avoid
55   // unnecessary changes to this mechanism to minimize impact on atrace.
PokeService(const char * fpath,const struct stat *,int typeflag,struct FTW *)56   static int PokeService(const char* fpath, const struct stat* /*sb*/,
57                          int typeflag, struct FTW* /*ftwbuf*/) {
58     const bool kIgnoreErrors = true;
59 
60     if (typeflag == FTW_F) {
61       int error;
62       auto utility = ServiceUtility::Create(fpath, &error);
63       if (!utility) {
64         if (error != -ECONNREFUSED) {
65           ALOGE("ServiceUtility::PokeService: Failed to open %s: %s.", fpath,
66                 strerror(-error));
67         }
68         return kIgnoreErrors ? 0 : error;
69       }
70 
71       auto status = utility->ReloadSystemProperties();
72       if (!status) {
73         ALOGE(
74             "ServiceUtility::PokeService: Failed to send sysprop change to %s: "
75             "%s",
76             fpath, status.GetErrorMessage().c_str());
77         return kIgnoreErrors ? 0 : -status.error();
78       }
79     }
80 
81     return 0;
82   }
83 
84   ServiceUtility(const ServiceUtility&) = delete;
85   void operator=(const ServiceUtility&) = delete;
86 };
87 
88 }  // namespace default_transport
89 }  // namespace pdx
90 }  // namespace android
91 
92 #endif  // ANDROID_PDX_DEFAULT_TRANSPORT_SERVICE_UTILITY_H_
93