/*
 * Copyright (C) 2021 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "src/android_internal/power_stats.h"

#include "perfetto/ext/base/utils.h"

#include <string.h>

#include <algorithm>
#include <memory>
#include <vector>

// Legacy HAL interfacte for devices shipped before Android S.
#include <android/hardware/power/stats/1.0/IPowerStats.h>

// AIDL interface for Android S+.
#include <android/hardware/power/stats/IPowerStats.h>

#include <binder/IServiceManager.h>

namespace perfetto {
namespace android_internal {

namespace hal = android::hardware::power::stats::V1_0;
namespace aidl = android::hardware::power::stats;

namespace {

// Common interface for data from power stats service.  Devices prior to
// Android S, uses the HAL interface while device from Android S or later
// uses the AIDL interfact.
class PowerStatsDataProvider {
 public:
  virtual bool GetAvailableRails(RailDescriptor*, size_t* size_of_arr) = 0;
  virtual bool GetRailEnergyData(RailEnergyData*, size_t* size_of_arr) = 0;

  // Available from Android S+.
  virtual bool GetEnergyConsumerInfo(EnergyConsumerInfo* consumers,
                                     size_t* size_of_arr) = 0;
  virtual bool GetEnergyConsumed(EnergyEstimationBreakdown* breakdown,
                                 size_t* size_of_arr) = 0;
  virtual bool GetPowerEntityStates(PowerEntityState* state,
                                    size_t* size_of_arr) = 0;
  virtual bool GetPowerEntityStateResidency(PowerEntityStateResidency* state,
                                            size_t* size_of_arr) = 0;
  virtual ~PowerStatsDataProvider() = default;
};

class PowerStatsHalDataProvider : public PowerStatsDataProvider {
 public:
  bool GetAvailableRails(RailDescriptor*, size_t* size_of_arr) override;
  bool GetRailEnergyData(RailEnergyData*, size_t* size_of_arr) override;
  bool GetEnergyConsumerInfo(EnergyConsumerInfo* consumers,
                             size_t* size_of_arr) override;
  bool GetEnergyConsumed(EnergyEstimationBreakdown* breakdown,
                         size_t* size_of_arr) override;
  bool GetPowerEntityStates(PowerEntityState* state,
                            size_t* size_of_arr) override;
  bool GetPowerEntityStateResidency(PowerEntityStateResidency* state,
                                    size_t* size_of_arr) override;

  PowerStatsHalDataProvider() = default;
  ~PowerStatsHalDataProvider() override = default;

 private:
  android::sp<hal::IPowerStats> svc_;
  hal::IPowerStats* MaybeGetService();
};

class PowerStatsAidlDataProvider : public PowerStatsDataProvider {
 public:
  static constexpr char INSTANCE[] =
      "android.hardware.power.stats.IPowerStats/default";

  bool GetAvailableRails(RailDescriptor*, size_t* size_of_arr) override;
  bool GetRailEnergyData(RailEnergyData*, size_t* size_of_arr) override;
  bool GetEnergyConsumerInfo(EnergyConsumerInfo* consumers,
                             size_t* size_of_arr) override;
  bool GetEnergyConsumed(EnergyEstimationBreakdown* breakdown,
                         size_t* size_of_arr) override;
  bool GetPowerEntityStates(PowerEntityState* state,
                            size_t* size_of_arr) override;
  bool GetPowerEntityStateResidency(PowerEntityStateResidency* state,
                                    size_t* size_of_arr) override;

  PowerStatsAidlDataProvider() = default;
  ~PowerStatsAidlDataProvider() override = default;

 private:
  android::sp<aidl::IPowerStats> svc_;

  aidl::IPowerStats* MaybeGetService();
  void ResetService();
};

PowerStatsDataProvider* GetDataProvider() {
  static std::unique_ptr<PowerStatsDataProvider> data_provider;
  if (data_provider == nullptr) {
    const android::sp<android::IServiceManager> sm =
        android::defaultServiceManager();
    if (sm->isDeclared(
            android::String16(PowerStatsAidlDataProvider::INSTANCE))) {
      data_provider = std::make_unique<PowerStatsAidlDataProvider>();
    } else {
      data_provider = std::make_unique<PowerStatsHalDataProvider>();
    }
  }
  return data_provider.get();
}

}  // anonymous namespace

bool GetAvailableRails(RailDescriptor* descriptor, size_t* size_of_arr) {
  return GetDataProvider()->GetAvailableRails(descriptor, size_of_arr);
}

bool GetRailEnergyData(RailEnergyData* data, size_t* size_of_arr) {
  return GetDataProvider()->GetRailEnergyData(data, size_of_arr);
}

bool GetEnergyConsumerInfo(EnergyConsumerInfo* consumers, size_t* size_of_arr) {
  return GetDataProvider()->GetEnergyConsumerInfo(consumers, size_of_arr);
}

bool GetEnergyConsumed(EnergyEstimationBreakdown* breakdown,
                       size_t* size_of_arr) {
  return GetDataProvider()->GetEnergyConsumed(breakdown, size_of_arr);
}

bool GetPowerEntityStates(PowerEntityState* state, size_t* size_of_arr) {
  return GetDataProvider()->GetPowerEntityStates(state, size_of_arr);
}

bool GetPowerEntityStateResidency(PowerEntityStateResidency* residency,
                                  size_t* size_of_arr) {
  return GetDataProvider()->GetPowerEntityStateResidency(residency,
                                                         size_of_arr);
}

/*** Power Stats HAL Implemenation *******************************************/

