C++程序  |  328行  |  10.02 KB

/*
 * 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.
 */
#define LOG_TAG "VehicleNetwork.Lib"

#include <binder/IServiceManager.h>
#include <binder/ProcessState.h>
#include <utils/threads.h>

#include <hardware/vehicle.h>

#include <VehicleNetwork.h>

namespace android {

VehicleNetworkEventMessageHandler::VehicleNetworkEventMessageHandler(const sp<Looper>& looper,
            sp<VehicleNetworkListener>& listener) :
            mLooper(looper),
            mListener(listener) {

}

VehicleNetworkEventMessageHandler::~VehicleNetworkEventMessageHandler() {
    Mutex::Autolock autoLock(mLock);
    mEvents.clear();
    for (VehicleHalError* e : mHalErrors) {
        delete e;
    }
    mHalErrors.clear();
    mHalRestartEvents.clear();
}

void VehicleNetworkEventMessageHandler::handleHalEvents(sp<VehiclePropValueListHolder>& events) {
    Mutex::Autolock autoLock(mLock);
    mEvents.push_back(events);
    mLooper->sendMessage(this, Message(EVENT_EVENTS));
}

void VehicleNetworkEventMessageHandler::handleHalError(int32_t errorCode, int32_t property,
        int32_t operation) {
    Mutex::Autolock autoLock(mLock);
    VehicleHalError* error = new VehicleHalError(errorCode, property, operation);
    if (error == NULL) {
        ALOGE("VehicleNetworkEventMessageHandler::handleHalError, new failed");
        return;
    }
    mHalErrors.push_back(error);
    mLooper->sendMessage(this, Message(EVENT_HAL_ERROR));
}

void VehicleNetworkEventMessageHandler::handleHalRestart(bool inMocking) {
    Mutex::Autolock autoLock(mLock);
    mHalRestartEvents.push_back(inMocking);
    mLooper->sendMessage(this, Message(EVENT_HAL_RESTART));
}

void VehicleNetworkEventMessageHandler::doHandleHalEvents() {
    sp<VehiclePropValueListHolder> values;
    do {
        Mutex::Autolock autoLock(mLock);
        if (mEvents.size() > 0) {
            auto itr = mEvents.begin();
            values = *itr;
            mEvents.erase(itr);
        }
    } while (false);
    if (values.get() != NULL) {
        mListener->onEvents(values);
    }
}

void VehicleNetworkEventMessageHandler::doHandleHalError() {
    VehicleHalError* error = NULL;
    do {
        Mutex::Autolock autoLock(mLock);
        if (mHalErrors.size() > 0) {
            auto itr = mHalErrors.begin();
            error = *itr;
            mHalErrors.erase(itr);
        }
    } while (false);
    if (error != NULL) {
        mListener->onHalError(error->errorCode, error->property, error->operation);
        delete error;
    }
}

void VehicleNetworkEventMessageHandler::doHandleHalRestart() {
    bool shouldDispatch = false;
    bool inMocking = false;
    do {
        Mutex::Autolock autoLock(mLock);
        if (mHalRestartEvents.size() > 0) {
            auto itr = mHalRestartEvents.begin();
            inMocking = *itr;
            mHalRestartEvents.erase(itr);
            shouldDispatch = true;
        }
    } while (false);
    if (shouldDispatch) {
        mListener->onHalRestart(inMocking);
    }
}

void VehicleNetworkEventMessageHandler::handleMessage(const Message& message) {
    switch (message.what) {
    case EVENT_EVENTS:
        doHandleHalEvents();
        break;
    case EVENT_HAL_ERROR:
        doHandleHalError();
        break;
    case EVENT_HAL_RESTART:
        doHandleHalRestart();
        break;
    }
}

// ----------------------------------------------------------------------------

sp<VehicleNetwork> VehicleNetwork::createVehicleNetwork(sp<VehicleNetworkListener>& listener) {
    sp<IBinder> binder = defaultServiceManager()->getService(
            String16(IVehicleNetwork::SERVICE_NAME));
    sp<VehicleNetwork> vn;
    if (binder != NULL) {
        sp<IVehicleNetwork> ivn(interface_cast<IVehicleNetwork>(binder));
        vn = new VehicleNetwork(ivn, listener);
        if (vn != NULL) {
            // in case thread pool is not started, start it.
            ProcessState::self()->startThreadPool();
        }
    }
    return vn;
}

VehicleNetwork::VehicleNetwork(sp<IVehicleNetwork>& vehicleNetwork,
        sp<VehicleNetworkListener> &listener) :
        mService(vehicleNetwork),
        mClientListener(listener) {
}

VehicleNetwork::~VehicleNetwork() {
    sp<IVehicleNetwork> service = getService();
    IInterface::asBinder(service)->unlinkToDeath(this);
    service->stopHalRestartMonitoring(this);
    mHandlerThread->quit();
}

void VehicleNetwork::onFirstRef() {
    Mutex::Autolock autoLock(mLock);
    mHandlerThread = new HandlerThread();
    status_t r = mHandlerThread->start("VNS.NATIVE_LOOP");
    if (r != NO_ERROR) {
        ALOGE("cannot start handler thread, error:%d", r);
        return;
    }
    sp<VehicleNetworkEventMessageHandler> handler(
            new VehicleNetworkEventMessageHandler(mHandlerThread->getLooper(), mClientListener));
    ASSERT_ALWAYS_ON_NO_MEMORY(handler.get());
    mEventHandler = handler;
    IInterface::asBinder(mService)->linkToDeath(this);
    mService->startHalRestartMonitoring(this);
}

status_t VehicleNetwork::setInt32Property(int32_t property, int32_t value) {
    vehicle_prop_value_t v;
    v.prop = property;
    v.value_type = VEHICLE_VALUE_TYPE_INT32;
    v.value.int32_value = value;
    return setProperty(v);
}

status_t VehicleNetwork::getInt32Property(int32_t property, int32_t* value, int64_t* timestamp) {
    vehicle_prop_value_t v;
    v.prop = property;
    // do not check error as it is always safe to access members for this data type.
    // saves one if for normal flow.
    status_t r = getProperty(&v);
    *value = v.value.int32_value;
    *timestamp = v.timestamp;
    return r;
}

status_t VehicleNetwork::setInt64Property(int32_t property, int64_t value) {
    vehicle_prop_value_t v;
    v.prop = property;
    v.value_type = VEHICLE_VALUE_TYPE_INT64;
    v.value.int64_value = value;
    return setProperty(v);
}

status_t VehicleNetwork::getInt64Property(int32_t property, int64_t* value, int64_t* timestamp) {
    vehicle_prop_value_t v;
    v.prop = property;
    status_t r = getProperty(&v);
    *value = v.value.int64_value;
    *timestamp = v.timestamp;
    return r;
}

status_t VehicleNetwork::setFloatProperty(int32_t property, float value) {
    vehicle_prop_value_t v;
    v.prop = property;
    v.value_type = VEHICLE_VALUE_TYPE_FLOAT;
    v.value.float_value = value;
    return setProperty(v);
}

status_t VehicleNetwork::getFloatProperty(int32_t property, float* value, int64_t* timestamp) {
    vehicle_prop_value_t v;
    v.prop = property;
    status_t r = getProperty(&v);
    *value = v.value.float_value;
    *timestamp = v.timestamp;
    return r;
}

status_t VehicleNetwork::setStringProperty(int32_t property, const String8& value) {
    vehicle_prop_value_t v;
    v.prop = property;
    v.value_type = VEHICLE_VALUE_TYPE_STRING;
    v.value.str_value.data = (uint8_t*)value.string();
    v.value.str_value.len = value.length();
    return setProperty(v);
}

status_t VehicleNetwork::getStringProperty(int32_t property, String8& value, int64_t* timestamp) {
    vehicle_prop_value_t v;
    v.prop = property;
    v.value.str_value.len = 0;
    status_t r = getProperty(&v);
    if (r == NO_ERROR) {
        value.setTo((char*)v.value.str_value.data, v.value.str_value.len);
    }
    *timestamp = v.timestamp;
    return r;
}

sp<VehiclePropertiesHolder> VehicleNetwork::listProperties(int32_t property) {
    return getService()->listProperties(property);
}

status_t VehicleNetwork::setProperty(const vehicle_prop_value_t& value) {
    return getService()->setProperty(value);
}

status_t VehicleNetwork::getProperty(vehicle_prop_value_t* value) {
    return getService()->getProperty(value);
}

status_t VehicleNetwork::subscribe(int32_t property, float sampleRate, int32_t zones) {
    return getService()->subscribe(this, property, sampleRate, zones);
}

void VehicleNetwork::unsubscribe(int32_t property) {
    getService()->unsubscribe(this, property);
}

status_t VehicleNetwork::injectEvent(const vehicle_prop_value_t& value) {
    return getService()->injectEvent(value);
}

status_t VehicleNetwork::startMocking(const sp<IVehicleNetworkHalMock>& mock) {
    return getService()->startMocking(mock);
}

void VehicleNetwork::stopMocking(const sp<IVehicleNetworkHalMock>& mock) {
    getService()->stopMocking(mock);
}

status_t VehicleNetwork::startErrorListening() {
    return getService()->startErrorListening(this);
}

void VehicleNetwork::stopErrorListening() {
    getService()->stopErrorListening(this);
}

void VehicleNetwork::binderDied(const wp<IBinder>& who) {
    ALOGE("service died");
    do {
        Mutex::Autolock autoLock(mLock);
        sp<IBinder> ibinder = who.promote();
        ibinder->unlinkToDeath(this);
        sp<IBinder> binder = defaultServiceManager()->getService(
                String16(IVehicleNetwork::SERVICE_NAME));
        mService = interface_cast<IVehicleNetwork>(binder);
        IInterface::asBinder(mService)->linkToDeath(this);
        mService->startHalRestartMonitoring(this);
    } while (false);
    onHalRestart(false);
}

sp<IVehicleNetwork> VehicleNetwork::getService() {
    Mutex::Autolock autoLock(mLock);
    return mService;
}

sp<VehicleNetworkEventMessageHandler> VehicleNetwork::getEventHandler() {
    Mutex::Autolock autoLock(mLock);
    return mEventHandler;
}

void VehicleNetwork::onEvents(sp<VehiclePropValueListHolder>& events) {
    getEventHandler()->handleHalEvents(events);
}

void VehicleNetwork::onHalError(int32_t errorCode, int32_t property, int32_t operation) {
    getEventHandler()->handleHalError(errorCode, property, operation);
}

void VehicleNetwork::onHalRestart(bool inMocking) {
    getEventHandler()->handleHalRestart(inMocking);
}
}; // namespace android