Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d429b182 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Implemented INITIAL_USER_INFO."

parents 7afe2319 003fe685
Loading
Loading
Loading
Loading
+21 −7
Original line number Diff line number Diff line
@@ -28,6 +28,8 @@

#include <hwbinder/IPCThreadState.h>

#include <utils/SystemClock.h>

#include "VehicleUtils.h"

// TODO: figure out how to include private/android_filesystem_config.h instead...
@@ -247,10 +249,11 @@ void VehicleHalManager::cmdHelp(int fd) const {
    dprintf(fd, "--get <PROP1> [PROP2] [PROPN]: dumps the value of specific properties \n");
    // TODO: support other formats (int64, float, bytes)
    dprintf(fd,
            "--set <PROP> <i|s> <VALUE_1> [<i|s> <VALUE_N>]: sets the value of property PROP, using"
            " arbitrary number of key/value parameters (i for int32, s for string). Notice that "
            "the string value can be set just once, while the other can have multiple values "
            "(so they're used in the respective array)\n");
            "--set <PROP> <i|s> <VALUE_1> [<i|s> <VALUE_N>] [a AREA_ID] : sets the value of "
            "property PROP, using arbitrary number of key/value parameters (i for int32, "
            "s for string) and an optional area.\n"
            "Notice that the string value can be set just once, while the other can have multiple "
            "values (so they're used in the respective array)\n");
}

