Merge "Add tethering offload HAL call via JNI"
This commit is contained in:
@@ -18,10 +18,18 @@ LOCAL_SRC_FILES += \
|
||||
LOCAL_AIDL_INCLUDES += \
|
||||
system/netd/server/binder
|
||||
|
||||
LOCAL_JAVA_LIBRARIES := services.net
|
||||
LOCAL_STATIC_JAVA_LIBRARIES := tzdata_shared2 tzdata_update2
|
||||
LOCAL_PROTOC_OPTIMIZE_TYPE := nano
|
||||
|
||||
LOCAL_JAVA_LIBRARIES := \
|
||||
services.net \
|
||||
android.hidl.manager-V1.0-java \
|
||||
|
||||
LOCAL_STATIC_JAVA_LIBRARIES := \
|
||||
tzdata_shared2 \
|
||||
tzdata_update2 \
|
||||
android.hidl.base-V1.0-java-static \
|
||||
android.hardware.tetheroffload.control-V1.0-java-static \
|
||||
|
||||
ifneq ($(INCREMENTAL_BUILDS),)
|
||||
LOCAL_PROGUARD_ENABLED := disabled
|
||||
LOCAL_JACK_ENABLED := incremental
|
||||
|
||||
@@ -145,6 +145,7 @@ import com.android.server.connectivity.NetworkNotificationManager.NotificationTy
|
||||
import com.android.server.connectivity.PacManager;
|
||||
import com.android.server.connectivity.PermissionMonitor;
|
||||
import com.android.server.connectivity.Tethering;
|
||||
import com.android.server.connectivity.tethering.TetheringDependencies;
|
||||
import com.android.server.connectivity.Vpn;
|
||||
import com.android.server.net.BaseNetworkObserver;
|
||||
import com.android.server.net.LockdownVpnTracker;
|
||||
@@ -802,8 +803,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
mTestMode = mSystemProperties.get("cm.test.mode").equals("true")
|
||||
&& mSystemProperties.get("ro.build.type").equals("eng");
|
||||
|
||||
mTethering = new Tethering(mContext, mNetd, statsService, mPolicyManager,
|
||||
IoThread.get().getLooper(), new MockableSystemProperties());
|
||||
mTethering = makeTethering();
|
||||
|
||||
mPermissionMonitor = new PermissionMonitor(mContext, mNetd);
|
||||
|
||||
@@ -853,6 +853,14 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
mMultinetworkPolicyTracker.start();
|
||||
}
|
||||
|
||||
private Tethering makeTethering() {
|
||||
// TODO: Move other elements into @Overridden getters.
|
||||
final TetheringDependencies deps = new TetheringDependencies();
|
||||
return new Tethering(mContext, mNetd, mStatsService, mPolicyManager,
|
||||
IoThread.get().getLooper(), new MockableSystemProperties(),
|
||||
deps);
|
||||
}
|
||||
|
||||
private NetworkRequest createInternetRequestForTransport(
|
||||
int transportType, NetworkRequest.Type type) {
|
||||
NetworkCapabilities netCap = new NetworkCapabilities();
|
||||
|
||||
@@ -81,6 +81,7 @@ import com.android.server.connectivity.tethering.OffloadController;
|
||||
import com.android.server.connectivity.tethering.SimChangeListener;
|
||||
import com.android.server.connectivity.tethering.TetherInterfaceStateMachine;
|
||||
import com.android.server.connectivity.tethering.TetheringConfiguration;
|
||||
import com.android.server.connectivity.tethering.TetheringDependencies;
|
||||
import com.android.server.connectivity.tethering.UpstreamNetworkMonitor;
|
||||
import com.android.server.net.BaseNetworkObserver;
|
||||
|
||||
@@ -178,7 +179,8 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
|
||||
|
||||
public Tethering(Context context, INetworkManagementService nmService,
|
||||
INetworkStatsService statsService, INetworkPolicyManager policyManager,
|
||||
Looper looper, MockableSystemProperties systemProperties) {
|
||||
Looper looper, MockableSystemProperties systemProperties,
|
||||
TetheringDependencies deps) {
|
||||
mLocalLog.log("CONSTRUCTED");
|
||||
mContext = context;
|
||||
mNMService = nmService;
|
||||
@@ -194,7 +196,8 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
|
||||
mTetherMasterSM = new TetherMasterSM("TetherMaster", mLooper);
|
||||
mTetherMasterSM.start();
|
||||
|
||||
mOffloadController = new OffloadController(mTetherMasterSM.getHandler());
|
||||
mOffloadController = new OffloadController(mTetherMasterSM.getHandler(),
|
||||
deps.getOffloadHardwareInterface());
|
||||
mUpstreamNetworkMonitor = new UpstreamNetworkMonitor(
|
||||
mContext, mTetherMasterSM, TetherMasterSM.EVENT_UPSTREAM_CALLBACK);
|
||||
mForwardedDownstreams = new HashSet<>();
|
||||
@@ -1474,7 +1477,8 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
|
||||
handleInterfaceServingStateInactive(who);
|
||||
|
||||
if (mNotifyList.isEmpty()) {
|
||||
// transitions appropriately
|
||||
// This transitions us out of TetherModeAliveState,
|
||||
// either to InitialState or an error state.
|
||||
turnOffMasterTetherSettings();
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -18,10 +18,12 @@ package com.android.server.connectivity.tethering;
|
||||
|
||||
import android.net.LinkProperties;
|
||||
import android.os.Handler;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* A wrapper around hardware offload interface.
|
||||
* A class to encapsulate the business logic of programming the tethering
|
||||
* hardware offload interface.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@@ -29,25 +31,48 @@ public class OffloadController {
|
||||
private static final String TAG = OffloadController.class.getSimpleName();
|
||||
|
||||
private final Handler mHandler;
|
||||
private final OffloadHardwareInterface mHwInterface;
|
||||
private boolean mConfigInitialized;
|
||||
private boolean mControlInitialized;
|
||||
private LinkProperties mUpstreamLinkProperties;
|
||||
|
||||
public OffloadController(Handler h) {
|
||||
public OffloadController(Handler h, OffloadHardwareInterface hwi) {
|
||||
mHandler = h;
|
||||
mHwInterface = hwi;
|
||||
}
|
||||
|
||||
public void start() {
|
||||
// TODO: initOffload() and configure callbacks to be handled on our
|
||||
// preferred Handler.
|
||||
Log.d(TAG, "tethering offload not supported");
|
||||
if (started()) return;
|
||||
|
||||
if (!mConfigInitialized) {
|
||||
mConfigInitialized = mHwInterface.initOffloadConfig();
|
||||
if (!mConfigInitialized) {
|
||||
Log.d(TAG, "tethering offload config not supported");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Create and register ITetheringOffloadCallback.
|
||||
mControlInitialized = mHwInterface.initOffloadControl();
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
// TODO: stopOffload().
|
||||
mUpstreamLinkProperties = null;
|
||||
mHwInterface.stopOffloadControl();
|
||||
mControlInitialized = false;
|
||||
mConfigInitialized = false;
|
||||
}
|
||||
|
||||
public void setUpstreamLinkProperties(LinkProperties lp) {
|
||||
if (!started()) return;
|
||||
|
||||
// TODO: setUpstreamParameters().
|
||||
mUpstreamLinkProperties = lp;
|
||||
}
|
||||
|
||||
// TODO: public void addDownStream(...)
|
||||
|
||||
private boolean started() {
|
||||
return mConfigInitialized && mControlInitialized;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.
|
||||
*/
|
||||
|
||||
package com.android.server.connectivity.tethering;
|
||||
|
||||
import android.hardware.tetheroffload.control.V1_0.IOffloadControl;
|
||||
import android.hardware.tetheroffload.control.V1_0.IOffloadControl.stopOffloadCallback;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
|
||||
|
||||
/**
|
||||
* Capture tethering dependencies, for injection.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public class OffloadHardwareInterface {
|
||||
private static final String TAG = OffloadHardwareInterface.class.getSimpleName();
|
||||
|
||||
private static native boolean configOffload();
|
||||
|
||||
private IOffloadControl mOffloadControl;
|
||||
|
||||
public OffloadHardwareInterface() {}
|
||||
|
||||
public boolean initOffloadConfig() {
|
||||
return configOffload();
|
||||
}
|
||||
|
||||
// TODO: Extend this to take a TetheringControlCallback for registration.
|
||||
public boolean initOffloadControl() {
|
||||
if (mOffloadControl == null) {
|
||||
try {
|
||||
mOffloadControl = IOffloadControl.getService();
|
||||
} catch (RemoteException e) {
|
||||
Log.d(TAG, "tethering offload control not supported: " + e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: call mOffloadControl.initOffload(...callback...);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void stopOffloadControl() {
|
||||
if (mOffloadControl == null) return;
|
||||
|
||||
try {
|
||||
final stopOffloadCallback cb = new stopOffloadCallback() {
|
||||
@Override
|
||||
public void onValues(boolean success, String errMsg) {
|
||||
if (success) return;
|
||||
|
||||
Log.e(TAG, "stopOffload failed: " + errMsg);
|
||||
}
|
||||
};
|
||||
mOffloadControl.stopOffload(cb);
|
||||
} catch (RemoteException e) {
|
||||
Log.d(TAG, "failed to stopOffload: " + e);
|
||||
}
|
||||
mOffloadControl = null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.
|
||||
*/
|
||||
|
||||
package com.android.server.connectivity.tethering;
|
||||
|
||||
|
||||
/**
|
||||
* Capture tethering dependencies, for injection.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public class TetheringDependencies {
|
||||
public OffloadHardwareInterface getOffloadHardwareInterface() {
|
||||
return new OffloadHardwareInterface();
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,7 @@ LOCAL_SRC_FILES += \
|
||||
$(LOCAL_REL_DIR)/com_android_server_am_ActivityManagerService.cpp \
|
||||
$(LOCAL_REL_DIR)/com_android_server_AssetAtlasService.cpp \
|
||||
$(LOCAL_REL_DIR)/com_android_server_connectivity_Vpn.cpp \
|
||||
$(LOCAL_REL_DIR)/com_android_server_connectivity_tethering_OffloadHardwareInterface.cpp \
|
||||
$(LOCAL_REL_DIR)/com_android_server_ConsumerIrService.cpp \
|
||||
$(LOCAL_REL_DIR)/com_android_server_HardwarePropertiesManagerService.cpp \
|
||||
$(LOCAL_REL_DIR)/com_android_server_hdmi_HdmiCecController.cpp \
|
||||
@@ -58,6 +59,9 @@ LOCAL_SHARED_LIBRARIES += \
|
||||
liblog \
|
||||
libhardware \
|
||||
libhardware_legacy \
|
||||
libhidlbase \
|
||||
libhidltransport \
|
||||
libhwbinder \
|
||||
libkeystore_binder \
|
||||
libnativehelper \
|
||||
libutils \
|
||||
@@ -73,4 +77,5 @@ LOCAL_SHARED_LIBRARIES += \
|
||||
libEGL \
|
||||
libGLESv2 \
|
||||
libnetutils \
|
||||
android.hardware.tetheroffload.config@1.0 \
|
||||
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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 <errno.h>
|
||||
#include <error.h>
|
||||
#include <hidl/HidlSupport.h>
|
||||
#include <jni.h>
|
||||
#include <JNIHelp.h>
|
||||
#include <linux/netfilter/nfnetlink.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <sys/socket.h>
|
||||
#include <android-base/unique_fd.h>
|
||||
#include <android/hardware/tetheroffload/config/1.0/IOffloadConfig.h>
|
||||
|
||||
#define LOG_TAG "OffloadHardwareInterface"
|
||||
#include <utils/Log.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
using hardware::hidl_handle;
|
||||
using hardware::hidl_string;
|
||||
using hardware::tetheroffload::config::V1_0::IOffloadConfig;
|
||||
|
||||
namespace {
|
||||
|
||||
inline const sockaddr * asSockaddr(const sockaddr_nl *nladdr) {
|
||||
return reinterpret_cast<const sockaddr *>(nladdr);
|
||||
}
|
||||
|
||||
int conntrackSocket(unsigned groups) {
|
||||
base::unique_fd s(socket(AF_NETLINK, SOCK_DGRAM, NETLINK_NETFILTER));
|
||||
if (s.get() < 0) return -errno;
|
||||
|
||||
const struct sockaddr_nl bind_addr = {
|
||||
.nl_family = AF_NETLINK,
|
||||
.nl_pad = 0,
|
||||
.nl_pid = 0,
|
||||
.nl_groups = groups,
|
||||
};
|
||||
if (bind(s.get(), asSockaddr(&bind_addr), sizeof(bind_addr)) != 0) {
|
||||
return -errno;
|
||||
}
|
||||
|
||||
const struct sockaddr_nl kernel_addr = {
|
||||
.nl_family = AF_NETLINK,
|
||||
.nl_pad = 0,
|
||||
.nl_pid = 0,
|
||||
.nl_groups = groups,
|
||||
};
|
||||
if (connect(s.get(), asSockaddr(&kernel_addr), sizeof(kernel_addr)) != 0) {
|
||||
return -errno;
|
||||
}
|
||||
|
||||
return s.release();
|
||||
}
|
||||
|
||||
// Return a hidl_handle that owns the file descriptor owned by fd, and will
|
||||
// auto-close it (otherwise there would be double-close problems).
|
||||
//
|
||||
// Rely upon the compiler to eliminate the constexprs used for clarity.
|
||||
hidl_handle&& handleFromFileDescriptor(base::unique_fd fd) {
|
||||
hidl_handle h;
|
||||
|
||||
NATIVE_HANDLE_DECLARE_STORAGE(storage, 0, 0);
|
||||
static constexpr int kNumFds = 1;
|
||||
static constexpr int kNumInts = 0;
|
||||
native_handle_t *nh = native_handle_init(storage, kNumFds, kNumInts);
|
||||
nh->data[0] = fd.release();
|
||||
|
||||
static constexpr bool kTakeOwnership = true;
|
||||
h.setTo(nh, kTakeOwnership);
|
||||
|
||||
return std::move(h);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
static jboolean android_server_connectivity_tethering_OffloadHardwareInterface_configOffload(
|
||||
JNIEnv* /* env */) {
|
||||
sp<IOffloadConfig> configInterface = IOffloadConfig::getService();
|
||||
if (configInterface.get() == nullptr) {
|
||||
ALOGD("Could not find IOffloadConfig service.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Per the IConfigOffload definition:
|
||||
//
|
||||
// fd1 A file descriptor bound to the following netlink groups
|
||||
// (NF_NETLINK_CONNTRACK_NEW | NF_NETLINK_CONNTRACK_DESTROY).
|
||||
//
|
||||
// fd2 A file descriptor bound to the following netlink groups
|
||||
// (NF_NETLINK_CONNTRACK_UPDATE | NF_NETLINK_CONNTRACK_DESTROY).
|
||||
base::unique_fd
|
||||
fd1(conntrackSocket(NFNLGRP_CONNTRACK_NEW | NFNLGRP_CONNTRACK_DESTROY)),
|
||||
fd2(conntrackSocket(NFNLGRP_CONNTRACK_UPDATE | NFNLGRP_CONNTRACK_DESTROY));
|
||||
if (fd1.get() < 0 || fd2.get() < 0) {
|
||||
ALOGE("Unable to create conntrack handles: %d/%s", errno, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
hidl_handle h1(handleFromFileDescriptor(std::move(fd1))),
|
||||
h2(handleFromFileDescriptor(std::move(fd2)));
|
||||
|
||||
bool rval;
|
||||
hidl_string msg;
|
||||
configInterface->setHandles(h1, h2,
|
||||
[&rval, &msg](bool success, const hidl_string& errMsg) {
|
||||
rval = success;
|
||||
msg = errMsg;
|
||||
});
|
||||
if (!rval) {
|
||||
ALOGE("IOffloadConfig::setHandles() error: %s", msg.c_str());
|
||||
}
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
/*
|
||||
* JNI registration.
|
||||
*/
|
||||
static const JNINativeMethod gMethods[] = {
|
||||
/* name, signature, funcPtr */
|
||||
{ "configOffload", "()Z",
|
||||
(void*) android_server_connectivity_tethering_OffloadHardwareInterface_configOffload },
|
||||
};
|
||||
|
||||
int register_android_server_connectivity_tethering_OffloadHardwareInterface(JNIEnv* env) {
|
||||
return jniRegisterNativeMethods(env,
|
||||
"com/android/server/connectivity/tethering/OffloadHardwareInterface",
|
||||
gMethods, NELEM(gMethods));
|
||||
}
|
||||
|
||||
}; // namespace android
|
||||
@@ -40,6 +40,7 @@ int register_android_server_VibratorService(JNIEnv* env);
|
||||
int register_android_server_location_GnssLocationProvider(JNIEnv* env);
|
||||
int register_android_server_location_FlpHardwareProvider(JNIEnv* env);
|
||||
int register_android_server_connectivity_Vpn(JNIEnv* env);
|
||||
int register_android_server_connectivity_tethering_OffloadHardwareInterface(JNIEnv*);
|
||||
int register_android_server_hdmi_HdmiCecController(JNIEnv* env);
|
||||
int register_android_server_tv_TvUinputBridge(JNIEnv* env);
|
||||
int register_android_server_tv_TvInputHal(JNIEnv* env);
|
||||
@@ -78,6 +79,7 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
|
||||
register_android_server_location_GnssLocationProvider(env);
|
||||
register_android_server_location_FlpHardwareProvider(env);
|
||||
register_android_server_connectivity_Vpn(env);
|
||||
register_android_server_connectivity_tethering_OffloadHardwareInterface(env);
|
||||
register_android_server_AssetAtlasService(env);
|
||||
register_android_server_ConsumerIrService(env);
|
||||
register_android_server_BatteryStatsService(env);
|
||||
|
||||
@@ -56,6 +56,8 @@ import android.support.test.runner.AndroidJUnit4;
|
||||
import android.telephony.CarrierConfigManager;
|
||||
|
||||
import com.android.internal.util.test.BroadcastInterceptingContext;
|
||||
import com.android.server.connectivity.tethering.OffloadHardwareInterface;
|
||||
import com.android.server.connectivity.tethering.TetheringDependencies;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
@@ -78,7 +80,9 @@ public class TetheringTest {
|
||||
@Mock private INetworkStatsService mStatsService;
|
||||
@Mock private INetworkPolicyManager mPolicyManager;
|
||||
@Mock private MockableSystemProperties mSystemProperties;
|
||||
@Mock private OffloadHardwareInterface mOffloadHardwareInterface;
|
||||
@Mock private Resources mResources;
|
||||
@Mock private TetheringDependencies mTetheringDependencies;
|
||||
@Mock private UsbManager mUsbManager;
|
||||
@Mock private WifiManager mWifiManager;
|
||||
@Mock private CarrierConfigManager mCarrierConfigManager;
|
||||
@@ -138,8 +142,11 @@ public class TetheringTest {
|
||||
};
|
||||
mServiceContext.registerReceiver(mBroadcastReceiver,
|
||||
new IntentFilter(ConnectivityManager.ACTION_TETHER_STATE_CHANGED));
|
||||
when(mTetheringDependencies.getOffloadHardwareInterface())
|
||||
.thenReturn(mOffloadHardwareInterface);
|
||||
mTethering = new Tethering(mServiceContext, mNMService, mStatsService, mPolicyManager,
|
||||
mLooper.getLooper(), mSystemProperties);
|
||||
mLooper.getLooper(), mSystemProperties,
|
||||
mTetheringDependencies);
|
||||
}
|
||||
|
||||
@After
|
||||
|
||||
Reference in New Issue
Block a user