using android::hardware::hidl_vec;
using android::hardware::Return;

hal::IPowerStats* PowerStatsHalDataProvider::MaybeGetService() {
  if (svc_ == nullptr) {
    svc_ = hal::IPowerStats::tryGetService();
  }
  return svc_.get();
}

bool PowerStatsHalDataProvider::GetAvailableRails(
    RailDescriptor* rail_descriptors,
    size_t* size_of_arr) {
  const size_t in_array_size = *size_of_arr;
  *size_of_arr = 0;
  hal::IPowerStats* svc = MaybeGetService();
  if (svc == nullptr) {
    return false;
  }

  hal::Status status;
  auto rails_cb = [rail_descriptors, size_of_arr, &in_array_size, &status](
                      hidl_vec<hal::RailInfo> r, hal::Status s) {
    status = s;
    if (status == hal::Status::SUCCESS) {
      *size_of_arr = std::min(in_array_size, r.size());
      for (int i = 0; i < *size_of_arr; ++i) {
        const hal::RailInfo& rail_info = r[i];
        RailDescriptor& descriptor = rail_descriptors[i];

        descriptor.index = rail_info.index;
        descriptor.sampling_rate = rail_info.samplingRate;

        strlcpy(descriptor.rail_name, rail_info.railName.c_str(),
                sizeof(descriptor.rail_name));
        strlcpy(descriptor.subsys_name, rail_info.subsysName.c_str(),
                sizeof(descriptor.subsys_name));
      }
    }
  };

  Return<void> ret = svc->getRailInfo(rails_cb);
  return status == hal::Status::SUCCESS;
}

bool PowerStatsHalDataProvider::GetRailEnergyData(
    RailEnergyData* rail_energy_array,
    size_t* size_of_arr) {
  const size_t in_array_size = *size_of_arr;
  *size_of_arr = 0;

  hal::IPowerStats* svc = MaybeGetService();
  if (svc == nullptr) {
    return false;
  }

  hal::Status status;
  auto energy_cb = [rail_energy_array, size_of_arr, &in_array_size, &status](
                       hidl_vec<hal::EnergyData> m, hal::Status s) {
    status = s;
    if (status == hal::Status::SUCCESS) {
      *size_of_arr = std::min(in_array_size, m.size());
      for (int i = 0; i < *size_of_arr; ++i) {
        const hal::EnergyData& measurement = m[i];
        RailEnergyData& element = rail_energy_array[i];

        element.index = measurement.index;
        element.timestamp = measurement.timestamp;
        element.energy = measurement.energy;
      }
    }
  };

  Return<void> ret = svc_->getEnergyData(hidl_vec<uint32_t>(), energy_cb);
  return status == hal::Status::SUCCESS;
}

bool PowerStatsHalDataProvider::GetEnergyConsumerInfo(EnergyConsumerInfo*,
                                                      size_t*) {
  return false;
}

bool PowerStatsHalDataProvider::GetEnergyConsumed(EnergyEstimationBreakdown*,
                                                  size_t*) {
  return false;
}