void VehicleHalManager::cmdListAllProperties(int fd) const {
@@ -352,13 +355,13 @@ void VehicleHalManager::cmdSetOneProperty(int fd, const hidl_vec<hidl_string>& o

    VehiclePropValue prop;
    if (!safelyParseInt(fd, 1, options[1], &prop.prop)) return;
    prop.timestamp = 0;
    prop.areaId = 0;  // TODO: add option to pass areaId as parameter
    prop.timestamp = elapsedRealtimeNano();
    prop.status = VehiclePropertyStatus::AVAILABLE;

    // First pass calculate sizes
    // First pass: calculate sizes
    int sizeInt32 = 0;
    int stringIndex = 0;
    int areaIndex = 0;
    for (int i = 2, kv = 1; kv <= numberValues; kv++) {
        // iterate through the kv=1..n key/value pairs, accessing indexes i / i+1 at each step
        std::string type = options[i];
@@ -374,6 +377,15 @@ void VehicleHalManager::cmdSetOneProperty(int fd, const hidl_vec<hidl_string>& o
                return;
            }
            stringIndex = i;
        } else if (EqualsIgnoreCase(type, "a")) {
            if (areaIndex != 0) {
                dprintf(fd,
                        "defining area value (%s) again at index %d (already defined at %d=%s"
                        ")\n",
                        value.c_str(), i, areaIndex, options[areaIndex + 1].c_str());
                return;
            }
            areaIndex = i;
        } else {
            dprintf(fd, "invalid (%s) type at index %d\n", type.c_str(), i);
            return;
@@ -395,6 +407,8 @@ void VehicleHalManager::cmdSetOneProperty(int fd, const hidl_vec<hidl_string>& o
            prop.value.int32Values[indexInt32++] = safeInt;
        } else if (EqualsIgnoreCase(type, "s")) {
            prop.value.stringValue = value;
        } else if (EqualsIgnoreCase(type, "a")) {
            if (!safelyParseInt(fd, valueIndex, value, &prop.areaId)) return;
        }
        i += 2;
    }
+11 −0
Original line number Diff line number Diff line
@@ -76,6 +76,7 @@ constexpr int WHEEL_FRONT_LEFT = (int)VehicleAreaWheel::LEFT_FRONT;
constexpr int WHEEL_FRONT_RIGHT = (int)VehicleAreaWheel::RIGHT_FRONT;
constexpr int WHEEL_REAR_LEFT = (int)VehicleAreaWheel::LEFT_REAR;
constexpr int WHEEL_REAR_RIGHT = (int)VehicleAreaWheel::RIGHT_REAR;
constexpr int INITIAL_USER_INFO = (int)VehicleProperty::INITIAL_USER_INFO;

/**
 * This property is used for test purpose to generate fake events. Here is the test package that
@@ -990,6 +991,16 @@ const ConfigDeclaration kVehicleProperties[]{
                                  (int)VehicleVendorPermission::PERMISSION_DEFAULT},
                 },
         .initialValue = {.int32Values = {1}}},

        {
                .config =
                        {
                                .prop = toInt(VehicleProperty::INITIAL_USER_INFO),
                                .access = VehiclePropertyAccess::READ_WRITE,
                                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
                        },
        },

};

}  // impl
+96 −0
Original line number Diff line number Diff line
@@ -13,6 +13,9 @@
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#define LOG_TAG "automotive.vehicle@2.0-connector"

#include <android-base/logging.h>
#include <utils/SystemClock.h>

@@ -261,6 +264,8 @@ StatusCode EmulatedVehicleServer::onSetProperty(const VehiclePropValue& value, b
                    break;
            }
            break;
        case INITIAL_USER_INFO:
            return onSetInitialUserInfo(value, updateStatus);
        default:
            break;
    }
@@ -274,6 +279,97 @@ StatusCode EmulatedVehicleServer::onSetProperty(const VehiclePropValue& value, b
    return StatusCode::OK;
}

/**
 * INITIAL_USER_INFO is called by Android when it starts, and it's expecting a property change
 * indicating what the initial user should be.
 *
 * During normal circumstances, the emulator will reply right away, passing a response if
 * InitialUserInfoResponseAction::DEFAULT (so Android could use its own logic to decide which user
 * to boot).
 *
 * But during development / testing, the behavior can be changed using lshal dump, which must use
 * the areaId to indicate what should happen next.
 *
 * So, the behavior of set(INITIAL_USER_INFO) is:
 *
 * - if it has an areaId, store the property into mInitialUserResponseFromCmd (as it was called by
 *   lshal).
 * - else if mInitialUserResponseFromCmd is not set, return a response with the same request id and
 *   InitialUserInfoResponseAction::DEFAULT
 * - else the behavior is defined by the areaId on mInitialUserResponseFromCmd:
 * - if it's 1, reply with mInitialUserResponseFromCmd and the right request id
 * - if it's 2, reply with mInitialUserResponseFromCmd but a wrong request id (so Android can test
 *   this error scenario)
 * - if it's 3, then don't send a property change (so Android can emulate a timeout)
 *
 */
StatusCode EmulatedVehicleServer::onSetInitialUserInfo(const VehiclePropValue& value,
                                                       bool updateStatus) {
    // TODO: LOG calls below might be more suited to be DEBUG, but those are not being logged
    // (even when explicitly calling setprop log.tag. As this class should be using ALOG instead of
    // LOG, it's not worth investigating why...

    if (value.areaId != 0) {
        LOG(INFO) << "set(INITIAL_USER_INFO) called from lshal; storing it: " << toString(value);
        mInitialUserResponseFromCmd.reset(new VehiclePropValue(value));
        return StatusCode::OK;
    }
    LOG(INFO) << "set(INITIAL_USER_INFO) called from Android: " << toString(value);

    if (value.value.int32Values.size() == 0) {
        LOG(ERROR) << "invalid request (no requestId): " << toString(value);
        return StatusCode::INVALID_ARG;
    }
    int32_t requestId = value.value.int32Values[0];

    // Create the update property and set common values
    auto updatedValue = createVehiclePropValue(VehiclePropertyType::MIXED, 0);
    updatedValue->prop = INITIAL_USER_INFO;
    updatedValue->timestamp = elapsedRealtimeNano();

    if (mInitialUserResponseFromCmd == nullptr) {
        updatedValue->value.int32Values.resize(2);
        updatedValue->value.int32Values[0] = requestId;
        updatedValue->value.int32Values[1] = (int32_t)InitialUserInfoResponseAction::DEFAULT;
        LOG(INFO) << "no lshal response; returning InitialUserInfoResponseAction::DEFAULT: "
                  << toString(*updatedValue);
        onPropertyValueFromCar(*updatedValue, updateStatus);
        return StatusCode::OK;
    }

    // mInitialUserResponseFromCmd is used for just one request
    std::unique_ptr<VehiclePropValue> response = std::move(mInitialUserResponseFromCmd);

    // TODO(b/138709788): rather than populate the raw values directly, it should use the
    // libraries that convert a InitialUserInfoResponse into a VehiclePropValue)

    switch (response->areaId) {
        case 1:
            LOG(INFO) << "returning response with right request id";
            *updatedValue = *response;
            updatedValue->areaId = 0;
            updatedValue->value.int32Values[0] = requestId;
            break;
        case 2:
            LOG(INFO) << "returning response with wrong request id";
            *updatedValue = *response;
            updatedValue->areaId = 0;
            updatedValue->value.int32Values[0] = -requestId;
            break;
        case 3:
            LOG(INFO) << "not generating a property change event because of lshal prop: "
                      << toString(*response);
            return StatusCode::OK;
        default:
            LOG(ERROR) << "invalid action on lshal response: " << toString(*response);
            return StatusCode::INTERNAL_ERROR;
    }

    LOG(INFO) << "updating property to: " << toString(*updatedValue);
    onPropertyValueFromCar(*updatedValue, updateStatus);
    return StatusCode::OK;
}

EmulatedPassthroughConnectorPtr makeEmulatedPassthroughConnector() {
    return std::make_unique<EmulatedPassthroughConnector>();
}
+4 −0
Original line number Diff line number Diff line
@@ -77,6 +77,10 @@ class EmulatedVehicleServer : public IVehicleServer {
            std::bind(&EmulatedVehicleServer::onFakeValueGenerated, this, std::placeholders::_1)};

    VehiclePropValuePool* mValuePool{nullptr};

    // TODO(b/146207078): it might be clearer to move members below to an EmulatedUserHal class
    std::unique_ptr<VehiclePropValue> mInitialUserResponseFromCmd;
    StatusCode onSetInitialUserInfo(const VehiclePropValue& value, bool updateStatus);
};

// Helper functions