/*
 * Copyright (C) 2017 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 <hidl/HidlBinderSupport.h>
#include <hidl/HidlTransportSupport.h>
#include <hidl/Static.h>

#include <android-base/logging.h>
#include <android/hidl/manager/1.0/IServiceManager.h>

namespace android {
namespace hardware {

using ::android::hidl::base::V1_0::IBase;

void configureRpcThreadpool(size_t maxThreads, bool callerWillJoin) {
    // TODO(b/32756130) this should be transport-dependent
    configureBinderRpcThreadpool(maxThreads, callerWillJoin);
}
void joinRpcThreadpool() {
    // TODO(b/32756130) this should be transport-dependent
    joinBinderRpcThreadpool();
}

int setupTransportPolling() {
    return setupBinderPolling();
}

status_t handleTransportPoll(int /*fd*/) {
    return handleBinderPoll();
}

// TODO(b/122472540): only store one data item per object
template <typename V>
static void pruneMapLocked(ConcurrentMap<wp<::android::hidl::base::V1_0::IBase>, V>& map) {
    using ::android::hidl::base::V1_0::IBase;

    std::vector<wp<IBase>> toDelete;
    for (const auto& kv : map) {
        if (kv.first.promote() == nullptr) {
            toDelete.push_back(kv.first);
        }
    }
    for (const auto& k : toDelete) {
        map.eraseLocked(k);
    }
}

bool setMinSchedulerPolicy(const sp<::android::hidl::base::V1_0::IBase>& service,
                           int policy, int priority) {
    if (service->isRemote()) {
        LOG(ERROR) << "Can't set scheduler policy on remote service.";
        return false;
    }

    switch (policy) {
        case SCHED_NORMAL: {
            if (priority < -20 || priority > 19) {
                LOG(ERROR) << "Invalid priority for SCHED_NORMAL: " << priority;
                return false;
            }
        } break;
        case SCHED_RR:
        case SCHED_FIFO: {
            if (priority < 1 || priority > 99) {
                LOG(ERROR) << "Invalid priority for " << policy << " policy: " << priority;
                return false;
            }
        } break;
        default: {
            LOG(ERROR) << "Invalid scheduler policy " << policy;
            return false;
        }
    }

    // Due to ABI considerations, IBase cannot have a destructor to clean this up.
    // So, because this API is so infrequently used, (expected to be usually only
    // one time for a process, but it can be more), we are cleaning it up here.
    std::unique_lock<std::mutex> lock = details::gServicePrioMap->lock();
    pruneMapLocked(details::gServicePrioMap.get());
    details::gServicePrioMap->setLocked(service, {policy, priority});

    return true;
}

bool setRequestingSid(const sp<::android::hidl::base::V1_0::IBase>& service, bool requesting) {
    if (service->isRemote()) {
        ALOGE("Can't set requesting sid on remote service.");
        return false;
    }

    // Due to ABI considerations, IBase cannot have a destructor to clean this up.
    // So, because this API is so infrequently used, (expected to be usually only
    // one time for a process, but it can be more), we are cleaning it up here.
    std::unique_lock<std::mutex> lock = details::gServiceSidMap->lock();
    pruneMapLocked(details::gServiceSidMap.get());
    details::gServiceSidMap->setLocked(service, requesting);

    return true;
}

bool interfacesEqual(const sp<IBase>& left, const sp<IBase>& right) {
    if (left == nullptr || right == nullptr || !left->isRemote() || !right->isRemote()) {
        return left == right;
    }
    return getOrCreateCachedBinder(left.get()) == getOrCreateCachedBinder(right.get());
}

namespace details {
int32_t getPidIfSharable() {
#if LIBHIDL_TARGET_DEBUGGABLE
    return getpid();
#else
    using android::hidl::manager::V1_0::IServiceManager;
    return static_cast<int32_t>(IServiceManager::PidConstant::NO_PID);
#endif
}
}  // namespace details

}  // namespace hardware
}  // namespace android
