/*
* Copyright (c) 2017, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _HAL_H_
#define _HAL_H_
/* HIDL Includes */
#include <android/hardware/tetheroffload/config/1.0/IOffloadConfig.h>
#include <android/hardware/tetheroffload/control/1.0/IOffloadControl.h>
#include <hidl/HidlTransportSupport.h>
/* External Includes */
#include <string>
#include <vector>
/* Internal Includes */
#include "CtUpdateAmbassador.h"
#include "IOffloadManager.h"
#include "IpaEventRelay.h"
#include "LocalLogBuffer.h"
/* Avoid the namespace litering everywhere */
using ::android::hardware::configureRpcThreadpool;
using ::android::hardware::joinRpcThreadpool;
using ::android::hardware::Return;
using ::android::hardware::hidl_handle;
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
using RET = ::IOffloadManager::RET;
using Prefix = ::IOffloadManager::Prefix;
using ::std::map;
using ::std::string;
using ::std::vector;
using ::android::hardware::tetheroffload::config::V1_0::IOffloadConfig;
using ::android::hardware::tetheroffload::control::V1_0::IOffloadControl;
using ::android::hardware::tetheroffload::control::V1_0::ITetheringOffloadCallback;
class HAL : public IOffloadControl, IOffloadConfig {
public:
/* Static Const Definitions */
static const uint32_t UDP_SUBSCRIPTIONS =
NF_NETLINK_CONNTRACK_NEW | NF_NETLINK_CONNTRACK_DESTROY;
static const uint32_t TCP_SUBSCRIPTIONS =
NF_NETLINK_CONNTRACK_UPDATE | NF_NETLINK_CONNTRACK_DESTROY;
/* Interface to IPACM */
/**
* @TODO This will likely need to be extended into a proper FactoryPattern
* when version bumps are needed.
*
* This makeIPAHAL function would move to a HALFactory class. Each HAL could
* then be versioned (class HAL_V1, class HAL_V2, etc) and inherit from a base class HAL.
* Then the version number in this function could be used to decide which one to return
* (if any).
*
* IPACM does not need to talk directly back to the returned HAL class. The other methods that
* IPACM needs to call are covered by registering the event listeners. If IPACM did need to
* talk directly back to the HAL object, without HAL registering a callback, these methods would
* need to be defined in the HAL base class.
*
* This would slightly break backwards compatibility so it should be discouraged; however, the
* base class could define a sane default implementation and not require that the child class
* implement this new method. This "sane default implementation" might only be possible in the
* case of listening to async events; if IPACM needs to query something, then this would not
* be backwards compatible and should be done via registering a callback so that IPACM knows
* this version of HAL supports that functionality.
*
* The above statements assume that only one version of the HAL will be instantiated at a time.
* Yet, it seems possible that a HAL_V1 and HAL_V2 service could both be registered, extending
* support to both old and new client implementations. It would be difficult to multiplex
* information from both versions. Additionally, IPACM would be responsible for instantiating
* two HALs (makeIPAHAL(1, ...); makeIPAHAL(2, ...)) which makes signaling between HAL versions
* (see next paragraph) slightly more difficult but not impossible.
*
* If concurrent versions of HAL are required, there will likely need to only be one master.
* Whichever version of HAL receives a client first may be allowed to take over control while
* other versions would be required to return failures (ETRYAGAIN: another version in use) until
* that version of the client relinquishes control. This should work seemlessly because we
* currently have an assumption that only one client will be present in system image.
* Logically, that client will have only a single version (or if it supports multiple, it will
* always attempt the newest version of HAL before falling back) and therefore no version
* collisions could possibly occur.
*
* Dislaimer:
* ==========
* Supporting multiple versions of an interface, in the same code base, at runtime, comes with a
* significant carrying cost and overhead in the form of developer headaches. This should not
* be done lightly and should be extensively scoped before committing to the effort.
*
* Perhaps the notion of minor version could be introduced to bridge the gaps created above.
* For example, 1.x and 1.y could be ran concurrently and supported from the same IPACM code.
* Yet, a major version update, would not be backwards compatible. This means that a 2.x HAL
* could not linked into the same IPACM code base as a 1.x HAL.
*/
static HAL* makeIPAHAL(int /* version */, IOffloadManager* /* mgr */);
/* IOffloadConfig */
Return<void> setHandles(
const hidl_handle& /* fd1 */,
const hidl_handle& /* fd2 */,
setHandles_cb /* hidl_cb */);
/* IOffloadControl */
Return<void> initOffload(
const ::android::sp<ITetheringOffloadCallback>& /* cb */,
initOffload_cb /* hidl_cb */);
Return<void> stopOffload(
stopOffload_cb /* hidl_cb */);
Return<void> setLocalPrefixes(
const hidl_vec<hidl_string>& /* prefixes */,
setLocalPrefixes_cb /* hidl_cb */);
Return<void> getForwardedStats(
const hidl_string& /* upstream */,
getForwardedStats_cb /* hidl_cb */);
Return<void> setDataLimit(
const hidl_string& /* upstream */,
uint64_t /* limit */,
setDataLimit_cb /* hidl_cb */);
Return<void> setUpstreamParameters(
const hidl_string& /* iface */,
const hidl_string& /* v4Addr */,
const hidl_string& /* v4Gw */,
const hidl_vec<hidl_string>& /* v6Gws */,
setUpstreamParameters_cb /* hidl_cb */);
Return<void> addDownstream(
const hidl_string& /* iface */,
const hidl_string& /* prefix */,
addDownstream_cb /* hidl_cb */);
Return<void> removeDownstream(
const hidl_string& /* iface */,
const hidl_string& /* prefix */,
removeDownstream_cb /* hidl_cb */);
/* Common */
Return<void> debug(const hidl_handle& /* fd */, const hidl_vec<hidl_string>& /* options */);
private:
typedef struct BoolResult {
bool success;
string errMsg;
} boolResult_t;
HAL(IOffloadManager* /* mgr */);
void registerAsSystemService();
void doLogcatDump();
static BoolResult makeInputCheckFailure(string /* customErr */);
static BoolResult ipaResultToBoolResult(RET /* in */);
static vector<string> convertHidlStrToStdStr(hidl_vec<hidl_string> /* in */);
void registerEventListeners();
void registerIpaCb();
void registerCtCb();
void unregisterEventListeners();
void unregisterIpaCb();
void unregisterCtCb();
void clearHandles();
bool isInitialized();
IOffloadManager* mIPA;
hidl_handle mHandle1;
hidl_handle mHandle2;
LocalLogBuffer mLogs;
::android::sp<ITetheringOffloadCallback> mCb;
IpaEventRelay *mCbIpa;
CtUpdateAmbassador *mCbCt;
}; /* HAL */
#endif /* _HAL_H_ */