/*
 * Copyright (C) 2010 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.
 */

#define LOG_TAG "Sensors"

#include <sensor/SensorManager.h>

#include <stdint.h>
#include <sys/types.h>

#include <cutils/native_handle.h>
#include <utils/Errors.h>
#include <utils/RefBase.h>
#include <utils/Singleton.h>

#include <binder/IBinder.h>
#include <binder/IPermissionController.h>
#include <binder/IServiceManager.h>

#include <sensor/ISensorServer.h>
#include <sensor/ISensorEventConnection.h>
#include <sensor/Sensor.h>
#include <sensor/SensorEventQueue.h>

// ----------------------------------------------------------------------------
namespace android {
// ----------------------------------------------------------------------------

Mutex SensorManager::sLock;
std::map<String16, SensorManager*> SensorManager::sPackageInstances;

SensorManager& SensorManager::getInstanceForPackage(const String16& packageName) {
    waitForSensorService(nullptr);

    Mutex::Autolock _l(sLock);
    SensorManager* sensorManager;
    auto iterator = sPackageInstances.find(packageName);

    if (iterator != sPackageInstances.end()) {
        sensorManager = iterator->second;
    } else {
        String16 opPackageName = packageName;

        // It is possible that the calling code has no access to the package name.
        // In this case we will get the packages for the calling UID and pick the
        // first one for attributing the app op. This will work correctly for
        // runtime permissions as for legacy apps we will toggle the app op for
        // all packages in the UID. The caveat is that the operation may be attributed
        // to the wrong package and stats based on app ops may be slightly off.
        if (opPackageName.size() <= 0) {
            sp<IBinder> binder = defaultServiceManager()->getService(String16("permission"));
            if (binder != nullptr) {
                const uid_t uid = IPCThreadState::self()->getCallingUid();
                Vector<String16> packages;
                interface_cast<IPermissionController>(binder)->getPackagesForUid(uid, packages);
                if (!packages.isEmpty()) {
                    opPackageName = packages[0];
                } else {
                    ALOGE("No packages for calling UID");
                }
            } else {
                ALOGE("Cannot get permission service");
            }
        }

        sensorManager = new SensorManager(opPackageName);

        // If we had no package name, we looked it up from the UID and the sensor
        // manager instance we created should also be mapped to the empty package
        // name, to avoid looking up the packages for a UID and get the same result.
        if (packageName.size() <= 0) {
            sPackageInstances.insert(std::make_pair(String16(), sensorManager));
        }

        // Stash the per package sensor manager.
        sPackageInstances.insert(std::make_pair(opPackageName, sensorManager));
    }

    return *sensorManager;
}

void SensorManager::removeInstanceForPackage(const String16& packageName) {
    Mutex::Autolock _l(sLock);
    auto iterator = sPackageInstances.find(packageName);
    if (iterator != sPackageInstances.end()) {
        SensorManager* sensorManager = iterator->second;
        delete sensorManager;
        sPackageInstances.erase(iterator);
    }
}

SensorManager::SensorManager(const String16& opPackageName)
    : mSensorList(nullptr), mOpPackageName(opPackageName), mDirectConnectionHandle(1) {
    Mutex::Autolock _l(mLock);
    assertStateLocked();
}

SensorManager::~SensorManager() {
    free(mSensorList);
}

status_t SensorManager::waitForSensorService(sp<ISensorServer> *server) {
    // try for 300 seconds (60*5(getService() tries for 5 seconds)) before giving up ...
    sp<ISensorServer> s;
    const String16 name("sensorservice");
    for (int i = 0; i < 60; i++) {
        status_t err = getService(name, &s);
        switch (err) {
            case NAME_NOT_FOUND:
                sleep(1);
                continue;
            case NO_ERROR:
                if (server != nullptr) {
                    *server = s;
                }
                return NO_ERROR;
            default:
                return err;
        }
    }
    return TIMED_OUT;
}

void SensorManager::sensorManagerDied() {
    Mutex::Autolock _l(mLock);
    mSensorServer.clear();
    free(mSensorList);
    mSensorList = nullptr;
    mSensors.clear();
}

status_t SensorManager::assertStateLocked() {
    bool initSensorManager = false;
    if (mSensorServer == nullptr) {
        initSensorManager = true;
    } else {
        // Ping binder to check if sensorservice is alive.
        status_t err = IInterface::asBinder(mSensorServer)->pingBinder();
        if (err != NO_ERROR) {
            initSensorManager = true;
        }
    }
    if (initSensorManager) {
        waitForSensorService(&mSensorServer);
        LOG_ALWAYS_FATAL_IF(mSensorServer == nullptr, "getService(SensorService) NULL");

        class DeathObserver : public IBinder::DeathRecipient {
            SensorManager& mSensorManager;
            virtual void binderDied(const wp<IBinder>& who) {
                ALOGW("sensorservice died [%p]", static_cast<void*>(who.unsafe_get()));
                mSensorManager.sensorManagerDied();
            }
        public:
            explicit DeathObserver(SensorManager& mgr) : mSensorManager(mgr) { }
        };

        mDeathObserver = new DeathObserver(*const_cast<SensorManager *>(this));
        IInterface::asBinder(mSensorServer)->linkToDeath(mDeathObserver);

        mSensors = mSensorServer->getSensorList(mOpPackageName);
        size_t count = mSensors.size();
        if (count == 0) {
            ALOGE("Failed to get Sensor list");
            mSensorServer.clear();
            return UNKNOWN_ERROR;
        }
        mSensorList =
                static_cast<Sensor const**>(malloc(count * sizeof(Sensor*)));
        LOG_ALWAYS_FATAL_IF(mSensorList == nullptr, "mSensorList NULL");

        for (size_t i=0 ; i<count ; i++) {
            mSensorList[i] = mSensors.array() + i;
        }
    }

    return NO_ERROR;
}

ssize_t SensorManager::getSensorList(Sensor const* const** list) {
    Mutex::Autolock _l(mLock);
    status_t err = assertStateLocked();
    if (err < 0) {
        return static_cast<ssize_t>(err);
    }
    *list = mSensorList;
    return static_cast<ssize_t>(mSensors.size());
}

ssize_t SensorManager::getDynamicSensorList(Vector<Sensor> & dynamicSensors) {
    Mutex::Autolock _l(mLock);
    status_t err = assertStateLocked();
    if (err < 0) {
        return static_cast<ssize_t>(err);
    }

    dynamicSensors = mSensorServer->getDynamicSensorList(mOpPackageName);
    size_t count = dynamicSensors.size();

    return static_cast<ssize_t>(count);
}

Sensor const* SensorManager::getDefaultSensor(int type)
{
    Mutex::Autolock _l(mLock);
    if (assertStateLocked() == NO_ERROR) {
        bool wakeUpSensor = false;
        // For the following sensor types, return a wake-up sensor. These types are by default
        // defined as wake-up sensors. For the rest of the sensor types defined in sensors.h return
        // a non_wake-up version.
        if (type == SENSOR_TYPE_PROXIMITY || type == SENSOR_TYPE_SIGNIFICANT_MOTION ||
            type == SENSOR_TYPE_TILT_DETECTOR || type == SENSOR_TYPE_WAKE_GESTURE ||
            type == SENSOR_TYPE_GLANCE_GESTURE || type == SENSOR_TYPE_PICK_UP_GESTURE ||
            type == SENSOR_TYPE_WRIST_TILT_GESTURE ||
            type == SENSOR_TYPE_LOW_LATENCY_OFFBODY_DETECT || type == SENSOR_TYPE_HINGE_ANGLE) {
            wakeUpSensor = true;
        }
        // For now we just return the first sensor of that type we find.
        // in the future it will make sense to let the SensorService make
        // that decision.
        for (size_t i=0 ; i<mSensors.size() ; i++) {
            if (mSensorList[i]->getType() == type &&
                mSensorList[i]->isWakeUpSensor() == wakeUpSensor) {
                return mSensorList[i];
            }
        }
    }
    return nullptr;
}

sp<SensorEventQueue> SensorManager::createEventQueue(String8 packageName, int mode) {
    sp<SensorEventQueue> queue;

    Mutex::Autolock _l(mLock);
    while (assertStateLocked() == NO_ERROR) {
        sp<ISensorEventConnection> connection =
                mSensorServer->createSensorEventConnection(packageName, mode, mOpPackageName);
        if (connection == nullptr) {
            // SensorService just died or the app doesn't have required permissions.
            ALOGE("createEventQueue: connection is NULL.");
            return nullptr;
        }
        queue = new SensorEventQueue(connection);
        break;
    }
    return queue;
}

bool SensorManager::isDataInjectionEnabled() {
    Mutex::Autolock _l(mLock);
    if (assertStateLocked() == NO_ERROR) {
        return mSensorServer->isDataInjectionEnabled();
    }
    return false;
}

int SensorManager::createDirectChannel(
        size_t size, int channelType, const native_handle_t *resourceHandle) {
    Mutex::Autolock _l(mLock);
    if (assertStateLocked() != NO_ERROR) {
        return NO_INIT;
    }

    if (channelType != SENSOR_DIRECT_MEM_TYPE_ASHMEM
            && channelType != SENSOR_DIRECT_MEM_TYPE_GRALLOC) {
        ALOGE("Bad channel shared memory type %d", channelType);
        return BAD_VALUE;
    }

    sp<ISensorEventConnection> conn =
              mSensorServer->createSensorDirectConnection(mOpPackageName,
                  static_cast<uint32_t>(size),
                  static_cast<int32_t>(channelType),
                  SENSOR_DIRECT_FMT_SENSORS_EVENT, resourceHandle);
    if (conn == nullptr) {
        return NO_MEMORY;
    }

    int nativeHandle = mDirectConnectionHandle++;
    mDirectConnection.emplace(nativeHandle, conn);
    return nativeHandle;
}

void SensorManager::destroyDirectChannel(int channelNativeHandle) {
    Mutex::Autolock _l(mLock);
    if (assertStateLocked() == NO_ERROR) {
        mDirectConnection.erase(channelNativeHandle);
    }
}

int SensorManager::configureDirectChannel(int channelNativeHandle, int sensorHandle, int rateLevel) {
    Mutex::Autolock _l(mLock);
    if (assertStateLocked() != NO_ERROR) {
        return NO_INIT;
    }

    auto i = mDirectConnection.find(channelNativeHandle);
    if (i == mDirectConnection.end()) {
        ALOGE("Cannot find the handle in client direct connection table");
        return BAD_VALUE;
    }

    int ret;
    ret = i->second->configureChannel(sensorHandle, rateLevel);
    ALOGE_IF(ret < 0, "SensorManager::configureChannel (%d, %d) returns %d",
            static_cast<int>(sensorHandle), static_cast<int>(rateLevel),
            static_cast<int>(ret));
    return ret;
}

int SensorManager::setOperationParameter(
        int handle, int type,
        const Vector<float> &floats, const Vector<int32_t> &ints) {
    Mutex::Autolock _l(mLock);
    if (assertStateLocked() != NO_ERROR) {
        return NO_INIT;
    }
    return mSensorServer->setOperationParameter(handle, type, floats, ints);
}

// ----------------------------------------------------------------------------
}; // namespace android
