Merge "Remove dependency to libbinder in VHAL"
This commit is contained in:
commit
a5ecf4604a
10 changed files with 18 additions and 595 deletions
|
@ -22,7 +22,6 @@ vhal_v2_0 = android.hardware.automotive.vehicle@2.0
|
||||||
include $(CLEAR_VARS)
|
include $(CLEAR_VARS)
|
||||||
LOCAL_MODULE := $(vhal_v2_0)-manager-lib
|
LOCAL_MODULE := $(vhal_v2_0)-manager-lib
|
||||||
LOCAL_SRC_FILES := \
|
LOCAL_SRC_FILES := \
|
||||||
common/src/AccessControlConfigParser.cpp \
|
|
||||||
common/src/SubscriptionManager.cpp \
|
common/src/SubscriptionManager.cpp \
|
||||||
common/src/VehicleHalManager.cpp \
|
common/src/VehicleHalManager.cpp \
|
||||||
common/src/VehicleObjectPool.cpp \
|
common/src/VehicleObjectPool.cpp \
|
||||||
|
@ -35,7 +34,6 @@ LOCAL_EXPORT_C_INCLUDE_DIRS := \
|
||||||
$(LOCAL_PATH)/common/include
|
$(LOCAL_PATH)/common/include
|
||||||
|
|
||||||
LOCAL_SHARED_LIBRARIES := \
|
LOCAL_SHARED_LIBRARIES := \
|
||||||
libbinder \
|
|
||||||
libhidlbase \
|
libhidlbase \
|
||||||
libhidltransport \
|
libhidltransport \
|
||||||
libhwbinder \
|
libhwbinder \
|
||||||
|
@ -89,7 +87,6 @@ LOCAL_WHOLE_STATIC_LIBRARIES := \
|
||||||
|
|
||||||
LOCAL_SHARED_LIBRARIES := \
|
LOCAL_SHARED_LIBRARIES := \
|
||||||
libbase \
|
libbase \
|
||||||
libbinder \
|
|
||||||
libhidlbase \
|
libhidlbase \
|
||||||
libhidltransport \
|
libhidltransport \
|
||||||
libhwbinder \
|
libhwbinder \
|
||||||
|
@ -118,7 +115,6 @@ LOCAL_WHOLE_STATIC_LIBRARIES := \
|
||||||
$(vhal_v2_0)-manager-lib \
|
$(vhal_v2_0)-manager-lib \
|
||||||
|
|
||||||
LOCAL_SRC_FILES:= \
|
LOCAL_SRC_FILES:= \
|
||||||
tests/AccessControlConfigParser_test.cpp \
|
|
||||||
tests/RecurrentTimer_test.cpp \
|
tests/RecurrentTimer_test.cpp \
|
||||||
tests/SubscriptionManager_test.cpp \
|
tests/SubscriptionManager_test.cpp \
|
||||||
tests/VehicleHalManager_test.cpp \
|
tests/VehicleHalManager_test.cpp \
|
||||||
|
@ -126,7 +122,6 @@ LOCAL_SRC_FILES:= \
|
||||||
tests/VehiclePropConfigIndex_test.cpp \
|
tests/VehiclePropConfigIndex_test.cpp \
|
||||||
|
|
||||||
LOCAL_SHARED_LIBRARIES := \
|
LOCAL_SHARED_LIBRARIES := \
|
||||||
libbinder \
|
|
||||||
libhidlbase \
|
libhidlbase \
|
||||||
libhidltransport \
|
libhidltransport \
|
||||||
libhwbinder \
|
libhwbinder \
|
||||||
|
@ -154,7 +149,6 @@ LOCAL_SRC_FILES := \
|
||||||
|
|
||||||
LOCAL_SHARED_LIBRARIES := \
|
LOCAL_SHARED_LIBRARIES := \
|
||||||
libbase \
|
libbase \
|
||||||
libbinder \
|
|
||||||
libhidlbase \
|
libhidlbase \
|
||||||
libhidltransport \
|
libhidltransport \
|
||||||
libhwbinder \
|
libhwbinder \
|
||||||
|
|
|
@ -1,113 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2016 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef android_hardware_automotive_vehicle_V2_0_AccessControlConfigParser_H_
|
|
||||||
#define android_hardware_automotive_vehicle_V2_0_AccessControlConfigParser_H_
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <list>
|
|
||||||
|
|
||||||
#include <android/hardware/automotive/vehicle/2.0/types.h>
|
|
||||||
|
|
||||||
namespace android {
|
|
||||||
namespace hardware {
|
|
||||||
namespace automotive {
|
|
||||||
namespace vehicle {
|
|
||||||
namespace V2_0 {
|
|
||||||
|
|
||||||
struct PropertyAcl {
|
|
||||||
int32_t propId;
|
|
||||||
unsigned uid;
|
|
||||||
VehiclePropertyAccess access;
|
|
||||||
};
|
|
||||||
|
|
||||||
using PropertyAclMap = std::unordered_multimap<int32_t, PropertyAcl>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parser for per-property access control in vehicle HAL.
|
|
||||||
*
|
|
||||||
* It supports the following format:
|
|
||||||
* Set ALIAS_NAME UID
|
|
||||||
* {S,V}:0x0305 {ALIAS_NAME,UID} {R,W,RW}
|
|
||||||
*
|
|
||||||
* ALIAS_NAME is just an alias for UID
|
|
||||||
* S - for system properties (VehiclePropertyGroup::SYSTEM)
|
|
||||||
* V - for vendor properties (VehiclePropertyGroup::VENDOR)
|
|
||||||
*
|
|
||||||
* Example:
|
|
||||||
*
|
|
||||||
* Set AID_AUDIO 1004
|
|
||||||
* Set AID_MY_APP 10022
|
|
||||||
*
|
|
||||||
* S:0x0305 AID_AUDIO RW
|
|
||||||
* S:0x0305 10021 R
|
|
||||||
* V:0x0101 AID_MY_APP R
|
|
||||||
*/
|
|
||||||
class AccessControlConfigParser {
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* Creates an instance of AccessControlConfigParser
|
|
||||||
*
|
|
||||||
* @param properties - properties supported by HAL implementation
|
|
||||||
*/
|
|
||||||
AccessControlConfigParser(const std::vector<int32_t>& properties);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parses config content from given stream and writes results to
|
|
||||||
* propertyAclMap.
|
|
||||||
*/
|
|
||||||
bool parseFromStream(std::istream* stream, PropertyAclMap* propertyAclMap);
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool processTokens(std::list<std::string>* tokens,
|
|
||||||
PropertyAclMap* propertyAclMap);
|
|
||||||
|
|
||||||
bool parsePropertyGroup(char group,
|
|
||||||
VehiclePropertyGroup* outPropertyGroup) const;
|
|
||||||
|
|
||||||
bool parsePropertyId(const std::string& strPropId,
|
|
||||||
VehiclePropertyGroup propertyGroup,
|
|
||||||
int32_t* outVehicleProperty) const;
|
|
||||||
|
|
||||||
bool parseUid(const std::string& strUid, unsigned* outUid) const;
|
|
||||||
|
|
||||||
bool parseAccess(const std::string& strAccess,
|
|
||||||
VehiclePropertyAccess* outAccess) const;
|
|
||||||
|
|
||||||
|
|
||||||
std::string readNextToken(std::list<std::string>* tokens) const;
|
|
||||||
|
|
||||||
static bool parseInt(const char* strValue, int* outIntValue);
|
|
||||||
static void split(const std::string& line,
|
|
||||||
std::list<std::string>* outTokens);
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::unordered_map<std::string, unsigned> mUidMap {}; // Contains UID
|
|
||||||
// aliases.
|
|
||||||
|
|
||||||
// Map property ids w/o TYPE and AREA to VehicleProperty.
|
|
||||||
std::unordered_map<int32_t, int32_t> mStrippedToVehiclePropertyMap;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace V2_0
|
|
||||||
} // namespace vehicle
|
|
||||||
} // namespace automotive
|
|
||||||
} // namespace hardware
|
|
||||||
} // namespace android
|
|
||||||
|
|
||||||
#endif // android_hardware_automotive_vehicle_V2_0_AccessControlConfigParser_H_
|
|
|
@ -24,7 +24,7 @@
|
||||||
|
|
||||||
#include <android/log.h>
|
#include <android/log.h>
|
||||||
#include <hidl/HidlSupport.h>
|
#include <hidl/HidlSupport.h>
|
||||||
#include <hwbinder/IPCThreadState.h>
|
#include <utils/SortedVector.h>
|
||||||
|
|
||||||
#include <android/hardware/automotive/vehicle/2.0/IVehicle.h>
|
#include <android/hardware/automotive/vehicle/2.0/IVehicle.h>
|
||||||
|
|
||||||
|
@ -39,10 +39,8 @@ namespace V2_0 {
|
||||||
|
|
||||||
class HalClient : public android::RefBase {
|
class HalClient : public android::RefBase {
|
||||||
public:
|
public:
|
||||||
HalClient(const sp<IVehicleCallback> &callback,
|
HalClient(const sp<IVehicleCallback> &callback)
|
||||||
int32_t pid,
|
: mCallback(callback) {}
|
||||||
int32_t uid)
|
|
||||||
: mCallback(callback), mPid(pid), mUid(uid) {}
|
|
||||||
|
|
||||||
virtual ~HalClient() {}
|
virtual ~HalClient() {}
|
||||||
public:
|
public:
|
||||||
|
@ -56,8 +54,6 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const sp<IVehicleCallback> mCallback;
|
const sp<IVehicleCallback> mCallback;
|
||||||
const int32_t mPid;
|
|
||||||
const int32_t mUid;
|
|
||||||
|
|
||||||
std::map<int32_t, SubscribeOptions> mSubscriptions;
|
std::map<int32_t, SubscribeOptions> mSubscriptions;
|
||||||
};
|
};
|
||||||
|
|
|
@ -27,9 +27,7 @@
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
#include <android/hardware/automotive/vehicle/2.0/IVehicle.h>
|
#include <android/hardware/automotive/vehicle/2.0/IVehicle.h>
|
||||||
#include <hwbinder/IPCThreadState.h>
|
|
||||||
|
|
||||||
#include "AccessControlConfigParser.h"
|
|
||||||
#include "ConcurrentQueue.h"
|
#include "ConcurrentQueue.h"
|
||||||
#include "SubscriptionManager.h"
|
#include "SubscriptionManager.h"
|
||||||
#include "VehicleHal.h"
|
#include "VehicleHal.h"
|
||||||
|
@ -42,11 +40,6 @@ namespace automotive {
|
||||||
namespace vehicle {
|
namespace vehicle {
|
||||||
namespace V2_0 {
|
namespace V2_0 {
|
||||||
|
|
||||||
struct Caller {
|
|
||||||
pid_t pid;
|
|
||||||
uid_t uid;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class is a thick proxy between IVehicle HIDL interface and vendor's implementation.
|
* This class is a thick proxy between IVehicle HIDL interface and vendor's implementation.
|
||||||
*
|
*
|
||||||
|
@ -99,14 +92,8 @@ private:
|
||||||
|
|
||||||
const VehiclePropConfig* getPropConfigOrNull(int32_t prop) const;
|
const VehiclePropConfig* getPropConfigOrNull(int32_t prop) const;
|
||||||
|
|
||||||
bool checkWritePermission(const VehiclePropConfig &config,
|
bool checkWritePermission(const VehiclePropConfig &config) const;
|
||||||
const Caller& callee) const;
|
bool checkReadPermission(const VehiclePropConfig &config) const;
|
||||||
bool checkReadPermission(const VehiclePropConfig &config,
|
|
||||||
const Caller& caller) const;
|
|
||||||
bool checkAcl(uid_t callerUid,
|
|
||||||
int32_t propertyId,
|
|
||||||
VehiclePropertyAccess requiredAccess) const;
|
|
||||||
|
|
||||||
void onAllClientsUnsubscribed(int32_t propertyId);
|
void onAllClientsUnsubscribed(int32_t propertyId);
|
||||||
|
|
||||||
static bool isSubscribable(const VehiclePropConfig& config,
|
static bool isSubscribable(const VehiclePropConfig& config,
|
||||||
|
@ -114,12 +101,6 @@ private:
|
||||||
static bool isSampleRateFixed(VehiclePropertyChangeMode mode);
|
static bool isSampleRateFixed(VehiclePropertyChangeMode mode);
|
||||||
static float checkSampleRate(const VehiclePropConfig& config,
|
static float checkSampleRate(const VehiclePropConfig& config,
|
||||||
float sampleRate);
|
float sampleRate);
|
||||||
static void readAndParseAclConfig(const char* filename,
|
|
||||||
AccessControlConfigParser* parser,
|
|
||||||
PropertyAclMap* outAclMap);
|
|
||||||
|
|
||||||
static Caller getCaller();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
VehicleHal* mHal;
|
VehicleHal* mHal;
|
||||||
std::unique_ptr<VehiclePropConfigIndex> mConfigIndex;
|
std::unique_ptr<VehiclePropConfigIndex> mConfigIndex;
|
||||||
|
@ -130,7 +111,6 @@ private:
|
||||||
ConcurrentQueue<VehiclePropValuePtr> mEventQueue;
|
ConcurrentQueue<VehiclePropValuePtr> mEventQueue;
|
||||||
BatchingConsumer<VehiclePropValuePtr> mBatchingConsumer;
|
BatchingConsumer<VehiclePropValuePtr> mBatchingConsumer;
|
||||||
VehiclePropValuePool mValueObjectPool;
|
VehiclePropValuePool mValueObjectPool;
|
||||||
PropertyAclMap mPropertyAclMap;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace V2_0
|
} // namespace V2_0
|
||||||
|
|
|
@ -1,228 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2016 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 "automotive.vehicle@2.0-impl"
|
|
||||||
|
|
||||||
#include "AccessControlConfigParser.h"
|
|
||||||
#include "VehicleUtils.h"
|
|
||||||
|
|
||||||
#include <fstream>
|
|
||||||
#include <iostream>
|
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
#include <log/log.h>
|
|
||||||
|
|
||||||
namespace android {
|
|
||||||
namespace hardware {
|
|
||||||
namespace automotive {
|
|
||||||
namespace vehicle {
|
|
||||||
namespace V2_0 {
|
|
||||||
|
|
||||||
AccessControlConfigParser::AccessControlConfigParser(
|
|
||||||
const std::vector<int32_t>& properties) {
|
|
||||||
// Property Id in the config file doesn't include information about
|
|
||||||
// type and area. So we want to create a map from these kind of
|
|
||||||
// *stripped* properties to the whole VehicleProperty.
|
|
||||||
// We also want to filter out ACL to the properties that supported
|
|
||||||
// by concrete Vehicle HAL implementation.
|
|
||||||
for (auto prop : properties) {
|
|
||||||
auto strippedProp = prop
|
|
||||||
& ~toInt(VehiclePropertyType::MASK)
|
|
||||||
& ~toInt(VehicleArea::MASK);
|
|
||||||
mStrippedToVehiclePropertyMap.emplace(strippedProp, prop);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AccessControlConfigParser::parseFromStream(
|
|
||||||
std::istream* stream, PropertyAclMap* propertyAclMap) {
|
|
||||||
std::list<std::string> tokens;
|
|
||||||
std::string line;
|
|
||||||
int lineNo = 0;
|
|
||||||
bool warnings = false;
|
|
||||||
for (;std::getline(*stream, line); lineNo++) {
|
|
||||||
split(line, &tokens);
|
|
||||||
if (!processTokens(&tokens, propertyAclMap)) {
|
|
||||||
warnings = true;
|
|
||||||
ALOGW("Failed to parse line %d : %s", lineNo, line.c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return !warnings;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool AccessControlConfigParser::processTokens(std::list<std::string>* tokens,
|
|
||||||
PropertyAclMap* propertyAclMap) {
|
|
||||||
std::string token = readNextToken(tokens);
|
|
||||||
if (token.empty() || token[0] == '#') { // Ignore comment.
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (token == "Set") {
|
|
||||||
std::string alias = readNextToken(tokens);
|
|
||||||
std::string strUid = readNextToken(tokens);
|
|
||||||
if (alias.empty() || strUid.empty()) {
|
|
||||||
ALOGW("Expected alias and UID must be specified");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
int uid;
|
|
||||||
if (!parseInt(strUid.c_str(), &uid)) {
|
|
||||||
ALOGW("Invalid UID: %d", uid);
|
|
||||||
}
|
|
||||||
mUidMap.emplace(std::move(alias), uid);
|
|
||||||
} else if (token.size() > 2 && token[1] == ':') {
|
|
||||||
VehiclePropertyGroup propGroup;
|
|
||||||
if (!parsePropertyGroup(token[0], &propGroup)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
std::string strUid = readNextToken(tokens);
|
|
||||||
std::string strAccess = readNextToken(tokens);
|
|
||||||
if (strUid.empty() || strAccess.empty()) {
|
|
||||||
ALOGW("Expected UID and access for property: %s",
|
|
||||||
token.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
PropertyAcl acl;
|
|
||||||
if (parsePropertyId(token.substr(2), propGroup, &acl.propId)
|
|
||||||
&& parseUid(strUid, &acl.uid)
|
|
||||||
&& parseAccess(strAccess, &acl.access)) {
|
|
||||||
propertyAclMap->emplace(acl.propId, std::move(acl));
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ALOGW("Unexpected token: %s", token.c_str());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AccessControlConfigParser::parsePropertyGroup(
|
|
||||||
char group, VehiclePropertyGroup* outPropertyGroup) const {
|
|
||||||
switch (group) {
|
|
||||||
case 'S': // Fall through.
|
|
||||||
case 's':
|
|
||||||
*outPropertyGroup = VehiclePropertyGroup::SYSTEM;
|
|
||||||
break;
|
|
||||||
case 'V': // Fall through.
|
|
||||||
case 'v':
|
|
||||||
*outPropertyGroup = VehiclePropertyGroup::VENDOR;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ALOGW("Unexpected group: %c", group);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AccessControlConfigParser::parsePropertyId(
|
|
||||||
const std::string& strPropId,
|
|
||||||
VehiclePropertyGroup propertyGroup,
|
|
||||||
int32_t* outVehicleProperty) const {
|
|
||||||
int32_t propId;
|
|
||||||
if (!parseInt(strPropId.c_str(), &propId)) {
|
|
||||||
ALOGW("Failed to convert property id to integer: %s",
|
|
||||||
strPropId.c_str());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
propId |= static_cast<int>(propertyGroup);
|
|
||||||
auto it = mStrippedToVehiclePropertyMap.find(propId);
|
|
||||||
if (it == mStrippedToVehiclePropertyMap.end()) {
|
|
||||||
ALOGW("Property Id not found or not supported: 0x%x", propId);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
*outVehicleProperty = it->second;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AccessControlConfigParser::parseInt(const char* strValue,
|
|
||||||
int* outIntValue) {
|
|
||||||
char* end;
|
|
||||||
long num = std::strtol(strValue, &end, 0 /* auto detect base */);
|
|
||||||
bool success = *end == 0 && errno != ERANGE;
|
|
||||||
if (success) {
|
|
||||||
*outIntValue = static_cast<int>(num);
|
|
||||||
}
|
|
||||||
|
|
||||||
return success;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AccessControlConfigParser::parseUid(const std::string& strUid,
|
|
||||||
unsigned* outUid) const {
|
|
||||||
auto element = mUidMap.find(strUid);
|
|
||||||
if (element != mUidMap.end()) {
|
|
||||||
*outUid = element->second;
|
|
||||||
} else {
|
|
||||||
int val;
|
|
||||||
if (!parseInt(strUid.c_str(), &val)) {
|
|
||||||
ALOGW("Failed to convert UID '%s' to integer", strUid.c_str());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
*outUid = static_cast<unsigned>(val);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AccessControlConfigParser::parseAccess(
|
|
||||||
const std::string& strAccess, VehiclePropertyAccess* outAccess) const {
|
|
||||||
if (strAccess.size() == 0 || strAccess.size() > 2) {
|
|
||||||
ALOGW("Unknown access mode '%s'", strAccess.c_str());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
int32_t access = static_cast<int32_t>(VehiclePropertyAccess::NONE);
|
|
||||||
for (char c : strAccess) {
|
|
||||||
if (c == 'R' || c == 'r') {
|
|
||||||
access |= VehiclePropertyAccess::READ;
|
|
||||||
} else if (c == 'W' || c == 'w') {
|
|
||||||
access |= VehiclePropertyAccess::WRITE;
|
|
||||||
} else {
|
|
||||||
ALOGW("Unknown access mode: %c", c);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*outAccess = static_cast<VehiclePropertyAccess>(access);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AccessControlConfigParser::split(const std::string& line,
|
|
||||||
std::list<std::string>* outTokens) {
|
|
||||||
outTokens->clear();
|
|
||||||
std::istringstream iss(line);
|
|
||||||
|
|
||||||
while (!iss.eof()) {
|
|
||||||
std::string token;
|
|
||||||
iss >> token;
|
|
||||||
outTokens->push_back(std::move(token));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string AccessControlConfigParser::readNextToken(
|
|
||||||
std::list<std::string>* tokens) const {
|
|
||||||
if (tokens->empty()) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string token = tokens->front();
|
|
||||||
tokens->pop_front();
|
|
||||||
return token;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace V2_0
|
|
||||||
} // namespace vehicle
|
|
||||||
} // namespace automotive
|
|
||||||
} // namespace hardware
|
|
||||||
} // namespace android
|
|
|
@ -232,10 +232,8 @@ sp<HalClient> SubscriptionManager::getOrCreateHalClientLocked(
|
||||||
__func__, callback.get(), res.description().c_str());
|
__func__, callback.get(), res.description().c_str());
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
IPCThreadState* self = IPCThreadState::self();
|
|
||||||
pid_t pid = self->getCallingPid();
|
sp<HalClient> client = new HalClient(callback);
|
||||||
uid_t uid = self->getCallingUid();
|
|
||||||
sp<HalClient> client = new HalClient(callback, pid, uid);
|
|
||||||
mClients.emplace(callback, client);
|
mClients.emplace(callback, client);
|
||||||
return client;
|
return client;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -18,10 +18,10 @@
|
||||||
|
|
||||||
#include "VehicleHalManager.h"
|
#include "VehicleHalManager.h"
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
||||||
#include <android/log.h>
|
#include <android/log.h>
|
||||||
#include <private/android_filesystem_config.h>
|
|
||||||
|
|
||||||
#include "VehicleUtils.h"
|
#include "VehicleUtils.h"
|
||||||
|
|
||||||
|
@ -84,7 +84,7 @@ Return<void> VehicleHalManager::get(const VehiclePropValue& requestedPropValue,
|
||||||
return Void();
|
return Void();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!checkReadPermission(*config, getCaller())) {
|
if (!checkReadPermission(*config)) {
|
||||||
_hidl_cb(StatusCode::ACCESS_DENIED, kEmptyValue);
|
_hidl_cb(StatusCode::ACCESS_DENIED, kEmptyValue);
|
||||||
return Void();
|
return Void();
|
||||||
}
|
}
|
||||||
|
@ -105,7 +105,7 @@ Return<StatusCode> VehicleHalManager::set(const VehiclePropValue &value) {
|
||||||
return StatusCode::INVALID_ARG;
|
return StatusCode::INVALID_ARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!checkWritePermission(*config, getCaller())) {
|
if (!checkWritePermission(*config)) {
|
||||||
return StatusCode::ACCESS_DENIED;
|
return StatusCode::ACCESS_DENIED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,7 +119,6 @@ Return<StatusCode> VehicleHalManager::set(const VehiclePropValue &value) {
|
||||||
Return<StatusCode> VehicleHalManager::subscribe(const sp<IVehicleCallback> &callback,
|
Return<StatusCode> VehicleHalManager::subscribe(const sp<IVehicleCallback> &callback,
|
||||||
const hidl_vec<SubscribeOptions> &options) {
|
const hidl_vec<SubscribeOptions> &options) {
|
||||||
hidl_vec<SubscribeOptions> verifiedOptions(options);
|
hidl_vec<SubscribeOptions> verifiedOptions(options);
|
||||||
auto caller = getCaller();
|
|
||||||
for (size_t i = 0; i < verifiedOptions.size(); i++) {
|
for (size_t i = 0; i < verifiedOptions.size(); i++) {
|
||||||
SubscribeOptions& ops = verifiedOptions[i];
|
SubscribeOptions& ops = verifiedOptions[i];
|
||||||
auto prop = ops.propId;
|
auto prop = ops.propId;
|
||||||
|
@ -136,10 +135,6 @@ Return<StatusCode> VehicleHalManager::subscribe(const sp<IVehicleCallback> &call
|
||||||
return StatusCode::INVALID_ARG;
|
return StatusCode::INVALID_ARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!checkAcl(caller.uid, config->prop, VehiclePropertyAccess::READ)) {
|
|
||||||
return StatusCode::ACCESS_DENIED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isSubscribable(*config, ops.flags)) {
|
if (!isSubscribable(*config, ops.flags)) {
|
||||||
ALOGE("Failed to subscribe: property 0x%x is not subscribable",
|
ALOGE("Failed to subscribe: property 0x%x is not subscribable",
|
||||||
prop);
|
prop);
|
||||||
|
@ -209,13 +204,6 @@ void VehicleHalManager::init() {
|
||||||
for (const auto& config : supportedPropConfigs) {
|
for (const auto& config : supportedPropConfigs) {
|
||||||
supportedProperties.push_back(config.prop);
|
supportedProperties.push_back(config.prop);
|
||||||
}
|
}
|
||||||
|
|
||||||
AccessControlConfigParser aclParser(supportedProperties);
|
|
||||||
const char* configs[] = { "/system/etc/vehicle_access.conf",
|
|
||||||
"/vendor/etc/vehicle_access.conf" };
|
|
||||||
for (const char* filename : configs) {
|
|
||||||
readAndParseAclConfig(filename, &aclParser, &mPropertyAclMap);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VehicleHalManager::~VehicleHalManager() {
|
VehicleHalManager::~VehicleHalManager() {
|
||||||
|
@ -317,39 +305,22 @@ bool VehicleHalManager::isSubscribable(const VehiclePropConfig& config,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VehicleHalManager::checkAcl(uid_t callerUid, int32_t propertyId,
|
bool VehicleHalManager::checkWritePermission(const VehiclePropConfig &config) const {
|
||||||
VehiclePropertyAccess requiredAccess) const {
|
|
||||||
if (callerUid == AID_SYSTEM && isSystemProperty(propertyId)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto range = mPropertyAclMap.equal_range(propertyId);
|
|
||||||
for (auto it = range.first; it != range.second; ++it) {
|
|
||||||
auto& acl = it->second;
|
|
||||||
if (acl.uid == callerUid && (acl.access & requiredAccess)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool VehicleHalManager::checkWritePermission(const VehiclePropConfig &config,
|
|
||||||
const Caller& caller) const {
|
|
||||||
if (!(config.access & VehiclePropertyAccess::WRITE)) {
|
if (!(config.access & VehiclePropertyAccess::WRITE)) {
|
||||||
ALOGW("Property 0%x has no write access", config.prop);
|
ALOGW("Property 0%x has no write access", config.prop);
|
||||||
return false;
|
return false;
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
return checkAcl(caller.uid, config.prop, VehiclePropertyAccess::WRITE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VehicleHalManager::checkReadPermission(const VehiclePropConfig &config,
|
bool VehicleHalManager::checkReadPermission(const VehiclePropConfig &config) const {
|
||||||
const Caller& caller) const {
|
|
||||||
if (!(config.access & VehiclePropertyAccess::READ)) {
|
if (!(config.access & VehiclePropertyAccess::READ)) {
|
||||||
ALOGW("Property 0%x has no read access", config.prop);
|
ALOGW("Property 0%x has no read access", config.prop);
|
||||||
return false;
|
return false;
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return checkAcl(caller.uid, config.prop, VehiclePropertyAccess::READ);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VehicleHalManager::handlePropertySetEvent(const VehiclePropValue& value) {
|
void VehicleHalManager::handlePropertySetEvent(const VehiclePropValue& value) {
|
||||||
|
@ -366,26 +337,6 @@ const VehiclePropConfig* VehicleHalManager::getPropConfigOrNull(
|
||||||
? &mConfigIndex->getConfig(prop) : nullptr;
|
? &mConfigIndex->getConfig(prop) : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Caller VehicleHalManager::getCaller() {
|
|
||||||
Caller caller;
|
|
||||||
IPCThreadState* self = IPCThreadState::self();
|
|
||||||
caller.pid = self->getCallingPid();
|
|
||||||
caller.uid = self->getCallingUid();
|
|
||||||
|
|
||||||
return caller;
|
|
||||||
}
|
|
||||||
|
|
||||||
void VehicleHalManager::readAndParseAclConfig(const char* filename,
|
|
||||||
AccessControlConfigParser* parser,
|
|
||||||
PropertyAclMap* outAclMap) {
|
|
||||||
std::ifstream file(filename);
|
|
||||||
if (file.is_open()) {
|
|
||||||
ALOGI("Parsing file: %s", filename);
|
|
||||||
parser->parseFromStream(&file, outAclMap);
|
|
||||||
file.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void VehicleHalManager::onAllClientsUnsubscribed(int32_t propertyId) {
|
void VehicleHalManager::onAllClientsUnsubscribed(int32_t propertyId) {
|
||||||
mHal->unsubscribe(propertyId);
|
mHal->unsubscribe(propertyId);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,152 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2016 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 <gtest/gtest.h>
|
|
||||||
#include <memory>
|
|
||||||
#include <fstream>
|
|
||||||
#include <unordered_set>
|
|
||||||
|
|
||||||
#include "vhal_v2_0/AccessControlConfigParser.h"
|
|
||||||
#include "vhal_v2_0/VehicleUtils.h"
|
|
||||||
|
|
||||||
namespace android {
|
|
||||||
namespace hardware {
|
|
||||||
namespace automotive {
|
|
||||||
namespace vehicle {
|
|
||||||
namespace V2_0 {
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
class AccessControlConfigParserTest : public ::testing::Test {
|
|
||||||
protected:
|
|
||||||
void SetUp() override {
|
|
||||||
std::vector<int32_t> supportedProperties {
|
|
||||||
toInt(VehicleProperty::HVAC_FAN_SPEED),
|
|
||||||
toInt(VehicleProperty::HVAC_FAN_DIRECTION),
|
|
||||||
};
|
|
||||||
parser.reset(new AccessControlConfigParser(supportedProperties));
|
|
||||||
}
|
|
||||||
public:
|
|
||||||
PropertyAclMap aclMap;
|
|
||||||
std::unique_ptr<AccessControlConfigParser> parser;
|
|
||||||
};
|
|
||||||
|
|
||||||
TEST_F(AccessControlConfigParserTest, basicParsing) {
|
|
||||||
std::stringstream file;
|
|
||||||
file << "S:0x0500 1000 RW" << std::endl;
|
|
||||||
|
|
||||||
ASSERT_TRUE(parser->parseFromStream(&file, &aclMap));
|
|
||||||
|
|
||||||
ASSERT_EQ(1u, aclMap.size());
|
|
||||||
auto it = aclMap.find(toInt(VehicleProperty::HVAC_FAN_SPEED));
|
|
||||||
ASSERT_NE(aclMap.end(), it);
|
|
||||||
ASSERT_EQ(VehiclePropertyAccess::READ_WRITE, it->second.access);
|
|
||||||
ASSERT_EQ(toInt(VehicleProperty::HVAC_FAN_SPEED), it->second.propId);
|
|
||||||
ASSERT_EQ(1000u, it->second.uid);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(AccessControlConfigParserTest, multipleUids) {
|
|
||||||
std::stringstream file;
|
|
||||||
file << "Set AID_AUDIO 1004" << std::endl
|
|
||||||
<< "Set AID_SYSTEM 1000" << std::endl
|
|
||||||
<< "S:0x0500 AID_SYSTEM RW" << std::endl
|
|
||||||
<< "S:0x0500 AID_AUDIO RW" << std::endl
|
|
||||||
<< "S:0x0500 0xbeef R" << std::endl; // Read-only.
|
|
||||||
|
|
||||||
std::unordered_set<unsigned> expectedUids {1000, 1004, 0xbeef};
|
|
||||||
|
|
||||||
ASSERT_TRUE(parser->parseFromStream(&file, &aclMap));
|
|
||||||
|
|
||||||
auto range = aclMap.equal_range(toInt(VehicleProperty::HVAC_FAN_SPEED));
|
|
||||||
for (auto it = range.first; it != range.second; ++it) {
|
|
||||||
auto& acl = it->second;
|
|
||||||
|
|
||||||
ASSERT_EQ(1u, expectedUids.count(acl.uid))
|
|
||||||
<< " uid: " << std::hex << acl.uid;
|
|
||||||
|
|
||||||
if (acl.uid == 0xbeef) {
|
|
||||||
ASSERT_EQ(VehiclePropertyAccess::READ, acl.access);
|
|
||||||
} else {
|
|
||||||
ASSERT_EQ(VehiclePropertyAccess::READ_WRITE, acl.access);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(AccessControlConfigParserTest, fileContainsJunk) {
|
|
||||||
std::stringstream file;
|
|
||||||
file << "This string will be ignored with warning in the log" << std::endl
|
|
||||||
<< "# However comments are quit legitimate" << std::endl
|
|
||||||
<< "S:0x0500 0xbeef R # YAY" << std::endl;
|
|
||||||
|
|
||||||
ASSERT_FALSE(parser->parseFromStream(&file, &aclMap));
|
|
||||||
|
|
||||||
ASSERT_EQ(1u, aclMap.size());
|
|
||||||
auto it = aclMap.find(toInt(VehicleProperty::HVAC_FAN_SPEED));
|
|
||||||
ASSERT_NE(aclMap.end(), it);
|
|
||||||
ASSERT_EQ(VehiclePropertyAccess::READ, it->second.access);
|
|
||||||
ASSERT_EQ(toInt(VehicleProperty::HVAC_FAN_SPEED), it->second.propId);
|
|
||||||
ASSERT_EQ(0xBEEFu, it->second.uid);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(AccessControlConfigParserTest, badIntegerFormat) {
|
|
||||||
std::stringstream file;
|
|
||||||
file << "S:0x0500 A12 RW " << std::endl;
|
|
||||||
|
|
||||||
ASSERT_FALSE(parser->parseFromStream(&file, &aclMap));
|
|
||||||
ASSERT_EQ(0u, aclMap.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(AccessControlConfigParserTest, ignoreNotSupportedProperties) {
|
|
||||||
std::stringstream file;
|
|
||||||
file << "S:0x0666 1000 RW " << std::endl;
|
|
||||||
|
|
||||||
ASSERT_FALSE(parser->parseFromStream(&file, &aclMap));
|
|
||||||
ASSERT_EQ(0u, aclMap.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(AccessControlConfigParserTest, multipleCalls) {
|
|
||||||
std::stringstream configFile;
|
|
||||||
configFile << "S:0x0500 1000 RW" << std::endl;
|
|
||||||
|
|
||||||
ASSERT_TRUE(parser->parseFromStream(&configFile, &aclMap));
|
|
||||||
ASSERT_EQ(1u, aclMap.size());
|
|
||||||
|
|
||||||
std::stringstream configFile2;
|
|
||||||
configFile2 << "S:0x0501 1004 RW" << std::endl;
|
|
||||||
ASSERT_TRUE(parser->parseFromStream(&configFile2, &aclMap));
|
|
||||||
ASSERT_EQ(2u, aclMap.size());
|
|
||||||
|
|
||||||
auto it = aclMap.find(toInt(VehicleProperty::HVAC_FAN_SPEED));
|
|
||||||
ASSERT_NE(aclMap.end(), it);
|
|
||||||
ASSERT_EQ(VehiclePropertyAccess::READ_WRITE, it->second.access);
|
|
||||||
ASSERT_EQ(toInt(VehicleProperty::HVAC_FAN_SPEED), it->second.propId);
|
|
||||||
ASSERT_EQ(1000u, it->second.uid);
|
|
||||||
|
|
||||||
it = aclMap.find(toInt(VehicleProperty::HVAC_FAN_DIRECTION));
|
|
||||||
ASSERT_NE(aclMap.end(), it);
|
|
||||||
ASSERT_EQ(VehiclePropertyAccess::READ_WRITE, it->second.access);
|
|
||||||
ASSERT_EQ(toInt(VehicleProperty::HVAC_FAN_DIRECTION), it->second.propId);
|
|
||||||
ASSERT_EQ(1004u, it->second.uid);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace anonymous
|
|
||||||
|
|
||||||
} // namespace V2_0
|
|
||||||
} // namespace vehicle
|
|
||||||
} // namespace automotive
|
|
||||||
} // namespace hardware
|
|
||||||
} // namespace android
|
|
|
@ -452,8 +452,8 @@ TEST(HalClientVectorTest, basic) {
|
||||||
HalClientVector clients;
|
HalClientVector clients;
|
||||||
sp<IVehicleCallback> callback1 = new MockedVehicleCallback();
|
sp<IVehicleCallback> callback1 = new MockedVehicleCallback();
|
||||||
|
|
||||||
sp<HalClient> c1 = new HalClient(callback1, 10, 20);
|
sp<HalClient> c1 = new HalClient(callback1);
|
||||||
sp<HalClient> c2 = new HalClient(callback1, 10, 20);
|
sp<HalClient> c2 = new HalClient(callback1);
|
||||||
|
|
||||||
clients.addOrUpdate(c1);
|
clients.addOrUpdate(c1);
|
||||||
clients.addOrUpdate(c1);
|
clients.addOrUpdate(c1);
|
||||||
|
|
|
@ -33,7 +33,6 @@ LOCAL_EXPORT_C_INCLUDE_DIRS := \
|
||||||
$(LOCAL_PATH)/common/include
|
$(LOCAL_PATH)/common/include
|
||||||
|
|
||||||
LOCAL_SHARED_LIBRARIES := \
|
LOCAL_SHARED_LIBRARIES := \
|
||||||
libbinder \
|
|
||||||
libhidlbase \
|
libhidlbase \
|
||||||
libhidltransport \
|
libhidltransport \
|
||||||
libhwbinder \
|
libhwbinder \
|
||||||
|
@ -72,7 +71,6 @@ LOCAL_STATIC_LIBRARIES := \
|
||||||
|
|
||||||
LOCAL_SHARED_LIBRARIES := \
|
LOCAL_SHARED_LIBRARIES := \
|
||||||
libbase \
|
libbase \
|
||||||
libbinder \
|
|
||||||
libhidlbase \
|
libhidlbase \
|
||||||
libhidltransport \
|
libhidltransport \
|
||||||
libhwbinder \
|
libhwbinder \
|
||||||
|
@ -109,7 +107,6 @@ LOCAL_STATIC_LIBRARIES := \
|
||||||
|
|
||||||
LOCAL_SHARED_LIBRARIES := \
|
LOCAL_SHARED_LIBRARIES := \
|
||||||
libbase \
|
libbase \
|
||||||
libbinder \
|
|
||||||
libhidlbase \
|
libhidlbase \
|
||||||
libhidltransport \
|
libhidltransport \
|
||||||
libhwbinder \
|
libhwbinder \
|
||||||
|
|
Loading…
Reference in a new issue