bool PowerStatsHalDataProvider::GetPowerEntityStates(PowerEntityState*,
                                                     size_t*) {
  return false;
}

bool PowerStatsHalDataProvider::GetPowerEntityStateResidency(
    PowerEntityStateResidency*,
    size_t*) {
  return false;
}

/*** End of Power Stats HAL Implemenation *************************************/

/*** Power Stats AIDL Implemenation *******************************************/
aidl::IPowerStats* PowerStatsAidlDataProvider::MaybeGetService() {
  if (svc_ == nullptr) {
    svc_ = android::checkDeclaredService<aidl::IPowerStats>(
        android::String16(INSTANCE));
  }
  return svc_.get();
}

void PowerStatsAidlDataProvider::ResetService() {
  svc_.clear();
}

bool PowerStatsAidlDataProvider::GetAvailableRails(RailDescriptor* descriptor,
                                                   size_t* size_of_arr) {
  const size_t in_array_size = *size_of_arr;
  *size_of_arr = 0;

  aidl::IPowerStats* svc = MaybeGetService();
  if (svc_ == nullptr) {
    return false;
  }

  std::vector<aidl::Channel> results;
  android::binder::Status status = svc->getEnergyMeterInfo(&results);
  if (!status.isOk()) {
    if (status.transactionError() == android::DEAD_OBJECT) {
      // Service has died.  Reset it to attempt to acquire a new one next time.
      ResetService();
    }
    return false;
  }

  size_t max_size = std::min(in_array_size, results.size());
  for (const auto& result : results) {
    if (*size_of_arr >= max_size) {
      break;
    }
    auto& cur = descriptor[(*size_of_arr)++];
    cur.index = result.id;
    cur.sampling_rate = 0;
    strlcpy(cur.rail_name, result.name.c_str(), sizeof(cur.rail_name));
    strlcpy(cur.subsys_name, result.subsystem.c_str(), sizeof(cur.subsys_name));
  }
  return true;
}

bool PowerStatsAidlDataProvider::GetRailEnergyData(RailEnergyData* data,
                                                   size_t* size_of_arr) {
  const size_t in_array_size = *size_of_arr;
  *size_of_arr = 0;

  aidl::IPowerStats* svc = MaybeGetService();
  if (svc == nullptr) {
    return false;
  }

  std::vector<int> ids;
  std::vector<aidl::EnergyMeasurement> results;
  android::binder::Status status = svc->readEnergyMeter(ids, &results);
  if (!status.isOk()) {
    if (status.transactionError() == android::DEAD_OBJECT) {
      // Service has died.  Reset it to attempt to acquire a new one next time.
      ResetService();
    }
    return false;
  }

  size_t max_size = std::min(in_array_size, results.size());
  for (const auto& result : results) {
    if (*size_of_arr >= max_size) {
      break;
    }
    auto& cur = data[(*size_of_arr)++];
    cur.index = result.id;
    cur.timestamp = result.timestampMs;
    cur.energy = result.energyUWs;
  }
  return true;
}

