/*
 * Copyright (C) 2019 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 "test/android_test_utils.h"

#include <stdlib.h>

#include "perfetto/base/logging.h"
#include "perfetto/ext/base/android_utils.h"
#include "perfetto/ext/base/file_utils.h"

namespace perfetto {
namespace {

// invokes |callback| once the target app is in the desired state
void PollRunState(bool desired_run_state,
                  base::TestTaskRunner* task_runner,
                  const std::string& name,
                  std::function<void()> callback) {
  bool app_running = IsAppRunning(name);
  if (app_running == desired_run_state) {
    callback();
    return;
  }
  task_runner->PostDelayedTask(
      [desired_run_state, task_runner, name, callback] {
        PollRunState(desired_run_state, task_runner, name, std::move(callback));
      },
      /*delay_ms=*/5);
}

}  // namespace

bool IsDebuggableBuild() {
  std::string debuggable = base::GetAndroidProp("ro.debuggable");
  return debuggable == "1";
}

bool IsUserBuild() {
  std::string build_type = base::GetAndroidProp("ro.build.type");
  return build_type == "user";
}

// note: cannot use gtest macros due to return type
bool IsAppRunning(const std::string& name) {
  std::string cmd = "pgrep -f ^" + name + "$";
  int retcode = system(cmd.c_str());
  PERFETTO_CHECK(retcode >= 0);
  int exit_status = WEXITSTATUS(retcode);
  if (exit_status == 0)
    return true;
  if (exit_status == 1)
    return false;
  PERFETTO_FATAL("unexpected exit status from system(pgrep): %d", exit_status);
}

int PidForProcessName(const std::string& name) {
  std::string cmd = "pgrep -f ^" + name + "$";
  FILE* fp = popen(cmd.c_str(), "re");
  if (!fp)
    return -1;

  std::string out;
  base::ReadFileStream(fp, &out);
  pclose(fp);

  char* endptr = nullptr;
  int pid = static_cast<int>(strtol(out.c_str(), &endptr, 10));
  if (*endptr != '\0' && *endptr != '\n')
    return -1;
  return pid;
}

void WaitForProcess(const std::string& process,
                    const std::string& checkpoint_name,
                    base::TestTaskRunner* task_runner,
                    uint32_t delay_ms) {
  bool desired_run_state = true;
  const auto checkpoint = task_runner->CreateCheckpoint(checkpoint_name);
  task_runner->PostDelayedTask(
      [desired_run_state, task_runner, process, checkpoint] {
        PollRunState(desired_run_state, task_runner, process,
                     std::move(checkpoint));
      },
      delay_ms);
}

void StartAppActivity(const std::string& app_name,
                      const std::string& activity_name,
                      const std::string& checkpoint_name,
                      base::TestTaskRunner* task_runner,
                      uint32_t delay_ms) {
  std::string start_cmd = "am start " + app_name + "/." + activity_name;
  int status = system(start_cmd.c_str());
  PERFETTO_CHECK(status >= 0 && WEXITSTATUS(status) == 0);
  WaitForProcess(app_name, checkpoint_name, task_runner, delay_ms);
}

void StopApp(const std::string& app_name,
             const std::string& checkpoint_name,
             base::TestTaskRunner* task_runner) {
  std::string stop_cmd = "am force-stop " + app_name;
  int status = system(stop_cmd.c_str());
  PERFETTO_CHECK(status >= 0 && WEXITSTATUS(status) == 0);

  bool desired_run_state = false;
  auto checkpoint = task_runner->CreateCheckpoint(checkpoint_name);
  task_runner->PostTask([desired_run_state, task_runner, app_name, checkpoint] {
    PollRunState(desired_run_state, task_runner, app_name,
                 std::move(checkpoint));
  });
}

void StopApp(const std::string& app_name) {
  std::string stop_cmd = "am force-stop " + app_name;
  system(stop_cmd.c_str());
}

}  // namespace perfetto
