/*
 * Copyright (C) 2015 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 "power_manager.h"

#include <base/files/file_util.h>
#include <base/logging.h>
#include <base/sys_info.h>
#include <binderwrapper/binder_wrapper.h>
#include <cutils/android_reboot.h>
#include <nativepower/constants.h>
#include <powermanager/IPowerManager.h>
#include <utils/Errors.h>
#include <utils/String8.h>

namespace android {
namespace {

// Path to real sysfs file that can be written to change the power state.
const char kDefaultPowerStatePath[] = "/sys/power/state";

}  // namespace

const char PowerManager::kRebootPrefix[] = "reboot,";
const char PowerManager::kShutdownPrefix[] = "shutdown,";
const char PowerManager::kPowerStateSuspend[] = "mem";

PowerManager::PowerManager()
    : power_state_path_(kDefaultPowerStatePath) {}

PowerManager::~PowerManager() = default;

bool PowerManager::Init() {
  if (!property_setter_)
    property_setter_.reset(new SystemPropertySetter());
  if (!wake_lock_manager_) {
    wake_lock_manager_.reset(new WakeLockManager());
    if (!static_cast<WakeLockManager*>(wake_lock_manager_.get())->Init())
      return false;
  }

  LOG(INFO) << "Registering with service manager as \""
            << kPowerManagerServiceName << "\"";
  return BinderWrapper::Get()->RegisterService(kPowerManagerServiceName, this);
}

status_t PowerManager::acquireWakeLock(int flags,
                                       const sp<IBinder>& lock,
                                       const String16& tag,
                                       const String16& packageName,
                                       bool isOneWay) {
  return AddWakeLockRequest(lock, tag, packageName,
                            BinderWrapper::Get()->GetCallingUid())
             ? OK
             : UNKNOWN_ERROR;
}

status_t PowerManager::acquireWakeLockWithUid(int flags,
                                              const sp<IBinder>& lock,
                                              const String16& tag,
                                              const String16& packageName,
                                              int uid,
                                              bool isOneWay) {
  return AddWakeLockRequest(lock, tag, packageName, static_cast<uid_t>(uid))
             ? OK
             : UNKNOWN_ERROR;
}

status_t PowerManager::releaseWakeLock(const sp<IBinder>& lock,
                                       int flags,
                                       bool isOneWay) {
  return wake_lock_manager_->RemoveRequest(lock) ? OK : UNKNOWN_ERROR;
}

status_t PowerManager::updateWakeLockUids(const sp<IBinder>& lock,
                                          int len,
                                          const int* uids,
                                          bool isOneWay) {
  NOTIMPLEMENTED() << "updateWakeLockUids: lock=" << lock.get()
                   << " len=" << len;
  return OK;
}

status_t PowerManager::powerHint(int hintId, int data) {
  NOTIMPLEMENTED() << "powerHint: hintId=" << hintId << " data=" << data;
  return OK;
}

status_t PowerManager::goToSleep(int64_t event_time_ms, int reason, int flags) {
  if (event_time_ms < last_resume_uptime_.InMilliseconds()) {
    LOG(WARNING) << "Ignoring request to suspend in response to event at "
                 << event_time_ms << " preceding last resume time "
                 << last_resume_uptime_.InMilliseconds();
    return BAD_VALUE;
  }

  LOG(INFO) << "Suspending immediately for event at " << event_time_ms
            << " (reason=" << reason << " flags=" << flags << ")";
  if (base::WriteFile(power_state_path_, kPowerStateSuspend,
                      strlen(kPowerStateSuspend)) !=
      static_cast<int>(strlen(kPowerStateSuspend))) {
    PLOG(ERROR) << "Failed to write \"" << kPowerStateSuspend << "\" to "
                << power_state_path_.value();
    return UNKNOWN_ERROR;
  }

  last_resume_uptime_ =
      base::TimeDelta::FromMilliseconds(base::SysInfo::Uptime());
  LOG(INFO) << "Resumed from suspend at "
            << last_resume_uptime_.InMilliseconds();
  return OK;
}

status_t PowerManager::reboot(bool confirm, const String16& reason, bool wait) {
  const std::string reason_str(String8(reason).string());
  if (!(reason_str.empty() || reason_str == kRebootReasonRecovery)) {
    LOG(WARNING) << "Ignoring reboot request with invalid reason \""
                 << reason_str << "\"";
    return BAD_VALUE;
  }

  LOG(INFO) << "Rebooting with reason \"" << reason_str << "\"";
  if (!property_setter_->SetProperty(ANDROID_RB_PROPERTY,
                                     kRebootPrefix + reason_str)) {
    return UNKNOWN_ERROR;
  }
  return OK;
}

status_t PowerManager::shutdown(bool confirm,
                                const String16& reason,
                                bool wait) {
  const std::string reason_str(String8(reason).string());
  if (!(reason_str.empty() || reason_str == kShutdownReasonUserRequested)) {
    LOG(WARNING) << "Ignoring shutdown request with invalid reason \""
                 << reason_str << "\"";
    return BAD_VALUE;
  }

  LOG(INFO) << "Shutting down with reason \"" << reason_str << "\"";
  if (!property_setter_->SetProperty(ANDROID_RB_PROPERTY,
                                     kShutdownPrefix + reason_str)) {
    return UNKNOWN_ERROR;
  }
  return OK;
}

status_t PowerManager::crash(const String16& message) {
  NOTIMPLEMENTED() << "crash: message=" << message;
  return OK;
}

bool PowerManager::AddWakeLockRequest(const sp<IBinder>& lock,
                                      const String16& tag,
                                      const String16& packageName,
                                      int uid) {
  return wake_lock_manager_->AddRequest(lock, String8(tag).string(),
                                        String8(packageName).string(), uid);
}

}  // namespace android
