// 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 "android/metrics/AdbLivenessChecker.h"

#include "android/base/system/System.h"
#include "android/base/files/PathUtils.h"
#include "android/base/Log.h"
#include "android/base/threads/ParallelTask.h"
#include "android/emulation/ConfigDirs.h"

#include "android/metrics/proto/studio_stats.pb.h"

namespace android {
namespace metrics {

using android::base::PathUtils;
using android::base::System;
using android::ConfigDirs;
using std::shared_ptr;

static const char kAdbExecutableBaseName[] = "adb";
static const char kAdbLivenessKey[] = "adb_liveness";
static const int kMaxAttempts = 3;
static const char kPlatformToolsSubdir[] = "platform-tools";

// static
AdbLivenessChecker::Ptr AdbLivenessChecker::create(
        android::base::Looper* looper,
        MetricsReporter* reporter,
        android::base::StringView emulatorName,
        android::base::Looper::Duration checkIntervalMs) {
    auto inst = Ptr(new AdbLivenessChecker(looper, reporter, emulatorName,
                                           checkIntervalMs));
    return inst;
}

AdbLivenessChecker::AdbLivenessChecker(
        android::base::Looper* looper,
        MetricsReporter* reporter,
        android::base::StringView emulatorName,
        android::base::Looper::Duration checkIntervalMs)
    : mAdbPath(PathUtils::join(
              ConfigDirs::getSdkRootDirectory(),
              PathUtils::join(
                      kPlatformToolsSubdir,
                      PathUtils::toExecutableName(kAdbExecutableBaseName)))),
      mLooper(looper),
      mReporter(reporter),
      mEmulatorName(emulatorName),
      mCheckIntervalMs(checkIntervalMs),
      // We use raw pointer to |this| instead of a shared_ptr to avoid cicrular
      // ownership. mRecurrentTask promises to cancel any outstanding tasks when
      // it's destructed.
      mRecurrentTask(looper,
                     [this]() { return adbCheckRequest(); },
                     mCheckIntervalMs),
      mRemainingAttempts(kMaxAttempts) {
    // Don't call start() here: start() launches a parallel task that calls
    // shared_from_this(), which needs at least one shared pointer owning
    // |this|. We can't guarantee that until the constructor call returns.
}

AdbLivenessChecker::~AdbLivenessChecker() {
    stop();
}

void AdbLivenessChecker::start() {
    mRecurrentTask.start();
}

void AdbLivenessChecker::stop() {
    mRecurrentTask.stop();
}

bool AdbLivenessChecker::adbCheckRequest() {
    if (!mRemainingAttempts) {
        LOG(VERBOSE) << "Quitting adb liveness check";
        return false;
    }

    if (mIsCheckRunning) {
        return true;
    }
    mIsCheckRunning = true;

    // NOTE: Capture a shared_ptr to |this| to guarantee object lifetime while
    // the parallel task is running.
    auto shared_this = shared_from_this();
    auto taskFunction = [shared_this](CheckResult* outResult) {
        shared_this->runCheckBlocking(outResult);
    };
    auto taskDoneFunction = [shared_this](const CheckResult& result) {
        shared_this->reportCheckResult(result);
    };
    if (!android::base::runParallelTask<CheckResult>(mLooper, taskFunction,
                                                     taskDoneFunction)) {
        mIsCheckRunning = false;
        return false;
    }
    return true;
}

void AdbLivenessChecker::runCheckBlocking(CheckResult* outResult) const {
    System::ProcessExitCode exitCode;
    const std::vector<std::string> adbServerAliveCmd = {mAdbPath, "devices"};
    if (!System::get()->runCommand(
                adbServerAliveCmd,
                System::RunOptions::WaitForCompletion |
                        System::RunOptions::TerminateOnTimeout,
                mCheckIntervalMs / 3, &exitCode) ||
        exitCode != 0) {
        *outResult = CheckResult::kFailureAdbServerDead;
        return;
    }

    const std::vector<std::string> emulatorAliveCmd = {
            mAdbPath, "-s", mEmulatorName, "shell", "exit"};
    if (!System::get()->runCommand(
                emulatorAliveCmd,
                System::RunOptions::WaitForCompletion |
                        System::RunOptions::TerminateOnTimeout,
                mCheckIntervalMs / 3, &exitCode) ||
        exitCode != 0) {
        *outResult = CheckResult::kFailureEmulatorDead;
        return;
    }

    *outResult = AdbLivenessChecker::CheckResult::kOnline;
}

void AdbLivenessChecker::reportCheckResult(const CheckResult& result) {
    mIsCheckRunning = false;

    // |mIsOnline| starts off set to false. We set it to true if we successfully
    // talk to the emulator at least once. This allows us to distinguish the
    // cases where adb is missing or emulator doesn't boot at all from cases
    // where emulator boots and then disappears from adb.
    if (!mIsOnline) {
        switch (result) {
            case CheckResult::kFailureAdbServerDead:
                dropMetrics(CheckResult::kFailureNoAdb);
                break;
            case CheckResult::kOnline:
                dropMetrics(result);
                mIsOnline = true;
                break;
            default:
                dropMetrics(CheckResult::kNoResult);
        }
        return;
    }

    if (result == CheckResult::kOnline) {
        mRemainingAttempts = kMaxAttempts;
        dropMetrics(result);
    } else if (--mRemainingAttempts == 0) {
        LOG(VERBOSE) << "Reporting error: " << static_cast<int>(result);
        dropMetrics(result);
    } else {
        LOG(VERBOSE) << "Encountered  error. mRemainingAttempts: "
                     << mRemainingAttempts;
    }
}

void AdbLivenessChecker::dropMetrics(const CheckResult& result) {
    // Only report state if it changes. We start with kNoResult, and we only
    // report kNoResult or kFailureNoAdb until emulator starts.
    if (mCurrentState != result) {
        mCurrentState = result;
        mReporter->report([result](android_studio::AndroidStudioEvent* event) {
            event->mutable_emulator_details()->set_adb_liveness(
                    static_cast<android_studio::EmulatorDetails::
                                        EmulatorAdbLiveness>(
                            static_cast<int>(result)));
        });
    }
}

}  // namespace metrics
}  // namespace android
