1e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#ifndef ANDROID_PDX_DEFAULT_TRANSPORT_SERVICE_UTILITY_H_
2e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#define ANDROID_PDX_DEFAULT_TRANSPORT_SERVICE_UTILITY_H_
3e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
416f1c1a30abafb346f4b03643d0fcbf799fdc308Corey Tabaka#include <ftw.h>
516f1c1a30abafb346f4b03643d0fcbf799fdc308Corey Tabaka
6e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <pdx/client.h>
7e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <pdx/default_transport/client_channel_factory.h>
8e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <pdx/service.h>
9e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <pdx/status.h>
10e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
11e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkonamespace android {
12e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkonamespace pdx {
13e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkonamespace default_transport {
14e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
15e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoclass ServiceUtility : public ClientBase<ServiceUtility> {
16e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko public:
17e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  Status<int> ReloadSystemProperties() {
18e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    Transaction transaction{*this};
19e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return ReturnStatusOrError(
20e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        transaction.Send<int>(opcodes::REPORT_SYSPROP_CHANGE));
21e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
22e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
23e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  static std::string GetRootEndpointPath() {
24e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return ClientChannelFactory::GetRootEndpointPath();
25e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
26e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  static std::string GetEndpointPath(const std::string& endpoint_path) {
27e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return ClientChannelFactory::GetEndpointPath(endpoint_path);
28e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
29e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
3016f1c1a30abafb346f4b03643d0fcbf799fdc308Corey Tabaka  // Traverses the PDX service path space and sends a message to reload system
3116f1c1a30abafb346f4b03643d0fcbf799fdc308Corey Tabaka  // properties to each service endpoint it finds along the way.
3216f1c1a30abafb346f4b03643d0fcbf799fdc308Corey Tabaka  // NOTE: This method is used by atrace to poke PDX services. Please avoid
3316f1c1a30abafb346f4b03643d0fcbf799fdc308Corey Tabaka  // unnecessary changes to this mechanism to minimize impact on atrace.
3416f1c1a30abafb346f4b03643d0fcbf799fdc308Corey Tabaka  static bool PokeServices() {
3516f1c1a30abafb346f4b03643d0fcbf799fdc308Corey Tabaka    const int kMaxDepth = 16;
3616f1c1a30abafb346f4b03643d0fcbf799fdc308Corey Tabaka    const int result =
3716f1c1a30abafb346f4b03643d0fcbf799fdc308Corey Tabaka        nftw(GetRootEndpointPath().c_str(), PokeService, kMaxDepth, FTW_PHYS);
3816f1c1a30abafb346f4b03643d0fcbf799fdc308Corey Tabaka    return result == 0 ? true : false;
3916f1c1a30abafb346f4b03643d0fcbf799fdc308Corey Tabaka  }
4016f1c1a30abafb346f4b03643d0fcbf799fdc308Corey Tabaka
41e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko private:
42e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  friend BASE;
43e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
44e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ServiceUtility(const std::string& endpoint_path, int* error = nullptr)
4516f1c1a30abafb346f4b03643d0fcbf799fdc308Corey Tabaka      : BASE(ClientChannelFactory::Create(endpoint_path), 0) {
46e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (error)
47e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      *error = Client::error();
48e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
49e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
5016f1c1a30abafb346f4b03643d0fcbf799fdc308Corey Tabaka  // Sends the sysprop_change message to the service at fpath, so it re-reads
5116f1c1a30abafb346f4b03643d0fcbf799fdc308Corey Tabaka  // its system properties. Returns 0 on success or a negated errno code on
5216f1c1a30abafb346f4b03643d0fcbf799fdc308Corey Tabaka  // failure.
5316f1c1a30abafb346f4b03643d0fcbf799fdc308Corey Tabaka  // NOTE: This method is used by atrace to poke PDX services. Please avoid
5416f1c1a30abafb346f4b03643d0fcbf799fdc308Corey Tabaka  // unnecessary changes to this mechanism to minimize impact on atrace.
5516f1c1a30abafb346f4b03643d0fcbf799fdc308Corey Tabaka  static int PokeService(const char* fpath, const struct stat* /*sb*/,
5616f1c1a30abafb346f4b03643d0fcbf799fdc308Corey Tabaka                         int typeflag, struct FTW* /*ftwbuf*/) {
5716f1c1a30abafb346f4b03643d0fcbf799fdc308Corey Tabaka    const bool kIgnoreErrors = true;
5816f1c1a30abafb346f4b03643d0fcbf799fdc308Corey Tabaka
5916f1c1a30abafb346f4b03643d0fcbf799fdc308Corey Tabaka    if (typeflag == FTW_F) {
6016f1c1a30abafb346f4b03643d0fcbf799fdc308Corey Tabaka      int error;
6116f1c1a30abafb346f4b03643d0fcbf799fdc308Corey Tabaka      auto utility = ServiceUtility::Create(fpath, &error);
6216f1c1a30abafb346f4b03643d0fcbf799fdc308Corey Tabaka      if (!utility) {
6316f1c1a30abafb346f4b03643d0fcbf799fdc308Corey Tabaka        if (error != -ECONNREFUSED) {
6416f1c1a30abafb346f4b03643d0fcbf799fdc308Corey Tabaka          ALOGE("ServiceUtility::PokeService: Failed to open %s: %s.", fpath,
6516f1c1a30abafb346f4b03643d0fcbf799fdc308Corey Tabaka                strerror(-error));
6616f1c1a30abafb346f4b03643d0fcbf799fdc308Corey Tabaka        }
6716f1c1a30abafb346f4b03643d0fcbf799fdc308Corey Tabaka        return kIgnoreErrors ? 0 : error;
6816f1c1a30abafb346f4b03643d0fcbf799fdc308Corey Tabaka      }
6916f1c1a30abafb346f4b03643d0fcbf799fdc308Corey Tabaka
7016f1c1a30abafb346f4b03643d0fcbf799fdc308Corey Tabaka      auto status = utility->ReloadSystemProperties();
7116f1c1a30abafb346f4b03643d0fcbf799fdc308Corey Tabaka      if (!status) {
7216f1c1a30abafb346f4b03643d0fcbf799fdc308Corey Tabaka        ALOGE(
7316f1c1a30abafb346f4b03643d0fcbf799fdc308Corey Tabaka            "ServiceUtility::PokeService: Failed to send sysprop change to %s: "
7416f1c1a30abafb346f4b03643d0fcbf799fdc308Corey Tabaka            "%s",
7516f1c1a30abafb346f4b03643d0fcbf799fdc308Corey Tabaka            fpath, status.GetErrorMessage().c_str());
7616f1c1a30abafb346f4b03643d0fcbf799fdc308Corey Tabaka        return kIgnoreErrors ? 0 : -status.error();
7716f1c1a30abafb346f4b03643d0fcbf799fdc308Corey Tabaka      }
7816f1c1a30abafb346f4b03643d0fcbf799fdc308Corey Tabaka    }
7916f1c1a30abafb346f4b03643d0fcbf799fdc308Corey Tabaka
8016f1c1a30abafb346f4b03643d0fcbf799fdc308Corey Tabaka    return 0;
8116f1c1a30abafb346f4b03643d0fcbf799fdc308Corey Tabaka  }
8216f1c1a30abafb346f4b03643d0fcbf799fdc308Corey Tabaka
83e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ServiceUtility(const ServiceUtility&) = delete;
84e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  void operator=(const ServiceUtility&) = delete;
85e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko};
86e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
87e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}  // namespace default_transport
88e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}  // namespace pdx
89e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}  // namespace android
90e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
91e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#endif  // ANDROID_PDX_DEFAULT_TRANSPORT_SERVICE_UTILITY_H_
92