bool PowerStatsAidlDataProvider::GetEnergyConsumerInfo(
    EnergyConsumerInfo* consumers,
    size_t* size_of_arr) {
  const size_t in_array_size = *size_of_arr;
  *size_of_arr = 0;

  aidl::IPowerStats* svc = MaybeGetService();
  if (svc == nullptr) {
    return false;
  }
  std::vector<aidl::EnergyConsumer> results;
  android::binder::Status status = svc->getEnergyConsumerInfo(&results);

  if (!status.isOk()) {
    if (status.transactionError() == android::DEAD_OBJECT) {
      // Service has died.  Reset it to attempt to acquire a new one next time.
      ResetService();
    }
    return false;
  }
  size_t max_size = std::min(in_array_size, results.size());
  for (const auto& result : results) {
    if (*size_of_arr >= max_size) {
      break;
    }
    auto& cur = consumers[(*size_of_arr)++];
    cur.energy_consumer_id = result.id;
    cur.ordinal = result.ordinal;
    strlcpy(cur.type, aidl::toString(result.type).c_str(), sizeof(cur.type));
    strlcpy(cur.name, result.name.c_str(), sizeof(cur.name));
  }
  return true;
}
bool PowerStatsAidlDataProvider::GetEnergyConsumed(
    EnergyEstimationBreakdown* breakdown,
    size_t* size_of_arr) {
  const size_t in_array_size = *size_of_arr;
  *size_of_arr = 0;

  aidl::IPowerStats* svc = MaybeGetService();
  if (svc == nullptr) {
    return false;
  }

  std::vector<int> ids;
  std::vector<aidl::EnergyConsumerResult> results;
  android::binder::Status status = svc->getEnergyConsumed(ids, &results);

  if (!status.isOk()) {
    if (status.transactionError() == android::DEAD_OBJECT) {
      // Service has died.  Reset it to attempt to acquire a new one next time.
      ResetService();
    }
    return false;
  }

  size_t max_size = std::min(in_array_size, results.size());
  // Iterate through all consumer ID.
  for (const auto& result : results) {
    if (*size_of_arr >= max_size) {
      break;
    }
    auto& cur = breakdown[(*size_of_arr)++];
    cur.energy_consumer_id = result.id;
    cur.uid = ALL_UIDS_FOR_CONSUMER;
    cur.energy_uws = result.energyUWs;

    // Iterate through all UIDs for this consumer.
    for (const auto& attribution : result.attribution) {
      if (*size_of_arr >= max_size) {
        break;
      }
      auto& cur = breakdown[(*size_of_arr)++];
      cur.energy_consumer_id = result.id;
      cur.uid = attribution.uid;
      cur.energy_uws = attribution.energyUWs;
    }
  }
  return true;
}

bool PowerStatsAidlDataProvider::GetPowerEntityStates(
    PowerEntityState* entity_state,
    size_t* size_of_arr) {
  const size_t in_array_size = *size_of_arr;
  *size_of_arr = 0;

  aidl::IPowerStats* svc = MaybeGetService();
  if (svc == nullptr) {
    return false;
  }

  std::vector<aidl::PowerEntity> entities;
  android::binder::Status status = svc->getPowerEntityInfo(&entities);

  if (!status.isOk()) {
    if (status.transactionError() == android::DEAD_OBJECT) {
      // Service has died.  Reset it to attempt to acquire a new one next time.
      ResetService();
    }
    return false;
  }

  // Iterate through all entities.
  for (const auto& entity : entities) {
    if (*size_of_arr >= in_array_size) {
      break;
    }

    // Iterate through all states for this entity.
    for (const auto& state : entity.states) {
      if (*size_of_arr >= in_array_size) {
        break;
      }
      auto& cur = entity_state[(*size_of_arr)++];
      cur.entity_id = entity.id;
      strlcpy(cur.entity_name, entity.name.c_str(), sizeof(cur.entity_name));
      cur.state_id = state.id;
      strlcpy(cur.state_name, state.name.c_str(), sizeof(cur.state_name));
    }
  }
  return true;
}

bool PowerStatsAidlDataProvider::GetPowerEntityStateResidency(
    PowerEntityStateResidency* residency,
    size_t* size_of_arr) {
  const size_t in_array_size = *size_of_arr;
  *size_of_arr = 0;

  aidl::IPowerStats* svc = MaybeGetService();
  if (svc == nullptr) {
    return false;
  }

  std::vector<int> ids;
  std::vector<aidl::StateResidencyResult> entities;
  android::binder::Status status = svc->getStateResidency(ids, &entities);

  if (!status.isOk()) {
    if (status.transactionError() == android::DEAD_OBJECT) {
      // Service has died.  Reset it to attempt to acquire a new one next time.
      ResetService();
    }
    return false;
  }

  // Iterate through all entities.
  for (const auto& entity : entities) {
    if (*size_of_arr >= in_array_size) {
      break;
    }

    // Iterate through all states for this entity.
    for (const auto& stateResidencyData : entity.stateResidencyData) {
      if (*size_of_arr >= in_array_size) {
        break;
      }
      auto& cur = residency[(*size_of_arr)++];
      cur.entity_id = entity.id;
      cur.state_id = stateResidencyData.id;
      cur.total_time_in_state_ms = stateResidencyData.totalTimeInStateMs;
      cur.total_state_entry_count = stateResidencyData.totalStateEntryCount;
      cur.last_entry_timestamp_ms = stateResidencyData.lastEntryTimestampMs;
    }
  }
  return true;
}

/*** End of Power Stats AIDL Implemenation ************************************/

}  // namespace android_internal
}  // namespace perfetto
