summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorandroid-build-team Robot <android-build-team-robot@google.com>2020-04-28 20:22:36 +0000
committerandroid-build-team Robot <android-build-team-robot@google.com>2020-04-28 20:22:36 +0000
commit6c983bd5dc46406187b3edf67a16f1ea460cb65f (patch)
tree7d6869a7e3639cc92aab6f34159cfaba1c94b1dd
parentf4f861d5b93e066a0c734a39f7c52a5b70a28d49 (diff)
parentb8fb19acda9835e0577cef9046c1d3124141b770 (diff)
downloadgoldfish-android12-mainline-tzdata-release.tar.gz
Change-Id: Ic72743535a20f380954a47049e6ad0738e638a34
-rw-r--r--Android.mk4
-rw-r--r--AndroidProducts.mk3
-rw-r--r--MultiDisplayProvider/Android.bp27
-rw-r--r--MultiDisplayProvider/Android.mk (renamed from input/qwerty2.idc)26
-rw-r--r--MultiDisplayProvider/jni/Android.bp39
-rw-r--r--MultiDisplayProvider/jni/Android.mk41
-rw-r--r--MultiDisplayProvider/src/com/android/emulator/multidisplay/MultiDisplayService.java1
-rw-r--r--arm32-vendor.mk19
-rw-r--r--arm64-vendor.mk20
-rw-r--r--camera/Android.mk19
-rw-r--r--camera/EmulatedFakeCamera3.cpp96
-rwxr-xr-xcamera/EmulatedQemuCamera.h3
-rw-r--r--camera/EmulatedQemuCamera3.h1
-rwxr-xr-xcamera/EmulatedQemuCameraDevice.h2
-rw-r--r--camera/EmulatorCameraTest.cpp91
-rw-r--r--camera/Thumbnail.cpp59
-rw-r--r--camera/fake-pipeline2/JpegCompressor.h2
-rw-r--r--camera/fake-pipeline2/Scene.cpp41
-rw-r--r--camera/fake-pipeline2/Scene.h34
-rw-r--r--camera/fake-pipeline2/Sensor.cpp86
-rw-r--r--camera/fake-pipeline2/Sensor.h4
-rw-r--r--camera/jpeg-stub/Compressor.cpp35
-rw-r--r--camera/media_codecs_google_video.xml (renamed from camera/media_codecs_google_video_default.xml)6
-rw-r--r--camera/media_codecs_google_video_v2.xml120
-rw-r--r--camera/qemu-pipeline3/QemuSensor.cpp21
-rw-r--r--camera/qemu-pipeline3/QemuSensor.h2
-rw-r--r--data/etc/advancedFeatures.ini4
-rw-r--r--data/etc/config.ini3
-rw-r--r--data/etc/config.ini.nexus53
-rw-r--r--data/etc/dummy.vbmeta.imgbin4096 -> 0 bytes
-rw-r--r--data/etc/encryptionkey.imgbin18874368 -> 1048576 bytes
-rw-r--r--data/etc/google/user/advancedFeatures.ini12
-rw-r--r--data/etc/google/userdebug/advancedFeatures.ini (renamed from data/etc/user/advancedFeatures.ini)4
-rwxr-xr-xdata/etc/x86/emulatoripbin497284 -> 0 bytes
-rw-r--r--dhcp/client/dhcpclient.cpp52
-rw-r--r--dhcp/client/dhcpclient.h9
-rw-r--r--dhcp/client/interface.cpp99
-rw-r--r--dhcp/client/interface.h3
-rw-r--r--dhcp/client/main.cpp9
-rw-r--r--dhcp/client/netlink.h22
-rw-r--r--dhcp/client/router.cpp21
-rw-r--r--dhcp/server/Android.mk22
-rw-r--r--dhcp/server/dhcpserver.cpp390
-rw-r--r--dhcp/server/dhcpserver.h75
-rw-r--r--dhcp/server/lease.h67
-rw-r--r--dhcp/server/log.h (renamed from network/wifi_forwarder/log.h)8
-rw-r--r--dhcp/server/main.cpp66
-rw-r--r--emulator-info.txt2
-rw-r--r--fingerprint/fingerprint.c2
-rw-r--r--fstab.goldfish1
-rw-r--r--fstab.ranchu1
-rw-r--r--fstab.ranchu.arm.ex10
-rw-r--r--fstab.ranchu.ex10
-rw-r--r--fstab.ranchu.initrd1
-rw-r--r--fstab.ranchu.initrd.arm.ex6
-rw-r--r--fstab.ranchu.initrd.ex7
-rw-r--r--fstab.ranchu.initrd.noavb5
-rw-r--r--fstab.ranchu.initrd.noavb.ex7
-rw-r--r--fstab.ranchu.noavb8
-rw-r--r--fstab.ranchu.noavb.ex10
-rw-r--r--fvp.mk103
-rw-r--r--fvpbase/BoardConfig.mk51
-rw-r--r--fvpbase/fstab.fvpbase8
-rw-r--r--fvpbase/fstab.fvpbase.initrd4
-rw-r--r--fvpbase/init.fvpbase.rc12
-rw-r--r--fvpbase/init.insmod.sh18
-rw-r--r--fvpbase/manifest.xml102
-rw-r--r--fvpbase/sepolicy/file.te1
-rw-r--r--fvpbase/sepolicy/file_contexts8
-rw-r--r--fvpbase/sepolicy/hal_graphics_allocator_default.te4
-rw-r--r--fvpbase/sepolicy/healthd.te4
-rw-r--r--fvpbase/sepolicy/init_insmod_sh.te14
-rw-r--r--fvpbase/sepolicy/property.te1
-rw-r--r--fvpbase/sepolicy/property_contexts1
-rw-r--r--fvpbase/sepolicy/surfaceflinger.te1
-rw-r--r--gatekeeper/Android.mk45
-rw-r--r--gatekeeper/SoftGateKeeper.h182
-rw-r--r--gatekeeper/SoftGateKeeperDevice.cpp116
-rw-r--r--gatekeeper/SoftGateKeeperDevice.h76
-rw-r--r--gatekeeper/module.cpp127
-rw-r--r--health/Android.bp6
-rw-r--r--include/qemu_pipe.h4
-rw-r--r--init.ranchu.rc33
-rw-r--r--input-mt/virtio_input_multi_touch_1.idc7
-rw-r--r--input-mt/virtio_input_multi_touch_2.idc12
-rw-r--r--input-mt/virtio_input_multi_touch_3.idc12
-rw-r--r--input-mt/virtio_input_multi_touch_4.idc12
-rw-r--r--input-mt/virtio_input_multi_touch_5.idc12
-rw-r--r--input/qwerty.kl132
-rw-r--r--input/virtio_input_multi_touch_1.idc1
-rw-r--r--kernel-tests/goldfish_kernel_tests_x86_64.mk4
-rw-r--r--kernel-tests/manifest.xml2
-rw-r--r--keymaster/strongbox/Android.bp1
-rw-r--r--manifest-arm.xml215
-rw-r--r--manifest.camera.xml11
-rw-r--r--manifest.gnss.xml11
-rw-r--r--manifest.sensors.xml11
-rw-r--r--manifest.xml71
-rw-r--r--network/netmgr/Android.bp5
-rw-r--r--network/netmgr/address_assigner.cpp151
-rw-r--r--network/netmgr/address_assigner.h (renamed from network/netmgr/bridge_builder.h)31
-rw-r--r--network/netmgr/bridge.cpp135
-rw-r--r--network/netmgr/bridge.h41
-rw-r--r--network/netmgr/bridge_builder.cpp43
-rw-r--r--network/netmgr/commands/wifi_command.cpp89
-rw-r--r--network/netmgr/commands/wifi_command.h6
-rw-r--r--network/netmgr/interface_state.h1
-rw-r--r--network/netmgr/main.cpp98
-rw-r--r--network/netmgr/monitor.cpp61
-rw-r--r--network/netmgr/monitor.h4
-rw-r--r--network/netmgr/timestamp.cpp (renamed from network/netmgr/utils.h)19
-rw-r--r--network/netmgr/timestamp.h (renamed from network/wifi_forwarder/poller.h)15
-rw-r--r--network/netmgr/utils.cpp37
-rw-r--r--network/wifi_forwarder/Android.bp46
-rw-r--r--network/wifi_forwarder/cache.h192
-rw-r--r--network/wifi_forwarder/frame.cpp370
-rw-r--r--network/wifi_forwarder/frame.h158
-rw-r--r--network/wifi_forwarder/frame_id.h63
-rw-r--r--network/wifi_forwarder/hwsim.h64
-rw-r--r--network/wifi_forwarder/ieee80211.h31
-rw-r--r--network/wifi_forwarder/local_connection.cpp392
-rw-r--r--network/wifi_forwarder/local_connection.h92
-rw-r--r--network/wifi_forwarder/macaddress.h73
-rw-r--r--network/wifi_forwarder/main.cpp33
-rw-r--r--network/wifi_forwarder/netlink_message.cpp61
-rw-r--r--network/wifi_forwarder/netlink_message.h59
-rw-r--r--network/wifi_forwarder/netlink_socket.cpp143
-rw-r--r--network/wifi_forwarder/netlink_socket.h82
-rw-r--r--network/wifi_forwarder/pollable.h62
-rw-r--r--network/wifi_forwarder/poller.cpp157
-rw-r--r--network/wifi_forwarder/remote_connection.cpp335
-rw-r--r--network/wifi_forwarder/remote_connection.h62
-rw-r--r--network/wifi_forwarder/wifi_forwarder.cpp258
-rw-r--r--network/wifi_forwarder/wifi_forwarder.h61
-rw-r--r--power/Android.mk1
-rw-r--r--ril/Android.mk1
-rw-r--r--ril/if_monitor.cpp107
-rw-r--r--ril/ipv6_monitor.cpp496
-rw-r--r--ril/ipv6_monitor.h47
-rw-r--r--ril/reference-ril.c156
-rw-r--r--sepolicy/common/OWNERS1
-rw-r--r--sepolicy/common/bootanim.te1
-rw-r--r--sepolicy/common/bug_map17
-rw-r--r--sepolicy/common/dhcpclient.te14
-rw-r--r--sepolicy/common/dhcprelay.te21
-rw-r--r--sepolicy/common/dhcpserver.te12
-rw-r--r--sepolicy/common/execns.te3
-rw-r--r--sepolicy/common/file_contexts10
-rw-r--r--sepolicy/common/goldfish_ip.te5
-rw-r--r--sepolicy/common/goldfish_setup.te8
-rw-r--r--sepolicy/common/hal_drm_clearkey.te2
-rw-r--r--sepolicy/common/hal_drm_widevine.te1
-rw-r--r--sepolicy/common/hal_graphics_allocator_default.te4
-rw-r--r--sepolicy/common/hal_graphics_composer_default.te3
-rw-r--r--sepolicy/common/ipv6proxy.te18
-rw-r--r--sepolicy/common/mediacodec.te3
-rw-r--r--sepolicy/common/netmgr.te26
-rw-r--r--sepolicy/common/property.te2
-rw-r--r--sepolicy/common/property_contexts2
-rw-r--r--sepolicy/common/radio.te1
-rw-r--r--sepolicy/common/rild.te7
-rw-r--r--sepolicy/common/surfaceflinger.te1
-rw-r--r--sepolicy/common/wifi_forwarder.te11
-rw-r--r--sepolicy/x86/OWNERS1
-rw-r--r--tnc/Android.bp32
-rw-r--r--tnc/main.cpp217
-rw-r--r--tools/Android.bp30
-rw-r--r--tools/Android.mk97
-rwxr-xr-xtools/extract_head_tail.sh20
-rwxr-xr-xtools/mk_combined_img.py105
-rwxr-xr-xtools/mk_qemu_image.sh7
-rwxr-xr-xtools/mk_vbmeta_boot_params.sh7
-rw-r--r--tools/prebuilt/gpt/1_3080/head.imgbin1048576 -> 0 bytes
-rw-r--r--tools/prebuilt/gpt/1_3080/tail.imgbin1048576 -> 0 bytes
-rw-r--r--ueventd.goldfish.rc1
-rw-r--r--ueventd.ranchu.rc4
-rw-r--r--vendor.mk101
-rw-r--r--wifi/createns/createns.cpp8
-rwxr-xr-xwifi/init.wifi.sh77
-rw-r--r--wifi/ipv6proxy/Android.mk24
-rw-r--r--wifi/ipv6proxy/address.cpp109
-rw-r--r--wifi/ipv6proxy/address.h63
-rw-r--r--wifi/ipv6proxy/interface.cpp143
-rw-r--r--wifi/ipv6proxy/interface.h54
-rw-r--r--wifi/ipv6proxy/log.cpp65
-rw-r--r--wifi/ipv6proxy/log.h32
-rw-r--r--wifi/ipv6proxy/main.cpp111
-rw-r--r--wifi/ipv6proxy/message.h32
-rw-r--r--wifi/ipv6proxy/namespace.cpp80
-rw-r--r--wifi/ipv6proxy/namespace.h (renamed from network/wifi_forwarder/hash.h)14
-rw-r--r--wifi/ipv6proxy/packet.cpp134
-rw-r--r--wifi/ipv6proxy/packet.h72
-rw-r--r--wifi/ipv6proxy/proxy.cpp262
-rw-r--r--wifi/ipv6proxy/proxy.h67
-rw-r--r--wifi/ipv6proxy/result.h (renamed from network/wifi_forwarder/result.h)26
-rw-r--r--wifi/ipv6proxy/router.cpp154
-rw-r--r--wifi/ipv6proxy/router.h52
-rw-r--r--wifi/ipv6proxy/socket.cpp272
-rw-r--r--wifi/ipv6proxy/socket.h156
-rw-r--r--wifi/wpa_supplicant_8_lib/Android.mk1
-rw-r--r--x86-vendor.mk5
-rw-r--r--x86_64-vendor.mk5
202 files changed, 4362 insertions, 5965 deletions
diff --git a/Android.mk b/Android.mk
index ebf71170..6350f27e 100644
--- a/Android.mk
+++ b/Android.mk
@@ -17,9 +17,6 @@
LOCAL_PATH := $(call my-dir)
ifeq ($(BUILD_QEMU_IMAGES),true)
- QEMU_CUSTOMIZATIONS := true
-endif
-ifeq ($(QEMU_CUSTOMIZATIONS),true)
INSTALLED_EMULATOR_INFO_TXT_TARGET := $(PRODUCT_OUT)/emulator-info.txt
emulator_info_txt := $(wildcard ${LOCAL_PATH}/emulator-info.txt)
@@ -28,7 +25,6 @@ ifeq ($(QEMU_CUSTOMIZATIONS),true)
$(hide) grep -v '#' $< > $@
$(call dist-for-goals, dist_files, $(INSTALLED_EMULATOR_INFO_TXT_TARGET))
- $(call dist-for-goals, sdk, $(INSTALLED_EMULATOR_INFO_TXT_TARGET))
subdir_makefiles=$(call first-makefiles-under,$(LOCAL_PATH))
$(foreach mk,$(subdir_makefiles),$(info including $(mk) ...)$(eval include $(mk)))
diff --git a/AndroidProducts.mk b/AndroidProducts.mk
index 3310b9c3..77183bba 100644
--- a/AndroidProducts.mk
+++ b/AndroidProducts.mk
@@ -1,4 +1,3 @@
PRODUCT_MAKEFILES := \
$(LOCAL_DIR)/kernel-tests/goldfish_kernel_tests_x86_64.mk \
- $(LOCAL_DIR)/sdk_phone_x86_vendor.mk \
- $(LOCAL_DIR)/fvp.mk
+ $(LOCAL_DIR)/sdk_phone_x86_vendor.mk
diff --git a/MultiDisplayProvider/Android.bp b/MultiDisplayProvider/Android.bp
deleted file mode 100644
index b0bd4387..00000000
--- a/MultiDisplayProvider/Android.bp
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (C) 2019 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.
-
-android_app {
- name: "MultiDisplayProvider",
-
- // Build the application.
-
- privileged: true,
- srcs: ["src/**/*.java"],
- platform_apis: true,
- certificate: "platform",
- resource_dirs: ["res"],
- jni_libs: ["libemulator_multidisplay_jni"],
- system_ext_specific: true,
-}
diff --git a/input/qwerty2.idc b/MultiDisplayProvider/Android.mk
index ca416651..21918a8e 100644
--- a/input/qwerty2.idc
+++ b/MultiDisplayProvider/Android.mk
@@ -12,17 +12,17 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-#
-# Emulator keyboard configuration file #2.
-#
-touch.deviceType = touchScreen
-touch.orientationAware = 1
-
-keyboard.layout = qwerty
-keyboard.characterMap = qwerty2
-keyboard.orientationAware = 0
-keyboard.builtIn = 1
-
-cursor.mode = navigation
-cursor.orientationAware = 1
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+# Build the application.
+LOCAL_MODULE_TAGS := optional
+LOCAL_PRIVILEGED_MODULE := true
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_PACKAGE_NAME := MultiDisplayProvider
+LOCAL_PRIVATE_PLATFORM_APIS := true
+LOCAL_CERTIFICATE := platform
+LOCAL_RESOURCE_DIR = $(LOCAL_PATH)/res
+LOCAL_JNI_SHARED_LIBRARIES := libemulator_multidisplay_jni
+include $(BUILD_PACKAGE)
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/MultiDisplayProvider/jni/Android.bp b/MultiDisplayProvider/jni/Android.bp
deleted file mode 100644
index 0fa0b2e1..00000000
--- a/MultiDisplayProvider/jni/Android.bp
+++ /dev/null
@@ -1,39 +0,0 @@
-// 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.
-
-cc_library_shared {
- name: "libemulator_multidisplay_jni",
-
- srcs: ["com_android_emulator_multidisplay.cpp"],
-
- include_dirs: ["system/core/base/include"],
-
- shared_libs: [
- "libandroid_runtime",
- "libnativehelper",
- "libcutils",
- "libutils",
- "liblog",
- "libui",
- "libgui",
- ],
-
- cflags: [
- "-Wall",
- "-Wextra",
- "-Wno-unused-parameter",
- ],
-
- system_ext_specific: true,
-}
diff --git a/MultiDisplayProvider/jni/Android.mk b/MultiDisplayProvider/jni/Android.mk
new file mode 100644
index 00000000..7ab3c03c
--- /dev/null
+++ b/MultiDisplayProvider/jni/Android.mk
@@ -0,0 +1,41 @@
+# 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ com_android_emulator_multidisplay.cpp
+
+LOCAL_C_INCLUDES += \
+ $(JNI_H_INCLUDE) \
+ system/core/base/include \
+
+LOCAL_SHARED_LIBRARIES := \
+ libandroid_runtime \
+ libnativehelper \
+ libcutils \
+ libutils \
+ liblog \
+ libui \
+ libgui \
+
+LOCAL_CFLAGS += -Wall -Wextra -Wno-unused-parameter
+
+LOCAL_MODULE := libemulator_multidisplay_jni
+LOCAL_MODULE_TAGS := optional
+LOCAL_PROGUARD_ENABLED := disabled
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/MultiDisplayProvider/src/com/android/emulator/multidisplay/MultiDisplayService.java b/MultiDisplayProvider/src/com/android/emulator/multidisplay/MultiDisplayService.java
index 923b94bf..608b590a 100644
--- a/MultiDisplayProvider/src/com/android/emulator/multidisplay/MultiDisplayService.java
+++ b/MultiDisplayProvider/src/com/android/emulator/multidisplay/MultiDisplayService.java
@@ -45,7 +45,6 @@ public class MultiDisplayService extends Service {
private static final int DEL = 2;
private static final int mFlags = DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC |
DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY |
- DisplayManager.VIRTUAL_DISPLAY_FLAG_ROTATES_WITH_CONTENT |
1 << 6 |//DisplayManager.VIRTUAL_DISPLAY_FLAG_SUPPORTS_TOUCH
1 << 9; //DisplayManager.VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS;
private DisplayManager mDisplayManager;
diff --git a/arm32-vendor.mk b/arm32-vendor.mk
index f447325e..9a34d5dd 100644
--- a/arm32-vendor.mk
+++ b/arm32-vendor.mk
@@ -1,3 +1,4 @@
+PRODUCT_KERNEL_VERSION := 4.4
PRODUCT_PROPERTY_OVERRIDES += \
vendor.rild.libpath=/vendor/lib/libgoldfish-ril.so
@@ -5,18 +6,14 @@ PRODUCT_PROPERTY_OVERRIDES += \
# Note: the following lines need to stay at the beginning so that it can
# take priority and override the rules it inherit from other mk files
# see copy file rules in core/Makefile
-ifeq ($(QEMU_USE_SYSTEM_EXT_PARTITIONS),true)
- PRODUCT_COPY_FILES += \
- device/generic/goldfish/fstab.ranchu.initrd.arm.ex:$(TARGET_COPY_OUT_RAMDISK)/fstab.ranchu \
- device/generic/goldfish/fstab.ranchu.arm.ex:$(TARGET_COPY_OUT_VENDOR)/etc/fstab.ranchu
-else
- PRODUCT_COPY_FILES += \
- device/generic/goldfish/fstab.ranchu.initrd.arm:$(TARGET_COPY_OUT_RAMDISK)/fstab.ranchu \
- device/generic/goldfish/fstab.ranchu.arm:$(TARGET_COPY_OUT_VENDOR)/etc/fstab.ranchu
-endif
-
+PRODUCT_SDK_ADDON_COPY_FILES += \
+ device/generic/goldfish/data/etc/advancedFeatures.ini.arm:images/armeabi-v7a/advancedFeatures.ini \
+ prebuilts/qemu-kernel/arm64/$(PRODUCT_KERNEL_VERSION)/kernel-qemu2:images/armeabi-v7a/kernel-ranchu-64
PRODUCT_COPY_FILES += \
- prebuilts/qemu-kernel/arm64/4.4/kernel-qemu2:kernel-ranchu-64 \
+ device/generic/goldfish/fstab.ranchu.initrd.arm:$(TARGET_COPY_OUT_RAMDISK)/fstab.ranchu \
+ device/generic/goldfish/manifest-arm.xml:$(TARGET_COPY_OUT_VENDOR)/manifest.xml \
device/generic/goldfish/data/etc/advancedFeatures.ini.arm:advancedFeatures.ini \
+ prebuilts/qemu-kernel/arm64/$(PRODUCT_KERNEL_VERSION)/kernel-qemu2:kernel-ranchu-64 \
+ device/generic/goldfish/fstab.ranchu.arm:$(TARGET_COPY_OUT_VENDOR)/etc/fstab.ranchu
EMULATOR_VENDOR_NO_GNSS := true
diff --git a/arm64-vendor.mk b/arm64-vendor.mk
index 6343136b..a05654d1 100644
--- a/arm64-vendor.mk
+++ b/arm64-vendor.mk
@@ -1,3 +1,4 @@
+PRODUCT_KERNEL_VERSION := 4.4
PRODUCT_PROPERTY_OVERRIDES += \
vendor.rild.libpath=/vendor/lib64/libgoldfish-ril.so
@@ -5,20 +6,15 @@ PRODUCT_PROPERTY_OVERRIDES += \
# Note: the following lines need to stay at the beginning so that it can
# take priority and override the rules it inherit from other mk files
# see copy file rules in core/Makefile
-ifeq ($(QEMU_USE_SYSTEM_EXT_PARTITIONS),true)
- PRODUCT_COPY_FILES += \
- device/generic/goldfish/fstab.ranchu.initrd.arm.ex:$(TARGET_COPY_OUT_RAMDISK)/fstab.ranchu \
- device/generic/goldfish/fstab.ranchu.arm.ex:$(TARGET_COPY_OUT_VENDOR)/etc/fstab.ranchu
-else
- PRODUCT_COPY_FILES += \
- device/generic/goldfish/fstab.ranchu.initrd.arm:$(TARGET_COPY_OUT_RAMDISK)/fstab.ranchu \
- device/generic/goldfish/fstab.ranchu.arm:$(TARGET_COPY_OUT_VENDOR)/etc/fstab.ranchu
-endif
-
+PRODUCT_SDK_ADDON_COPY_FILES += \
+ device/generic/goldfish/data/etc/advancedFeatures.ini.arm:images/arm64-v8a/advancedFeatures.ini \
+ prebuilts/qemu-kernel/arm64/$(PRODUCT_KERNEL_VERSION)/kernel-qemu2:images/arm64-v8a/kernel-ranchu
PRODUCT_COPY_FILES += \
- prebuilts/qemu-kernel/arm64/4.4/kernel-qemu2:kernel-ranchu \
+ device/generic/goldfish/fstab.ranchu.initrd.arm:$(TARGET_COPY_OUT_RAMDISK)/fstab.ranchu \
+ device/generic/goldfish/manifest-arm.xml:$(TARGET_COPY_OUT_VENDOR)/manifest.xml \
+ device/generic/goldfish/data/etc/advancedFeatures.ini.arm:advancedFeatures.ini \
+ prebuilts/qemu-kernel/arm64/$(PRODUCT_KERNEL_VERSION)/kernel-qemu2:kernel-ranchu \
device/generic/goldfish/fstab.ranchu.arm:$(TARGET_COPY_OUT_VENDOR)/etc/fstab.ranchu
-
EMULATOR_VENDOR_NO_GNSS := true
diff --git a/camera/Android.mk b/camera/Android.mk
index e5a1b046..088af564 100644
--- a/camera/Android.mk
+++ b/camera/Android.mk
@@ -122,27 +122,8 @@ LOCAL_SRC_FILES := ${emulator_camera_src}
LOCAL_MODULE := camera.ranchu
-# Symlink media profile configurations from /vendor/etc to /data/vendor/etc/
-LOCAL_POST_INSTALL_CMD := ln -sf /data/vendor/etc/media_codecs_google_video.xml $(PRODUCT_OUT)/vendor/etc/media_codecs_google_video.xml
include $(BUILD_SHARED_LIBRARY)
-# Emulator camera - test binary################################################
-
-include ${CLEAR_VARS}
-
-LOCAL_MODULE_RELATIVE_PATH := ${emulator_camera_module_relative_path}
-LOCAL_CFLAGS := ${emulator_camera_cflags}
-LOCAL_CLANG_CFLAGS += ${emulator_camera_clang_flags}
-
-LOCAL_SHARED_LIBRARIES := ${emulator_camera_shared_libraries}
-LOCAL_STATIC_LIBRARIES := ${emulator_camera_static_libraries}
-LOCAL_C_INCLUDES += ${emulator_camera_c_includes}
-LOCAL_SRC_FILES := ${emulator_camera_src}
-LOCAL_SRC_FILES += EmulatorCameraTest.cpp
-
-LOCAL_MODULE := emulatorcameratest
-include $(BUILD_EXECUTABLE)
-
# Build all subdirectories #####################################################
include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/camera/EmulatedFakeCamera3.cpp b/camera/EmulatedFakeCamera3.cpp
index 16d4d13b..625a0f18 100644
--- a/camera/EmulatedFakeCamera3.cpp
+++ b/camera/EmulatedFakeCamera3.cpp
@@ -66,13 +66,13 @@ const int32_t EmulatedFakeCamera3::kAvailableFormats[] = {
HAL_PIXEL_FORMAT_Y16
};
-const uint32_t EmulatedFakeCamera3::kAvailableRawSizes[6] = {
+const uint32_t EmulatedFakeCamera3::kAvailableRawSizes[4] = {
640, 480,
- 1280, 720,
- 1920, 1080
+ 1280, 720
// mSensorWidth, mSensorHeight
};
+
/**
* 3A constants
*/
@@ -706,7 +706,7 @@ const camera_metadata_t* EmulatedFakeCamera3::constructDefaultRequestSettings(
uint8_t afMode = 0;
- {
+ if (mFacingBack) {
switch (type) {
case CAMERA3_TEMPLATE_PREVIEW:
afMode = ANDROID_CONTROL_AF_MODE_CONTINUOUS_PICTURE;
@@ -730,8 +730,9 @@ const camera_metadata_t* EmulatedFakeCamera3::constructDefaultRequestSettings(
afMode = ANDROID_CONTROL_AF_MODE_AUTO;
break;
}
+ } else {
+ afMode = ANDROID_CONTROL_AF_MODE_OFF;
}
-
settings.update(ANDROID_CONTROL_AF_MODE, &afMode, 1);
settings.update(ANDROID_CONTROL_AF_REGIONS, controlRegions, 5);
@@ -1250,12 +1251,12 @@ status_t EmulatedFakeCamera3::constructStaticInfo() {
if (hasCapability(BACKWARD_COMPATIBLE)) {
// 5 cm min focus distance for back camera, infinity (fixed focus) for front
- const float minFocusDistance = 1.0/0.05;
+ const float minFocusDistance = mFacingBack ? 1.0/0.05 : 0.0;
ADD_STATIC_ENTRY(ANDROID_LENS_INFO_MINIMUM_FOCUS_DISTANCE,
&minFocusDistance, 1);
// 5 m hyperfocal distance for back camera, infinity (fixed focus) for front
- const float hyperFocalDistance = 1.0/5.0;
+ const float hyperFocalDistance = mFacingBack ? 1.0/5.0 : 0.0;
ADD_STATIC_ENTRY(ANDROID_LENS_INFO_HYPERFOCAL_DISTANCE,
&hyperFocalDistance, 1);
@@ -1286,7 +1287,8 @@ status_t EmulatedFakeCamera3::constructStaticInfo() {
// 90 degree rotation to align with long edge of a phone device that's by default portrait
static const float qO[] = { 0.707107f, 0.f, 0.f, 0.707107f};
- const float qF[] = {0, 1.f, 0, 0.f};
+ // Either a 180-degree rotation for back-facing, or no rotation for front-facing
+ const float qF[] = {0, (mFacingBack ? 1.f : 0.f), 0, (mFacingBack ? 0.f : 1.f)};
// Quarternion product, orientation change then facing
const float lensPoseRotation[] = {qO[0]*qF[0] - qO[1]*qF[1] - qO[2]*qF[2] - qO[3]*qF[3],
@@ -1362,18 +1364,22 @@ status_t EmulatedFakeCamera3::constructStaticInfo() {
const std::vector<int32_t> availableStreamConfigurationsBasic = {
HAL_PIXEL_FORMAT_BLOB, width, height, ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT,
- HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, 1280, 720, ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT,
- HAL_PIXEL_FORMAT_YCbCr_420_888, 1280, 720, ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT,
- HAL_PIXEL_FORMAT_BLOB, 1280, 720, ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT,
- HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, 640, 480, ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT,
- HAL_PIXEL_FORMAT_YCbCr_420_888, 640, 480, ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT,
- HAL_PIXEL_FORMAT_BLOB, 640, 480, ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT,
HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, 320, 240, ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT,
HAL_PIXEL_FORMAT_YCbCr_420_888, 320, 240, ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT,
HAL_PIXEL_FORMAT_BLOB, 320, 240, ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT,
HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, 176, 144, ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT,
HAL_PIXEL_FORMAT_YCbCr_420_888, 176, 144, ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT,
HAL_PIXEL_FORMAT_BLOB, 176, 144, ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT,
+ HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, 1280, 720, ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT,
+ HAL_PIXEL_FORMAT_YCbCr_420_888, 1280, 720, ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT,
+ HAL_PIXEL_FORMAT_BLOB, 1280, 720, ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT,
+ };
+
+ // Always need to include 640x480 in basic formats
+ const std::vector<int32_t> availableStreamConfigurationsBasic640 = {
+ HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, 640, 480, ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT,
+ HAL_PIXEL_FORMAT_YCbCr_420_888, 640, 480, ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT,
+ HAL_PIXEL_FORMAT_BLOB, 640, 480, ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT
};
const std::vector<int32_t> availableStreamConfigurationsRaw = {
@@ -1392,6 +1398,11 @@ status_t EmulatedFakeCamera3::constructStaticInfo() {
availableStreamConfigurations.insert(availableStreamConfigurations.end(),
availableStreamConfigurationsBasic.begin(),
availableStreamConfigurationsBasic.end());
+ if (width > 640) {
+ availableStreamConfigurations.insert(availableStreamConfigurations.end(),
+ availableStreamConfigurationsBasic640.begin(),
+ availableStreamConfigurationsBasic640.end());
+ }
}
if (hasCapability(RAW)) {
availableStreamConfigurations.insert(availableStreamConfigurations.end(),
@@ -1412,18 +1423,22 @@ status_t EmulatedFakeCamera3::constructStaticInfo() {
const std::vector<int64_t> availableMinFrameDurationsBasic = {
HAL_PIXEL_FORMAT_BLOB, width, height, Sensor::kFrameDurationRange[0],
- HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, 1280, 720, Sensor::kFrameDurationRange[0],
- HAL_PIXEL_FORMAT_YCbCr_420_888, 1280, 720, Sensor::kFrameDurationRange[0],
- HAL_PIXEL_FORMAT_BLOB, 1280, 720, Sensor::kFrameDurationRange[0],
- HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, 640, 480, Sensor::kFrameDurationRange[0],
- HAL_PIXEL_FORMAT_YCbCr_420_888, 640, 480, Sensor::kFrameDurationRange[0],
- HAL_PIXEL_FORMAT_BLOB, 640, 480, Sensor::kFrameDurationRange[0],
HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, 320, 240, Sensor::kFrameDurationRange[0],
HAL_PIXEL_FORMAT_YCbCr_420_888, 320, 240, Sensor::kFrameDurationRange[0],
HAL_PIXEL_FORMAT_BLOB, 320, 240, Sensor::kFrameDurationRange[0],
HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, 176, 144, Sensor::kFrameDurationRange[0],
HAL_PIXEL_FORMAT_YCbCr_420_888, 176, 144, Sensor::kFrameDurationRange[0],
HAL_PIXEL_FORMAT_BLOB, 176, 144, Sensor::kFrameDurationRange[0],
+ HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, 1280, 720, Sensor::kFrameDurationRange[0],
+ HAL_PIXEL_FORMAT_YCbCr_420_888, 1280, 720, Sensor::kFrameDurationRange[0],
+ HAL_PIXEL_FORMAT_BLOB, 1280, 720, Sensor::kFrameDurationRange[0],
+ };
+
+ // Always need to include 640x480 in basic formats
+ const std::vector<int64_t> availableMinFrameDurationsBasic640 = {
+ HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, 640, 480, Sensor::kFrameDurationRange[0],
+ HAL_PIXEL_FORMAT_YCbCr_420_888, 640, 480, Sensor::kFrameDurationRange[0],
+ HAL_PIXEL_FORMAT_BLOB, 640, 480, Sensor::kFrameDurationRange[0]
};
const std::vector<int64_t> availableMinFrameDurationsRaw = {
@@ -1442,6 +1457,11 @@ status_t EmulatedFakeCamera3::constructStaticInfo() {
availableMinFrameDurations.insert(availableMinFrameDurations.end(),
availableMinFrameDurationsBasic.begin(),
availableMinFrameDurationsBasic.end());
+ if (width > 640) {
+ availableMinFrameDurations.insert(availableMinFrameDurations.end(),
+ availableMinFrameDurationsBasic640.begin(),
+ availableMinFrameDurationsBasic640.end());
+ }
}
if (hasCapability(RAW)) {
availableMinFrameDurations.insert(availableMinFrameDurations.end(),
@@ -1462,27 +1482,31 @@ status_t EmulatedFakeCamera3::constructStaticInfo() {
const std::vector<int64_t> availableStallDurationsBasic = {
HAL_PIXEL_FORMAT_BLOB, width, height, Sensor::kFrameDurationRange[0],
- HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, 1280, 720, 0,
- HAL_PIXEL_FORMAT_YCbCr_420_888, 1280, 720, 0,
- HAL_PIXEL_FORMAT_BLOB, 1280, 720, Sensor::kFrameDurationRange[0],
- HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, 640, 480, 0,
- HAL_PIXEL_FORMAT_YCbCr_420_888, 640, 480, 0,
- HAL_PIXEL_FORMAT_BLOB, 640, 480, Sensor::kFrameDurationRange[0],
HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, 320, 240, 0,
HAL_PIXEL_FORMAT_YCbCr_420_888, 320, 240, 0,
HAL_PIXEL_FORMAT_RGBA_8888, 320, 240, 0,
HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, 176, 144, 0,
HAL_PIXEL_FORMAT_YCbCr_420_888, 176, 144, 0,
HAL_PIXEL_FORMAT_RGBA_8888, 176, 144, 0,
+ HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, 1280, 720, 0,
+ HAL_PIXEL_FORMAT_YCbCr_420_888, 1280, 720, 0,
+ HAL_PIXEL_FORMAT_RGBA_8888, 1280, 720, 0,
+ };
+
+ // Always need to include 640x480 in basic formats
+ const std::vector<int64_t> availableStallDurationsBasic640 = {
+ HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, 640, 480, 0,
+ HAL_PIXEL_FORMAT_YCbCr_420_888, 640, 480, 0,
+ HAL_PIXEL_FORMAT_BLOB, 640, 480, Sensor::kFrameDurationRange[0]
};
const std::vector<int64_t> availableStallDurationsRaw = {
- HAL_PIXEL_FORMAT_RAW16, width, height, Sensor::kFrameDurationRange[0]
+ HAL_PIXEL_FORMAT_RAW16, 640, 480, Sensor::kFrameDurationRange[0]
};
const std::vector<int64_t> availableStallDurationsBurst = {
- HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, width, height, 0,
- HAL_PIXEL_FORMAT_YCbCr_420_888, width, height, 0,
- HAL_PIXEL_FORMAT_RGBA_8888, width, height, 0
+ HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, 640, 480, 0,
+ HAL_PIXEL_FORMAT_YCbCr_420_888, 640, 480, 0,
+ HAL_PIXEL_FORMAT_RGBA_8888, 640, 480, 0
};
std::vector<int64_t> availableStallDurations;
@@ -1491,6 +1515,11 @@ status_t EmulatedFakeCamera3::constructStaticInfo() {
availableStallDurations.insert(availableStallDurations.end(),
availableStallDurationsBasic.begin(),
availableStallDurationsBasic.end());
+ if (width > 640) {
+ availableStallDurations.insert(availableStallDurations.end(),
+ availableStallDurationsBasic640.begin(),
+ availableStallDurationsBasic640.end());
+ }
}
if (hasCapability(RAW)) {
availableStallDurations.insert(availableStallDurations.end(),
@@ -1674,7 +1703,7 @@ status_t EmulatedFakeCamera3::constructStaticInfo() {
ANDROID_CONTROL_AF_MODE_OFF
};
- if (hasCapability(BACKWARD_COMPATIBLE)) {
+ if (mFacingBack && hasCapability(BACKWARD_COMPATIBLE)) {
ADD_STATIC_ENTRY(ANDROID_CONTROL_AF_AVAILABLE_MODES,
availableAfModesBack, sizeof(availableAfModesBack));
} else {
@@ -2125,6 +2154,11 @@ status_t EmulatedFakeCamera3::doFakeAF(CameraMetadata &settings) {
case ANDROID_CONTROL_AF_MODE_MACRO:
case ANDROID_CONTROL_AF_MODE_CONTINUOUS_VIDEO:
case ANDROID_CONTROL_AF_MODE_CONTINUOUS_PICTURE:
+ if (!mFacingBack) {
+ // Always report INACTIVE for front Emulated Camera
+ mAfState = ANDROID_CONTROL_AF_STATE_INACTIVE;
+ return OK;
+ }
break;
default:
ALOGE("%s: Emulator doesn't support AF mode %d",
diff --git a/camera/EmulatedQemuCamera.h b/camera/EmulatedQemuCamera.h
index 83397ef3..1b826c7f 100755
--- a/camera/EmulatedQemuCamera.h
+++ b/camera/EmulatedQemuCamera.h
@@ -66,9 +66,6 @@ protected:
/* Supported frame dimensions reported by the camera device. */
String8 mFrameDims;
-
-private:
- using EmulatedCamera::Initialize;
};
}; /* namespace android */
diff --git a/camera/EmulatedQemuCamera3.h b/camera/EmulatedQemuCamera3.h
index 5656f539..c26f0379 100644
--- a/camera/EmulatedQemuCamera3.h
+++ b/camera/EmulatedQemuCamera3.h
@@ -120,7 +120,6 @@ private:
* Handle interrupt events from the sensor.
*/
void onQemuSensorEvent(uint32_t frameNumber, Event e, nsecs_t timestamp);
- using EmulatedCamera3::Initialize;
private:
/**************************************************************************
diff --git a/camera/EmulatedQemuCameraDevice.h b/camera/EmulatedQemuCameraDevice.h
index 2b2dfc9e..1cabd6f1 100755
--- a/camera/EmulatedQemuCameraDevice.h
+++ b/camera/EmulatedQemuCameraDevice.h
@@ -132,7 +132,7 @@ private:
* pair. */
using FrameBufferPair = std::pair<uint8_t*, uint32_t*>;
FrameBufferPair mFrameBufferPairs[2];
- using EmulatedCameraDevice::Initialize;
+
};
}; /* namespace android */
diff --git a/camera/EmulatorCameraTest.cpp b/camera/EmulatorCameraTest.cpp
deleted file mode 100644
index 684e6d78..00000000
--- a/camera/EmulatorCameraTest.cpp
+++ /dev/null
@@ -1,91 +0,0 @@
-#include <iostream>
-#include <string>
-#include <vector>
-
-#include "fake-pipeline2/Base.h"
-#include "QemuClient.h"
-
-#include <linux/videodev2.h>
-#include <utils/Timers.h>
-
-using namespace android;
-
-// Test the capture speed of qemu camera, e.g., webcam and virtual scene
-int main(int argc, char* argv[]) {
- uint32_t pixFmt;
- if (!strncmp(argv[1], "RGB", 3)) {
- pixFmt = V4L2_PIX_FMT_RGB32;
- } else if (!strncmp(argv[1], "NV21", 3)) {
- pixFmt = V4L2_PIX_FMT_NV21;
- } else if (!strncmp(argv[1], "YV12", 3)) {
- pixFmt = V4L2_PIX_FMT_YVU420;
- } else {
- printf("format error, use RGB, NV21 or YV12");
- return -1;
- }
- uint32_t width = atoi(argv[2]);
- uint32_t height = atoi(argv[3]);
- std::string deviceName;
- if (!strncmp(argv[4], "web", 3)) {
- deviceName = "name=/dev/video0";
- } else if (!strncmp(argv[4], "vir", 3)) {
- deviceName = "name=virtualscene";
- } else {
- printf("device error, use web or virtual");
- return -1;
- }
-
- // Open qemu pipe
- CameraQemuClient client;
- int ret = client.connectClient(deviceName.c_str());
- if (ret != NO_ERROR) {
- printf("Failed to connect device\n");
- return -1;
- }
- ret = client.queryConnect();
- if (ret == NO_ERROR) {
- printf("Connected to device\n");
- } else {
- printf("Failed to connect device\n");
- return -1;
- }
-
- // Caputre ASAP
- ret = client.queryStart(pixFmt, width, height);
- if (ret != NO_ERROR) {
- printf("Failed to configure device for query\n");
- return -1;
- }
- size_t bufferSize;
- if (pixFmt == V4L2_PIX_FMT_RGB32) {
- bufferSize = width * height * 4;
- } else {
- bufferSize = width * height * 12 / 8;
- }
- std::vector<char> buffer(bufferSize, 0);
- float whiteBalance[] = {1.0f, 1.0f, 1.0f};
- float exposureCompensation = 1.0f;
- std::vector<nsecs_t> report;
- size_t repeated = 100;
- for (int i = 0 ; i < repeated; i++) {
- nsecs_t start = systemTime();
- client.queryFrame(buffer.data(), nullptr, 0, bufferSize,
- whiteBalance[0], whiteBalance[1], whiteBalance[2],
- exposureCompensation, nullptr);
- nsecs_t end = systemTime();
- report.push_back(end - start);
- }
-
- // Report
- nsecs_t average, sum = 0;
- for (int i = 0; i < repeated; i++) {
- sum += report[i];
- }
- average = sum / repeated;
- printf("Report for reading %d frames\n", repeated);
- printf("\ttime total: %lld\n", sum);
- printf("\tframe average: %lld\n", average);
-
- return 0;
-}
-
diff --git a/camera/Thumbnail.cpp b/camera/Thumbnail.cpp
index d3472a4b..8f901a31 100644
--- a/camera/Thumbnail.cpp
+++ b/camera/Thumbnail.cpp
@@ -27,14 +27,40 @@
#include <vector>
/*
- * The YU12 format is a YUV format with an 8-bit Y-component and the U and V
+ * The NV21 format is a YUV format with an 8-bit Y-component and the U and V
* components are stored as 8 bits each but they are shared between a block of
* 2x2 pixels. So when calculating bits per pixel the 16 bits of U and V are
* shared between 4 pixels leading to 4 bits of U and V per pixel. Together
* with the 8 bits of Y this gives us 12 bits per pixel..
*
- * The components are not grouped by pixels but separated into one Y-plane, one
- * U-plane and one V-plane.
+ * The components are not grouped by pixels but separated into one Y-plane and
+ * one interleaved U and V-plane. The first half of the byte sequence is all of
+ * the Y data laid out in a linear fashion. After that the interleaved U and V-
+ * plane starts with one byte of V followed by one byte of U followed by one
+ * byte of V and so on. Each byte of U or V is associated with a 2x2 pixel block
+ * in a linear fashion.
+ *
+ * For an 8 by 4 pixel image the layout would be:
+ *
+ * +-----+-----+-----+-----+-----+-----+-----+-----+
+ * | Y0 | Y1 | Y2 | Y3 | Y4 | Y5 | Y6 | Y7 |
+ * +-----+-----+-----+-----+-----+-----+-----+-----+
+ * | Y8 | Y9 | Y10 | Y11 | Y12 | Y13 | Y14 | Y15 |
+ * +-----+-----+-----+-----+-----+-----+-----+-----+
+ * | Y16 | Y17 | Y18 | Y19 | Y20 | Y21 | Y22 | Y23 |
+ * +-----+-----+-----+-----+-----+-----+-----+-----+
+ * | Y24 | Y25 | Y26 | Y27 | Y28 | Y29 | Y30 | Y31 |
+ * +-----+-----+-----+-----+-----+-----+-----+-----+
+ * | V0 | U0 | V1 | U1 | V2 | U2 | V3 | U3 |
+ * +-----+-----+-----+-----+-----+-----+-----+-----+
+ * | V4 | U4 | V5 | U5 | V6 | U6 | V7 | U7 |
+ * +-----+-----+-----+-----+-----+-----+-----+-----+
+ *
+ * In this image V0 and U0 are the V and U components for the 2x2 block of
+ * pixels whose Y components are Y0, Y1, Y8 and Y9. V1 and U1 are matched with
+ * the Y components Y2, Y3, Y10, Y11, and so on for that row. For the next row
+ * of V and U the V4 and U4 components would be paired with Y16, Y17, Y24 and
+ * Y25.
*/
namespace android {
@@ -43,9 +69,20 @@ static bool createRawThumbnail(const unsigned char* sourceImage,
int sourceWidth, int sourceHeight,
int thumbnailWidth, int thumbnailHeight,
std::vector<unsigned char>* thumbnail) {
+ // Deinterleave the U and V planes into separate planes, this is because
+ // libyuv requires the planes to be separate when scaling
+ const size_t sourceUVPlaneSize = (sourceWidth * sourceHeight) / 4;
+ // Put both U and V planes in one buffer, one after the other, to reduce
+ // memory fragmentation and number of allocations
+ std::vector<unsigned char> sourcePlanes(sourceUVPlaneSize * 2);
const unsigned char* ySourcePlane = sourceImage;
- const unsigned char* uSourcePlane = sourceImage + sourceWidth * sourceHeight;
- const unsigned char* vSourcePlane = uSourcePlane + sourceWidth * sourceHeight / 4;
+ unsigned char* uSourcePlane = &sourcePlanes[0];
+ unsigned char* vSourcePlane = &sourcePlanes[sourceUVPlaneSize];
+
+ for (size_t i = 0; i < sourceUVPlaneSize; ++i) {
+ vSourcePlane[i] = sourceImage[sourceWidth * sourceHeight + i * 2 + 0];
+ uSourcePlane[i] = sourceImage[sourceWidth * sourceHeight + i * 2 + 1];
+ }
// Create enough space in the output vector for the result
thumbnail->resize((thumbnailWidth * thumbnailHeight * 12) / 8);
@@ -55,8 +92,8 @@ static bool createRawThumbnail(const unsigned char* sourceImage,
const size_t destUVPlaneSize = (thumbnailWidth * thumbnailHeight) / 4;
std::vector<unsigned char> destPlanes(destUVPlaneSize * 2);
unsigned char* yDestPlane = &(*thumbnail)[0];
- unsigned char* uDestPlane = yDestPlane + thumbnailWidth * thumbnailHeight;
- unsigned char* vDestPlane = uDestPlane + thumbnailWidth * thumbnailHeight / 4;
+ unsigned char* uDestPlane = &destPlanes[0];
+ unsigned char* vDestPlane = &destPlanes[destUVPlaneSize];
// The strides for the U and V planes are half the width because the U and V
// components are common to 2x2 pixel blocks
@@ -75,6 +112,14 @@ static bool createRawThumbnail(const unsigned char* sourceImage,
return false;
}
+ // Now we need to interleave the downscaled U and V planes into the
+ // output buffer to make it NV21 encoded
+ const size_t uvPlanesOffset = thumbnailWidth * thumbnailHeight;
+ for (size_t i = 0; i < destUVPlaneSize; ++i) {
+ (*thumbnail)[uvPlanesOffset + i * 2 + 0] = vDestPlane[i];
+ (*thumbnail)[uvPlanesOffset + i * 2 + 1] = uDestPlane[i];
+ }
+
return true;
}
diff --git a/camera/fake-pipeline2/JpegCompressor.h b/camera/fake-pipeline2/JpegCompressor.h
index 7a78ef79..493e4a63 100644
--- a/camera/fake-pipeline2/JpegCompressor.h
+++ b/camera/fake-pipeline2/JpegCompressor.h
@@ -77,7 +77,7 @@ class JpegCompressor: private Thread, public virtual RefBase {
status_t reserve();
// TODO: Measure this
- static const size_t kMaxJpegSize = 675000;
+ static const size_t kMaxJpegSize = 300000;
private:
Mutex mBusyMutex;
diff --git a/camera/fake-pipeline2/Scene.cpp b/camera/fake-pipeline2/Scene.cpp
index 1bfd216a..0fea38e9 100644
--- a/camera/fake-pipeline2/Scene.cpp
+++ b/camera/fake-pipeline2/Scene.cpp
@@ -42,8 +42,6 @@ namespace android {
const int Scene::kSceneWidth = 20;
const int Scene::kSceneHeight = 20;
-const int Scene::kMaxWidth = 20;
-const int Scene::kMaxHeight = 20;
const uint8_t Scene::kScene[Scene::kSceneWidth * Scene::kSceneHeight] = {
// 5 10 15 20
@@ -341,15 +339,44 @@ void Scene::calculateScene(nsecs_t time) {
setReadoutPixel(0,0);
}
+void Scene::setReadoutPixel(int x, int y) {
+ mCurrentX = x;
+ mCurrentY = y;
+ mSubX = (x + mOffsetX + mHandshakeX) % mMapDiv;
+ mSubY = (y + mOffsetY + mHandshakeY) % mMapDiv;
+ mSceneX = (x + mOffsetX + mHandshakeX) / mMapDiv;
+ mSceneY = (y + mOffsetY + mHandshakeY) / mMapDiv;
+ mSceneIdx = mSceneY * kSceneWidth + mSceneX;
+ mCurrentSceneMaterial = &(mCurrentColors[kScene[mSceneIdx]]);
+}
+
+const uint32_t* Scene::getPixelElectrons() {
+ const uint32_t *pixel = mCurrentSceneMaterial;
+ mCurrentX++;
+ mSubX++;
+ if (mCurrentX >= mSensorWidth) {
+ mCurrentX = 0;
+ mCurrentY++;
+ if (mCurrentY >= mSensorHeight) mCurrentY = 0;
+ setReadoutPixel(mCurrentX, mCurrentY);
+ } else if (mSubX > mMapDiv) {
+ mSceneIdx++;
+ mSceneX++;
+ mCurrentSceneMaterial = &(mCurrentColors[kScene[mSceneIdx]]);
+ mSubX = 0;
+ }
+ return pixel;
+}
+
// Handshake model constants.
// Frequencies measured in a nanosecond timebase
-const float Scene::kHorizShakeFreq1 = 2 * M_PI * 1 / 1e9; // 1 Hz
-const float Scene::kHorizShakeFreq2 = 2 * M_PI * 1 / 1e9; // 1 Hz
-const float Scene::kVertShakeFreq1 = 2 * M_PI * 1 / 1e9; // 1 Hz
-const float Scene::kVertShakeFreq2 = 2 * M_PI * 1 / 1e9; // 1 Hz
+const float Scene::kHorizShakeFreq1 = 2 * M_PI * 2 / 1e9; // 2 Hz
+const float Scene::kHorizShakeFreq2 = 2 * M_PI * 13 / 1e9; // 13 Hz
+const float Scene::kVertShakeFreq1 = 2 * M_PI * 3 / 1e9; // 3 Hz
+const float Scene::kVertShakeFreq2 = 2 * M_PI * 11 / 1e9; // 1 Hz
const float Scene::kFreq1Magnitude = 5;
const float Scene::kFreq2Magnitude = 1;
-const float Scene::kShakeFraction = 0.2; // As a fraction of a scene tile
+const float Scene::kShakeFraction = 0.03; // As a fraction of a scene tile
// RGB->YUV, Jpeg standard
const float Scene::kRgb2Yuv[12] = {
diff --git a/camera/fake-pipeline2/Scene.h b/camera/fake-pipeline2/Scene.h
index aec53f7c..3a7a001a 100644
--- a/camera/fake-pipeline2/Scene.h
+++ b/camera/fake-pipeline2/Scene.h
@@ -64,38 +64,13 @@ class Scene {
void calculateScene(nsecs_t time);
// Set sensor pixel readout location.
- inline void setReadoutPixel(int x, int y) {
- mCurrentX = x;
- mCurrentY = y;
- mSubX = (x + mOffsetX + mHandshakeX) % mMapDiv;
- mSubY = (y + mOffsetY + mHandshakeY) % mMapDiv;
- mSceneX = (x + mOffsetX + mHandshakeX) / mMapDiv;
- mSceneY = (y + mOffsetY + mHandshakeY) / mMapDiv;
- mSceneIdx = mSceneY * kSceneWidth + mSceneX;
- mCurrentSceneMaterial = &(mCurrentColors[kScene[mSceneIdx]]);
- }
+ void setReadoutPixel(int x, int y);
// Get sensor response in physical units (electrons) for light hitting the
// current readout pixel, after passing through color filters. The readout
// pixel will be auto-incremented. The returned array can be indexed with
// ColorChannels.
- inline const uint32_t* getPixelElectrons() {
- const uint32_t *pixel = mCurrentSceneMaterial;
- mCurrentX++;
- mSubX++;
- if (mCurrentX >= mSensorWidth) {
- mCurrentX = 0;
- mCurrentY++;
- if (mCurrentY >= mSensorHeight) mCurrentY = 0;
- setReadoutPixel(mCurrentX, mCurrentY);
- } else if (mSubX > mMapDiv) {
- mSceneIdx++;
- mSceneX++;
- mCurrentSceneMaterial = &(mCurrentColors[kScene[mSceneIdx]]);
- mSubX = 0;
- }
- return pixel;
- }
+ const uint32_t* getPixelElectrons();
enum ColorChannels {
R = 0,
@@ -108,11 +83,6 @@ class Scene {
NUM_CHANNELS
};
- // Max scene width and height. Calculation for larger scene consumes much
- // CPU resource. So we put a limit here.
- static const int kMaxWidth;
- static const int kMaxHeight;
-
private:
// Sensor color filtering coefficients in XYZ
float mFilterR[3];
diff --git a/camera/fake-pipeline2/Sensor.cpp b/camera/fake-pipeline2/Sensor.cpp
index ab984efe..c5552754 100644
--- a/camera/fake-pipeline2/Sensor.cpp
+++ b/camera/fake-pipeline2/Sensor.cpp
@@ -17,7 +17,6 @@
//#define LOG_NDEBUG 0
//#define LOG_NNDEBUG 0
#define LOG_TAG "EmulatedCamera2_Sensor"
-#define ATRACE_TAG ATRACE_TAG_CAMERA
#ifdef LOG_NNDEBUG
#define ALOGVV(...) ALOGV(__VA_ARGS__)
@@ -26,7 +25,6 @@
#endif
#include <log/log.h>
-#include <utils/Trace.h>
#include "../EmulatedFakeCamera2.h"
#include "Sensor.h"
@@ -78,7 +76,6 @@ const float Sensor::kReadNoiseVarAfterGain =
const int32_t Sensor::kSensitivityRange[2] = {100, 1600};
const uint32_t Sensor::kDefaultSensitivity = 100;
-
/** A few utility functions for math, normal distributions */
// Take advantage of IEEE floating-point format to calculate an approximate
@@ -111,9 +108,7 @@ Sensor::Sensor(uint32_t width, uint32_t height):
mFrameNumber(0),
mCapturedBuffers(NULL),
mListener(NULL),
- mSceneWidth((width < Scene::kMaxWidth) ? width : Scene::kMaxWidth),
- mSceneHeight((height < Scene::kMaxHeight) ? height : Scene::kMaxHeight),
- mScene(mSceneWidth, mSceneHeight, kElectronsPerLuxSecond)
+ mScene(width, height, kElectronsPerLuxSecond)
{
ALOGV("Sensor created with pixel array %d x %d", width, height);
}
@@ -229,7 +224,6 @@ status_t Sensor::readyToRun() {
}
bool Sensor::threadLoop() {
- ATRACE_CALL();
/**
* Sensor capture operation main loop.
*
@@ -353,7 +347,7 @@ bool Sensor::threadLoop() {
}
break;
case HAL_PIXEL_FORMAT_YCbCr_420_888:
- captureYU12(b.img, gain, b.width, b.height);
+ captureNV21(b.img, gain, b.width, b.height);
break;
case HAL_PIXEL_FORMAT_YV12:
// TODO:
@@ -390,7 +384,6 @@ bool Sensor::threadLoop() {
};
void Sensor::captureRaw(uint8_t *img, uint32_t gain, uint32_t stride) {
- ATRACE_CALL();
float totalGain = gain/100.0 * kBaseGainFactor;
float noiseVarGain = totalGain * totalGain;
float readNoiseVar = kReadNoiseVarBeforeGain * noiseVarGain
@@ -432,12 +425,11 @@ void Sensor::captureRaw(uint8_t *img, uint32_t gain, uint32_t stride) {
}
void Sensor::captureRGBA(uint8_t *img, uint32_t gain, uint32_t width, uint32_t height) {
- ATRACE_CALL();
float totalGain = gain/100.0 * kBaseGainFactor;
// In fixed-point math, calculate total scaling from electrons to 8bpp
int scale64x = 64 * totalGain * 255 / kMaxRawValue;
- unsigned int DivH= (float)mSceneHeight/height * (0x1 << 10);
- unsigned int DivW = (float)mSceneWidth/width * (0x1 << 10);
+ unsigned int DivH= (float)mResolution[1]/height * (0x1 << 10);
+ unsigned int DivW = (float)mResolution[0]/width * (0x1 << 10);
for (unsigned int outY = 0; outY < height; outY++) {
unsigned int y = outY * DivH >> 10;
@@ -455,9 +447,9 @@ void Sensor::captureRGBA(uint8_t *img, uint32_t gain, uint32_t width, uint32_t h
}
lastX = x;
// TODO: Perfect demosaicing is a cheat
- rCount = pixel[Scene::R] * scale64x;
- gCount = pixel[Scene::Gr] * scale64x;
- bCount = pixel[Scene::B] * scale64x;
+ rCount = (pixel[Scene::R]+(outX+outY)%64) * scale64x;
+ gCount = (pixel[Scene::Gr]+(outX+outY)%64) * scale64x;
+ bCount = (pixel[Scene::B]+(outX+outY)%64) * scale64x;
*px++ = rCount < 255*64 ? rCount / 64 : 255;
*px++ = gCount < 255*64 ? gCount / 64 : 255;
@@ -471,12 +463,11 @@ void Sensor::captureRGBA(uint8_t *img, uint32_t gain, uint32_t width, uint32_t h
}
void Sensor::captureRGB(uint8_t *img, uint32_t gain, uint32_t width, uint32_t height) {
- ATRACE_CALL();
float totalGain = gain/100.0 * kBaseGainFactor;
// In fixed-point math, calculate total scaling from electrons to 8bpp
int scale64x = 64 * totalGain * 255 / kMaxRawValue;
- unsigned int DivH= (float)mSceneHeight/height * (0x1 << 10);
- unsigned int DivW = (float)mSceneWidth/width * (0x1 << 10);
+ unsigned int DivH= (float)mResolution[1]/height * (0x1 << 10);
+ unsigned int DivW = (float)mResolution[0]/width * (0x1 << 10);
for (unsigned int outY = 0; outY < height; outY++) {
unsigned int y = outY * DivH >> 10;
@@ -494,9 +485,9 @@ void Sensor::captureRGB(uint8_t *img, uint32_t gain, uint32_t width, uint32_t he
}
lastX = x;
// TODO: Perfect demosaicing is a cheat
- rCount = pixel[Scene::R] * scale64x;
- gCount = pixel[Scene::Gr] * scale64x;
- bCount = pixel[Scene::B] * scale64x;
+ rCount = (pixel[Scene::R]+(outX+outY)%64) * scale64x;
+ gCount = (pixel[Scene::Gr]+(outX+outY)%64) * scale64x;
+ bCount = (pixel[Scene::B]+(outX+outY)%64) * scale64x;
*px++ = rCount < 255*64 ? rCount / 64 : 255;
*px++ = gCount < 255*64 ? gCount / 64 : 255;
@@ -506,8 +497,7 @@ void Sensor::captureRGB(uint8_t *img, uint32_t gain, uint32_t width, uint32_t he
ALOGVV("RGB sensor image captured");
}
-void Sensor::captureYU12(uint8_t *img, uint32_t gain, uint32_t width, uint32_t height) {
- ATRACE_CALL();
+void Sensor::captureNV21(uint8_t *img, uint32_t gain, uint32_t width, uint32_t height) {
float totalGain = gain/100.0 * kBaseGainFactor;
// Using fixed-point math with 6 bits of fractional precision.
// In fixed-point math, calculate total scaling from electrons to 8bpp
@@ -517,27 +507,19 @@ void Sensor::captureYU12(uint8_t *img, uint32_t gain, uint32_t width, uint32_t h
// Fixed-point coefficients for RGB-YUV transform
// Based on JFIF RGB->YUV transform.
// Cb/Cr offset scaled by 64x twice since they're applied post-multiply
- float rgbToY[] = {19.0, 37.0, 7.0, 0.0};
- float rgbToCb[] = {-10.0,-21.0, 32.0, 524288.0};
- float rgbToCr[] = {32.0,-26.0, -5.0, 524288.0};
+ const int rgbToY[] = {19, 37, 7};
+ const int rgbToCb[] = {-10,-21, 32, 524288};
+ const int rgbToCr[] = {32,-26, -5, 524288};
// Scale back to 8bpp non-fixed-point
const int scaleOut = 64;
const int scaleOutSq = scaleOut * scaleOut; // after multiplies
- const double invscaleOutSq = 1.0/scaleOutSq;
- for (int i=0; i < 4; ++i) {
- rgbToY[i] *= invscaleOutSq;
- rgbToCb[i] *= invscaleOutSq;
- rgbToCr[i] *= invscaleOutSq;
- }
- unsigned int DivH= (float)mSceneHeight/height * (0x1 << 10);
- unsigned int DivW = (float)mSceneWidth/width * (0x1 << 10);
+ unsigned int DivH= (float)mResolution[1]/height * (0x1 << 10);
+ unsigned int DivW = (float)mResolution[0]/width * (0x1 << 10);
for (unsigned int outY = 0; outY < height; outY++) {
unsigned int y = outY * DivH >> 10;
uint8_t *pxY = img + outY * width;
uint8_t *pxVU = img + (height + outY / 2) * width;
- uint8_t *pxU = img + height * width + (outY / 2) * (width / 2);
- uint8_t *pxV = pxU + (height / 2) * (width / 2);
mScene.setReadoutPixel(0, y);
unsigned int lastX = 0;
const uint32_t *pixel = mScene.getPixelElectrons();
@@ -550,29 +532,39 @@ void Sensor::captureYU12(uint8_t *img, uint32_t gain, uint32_t width, uint32_t h
}
}
lastX = x;
- rCount = pixel[Scene::R] * scale64x;
+ //Slightly different color for the same Scene, result in larger
+ //jpeg image size requried by CTS test
+ //android.provider.cts.MediaStoreUiTest#testImageCapture
+ rCount = (pixel[Scene::R]+(outX+outY)%64) * scale64x;
rCount = rCount < saturationPoint ? rCount : saturationPoint;
- gCount = pixel[Scene::Gr] * scale64x;
+ gCount = (pixel[Scene::Gr]+(outX+outY)%64) * scale64x;
gCount = gCount < saturationPoint ? gCount : saturationPoint;
- bCount = pixel[Scene::B] * scale64x;
+ bCount = (pixel[Scene::B]+(outX+outY)%64) * scale64x;
bCount = bCount < saturationPoint ? bCount : saturationPoint;
- *pxY++ = (rgbToY[0] * rCount + rgbToY[1] * gCount + rgbToY[2] * bCount);
+ *pxY++ = (rgbToY[0] * rCount +
+ rgbToY[1] * gCount +
+ rgbToY[2] * bCount) / scaleOutSq;
if (outY % 2 == 0 && outX % 2 == 0) {
- *pxV++ = (rgbToCr[0] * rCount + rgbToCr[1] * gCount + rgbToCr[2] * bCount + rgbToCr[3]);
- *pxU++ = (rgbToCb[0] * rCount + rgbToCb[1] * gCount + rgbToCb[2] * bCount + rgbToCb[3]);
+ *pxVU++ = (rgbToCr[0] * rCount +
+ rgbToCr[1] * gCount +
+ rgbToCr[2] * bCount +
+ rgbToCr[3]) / scaleOutSq;
+ *pxVU++ = (rgbToCb[0] * rCount +
+ rgbToCb[1] * gCount +
+ rgbToCb[2] * bCount +
+ rgbToCb[3]) / scaleOutSq;
}
}
}
- ALOGVV("YU21 sensor image captured");
+ ALOGVV("NV21 sensor image captured");
}
void Sensor::captureDepth(uint8_t *img, uint32_t gain, uint32_t width, uint32_t height) {
- ATRACE_CALL();
float totalGain = gain/100.0 * kBaseGainFactor;
// In fixed-point math, calculate scaling factor to 13bpp millimeters
int scale64x = 64 * totalGain * 8191 / kMaxRawValue;
- unsigned int DivH= (float)mSceneHeight/height * (0x1 << 10);
- unsigned int DivW = (float)mSceneWidth/width * (0x1 << 10);
+ unsigned int DivH= (float)mResolution[1]/height * (0x1 << 10);
+ unsigned int DivW = (float)mResolution[0]/width * (0x1 << 10);
for (unsigned int outY = 0; outY < height; outY++) {
unsigned int y = outY * DivH >> 10;
@@ -599,7 +591,7 @@ void Sensor::captureDepth(uint8_t *img, uint32_t gain, uint32_t width, uint32_t
}
void Sensor::captureDepthCloud(uint8_t *img) {
- ATRACE_CALL();
+
android_depth_points *cloud = reinterpret_cast<android_depth_points*>(img);
cloud->num_points = 16;
diff --git a/camera/fake-pipeline2/Sensor.h b/camera/fake-pipeline2/Sensor.h
index 0dc99622..19428612 100644
--- a/camera/fake-pipeline2/Sensor.h
+++ b/camera/fake-pipeline2/Sensor.h
@@ -231,14 +231,12 @@ class Sensor: private Thread, public virtual RefBase {
nsecs_t mNextCaptureTime;
Buffers *mNextCapturedBuffers;
- int mSceneWidth;
- int mSceneHeight;
Scene mScene;
void captureRaw(uint8_t *img, uint32_t gain, uint32_t stride);
void captureRGBA(uint8_t *img, uint32_t gain, uint32_t width, uint32_t height);
void captureRGB(uint8_t *img, uint32_t gain, uint32_t width, uint32_t height);
- void captureYU12(uint8_t *img, uint32_t gain, uint32_t width, uint32_t height);
+ void captureNV21(uint8_t *img, uint32_t gain, uint32_t width, uint32_t height);
void captureDepth(uint8_t *img, uint32_t gain, uint32_t width, uint32_t height);
void captureDepthCloud(uint8_t *img);
diff --git a/camera/jpeg-stub/Compressor.cpp b/camera/jpeg-stub/Compressor.cpp
index 02a05fd7..3fe0bd6c 100644
--- a/camera/jpeg-stub/Compressor.cpp
+++ b/camera/jpeg-stub/Compressor.cpp
@@ -33,6 +33,7 @@ bool Compressor::compress(const unsigned char* data,
// provide here so just return.
return false;
}
+
return compressData(data, exifData);
}
@@ -79,6 +80,24 @@ bool Compressor::configureCompressor(int width, int height, int quality) {
return true;
}
+static void deinterleave(const uint8_t* vuPlanar, std::vector<uint8_t>& uRows,
+ std::vector<uint8_t>& vRows, int rowIndex, int width,
+ int height, int stride) {
+ int numRows = (height - rowIndex) / 2;
+ if (numRows > 8) numRows = 8;
+ for (int row = 0; row < numRows; ++row) {
+ int offset = ((rowIndex >> 1) + row) * stride;
+ const uint8_t* vu = vuPlanar + offset;
+ for (int i = 0; i < (width >> 1); ++i) {
+ int index = row * (width >> 1) + i;
+ uRows[index] = vu[1];
+ vRows[index] = vu[0];
+ vu += 2;
+ }
+ }
+}
+
+
bool Compressor::compressData(const unsigned char* data, ExifData* exifData) {
const uint8_t* y[16];
const uint8_t* cb[8];
@@ -89,8 +108,9 @@ bool Compressor::compressData(const unsigned char* data, ExifData* exifData) {
int width = mCompressInfo.image_width;
int height = mCompressInfo.image_height;
const uint8_t* yPlanar = data;
- const uint8_t* uPlanar = yPlanar + width * height;
- const uint8_t* vPlanar = uPlanar + width * height / 4;
+ const uint8_t* vuPlanar = data + (width * height);
+ std::vector<uint8_t> uRows(8 * (width >> 1));
+ std::vector<uint8_t> vRows(8 * (width >> 1));
// NOTE! DANGER! Do not construct any non-trivial objects below setjmp!
// The compiler will not generate code to destroy them during the return
@@ -108,6 +128,10 @@ bool Compressor::compressData(const unsigned char* data, ExifData* exifData) {
// process 16 lines of Y and 8 lines of U/V each time.
while (mCompressInfo.next_scanline < mCompressInfo.image_height) {
+ //deinterleave u and v
+ deinterleave(vuPlanar, uRows, vRows, mCompressInfo.next_scanline,
+ width, height, width);
+
// Jpeg library ignores the rows whose indices are greater than height.
for (i = 0; i < 16; i++) {
// y row
@@ -116,10 +140,11 @@ bool Compressor::compressData(const unsigned char* data, ExifData* exifData) {
// construct u row and v row
if ((i & 1) == 0) {
// height and width are both halved because of downsampling
- cb[i/2] = uPlanar + (mCompressInfo.next_scanline + i) * width / 4;
- cr[i/2] = vPlanar + (mCompressInfo.next_scanline + i) * width / 4;
+ offset = (i >> 1) * (width >> 1);
+ cb[i/2] = &uRows[offset];
+ cr[i/2] = &vRows[offset];
}
- }
+ }
jpeg_write_raw_data(&mCompressInfo, const_cast<JSAMPIMAGE>(planes), 16);
}
diff --git a/camera/media_codecs_google_video_default.xml b/camera/media_codecs_google_video.xml
index 75f42646..1dbd13df 100644
--- a/camera/media_codecs_google_video_default.xml
+++ b/camera/media_codecs_google_video.xml
@@ -23,7 +23,6 @@
<Limit name="block-size" value="16x16" />
<Limit name="blocks-per-second" range="12-11880" />
<Limit name="bitrate" range="1-384000" />
- <Limit name="performance-point-1920x1080" value="30" />
<Feature name="adaptive-playback" />
</MediaCodec>
<MediaCodec name="OMX.google.h263.decoder" type="video/3gpp">
@@ -32,7 +31,6 @@
<Limit name="size" min="2x2" max="352x288" />
<Limit name="alignment" value="2x2" />
<Limit name="bitrate" range="1-384000" />
- <Limit name="performance-point-1920x1080" value="30" />
<Feature name="adaptive-playback" />
</MediaCodec>
<MediaCodec name="OMX.google.h264.decoder" type="video/avc">
@@ -42,7 +40,6 @@
<Limit name="block-size" value="16x16" />
<Limit name="blocks-per-second" range="1-244800" />
<Limit name="bitrate" range="1-12000000" />
- <Limit name="performance-point-1920x1080" value="30" />
<Feature name="adaptive-playback" />
</MediaCodec>
<MediaCodec name="OMX.google.hevc.decoder" type="video/hevc">
@@ -53,7 +50,6 @@
<Limit name="block-count" range="1-139264" />
<Limit name="blocks-per-second" range="1-2000000" />
<Limit name="bitrate" range="1-10000000" />
- <Limit name="performance-point-1920x1080" value="30" />
<Feature name="adaptive-playback" />
</MediaCodec>
<MediaCodec name="OMX.google.vp8.decoder" type="video/x-vnd.on2.vp8">
@@ -62,7 +58,6 @@
<Limit name="block-size" value="16x16" />
<Limit name="blocks-per-second" range="1-1000000" />
<Limit name="bitrate" range="1-40000000" />
- <Limit name="performance-point-1920x1080" value="30" />
<Feature name="adaptive-playback" />
</MediaCodec>
<MediaCodec name="OMX.google.vp9.decoder" type="video/x-vnd.on2.vp9">
@@ -71,7 +66,6 @@
<Limit name="block-size" value="16x16" />
<Limit name="blocks-per-second" range="1-500000" />
<Limit name="bitrate" range="1-40000000" />
- <Limit name="performance-point-1920x1080" value="30" />
<Feature name="adaptive-playback" />
</MediaCodec>
</Decoders>
diff --git a/camera/media_codecs_google_video_v2.xml b/camera/media_codecs_google_video_v2.xml
deleted file mode 100644
index d64d928f..00000000
--- a/camera/media_codecs_google_video_v2.xml
+++ /dev/null
@@ -1,120 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!-- Copyright (C) 2014 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.
--->
-
-<Included>
- <Decoders>
- <MediaCodec name="OMX.google.mpeg4.decoder" type="video/mp4v-es">
- <!-- profiles and levels: ProfileSimple : Level3 -->
- <Limit name="size" min="2x2" max="352x288" />
- <Limit name="alignment" value="2x2" />
- <Limit name="block-size" value="16x16" />
- <Limit name="blocks-per-second" range="12-11880" />
- <Limit name="bitrate" range="1-384000" />
- <Limit name="performance-point-1920x1080" value="30" />
- <Feature name="adaptive-playback" />
- </MediaCodec>
- <MediaCodec name="OMX.google.h263.decoder" type="video/3gpp">
- <!-- profiles and levels: ProfileBaseline : Level30, ProfileBaseline : Level45
- ProfileISWV2 : Level30, ProfileISWV2 : Level45 -->
- <Limit name="size" min="2x2" max="352x288" />
- <Limit name="alignment" value="2x2" />
- <Limit name="bitrate" range="1-384000" />
- <Limit name="performance-point-1920x1080" value="30" />
- <Feature name="adaptive-playback" />
- </MediaCodec>
- <MediaCodec name="OMX.google.goldfish.h264.decoder" type="video/avc">
- <!-- profiles and levels: ProfileHigh : Level52 -->
- <Limit name="size" min="2x2" max="4080x4080" />
- <Limit name="alignment" value="2x2" />
- <Limit name="block-size" value="16x16" />
- <Limit name="block-count" range="1-32768" /> <!-- max 4096x2048 equivalent -->
- <Limit name="blocks-per-second" range="1-1966080" />
- <Limit name="bitrate" range="1-48000000" />
- <Limit name="performance-point-1920x1080" value="30" />
- <Feature name="adaptive-playback" />
- </MediaCodec>
- <MediaCodec name="OMX.google.hevc.decoder" type="video/hevc">
- <!-- profiles and levels: ProfileMain : MainTierLevel51 -->
- <Limit name="size" min="2x2" max="4096x4096" />
- <Limit name="alignment" value="2x2" />
- <Limit name="block-size" value="8x8" />
- <Limit name="block-count" range="1-196608" /> <!-- max 4096x3072 -->
- <Limit name="blocks-per-second" range="1-2000000" />
- <Limit name="bitrate" range="1-10000000" />
- <Limit name="performance-point-1920x1080" value="30" />
- <Feature name="adaptive-playback" />
- </MediaCodec>
- <MediaCodec name="OMX.google.goldfish.vp8.decoder" type="video/x-vnd.on2.vp8">
- <Limit name="size" min="2x2" max="2048x2048" />
- <Limit name="alignment" value="2x2" />
- <Limit name="block-size" value="16x16" />
- <Limit name="block-count" range="1-16384" />
- <Limit name="blocks-per-second" range="1-1000000" />
- <Limit name="bitrate" range="1-40000000" />
- <Limit name="performance-point-1920x1080" value="30" />
- <Feature name="adaptive-playback" />
- </MediaCodec>
- <MediaCodec name="OMX.google.goldfish.vp9.decoder" type="video/x-vnd.on2.vp9">
- <Limit name="size" min="2x2" max="2048x2048" />
- <Limit name="alignment" value="2x2" />
- <Limit name="block-size" value="16x16" />
- <Limit name="block-count" range="1-16384" />
- <Limit name="blocks-per-second" range="1-500000" />
- <Limit name="bitrate" range="1-40000000" />
- <Limit name="performance-point-1920x1080" value="30" />
- <Feature name="adaptive-playback" />
- </MediaCodec>
- </Decoders>
-
- <Encoders>
- <MediaCodec name="OMX.google.h263.encoder" type="video/3gpp">
- <!-- profiles and levels: ProfileBaseline : Level45 -->
- <Limit name="size" min="176x144" max="176x144" />
- <Limit name="alignment" value="16x16" />
- <Limit name="bitrate" range="1-128000" />
- </MediaCodec>
- <MediaCodec name="OMX.google.h264.encoder" type="video/avc">
- <!-- profiles and levels: ProfileBaseline : Level41 -->
- <Limit name="size" min="16x16" max="2048x2048" />
- <Limit name="alignment" value="2x2" />
- <Limit name="block-size" value="16x16" />
- <Limit name="block-count" range="1-8192" /> <!-- max 2048x1024 -->
- <Limit name="blocks-per-second" range="1-245760" />
- <Limit name="bitrate" range="1-12000000" />
- <Feature name="intra-refresh" />
- </MediaCodec>
- <MediaCodec name="OMX.google.mpeg4.encoder" type="video/mp4v-es">
- <!-- profiles and levels: ProfileCore : Level2 -->
- <Limit name="size" min="16x16" max="176x144" />
- <Limit name="alignment" value="16x16" />
- <Limit name="block-size" value="16x16" />
- <Limit name="blocks-per-second" range="12-1485" />
- <Limit name="bitrate" range="1-64000" />
- </MediaCodec>
- <!-- Overwrites the max frame size to 1440p (see b/110911862). -->
- <MediaCodec name="OMX.google.vp8.decoder" type="video/x-vnd.on2.vp8" update="true">
- <Limit name="size" min="2x2" max="2560x2560" />
- <Limit name="block-count" range="1-25600" />
- <Limit name="blocks-per-second" range="1-1536000" />
- </MediaCodec>
- <!-- Overwrites the max frame size to 1440p (see b/110911862). -->
- <MediaCodec name="OMX.google.vp9.decoder" type="video/x-vnd.on2.vp9" update="true">
- <Limit name="size" min="2x2" max="2560x2560" />
- <Limit name="block-count" range="1-25600" />
- <Limit name="blocks-per-second" range="1-768000" />
- </MediaCodec>
- </Encoders>
-</Included>
diff --git a/camera/qemu-pipeline3/QemuSensor.cpp b/camera/qemu-pipeline3/QemuSensor.cpp
index db2a66a3..529bf961 100644
--- a/camera/qemu-pipeline3/QemuSensor.cpp
+++ b/camera/qemu-pipeline3/QemuSensor.cpp
@@ -21,7 +21,6 @@
//#define LOG_NNDEBUG 0
#define LOG_TAG "EmulatedCamera3_QemuSensor"
-#define ATRACE_TAG ATRACE_TAG_CAMERA
#ifdef LOG_NNDEBUG
#define ALOGVV(...) ALOGV(__VA_ARGS__)
@@ -36,7 +35,6 @@
#include <cstdlib>
#include <linux/videodev2.h>
#include <log/log.h>
-#include <utils/Trace.h>
namespace android {
@@ -189,7 +187,6 @@ status_t QemuSensor::readyToRun() {
}
bool QemuSensor::threadLoop() {
- ATRACE_CALL();
/*
* Stages are out-of-order relative to a single frame's processing, but
* in-order in time.
@@ -306,7 +303,7 @@ bool QemuSensor::threadLoop() {
}
break;
case HAL_PIXEL_FORMAT_YCbCr_420_888:
- captureYU12(b.img, b.width, b.height, b.stride, &timestamp);
+ captureNV21(b.img, b.width, b.height, b.stride, &timestamp);
break;
default:
ALOGE("%s: Unknown/unsupported format %x, no output",
@@ -346,7 +343,6 @@ bool QemuSensor::threadLoop() {
void QemuSensor::captureRGBA(uint8_t *img, uint32_t width, uint32_t height,
uint32_t stride, int64_t *timestamp) {
- ATRACE_CALL();
status_t res;
if (width != (uint32_t)mLastRequestWidth ||
height != (uint32_t)mLastRequestHeight) {
@@ -373,9 +369,9 @@ void QemuSensor::captureRGBA(uint8_t *img, uint32_t width, uint32_t height,
/*
* Host Camera always assumes V4L2_PIX_FMT_RGB32 as the preview format,
* and asks for the video format from the pixFmt parameter, which is
- * V4L2_PIX_FMT_YUV420 in our implementation.
+ * V4L2_PIX_FMT_NV21 in our implementation.
*/
- uint32_t pixFmt = V4L2_PIX_FMT_YUV420;
+ uint32_t pixFmt = V4L2_PIX_FMT_NV21;
res = mCameraQemuClient.queryStart(pixFmt, width, height);
if (res == NO_ERROR) {
mLastRequestWidth = width;
@@ -415,8 +411,7 @@ void QemuSensor::captureRGB(uint8_t *img, uint32_t width, uint32_t height, uint3
ALOGE("%s: Not implemented", __FUNCTION__);
}
-void QemuSensor::captureYU12(uint8_t *img, uint32_t width, uint32_t height, uint32_t stride, int64_t *timestamp) {
- ATRACE_CALL();
+void QemuSensor::captureNV21(uint8_t *img, uint32_t width, uint32_t height, uint32_t stride, int64_t *timestamp) {
status_t res;
if (width != (uint32_t)mLastRequestWidth ||
height != (uint32_t)mLastRequestHeight) {
@@ -443,9 +438,9 @@ void QemuSensor::captureYU12(uint8_t *img, uint32_t width, uint32_t height, uint
/*
* Host Camera always assumes V4L2_PIX_FMT_RGB32 as the preview format,
* and asks for the video format from the pixFmt parameter, which is
- * V4L2_PIX_FMT_YUV420 in our implementation.
+ * V4L2_PIX_FMT_NV21 in our implementation.
*/
- uint32_t pixFmt = V4L2_PIX_FMT_YUV420;
+ uint32_t pixFmt = V4L2_PIX_FMT_NV21;
res = mCameraQemuClient.queryStart(pixFmt, width, height);
if (res == NO_ERROR) {
mLastRequestWidth = width;
@@ -468,7 +463,7 @@ void QemuSensor::captureYU12(uint8_t *img, uint32_t width, uint32_t height, uint
width, stride);
}
- // Calculate the buffer size for YUV420.
+ // Calculate the buffer size for NV21.
size_t bufferSize = (width * height * 12) / 8;
// Apply no white balance or exposure compensation.
float whiteBalance[] = {1.0f, 1.0f, 1.0f};
@@ -478,7 +473,7 @@ void QemuSensor::captureYU12(uint8_t *img, uint32_t width, uint32_t height, uint
whiteBalance[1], whiteBalance[2],
exposureCompensation, timestamp);
- ALOGVV("YUV420 sensor image captured");
+ ALOGVV("NV21 sensor image captured");
}
}; // end of namespace android
diff --git a/camera/qemu-pipeline3/QemuSensor.h b/camera/qemu-pipeline3/QemuSensor.h
index a39d3e56..a867d8ab 100644
--- a/camera/qemu-pipeline3/QemuSensor.h
+++ b/camera/qemu-pipeline3/QemuSensor.h
@@ -190,7 +190,7 @@ class QemuSensor: private Thread, public virtual RefBase {
uint32_t stride, int64_t *timestamp);
void captureRGB(uint8_t *img, uint32_t width, uint32_t height,
uint32_t stride, int64_t *timestamp);
- void captureYU12(uint8_t *img, uint32_t width, uint32_t height,
+ void captureNV21(uint8_t *img, uint32_t width, uint32_t height,
uint32_t stride, int64_t *timestamp);
};
diff --git a/data/etc/advancedFeatures.ini b/data/etc/advancedFeatures.ini
index 731e3f53..e1f8b6ad 100644
--- a/data/etc/advancedFeatures.ini
+++ b/data/etc/advancedFeatures.ini
@@ -7,8 +7,4 @@ EncryptUserData = on
IntelPerformanceMonitoringUnit = on
Wifi = on
HostComposition = on
-RefCountPipe = on
-VirtioInput = on
DynamicPartition = on
-YUVCache = on
-MultiDisplay = on
diff --git a/data/etc/config.ini b/data/etc/config.ini
index f7025b0f..a28b600d 100644
--- a/data/etc/config.ini
+++ b/data/etc/config.ini
@@ -1,6 +1,5 @@
avd.ini.encoding=UTF-8
-disk.dataPartition.size=6G
-fastboot.forceColdBoot = yes
+disk.dataPartition.size=2G
hw.accelerometer=yes
hw.audioInput=yes
hw.battery=yes
diff --git a/data/etc/config.ini.nexus5 b/data/etc/config.ini.nexus5
index 6d2da8b8..df58c7ca 100644
--- a/data/etc/config.ini.nexus5
+++ b/data/etc/config.ini.nexus5
@@ -1,6 +1,5 @@
avd.ini.encoding=UTF-8
-disk.dataPartition.size=6G
-fastboot.forceColdBoot = yes
+disk.dataPartition.size=2G
hw.accelerometer=yes
hw.audioInput=yes
hw.battery=yes
diff --git a/data/etc/dummy.vbmeta.img b/data/etc/dummy.vbmeta.img
deleted file mode 100644
index 79892eae..00000000
--- a/data/etc/dummy.vbmeta.img
+++ /dev/null
Binary files differ
diff --git a/data/etc/encryptionkey.img b/data/etc/encryptionkey.img
index 139b1720..9e0f96a2 100644
--- a/data/etc/encryptionkey.img
+++ b/data/etc/encryptionkey.img
Binary files differ
diff --git a/data/etc/google/user/advancedFeatures.ini b/data/etc/google/user/advancedFeatures.ini
new file mode 100644
index 00000000..7ad2fa81
--- /dev/null
+++ b/data/etc/google/user/advancedFeatures.ini
@@ -0,0 +1,12 @@
+GrallocSync = on
+GLDMA = on
+LogcatPipe = on
+GLAsyncSwap = on
+GLESDynamicVersion = on
+PlayStoreImage = on
+EncryptUserData = on
+IntelPerformanceMonitoringUnit = on
+Wifi = on
+HostComposition = on
+DynamicPartition = on
+MultiDisplay = on
diff --git a/data/etc/user/advancedFeatures.ini b/data/etc/google/userdebug/advancedFeatures.ini
index 6c450301..775e5af7 100644
--- a/data/etc/user/advancedFeatures.ini
+++ b/data/etc/google/userdebug/advancedFeatures.ini
@@ -1,9 +1,8 @@
GrallocSync = on
-GLDMA = on
LogcatPipe = on
GLAsyncSwap = on
GLESDynamicVersion = on
-PlayStoreImage = on
+GLDMA = on
EncryptUserData = on
IntelPerformanceMonitoringUnit = on
Wifi = on
@@ -11,3 +10,4 @@ HostComposition = on
RefCountPipe = on
VirtioInput = on
DynamicPartition = on
+MultiDisplay = on
diff --git a/data/etc/x86/emulatorip b/data/etc/x86/emulatorip
deleted file mode 100755
index 72541a37..00000000
--- a/data/etc/x86/emulatorip
+++ /dev/null
Binary files differ
diff --git a/dhcp/client/dhcpclient.cpp b/dhcp/client/dhcpclient.cpp
index 0897b4c2..20dd143e 100644
--- a/dhcp/client/dhcpclient.cpp
+++ b/dhcp/client/dhcpclient.cpp
@@ -50,9 +50,8 @@ static std::string addrToStr(in_addr_t address) {
return inet_ntop(AF_INET, &addr, buffer, sizeof(buffer));
}
-DhcpClient::DhcpClient(uint32_t options)
- : mOptions(options),
- mRandomEngine(std::random_device()()),
+DhcpClient::DhcpClient()
+ : mRandomEngine(std::random_device()()),
mRandomDistribution(-kTimeoutSpan, kTimeoutSpan),
mState(State::Init),
mNextTimeout(kInitialTimeout),
@@ -420,50 +419,45 @@ bool DhcpClient::configureDhcp(const Message& msg) {
}
}
+ res = mInterface.setAddress(mDhcpInfo.offeredAddress);
+ if (!res) {
+ ALOGE("Could not configure DHCP: %s", res.c_str());
+ return false;
+ }
+
+ res = mInterface.setSubnetMask(mDhcpInfo.subnetMask);
+ if (!res) {
+ ALOGE("Could not configure DHCP: %s", res.c_str());
+ return false;
+ }
+
+ res = mRouter.setDefaultGateway(mDhcpInfo.gateway, mInterface.getIndex());
+ if (!res) {
+ ALOGE("Could not configure DHCP: %s", res.c_str());
+ return false;
+ }
char propName[64];
snprintf(propName, sizeof(propName), "net.%s.gw",
mInterface.getName().c_str());
- if (property_set(propName, addrToStr(mDhcpInfo.gateway).c_str()) != 0) {
- ALOGE("Failed to set %s: %s", propName, strerror(errno));
- }
+ property_set(propName, addrToStr(mDhcpInfo.gateway).c_str());
int numDnsEntries = sizeof(mDhcpInfo.dns) / sizeof(mDhcpInfo.dns[0]);
for (int i = 0; i < numDnsEntries; ++i) {
snprintf(propName, sizeof(propName), "net.%s.dns%d",
mInterface.getName().c_str(), i + 1);
if (mDhcpInfo.dns[i] != 0) {
- if (property_set(propName,
- addrToStr(mDhcpInfo.dns[i]).c_str()) != 0) {
- ALOGE("Failed to set %s: %s", propName, strerror(errno));
- }
+ property_set(propName, addrToStr(mDhcpInfo.dns[i]).c_str());
} else {
// Clear out any previous value here in case it was set
- if (property_set(propName, "") != 0) {
- ALOGE("Failed to clear %s: %s", propName, strerror(errno));
- }
+ property_set(propName, "");
}
}
- res = mInterface.setAddress(mDhcpInfo.offeredAddress,
- mDhcpInfo.subnetMask);
- if (!res) {
- ALOGE("Could not configure DHCP: %s", res.c_str());
- return false;
- }
-
- if ((mOptions & static_cast<uint32_t>(ClientOption::NoGateway)) == 0) {
- res = mRouter.setDefaultGateway(mDhcpInfo.gateway,
- mInterface.getIndex());
- if (!res) {
- ALOGE("Could not configure DHCP: %s", res.c_str());
- return false;
- }
- }
return true;
}
void DhcpClient::haltNetwork() {
- Result res = mInterface.setAddress(0, 0);
+ Result res = mInterface.setAddress(0);
if (!res) {
ALOGE("Could not halt network: %s", res.c_str());
}
diff --git a/dhcp/client/dhcpclient.h b/dhcp/client/dhcpclient.h
index 128d416f..718f4c9c 100644
--- a/dhcp/client/dhcpclient.h
+++ b/dhcp/client/dhcpclient.h
@@ -27,16 +27,10 @@
#include <random>
-// Options to configure the behavior of the DHCP client.
-enum class ClientOption : uint32_t {
- NoGateway = (1 << 0), // Do not configure the system's default gateway
-};
class DhcpClient {
public:
- // Create a DHCP client with the given |options|. These options are values
- // from the ClientOption enum.
- explicit DhcpClient(uint32_t options);
+ DhcpClient();
// Initialize the DHCP client to listen on |interfaceName|.
Result init(const char* interfaceName);
@@ -78,7 +72,6 @@ private:
uint16_t sourcePort, uint16_t destinationPort,
const uint8_t* data, size_t size);
- uint32_t mOptions;
std::mt19937 mRandomEngine; // Mersenne Twister RNG
std::uniform_int_distribution<int> mRandomDistribution;
diff --git a/dhcp/client/interface.cpp b/dhcp/client/interface.cpp
index a13af084..805fa521 100644
--- a/dhcp/client/interface.cpp
+++ b/dhcp/client/interface.cpp
@@ -16,26 +16,13 @@
#include "interface.h"
-#include "netlink.h"
-
#include <errno.h>
#include <linux/if.h>
#include <linux/if_ether.h>
#include <linux/route.h>
-#include <linux/rtnetlink.h>
#include <string.h>
#include <unistd.h>
-in_addr_t broadcastFromNetmask(in_addr_t address, in_addr_t netmask) {
- // The broadcast address is the address with the bits excluded in the
- // netmask set to 1. For example if address = 10.0.2.15 and netmask is
- // 255.255.255.0 then the broadcast is 10.0.2.255. If instead netmask was
- // 255.0.0.0.0 then the broadcast would be 10.255.255.255
- //
- // Simply set all the lower bits to 1 and that should do it.
- return address | (~netmask);
-}
-
Interface::Interface() : mSocketFd(-1) {
}
@@ -53,7 +40,7 @@ Result Interface::init(const char* interfaceName) {
return Result::error("Interface initialized more than once");
}
- mSocketFd = ::socket(AF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_ROUTE);
+ mSocketFd = ::socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, IPPROTO_IP);
if (mSocketFd == -1) {
return Result::error("Failed to create interface socket for '%s': %s",
interfaceName, strerror(errno));
@@ -74,7 +61,7 @@ Result Interface::init(const char* interfaceName) {
return res;
}
- res = setAddress(0, 0);
+ res = setAddress(0);
if (!res) {
return res;
}
@@ -106,65 +93,37 @@ Result Interface::setMtu(uint16_t mtu) {
return Result::success();
}
-Result Interface::setAddress(in_addr_t address, in_addr_t subnetMask) {
- struct Request {
- struct nlmsghdr hdr;
- struct ifaddrmsg msg;
- char buf[256];
- } request;
+Result Interface::setAddress(in_addr_t address) {
+ struct ifreq request = createRequest();
- memset(&request, 0, sizeof(request));
+ auto requestAddr = reinterpret_cast<struct sockaddr_in*>(&request.ifr_addr);
+ requestAddr->sin_family = AF_INET;
+ requestAddr->sin_port = 0;
+ requestAddr->sin_addr.s_addr = address;
- request.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(request.msg));
- request.hdr.nlmsg_type = RTM_NEWADDR;
- request.hdr.nlmsg_flags = NLM_F_REQUEST |
- NLM_F_ACK |
- NLM_F_CREATE |
- NLM_F_REPLACE;
-
- request.msg.ifa_family = AF_INET;
- // Count the number of bits in the subnet mask, this is the length.
- request.msg.ifa_prefixlen = __builtin_popcount(subnetMask);
- request.msg.ifa_index = mIndex;
-
- addRouterAttribute(request, IFA_ADDRESS, &address, sizeof(address));
- addRouterAttribute(request, IFA_LOCAL, &address, sizeof(address));
- in_addr_t broadcast = broadcastFromNetmask(address, subnetMask);
- addRouterAttribute(request, IFA_BROADCAST, &broadcast, sizeof(broadcast));
-
- struct sockaddr_nl nlAddr;
- memset(&nlAddr, 0, sizeof(nlAddr));
- nlAddr.nl_family = AF_NETLINK;
-
- int status = ::sendto(mSocketFd, &request, request.hdr.nlmsg_len, 0,
- reinterpret_cast<sockaddr*>(&nlAddr),
- sizeof(nlAddr));
- if (status == -1) {
- return Result::error("Unable to set interface address: %s",
- strerror(errno));
- }
- char buffer[8192];
- status = ::recv(mSocketFd, buffer, sizeof(buffer), 0);
- if (status < 0) {
- return Result::error("Unable to read netlink response: %s",
- strerror(errno));
- }
- size_t responseSize = static_cast<size_t>(status);
- if (responseSize < sizeof(nlmsghdr)) {
- return Result::error("Received incomplete response from netlink");
+ int status = ::ioctl(mSocketFd, SIOCSIFADDR, &request);
+ if (status != 0) {
+ return Result::error("Failed to set interface address for '%s': %s",
+ mInterfaceName.c_str(), strerror(errno));
}
- auto response = reinterpret_cast<const nlmsghdr*>(buffer);
- if (response->nlmsg_type == NLMSG_ERROR) {
- if (responseSize < NLMSG_HDRLEN + sizeof(nlmsgerr)) {
- return Result::error("Recieved an error from netlink but the "
- "response was incomplete");
- }
- auto err = reinterpret_cast<const nlmsgerr*>(NLMSG_DATA(response));
- if (err->error) {
- return Result::error("Could not set interface address: %s",
- strerror(-err->error));
- }
+
+ return Result::success();
+}
+
+Result Interface::setSubnetMask(in_addr_t subnetMask) {
+ struct ifreq request = createRequest();
+
+ auto addr = reinterpret_cast<struct sockaddr_in*>(&request.ifr_addr);
+ addr->sin_family = AF_INET;
+ addr->sin_port = 0;
+ addr->sin_addr.s_addr = subnetMask;
+
+ int status = ::ioctl(mSocketFd, SIOCSIFNETMASK, &request);
+ if (status != 0) {
+ return Result::error("Failed to set subnet mask for '%s': %s",
+ mInterfaceName.c_str(), strerror(errno));
}
+
return Result::success();
}
diff --git a/dhcp/client/interface.h b/dhcp/client/interface.h
index ca9e9e5a..b7f549af 100644
--- a/dhcp/client/interface.h
+++ b/dhcp/client/interface.h
@@ -40,7 +40,8 @@ public:
Result bringUp();
Result bringDown();
Result setMtu(uint16_t mtu);
- Result setAddress(in_addr_t address, in_addr_t subnetMask);
+ Result setAddress(in_addr_t address);
+ Result setSubnetMask(in_addr_t subnetMask);
private:
struct ifreq createRequest() const;
diff --git a/dhcp/client/main.cpp b/dhcp/client/main.cpp
index 70b854f4..f4a3ea98 100644
--- a/dhcp/client/main.cpp
+++ b/dhcp/client/main.cpp
@@ -18,9 +18,7 @@
#include "log.h"
static void usage(const char* program) {
- ALOGE("Usage: %s [--no-gateway] -i <interface>", program);
- ALOGE(" If the optional parameter --no-gateway is specified the client");
- ALOGE(" will not configure the default gateway of the system.");
+ ALOGE("Usage: %s -i <interface>", program);
}
int main(int argc, char* argv[]) {
@@ -29,7 +27,6 @@ int main(int argc, char* argv[]) {
return 1;
}
const char* interfaceName = nullptr;
- uint32_t options = 0;
for (int i = 1; i < argc; ++i) {
if (strcmp(argv[i], "-i") == 0) {
@@ -40,8 +37,6 @@ int main(int argc, char* argv[]) {
usage(argv[0]);
return 1;
}
- } else if (strcmp(argv[i], "--no-gateway") == 0) {
- options |= static_cast<uint32_t>(ClientOption::NoGateway);
} else {
ALOGE("ERROR: unknown parameters %s", argv[i]);
usage(argv[0]);
@@ -54,7 +49,7 @@ int main(int argc, char* argv[]) {
return 1;
}
- DhcpClient client(options);
+ DhcpClient client;
Result res = client.init(interfaceName);
if (!res) {
ALOGE("Failed to initialize DHCP client: %s\n", res.c_str());
diff --git a/dhcp/client/netlink.h b/dhcp/client/netlink.h
deleted file mode 100644
index e0c916f3..00000000
--- a/dhcp/client/netlink.h
+++ /dev/null
@@ -1,22 +0,0 @@
-#pragma once
-
-#include <linux/rtnetlink.h>
-
-template<class Request>
-inline void addRouterAttribute(Request& r,
- int type,
- const void* data,
- size_t size) {
- // Calculate the offset into the character buffer where the RTA data lives
- // We use offsetof on the buffer to get it. This avoids undefined behavior
- // by casting the buffer (which is safe because it's char) instead of the
- // Request struct.(which is undefined because of aliasing)
- size_t offset = NLMSG_ALIGN(r.hdr.nlmsg_len) - offsetof(Request, buf);
- auto attr = reinterpret_cast<struct rtattr*>(r.buf + offset);
- attr->rta_type = type;
- attr->rta_len = RTA_LENGTH(size);
- memcpy(RTA_DATA(attr), data, size);
-
- // Update the message length to include the router attribute.
- r.hdr.nlmsg_len = NLMSG_ALIGN(r.hdr.nlmsg_len) + RTA_ALIGN(attr->rta_len);
-}
diff --git a/dhcp/client/router.cpp b/dhcp/client/router.cpp
index 7c87e2d9..9b9f17d6 100644
--- a/dhcp/client/router.cpp
+++ b/dhcp/client/router.cpp
@@ -16,14 +16,31 @@
#include "router.h"
-#include "netlink.h"
-
#include <linux/rtnetlink.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
+template<class Request>
+static void addRouterAttribute(Request& r,
+ int type,
+ const void* data,
+ size_t size) {
+ // Calculate the offset into the character buffer where the RTA data lives
+ // We use offsetof on the buffer to get it. This avoids undefined behavior
+ // by casting the buffer (which is safe because it's char) instead of the
+ // Request struct.(which is undefined because of aliasing)
+ size_t offset = NLMSG_ALIGN(r.hdr.nlmsg_len) - offsetof(Request, buf);
+ auto attr = reinterpret_cast<struct rtattr*>(r.buf + offset);
+ attr->rta_type = type;
+ attr->rta_len = RTA_LENGTH(size);
+ memcpy(RTA_DATA(attr), data, size);
+
+ // Update the message length to include the router attribute.
+ r.hdr.nlmsg_len = NLMSG_ALIGN(r.hdr.nlmsg_len) + RTA_ALIGN(attr->rta_len);
+}
+
Router::Router() : mSocketFd(-1) {
}
diff --git a/dhcp/server/Android.mk b/dhcp/server/Android.mk
new file mode 100644
index 00000000..38234de4
--- /dev/null
+++ b/dhcp/server/Android.mk
@@ -0,0 +1,22 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ dhcpserver.cpp \
+ main.cpp \
+ ../common/message.cpp \
+ ../common/socket.cpp \
+ ../common/utils.cpp \
+
+
+LOCAL_CPPFLAGS += -Werror
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/../common
+LOCAL_SHARED_LIBRARIES := libcutils liblog
+LOCAL_PROPRIETARY_MODULE := true
+LOCAL_MODULE := dhcpserver
+
+LOCAL_MODULE_CLASS := EXECUTABLES
+
+include $(BUILD_EXECUTABLE)
+
diff --git a/dhcp/server/dhcpserver.cpp b/dhcp/server/dhcpserver.cpp
new file mode 100644
index 00000000..d6d4a7ba
--- /dev/null
+++ b/dhcp/server/dhcpserver.cpp
@@ -0,0 +1,390 @@
+/*
+ * Copyright 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 "dhcpserver.h"
+
+#include "dhcp.h"
+#include "log.h"
+#include "message.h"
+
+#include <arpa/inet.h>
+#include <errno.h>
+#include <linux/sockios.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <poll.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <unistd.h>
+
+#include <cutils/properties.h>
+
+static const int kMaxDnsServers = 4;
+
+DhcpServer::DhcpServer(unsigned int excludeInterface) :
+ mExcludeInterface(excludeInterface)
+{
+}
+
+Result DhcpServer::init() {
+ Result res = mSocket.open(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ if (!res) {
+ return res;
+ }
+ res = mSocket.enableOption(SOL_IP, IP_PKTINFO);
+ if (!res) {
+ return res;
+ }
+ res = mSocket.enableOption(SOL_SOCKET, SO_BROADCAST);
+ if (!res) {
+ return res;
+ }
+
+ res = mSocket.bindIp(INADDR_ANY, PORT_BOOTP_SERVER);
+ if (!res) {
+ return res;
+ }
+
+ return Result::success();
+}
+
+Result DhcpServer::run() {
+ // Block all signals while we're running. This way we don't have to deal
+ // with things like EINTR. We then uses ppoll to set the original mask while
+ // polling. This way polling can be interrupted but socket writing, reading
+ // and ioctl remain interrupt free. If a signal arrives while we're blocking
+ // it it will be placed in the signal queue and handled once ppoll sets the
+ // original mask. This way no signals are lost.
+ sigset_t blockMask, originalMask;
+ int status = ::sigfillset(&blockMask);
+ if (status != 0) {
+ return Result::error("Unable to fill signal set: %s", strerror(errno));
+ }
+ status = ::sigprocmask(SIG_SETMASK, &blockMask, &originalMask);
+ if (status != 0) {
+ return Result::error("Unable to set signal mask: %s", strerror(errno));
+ }
+
+ struct pollfd fds;
+ fds.fd = mSocket.get();
+ fds.events = POLLIN;
+ Message message;
+ while ((status = ::ppoll(&fds, 1, nullptr, &originalMask)) >= 0) {
+ if (status == 0) {
+ // Timeout
+ continue;
+ }
+
+ unsigned int interfaceIndex = 0;
+ Result res = mSocket.receiveFromInterface(&message,
+ &interfaceIndex);
+ if (!res) {
+ ALOGE("Failed to recieve on socket: %s", res.c_str());
+ continue;
+ }
+ if (interfaceIndex == 0 || mExcludeInterface == interfaceIndex) {
+ // Received packet on unknown or unwanted interface, drop it
+ continue;
+ }
+ if (!message.isValidDhcpMessage(OP_BOOTREQUEST)) {
+ // Not a DHCP request, drop it
+ continue;
+ }
+ switch (message.type()) {
+ case DHCPDISCOVER:
+ // Someone is trying to find us, let them know we exist
+ sendDhcpOffer(message, interfaceIndex);
+ break;
+ case DHCPREQUEST:
+ // Someone wants a lease based on an offer
+ if (isValidDhcpRequest(message, interfaceIndex)) {
+ // The request matches our offer, acknowledge it
+ sendAck(message, interfaceIndex);
+ } else {
+ // Request for something other than we offered, denied
+ sendNack(message, interfaceIndex);
+ }
+ break;
+ }
+ }
+ // Polling failed, exit
+ return Result::error("Polling failed: %s", strerror(errno));
+}
+
+Result DhcpServer::sendMessage(unsigned int interfaceIndex,
+ in_addr_t /*sourceAddress*/,
+ const Message& message) {
+ return mSocket.sendOnInterface(interfaceIndex,
+ INADDR_BROADCAST,
+ PORT_BOOTP_CLIENT,
+ message);
+}
+
+void DhcpServer::sendDhcpOffer(const Message& message,
+ unsigned int interfaceIndex ) {
+ updateDnsServers();
+ in_addr_t offerAddress;
+ in_addr_t netmask;
+ in_addr_t gateway;
+ Result res = getOfferAddress(interfaceIndex,
+ message.dhcpData.chaddr,
+ &offerAddress,
+ &netmask,
+ &gateway);
+ if (!res) {
+ ALOGE("Failed to get address for offer: %s", res.c_str());
+ return;
+ }
+ in_addr_t serverAddress;
+ res = getInterfaceAddress(interfaceIndex, &serverAddress);
+ if (!res) {
+ ALOGE("Failed to get address for interface %u: %s",
+ interfaceIndex, res.c_str());
+ return;
+ }
+
+ Message offer = Message::offer(message,
+ serverAddress,
+ offerAddress,
+ netmask,
+ gateway,
+ mDnsServers.data(),
+ mDnsServers.size());
+ res = sendMessage(interfaceIndex, serverAddress, offer);
+ if (!res) {
+ ALOGE("Failed to send DHCP offer: %s", res.c_str());
+ }
+}
+
+void DhcpServer::sendAck(const Message& message, unsigned int interfaceIndex) {
+ updateDnsServers();
+ in_addr_t offerAddress;
+ in_addr_t netmask;
+ in_addr_t gateway;
+ in_addr_t serverAddress;
+ Result res = getOfferAddress(interfaceIndex,
+ message.dhcpData.chaddr,
+ &offerAddress,
+ &netmask,
+ &gateway);
+ if (!res) {
+ ALOGE("Failed to get address for offer: %s", res.c_str());
+ return;
+ }
+ res = getInterfaceAddress(interfaceIndex, &serverAddress);
+ if (!res) {
+ ALOGE("Failed to get address for interface %u: %s",
+ interfaceIndex, res.c_str());
+ return;
+ }
+ Message ack = Message::ack(message,
+ serverAddress,
+ offerAddress,
+ netmask,
+ gateway,
+ mDnsServers.data(),
+ mDnsServers.size());
+ res = sendMessage(interfaceIndex, serverAddress, ack);
+ if (!res) {
+ ALOGE("Failed to send DHCP ack: %s", res.c_str());
+ }
+}
+
+void DhcpServer::sendNack(const Message& message, unsigned int interfaceIndex) {
+ in_addr_t serverAddress;
+ Result res = getInterfaceAddress(interfaceIndex, &serverAddress);
+ if (!res) {
+ ALOGE("Failed to get address for interface %u: %s",
+ interfaceIndex, res.c_str());
+ return;
+ }
+ Message nack = Message::nack(message, serverAddress);
+ res = sendMessage(interfaceIndex, serverAddress, nack);
+ if (!res) {
+ ALOGE("Failed to send DHCP nack: %s", res.c_str());
+ }
+}
+
+bool DhcpServer::isValidDhcpRequest(const Message& message,
+ unsigned int interfaceIndex) {
+ in_addr_t offerAddress;
+ in_addr_t netmask;
+ in_addr_t gateway;
+ Result res = getOfferAddress(interfaceIndex,
+ message.dhcpData.chaddr,
+ &offerAddress,
+ &netmask,
+ &gateway);
+ if (!res) {
+ ALOGE("Failed to get address for offer: %s", res.c_str());
+ return false;
+ }
+ if (message.requestedIp() != offerAddress) {
+ ALOGE("Client requested a different IP address from the offered one");
+ return false;
+ }
+ return true;
+}
+
+void DhcpServer::updateDnsServers() {
+ char key[64];
+ char value[PROPERTY_VALUE_MAX];
+ mDnsServers.clear();
+ for (int i = 1; i <= kMaxDnsServers; ++i) {
+ snprintf(key, sizeof(key), "net.eth0.dns%d", i);
+ if (property_get(key, value, nullptr) > 0) {
+ struct in_addr address;
+ if (::inet_pton(AF_INET, value, &address) > 0) {
+ mDnsServers.push_back(address.s_addr);
+ }
+ }
+ }
+}
+
+Result DhcpServer::getInterfaceData(unsigned int interfaceIndex,
+ unsigned long type,
+ struct ifreq* response) {
+ char interfaceName[IF_NAMESIZE + 1];
+ if (if_indextoname(interfaceIndex, interfaceName) == nullptr) {
+ return Result::error("Failed to get interface name for index %u: %s",
+ interfaceIndex, strerror(errno));
+ }
+ memset(response, 0, sizeof(*response));
+ response->ifr_addr.sa_family = AF_INET;
+ strncpy(response->ifr_name, interfaceName, IFNAMSIZ - 1);
+
+ if (::ioctl(mSocket.get(), type, response) == -1) {
+ return Result::error("Failed to get data for interface %s: %s",
+ interfaceName, strerror(errno));
+ }
+
+ return Result::success();
+}
+
+Result DhcpServer::getInterfaceAddress(unsigned int interfaceIndex,
+ in_addr_t* address) {
+ struct ifreq data;
+ Result res = getInterfaceData(interfaceIndex, SIOCGIFADDR, &data);
+ if (res.isSuccess()) {
+ auto inAddr = reinterpret_cast<struct sockaddr_in*>(&data.ifr_addr);
+ *address = inAddr->sin_addr.s_addr;
+ }
+ return res;
+}
+
+Result DhcpServer::getInterfaceNetmask(unsigned int interfaceIndex,
+ in_addr_t* address) {
+ struct ifreq data;
+ Result res = getInterfaceData(interfaceIndex, SIOCGIFNETMASK, &data);
+ if (res.isSuccess()) {
+ auto inAddr = reinterpret_cast<struct sockaddr_in*>(&data.ifr_addr);
+ *address = inAddr->sin_addr.s_addr;
+ }
+ return res;
+}
+
+static bool isValidHost(const in_addr_t address,
+ const in_addr_t interfaceAddress,
+ const in_addr_t netmask) {
+ // If the bits outside of the netmask are all zero it's a network address,
+ // don't use this.
+ bool isNetworkAddress = (address & ~netmask) == 0;
+ // If all bits outside of the netmask are set then it's a broadcast address,
+ // don't use this either.
+ bool isBroadcastAddress = (address & ~netmask) == ~netmask;
+ // Don't assign the interface address to a host
+ bool isInterfaceAddress = address == interfaceAddress;
+
+ return !isNetworkAddress && !isBroadcastAddress && !isInterfaceAddress;
+}
+
+static bool addressInRange(const in_addr_t address,
+ const in_addr_t interfaceAddress,
+ const in_addr_t netmask) {
+ if (address <= (interfaceAddress & netmask)) {
+ return false;
+ }
+ if (address >= (interfaceAddress | ~netmask)) {
+ return false;
+ }
+ return true;
+}
+
+Result DhcpServer::getOfferAddress(unsigned int interfaceIndex,
+ const uint8_t* macAddress,
+ in_addr_t* address,
+ in_addr_t* netmask,
+ in_addr_t* gateway) {
+ // The interface address will be the gateway and will be used to determine
+ // the range of valid addresses (along with the netmask) for the client.
+ in_addr_t interfaceAddress = 0;
+ Result res = getInterfaceAddress(interfaceIndex, &interfaceAddress);
+ if (!res) {
+ return res;
+ }
+ // The netmask of the interface will be the netmask for the client as well
+ // as used to determine network range.
+ in_addr_t mask = 0;
+ res = getInterfaceNetmask(interfaceIndex, &mask);
+ if (!res) {
+ return res;
+ }
+
+ // Assign these values now before they are modified below
+ *gateway = interfaceAddress;
+ *netmask = mask;
+
+ Lease key(interfaceIndex, macAddress);
+
+ // Find or create entry, if it's created it will be zero and we update it
+ in_addr_t& value = mLeases[key];
+ if (value == 0) {
+ // Addresses are stored in network byte order so when doing math on them
+ // they have to be converted to host byte order
+ interfaceAddress = ntohl(interfaceAddress);
+ mask = ntohl(mask);
+ // Get a reference to the offset so we can use it and increase it at the
+ // same time. If the entry does not exist it will be created with a
+ // value of zero.
+ in_addr_t& offset = mNextAddressOffsets[interfaceIndex];
+ if (offset == 0) {
+ // Increase if zero to avoid assigning network address
+ ++offset;
+ }
+ // Start out at the first address in the range as determined by netmask
+ in_addr_t nextAddress = (interfaceAddress & mask) + offset;
+
+ // Ensure the address is valid
+ while (!isValidHost(nextAddress, interfaceAddress, mask) &&
+ addressInRange(nextAddress, interfaceAddress, mask)) {
+ ++nextAddress;
+ ++offset;
+ }
+
+ if (addressInRange(nextAddress, interfaceAddress, mask)) {
+ // Convert back to network byte order
+ value = htonl(nextAddress);
+ ++offset;
+ } else {
+ // Ran out of addresses
+ return Result::error("DHCP server is out of addresses");
+ }
+ }
+ *address = value;
+ return Result::success();
+}
+
diff --git a/dhcp/server/dhcpserver.h b/dhcp/server/dhcpserver.h
new file mode 100644
index 00000000..276cd5b1
--- /dev/null
+++ b/dhcp/server/dhcpserver.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright 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.
+ */
+
+#pragma once
+
+#include "lease.h"
+#include "result.h"
+#include "socket.h"
+
+#include <netinet/in.h>
+#include <stdint.h>
+
+#include <unordered_map>
+#include <vector>
+
+class Message;
+
+class DhcpServer {
+public:
+ // Construct a DHCP server. Ignore any requests and discoveries coming on
+ // the network interface identified by |excludeInterface|.
+ explicit DhcpServer(unsigned int excludeInterface);
+
+ Result init();
+ Result run();
+
+private:
+ Result sendMessage(unsigned int interfaceIndex,
+ in_addr_t sourceAddress,
+ const Message& message);
+
+ void sendDhcpOffer(const Message& message, unsigned int interfaceIndex);
+ void sendAck(const Message& message, unsigned int interfaceIndex);
+ void sendNack(const Message& message, unsigned int interfaceIndex);
+
+ bool isValidDhcpRequest(const Message& message,
+ unsigned int interfaceIndex);
+ void updateDnsServers();
+ Result getInterfaceData(unsigned int interfaceIndex,
+ unsigned long type,
+ struct ifreq* response);
+ Result getInterfaceAddress(unsigned int interfaceIndex,
+ in_addr_t* address);
+ Result getInterfaceNetmask(unsigned int interfaceIndex,
+ in_addr_t* netmask);
+ Result getOfferAddress(unsigned int interfaceIndex,
+ const uint8_t* macAddress,
+ in_addr_t* address,
+ in_addr_t* netmask,
+ in_addr_t* gateway);
+
+ Socket mSocket;
+ // This is the next address offset. This will be added to whatever the base
+ // address of the DHCP address range is. For each new MAC address seen this
+ // value will increase by one.
+ std::vector<in_addr_t> mDnsServers;
+ // Map a lease to an IP address for that lease
+ std::unordered_map<Lease, in_addr_t> mLeases;
+ std::unordered_map<unsigned int, in_addr_t> mNextAddressOffsets;
+ unsigned int mExcludeInterface;
+};
+
diff --git a/dhcp/server/lease.h b/dhcp/server/lease.h
new file mode 100644
index 00000000..bad56147
--- /dev/null
+++ b/dhcp/server/lease.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright 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.
+ */
+
+#pragma once
+
+#include <linux/if_ether.h>
+#include <stdint.h>
+
+#include <functional>
+
+// A lease consists of both the interface index and the MAC address. This
+// way the server can run on many different interfaces that have the same
+// client MAC address without giving out the same IP address. The reason
+// this is useful is because we might have several virtual interfaces, one
+// for each access point, that all have the same endpoint on the other side.
+// This endpoint would then have the same MAC address and always get the
+// same address. But for routing purposes it's useful to give it different
+// addresses depending on the server side interface. That way the routing
+// table can be set up so that packets are forwarded to the correct access
+// point interface based on IP address.
+struct Lease {
+ Lease(unsigned int interfaceIndex, const uint8_t* macAddress) {
+ InterfaceIndex = interfaceIndex;
+ memcpy(MacAddress, macAddress, sizeof(MacAddress));
+ }
+ unsigned int InterfaceIndex;
+ uint8_t MacAddress[ETH_ALEN];
+};
+
+template<class T>
+inline void hash_combine(size_t& seed, const T& value) {
+ std::hash<T> hasher;
+ seed ^= hasher(value) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
+}
+
+namespace std {
+template<> struct hash<Lease> {
+ size_t operator()(const Lease& lease) const {
+ size_t seed = 0;
+ hash_combine(seed, lease.InterfaceIndex);
+ // Treat the first 4 bytes as an uint32_t to save some computation
+ hash_combine(seed, *reinterpret_cast<const uint32_t*>(lease.MacAddress));
+ // And the remaining 2 bytes as an uint16_t
+ hash_combine(seed,
+ *reinterpret_cast<const uint16_t*>(lease.MacAddress + 4));
+ return seed;
+ }
+};
+}
+
+inline bool operator==(const Lease& left, const Lease& right) {
+ return left.InterfaceIndex == right.InterfaceIndex &&
+ memcmp(left.MacAddress, right.MacAddress, sizeof(left.MacAddress)) == 0;
+}
diff --git a/network/wifi_forwarder/log.h b/dhcp/server/log.h
index edadc43b..a0f21e08 100644
--- a/network/wifi_forwarder/log.h
+++ b/dhcp/server/log.h
@@ -1,11 +1,11 @@
/*
- * Copyright 2018, The Android Open Source Project
+ * 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
+ * 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,
@@ -13,8 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
#pragma once
-#define LOG_TAG "wifi_forwarder"
+#define LOG_TAG "dhcpserver"
#include <log/log.h>
+
diff --git a/dhcp/server/main.cpp b/dhcp/server/main.cpp
new file mode 100644
index 00000000..482ffd61
--- /dev/null
+++ b/dhcp/server/main.cpp
@@ -0,0 +1,66 @@
+/*
+ * Copyright 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 "dhcpserver.h"
+
+#include "log.h"
+
+#include <arpa/inet.h>
+#include <net/if.h>
+
+static void usage(const char* program) {
+ ALOGE("Usage: %s -i <interface> -r <", program);
+}
+
+int main(int argc, char* argv[]) {
+ char* excludeInterfaceName = nullptr;
+ unsigned int excludeInterfaceIndex = 0;
+ for (int i = 1; i < argc; ++i) {
+ if (strcmp("--exclude-interface", argv[i]) == 0) {
+ if (i + 1 >= argc) {
+ ALOGE("ERROR: Missing argument to "
+ "--exclude-interfaces parameter");
+ usage(argv[0]);
+ return 1;
+ }
+ excludeInterfaceName = argv[i + 1];
+ excludeInterfaceIndex = if_nametoindex(excludeInterfaceName);
+ if (excludeInterfaceIndex == 0) {
+ ALOGE("ERROR: Invalid argument '%s' to --exclude-interface",
+ argv[i + 1]);
+ usage(argv[0]);
+ return 1;
+ }
+ }
+ }
+
+ DhcpServer server(excludeInterfaceIndex);
+ Result res = server.init();
+ if (!res) {
+ ALOGE("Failed to initialize DHCP server: %s\n", res.c_str());
+ return 1;
+ }
+
+ res = server.run();
+ if (!res) {
+ ALOGE("DHCP server failed: %s\n", res.c_str());
+ return 1;
+ }
+ // This is weird and shouldn't happen, the server should run forever.
+ return 0;
+}
+
+
diff --git a/emulator-info.txt b/emulator-info.txt
index f35794e4..6058b939 100644
--- a/emulator-info.txt
+++ b/emulator-info.txt
@@ -1,2 +1,2 @@
# Emulator (stable) version
-require version-emulator=5971124
+require version-emulator=5513838
diff --git a/fingerprint/fingerprint.c b/fingerprint/fingerprint.c
index 507fe13d..8b54c11a 100644
--- a/fingerprint/fingerprint.c
+++ b/fingerprint/fingerprint.c
@@ -123,7 +123,7 @@ static void saveFingerprint(worker_thread_t* listener, int idx) {
return;
}
int nf = fwrite(&listener->fingerid[idx], sizeof(uint64_t), 1, fp);
- if (ns != 1 || nf !=1)
+ if (ns != 1 || ns !=1)
ALOGW("Corrupt emulator fingerprints storage; could not save "
"fingerprints");
diff --git a/fstab.goldfish b/fstab.goldfish
index c626f400..cecc0471 100644
--- a/fstab.goldfish
+++ b/fstab.goldfish
@@ -4,4 +4,5 @@
# specify MF_CHECK, and must come before any filesystems that do specify MF_CHECK
/dev/block/mtdblock0 /system ext4 ro,barrier=1 wait
/dev/block/mtdblock1 /data ext4 noatime,nosuid,nodev,barrier=1,nomblk_io_submit wait,check
+/dev/block/mtdblock2 /cache ext4 noatime,nosuid,nodev wait,check
/devices/platform/goldfish_mmc.0* auto auto defaults voldmanaged=sdcard:auto,encryptable=userdata
diff --git a/fstab.ranchu b/fstab.ranchu
index f4e46e8c..5fcd5cec 100644
--- a/fstab.ranchu
+++ b/fstab.ranchu
@@ -3,6 +3,5 @@
system /system ext4 ro,barrier=1 wait,logical,avb=vbmeta,first_stage_mount
vendor /vendor ext4 ro,barrier=1 wait,logical,first_stage_mount
/dev/block/vdc /data ext4 noatime,nosuid,nodev,nomblk_io_submit,errors=panic wait,check,quota,fileencryption=aes-256-xts:aes-256-cts,reservedsize=128M
-/dev/block/pci/pci0000:00/0000:00:06.0/by-name/metadata /metadata ext4 noatime,nosuid,nodev wait,formattable,first_stage_mount
/devices/*/block/vdf auto auto defaults voldmanaged=sdcard:auto,encryptable=userdata
dev/block/zram0 none swap defaults zramsize=75%
diff --git a/fstab.ranchu.arm.ex b/fstab.ranchu.arm.ex
deleted file mode 100644
index 9946b6aa..00000000
--- a/fstab.ranchu.arm.ex
+++ /dev/null
@@ -1,10 +0,0 @@
-# Android fstab file.
-#<src> <mnt_point> <type> <mnt_flags and options> <fs_mgr_flags>
-# The filesystem that contains the filesystem checker binary (typically /system) cannot
-# specify MF_CHECK, and must come before any filesystems that do specify MF_CHECK
-system /system ext4 ro,barrier=1 wait,logical,first_stage_mount
-vendor /vendor ext4 ro,barrier=1 wait,logical,first_stage_mount
-product /product ext4 ro,barrier=1 wait,logical,first_stage_mount
-system_ext /system_ext ext4 ro,barrier=1 wait,logical,first_stage_mount
-/dev/block/vdc /data ext4 noatime,nosuid,nodev,nomblk_io_submit,errors=panic wait,check,quota
-/devices/*/block/vde auto auto defaults voldmanaged=sdcard:auto,encryptable=userdata
diff --git a/fstab.ranchu.ex b/fstab.ranchu.ex
deleted file mode 100644
index 9dc7eb36..00000000
--- a/fstab.ranchu.ex
+++ /dev/null
@@ -1,10 +0,0 @@
-# Android fstab file.
-#<dev> <mnt_point> <type> <mnt_flags options> <fs_mgr_flags>
-system /system ext4 ro,barrier=1 wait,logical,avb=vbmeta,first_stage_mount
-vendor /vendor ext4 ro,barrier=1 wait,logical,first_stage_mount
-product /product ext4 ro,barrier=1 wait,logical,first_stage_mount
-system_ext /system_ext ext4 ro,barrier=1 wait,logical,first_stage_mount
-/dev/block/vdc /data ext4 noatime,nosuid,nodev,nomblk_io_submit,errors=panic wait,check,quota,fileencryption=aes-256-xts:aes-256-cts,reservedsize=128M
-/dev/block/pci/pci0000:00/0000:00:06.0/by-name/metadata /metadata ext4 noatime,nosuid,nodev wait,formattable,first_stage_mount
-/devices/*/block/vdf auto auto defaults voldmanaged=sdcard:auto,encryptable=userdata
-dev/block/zram0 none swap defaults zramsize=75%
diff --git a/fstab.ranchu.initrd b/fstab.ranchu.initrd
index c3799601..e792febb 100644
--- a/fstab.ranchu.initrd
+++ b/fstab.ranchu.initrd
@@ -2,4 +2,3 @@
#<dev> <mnt_point> <type> <mnt_flags options> <fs_mgr_flags>
system /system ext4 ro,barrier=1 wait,logical,avb=vbmeta,first_stage_mount
vendor /vendor ext4 ro,barrier=1 wait,logical,first_stage_mount
-/dev/block/pci/pci0000:00/0000:00:06.0/by-name/metadata /metadata ext4 noatime,nosuid,nodev wait,formattable,first_stage_mount
diff --git a/fstab.ranchu.initrd.arm.ex b/fstab.ranchu.initrd.arm.ex
deleted file mode 100644
index d9398413..00000000
--- a/fstab.ranchu.initrd.arm.ex
+++ /dev/null
@@ -1,6 +0,0 @@
-# Android fstab file.
-#<dev> <mnt_point> <type> <mnt_flags options> <fs_mgr_flags>
-system /system ext4 ro,barrier=1 wait,logical,first_stage_mount
-vendor /vendor ext4 ro,barrier=1 wait,logical,first_stage_mount
-product /product ext4 ro,barrier=1 wait,logical,first_stage_mount
-system_ext /system_ext ext4 ro,barrier=1 wait,logical,first_stage_mount
diff --git a/fstab.ranchu.initrd.ex b/fstab.ranchu.initrd.ex
deleted file mode 100644
index 971d83a0..00000000
--- a/fstab.ranchu.initrd.ex
+++ /dev/null
@@ -1,7 +0,0 @@
-# Android fstab file for ramdisk
-#<dev> <mnt_point> <type> <mnt_flags options> <fs_mgr_flags>
-system /system ext4 ro,barrier=1 wait,logical,avb=vbmeta,first_stage_mount
-vendor /vendor ext4 ro,barrier=1 wait,logical,first_stage_mount
-product /product ext4 ro,barrier=1 wait,logical,first_stage_mount
-system_ext /system_ext ext4 ro,barrier=1 wait,logical,first_stage_mount
-/dev/block/pci/pci0000:00/0000:00:06.0/by-name/metadata /metadata ext4 noatime,nosuid,nodev wait,formattable,first_stage_mount
diff --git a/fstab.ranchu.initrd.noavb b/fstab.ranchu.initrd.noavb
deleted file mode 100644
index 53da533c..00000000
--- a/fstab.ranchu.initrd.noavb
+++ /dev/null
@@ -1,5 +0,0 @@
-# Android fstab file for ramdisk
-#<dev> <mnt_point> <type> <mnt_flags options> <fs_mgr_flags>
-system /system ext4 ro,barrier=1 wait,logical,first_stage_mount
-vendor /vendor ext4 ro,barrier=1 wait,logical,first_stage_mount
-/dev/block/pci/pci0000:00/0000:00:06.0/by-name/metadata /metadata ext4 noatime,nosuid,nodev wait,formattable,first_stage_mount
diff --git a/fstab.ranchu.initrd.noavb.ex b/fstab.ranchu.initrd.noavb.ex
deleted file mode 100644
index c3be28a7..00000000
--- a/fstab.ranchu.initrd.noavb.ex
+++ /dev/null
@@ -1,7 +0,0 @@
-# Android fstab file for ramdisk
-#<dev> <mnt_point> <type> <mnt_flags options> <fs_mgr_flags>
-system /system ext4 ro,barrier=1 wait,logical,first_stage_mount
-vendor /vendor ext4 ro,barrier=1 wait,logical,first_stage_mount
-product /product ext4 ro,barrier=1 wait,logical,first_stage_mount
-system_ext /system_ext ext4 ro,barrier=1 wait,logical,first_stage_mount
-/dev/block/pci/pci0000:00/0000:00:06.0/by-name/metadata /metadata ext4 noatime,nosuid,nodev wait,formattable,first_stage_mount
diff --git a/fstab.ranchu.noavb b/fstab.ranchu.noavb
deleted file mode 100644
index 88e009df..00000000
--- a/fstab.ranchu.noavb
+++ /dev/null
@@ -1,8 +0,0 @@
-# Android fstab file.
-#<dev> <mnt_point> <type> <mnt_flags options> <fs_mgr_flags>
-system /system ext4 ro,barrier=1 wait,logical,first_stage_mount
-vendor /vendor ext4 ro,barrier=1 wait,logical,first_stage_mount
-/dev/block/vdc /data ext4 noatime,nosuid,nodev,nomblk_io_submit,errors=panic wait,check,quota,fileencryption=aes-256-xts:aes-256-cts,reservedsize=128M
-/dev/block/pci/pci0000:00/0000:00:06.0/by-name/metadata /metadata ext4 noatime,nosuid,nodev wait,formattable,first_stage_mount
-/devices/*/block/vdf auto auto defaults voldmanaged=sdcard:auto,encryptable=userdata
-dev/block/zram0 none swap defaults zramsize=75%
diff --git a/fstab.ranchu.noavb.ex b/fstab.ranchu.noavb.ex
deleted file mode 100644
index 7b4b921f..00000000
--- a/fstab.ranchu.noavb.ex
+++ /dev/null
@@ -1,10 +0,0 @@
-# Android fstab file.
-#<dev> <mnt_point> <type> <mnt_flags options> <fs_mgr_flags>
-system /system ext4 ro,barrier=1 wait,logical,first_stage_mount
-vendor /vendor ext4 ro,barrier=1 wait,logical,first_stage_mount
-product /product ext4 ro,barrier=1 wait,logical,first_stage_mount
-system_ext /system_ext ext4 ro,barrier=1 wait,logical,first_stage_mount
-/dev/block/vdc /data ext4 noatime,nosuid,nodev,nomblk_io_submit,errors=panic wait,check,quota,fileencryption=aes-256-xts:aes-256-cts,reservedsize=128M
-/dev/block/pci/pci0000:00/0000:00:06.0/by-name/metadata /metadata ext4 noatime,nosuid,nodev wait,formattable,first_stage_mount
-/devices/*/block/vdf auto auto defaults voldmanaged=sdcard:auto,encryptable=userdata
-dev/block/zram0 none swap defaults zramsize=75%
diff --git a/fvp.mk b/fvp.mk
deleted file mode 100644
index f403230d..00000000
--- a/fvp.mk
+++ /dev/null
@@ -1,103 +0,0 @@
-#
-# Copyright 2019 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.
-#
-
-PRODUCT_USE_DYNAMIC_PARTITIONS := true
-PRODUCT_FULL_TREBLE_OVERRIDE := true
-
-#
-# All components inherited here go to system image
-#
-$(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit.mk)
-$(call inherit-product, $(SRC_TARGET_DIR)/product/mainline_system.mk)
-
-PRODUCT_ARTIFACT_PATH_REQUIREMENT_WHITELIST += \
- root/init.zygote64_32.rc \
-
-#
-# All components inherited here go to product image
-#
-$(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_product.mk)
-
-#
-# All components inherited here go to vendor image
-#
-$(call inherit-product, $(SRC_TARGET_DIR)/product/media_vendor.mk)
-
-PRODUCT_PACKAGES += \
- android.hardware.audio@2.0-service \
- android.hardware.audio@4.0-impl:32 \
- android.hardware.audio.effect@4.0-impl:32 \
- android.hardware.drm@1.0-service \
- android.hardware.drm@1.0-impl \
- android.hardware.drm@1.2-service.clearkey \
- android.hardware.gatekeeper@1.0-service.software \
- android.hardware.graphics.allocator@2.0-service \
- android.hardware.graphics.allocator@2.0-impl \
- android.hardware.graphics.composer@2.1-service \
- android.hardware.graphics.composer@2.1-impl \
- android.hardware.graphics.mapper@2.0-impl \
- android.hardware.health@2.0-service.goldfish \
- android.hardware.keymaster@4.0-service \
- android.hardware.keymaster@4.0-impl \
- libEGL_swiftshader \
- libGLESv1_CM_swiftshader \
- libGLESv2_swiftshader \
-
-PRODUCT_PACKAGE_OVERLAYS := device/generic/goldfish/overlay
-
-PRODUCT_NAME := fvp
-PRODUCT_DEVICE := fvpbase
-PRODUCT_BRAND := Android
-PRODUCT_MODEL := AOSP on FVP
-
-PRODUCT_COPY_FILES += \
- device/generic/goldfish/data/etc/handheld_core_hardware.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/handheld_core_hardware.xml \
- frameworks/native/data/etc/android.hardware.ethernet.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.ethernet.xml \
- device/generic/goldfish/fvpbase/fstab.fvpbase:$(TARGET_COPY_OUT_VENDOR)/etc/fstab.fvpbase \
- device/generic/goldfish/fvpbase/fstab.fvpbase.initrd:$(TARGET_COPY_OUT_RAMDISK)/fstab.fvpbase \
- device/generic/goldfish/fvpbase/init.fvpbase.rc:$(TARGET_COPY_OUT_VENDOR)/etc/init/hw/init.fvpbase.rc \
- device/generic/goldfish/fvpbase/init.insmod.sh:$(TARGET_COPY_OUT_VENDOR)/bin/init.insmod.sh \
- frameworks/av/services/audiopolicy/config/audio_policy_configuration_generic.xml:$(TARGET_COPY_OUT_VENDOR)/etc/audio_policy_configuration.xml \
- frameworks/av/services/audiopolicy/config/primary_audio_policy_configuration.xml:$(TARGET_COPY_OUT_VENDOR)/etc/primary_audio_policy_configuration.xml \
- frameworks/av/services/audiopolicy/config/r_submix_audio_policy_configuration.xml:$(TARGET_COPY_OUT_VENDOR)/etc/r_submix_audio_policy_configuration.xml \
- frameworks/av/services/audiopolicy/config/audio_policy_volumes.xml:$(TARGET_COPY_OUT_VENDOR)/etc/audio_policy_volumes.xml \
- frameworks/av/services/audiopolicy/config/default_volume_tables.xml:$(TARGET_COPY_OUT_VENDOR)/etc/default_volume_tables.xml \
- frameworks/av/services/audiopolicy/config/surround_sound_configuration_5_0.xml:$(TARGET_COPY_OUT_VENDOR)/etc/surround_sound_configuration_5_0.xml \
-
-PRODUCT_DEFAULT_PROPERTY_OVERRIDES += \
- ro.hardware.egl=swiftshader \
- debug.sf.nobootanimation=1 \
-
-PRODUCT_REQUIRES_INSECURE_EXECMEM_FOR_SWIFTSHADER := true
-
-# It's almost always faster to dexopt on the host even in eng builds.
-WITH_DEXPREOPT_BOOT_IMG_AND_SYSTEM_SERVER_ONLY := false
-
-BOARD_VENDOR_KERNEL_MODULES := \
- $(OUT_DIR)/target/product/$(PRODUCT_DEVICE)/boot/amba-clcd.ko \
- $(OUT_DIR)/target/product/$(PRODUCT_DEVICE)/boot/ambakmi.ko \
- $(OUT_DIR)/target/product/$(PRODUCT_DEVICE)/boot/armmmci.ko \
- $(OUT_DIR)/target/product/$(PRODUCT_DEVICE)/boot/cfbcopyarea.ko \
- $(OUT_DIR)/target/product/$(PRODUCT_DEVICE)/boot/cfbfillrect.ko \
- $(OUT_DIR)/target/product/$(PRODUCT_DEVICE)/boot/cfbimgblt.ko \
- $(OUT_DIR)/target/product/$(PRODUCT_DEVICE)/boot/fb.ko \
- $(OUT_DIR)/target/product/$(PRODUCT_DEVICE)/boot/fixed.ko \
- $(OUT_DIR)/target/product/$(PRODUCT_DEVICE)/boot/mmc_block.ko \
- $(OUT_DIR)/target/product/$(PRODUCT_DEVICE)/boot/mmc_core.ko \
- $(OUT_DIR)/target/product/$(PRODUCT_DEVICE)/boot/mousedev.ko \
- $(OUT_DIR)/target/product/$(PRODUCT_DEVICE)/boot/psmouse.ko
-
-DEVICE_MANIFEST_FILE := device/generic/goldfish/fvpbase/manifest.xml
diff --git a/fvpbase/BoardConfig.mk b/fvpbase/BoardConfig.mk
deleted file mode 100644
index 234645e7..00000000
--- a/fvpbase/BoardConfig.mk
+++ /dev/null
@@ -1,51 +0,0 @@
-# Copyright (C) 2019 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.
-#
-
-TARGET_ARCH := arm64
-TARGET_ARCH_VARIANT := armv8-a
-TARGET_CPU_VARIANT := generic
-TARGET_CPU_ABI := arm64-v8a
-
-TARGET_2ND_ARCH := arm
-TARGET_2ND_CPU_ABI := armeabi-v7a
-TARGET_2ND_CPU_ABI2 := armeabi
-TARGET_2ND_ARCH_VARIANT := armv8-a
-TARGET_2ND_CPU_VARIANT := generic
-
-include build/make/target/board/BoardConfigMainlineCommon.mk
-
-TARGET_NO_KERNEL := true
-
-BOARD_USES_SYSTEM_OTHER_ODEX :=
-
-BUILD_QEMU_IMAGES := true
-TARGET_USERIMAGES_SPARSE_EXT_DISABLED := true
-
-BOARD_BUILD_SUPER_IMAGE_BY_DEFAULT := true
-
-BOARD_SUPER_PARTITION_SIZE := 3229614080
-BOARD_SUPER_PARTITION_GROUPS := fvp_dynamic_partitions
-BOARD_FVP_DYNAMIC_PARTITIONS_SIZE := 3221225472
-BOARD_FVP_DYNAMIC_PARTITIONS_PARTITION_LIST := system vendor
-TARGET_COPY_OUT_PRODUCT := system/product
-TARGET_COPY_OUT_SYSTEM_EXT := system/system_ext
-
-BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE := ext4
-
-BOARD_USERDATAIMAGE_PARTITION_SIZE := 576716800
-
-BOARD_SEPOLICY_DIRS += device/generic/goldfish/fvpbase/sepolicy
-
-TARGET_EXPERIMENTAL_MTE := true
diff --git a/fvpbase/fstab.fvpbase b/fvpbase/fstab.fvpbase
deleted file mode 100644
index 6c62809c..00000000
--- a/fvpbase/fstab.fvpbase
+++ /dev/null
@@ -1,8 +0,0 @@
-# Android fstab file.
-#<src> <mnt_point> <type> <mnt_flags and options> <fs_mgr_flags>
-# The filesystem that contains the filesystem checker binary (typically /system) cannot
-# specify MF_CHECK, and must come before any filesystems that do specify MF_CHECK
-system /system ext4 ro,barrier=1 wait,logical,first_stage_mount
-vendor /vendor ext4 ro,barrier=1 wait,logical,first_stage_mount
-/dev/block/mmcblk0 /data ext4 noatime,nosuid,nodev,nomblk_io_submit,errors=panic wait,check,quota
-/devices/*/block/vde auto auto defaults voldmanaged=sdcard:auto,encryptable=userdata
diff --git a/fvpbase/fstab.fvpbase.initrd b/fvpbase/fstab.fvpbase.initrd
deleted file mode 100644
index 56056634..00000000
--- a/fvpbase/fstab.fvpbase.initrd
+++ /dev/null
@@ -1,4 +0,0 @@
-# Android fstab file.
-#<dev> <mnt_point> <type> <mnt_flags options> <fs_mgr_flags>
-system /system ext4 ro,barrier=1 wait,logical,first_stage_mount
-vendor /vendor ext4 ro,barrier=1 wait,logical,first_stage_mount
diff --git a/fvpbase/init.fvpbase.rc b/fvpbase/init.fvpbase.rc
deleted file mode 100644
index 41b6d7cf..00000000
--- a/fvpbase/init.fvpbase.rc
+++ /dev/null
@@ -1,12 +0,0 @@
-service insmod_sh /vendor/bin/init.insmod.sh
- user root
- group root system
- disabled
- oneshot
-
-on init
- start insmod_sh
-
-on fs
- wait_for_prop vendor.all.modules.ready 1
- mount_all /vendor/etc/fstab.fvpbase
diff --git a/fvpbase/init.insmod.sh b/fvpbase/init.insmod.sh
deleted file mode 100644
index f06a3827..00000000
--- a/fvpbase/init.insmod.sh
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/vendor/bin/sh -e
-
-insmod /vendor/lib/modules/fb.ko
-insmod /vendor/lib/modules/cfbcopyarea.ko
-insmod /vendor/lib/modules/cfbfillrect.ko
-insmod /vendor/lib/modules/cfbimgblt.ko
-insmod /vendor/lib/modules/amba-clcd.ko
-
-insmod /vendor/lib/modules/fixed.ko
-insmod /vendor/lib/modules/mmc_core.ko
-insmod /vendor/lib/modules/mmc_block.ko
-insmod /vendor/lib/modules/armmmci.ko
-
-insmod /vendor/lib/modules/ambakmi.ko
-insmod /vendor/lib/modules/mousedev.ko
-insmod /vendor/lib/modules/psmouse.ko
-
-setprop vendor.all.modules.ready 1
diff --git a/fvpbase/manifest.xml b/fvpbase/manifest.xml
deleted file mode 100644
index bd369aee..00000000
--- a/fvpbase/manifest.xml
+++ /dev/null
@@ -1,102 +0,0 @@
-<manifest version="1.0" type="device" target-level="3">
- <hal format="hidl">
- <name>android.hardware.audio</name>
- <transport>hwbinder</transport>
- <version>4.0</version>
- <interface>
- <name>IDevicesFactory</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl">
- <name>android.hardware.audio.effect</name>
- <transport>hwbinder</transport>
- <version>4.0</version>
- <interface>
- <name>IEffectsFactory</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl">
- <name>android.hardware.configstore</name>
- <transport>hwbinder</transport>
- <version>1.1</version>
- <interface>
- <name>ISurfaceFlingerConfigs</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl">
- <name>android.hardware.drm</name>
- <transport>hwbinder</transport>
- <version>1.0</version>
- <interface>
- <name>ICryptoFactory</name>
- <instance>default</instance>
- </interface>
- <interface>
- <name>IDrmFactory</name>
- <instance>default</instance>
- </interface>
- <fqname>@1.2::ICryptoFactory/clearkey</fqname>
- <fqname>@1.2::IDrmFactory/clearkey</fqname>
- </hal>
- <hal format="hidl">
- <name>android.hardware.graphics.allocator</name>
- <transport>hwbinder</transport>
- <version>2.0</version>
- <interface>
- <name>IAllocator</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl">
- <name>android.hardware.graphics.composer</name>
- <transport>hwbinder</transport>
- <version>2.1</version>
- <interface>
- <name>IComposer</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl">
- <name>android.hardware.graphics.mapper</name>
- <transport arch="32+64">passthrough</transport>
- <version>2.0</version>
- <interface>
- <name>IMapper</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl">
- <name>android.hardware.health</name>
- <transport>hwbinder</transport>
- <version>2.0</version>
- <interface>
- <name>IHealth</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl">
- <name>android.hardware.keymaster</name>
- <transport>hwbinder</transport>
- <version>4.0</version>
- <interface>
- <name>IKeymasterDevice</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl">
- <name>android.hardware.media.omx</name>
- <transport>hwbinder</transport>
- <version>1.0</version>
- <interface>
- <name>IOmx</name>
- <instance>default</instance>
- </interface>
- <interface>
- <name>IOmxStore</name>
- <instance>default</instance>
- </interface>
- </hal>
-</manifest>
diff --git a/fvpbase/sepolicy/file.te b/fvpbase/sepolicy/file.te
deleted file mode 100644
index b3bd582b..00000000
--- a/fvpbase/sepolicy/file.te
+++ /dev/null
@@ -1 +0,0 @@
-type varrun_file, file_type, data_file_type, mlstrustedobject;
diff --git a/fvpbase/sepolicy/file_contexts b/fvpbase/sepolicy/file_contexts
deleted file mode 100644
index 29ff279c..00000000
--- a/fvpbase/sepolicy/file_contexts
+++ /dev/null
@@ -1,8 +0,0 @@
-/data/vendor/var/run(/.*)? u:object_r:varrun_file:s0
-/dev/block/mmcblk0 u:object_r:userdata_block_device:s0
-/vendor/bin/hw/android\.hardware\.gatekeeper@1\.0-service.software u:object_r:hal_gatekeeper_default_exec:s0
-/vendor/bin/hw/android\.hardware\.health@2\.0-service.goldfish u:object_r:hal_health_default_exec:s0
-/vendor/bin/init\.insmod\.sh u:object_r:init_insmod_sh_exec:s0
-/vendor/lib(64)?/libEGL_swiftshader\.so u:object_r:same_process_hal_file:s0
-/vendor/lib(64)?/libGLESv1_CM_swiftshader\.so u:object_r:same_process_hal_file:s0
-/vendor/lib(64)?/libGLESv2_swiftshader\.so u:object_r:same_process_hal_file:s0
diff --git a/fvpbase/sepolicy/hal_graphics_allocator_default.te b/fvpbase/sepolicy/hal_graphics_allocator_default.te
deleted file mode 100644
index 6676f578..00000000
--- a/fvpbase/sepolicy/hal_graphics_allocator_default.te
+++ /dev/null
@@ -1,4 +0,0 @@
-allow hal_graphics_allocator_default graphics_device:dir search;
-allow hal_graphics_allocator_default graphics_device:chr_file { ioctl open read write map rw_file_perms };
-allow hal_graphics_allocator_default dumpstate:fd use;
-allow hal_graphics_allocator_default dumpstate:fifo_file write;
diff --git a/fvpbase/sepolicy/healthd.te b/fvpbase/sepolicy/healthd.te
deleted file mode 100644
index 80db9b72..00000000
--- a/fvpbase/sepolicy/healthd.te
+++ /dev/null
@@ -1,4 +0,0 @@
-# Allow to read /sys/class/power_supply directory
-allow healthd sysfs:dir r_dir_perms;
-
-allow healthd self:capability2 wake_alarm;
diff --git a/fvpbase/sepolicy/init_insmod_sh.te b/fvpbase/sepolicy/init_insmod_sh.te
deleted file mode 100644
index 52a0ad84..00000000
--- a/fvpbase/sepolicy/init_insmod_sh.te
+++ /dev/null
@@ -1,14 +0,0 @@
-type init_insmod_sh, domain;
-type init_insmod_sh_exec, exec_type, vendor_file_type, file_type;
-
-init_daemon_domain(init_insmod_sh)
-
-allow init_insmod_sh vendor_shell_exec:file rx_file_perms;
-allow init_insmod_sh vendor_toolbox_exec:file rx_file_perms;
-
-# Set the vendor.all.modules.ready property
-set_prop(init_insmod_sh, vendor_device_prop)
-
-# Allow insmod
-allow init_insmod_sh self:capability sys_module;
-allow init_insmod_sh vendor_file:system module_load;
diff --git a/fvpbase/sepolicy/property.te b/fvpbase/sepolicy/property.te
deleted file mode 100644
index f014ad52..00000000
--- a/fvpbase/sepolicy/property.te
+++ /dev/null
@@ -1 +0,0 @@
-type vendor_device_prop, property_type;
diff --git a/fvpbase/sepolicy/property_contexts b/fvpbase/sepolicy/property_contexts
deleted file mode 100644
index c389bdd3..00000000
--- a/fvpbase/sepolicy/property_contexts
+++ /dev/null
@@ -1 +0,0 @@
-vendor.all.modules.ready u:object_r:vendor_device_prop:s0
diff --git a/fvpbase/sepolicy/surfaceflinger.te b/fvpbase/sepolicy/surfaceflinger.te
deleted file mode 100644
index 95236305..00000000
--- a/fvpbase/sepolicy/surfaceflinger.te
+++ /dev/null
@@ -1 +0,0 @@
-allow surfaceflinger self:process execmem;
diff --git a/gatekeeper/Android.mk b/gatekeeper/Android.mk
new file mode 100644
index 00000000..0cb2c150
--- /dev/null
+++ b/gatekeeper/Android.mk
@@ -0,0 +1,45 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_VENDOR_MODULE := true
+LOCAL_MODULE := gatekeeper.ranchu
+LOCAL_MODULE_RELATIVE_PATH := hw
+
+LOCAL_CFLAGS := -Wall -Wextra -Werror -Wunused
+LOCAL_SRC_FILES := \
+ module.cpp \
+ SoftGateKeeperDevice.cpp
+
+
+LOCAL_SHARED_LIBRARIES := \
+ libbinder \
+ libgatekeeper \
+ liblog \
+ libhardware \
+ libbase \
+ libutils \
+ libcrypto \
+ libhidlbase \
+ libhidltransport \
+ libhwbinder \
+ android.hardware.gatekeeper@1.0 \
+
+LOCAL_STATIC_LIBRARIES := libscrypt_static
+LOCAL_C_INCLUDES := external/scrypt/lib/crypto
+include $(BUILD_SHARED_LIBRARY)
diff --git a/gatekeeper/SoftGateKeeper.h b/gatekeeper/SoftGateKeeper.h
new file mode 100644
index 00000000..2f4f4d7e
--- /dev/null
+++ b/gatekeeper/SoftGateKeeper.h
@@ -0,0 +1,182 @@
+/*
+ * Copyright 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.
+ *
+ */
+
+#ifndef SOFT_GATEKEEPER_H_
+#define SOFT_GATEKEEPER_H_
+
+extern "C" {
+#include <openssl/rand.h>
+#include <openssl/sha.h>
+
+#include <crypto_scrypt.h>
+}
+
+#include <android-base/memory.h>
+#include <gatekeeper/gatekeeper.h>
+
+#include <iostream>
+#include <unordered_map>
+#include <memory>
+
+namespace gatekeeper {
+
+struct fast_hash_t {
+ uint64_t salt;
+ uint8_t digest[SHA256_DIGEST_LENGTH];
+};
+
+class SoftGateKeeper : public GateKeeper {
+public:
+ static const uint32_t SIGNATURE_LENGTH_BYTES = 32;
+
+ // scrypt params
+ static const uint64_t N = 16384;
+ static const uint32_t r = 8;
+ static const uint32_t p = 1;
+
+ static const int MAX_UINT_32_CHARS = 11;
+
+ SoftGateKeeper() {
+ key_.reset(new uint8_t[SIGNATURE_LENGTH_BYTES]);
+ memset(key_.get(), 0, SIGNATURE_LENGTH_BYTES);
+ }
+
+ virtual ~SoftGateKeeper() {
+ }
+
+ virtual bool GetAuthTokenKey(const uint8_t **auth_token_key,
+ uint32_t *length) const {
+ if (auth_token_key == NULL || length == NULL) return false;
+ uint8_t *auth_token_key_copy = new uint8_t[SIGNATURE_LENGTH_BYTES];
+ memcpy(auth_token_key_copy, key_.get(), SIGNATURE_LENGTH_BYTES);
+
+ *auth_token_key = auth_token_key_copy;
+ *length = SIGNATURE_LENGTH_BYTES;
+ return true;
+ }
+
+ virtual void GetPasswordKey(const uint8_t **password_key, uint32_t *length) {
+ if (password_key == NULL || length == NULL) return;
+ uint8_t *password_key_copy = new uint8_t[SIGNATURE_LENGTH_BYTES];
+ memcpy(password_key_copy, key_.get(), SIGNATURE_LENGTH_BYTES);
+
+ *password_key = password_key_copy;
+ *length = SIGNATURE_LENGTH_BYTES;
+ }
+
+ virtual void ComputePasswordSignature(uint8_t *signature, uint32_t signature_length,
+ const uint8_t *, uint32_t, const uint8_t *password,
+ uint32_t password_length, salt_t salt) const {
+ if (signature == NULL) return;
+ crypto_scrypt(password, password_length, reinterpret_cast<uint8_t *>(&salt),
+ sizeof(salt), N, r, p, signature, signature_length);
+ }
+
+ virtual void GetRandom(void *random, uint32_t requested_length) const {
+ if (random == NULL) return;
+ RAND_pseudo_bytes((uint8_t *) random, requested_length);
+ }
+
+ virtual void ComputeSignature(uint8_t *signature, uint32_t signature_length,
+ const uint8_t *, uint32_t, const uint8_t *, const uint32_t) const {
+ if (signature == NULL) return;
+ memset(signature, 0, signature_length);
+ }
+
+ virtual uint64_t GetMillisecondsSinceBoot() const {
+ struct timespec time;
+ int res = clock_gettime(CLOCK_BOOTTIME, &time);
+ if (res < 0) return 0;
+ return (time.tv_sec * 1000) + (time.tv_nsec / 1000 / 1000);
+ }
+
+ virtual bool IsHardwareBacked() const {
+ return false;
+ }
+
+ virtual bool GetFailureRecord(uint32_t uid, secure_id_t user_id, failure_record_t *record,
+ bool /* secure */) {
+ failure_record_t *stored = &failure_map_[uid];
+ if (user_id != stored->secure_user_id) {
+ stored->secure_user_id = user_id;
+ stored->last_checked_timestamp = 0;
+ stored->failure_counter = 0;
+ }
+ memcpy(record, stored, sizeof(*record));
+ return true;
+ }
+
+ virtual bool ClearFailureRecord(uint32_t uid, secure_id_t user_id, bool /* secure */) {
+ failure_record_t *stored = &failure_map_[uid];
+ stored->secure_user_id = user_id;
+ stored->last_checked_timestamp = 0;
+ stored->failure_counter = 0;
+ return true;
+ }
+
+ virtual bool WriteFailureRecord(uint32_t uid, failure_record_t *record, bool /* secure */) {
+ failure_map_[uid] = *record;
+ return true;
+ }
+
+ fast_hash_t ComputeFastHash(const SizedBuffer &password, uint64_t salt) {
+ fast_hash_t fast_hash;
+ size_t digest_size = password.length + sizeof(salt);
+ std::unique_ptr<uint8_t[]> digest(new uint8_t[digest_size]);
+ memcpy(digest.get(), &salt, sizeof(salt));
+ memcpy(digest.get() + sizeof(salt), password.buffer.get(), password.length);
+
+ SHA256(digest.get(), digest_size, (uint8_t *) &fast_hash.digest);
+
+ fast_hash.salt = salt;
+ return fast_hash;
+ }
+
+ bool VerifyFast(const fast_hash_t &fast_hash, const SizedBuffer &password) {
+ fast_hash_t computed = ComputeFastHash(password, fast_hash.salt);
+ return memcmp(computed.digest, fast_hash.digest, SHA256_DIGEST_LENGTH) == 0;
+ }
+
+ bool DoVerify(const password_handle_t *expected_handle, const SizedBuffer &password) {
+ uint64_t user_id = android::base::get_unaligned<secure_id_t>(&expected_handle->user_id);
+ FastHashMap::const_iterator it = fast_hash_map_.find(user_id);
+ if (it != fast_hash_map_.end() && VerifyFast(it->second, password)) {
+ return true;
+ } else {
+ if (GateKeeper::DoVerify(expected_handle, password)) {
+ uint64_t salt;
+ GetRandom(&salt, sizeof(salt));
+ fast_hash_map_[user_id] = ComputeFastHash(password, salt);
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+private:
+
+ typedef std::unordered_map<uint32_t, failure_record_t> FailureRecordMap;
+ typedef std::unordered_map<uint64_t, fast_hash_t> FastHashMap;
+
+ std::unique_ptr<uint8_t[]> key_;
+ FailureRecordMap failure_map_;
+ FastHashMap fast_hash_map_;
+};
+}
+
+#endif // SOFT_GATEKEEPER_H_
diff --git a/gatekeeper/SoftGateKeeperDevice.cpp b/gatekeeper/SoftGateKeeperDevice.cpp
new file mode 100644
index 00000000..3dc69977
--- /dev/null
+++ b/gatekeeper/SoftGateKeeperDevice.cpp
@@ -0,0 +1,116 @@
+/*
+ * 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.
+ */
+#include "SoftGateKeeper.h"
+#include "SoftGateKeeperDevice.h"
+
+namespace goldfish {
+
+int SoftGateKeeperDevice::enroll(uint32_t uid,
+ const uint8_t *current_password_handle, uint32_t current_password_handle_length,
+ const uint8_t *current_password, uint32_t current_password_length,
+ const uint8_t *desired_password, uint32_t desired_password_length,
+ uint8_t **enrolled_password_handle, uint32_t *enrolled_password_handle_length) {
+
+ if (enrolled_password_handle == NULL || enrolled_password_handle_length == NULL ||
+ desired_password == NULL || desired_password_length == 0)
+ return -EINVAL;
+
+ // Current password and current password handle go together
+ if (current_password_handle == NULL || current_password_handle_length == 0 ||
+ current_password == NULL || current_password_length == 0) {
+ current_password_handle = NULL;
+ current_password_handle_length = 0;
+ current_password = NULL;
+ current_password_length = 0;
+ }
+
+ SizedBuffer desired_password_buffer(desired_password_length);
+ memcpy(desired_password_buffer.buffer.get(), desired_password, desired_password_length);
+
+ SizedBuffer current_password_handle_buffer(current_password_handle_length);
+ if (current_password_handle) {
+ memcpy(current_password_handle_buffer.buffer.get(), current_password_handle,
+ current_password_handle_length);
+ }
+
+ SizedBuffer current_password_buffer(current_password_length);
+ if (current_password) {
+ memcpy(current_password_buffer.buffer.get(), current_password, current_password_length);
+ }
+
+ EnrollRequest request(uid, &current_password_handle_buffer, &desired_password_buffer,
+ &current_password_buffer);
+ EnrollResponse response;
+
+ impl_->Enroll(request, &response);
+
+ if (response.error == ERROR_RETRY) {
+ return response.retry_timeout;
+ } else if (response.error != ERROR_NONE) {
+ return -EINVAL;
+ }
+
+ *enrolled_password_handle = response.enrolled_password_handle.buffer.release();
+ gatekeeper::password_handle_t *handle =
+ reinterpret_cast<gatekeeper::password_handle_t *>(*enrolled_password_handle);
+ //FIXIT: We need to move this module to host with gatekeeper pipe
+ handle->hardware_backed = true;
+
+ *enrolled_password_handle_length = response.enrolled_password_handle.length;
+ return 0;
+}
+
+int SoftGateKeeperDevice::verify(uint32_t uid,
+ uint64_t challenge, const uint8_t *enrolled_password_handle,
+ uint32_t enrolled_password_handle_length, const uint8_t *provided_password,
+ uint32_t provided_password_length, uint8_t **auth_token, uint32_t *auth_token_length,
+ bool *request_reenroll) {
+
+ if (enrolled_password_handle == NULL ||
+ provided_password == NULL) {
+ return -EINVAL;
+ }
+
+ SizedBuffer password_handle_buffer(enrolled_password_handle_length);
+ memcpy(password_handle_buffer.buffer.get(), enrolled_password_handle,
+ enrolled_password_handle_length);
+ SizedBuffer provided_password_buffer(provided_password_length);
+ memcpy(provided_password_buffer.buffer.get(), provided_password, provided_password_length);
+
+ VerifyRequest request(uid, challenge, &password_handle_buffer, &provided_password_buffer);
+ VerifyResponse response;
+
+ impl_->Verify(request, &response);
+
+ if (response.error == ERROR_RETRY) {
+ return response.retry_timeout;
+ } else if (response.error != ERROR_NONE) {
+ return -EINVAL;
+ }
+
+ if (auth_token != NULL && auth_token_length != NULL) {
+ *auth_token = response.auth_token.buffer.release();
+ *auth_token_length = response.auth_token.length;
+ }
+
+ if (request_reenroll != NULL) {
+ *request_reenroll = response.request_reenroll;
+ }
+
+ return 0;
+}
+
+} // namespace goldfish
diff --git a/gatekeeper/SoftGateKeeperDevice.h b/gatekeeper/SoftGateKeeperDevice.h
new file mode 100644
index 00000000..af3a1bc5
--- /dev/null
+++ b/gatekeeper/SoftGateKeeperDevice.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright 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.
+ */
+
+#ifndef SOFT_GATEKEEPER_DEVICE_H_
+#define SOFT_GATEKEEPER_DEVICE_H_
+
+#include "SoftGateKeeper.h"
+
+#include <memory>
+
+using namespace gatekeeper;
+
+namespace goldfish {
+
+/**
+ * Software based GateKeeper implementation
+ */
+class SoftGateKeeperDevice {
+public:
+ SoftGateKeeperDevice() {
+ impl_.reset(new SoftGateKeeper());
+ }
+
+ // Wrappers to translate the gatekeeper HAL API to the Kegyuard Messages API.
+
+ /**
+ * Enrolls password_payload, which should be derived from a user selected pin or password,
+ * with the authentication factor private key used only for enrolling authentication
+ * factor data.
+ *
+ * Returns: 0 on success or an error code less than 0 on error.
+ * On error, enrolled_password_handle will not be allocated.
+ */
+ int enroll(uint32_t uid,
+ const uint8_t *current_password_handle, uint32_t current_password_handle_length,
+ const uint8_t *current_password, uint32_t current_password_length,
+ const uint8_t *desired_password, uint32_t desired_password_length,
+ uint8_t **enrolled_password_handle, uint32_t *enrolled_password_handle_length);
+
+ /**
+ * Verifies provided_password matches enrolled_password_handle.
+ *
+ * Implementations of this module may retain the result of this call
+ * to attest to the recency of authentication.
+ *
+ * On success, writes the address of a verification token to auth_token,
+ * usable to attest password verification to other trusted services. Clients
+ * may pass NULL for this value.
+ *
+ * Returns: 0 on success or an error code less than 0 on error
+ * On error, verification token will not be allocated
+ */
+ int verify(uint32_t uid, uint64_t challenge,
+ const uint8_t *enrolled_password_handle, uint32_t enrolled_password_handle_length,
+ const uint8_t *provided_password, uint32_t provided_password_length,
+ uint8_t **auth_token, uint32_t *auth_token_length, bool *request_reenroll);
+private:
+ std::unique_ptr<SoftGateKeeper> impl_;
+};
+
+} // namespace gatekeeper
+
+#endif //SOFT_GATEKEEPER_DEVICE_H_
diff --git a/gatekeeper/module.cpp b/gatekeeper/module.cpp
new file mode 100644
index 00000000..3bcfe15a
--- /dev/null
+++ b/gatekeeper/module.cpp
@@ -0,0 +1,127 @@
+/*
+ * 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.
+ */
+
+#include <hardware/hardware.h>
+#include <hardware/gatekeeper.h>
+#define LOG_TAG "GoldfishGatekeeper"
+#include <log/log.h>
+
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+#include "SoftGateKeeper.h"
+#include "SoftGateKeeperDevice.h"
+
+using goldfish::SoftGateKeeperDevice;
+
+struct goldfish_gatekeeper_device {
+ gatekeeper_device device;
+ SoftGateKeeperDevice *s_gatekeeper;
+};
+
+static goldfish_gatekeeper_device s_device;
+
+static int enroll(const struct gatekeeper_device *dev __unused, uint32_t uid,
+ const uint8_t *current_password_handle, uint32_t current_password_handle_length,
+ const uint8_t *current_password, uint32_t current_password_length,
+ const uint8_t *desired_password, uint32_t desired_password_length,
+ uint8_t **enrolled_password_handle, uint32_t *enrolled_password_handle_length) {
+
+ SoftGateKeeperDevice *s_gatekeeper = ((goldfish_gatekeeper_device*)(dev))->s_gatekeeper;
+ ALOGE("called %s with gate keeper %p device %p\n", __func__, s_gatekeeper, dev);
+ if (s_gatekeeper == nullptr) {
+ abort();
+ return -EINVAL;
+ }
+
+ return s_gatekeeper->enroll(uid,
+ current_password_handle, current_password_handle_length,
+ current_password, current_password_length,
+ desired_password, desired_password_length,
+ enrolled_password_handle, enrolled_password_handle_length);
+}
+
+static int verify(const struct gatekeeper_device *dev __unused, uint32_t uid, uint64_t challenge,
+ const uint8_t *enrolled_password_handle, uint32_t enrolled_password_handle_length,
+ const uint8_t *provided_password, uint32_t provided_password_length,
+ uint8_t **auth_token, uint32_t *auth_token_length, bool *request_reenroll) {
+ SoftGateKeeperDevice *s_gatekeeper = ((goldfish_gatekeeper_device*)(dev))->s_gatekeeper;
+ ALOGE("called %s with gate keeper %p device %p\n", __func__, s_gatekeeper, dev);
+ if (s_gatekeeper == nullptr) return -EINVAL;
+ return s_gatekeeper->verify(uid, challenge,
+ enrolled_password_handle, enrolled_password_handle_length,
+ provided_password, provided_password_length,
+ auth_token, auth_token_length, request_reenroll);
+}
+
+static int close_device(hw_device_t* dev __unused) {
+ SoftGateKeeperDevice *s_gatekeeper = ((goldfish_gatekeeper_device*)(dev))->s_gatekeeper;
+ if (s_gatekeeper == nullptr) return 0;
+ delete s_gatekeeper;
+ s_gatekeeper = nullptr;
+ ALOGE("called %s with gate keeper %p device %p\n", __func__, s_gatekeeper, dev);
+ return 0;
+}
+
+static int goldfish_gatekeeper_open(const hw_module_t *module, const char *name,
+ hw_device_t **device) {
+
+ if (strcmp(name, HARDWARE_GATEKEEPER) != 0) {
+ abort();
+ return -EINVAL;
+ }
+
+ memset(&s_device, 0, sizeof(s_device));
+
+ SoftGateKeeperDevice *s_gatekeeper = new SoftGateKeeperDevice();
+ if (s_gatekeeper == nullptr) return -ENOMEM;
+
+ s_device.s_gatekeeper = s_gatekeeper;
+
+ s_device.device.common.tag = HARDWARE_DEVICE_TAG;
+ s_device.device.common.version = 1;
+ s_device.device.common.module = const_cast<hw_module_t *>(module);
+ s_device.device.common.close = close_device;
+
+ s_device.device.enroll = enroll;
+ s_device.device.verify = verify;
+ s_device.device.delete_user = nullptr;
+ s_device.device.delete_all_users = nullptr;
+
+ *device = &s_device.device.common;
+ ALOGE("called %s with gate keeper %p device %p\n", __func__, s_gatekeeper, *device);
+
+ return 0;
+}
+
+static struct hw_module_methods_t gatekeeper_module_methods = {
+ .open = goldfish_gatekeeper_open,
+};
+
+struct gatekeeper_module HAL_MODULE_INFO_SYM __attribute__((visibility("default"))) = {
+ .common = {
+ .tag = HARDWARE_MODULE_TAG,
+ .module_api_version = GATEKEEPER_MODULE_API_VERSION_0_1,
+ .hal_api_version = HARDWARE_HAL_API_VERSION,
+ .id = GATEKEEPER_HARDWARE_MODULE_ID,
+ .name = "Goldfish GateKeeper HAL",
+ .author = "The Android Open Source Project",
+ .methods = &gatekeeper_module_methods,
+ .dso = 0,
+ .reserved = {}
+ },
+};
diff --git a/health/Android.bp b/health/Android.bp
index 11a7a8dc..aab4fa9e 100644
--- a/health/Android.bp
+++ b/health/Android.bp
@@ -21,12 +21,10 @@ cc_binary {
"libbase",
"libcutils",
"libhidlbase",
+ "libhidltransport",
+ "libhwbinder",
"libutils",
"android.hardware.health@2.0",
],
header_libs: ["libhealthd_headers"],
-
- overrides: [
- "healthd",
- ],
}
diff --git a/include/qemu_pipe.h b/include/qemu_pipe.h
index d585ba12..986c3da2 100644
--- a/include/qemu_pipe.h
+++ b/include/qemu_pipe.h
@@ -34,7 +34,7 @@ typedef int QEMU_PIPE_HANDLE;
#define QEMU_PIPE_INVALID_HANDLE -1
-static __inline__ bool ReadFully(int fd, void* data, size_t byte_count) {
+static bool ReadFully(int fd, void* data, size_t byte_count) {
uint8_t* p = (uint8_t*)(data);
size_t remaining = byte_count;
while (remaining > 0) {
@@ -46,7 +46,7 @@ static __inline__ bool ReadFully(int fd, void* data, size_t byte_count) {
return true;
}
-static __inline__ bool WriteFully(int fd, const void* data, size_t byte_count) {
+static bool WriteFully(int fd, const void* data, size_t byte_count) {
const uint8_t* p = (const uint8_t*)(data);
size_t remaining = byte_count;
while (remaining > 0) {
diff --git a/init.ranchu.rc b/init.ranchu.rc
index 08a0c816..81bcc227 100644
--- a/init.ranchu.rc
+++ b/init.ranchu.rc
@@ -20,12 +20,6 @@ on post-fs-data
mkdir /data/vendor/var 0755 root root
mkdir /data/vendor/var/run 0755 root root
mkdir /data/vendor/var/run/netns 0755 root root
- start ranchu-net
-
- chown root root /data/vendor/etc
- rm /data/vendor/etc/media_codecs_google_video.xml
- symlink /data/vendor/etc/media_codecs_google_video_default.xml /data/vendor/etc/media_codecs_google_video.xml
- setprop qemu.mediaprofile.video ${ro.kernel.qemu.mediaprofile.video}
on zygote-start
# Create the directories used by the Wireless subsystem
@@ -39,7 +33,6 @@ on boot
setprop debug.hwui.renderer ${ro.kernel.qemu.uirenderer}
setprop ro.opengles.version ${ro.kernel.qemu.opengles.version}
setprop ro.zygote.disable_gl_preload 1
-
setprop dalvik.vm.heapsize 192m
setprop dalvik.vm.heapsize ${ro.kernel.qemu.dalvik.vm.heapsize}
chown root system /sys/power/wake_lock
@@ -60,10 +53,6 @@ service ranchu-setup /vendor/bin/init.ranchu-core.sh
group root
oneshot
-on property:qemu.mediaprofile.video=*
- rm /data/vendor/etc/media_codecs_google_video.xml
- symlink ${qemu.mediaprofile.video} /data/vendor/etc/media_codecs_google_video.xml
-
on property:vendor.qemu.timezone=*
setprop persist.sys.timezone ${vendor.qemu.timezone}
@@ -78,32 +67,33 @@ service ranchu-net /vendor/bin/init.ranchu-net.sh
user root
group root wakelock wifi
oneshot
- disabled # Started on post-fs-data
+
+service ipv6proxy /vendor/bin/execns router /vendor/bin/ipv6proxy -o eth0 -i wlan1,radio0-peer
+ user root
+ group root
+ disabled
service emu_hostapd /vendor/bin/execns router /vendor/bin/hostapd_nohidl /data/vendor/wifi/hostapd/hostapd.conf
user root
group root wifi net_raw net_admin
disabled
-service netmgr /vendor/bin/execns router /vendor/bin/netmgr --if-prefix wlan1 --bridge eth0,radio0-peer
+service dhcpserver /vendor/bin/execns router /vendor/bin/dhcpserver --exclude-interface eth0
user root
- group root wifi
+ group root
disabled
-service wifi_forwarder /vendor/bin/wifi_forwarder
+service netmgr /vendor/bin/execns router /vendor/bin/netmgr --if-prefix wlan1_ --network 192.168.232.9/29
user root
group root wifi
disabled
-service dhcpclient_rtr /vendor/bin/dhcpclient -i radio0 --no-gateway
+service dhcpclient_rtr /vendor/bin/execns router /vendor/bin/dhcpclient -i eth0
user root
group root
disabled
-on property:vendor.network.bridged=1
- start dhcpclient_rtr
-
-service dhcpclient_def /vendor/bin/dhcpclient -i eth0 --no-gateway
+service dhcpclient_def /vendor/bin/dhcpclient -i eth0
user root
group root
disabled
@@ -140,9 +130,6 @@ service bugreport /system/bin/dumpstate -d -p -B -z \
keycodes 114 115 116
service wpa_supplicant /vendor/bin/hw/wpa_supplicant -Dnl80211 -iwlan0 -c/vendor/etc/wifi/wpa_supplicant.conf -g@android:wpa_wlan0
- interface android.hardware.wifi.supplicant@1.0::ISupplicant default
- interface android.hardware.wifi.supplicant@1.1::ISupplicant default
- interface android.hardware.wifi.supplicant@1.2::ISupplicant default
socket wpa_wlan0 dgram 660 wifi wifi
group system wifi inet
oneshot
diff --git a/input-mt/virtio_input_multi_touch_1.idc b/input-mt/virtio_input_multi_touch_1.idc
deleted file mode 100644
index f740c047..00000000
--- a/input-mt/virtio_input_multi_touch_1.idc
+++ /dev/null
@@ -1,7 +0,0 @@
-device.internal = 1
-
-touch.deviceType = touchScreen
-touch.orientationAware = 1
-
-cursor.mode = navigation
-cursor.orientationAware = 1
diff --git a/input-mt/virtio_input_multi_touch_2.idc b/input-mt/virtio_input_multi_touch_2.idc
deleted file mode 100644
index 8e1b02ab..00000000
--- a/input-mt/virtio_input_multi_touch_2.idc
+++ /dev/null
@@ -1,12 +0,0 @@
-device.internal = 1
-
-touch.deviceType = touchScreen
-touch.orientationAware = 1
-
-cursor.mode = navigation
-cursor.orientationAware = 1
-
-# This displayID matches the unique ID of the virtual display created for Emulator.
-# This will indicate to input flinger than it should link this input device
-# with the virtual display.
-touch.displayId = local:8140900251843329
diff --git a/input-mt/virtio_input_multi_touch_3.idc b/input-mt/virtio_input_multi_touch_3.idc
deleted file mode 100644
index 6a112404..00000000
--- a/input-mt/virtio_input_multi_touch_3.idc
+++ /dev/null
@@ -1,12 +0,0 @@
-device.internal = 1
-
-touch.deviceType = touchScreen
-touch.orientationAware = 1
-
-cursor.mode = navigation
-cursor.orientationAware = 1
-
-# This displayID matches the unique ID of the virtual display created for Emulator.
-# This will indicate to input flinger than it should link this input device
-# with the virtual display.
-touch.displayId = local:8140940453066754
diff --git a/input-mt/virtio_input_multi_touch_4.idc b/input-mt/virtio_input_multi_touch_4.idc
deleted file mode 100644
index 33302f5b..00000000
--- a/input-mt/virtio_input_multi_touch_4.idc
+++ /dev/null
@@ -1,12 +0,0 @@
-device.internal = 1
-
-touch.deviceType = touchScreen
-touch.orientationAware = 1
-
-cursor.mode = navigation
-cursor.orientationAware = 1
-
-# This displayID matches the unique ID of the virtual display created for Emulator.
-# This will indicate to input flinger than it should link this input device
-# with the virtual display.
-touch.displayId = local:3
diff --git a/input-mt/virtio_input_multi_touch_5.idc b/input-mt/virtio_input_multi_touch_5.idc
deleted file mode 100644
index e489bb1f..00000000
--- a/input-mt/virtio_input_multi_touch_5.idc
+++ /dev/null
@@ -1,12 +0,0 @@
-device.internal = 1
-
-touch.deviceType = touchScreen
-touch.orientationAware = 1
-
-cursor.mode = navigation
-cursor.orientationAware = 1
-
-# This displayID matches the unique ID of the virtual display created for Emulator.
-# This will indicate to input flinger than it should link this input device
-# with the virtual display.
-touch.displayId = local:4
diff --git a/input/qwerty.kl b/input/qwerty.kl
deleted file mode 100644
index f508dde4..00000000
--- a/input/qwerty.kl
+++ /dev/null
@@ -1,132 +0,0 @@
-# Copyright (C) 2019 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.
-
-#
-# Emulator keyboard layout #1.
-#
-# This file is no longer used as the platform's default keyboard layout.
-# Refer to Generic.kl instead.
-#
-
-key 399 GRAVE
-key 2 1
-key 3 2
-key 4 3
-key 5 4
-key 6 5
-key 7 6
-key 8 7
-key 9 8
-key 10 9
-key 11 0
-key 158 BACK
-key 230 SOFT_RIGHT
-key 60 SOFT_LEFT
-key 107 ENDCALL
-key 62 ENDCALL
-key 229 MENU
-key 139 MENU
-key 59 MENU
-key 127 SEARCH
-key 217 SEARCH
-key 228 POUND
-key 227 STAR
-key 231 CALL
-key 61 CALL
-key 232 DPAD_CENTER
-key 108 DPAD_DOWN
-key 103 DPAD_UP
-key 102 HOME
-key 105 DPAD_LEFT
-key 106 DPAD_RIGHT
-key 115 VOLUME_UP
-key 114 VOLUME_DOWN
-key 116 POWER
-key 212 CAMERA
-
-key 16 Q
-key 17 W
-key 18 E
-key 19 R
-key 20 T
-key 21 Y
-key 22 U
-key 23 I
-key 24 O
-key 25 P
-key 26 LEFT_BRACKET
-key 27 RIGHT_BRACKET
-key 43 BACKSLASH
-
-key 30 A
-key 31 S
-key 32 D
-key 33 F
-key 34 G
-key 35 H
-key 36 J
-key 37 K
-key 38 L
-key 39 SEMICOLON
-key 40 APOSTROPHE
-key 14 DEL
-
-key 44 Z
-key 45 X
-key 46 C
-key 47 V
-key 48 B
-key 49 N
-key 50 M
-key 51 COMMA
-key 52 PERIOD
-key 53 SLASH
-key 28 ENTER
-
-key 56 ALT_LEFT
-key 100 ALT_RIGHT
-key 42 SHIFT_LEFT
-key 54 SHIFT_RIGHT
-key 15 TAB
-key 57 SPACE
-key 150 EXPLORER
-key 155 ENVELOPE
-key 58 CAPS_LOCK
-
-key 12 MINUS
-key 13 EQUALS
-key 215 AT
-
-# On an AT keyboard: ESC, F10
-key 1 BACK
-key 68 MENU
-
-# App switch = Overview key
-key 580 APP_SWITCH
-
-# Media control keys
-key 160 MEDIA_CLOSE
-key 161 MEDIA_EJECT
-key 163 MEDIA_NEXT
-key 164 MEDIA_PLAY_PAUSE
-key 165 MEDIA_PREVIOUS
-key 166 MEDIA_STOP
-key 167 MEDIA_RECORD
-key 168 MEDIA_REWIND
-
-key 142 SLEEP
-key 581 STEM_PRIMARY
-key 582 STEM_1
-key 583 STEM_2
-key 584 STEM_3
diff --git a/input/virtio_input_multi_touch_1.idc b/input/virtio_input_multi_touch_1.idc
index bc7ff663..78af5113 100644
--- a/input/virtio_input_multi_touch_1.idc
+++ b/input/virtio_input_multi_touch_1.idc
@@ -3,3 +3,4 @@ touch.deviceType = touchScreen
touch.orientationAware = 1
cursor.mode = navigation
cursor.orientationAware = 1
+
diff --git a/kernel-tests/goldfish_kernel_tests_x86_64.mk b/kernel-tests/goldfish_kernel_tests_x86_64.mk
index e3ccec62..19d4f0d6 100644
--- a/kernel-tests/goldfish_kernel_tests_x86_64.mk
+++ b/kernel-tests/goldfish_kernel_tests_x86_64.mk
@@ -29,8 +29,8 @@ THIS_DIR := device/generic/goldfish/kernel-tests
# android.hardware.
PRODUCT_PACKAGES += \
- android.hardware.keymaster@4.0-service \
- android.hardware.keymaster@4.0-impl \
+ android.hardware.keymaster@3.0-service \
+ android.hardware.keymaster@3.0-impl \
android.hardware.drm@1.1-service.clearkey \
android.hardware.graphics.allocator@2.0-service \
android.hardware.graphics.allocator@2.0-impl \
diff --git a/kernel-tests/manifest.xml b/kernel-tests/manifest.xml
index 82ba6d19..a9173447 100644
--- a/kernel-tests/manifest.xml
+++ b/kernel-tests/manifest.xml
@@ -2,7 +2,7 @@
<hal format="hidl">
<name>android.hardware.keymaster</name>
<transport>hwbinder</transport>
- <version>4.0</version>
+ <version>3.0</version>
<interface>
<name>IKeymasterDevice</name>
<instance>default</instance>
diff --git a/keymaster/strongbox/Android.bp b/keymaster/strongbox/Android.bp
index e615ba7a..39f4dcae 100644
--- a/keymaster/strongbox/Android.bp
+++ b/keymaster/strongbox/Android.bp
@@ -28,6 +28,7 @@ cc_binary {
"libcutils",
"libhardware",
"libhidlbase",
+ "libhidltransport",
"libkeymaster4",
"liblog",
"libutils",
diff --git a/manifest-arm.xml b/manifest-arm.xml
new file mode 100644
index 00000000..2189d914
--- /dev/null
+++ b/manifest-arm.xml
@@ -0,0 +1,215 @@
+<manifest version="1.0" type="device" target-level="3">
+ <hal format="hidl">
+ <name>android.hardware.drm</name>
+ <transport>hwbinder</transport>
+ <version>1.0</version>
+ <interface>
+ <name>ICryptoFactory</name>
+ <instance>default</instance>
+ </interface>
+ <interface>
+ <name>IDrmFactory</name>
+ <instance>default</instance>
+ </interface>
+ <fqname>@1.1::ICryptoFactory/clearkey</fqname>
+ <fqname>@1.1::IDrmFactory/clearkey</fqname>
+ <fqname>@1.1::ICryptoFactory/widevine</fqname>
+ <fqname>@1.1::IDrmFactory/widevine</fqname>
+ </hal>
+ <hal format="hidl">
+ <name>android.hardware.audio.effect</name>
+ <transport>hwbinder</transport>
+ <version>4.0</version>
+ <interface>
+ <name>IEffectsFactory</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl">
+ <name>android.hardware.biometrics.fingerprint</name>
+ <transport>hwbinder</transport>
+ <version>2.1</version>
+ <interface>
+ <name>IBiometricsFingerprint</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl">
+ <name>android.hardware.configstore</name>
+ <transport>hwbinder</transport>
+ <version>1.0</version>
+ <interface>
+ <name>ISurfaceFlingerConfigs</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl">
+ <name>android.hardware.audio</name>
+ <transport>hwbinder</transport>
+ <version>4.0</version>
+ <interface>
+ <name>IDevicesFactory</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl">
+ <name>android.hardware.keymaster</name>
+ <transport>hwbinder</transport>
+ <version>3.0</version>
+ <interface>
+ <name>IKeymasterDevice</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl">
+ <name>android.hardware.graphics.allocator</name>
+ <transport>hwbinder</transport>
+ <version>2.0</version>
+ <interface>
+ <name>IAllocator</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl">
+ <name>android.hardware.graphics.mapper</name>
+ <transport arch="32+64">passthrough</transport>
+ <version>2.0</version>
+ <interface>
+ <name>IMapper</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl">
+ <name>android.hardware.graphics.composer</name>
+ <transport>hwbinder</transport>
+ <version>2.1</version>
+ <interface>
+ <name>IComposer</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl">
+ <name>android.hardware.power</name>
+ <transport>hwbinder</transport>
+ <version>1.1</version>
+ <interface>
+ <name>IPower</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl">
+ <name>android.hardware.broadcastradio</name>
+ <transport>hwbinder</transport>
+ <version>1.0</version>
+ <interface>
+ <name>IBroadcastRadioFactory</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl">
+ <name>android.hardware.camera.provider</name>
+ <transport>hwbinder</transport>
+ <version>2.4</version>
+ <interface>
+ <name>ICameraProvider</name>
+ <instance>legacy/0</instance>
+ </interface>
+ </hal>
+ <hal format="hidl">
+ <name>android.hardware.sensors</name>
+ <transport>hwbinder</transport>
+ <version>1.0</version>
+ <interface>
+ <name>ISensors</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl">
+ <name>android.hardware.gatekeeper</name>
+ <transport>hwbinder</transport>
+ <version>1.0</version>
+ <interface>
+ <name>IGatekeeper</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl">
+ <name>android.hardware.gnss</name>
+ <transport>hwbinder</transport>
+ <version>1.0</version>
+ <interface>
+ <name>IGnss</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl">
+ <name>android.hardware.media.omx</name>
+ <transport>hwbinder</transport>
+ <version>1.0</version>
+ <interface>
+ <name>IOmx</name>
+ <instance>default</instance>
+ </interface>
+ <interface>
+ <name>IOmxStore</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl">
+ <name>android.hardware.radio</name>
+ <transport>hwbinder</transport>
+ <version>1.0</version>
+ <interface>
+ <name>IRadio</name>
+ <instance>slot1</instance>
+ </interface>
+ </hal>
+ <hal format="hidl">
+ <name>android.hardware.wifi</name>
+ <transport>hwbinder</transport>
+ <version>1.0</version>
+ <interface>
+ <name>IWifi</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl">
+ <name>android.hardware.wifi.hostapd</name>
+ <transport>hwbinder</transport>
+ <version>1.0</version>
+ <interface>
+ <name>IHostapd</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl">
+ <name>android.hardware.wifi.supplicant</name>
+ <transport>hwbinder</transport>
+ <version>1.0</version>
+ <interface>
+ <name>ISupplicant</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl">
+ <name>android.hardware.health</name>
+ <transport>hwbinder</transport>
+ <version>2.0</version>
+ <interface>
+ <name>IHealth</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl">
+ <name>android.hardware.thermal</name>
+ <transport>hwbinder</transport>
+ <version>2.0</version>
+ <interface>
+ <name>IThermal</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <sepolicy>
+ <version>27.0</version>
+ </sepolicy>
+</manifest>
diff --git a/manifest.camera.xml b/manifest.camera.xml
deleted file mode 100644
index 908c05c1..00000000
--- a/manifest.camera.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<manifest version="1.0" type="device" target-level="3">
- <hal format="hidl">
- <name>android.hardware.camera.provider</name>
- <transport>hwbinder</transport>
- <version>2.4</version>
- <interface>
- <name>ICameraProvider</name>
- <instance>legacy/0</instance>
- </interface>
- </hal>
-</manifest>
diff --git a/manifest.gnss.xml b/manifest.gnss.xml
deleted file mode 100644
index 69a178fd..00000000
--- a/manifest.gnss.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<manifest version="1.0" type="device" target-level="3">
- <hal format="hidl">
- <name>android.hardware.gnss</name>
- <transport>hwbinder</transport>
- <version>1.0</version>
- <interface>
- <name>IGnss</name>
- <instance>default</instance>
- </interface>
- </hal>
-</manifest>
diff --git a/manifest.sensors.xml b/manifest.sensors.xml
deleted file mode 100644
index 1c0a50b9..00000000
--- a/manifest.sensors.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<manifest version="1.0" type="device" target-level="3">
- <hal format="hidl">
- <name>android.hardware.sensors</name>
- <transport>hwbinder</transport>
- <version>1.0</version>
- <interface>
- <name>ISensors</name>
- <instance>default</instance>
- </interface>
- </hal>
-</manifest>
diff --git a/manifest.xml b/manifest.xml
index 53f344df..dd598e8a 100644
--- a/manifest.xml
+++ b/manifest.xml
@@ -37,7 +37,7 @@
<hal format="hidl">
<name>android.hardware.configstore</name>
<transport>hwbinder</transport>
- <version>1.1</version>
+ <version>1.0</version>
<interface>
<name>ISurfaceFlingerConfigs</name>
<instance>default</instance>
@@ -55,7 +55,7 @@
<hal format="hidl">
<name>android.hardware.keymaster</name>
<transport>hwbinder</transport>
- <version>4.0</version>
+ <version>3.0</version>
<interface>
<name>IKeymasterDevice</name>
<instance>default</instance>
@@ -82,7 +82,7 @@
<hal format="hidl">
<name>android.hardware.graphics.composer</name>
<transport>hwbinder</transport>
- <version>2.3</version>
+ <version>2.1</version>
<interface>
<name>IComposer</name>
<instance>default</instance>
@@ -100,47 +100,74 @@
<hal format="hidl">
<name>android.hardware.broadcastradio</name>
<transport>hwbinder</transport>
- <version>1.1</version>
+ <version>1.0</version>
<interface>
<name>IBroadcastRadioFactory</name>
<instance>default</instance>
</interface>
</hal>
<hal format="hidl">
- <name>android.hardware.media.omx</name>
+ <name>android.hardware.camera.provider</name>
+ <transport>hwbinder</transport>
+ <version>2.4</version>
+ <interface>
+ <name>ICameraProvider</name>
+ <instance>legacy/0</instance>
+ </interface>
+ </hal>
+ <hal format="hidl">
+ <name>android.hardware.sensors</name>
<transport>hwbinder</transport>
<version>1.0</version>
<interface>
- <name>IOmx</name>
+ <name>ISensors</name>
<instance>default</instance>
</interface>
+ </hal>
+ <hal format="hidl">
+ <name>android.hardware.gatekeeper</name>
+ <transport>hwbinder</transport>
+ <version>1.0</version>
<interface>
- <name>IOmxStore</name>
+ <name>IGatekeeper</name>
<instance>default</instance>
</interface>
</hal>
<hal format="hidl">
- <name>android.hardware.radio</name>
+ <name>android.hardware.gnss</name>
<transport>hwbinder</transport>
- <version>1.1</version>
+ <version>1.0</version>
<interface>
- <name>IRadio</name>
- <instance>slot1</instance>
+ <name>IGnss</name>
+ <instance>default</instance>
</interface>
</hal>
<hal format="hidl">
- <name>android.hardware.soundtrigger</name>
+ <name>android.hardware.media.omx</name>
<transport>hwbinder</transport>
- <version>2.0</version>
+ <version>1.0</version>
<interface>
- <name>ISoundTriggerHw</name>
+ <name>IOmx</name>
+ <instance>default</instance>
+ </interface>
+ <interface>
+ <name>IOmxStore</name>
<instance>default</instance>
</interface>
</hal>
<hal format="hidl">
+ <name>android.hardware.radio</name>
+ <transport>hwbinder</transport>
+ <version>1.0</version>
+ <interface>
+ <name>IRadio</name>
+ <instance>slot1</instance>
+ </interface>
+ </hal>
+ <hal format="hidl">
<name>android.hardware.wifi</name>
<transport>hwbinder</transport>
- <version>1.3</version>
+ <version>1.0</version>
<interface>
<name>IWifi</name>
<instance>default</instance>
@@ -158,7 +185,7 @@
<hal format="hidl">
<name>android.hardware.wifi.supplicant</name>
<transport>hwbinder</transport>
- <version>1.2</version>
+ <version>1.0</version>
<interface>
<name>ISupplicant</name>
<instance>default</instance>
@@ -173,4 +200,16 @@
<instance>default</instance>
</interface>
</hal>
+ <hal format="hidl">
+ <name>android.hardware.thermal</name>
+ <transport>hwbinder</transport>
+ <version>2.0</version>
+ <interface>
+ <name>IThermal</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <sepolicy>
+ <version>27.0</version>
+ </sepolicy>
</manifest>
diff --git a/network/netmgr/Android.bp b/network/netmgr/Android.bp
index 7530c916..6686f989 100644
--- a/network/netmgr/Android.bp
+++ b/network/netmgr/Android.bp
@@ -22,15 +22,14 @@ cc_binary {
"-Werror",
],
srcs: [
- "bridge.cpp",
- "bridge_builder.cpp",
+ "address_assigner.cpp",
"commander.cpp",
+ "fork.cpp",
"interface_state.cpp",
"log.cpp",
"main.cpp",
"monitor.cpp",
"poller.cpp",
- "utils.cpp",
"wifi_forwarder.cpp",
"commands/wifi_command.cpp",
],
diff --git a/network/netmgr/address_assigner.cpp b/network/netmgr/address_assigner.cpp
new file mode 100644
index 00000000..11df81d8
--- /dev/null
+++ b/network/netmgr/address_assigner.cpp
@@ -0,0 +1,151 @@
+/*
+ * Copyright 2018, 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 "address_assigner.h"
+
+#include "log.h"
+
+#include <errno.h>
+#include <net/if.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+AddressAssigner::AddressAssigner(const char* interfacePrefix,
+ in_addr_t baseAddress,
+ uint32_t maskLength) :
+ mInterfacePrefix(interfacePrefix),
+ mPrefixLength(strlen(interfacePrefix)),
+ mBaseAddress(baseAddress),
+ mMaskLength(maskLength) {
+
+}
+
+void AddressAssigner::onInterfaceState(unsigned int /*index*/,
+ const char* name,
+ InterfaceState state) {
+ if (strncmp(name, mInterfacePrefix, mPrefixLength) != 0) {
+ // The interface does not match the prefix, ignore this change
+ return;
+ }
+
+ switch (state) {
+ case InterfaceState::Up:
+ assignAddress(name);
+ break;
+ case InterfaceState::Down:
+ freeAddress(name);
+ break;
+ }
+}
+
+void AddressAssigner::assignAddress(const char* interfaceName) {
+ if (mMaskLength > 30) {
+ // The mask length is too long, we can't assign enough IP addresses from
+ // this. A maximum of 30 bits is supported, leaving 4 remaining
+ // addresses, one is network, one is broadcast, one is gateway, one is
+ // client.
+ return;
+ }
+ // Each subnet will have an amount of bits available to it that equals
+ // 32-bits - <mask length>, so if mask length is 29 there will be 3
+ // remaining bits for each subnet. Then the distance between each subnet
+ // is 2 to the power of this number, in our example 2^3 = 8 so to get to the
+ // next subnet we add 8 to the network address.
+ in_addr_t increment = 1 << (32 - mMaskLength);
+
+ // Convert the address to host byte-order first so we can do math on it.
+ for (in_addr_t addr = ntohl(mBaseAddress); true; addr += increment) {
+ // Take the reference of this lookup, that way we can assign a name to
+ // it if needed.
+ auto& usedName = mUsedIpAddresses[addr];
+ if (usedName.empty()) {
+ // This address is not in use, let's use it
+ usedName = interfaceName;
+ // Make sure we convert back to network byte-order when setting it.
+ setIpAddress(interfaceName, htonl(addr));
+ break;
+ }
+ }
+}
+
+void AddressAssigner::setIpAddress(const char* interfaceName,
+ in_addr_t address) {
+ int sock = ::socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
+ if (sock == -1) {
+ LOGE("AddressAssigner unable to open IP socket: %s", strerror(errno));
+ return;
+ }
+ if (!setAddress(sock, SIOCSIFADDR, interfaceName, address)) {
+ LOGE("AddressAssigner unable to set interface address: %s",
+ strerror(errno));
+ ::close(sock);
+ return;
+ }
+
+ // The netmask is the inverted maximum value of the lower bits. That is if
+ // the mask length is 29 then the the largest value of the 3 (32-29) lowest
+ // bits is 7 (2^3 - 1) (111 binary). Inverting this value gives the netmask
+ // because it excludes those three bits and sets every other bit.
+ in_addr_t netmask = htonl(~((1 << (32 - mMaskLength)) - 1));
+
+ if (!setAddress(sock, SIOCSIFNETMASK, interfaceName, netmask)) {
+ LOGE("AddressAssigner unable to set interface netmask: %s",
+ strerror(errno));
+ ::close(sock);
+ return;
+ }
+
+ // The broadcast address is just the assigned address with all bits outside
+ // of the netmask set to one.
+ in_addr_t broadcast = address | ~netmask;
+
+ if (!setAddress(sock, SIOCSIFBRDADDR, interfaceName, broadcast)) {
+ LOGE("AddressAssigner unable to set interface broadcast: %s",
+ strerror(errno));
+ ::close(sock);
+ return;
+ }
+ ::close(sock);
+}
+
+bool AddressAssigner::setAddress(int sock,
+ int type,
+ const char* interfaceName,
+ in_addr_t address) {
+ struct ifreq request;
+ memset(&request, 0, sizeof(request));
+ strlcpy(request.ifr_name, interfaceName, sizeof(request.ifr_name));
+ auto addr = reinterpret_cast<struct sockaddr_in*>(&request.ifr_addr);
+ addr->sin_family = AF_INET;
+ addr->sin_addr.s_addr = address;
+
+ if (::ioctl(sock, type, &request) != 0) {
+ return false;
+ }
+ return true;
+}
+
+void AddressAssigner::freeAddress(const char* interfaceName) {
+ for (auto& ipName : mUsedIpAddresses) {
+ if (ipName.second == interfaceName) {
+ // This is the one, free it up for future use
+ mUsedIpAddresses.erase(ipName.first);
+ }
+ }
+}
+
diff --git a/network/netmgr/bridge_builder.h b/network/netmgr/address_assigner.h
index e3d95805..dde42ee1 100644
--- a/network/netmgr/bridge_builder.h
+++ b/network/netmgr/address_assigner.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2019, The Android Open Source Project
+ * Copyright 2018, 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.
@@ -18,22 +18,37 @@
#include "interface_state.h"
-#include <stddef.h>
+#include <string>
+#include <unordered_map>
-class Bridge;
+#include <netinet/in.h>
+#include <stdint.h>
-class BridgeBuilder {
+class AddressAssigner {
public:
- // Construct a bridge builder that will add any interface that comes up to
- // |bridge| if the interface name begins with |interfacePrefix|.
- BridgeBuilder(Bridge& bridge, const char* interfacePrefix);
+ AddressAssigner(const char* interfacePrefix,
+ in_addr_t baseAddress,
+ uint32_t maskLength);
void onInterfaceState(unsigned int index,
const char* name,
InterfaceState state);
private:
- Bridge& mBridge;
+ void assignAddress(const char* interfaceName);
+ void freeAddress(const char* interfaceName);
+
+ void setIpAddress(const char* interfaceName, in_addr_t address);
+ bool setAddress(int socket,
+ int type,
+ const char* interfaceName,
+ in_addr_t address);
+ void removeIpAddress(const char* interfaceName, in_addr_t address);
+
const char* mInterfacePrefix;
size_t mPrefixLength;
+ in_addr_t mBaseAddress;
+ uint32_t mMaskLength;
+ std::unordered_map<in_addr_t, std::string> mUsedIpAddresses;
};
+
diff --git a/network/netmgr/bridge.cpp b/network/netmgr/bridge.cpp
deleted file mode 100644
index adbe21e6..00000000
--- a/network/netmgr/bridge.cpp
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright 2019, 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 "bridge.h"
-
-#include "log.h"
-
-#include <errno.h>
-#include <net/if.h>
-#include <string.h>
-#include <sys/ioctl.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-Bridge::Bridge(const std::string& bridgeName) : mBridgeName(bridgeName) {
-}
-
-Bridge::~Bridge() {
- if (mSocketFd != -1) {
- ::close(mSocketFd);
- mSocketFd = -1;
- }
-}
-
-Result Bridge::init() {
- Result res = createSocket();
- if (!res) {
- return res;
- }
- res = createBridge();
- if (!res) {
- return res;
- }
- return Result::success();
-}
-
-Result Bridge::addInterface(const std::string& interfaceName) {
- return doInterfaceOperation(interfaceName, SIOCBRADDIF, "add");
-}
-
-Result Bridge::removeInterface(const std::string& interfaceName) {
- return doInterfaceOperation(interfaceName, SIOCBRDELIF, "remove");
-}
-
-Result Bridge::createSocket() {
- if (mSocketFd != -1) {
- return Result::error("Bridge already initialized");
- }
- mSocketFd = ::socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
- if (mSocketFd < 0) {
- return Result::error("Unable to create socket for bridge: %s",
- strerror(errno));
- }
- return Result::success();
-}
-
-Result Bridge::createBridge() {
- int res = ::ioctl(mSocketFd, SIOCBRADDBR, mBridgeName.c_str());
- if (res < 0) {
- // If the bridge already exists we just keep going, that's fine.
- // Otherwise something went wrong.
- if (errno != EEXIST) {
- return Result::error("Cannot create bridge %s: %s",
- mBridgeName.c_str(), strerror(errno));
- }
- }
-
- struct ifreq request;
- memset(&request, 0, sizeof(request));
- // Determine interface index of bridge
- request.ifr_ifindex = if_nametoindex(mBridgeName.c_str());
- if (request.ifr_ifindex == 0) {
- return Result::error("Unable to get bridge %s interface index",
- mBridgeName.c_str());
- }
- // Get bridge interface flags
- strlcpy(request.ifr_name, mBridgeName.c_str(), sizeof(request.ifr_name));
- res = ::ioctl(mSocketFd, SIOCGIFFLAGS, &request);
- if (res != 0) {
- return Result::error("Unable to get interface flags for bridge %s: %s",
- mBridgeName.c_str(), strerror(errno));
- }
-
- if ((request.ifr_flags & IFF_UP) != 0) {
- // Bridge is already up, it's ready to go
- return Result::success();
- }
-
- // Bridge is not up, it needs to be up to work
- request.ifr_flags |= IFF_UP;
- res = ::ioctl(mSocketFd, SIOCSIFFLAGS, &request);
- if (res != 0) {
- return Result::error("Unable to set interface flags for bridge %s: %s",
- strerror(errno));
- }
-
- return Result::success();
-}
-
-Result Bridge::doInterfaceOperation(const std::string& interfaceName,
- unsigned long operation,
- const char* operationName) {
- struct ifreq request;
- memset(&request, 0, sizeof(request));
-
- request.ifr_ifindex = if_nametoindex(interfaceName.c_str());
- if (request.ifr_ifindex == 0) {
- return Result::error("Bridge unable to %s interface '%s', no such "
- "interface", operationName, interfaceName.c_str());
- }
- strlcpy(request.ifr_name, mBridgeName.c_str(), sizeof(request.ifr_name));
- int res = ::ioctl(mSocketFd, operation, &request);
- // An errno of EBUSY most likely indicates that the interface is already
- // part of the bridge. Ignore this.
- if (res < 0 && errno != EBUSY) {
- return Result::error("Bridge unable to %s interface '%s': %s",
- operationName, interfaceName.c_str(),
- strerror(errno));
- }
- return Result::success();
-}
diff --git a/network/netmgr/bridge.h b/network/netmgr/bridge.h
deleted file mode 100644
index fc7ff519..00000000
--- a/network/netmgr/bridge.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright 2019, 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.
- */
-
-#pragma once
-
-#include "result.h"
-
-#include <string>
-
-class Bridge {
-public:
- explicit Bridge(const std::string& bridgeName);
- ~Bridge();
-
- Result init();
-
- Result addInterface(const std::string& interfaceName);
- Result removeInterface(const std::string& interfaceName);
-private:
- Result createSocket();
- Result createBridge();
- Result doInterfaceOperation(const std::string& interfaceName,
- unsigned long operation,
- const char* operationName);
-
- std::string mBridgeName;
- int mSocketFd = -1;
-};
diff --git a/network/netmgr/bridge_builder.cpp b/network/netmgr/bridge_builder.cpp
deleted file mode 100644
index d772eaef..00000000
--- a/network/netmgr/bridge_builder.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright 2019, 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 "bridge_builder.h"
-
-#include "bridge.h"
-#include "log.h"
-#include "result.h"
-
-BridgeBuilder::BridgeBuilder(Bridge& bridge, const char* interfacePrefix) :
- mBridge(bridge),
- mInterfacePrefix(interfacePrefix),
- mPrefixLength(strlen(interfacePrefix)) {
-}
-
-void BridgeBuilder::onInterfaceState(unsigned int /*index*/,
- const char* name,
- InterfaceState state) {
- if (strncmp(name, mInterfacePrefix, mPrefixLength) != 0) {
- // Does not match our prefix, ignore it
- return;
- }
-
- if (state == InterfaceState::Up) {
- Result res = mBridge.addInterface(name);
- if (!res) {
- LOGE("%s", res.c_str());
- }
- }
-}
diff --git a/network/netmgr/commands/wifi_command.cpp b/network/netmgr/commands/wifi_command.cpp
index 27bf95a8..8f48a438 100644
--- a/network/netmgr/commands/wifi_command.cpp
+++ b/network/netmgr/commands/wifi_command.cpp
@@ -16,13 +16,18 @@
#include "wifi_command.h"
-#include "../bridge.h"
-#include "../utils.h"
+#include "../fork.h"
+#include "log.h"
#include <cutils/properties.h>
#include <errno.h>
+#include <net/if.h>
+#include <netinet/in.h>
#include <stdio.h>
#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/types.h>
#include <unistd.h>
static const char kHostApdStubFile[] = "/vendor/etc/simulated_hostapd.conf";
@@ -65,9 +70,24 @@ private:
int mFd;
};
-WifiCommand::WifiCommand(Bridge& bridge)
- : mBridge(bridge)
- , mLowestInterfaceNumber(1) {
+std::vector<std::string> explode(const char* str) {
+ const char* cur = str;
+ const char* space = nullptr;
+ std::vector<std::string> result;
+ do {
+ space = ::strchr(cur, ' ');
+ if (space) {
+ result.emplace_back(cur, space);
+ cur = space + 1;
+ } else {
+ result.emplace_back(cur);
+ }
+ } while (space);
+
+ return result;
+}
+
+WifiCommand::WifiCommand() : mLowestInterfaceNumber(1) {
readConfig();
}
@@ -83,7 +103,7 @@ Result WifiCommand::onCommand(const char* /*command*/, const char* args) {
return Result::error("Empty wifi command");
}
- std::vector<std::string> subArgs = explode(divider + 1, ' ');
+ std::vector<std::string> subArgs = explode(divider + 1);
if (subArgs.empty()) {
// All of these commands require sub arguments
return Result::error("Missing argument to command '%s'",
@@ -152,6 +172,55 @@ Result WifiCommand::triggerHostApd() {
return Result::success();
}
+static const char* sSetForwardRule[] = {"/system/bin/iptables",
+ "-w", // Wait for iptables lock if
+ "-W", // needed. This prevents
+ "50000", // spurious failures.
+ "<AddOrDelete>", // To be replaced
+ "FORWARD",
+ "-i",
+ "<InInterface>", // To be replaced
+ "-o",
+ "<OutInterface>", // To be replaced
+ "-j",
+ "DROP",
+ nullptr };
+
+static const char kIpTables[] = "/system/bin/iptables";
+static const char kIp6Tables[] = "/system/bin/ip6tables";
+static const char kAddRule[] = "-A";
+static const char kDeleteRule[] = "-D";
+static const size_t kIpTablesIndex = 0;
+static const size_t kActionIndex = 4;
+static const size_t kInInterfaceIndex = 7;
+static const size_t kOutInterfaceIndex = 9;
+
+
+Result WifiCommand::setBlocked(const char* ifName, bool blocked) {
+ // Blocking means adding block rules, unblocking means removing them
+ sSetForwardRule[kActionIndex] = blocked ? kAddRule : kDeleteRule;
+
+ // Do this for both IPv4 and IPv6 to ensure all traffic is blocked/unblocked
+ for (const auto& iptables : { kIpTables, kIp6Tables }) {
+ // Block traffic coming in from the outside world to this wlan
+ sSetForwardRule[kIpTablesIndex] = iptables;
+ sSetForwardRule[kInInterfaceIndex] = "eth0";
+ sSetForwardRule[kOutInterfaceIndex] = ifName;
+ if (!forkAndExec(sSetForwardRule)) {
+ return Result::error("Internal error: Unable to %s network",
+ blocked ? "block" : "unblock");
+ }
+ // Block traffic going from the wlan to the outside world
+ sSetForwardRule[kInInterfaceIndex] = ifName;
+ sSetForwardRule[kOutInterfaceIndex] = "eth0";
+ if (!forkAndExec(sSetForwardRule)) {
+ return Result::error("Internal error: Unable to %s network",
+ blocked ? "block" : "unblock");
+ }
+ }
+ return Result::success();
+}
+
Result WifiCommand::onAdd(const std::vector<std::string>& arguments) {
AccessPoint& ap = mAccessPoints[arguments[0]];
ap.ssid = arguments[0];
@@ -187,18 +256,18 @@ Result WifiCommand::onAdd(const std::vector<std::string>& arguments) {
Result WifiCommand::onBlock(const std::vector<std::string>& arguments) {
auto interface = mAccessPoints.find(arguments[0]);
if (interface == mAccessPoints.end()) {
- return Result::error("Unknown SSID '%s'", arguments[0].c_str());
+ return Result::error("Unknown SSID '%s", arguments[0].c_str());
}
interface->second.blocked = true;
- return mBridge.removeInterface(interface->second.ifName.c_str());
+ return setBlocked(interface->second.ifName.c_str(), true);
}
Result WifiCommand::onUnblock(const std::vector<std::string>& arguments) {
auto interface = mAccessPoints.find(arguments[0]);
if (interface == mAccessPoints.end()) {
- return Result::error("Unknown SSID '%s'", arguments[0].c_str());
+ return Result::error("Unknown SSID '%s", arguments[0].c_str());
}
interface->second.blocked = false;
- return mBridge.addInterface(interface->second.ifName.c_str());
+ return setBlocked(interface->second.ifName.c_str(), false);
}
diff --git a/network/netmgr/commands/wifi_command.h b/network/netmgr/commands/wifi_command.h
index b47edb89..f9ce96ce 100644
--- a/network/netmgr/commands/wifi_command.h
+++ b/network/netmgr/commands/wifi_command.h
@@ -24,11 +24,9 @@
#include <unordered_set>
#include <vector>
-class Bridge;
-
class WifiCommand : public Command {
public:
- explicit WifiCommand(Bridge& bridge);
+ WifiCommand();
virtual ~WifiCommand() = default;
Result onCommand(const char* command, const char* args) override;
@@ -36,6 +34,7 @@ private:
void readConfig();
Result writeConfig();
Result triggerHostApd();
+ Result setBlocked(const char* ifName, bool blocked);
Result onAdd(const std::vector<std::string>& args);
Result onBlock(const std::vector<std::string>& args);
@@ -49,7 +48,6 @@ private:
bool blocked;
};
- Bridge& mBridge;
std::unordered_map<std::string, AccessPoint> mAccessPoints;
std::unordered_set<std::string> mUsedInterfaces;
int mLowestInterfaceNumber;
diff --git a/network/netmgr/interface_state.h b/network/netmgr/interface_state.h
index 6d56aba1..5315b0f9 100644
--- a/network/netmgr/interface_state.h
+++ b/network/netmgr/interface_state.h
@@ -21,4 +21,3 @@ enum class InterfaceState {
Down,
};
-const char* interfaceStateToStr(InterfaceState state);
diff --git a/network/netmgr/main.cpp b/network/netmgr/main.cpp
index d83de399..e4b43f6d 100644
--- a/network/netmgr/main.cpp
+++ b/network/netmgr/main.cpp
@@ -14,28 +14,23 @@
* limitations under the License.
*/
-#include "bridge.h"
-#include "bridge_builder.h"
+#include "address_assigner.h"
#include "commander.h"
#include "commands/wifi_command.h"
#include "log.h"
#include "monitor.h"
#include "poller.h"
-#include "utils.h"
#include "wifi_forwarder.h"
#include <arpa/inet.h>
#include <netinet/in.h>
-#include <cutils/properties.h>
-
#include <functional>
-static const char kBridgeName[] = "br0";
-static const char kNetworkBridgedProperty[] = "vendor.network.bridged";
+static const char kWifiMonitorInterface[] = "hwsim0";
static void usage(const char* name) {
- LOGE("Usage: %s --if-prefix <prefix> --bridge <if1,if2,...>", name);
+ LOGE("Usage: %s --if-prefix <prefix> --network <ip/mask>", name);
LOGE(" <prefix> indicates the name of network interfaces to configure.");
LOGE(" <ip/mask> is the base IP address to assign to the first interface");
LOGE(" and mask indicates the netmask and broadcast to set.");
@@ -44,27 +39,52 @@ static void usage(const char* name) {
LOGE(" and the size of the subnet is indicated by <mask>");
}
-static Result addBridgeInterfaces(Bridge& bridge, const char* interfaces) {
- std::vector<std::string> ifNames = explode(interfaces, ',');
+static bool parseNetwork(const char* network,
+ in_addr_t* address,
+ uint32_t* mask) {
+ const char* divider = strchr(network, '/');
+ if (divider == nullptr) {
+ LOGE("Network specifier '%s' is missing netmask length", network);
+ return false;
+ }
+ if (divider - network >= INET_ADDRSTRLEN) {
+ LOGE("Network specifier '%s' contains an IP address that is too long",
+ network);
+ return false;
+ }
- for (const auto& ifName : ifNames) {
- Result res = bridge.addInterface(ifName);
- if (!res) {
- return res;
- }
+ char buffer[INET_ADDRSTRLEN];
+ strlcpy(buffer, network, divider - network + 1);
+ struct in_addr addr;
+ if (!::inet_aton(buffer, &addr)) {
+ // String could not be converted to IP address
+ LOGE("Network specifier '%s' contains an invalid IP address '%s'",
+ network, buffer);
+ return false;
}
- return Result::success();
+
+ ++divider;
+
+ char dummy = 0;
+ if (sscanf(divider, "%u%c", mask, &dummy) != 1) {
+ LOGE("Netork specifier '%s' contains an invalid netmask length '%s'",
+ network, divider);
+ return false;
+ }
+
+ *address = addr.s_addr;
+ return true;
}
int main(int argc, char* argv[]) {
const char* interfacePrefix = nullptr;
- const char* bridgeInterfaces = nullptr;
+ const char* network = nullptr;
for (int i = 1; i < argc; ++i) {
if (strcmp(argv[i], "--if-prefix") == 0 && i + 1 < argc) {
interfacePrefix = argv[++i];
- } else if (strcmp(argv[i], "--bridge") == 0 && i + 1 < argc) {
- bridgeInterfaces = argv[++i];
+ } else if (strcmp(argv[i], "--network") == 0 && i + 1 < argc) {
+ network = argv[++i];
} else {
LOGE("Unknown parameter '%s'", argv[i]);
usage(argv[0]);
@@ -75,39 +95,30 @@ int main(int argc, char* argv[]) {
if (interfacePrefix == nullptr) {
LOGE("Missing parameter --if-prefix");
}
- if (bridgeInterfaces == nullptr) {
- LOGE("Missing parameter --bridge");
+ if (network == nullptr) {
+ LOGE("Missing parameter --network");
}
- if (interfacePrefix == nullptr || bridgeInterfaces == nullptr) {
+ if (network == nullptr || interfacePrefix == nullptr) {
usage(argv[0]);
return 1;
}
- Bridge bridge(kBridgeName);
- Result res = bridge.init();
- if (!res) {
- LOGE("%s", res.c_str());
- return 1;
- }
- res = addBridgeInterfaces(bridge, bridgeInterfaces);
- if (!res) {
- LOGE("%s", res.c_str());
+ in_addr_t address = 0;
+ uint32_t mask = 0;
+ if (!parseNetwork(network, &address, &mask)) {
return 1;
}
- BridgeBuilder bridgeBuilder(bridge, interfacePrefix);
-
- property_set(kNetworkBridgedProperty, "1");
-
+ AddressAssigner assigner(interfacePrefix, address, mask);
Monitor monitor;
- monitor.setOnInterfaceState(std::bind(&BridgeBuilder::onInterfaceState,
- &bridgeBuilder,
+ monitor.setOnInterfaceState(std::bind(&AddressAssigner::onInterfaceState,
+ &assigner,
std::placeholders::_1,
std::placeholders::_2,
std::placeholders::_3));
- res = monitor.init();
+ Result res = monitor.init();
if (!res) {
LOGE("%s", res.c_str());
return 1;
@@ -120,13 +131,20 @@ int main(int argc, char* argv[]) {
return 1;
}
- WifiCommand wifiCommand(bridge);
+ WifiCommand wifiCommand;
commander.registerCommand("wifi", &wifiCommand);
+ WifiForwarder forwarder(kWifiMonitorInterface);
+ res = forwarder.init();
+ if (!res) {
+ LOGE("%s", res.c_str());
+ return 1;
+ }
+
Poller poller;
poller.addPollable(&monitor);
poller.addPollable(&commander);
-
+ poller.addPollable(&forwarder);
return poller.run();
}
diff --git a/network/netmgr/monitor.cpp b/network/netmgr/monitor.cpp
index a9d248ae..4ab111ea 100644
--- a/network/netmgr/monitor.cpp
+++ b/network/netmgr/monitor.cpp
@@ -37,11 +37,7 @@ Monitor::~Monitor() {
}
Result Monitor::init() {
- Result res = openSocket();
- if (!res) {
- return res;
- }
- return requestInterfaces();
+ return openSocket();
}
void Monitor::setOnInterfaceState(OnInterfaceStateCallback callback) {
@@ -88,7 +84,7 @@ bool Monitor::onReadAvailable(int /*fd*/, int* /*status*/) {
default:
break;
}
- hdr = NLMSG_NEXT(hdr, length);
+ NLMSG_NEXT(hdr, length);
}
}
}
@@ -144,36 +140,6 @@ Result Monitor::openSocket() {
return Result::success();
}
-Result Monitor::requestInterfaces() {
- if (mSocketFd == -1) {
- return Result::error("Monitor not initialized yet");
- }
-
- struct {
- struct nlmsghdr hdr;
- struct rtgenmsg gen;
- } request;
-
- memset(&request, 0, sizeof(request));
-
- request.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(request.gen));
- request.hdr.nlmsg_type = RTM_GETLINK;
- request.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
- request.hdr.nlmsg_seq = 1;
- request.hdr.nlmsg_pid = getpid();
- request.gen.rtgen_family = AF_PACKET;
-
- ssize_t result = TEMP_FAILURE_RETRY(::send(mSocketFd,
- &request,
- request.hdr.nlmsg_len,
- 0));
- if (result < 0) {
- return Result::error("Failed to request interfaces: %s",
- strerror(errno));
- }
- return Result::success();
-}
-
void Monitor::closeSocket() {
if (mSocketFd != -1) {
::close(mSocketFd);
@@ -188,23 +154,14 @@ void Monitor::handleNewLink(const struct nlmsghdr* hdr) {
auto msg = reinterpret_cast<const struct ifinfomsg*>(NLMSG_DATA(hdr));
- char name[IF_NAMESIZE + 1] = { 0 };
- const unsigned int ifIndex = msg->ifi_index;
- if (if_indextoname(ifIndex, name) == nullptr) {
- LOGE("Unable to get interface name for interface index %u", ifIndex);
- }
+ if (msg->ifi_change & IFF_UP) {
+ // The interface up/down flag changed, send a notification
+ char name[IF_NAMESIZE + 1] = { 0 };
+ if_indextoname(msg->ifi_index, name);
- bool isUp = !!(msg->ifi_flags & IFF_UP);
- auto iterator = mUpInterfaces.find(ifIndex);
-
- if (iterator == mUpInterfaces.end() && isUp) {
- // The interface was not known to be up but is up, known state changed
- mUpInterfaces.insert(ifIndex);
- mOnInterfaceStateCallback(ifIndex, name, InterfaceState::Up);
- } else if (iterator != mUpInterfaces.end() && !isUp) {
- // The interface was known to be up, now it's not, known state changed
- mUpInterfaces.erase(iterator);
- mOnInterfaceStateCallback(ifIndex, name, InterfaceState::Down);
+ InterfaceState state = (msg->ifi_flags & IFF_UP) ? InterfaceState::Up :
+ InterfaceState::Down;
+ mOnInterfaceStateCallback(msg->ifi_index, name, state);
}
}
diff --git a/network/netmgr/monitor.h b/network/netmgr/monitor.h
index 00f525ee..3d2dc621 100644
--- a/network/netmgr/monitor.h
+++ b/network/netmgr/monitor.h
@@ -20,7 +20,7 @@
#include "pollable.h"
#include "result.h"
-#include <unordered_set>
+const char* interfaceStateToStr(InterfaceState state);
/** Monitor network interfaces and provide notifications of changes to those
* interfaces.
@@ -46,12 +46,10 @@ public:
private:
Result openSocket();
- Result requestInterfaces();
void closeSocket();
void handleNewLink(const struct nlmsghdr* hdr);
int mSocketFd;
OnInterfaceStateCallback mOnInterfaceStateCallback;
- std::unordered_set<unsigned int> mUpInterfaces;
};
diff --git a/network/netmgr/utils.h b/network/netmgr/timestamp.cpp
index 7c05882c..36c79ee0 100644
--- a/network/netmgr/utils.h
+++ b/network/netmgr/timestamp.cpp
@@ -14,9 +14,20 @@
* limitations under the License.
*/
-#pragma once
+#include "timestamp.h"
-#include <string>
-#include <vector>
-std::vector<std::string> explode(const char* str, char divider);
+Timestamp::Timestamp() {
+ memset(&mTime, 0, sizeof(mTime));
+}
+
+static Timestamp Timestamp::now() {
+ Timestamp t;
+ clock_gettime(CLOCK_MONOTONIC, &t.mTime);
+ return t;
+}
+
+bool Timestamp::operator==(const Timestamp& other) const {
+}
+bool Timestamp::operator<(const Timestamp& other) const {
+}
diff --git a/network/wifi_forwarder/poller.h b/network/netmgr/timestamp.h
index 9794f4da..8ad7bf81 100644
--- a/network/wifi_forwarder/poller.h
+++ b/network/netmgr/timestamp.h
@@ -16,19 +16,18 @@
#pragma once
-#include <vector>
+#include <time.h>
-#include "pollable.h"
-
-class Poller {
+class Timestamp {
public:
- Poller();
+ Timestamp();
- void addPollable(Pollable* pollable);
+ static Timestamp now();
- int run();
+ bool operator==(const Timestamp& other) const;
+ bool operator<(const Timestamp& other) const;
private:
- std::vector<Pollable*> mPollables;
+ struct timespec mTime;
};
diff --git a/network/netmgr/utils.cpp b/network/netmgr/utils.cpp
deleted file mode 100644
index fa71c1e1..00000000
--- a/network/netmgr/utils.cpp
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright 2018, 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 "utils.h"
-
-#include <string.h>
-
-std::vector<std::string> explode(const char* str, char divider) {
- const char* cur = str;
- const char* space = nullptr;
- std::vector<std::string> result;
- do {
- space = ::strchr(cur, divider);
- if (space) {
- result.emplace_back(cur, space);
- cur = space + 1;
- } else {
- result.emplace_back(cur);
- }
- } while (space);
-
- return result;
-}
-
diff --git a/network/wifi_forwarder/Android.bp b/network/wifi_forwarder/Android.bp
deleted file mode 100644
index 6dbc9ca1..00000000
--- a/network/wifi_forwarder/Android.bp
+++ /dev/null
@@ -1,46 +0,0 @@
-//
-// Copyright (C) 2019 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.
-//
-
-cc_binary {
- name: "wifi_forwarder",
- vendor: true,
- cppflags: [
- "-Wall",
- "-Werror",
- "--std=c++17",
- ],
- srcs: [
- "frame.cpp",
- "local_connection.cpp",
- "main.cpp",
- "netlink_message.cpp",
- "netlink_socket.cpp",
- "poller.cpp",
- "remote_connection.cpp",
- "wifi_forwarder.cpp",
- ],
- shared_libs: [
- "libcutils",
- "liblog",
- "libnl",
- "libpcap",
- "libutils",
- "libutilscallstack",
- ],
- header_libs: [
- "goldfish_headers",
- ],
-}
diff --git a/network/wifi_forwarder/cache.h b/network/wifi_forwarder/cache.h
deleted file mode 100644
index bd64f1a4..00000000
--- a/network/wifi_forwarder/cache.h
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * Copyright 2019, 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.
- */
-
-#pragma once
-
-#include <inttypes.h>
-#include "log.h"
-
-#include <chrono>
-#include <unordered_map>
-
-// Default amount of time until a cache entry expires
-static constexpr auto kDefaultCacheTimeout = std::chrono::seconds(30);
-
-template<typename Key,
- typename Value,
- typename Timestamp = std::chrono::steady_clock::time_point>
-class Cache {
-public:
- using TimedValue = std::pair<Timestamp, Value>;
-
- using MapType = std::unordered_map<Key, TimedValue>;
- using key_type = typename MapType::key_type;
- using mapped_type = Value;
-
- class ConstIterator {
- public:
- class IterPair {
- public:
- IterPair(const Key& key, const Value& value)
- : first(key), second(value) {
- }
-
- const IterPair* operator->() const { return this; }
- const Key& first;
- const Value& second;
- private:
- };
-
- ConstIterator(typename MapType::const_iterator current)
- : mCurrent(current) { }
-
- IterPair operator->() const {
- return IterPair(mCurrent->first, mCurrent->second.second);
- }
-
- IterPair operator*() const {
- return IterPair(mCurrent->first, mCurrent->second.second);
- }
-
- bool operator==(const ConstIterator& other) const {
- return mCurrent == other.mCurrent;
- }
-
- bool operator!=(const ConstIterator& other) const {
- return mCurrent != other.mCurrent;
- }
-
- typename MapType::const_iterator internal() const { return mCurrent; }
-
- private:
- typename MapType::const_iterator mCurrent;
- };
- class Iterator {
- public:
- class IterPair {
- public:
- IterPair(const Key& key, Value& value) : first(key), second(value) { }
-
- IterPair* operator->() { return this; }
- const Key& first;
- Value& second;
- private:
- };
-
- Iterator(typename MapType::iterator current) : mCurrent(current) { }
-
- IterPair operator->() {
- return IterPair(mCurrent->first, mCurrent->second.second);
- }
-
- IterPair operator*() {
- return IterPair(mCurrent->first, mCurrent->second.second);
- }
-
- bool operator==(const Iterator& other) const {
- return mCurrent == other.mCurrent;
- }
-
- bool operator!=(const Iterator& other) const {
- return mCurrent != other.mCurrent;
- }
-
- typename MapType::iterator internal() { return mCurrent; }
-
- private:
- typename MapType::iterator mCurrent;
- };
-
- using iterator = Iterator;
- using const_iterator = ConstIterator;
- using insert_return_type = std::pair<const_iterator, bool>;
-
- Cache(std::chrono::milliseconds timeout = kDefaultCacheTimeout)
- : mTimeout(timeout) {
- }
-
- template<typename M>
- insert_return_type insert_or_assign(const key_type& key, M&& value) {
- std::pair<typename MapType::iterator,bool> inserted =
- mMap.insert_or_assign(key, TimedValue(mCurrentTime,
- std::move(value)));
- return insert_return_type(inserted.first, inserted.second);
- }
-
- mapped_type& operator[](const key_type& key) {
- TimedValue& v = mMap[key];
- v.first = mCurrentTime;
- return v.second;
- }
-
- iterator find(const key_type& key) {
- return iterator(mMap.find(key));
- }
-
- const_iterator find(const key_type& key) const {
- return const_iterator(mMap.find(key));
- }
-
- iterator erase(const_iterator pos) {
- return iterator(mMap.erase(pos.internal()));
- }
-
- iterator erase(iterator pos) {
- return iterator(mMap.erase(pos.internal()));
- }
-
- size_t erase(const key_type& key) {
- return mMap.erase(key);
- }
-
- iterator begin() {
- return iterator(mMap.begin());
- }
-
- iterator end() {
- return iterator(mMap.end());
- }
-
- const_iterator begin() const {
- return const_iterator(mMap.begin());
- }
-
- const_iterator end() const {
- return const_iterator(mMap.end());
- }
-
- void setCurrentTime(Timestamp currentTime) {
- mCurrentTime = currentTime;
- }
-
- void expireEntries() {
- for (auto it = mMap.begin(); it != mMap.end(); ) {
- const Timestamp timestamp = it->second.first;
- if (mCurrentTime > timestamp &&
- (mCurrentTime - timestamp) > mTimeout) {
- // This entry has expired, remove it
- it = mMap.erase(it);
- } else {
- ++it;
- }
- }
- }
-private:
- const std::chrono::milliseconds mTimeout;
- Timestamp mCurrentTime;
- MapType mMap;
-};
-
diff --git a/network/wifi_forwarder/frame.cpp b/network/wifi_forwarder/frame.cpp
deleted file mode 100644
index 3b20b4e1..00000000
--- a/network/wifi_forwarder/frame.cpp
+++ /dev/null
@@ -1,370 +0,0 @@
-/*
- * Copyright 2019, 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 "frame.h"
-
-#include "hwsim.h"
-#include "ieee80211.h"
-
-#include <asm/byteorder.h>
-
-#include <sstream>
-
-static constexpr uint64_t kSlotTime = 9;
-
-static const AccessCategory kPriorityToAc[8] = {
- AccessCategory::BestEffort,
- AccessCategory::Background,
- AccessCategory::Background,
- AccessCategory::BestEffort,
- AccessCategory::Video,
- AccessCategory::Video,
- AccessCategory::Voice,
- AccessCategory::Voice,
-};
-
-static uint32_t calcContentionWindowMin(AccessCategory ac) {
- switch (ac) {
- case AccessCategory::Voice:
- return 3;
- case AccessCategory::Video:
- return 7;
- case AccessCategory::BestEffort:
- return 15;
- case AccessCategory::Background:
- return 15;
- }
-}
-
-static uint32_t calcContentionWindowMax(AccessCategory ac) {
- switch (ac) {
- case AccessCategory::Voice:
- return 7;
- case AccessCategory::Video:
- return 15;
- case AccessCategory::BestEffort:
- return 1023;
- case AccessCategory::Background:
- return 1023;
- }
-}
-
-FrameType frameTypeFromByte(uint8_t byte) {
- if (byte == static_cast<uint8_t>(FrameType::Ack)) {
- return FrameType::Ack;
- } else if (byte == static_cast<uint8_t>(FrameType::Data)) {
- return FrameType::Data;
- }
- return FrameType::Unknown;
-}
-
-FrameInfo::FrameInfo(const MacAddress& transmitter,
- uint64_t cookie,
- uint32_t flags,
- uint32_t channel,
- const hwsim_tx_rate* rates,
- size_t numRates)
- : mTransmitter(transmitter)
- , mCookie(cookie)
- , mFlags(flags)
- , mChannel(channel) {
- size_t i = 0;
- for (; i < numRates; ++i) {
- mTxRates[i].count = 0;
- mTxRates[i].idx = rates[i].idx;
- }
- for (; i < mTxRates.size(); ++i) {
- mTxRates[i].count = 0;
- mTxRates[i].idx = -1;
- }
-}
-
-bool FrameInfo::shouldAck() const {
- return !!(mFlags & HWSIM_TX_CTL_REQ_TX_STATUS);
-}
-
-Frame::Frame(const uint8_t* data, size_t size) : mData(data, data + size) {
-}
-
-Frame::Frame(const uint8_t* data, size_t size, const MacAddress& transmitter,
- uint64_t cookie, uint32_t flags, uint32_t channel,
- const hwsim_tx_rate* rates, size_t numRates)
- : mData(data, data + size)
- , mInfo(transmitter, cookie, flags, channel, rates, numRates)
- , mContentionWindow(calcContentionWindowMin(getAc()))
- , mContentionWindowMax(calcContentionWindowMax(getAc())) {
- memcpy(mInitialTxRates.data(), rates, numRates * sizeof(*rates));
-}
-
-bool Frame::incrementAttempts() {
- Rates& rates = mInfo.rates();
- for (size_t i = 0; i < rates.size(); ++i) {
- if (mInitialTxRates[i].idx == -1) {
- // We've run out of attempts
- break;
- }
- if (rates[i].count < mInitialTxRates[i].count) {
- ++rates[i].count;
- return true;
- }
- }
- return false;
-}
-
-bool Frame::hasRemainingAttempts() {
- Rates& rates = mInfo.rates();
- for (size_t i = 0; i < rates.size(); ++i) {
- if (mInitialTxRates[i].idx == -1) {
- break;
- }
- if (rates[i].count < mInitialTxRates[i].count) {
- return true;
- }
- }
- return false;
-}
-
-const MacAddress& Frame::source() const {
- auto hdr = reinterpret_cast<const struct ieee80211_hdr*>(mData.data());
- return *reinterpret_cast<const MacAddress*>(hdr->addr2);
-}
-
-const MacAddress& Frame::destination() const {
- auto hdr = reinterpret_cast<const struct ieee80211_hdr*>(mData.data());
- return *reinterpret_cast<const MacAddress*>(hdr->addr1);
-}
-
-std::string Frame::str() const {
- uint8_t type = (mData[0] >> 2) & 0x3;
- uint8_t subType = (mData[0] >> 4) & 0x0F;
-
- std::stringstream ss;
- ss << "[ Ck: " << cookie() << " Ch: " << channel() << " ] ";
- switch (type) {
- case 0:
- // Management
- ss << "Management (";
- switch (subType) {
- case 0:
- ss << "Association Request";
- break;
- case 1:
- ss << "Association Response";
- break;
- case 2:
- ss << "Reassociation Request";
- break;
- case 3:
- ss << "Reassociation Response";
- break;
- case 4:
- ss << "Probe Request";
- break;
- case 5:
- ss << "Probe Response";
- break;
- case 6:
- ss << "Timing Advertisement";
- break;
- case 8:
- ss << "Beacon";
- break;
- case 9:
- ss << "ATIM";
- break;
- case 10:
- ss << "Disassociation";
- break;
- case 11:
- ss << "Authentication";
- break;
- case 12:
- ss << "Deauthentication";
- break;
- case 13:
- ss << "Action";
- break;
- case 14:
- ss << "Action No Ack";
- break;
- default:
- ss << subType;
- break;
- }
- ss << ')';
- break;
- case 1:
- // Control
- ss << "Control (";
- switch (subType) {
- case 4:
- ss << "Beamforming Report Poll";
- break;
- case 5:
- ss << "VHT NDP Announcement";
- break;
- case 6:
- ss << "Control Frame Extension";
- break;
- case 7:
- ss << "Control Wrapper";
- break;
- case 8:
- ss << "Block Ack Request";
- break;
- case 9:
- ss << "Block Ack";
- break;
- case 10:
- ss << "PS-Poll";
- break;
- case 11:
- ss << "RTS";
- break;
- case 12:
- ss << "CTS";
- break;
- case 13:
- ss << "Ack";
- break;
- case 14:
- ss << "CF-End";
- break;
- case 15:
- ss << "CF-End+CF-Ack";
- break;
- default:
- ss << subType;
- break;
- }
- ss << ')';
- break;
- case 2:
- // Data
- ss << "Data (";
- switch (subType) {
- case 0:
- ss << "Data";
- break;
- case 1:
- ss << "Data+CF-Ack";
- break;
- case 2:
- ss << "Data+CF-Poll";
- break;
- case 3:
- ss << "Data+CF-Ack+CF-Poll";
- break;
- case 4:
- ss << "Null";
- break;
- case 5:
- ss << "CF-Ack";
- break;
- case 6:
- ss << "CF-Poll";
- break;
- case 7:
- ss << "CF-Ack+CF-Poll";
- break;
- case 8:
- ss << "QoS Data";
- break;
- case 9:
- ss << "QoS Data+CF-Ack";
- break;
- case 10:
- ss << "QoS Data+CF-Poll";
- break;
- case 11:
- ss << "QoS Data+CF-Ack+CF-Poll";
- break;
- case 12:
- ss << "QoS Null";
- break;
- case 14:
- ss << "QoS CF-Poll";
- break;
- case 15:
- ss << "QoS CF-Poll+CF-Ack";
- break;
- default:
- ss << subType;
- break;
- }
- ss << ')';
- break;
- case 3:
- // Extension
- ss << "Extension (";
- switch (subType) {
- case 0:
- ss << "DMG Beacon";
- break;
- default:
- ss << subType;
- break;
- }
- ss << ')';
- break;
- default:
- ss << type << " (" << subType << ')';
- break;
- }
- return ss.str();
-}
-
-bool Frame::isBeacon() const {
- uint8_t totalType = mData[0] & 0xFC;
- return totalType == 0x80;
-}
-
-bool Frame::isData() const {
- uint8_t totalType = mData[0] & 0x0C;
- return totalType == 0x08;
-}
-
-bool Frame::isDataQoS() const {
- uint8_t totalType = mData[0] & 0xFC;
- return totalType == 0x88;
-}
-
-uint16_t Frame::getQoSControl() const {
- // Some frames have 4 address fields instead of 3 which pushes QoS control
- // forward 6 bytes.
- bool uses4Addresses = !!(mData[1] & 0x03);
- const uint8_t* addr = &mData[uses4Addresses ? 30 : 24];
-
- return __le16_to_cpu(*reinterpret_cast<const uint16_t*>(addr));
-}
-
-uint64_t Frame::calcNextTimeout() {
- mNextTimeout = (mContentionWindow * kSlotTime) / 2;
- mContentionWindow = std::min((mContentionWindow * 2) + 1,
- mContentionWindowMax);
- return mNextTimeout;
-}
-
-AccessCategory Frame::getAc() const {
- if (!isData()) {
- return AccessCategory::Voice;
- }
- if (!isDataQoS()) {
- return AccessCategory::BestEffort;
- }
- uint16_t priority = getQoSControl() & 0x07;
- return kPriorityToAc[priority];
-}
diff --git a/network/wifi_forwarder/frame.h b/network/wifi_forwarder/frame.h
deleted file mode 100644
index ac76f827..00000000
--- a/network/wifi_forwarder/frame.h
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * Copyright 2019, 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.
- */
-
-#pragma once
-
-#include "macaddress.h"
-
-#include <stdint.h>
-
-#include <array>
-#include <vector>
-
-#define IEEE80211_TX_MAX_RATES 4
-
-struct hwsim_tx_rate {
- signed char idx;
- unsigned char count;
-} __attribute__((__packed__));
-
-enum class FrameType : uint8_t {
- Unknown,
- Ack,
- Data,
-};
-
-enum class AccessCategory {
- Voice,
- Video,
- BestEffort,
- Background,
-};
-
-FrameType frameTypeFromByte(uint8_t byte);
-
-using Rates = std::array<hwsim_tx_rate, IEEE80211_TX_MAX_RATES>;
-
-class FrameInfo {
-public:
- FrameInfo() = default;
- FrameInfo(const FrameInfo&) = default;
- FrameInfo(FrameInfo&&) = default;
- FrameInfo(const MacAddress& transmitter,
- uint64_t cookie,
- uint32_t flags,
- uint32_t channel,
- const hwsim_tx_rate* rates,
- size_t numRates);
-
- FrameInfo& operator=(const FrameInfo&) = default;
- FrameInfo& operator=(FrameInfo&&) = default;
-
- const Rates& rates() const { return mTxRates; }
- Rates& rates() { return mTxRates; }
-
- const MacAddress& transmitter() const { return mTransmitter; }
- uint64_t cookie() const { return mCookie; }
- uint32_t flags() const { return mFlags; }
- uint32_t channel() const { return mChannel; }
-
- bool shouldAck() const;
-
-private:
- Rates mTxRates;
- MacAddress mTransmitter;
- uint64_t mCookie = 0;
- uint32_t mFlags = 0;
- uint32_t mChannel = 0;
-};
-
-class Frame {
-public:
- Frame() = default;
- Frame(const uint8_t* data, size_t size);
- Frame(const uint8_t* data,
- size_t size,
- const MacAddress& transmitter,
- uint64_t cookie,
- uint32_t flags,
- uint32_t channel,
- const hwsim_tx_rate* rates,
- size_t numRates);
- Frame(Frame&& other) = default;
-
- Frame& operator=(Frame&& other) = default;
-
- size_t size() const { return mData.size(); }
- const uint8_t* data() const { return mData.data(); }
- uint8_t* data() { return mData.data(); }
- uint64_t cookie() const { return mInfo.cookie(); }
- uint32_t flags() const { return mInfo.flags(); }
- uint32_t channel() const { return mInfo.channel(); }
-
- Rates& rates() { return mInfo.rates(); }
- const Rates& rates() const { return mInfo.rates(); }
-
- const Rates& initialRates() const { return mInitialTxRates; }
-
- // Increment the number of attempts made in the tx rates
- bool incrementAttempts();
- bool hasRemainingAttempts();
-
- // The transmitter as indicated by hwsim
- const MacAddress& transmitter() const { return mInfo.transmitter(); }
- // The source as indicated by the 802.11 frame
- const MacAddress& source() const;
- // The destination as indicated by the 802.11 frame
- const MacAddress& destination() const;
-
- std::string str() const;
-
- const FrameInfo& info() const { return mInfo; }
- FrameInfo& info() { return mInfo; }
-
- bool isBeacon() const;
- bool isData() const;
- bool isDataQoS() const;
-
- uint16_t getQoSControl() const;
-
- bool shouldAck() const { return mInfo.shouldAck(); }
-
- uint64_t calcNextTimeout();
-
- void setRadioDestination(const MacAddress& destination) {
- mRadioDestination = destination;
- }
- const MacAddress& radioDestination() const { return mRadioDestination; }
-private:
- Frame(const Frame&) = delete;
- Frame& operator=(const Frame&) = delete;
-
- AccessCategory getAc() const;
-
- std::vector<uint8_t> mData;
- FrameInfo mInfo;
- MacAddress mRadioDestination;
- Rates mInitialTxRates;
- uint64_t mNextTimeout = 0;
- // The contention winow determines how much time to back off on each retry.
- // The contention window initial value and max value are determined by the
- // access category of the frame.
- uint32_t mContentionWindow = 0;
- uint32_t mContentionWindowMax = 0;
-};
-
diff --git a/network/wifi_forwarder/frame_id.h b/network/wifi_forwarder/frame_id.h
deleted file mode 100644
index 545693a2..00000000
--- a/network/wifi_forwarder/frame_id.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright 2019, 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.
- */
-
-#pragma once
-
-#include "macaddress.h"
-
-#include <string.h>
-
-struct FrameId {
- FrameId() {}
- FrameId(uint64_t cookie, const MacAddress& transmitter)
- : cookie(cookie), transmitter(transmitter) {
- }
- FrameId(const FrameId&) = default;
- FrameId(FrameId&&) = default;
-
- FrameId& operator=(const FrameId&) = default;
- FrameId& operator=(FrameId&&) = default;
-
- uint64_t cookie;
- MacAddress transmitter;
-};
-
-namespace std {
-template<> struct hash<FrameId> {
- size_t operator()(const FrameId& id) const {
- size_t seed = 0;
- hash_combine(seed, id.cookie);
- hash_combine(seed, id.transmitter);
- return seed;
- }
-};
-}
-
-inline bool operator==(const FrameId& left, const FrameId& right) {
- return left.cookie == right.cookie && left.transmitter == right.transmitter;
-}
-
-inline bool operator<(const FrameId& left, const FrameId& right) {
- if (left.cookie < right.cookie) {
- return true;
- }
- if (left.cookie > right.cookie) {
- return false;
- }
- return memcmp(left.transmitter.addr,
- right.transmitter.addr,
- sizeof(left.transmitter.addr)) < 0;
-}
diff --git a/network/wifi_forwarder/hwsim.h b/network/wifi_forwarder/hwsim.h
deleted file mode 100644
index 1a7b09b3..00000000
--- a/network/wifi_forwarder/hwsim.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright 2019, 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.
- */
-
-#pragma once
-
-// mac80211_hwsim flags, from kernel drivers/net/wireless/mac80211_hwsim.h
-#define BIT(num) (1UL << (num))
-enum hwsim_tx_control_flags {
- HWSIM_TX_CTL_REQ_TX_STATUS = BIT(0),
- HWSIM_TX_CTL_NO_ACK = BIT(1),
- HWSIM_TX_STAT_ACK = BIT(2),
-};
-
-// mac80211_hwsim commands, from kernel drivers/net/wireless/mac80211_hwsim.h
-enum HwSimCommand {
- HWSIM_CMD_UNSPEC,
- HWSIM_CMD_REGISTER,
- HWSIM_CMD_FRAME,
- HWSIM_CMD_TX_INFO_FRAME,
- HWSIM_CMD_NEW_RADIO,
- HWSIM_CMD_DEL_RADIO,
- HWSIM_CMD_GET_RADIO,
- __HWSIM_CMD_MAX,
-};
-
-// mac80211_hwsim attributes, from kernel drivers/net/wireless/mac80211_hwsim.h
-enum HwSimAttribute {
- HWSIM_ATTR_UNSPEC,
- HWSIM_ATTR_ADDR_RECEIVER,
- HWSIM_ATTR_ADDR_TRANSMITTER,
- HWSIM_ATTR_FRAME,
- HWSIM_ATTR_FLAGS,
- HWSIM_ATTR_RX_RATE,
- HWSIM_ATTR_SIGNAL,
- HWSIM_ATTR_TX_INFO,
- HWSIM_ATTR_COOKIE,
- HWSIM_ATTR_CHANNELS,
- HWSIM_ATTR_RADIO_ID,
- HWSIM_ATTR_REG_HINT_ALPHA2,
- HWSIM_ATTR_REG_CUSTOM_REG,
- HWSIM_ATTR_REG_STRICT_REG,
- HWSIM_ATTR_SUPPORT_P2P_DEVICE,
- HWSIM_ATTR_USE_CHANCTX,
- HWSIM_ATTR_DESTROY_RADIO_ON_CLOSE,
- HWSIM_ATTR_RADIO_NAME,
- HWSIM_ATTR_NO_VIF,
- HWSIM_ATTR_FREQ,
- __HWSIM_ATTR_MAX,
-};
-#define HWSIM_ATTR_MAX (__HWSIM_ATTR_MAX - 1)
-
diff --git a/network/wifi_forwarder/ieee80211.h b/network/wifi_forwarder/ieee80211.h
deleted file mode 100644
index 6bcf2326..00000000
--- a/network/wifi_forwarder/ieee80211.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2019, 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.
- */
-
-#pragma once
-
-#include <net/ethernet.h>
-#include <stdint.h>
-
-struct ieee80211_hdr {
- uint16_t frame_control;
- uint16_t duration_id;
- uint8_t addr1[ETH_ALEN];
- uint8_t addr2[ETH_ALEN];
- uint8_t addr3[ETH_ALEN];
- uint16_t seq_ctrl;
- uint8_t addr4[ETH_ALEN];
-} __attribute__((__packed__));
-
diff --git a/network/wifi_forwarder/local_connection.cpp b/network/wifi_forwarder/local_connection.cpp
deleted file mode 100644
index 1cebc17e..00000000
--- a/network/wifi_forwarder/local_connection.cpp
+++ /dev/null
@@ -1,392 +0,0 @@
-/*
- * Copyright 2019, 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 "local_connection.h"
-
-#include "hwsim.h"
-#include "log.h"
-#include "macaddress.h"
-#include "netlink_message.h"
-
-#include <net/ethernet.h>
-#include <netlink/netlink.h>
-#include <netlink/genl/ctrl.h>
-#include <netlink/genl/genl.h>
-
-#include <utils/CallStack.h>
-
-#include <inttypes.h>
-#include <stdlib.h>
-
-static const char kHwSimFamilyName[] = "MAC80211_HWSIM";
-static const int kHwSimVersion = 1;
-static const unsigned int kDefaultSignalStrength = -50;
-static const int kDefaultSocketBufferSize = 8 * (1 << 20);
-
-static uint32_t getSeqNum(struct nl_msg* msg) {
- return nlmsg_hdr(msg)->nlmsg_seq;
-}
-
-static int onSent(struct nl_msg* , void*) {
- return NL_OK;
-}
-
-static int onSeqCheck(struct nl_msg* msg, void*) {
- uint32_t seq = getSeqNum(msg);
- return seq == 0 ? NL_SKIP : NL_OK;
-}
-
-LocalConnection::LocalConnection(OnFrameCallback onFrameCallback,
- OnAckCallback onAckCallback,
- OnErrorCallback onErrorCallback)
- : mOnFrameCallback(onFrameCallback)
- , mOnAckCallback(onAckCallback)
- , mOnErrorCallback(onErrorCallback) {
-
-}
-
-Result LocalConnection::init(std::chrono::steady_clock::time_point now) {
- Result res = mNetlinkSocket.init();
- if (!res) { return res; }
- res = mNetlinkSocket.setOnMsgInCallback(staticOnMessage, this);
- if (!res) { return res; }
- res = mNetlinkSocket.setOnMsgOutCallback(onSent, this);
- if (!res) { return res; }
- res = mNetlinkSocket.setOnSeqCheckCallback(onSeqCheck, this);
- if (!res) { return res; }
- res = mNetlinkSocket.setOnAckCallback(staticOnAck, this);
- if (!res) { return res; }
- res = mNetlinkSocket.setOnErrorCallback(staticOnError, this);
- if (!res) { return res; }
- res = mNetlinkSocket.connectGeneric();
- if (!res) { return res; }
- res = mNetlinkSocket.setBufferSizes(kDefaultSocketBufferSize,
- kDefaultSocketBufferSize);
- if (!res) { return res; }
-
- mNetlinkFamily = mNetlinkSocket.resolveNetlinkFamily(kHwSimFamilyName);
- if (mNetlinkFamily < 0) {
- return Result::error("Failed to resolve netlink family name: %s",
- nl_geterror(mNetlinkFamily));
- }
-
- mPendingFrames.setCurrentTime(now);
- mSequenceNumberCookies.setCurrentTime(now);
-
- mLastCacheTimeUpdate = now;
- mLastCacheExpiration = now;
-
- return registerReceiver();
-}
-
-int LocalConnection::getFd() const {
- return mNetlinkSocket.getFd();
-}
-
-bool LocalConnection::receive() {
- return mNetlinkSocket.receive();
-}
-
-uint32_t LocalConnection::transferFrame(std::unique_ptr<Frame> frame,
- const MacAddress& dest) {
- NetlinkMessage msg;
-
- if (!msg.initGeneric(mNetlinkFamily, HWSIM_CMD_FRAME, kHwSimVersion)) {
- ALOGE("LocalConnection transferFrame failed to init msg");
- return 0;
- }
-
- frame->incrementAttempts();
-
- if (!msg.addAttribute(HWSIM_ATTR_ADDR_RECEIVER, dest.addr, ETH_ALEN) ||
- !msg.addAttribute(HWSIM_ATTR_FRAME, frame->data(), frame->size()) ||
- !msg.addAttribute(HWSIM_ATTR_RX_RATE, 1u) ||
- !msg.addAttribute(HWSIM_ATTR_SIGNAL, kDefaultSignalStrength) ||
- !msg.addAttribute(HWSIM_ATTR_FREQ, frame->channel())) {
-
- ALOGE("LocalConnection transferFrame failed to set attrs");
- return 0;
- }
-
- if (!mNetlinkSocket.send(msg)) {
- return 0;
- }
-
- // Store the radio destination for potential retransmissions.
- frame->setRadioDestination(dest);
-
- uint32_t seqNum = msg.getSeqNum();
- uint64_t cookie = frame->cookie();
- FrameId id(cookie, frame->transmitter());
- mSequenceNumberCookies[seqNum] = id;
- mPendingFrames[id] = std::move(frame);
-
- return seqNum;
-}
-
-uint32_t LocalConnection::cloneFrame(const Frame& frame,
- const MacAddress& dest) {
- auto copy = std::make_unique<Frame>(frame.data(),
- frame.size(),
- frame.transmitter(),
- frame.cookie(),
- frame.flags(),
- frame.channel(),
- frame.rates().data(),
- frame.rates().size());
- return transferFrame(std::move(copy), dest);
-}
-
-bool LocalConnection::ackFrame(FrameInfo& info, bool success) {
- NetlinkMessage msg;
-
- if (!msg.initGeneric(mNetlinkFamily,
- HWSIM_CMD_TX_INFO_FRAME,
- kHwSimVersion)) {
- ALOGE("LocalConnection ackFrame failed to create msg");
- return false;
- }
-
- uint32_t flags = info.flags();
- if (success) {
- flags |= HWSIM_TX_STAT_ACK;
- }
-
- const uint8_t* transmitter = info.transmitter().addr;
- const Rates& rates = info.rates();
- if (!msg.addAttribute(HWSIM_ATTR_ADDR_TRANSMITTER, transmitter, ETH_ALEN) ||
- !msg.addAttribute(HWSIM_ATTR_TX_INFO, rates.data(), rates.size()) ||
- !msg.addAttribute(HWSIM_ATTR_FLAGS, flags) ||
- !msg.addAttribute(HWSIM_ATTR_SIGNAL, kDefaultSignalStrength) ||
- !msg.addAttribute(HWSIM_ATTR_COOKIE, info.cookie())) {
-
- ALOGE("LocalConnection ackFrame failed to set attributes");
- return false;
- }
-
- if (!mNetlinkSocket.send(msg)) {
- return false;
- }
- mPendingFrames.erase(FrameId(info.cookie(), info.transmitter()));
- return true;
-}
-
-std::chrono::steady_clock::time_point LocalConnection::getTimeout() const {
- if (mRetryQueue.empty()) {
- return std::chrono::steady_clock::time_point::max();
- }
- return mRetryQueue.top().first;
-}
-
-void LocalConnection::onTimeout(std::chrono::steady_clock::time_point now) {
-
- if (now - mLastCacheTimeUpdate > std::chrono::seconds(1)) {
- // Only update the time once per second, there's no need for a super
- // high resolution here. We just want to make sure these caches don't
- // fill up over a long period of time.
- mPendingFrames.setCurrentTime(now);
- mSequenceNumberCookies.setCurrentTime(now);
- mLastCacheTimeUpdate = now;
- }
- if (now - mLastCacheExpiration > std::chrono::seconds(10)) {
- // Only expire entries every 10 seconds, this is an operation that has
- // some cost to it and doesn't have to happen very often.
- mPendingFrames.expireEntries();
- mSequenceNumberCookies.expireEntries();
- mLastCacheExpiration = now;
- }
-
- while (!mRetryQueue.empty() && now >= mRetryQueue.top().first) {
- FrameId id = mRetryQueue.top().second;
- auto frameIt = mPendingFrames.find(id);
- if (frameIt != mPendingFrames.end()) {
- // Frame is still available, retry it
- std::unique_ptr<Frame> frame = std::move(frameIt->second);
- mPendingFrames.erase(frameIt);
- MacAddress dest = frame->radioDestination();
- transferFrame(std::move(frame), dest);
- }
- mRetryQueue.pop();
- }
-}
-
-Result LocalConnection::registerReceiver() {
- NetlinkMessage msg;
-
- if (!msg.initGeneric(mNetlinkFamily, HWSIM_CMD_REGISTER, kHwSimVersion)) {
- return Result::error("Failed to create register receiver message");
- }
-
- if (!mNetlinkSocket.send(msg)) {
- return Result::error("Failed to send register receiver message");
- }
- return Result::success();
-}
-
-int LocalConnection::staticOnMessage(struct nl_msg* msg, void* context) {
- if (!context) {
- return NL_SKIP;
- }
- auto connection = static_cast<LocalConnection*>(context);
- return connection->onMessage(msg);
-}
-
-int LocalConnection::staticOnAck(struct nl_msg* msg, void* context) {
- if (!context) {
- return NL_SKIP;
- }
- auto connection = static_cast<LocalConnection*>(context);
- return connection->onAck(msg);
-}
-
-int LocalConnection::staticOnError(struct sockaddr_nl* addr,
- struct nlmsgerr* error,
- void* context) {
- if (!context) {
- return NL_SKIP;
- }
- auto connection = static_cast<LocalConnection*>(context);
- return connection->onError(addr, error);
-}
-
-int LocalConnection::onMessage(struct nl_msg* msg) {
- struct nlmsghdr* hdr = nlmsg_hdr(msg);
- auto generic = reinterpret_cast<const struct genlmsghdr*>(nlmsg_data(hdr));
-
- switch (generic->cmd) {
- case HWSIM_CMD_FRAME:
- return onFrame(msg);
- }
- return NL_OK;
-}
-
-int LocalConnection::onFrame(struct nl_msg* msg) {
-
- struct nlmsghdr* hdr = nlmsg_hdr(msg);
- std::unique_ptr<Frame> frame = parseFrame(hdr);
- if (!frame) {
- return NL_SKIP;
- }
-
- mOnFrameCallback(std::move(frame));
- return NL_OK;
-}
-
-std::unique_ptr<Frame> LocalConnection::parseFrame(struct nlmsghdr* hdr) {
- struct nlattr* attrs[HWSIM_ATTR_MAX + 1];
- genlmsg_parse(hdr, 0, attrs, HWSIM_ATTR_MAX, nullptr);
- if (!attrs[HWSIM_ATTR_ADDR_TRANSMITTER]) {
- ALOGE("Received cmd frame without transmitter address");
- return nullptr;
- }
- if (!attrs[HWSIM_ATTR_TX_INFO]) {
- ALOGE("Received cmd frame without tx rates");
- return nullptr;
- }
- if (!attrs[HWSIM_ATTR_FREQ]) {
- ALOGE("Recieved cmd frame without channel frequency");
- return nullptr;
- }
-
- uint64_t cookie = nla_get_u64(attrs[HWSIM_ATTR_COOKIE]);
-
- const auto& source = *reinterpret_cast<const MacAddress*>(
- nla_data(attrs[HWSIM_ATTR_ADDR_TRANSMITTER]));
-
- auto rates = reinterpret_cast<const hwsim_tx_rate*>(
- nla_data(attrs[HWSIM_ATTR_TX_INFO]));
- int rateLength = nla_len(attrs[HWSIM_ATTR_TX_INFO]);
- // Make sure the length is valid, must be multiple of hwsim_tx_rate
- if (rateLength <= 0 || (rateLength % sizeof(hwsim_tx_rate)) != 0) {
- ALOGE("Invalid tx rate length %d", rateLength);
- }
- size_t numRates = static_cast<size_t>(rateLength) / sizeof(hwsim_tx_rate);
-
- int length = nla_len(attrs[HWSIM_ATTR_FRAME]);
- auto data = reinterpret_cast<uint8_t*>(nla_data(attrs[HWSIM_ATTR_FRAME]));
-
- uint32_t flags = nla_get_u32(attrs[HWSIM_ATTR_FLAGS]);
-
- uint32_t channel = nla_get_u32(attrs[HWSIM_ATTR_FREQ]);
-
- return std::make_unique<Frame>(data, length, source, cookie,
- flags, channel, rates, numRates);
-}
-
-int LocalConnection::onAck(struct nl_msg* msg) {
- struct nlmsghdr* hdr = nlmsg_hdr(msg);
- uint32_t seqNum = hdr->nlmsg_seq;
- auto cookie = mSequenceNumberCookies.find(seqNum);
- if (cookie == mSequenceNumberCookies.end()) {
- // This is not a frame we sent. This is fairly common for libnl's
- // internal use so don't log this.
- return NL_SKIP;
- }
- auto pendingFrame = mPendingFrames.find(cookie->second);
- // We don't need to keep this around anymore, erase it.
- mSequenceNumberCookies.erase(seqNum);
- if (pendingFrame == mPendingFrames.end()) {
- // We have no cookie associated with this sequence number. This might
- // happen if the remote connection already acked the frame and removed
- // the frame info. Consider this resolved.
- return NL_SKIP;
- }
-
- Frame* frame = pendingFrame->second.get();
- mOnAckCallback(frame->info());
- // Make sure to erase using the cookie instead of the iterator. The callback
- // might have already erased this entry so the iterator could be invalid at
- // this point. Instead of a fancy scheme of checking this just play it safe
- // to allow the callback more freedom.
- mPendingFrames.erase(cookie->second);
-
- return NL_OK;
-}
-
-int LocalConnection::onError(struct sockaddr_nl*, struct nlmsgerr* error) {
- struct nlmsghdr* hdr = &error->msg;
- uint32_t seqNum = hdr->nlmsg_seq;
-
- auto idIt = mSequenceNumberCookies.find(seqNum);
- if (idIt == mSequenceNumberCookies.end()) {
- return NL_SKIP;
- }
- FrameId id = idIt->second;
- // No need to keep the sequence number around anymore, it's expired and is
- // no longer useful.
- mSequenceNumberCookies.erase(idIt);
-
- auto frameIt = mPendingFrames.find(id);
- if (frameIt == mPendingFrames.end()) {
- return NL_SKIP;
- }
- Frame* frame = frameIt->second.get();
-
- if (!frame->hasRemainingAttempts()) {
- // This frame has used up all its attempts, there's nothing we can do
- mOnErrorCallback(frame->info());
- mPendingFrames.erase(id);
- return NL_SKIP;
- }
- // Store the frame in the retry queue
- uint64_t timeout = frame->calcNextTimeout();
- auto deadline = std::chrono::steady_clock::now() +
- std::chrono::microseconds(timeout);
- mRetryQueue.emplace(deadline, id);
-
- return NL_SKIP;
-}
-
diff --git a/network/wifi_forwarder/local_connection.h b/network/wifi_forwarder/local_connection.h
deleted file mode 100644
index 9f3969a0..00000000
--- a/network/wifi_forwarder/local_connection.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright 2019, 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.
- */
-
-#pragma once
-
-#include "cache.h"
-#include "frame.h"
-#include "frame_id.h"
-#include "macaddress.h"
-#include "netlink_socket.h"
-#include "result.h"
-
-#include <chrono>
-#include <functional>
-#include <memory>
-#include <queue>
-
-struct MacAddress;
-
-class LocalConnection {
-public:
- using OnFrameCallback = std::function<void (std::unique_ptr<Frame>)>;
- using OnAckCallback = std::function<void (FrameInfo&)>;
- using OnErrorCallback = OnAckCallback;
-
- LocalConnection(OnFrameCallback onFrameCallback,
- OnAckCallback onAckCallback,
- OnErrorCallback onErrorCallback);
- Result init(std::chrono::steady_clock::time_point now);
-
- int getFd() const;
- bool receive();
- uint32_t cloneFrame(const Frame& frame, const MacAddress& destination);
- uint32_t transferFrame(std::unique_ptr<Frame> frame,
- const MacAddress& destination);
- bool ackFrame(FrameInfo& info, bool success);
-
- std::chrono::steady_clock::time_point getTimeout() const;
- void onTimeout(std::chrono::steady_clock::time_point now);
-
-private:
- using Timestamp = std::chrono::steady_clock::time_point;
-
- Result registerReceiver();
- static int staticOnMessage(struct nl_msg* msg, void* context);
- static int staticOnAck(struct nl_msg* msg, void* context);
- static int staticOnError(struct sockaddr_nl* addr,
- struct nlmsgerr* error,
- void* context);
- int onMessage(struct nl_msg* msg);
- int onFrame(struct nl_msg* msg);
- std::unique_ptr<Frame> parseFrame(struct nlmsghdr* hdr);
-
- int onAck(struct nl_msg* msg);
- int onError(struct sockaddr_nl* addr, struct nlmsgerr* error);
- bool sendFrameOnNetlink(const Frame& frame, const MacAddress& dest);
-
- OnFrameCallback mOnFrameCallback;
- OnAckCallback mOnAckCallback;
- OnErrorCallback mOnErrorCallback;
-
- NetlinkSocket mNetlinkSocket;
- int mNetlinkFamily = -1;
-
- // [cookie,transmitter] -> frame.
- Cache<FrameId, std::unique_ptr<Frame>> mPendingFrames;
- // sequence number -> [cookie,transmitter]
- Cache<uint32_t, FrameId> mSequenceNumberCookies;
-
- Timestamp mLastCacheTimeUpdate;
- Timestamp mLastCacheExpiration;
-
- // A queue (using an ordered map) with the next timeout mapping to the
- // cookie and transmitter of the frame to retry. This way we can easily
- // determine when the next deadline is by looking at the first entry and we
- // can quickly determine which frames to retry by starting at the beginning.
- std::priority_queue<std::pair<Timestamp, FrameId>> mRetryQueue;
-};
-
diff --git a/network/wifi_forwarder/macaddress.h b/network/wifi_forwarder/macaddress.h
deleted file mode 100644
index a9bcb660..00000000
--- a/network/wifi_forwarder/macaddress.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright 2019, 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.
- */
-
-#pragma once
-
-#include "hash.h"
-
-#include <linux/if_ether.h>
-#include <stdint.h>
-#include <string.h>
-
-// Format macros for printf, e.g. printf("MAC address: " PRIMAC, MACARG(mac))
-#define PRIMAC "%02x:%02x:%02x:%02x:%02x:%02x"
-#define MACARG(x) (x)[0], (x)[1], (x)[2], (x)[3],(x)[4], (x)[5]
-
-struct MacAddress {
- MacAddress() {
- memset(addr, 0, sizeof(addr));
- }
- MacAddress(uint8_t b1, uint8_t b2, uint8_t b3,
- uint8_t b4, uint8_t b5, uint8_t b6) {
- addr[0] = b1; addr[1] = b2; addr[2] = b3;
- addr[3] = b4; addr[4] = b5; addr[5] = b6;
- }
- uint8_t addr[ETH_ALEN];
- bool isBroadcast() const {
- return memcmp(addr, "\xFF\xFF\xFF\xFF\xFF\xFF", ETH_ALEN) == 0;
- }
- bool isMulticast() const {
- return addr[0] & 0x01;
- }
- bool empty() const {
- return memcmp(addr, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) == 0;
- }
- uint8_t operator[](size_t index) const {
- return addr[index];
- }
-} __attribute__((__packed__));
-
-namespace std {
-template<> struct hash<MacAddress> {
- size_t operator()(const MacAddress& addr) const {
- size_t seed = 0;
- // Treat the first 4 bytes as an uint32_t to save some computation
- hash_combine(seed, *reinterpret_cast<const uint32_t*>(addr.addr));
- // And the remaining 2 bytes as an uint16_t
- hash_combine(seed, *reinterpret_cast<const uint16_t*>(addr.addr + 4));
- return seed;
- }
-};
-}
-
-inline bool operator==(const MacAddress& left, const MacAddress& right) {
- return memcmp(left.addr, right.addr, ETH_ALEN) == 0;
-}
-
-inline bool operator!=(const MacAddress& left, const MacAddress& right) {
- return memcmp(left.addr, right.addr, ETH_ALEN) != 0;
-}
-
diff --git a/network/wifi_forwarder/main.cpp b/network/wifi_forwarder/main.cpp
deleted file mode 100644
index 57127a94..00000000
--- a/network/wifi_forwarder/main.cpp
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2019, 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 "log.h"
-#include "poller.h"
-#include "wifi_forwarder.h"
-
-int main(int /*argc*/, char* /*argv*/[]) {
- WifiForwarder forwarder;
- Result res = forwarder.init();
- if (!res) {
- ALOGE("%s", res.c_str());
- return 1;
- }
-
- Poller poller;
- poller.addPollable(&forwarder);
- return poller.run();
-}
-
diff --git a/network/wifi_forwarder/netlink_message.cpp b/network/wifi_forwarder/netlink_message.cpp
deleted file mode 100644
index 265c2968..00000000
--- a/network/wifi_forwarder/netlink_message.cpp
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright 2019, 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 "netlink_message.h"
-
-#include <netlink/genl/genl.h>
-#include <netlink/msg.h>
-
-NetlinkMessage::NetlinkMessage() {
-}
-
-NetlinkMessage::NetlinkMessage(NetlinkMessage&& other) {
- std::swap(mMessage, other.mMessage);
-}
-
-NetlinkMessage::~NetlinkMessage() {
- if (mMessage) {
- nlmsg_free(mMessage);
- mMessage = nullptr;
- }
-}
-
-NetlinkMessage& NetlinkMessage::operator=(NetlinkMessage&& other) {
- if (mMessage) {
- nlmsg_free(mMessage);
- mMessage = nullptr;
- }
- std::swap(mMessage, other.mMessage);
- return *this;
-}
-
-bool NetlinkMessage::initGeneric(int family, uint8_t command, int version) {
- if (mMessage) {
- return false;
- }
-
- mMessage = nlmsg_alloc();
- if (!mMessage) {
- return false;
- }
-
- return genlmsg_put(mMessage, NL_AUTO_PORT, NL_AUTO_SEQ, family, 0,
- NLM_F_REQUEST, command, version) != nullptr;
-}
-
-uint32_t NetlinkMessage::getSeqNum() const {
- return nlmsg_hdr(mMessage)->nlmsg_seq;
-}
diff --git a/network/wifi_forwarder/netlink_message.h b/network/wifi_forwarder/netlink_message.h
deleted file mode 100644
index 53d97a96..00000000
--- a/network/wifi_forwarder/netlink_message.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 2019, 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.
- */
-
-#pragma once
-
-#include "result.h"
-
-#include <netlink/netlink.h>
-
-#include <type_traits>
-
-class NetlinkMessage {
-public:
- NetlinkMessage();
- NetlinkMessage(NetlinkMessage&& other);
- ~NetlinkMessage();
-
- NetlinkMessage& operator=(NetlinkMessage&& other);
-
- bool initGeneric(int family, uint8_t command, int version);
-
- template<typename T,
- typename = typename std::enable_if<!std::is_pointer<T>::value>::type>
- bool addAttribute(int attribute, const T& value) {
- return nla_put(mMessage, attribute, sizeof(T), &value) == 0;
- }
- template<typename T,
- typename = typename std::enable_if<std::is_pointer<T>::value>::type>
- bool addAttribute(int attribute, T data, size_t numElements) {
- return nla_put(mMessage,
- attribute,
- sizeof(*data) * numElements,
- data) == 0;
- }
-
- uint32_t getSeqNum() const;
-
- struct nl_msg* get() { return mMessage; }
-
-private:
- NetlinkMessage(const NetlinkMessage&) = delete;
- NetlinkMessage& operator=(const NetlinkMessage&) = delete;
-
- struct nl_msg* mMessage = nullptr;
-};
-
diff --git a/network/wifi_forwarder/netlink_socket.cpp b/network/wifi_forwarder/netlink_socket.cpp
deleted file mode 100644
index 5af66a56..00000000
--- a/network/wifi_forwarder/netlink_socket.cpp
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright 2019, 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 "netlink_socket.h"
-
-#include "log.h"
-#include "netlink_message.h"
-
-#include <netlink/genl/ctrl.h>
-#include <netlink/genl/genl.h>
-#include <netlink/netlink.h>
-
-NetlinkSocket::NetlinkSocket() {
-}
-
-NetlinkSocket::~NetlinkSocket() {
- if (mSocket) {
- nl_socket_free(mSocket);
- mSocket = nullptr;
- mCallback = nullptr;
- }
-}
-
-Result NetlinkSocket::init() {
- if (mSocket || mCallback) {
- return Result::error("Netlink socket already initialized");
- }
- mCallback = nl_cb_alloc(NL_CB_CUSTOM);
- if (!mCallback) {
- return Result::error("Netlink socket failed to allocate callbacks");
- }
- mSocket = nl_socket_alloc_cb(mCallback);
- if (!mSocket) {
- return Result::error("Failed to allocate netlink socket");
- }
- return Result::success();
-}
-
-Result NetlinkSocket::setBufferSizes(int rxBufferSize, int txBufferSize) {
- int res = nl_socket_set_buffer_size(mSocket, rxBufferSize, txBufferSize);
- if (res != 0) {
- return Result::error("Failed to set buffer sizes: %s",
- nl_geterror(res));
- }
- return Result::success();
-}
-
-Result NetlinkSocket::setOnMsgInCallback(int (*callback)(struct nl_msg*, void*),
- void* context) {
- if (nl_cb_set(mCallback, NL_CB_MSG_IN, NL_CB_CUSTOM, callback, context)) {
- return Result::error("Failed to set OnMsgIn callback");
- }
- return Result::success();
-}
-
-Result NetlinkSocket::setOnMsgOutCallback(int (*callback)(struct nl_msg*,
- void*),
- void* context) {
- if (nl_cb_set(mCallback, NL_CB_MSG_OUT, NL_CB_CUSTOM, callback, context)) {
- return Result::error("Failed to set OnMsgOut callback");
- }
- return Result::success();
-}
-
-Result NetlinkSocket::setOnSeqCheckCallback(int (*callback)(struct nl_msg*,
- void*),
- void* context) {
- if (nl_cb_set(mCallback, NL_CB_SEQ_CHECK, NL_CB_CUSTOM,
- callback, context)) {
- return Result::error("Failed to set OnSeqCheck callback");
- }
- return Result::success();
-}
-
-Result NetlinkSocket::setOnAckCallback(int (*callback)(struct nl_msg*, void*),
- void* context) {
- if (nl_cb_set(mCallback, NL_CB_ACK, NL_CB_CUSTOM, callback, context)) {
- return Result::error("Failed to set OnAck callback");
- }
- return Result::success();
-}
-
-Result NetlinkSocket::setOnErrorCallback(int (*callback)(struct sockaddr_nl*,
- struct nlmsgerr*,
- void*),
- void* context) {
- if (nl_cb_err(mCallback, NL_CB_CUSTOM, callback, context)) {
- return Result::error("Failed to set OnError callback");
- }
- return Result::success();
-}
-
-Result NetlinkSocket::connectGeneric() {
- int status = genl_connect(mSocket);
- if (status < 0) {
- return Result::error("WifiNetlinkForwarder socket connect failed: %d",
- status);
- }
- return Result::success();
-}
-
-int NetlinkSocket::resolveNetlinkFamily(const char* familyName) {
- return genl_ctrl_resolve(mSocket, familyName);
-}
-
-bool NetlinkSocket::send(NetlinkMessage& message) {
- int status = nl_send_auto(mSocket, message.get()) >= 0;
- if (status < 0) {
- ALOGE("Failed to send on netlink socket: %s", nl_geterror(status));
- return false;
- }
- return true;
-}
-
-bool NetlinkSocket::receive() {
- int res = nl_recvmsgs_default(mSocket);
- if (res != 0) {
- ALOGE("Failed to receive messages on netlink socket: %s",
- nl_geterror(res));
- return false;
- }
- return true;
-}
-
-int NetlinkSocket::getFd() const {
- if (!mSocket) {
- return -1;
- }
- return nl_socket_get_fd(mSocket);
-}
diff --git a/network/wifi_forwarder/netlink_socket.h b/network/wifi_forwarder/netlink_socket.h
deleted file mode 100644
index 9ff392c5..00000000
--- a/network/wifi_forwarder/netlink_socket.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright 2019, 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.
- */
-
-#pragma once
-
-#include "result.h"
-
-struct nl_cb;
-struct nl_msg;
-struct nl_sock;
-struct nlmsgerr;
-struct sockaddr_nl;
-
-class NetlinkMessage;
-
-class NetlinkSocket {
-public:
- NetlinkSocket();
- ~NetlinkSocket();
-
- Result init();
-
- /* Set the size of the receive buffer to |rxBufferSize| bytes and the
- * transmit buffer to |txBufferSize| bytes.
- */
- Result setBufferSizes(int rxBufferSize, int txBufferSize);
-
- Result setOnMsgInCallback(int (*callback)(struct nl_msg*, void*),
- void* context);
- Result setOnMsgOutCallback(int (*callback)(struct nl_msg*, void*),
- void* context);
- Result setOnSeqCheckCallback(int (*callback)(struct nl_msg*, void*),
- void* context);
- Result setOnAckCallback(int (*callback)(struct nl_msg*, void*),
- void* context);
- Result setOnErrorCallback(int (*callback)(struct sockaddr_nl*,
- struct nlmsgerr*,
- void*),
- void* context);
-
- /* Connect socket to generic netlink. This needs to be done before generic
- * netlink messages can be sent. After this is done the caller should use
- * @resolveGenericNetlinkFamily to determine the generic family id to use.
- * Then create NetlinkMessage's with that family id.
- */
- Result connectGeneric();
-
- /* Resolve a generic family name to a family identifier. This is used when
- * sending generic netlink messages to indicate where the message should go.
- * Examples of family names are "mac80211_hwsim" or "nl80211".
- */
- int resolveNetlinkFamily(const char* familyName);
-
- /* Send a netlink message on this socket. */
- bool send(NetlinkMessage& message);
-
- /* Receive all pending message. This method does not return any messages,
- * instead they will be provided through the callback set with
- * setOnMsgInCallback. This callback will be called on the same thread as
- * this method while this method is running. */
- bool receive();
-
- int getFd() const;
-
-private:
- struct nl_cb* mCallback = nullptr;
- struct nl_sock* mSocket = nullptr;
-};
-
diff --git a/network/wifi_forwarder/pollable.h b/network/wifi_forwarder/pollable.h
deleted file mode 100644
index 51724c05..00000000
--- a/network/wifi_forwarder/pollable.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright 2018, 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.
- */
-
-#pragma once
-
-#include <chrono>
-#include <vector>
-
-#include <poll.h>
-
-/* An interface for pollable classes.
- */
-class Pollable {
-public:
- using Clock = std::chrono::steady_clock;
- using Timestamp = Clock::time_point;
- virtual ~Pollable() = default;
-
- /* Get the poll data for the next poll loop. The implementation can place
- * as many fds as needed in |fds|.
- */
- virtual void getPollData(std::vector<pollfd>* fds) const = 0;
- /* Get the timeout for the next poll loop. This should be a timestamp
- * indicating when the timeout should be triggered. Note that this may
- * be called at any time and any number of times for a poll loop so the
- * deadline should not be adjusted in this call, a set deadline should
- * just be returned. Note specifically that if a call to onReadAvailable
- * modifies the deadline the timeout for the previous timestamp might not
- * fire as the poller will check the timestamp AFTER onReadAvailable is
- * called.
- */
- virtual Timestamp getTimeout() const = 0;
- /* Called when there is data available to read on an fd associated with
- * the pollable. |fd| indicates which fd to read from. If the call returns
- * false the poller will exit its poll loop with a return code of |status|.
- */
- virtual bool onReadAvailable(int fd, int* status) = 0;
- /* Called when an fd associated with the pollable is closed. |fd| indicates
- * which fd was closed. If the call returns false the poller will exit its
- * poll loop with a return code of |status|.
- */
- virtual bool onClose(int fd, int* status) = 0;
- /* Called when the timeout returned by getPollData has been reached. If
- * the call returns false the poller will exit its poll loop with a return
- * code of |status|.
- */
- virtual bool onTimeout(Timestamp now, int* status) = 0;
-};
-
diff --git a/network/wifi_forwarder/poller.cpp b/network/wifi_forwarder/poller.cpp
deleted file mode 100644
index 319dff4f..00000000
--- a/network/wifi_forwarder/poller.cpp
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Copyright 2018, 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 "poller.h"
-
-#include "log.h"
-
-#include <errno.h>
-#include <poll.h>
-#include <signal.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <unordered_map>
-#include <vector>
-
-using std::chrono::duration_cast;
-
-static struct timespec* calculateTimeout(Pollable::Timestamp deadline,
- struct timespec* ts) {
- Pollable::Timestamp now = Pollable::Clock::now();
- if (deadline < Pollable::Timestamp::max()) {
- if (deadline <= now) {
- ts->tv_sec = 0;
- ts->tv_nsec = 0;
- return ts;
- }
-
- auto timeout = deadline - now;
- // Convert and round down to seconds
- auto seconds = duration_cast<std::chrono::seconds>(timeout);
- // Then subtract the seconds from the timeout and convert the remainder
- auto nanos = duration_cast<std::chrono::nanoseconds>(timeout - seconds);
-
- ts->tv_sec = seconds.count();
- ts->tv_nsec = nanos.count();
-
- return ts;
- }
- return nullptr;
-}
-
-Poller::Poller() {
-}
-
-void Poller::addPollable(Pollable* pollable) {
- mPollables.push_back(pollable);
-}
-
-int Poller::run() {
- // Block all signals while we're running. This way we don't have to deal
- // with things like EINTR. We then uses ppoll to set the original mask while
- // polling. This way polling can be interrupted but socket writing, reading
- // and ioctl remain interrupt free. If a signal arrives while we're blocking
- // it it will be placed in the signal queue and handled once ppoll sets the
- // original mask. This way no signals are lost.
- sigset_t blockMask, mask;
- int status = ::sigfillset(&blockMask);
- if (status != 0) {
- ALOGE("Unable to fill signal set: %s", strerror(errno));
- return errno;
- }
- status = ::sigprocmask(SIG_SETMASK, &blockMask, &mask);
- if (status != 0) {
- ALOGE("Unable to set signal mask: %s", strerror(errno));
- return errno;
- }
-
- std::vector<struct pollfd> fds;
- std::unordered_map<int, Pollable*> pollables;
- while (true) {
- fds.clear();
- pollables.clear();
- Pollable::Timestamp deadline = Pollable::Timestamp::max();
- for (auto& pollable : mPollables) {
- size_t start = fds.size();
- pollable->getPollData(&fds);
- Pollable::Timestamp pollableDeadline = pollable->getTimeout();
- // Create a map from each fd to the pollable
- for (size_t i = start; i < fds.size(); ++i) {
- pollables[fds[i].fd] = pollable;
- }
- if (pollableDeadline < deadline) {
- deadline = pollableDeadline;
- }
- }
-
- struct timespec ts = { 0, 0 };
- struct timespec* tsPtr = calculateTimeout(deadline, &ts);
- status = ::ppoll(fds.data(), fds.size(), tsPtr, &mask);
- if (status < 0) {
- if (errno == EINTR) {
- // Interrupted, just keep going
- continue;
- }
- // Actual error, time to quit
- ALOGE("Polling failed: %s", strerror(errno));
- return errno;
- } else if (status > 0) {
- // Check for read or close events
- for (const auto& fd : fds) {
- if ((fd.revents & (POLLIN | POLLHUP)) == 0) {
- // Neither POLLIN nor POLLHUP, not interested
- continue;
- }
- auto pollable = pollables.find(fd.fd);
- if (pollable == pollables.end()) {
- // No matching fd, weird and unexpected
- ALOGE("Poller could not find fd matching %d", fd.fd);
- continue;
- }
- if (fd.revents & POLLIN) {
- // This pollable has data available for reading
- int status = 0;
- if (!pollable->second->onReadAvailable(fd.fd, &status)) {
- // The onReadAvailable handler signaled an exit
- return status;
- }
- }
- if (fd.revents & POLLHUP) {
- // The fd was closed from the other end
- int status = 0;
- if (!pollable->second->onClose(fd.fd, &status)) {
- // The onClose handler signaled an exit
- return status;
- }
- }
- }
- }
- // Check for timeouts
- Pollable::Timestamp now = Pollable::Clock::now();
- for (const auto& pollable : mPollables) {
- if (pollable->getTimeout() <= now) {
- int status = 0;
- if (!pollable->onTimeout(now, &status)) {
- // The onTimeout handler signaled an exit
- return status;
- }
- }
- }
- }
-
- return 0;
-}
diff --git a/network/wifi_forwarder/remote_connection.cpp b/network/wifi_forwarder/remote_connection.cpp
deleted file mode 100644
index 7255e052..00000000
--- a/network/wifi_forwarder/remote_connection.cpp
+++ /dev/null
@@ -1,335 +0,0 @@
-/*
- * Copyright 2019, 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 "remote_connection.h"
-
-#include "hwsim.h"
-#include "frame.h"
-#include "log.h"
-
-#include <errno.h>
-#include <linux/kernel.h>
-#include <netinet/in.h>
-// Ignore warning about unused static qemu pipe function
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wunused-function"
-#include <qemu_pipe.h>
-#pragma clang diagnostic pop
-#include <sys/uio.h>
-#include <unistd.h>
-
-static const char kQemuPipeName[] = "qemud:wififorward";
-static const size_t kReceiveBufferIncrement = 32768;
-static const size_t kReceiveBufferMaxSize = 1 << 20;
-
-static const uint8_t kWifiForwardVersion = 0x01;
-static const uint32_t kWifiForwardMagic = 0xD6C4B3A2;
-
-// This matches with the kernel constant IEEE80211_TX_MAX_RATES in
-// include/net/mac80211.h in the kernel tree.
-static const uint32_t kMaxNumRates = 4;
-
-struct WifiForwardHeader {
- WifiForwardHeader(FrameType type, const MacAddress& transmitter,
- uint32_t fullLength, uint64_t cookie,
- uint32_t flags, uint32_t channel, uint32_t numRates,
- const hwsim_tx_rate* txRates)
- : magic(__cpu_to_le32(kWifiForwardMagic))
- , version(kWifiForwardVersion)
- , type(static_cast<uint16_t>(type))
- , transmitter(transmitter)
- , dataOffset(sizeof(WifiForwardHeader))
- , fullLength(__cpu_to_le32(fullLength))
- , cookie(__cpu_to_le64(cookie))
- , flags(__cpu_to_le32(flags))
- , channel(__cpu_to_le32(channel))
- , numRates(__cpu_to_le32(numRates)) {
- memcpy(rates, txRates, std::min(numRates, kMaxNumRates));
- if (numRates < kMaxNumRates) {
- memset(&rates[numRates],
- 0,
- sizeof(rates[0]) * (kMaxNumRates - numRates));
- }
- }
-
- uint32_t magic;
- uint8_t version;
- uint8_t type;
- MacAddress transmitter;
- uint16_t dataOffset;
- uint32_t fullLength;
- uint64_t cookie;
- uint32_t flags;
- uint32_t channel;
- uint32_t numRates;
- hwsim_tx_rate rates[kMaxNumRates];
-} __attribute__((__packed__));
-
-RemoteConnection::RemoteConnection(OnFrameCallback onFrameCallback,
- OnAckCallback onAckCallback,
- OnErrorCallback onErrorCallback)
- : mOnFrameCallback(onFrameCallback)
- , mOnAckCallback(onAckCallback)
- , mOnErrorCallback(onErrorCallback) {
-
-}
-
-RemoteConnection::~RemoteConnection() {
- if (mPipeFd != -1) {
- ::close(mPipeFd);
- mPipeFd = -1;
- }
-}
-
-Result RemoteConnection::init() {
- if (mPipeFd != -1) {
- return Result::error("RemoteConnetion already initialized");
- }
-
- mPipeFd = qemu_pipe_open(kQemuPipeName);
- if (mPipeFd == -1) {
- return Result::error("RemoteConnection failed to open pipe");
- }
- return Result::success();
-}
-
-Pollable::Timestamp RemoteConnection::getTimeout() const {
- // If there is no pipe return the deadline, we're going to retry, otherwise
- // use an infinite timeout.
- return mPipeFd == -1 ? mDeadline : Pollable::Timestamp::max();
-}
-
-void RemoteConnection::receive() {
- size_t start = mBuffer.size();
- size_t newSize = start + kReceiveBufferIncrement;
- if (newSize > kReceiveBufferMaxSize) {
- // We've exceeded the maximum allowed size, drop everything we have so
- // far and start over. This is most likely caused by some delay in
- // injection or the injection failing in which case keeping old data
- // around isn't going to be very useful.
- ALOGE("RemoteConnection ran out of buffer space");
- newSize = kReceiveBufferIncrement;
- start = 0;
- }
- mBuffer.resize(newSize);
-
- while (true) {
- int result = ::read(mPipeFd,
- mBuffer.data() + start,
- mBuffer.size() - start);
- if (result < 0) {
- if (errno == EINTR) {
- continue;
- }
- ALOGE("RemoteConnection failed to read to forward buffer: %s",
- strerror(errno));
- // Return the buffer to its previous size
- mBuffer.resize(start);
- return;
- } else if (result == 0) {
- // Nothing received, nothing to write
- // Return the buffer to its previous size
- mBuffer.resize(start);
- ALOGE("RemoteConnection did not receive anything to inject");
- return;
- }
- // Adjust the buffer size to match everything we recieved
- mBuffer.resize(start + static_cast<size_t>(result));
- break;
- }
-
- while (mBuffer.size() >= sizeof(WifiForwardHeader)) {
- auto fwd = reinterpret_cast<WifiForwardHeader*>(mBuffer.data());
- if (__le32_to_cpu(fwd->magic) != kWifiForwardMagic) {
- // We are not properly aligned, this can happen for the first read
- // if the client or server happens to send something that's in the
- // middle of a stream. Attempt to find the next packet boundary.
- ALOGE("RemoteConnection found incorrect magic, finding next magic");
- uint32_t le32magic = __cpu_to_le32(kWifiForwardMagic);
- auto next = reinterpret_cast<unsigned char*>(
- ::memmem(mBuffer.data(), mBuffer.size(),
- &le32magic, sizeof(le32magic)));
- if (next) {
- // We've found a possible candidate, erase everything before
- size_t length = next - mBuffer.data();
- mBuffer.erase(mBuffer.begin(), mBuffer.begin() + length);
- continue;
- } else {
- // There is no possible candidate, drop everything except the
- // last three bytes. The last three bytes could possibly be the
- // start of the next magic without actually triggering the
- // search above.
- if (mBuffer.size() > 3) {
- mBuffer.erase(mBuffer.begin(), mBuffer.end() - 3);
- }
- // In this case there is nothing left to parse so just return
- // right away.
- return;
- }
- }
- // Check if we support this version
- if (fwd->version != kWifiForwardVersion) {
- // Unsupported version
- if (!mReportedVersionMismatches.test(fwd->version)) {
- // Only report these once per version or this might become
- // very spammy.
- ALOGE("RemoteConnection encountered unknown version %u",
- fwd->version);
- mReportedVersionMismatches.set(fwd->version);
- }
- // Drop the magic from the buffer and attempt to find the next magic
- mBuffer.erase(mBuffer.begin(), mBuffer.begin() + 4);
- continue;
- }
- // The length according to the wifi forward header
- const uint32_t fullLength = __le32_to_cpu(fwd->fullLength);
- const uint16_t offset = __le16_to_cpu(fwd->dataOffset);
- if (offset < sizeof(WifiForwardHeader) || offset > fullLength) {
- // The frame offset is not large enough to go past the header
- // or it's outside of the bounds of the length of the frame.
- ALOGE("Invalid data offset in header %u, full length is %u",
- offset, fullLength);
- // Erase the magic and try again
- mBuffer.erase(mBuffer.begin(), mBuffer.begin() + 4);
- continue;
- }
- const size_t frameLength = fullLength - offset;
-
- if (fullLength > mBuffer.size()) {
- // We have not received enough data yet, wait for more to arrive.
- return;
- }
-
- FrameType type = frameTypeFromByte(fwd->type);
- if (frameLength == 0 && type != FrameType::Ack) {
- ALOGE("Received empty frame for non-ack frame");
- return;
- }
- unsigned char* frameData = mBuffer.data() + offset;
- if (type == FrameType::Ack) {
- FrameInfo info(fwd->transmitter,
- __le64_to_cpu(fwd->cookie),
- __le32_to_cpu(fwd->flags),
- __le32_to_cpu(fwd->channel),
- fwd->rates,
- __le32_to_cpu(fwd->numRates));
-
- if (info.flags() & HWSIM_TX_STAT_ACK) {
- mOnAckCallback(info);
- } else {
- mOnErrorCallback(info);
- }
- } else if (type == FrameType::Data) {
- auto frame = std::make_unique<Frame>(frameData,
- frameLength,
- fwd->transmitter,
- __le64_to_cpu(fwd->cookie),
- __le32_to_cpu(fwd->flags),
- __le32_to_cpu(fwd->channel),
- fwd->rates,
- __le32_to_cpu(fwd->numRates));
- mOnFrameCallback(std::move(frame));
- } else {
- ALOGE("Received unknown message type %u from remote",
- static_cast<uint8_t>(fwd->type));
- }
-
- mBuffer.erase(mBuffer.begin(), mBuffer.begin() + fullLength);
- }
-}
-
-bool RemoteConnection::sendFrame(std::unique_ptr<Frame> frame) {
- if (mPipeFd == -1) {
- ALOGE("RemoteConnection unable to forward data, pipe not open");
- return false;
- }
-
- WifiForwardHeader header(FrameType::Data,
- frame->transmitter(),
- frame->size() + sizeof(WifiForwardHeader),
- frame->cookie(),
- frame->flags(),
- frame->channel(),
- frame->rates().size(),
- frame->rates().data());
-#if 1
- constexpr size_t count = 2;
- struct iovec iov[count];
- iov[0].iov_base = &header;
- iov[0].iov_len = sizeof(header);
- iov[1].iov_base = frame->data();
- iov[1].iov_len = frame->size();
-
- size_t totalSize = iov[0].iov_len + iov[1].iov_len;
-
- size_t current = 0;
- for (;;) {
- ssize_t written = ::writev(mPipeFd, iov + current, count - current);
- if (written < 0) {
- ALOGE("RemoteConnection failed to write to pipe: %s",
- strerror(errno));
- return false;
- }
- if (static_cast<size_t>(written) == totalSize) {
- // Optimize for most common case, everything was written
- break;
- }
- totalSize -= written;
- // Determine how much is left to write after this
- while (current < count && written >= iov[current].iov_len) {
- written -= iov[current++].iov_len;
- }
- if (current == count) {
- break;
- }
- iov[current].iov_base =
- reinterpret_cast<char*>(iov[current].iov_base) + written;
- iov[current].iov_len -= written;
- }
-#else
- if (!WriteFully(mPipeFd, &header, sizeof(header))) {
- ALOGE("RemoteConnection failed to write to pipe: %s", strerror(errno));
- return false;
- }
-
- if (!WriteFully(mPipeFd, frame->data(), frame->size())) {
- ALOGE("RemoteConnection failed to write to pipe: %s", strerror(errno));
- return false;
- }
-#endif
- return true;
-}
-
-bool RemoteConnection::ackFrame(FrameInfo& info, bool success) {
- uint32_t flags = info.flags();
- if (success) {
- flags |= HWSIM_TX_STAT_ACK;
- }
- WifiForwardHeader header(FrameType::Ack,
- info.transmitter(),
- sizeof(WifiForwardHeader),
- info.cookie(),
- flags,
- info.channel(),
- info.rates().size(),
- info.rates().data());
-
- if (!WriteFully(mPipeFd, &header, sizeof(header))) {
- ALOGE("RemoteConnection failed to write to pipe: %s", strerror(errno));
- return false;
- }
- return true;
-}
diff --git a/network/wifi_forwarder/remote_connection.h b/network/wifi_forwarder/remote_connection.h
deleted file mode 100644
index 94c7e36d..00000000
--- a/network/wifi_forwarder/remote_connection.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright 2019, 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.
- */
-
-#pragma once
-
-#include "frame.h"
-#include "pollable.h"
-#include "result.h"
-
-#include <bitset>
-#include <functional>
-#include <memory>
-#include <vector>
-
-struct MacAddress;
-
-class RemoteConnection {
-public:
- using OnFrameCallback = std::function<void (std::unique_ptr<Frame>)>;
- using OnAckCallback = std::function<void (FrameInfo&)>;
- using OnErrorCallback = OnAckCallback;
-
- RemoteConnection(OnFrameCallback onFrameCallback,
- OnAckCallback onAckCallback,
- OnErrorCallback onErrorCallback);
- ~RemoteConnection();
-
- Result init();
-
- int getFd() const { return mPipeFd; }
- Pollable::Timestamp getTimeout() const;
- void receive();
- bool sendFrame(std::unique_ptr<Frame> frame);
- bool ackFrame(FrameInfo& info, bool success);
-
-private:
- RemoteConnection(const RemoteConnection&) = delete;
- RemoteConnection& operator=(const RemoteConnection&) = delete;
-
- OnFrameCallback mOnFrameCallback;
- OnAckCallback mOnAckCallback;
- OnErrorCallback mOnErrorCallback;
-
- Pollable::Timestamp mDeadline = Pollable::Timestamp::max();
- std::vector<unsigned char> mBuffer;
- int mPipeFd = -1;
- std::bitset<256> mReportedVersionMismatches;
-};
-
diff --git a/network/wifi_forwarder/wifi_forwarder.cpp b/network/wifi_forwarder/wifi_forwarder.cpp
deleted file mode 100644
index b56c7cdb..00000000
--- a/network/wifi_forwarder/wifi_forwarder.cpp
+++ /dev/null
@@ -1,258 +0,0 @@
-/*
- * Copyright 2019, 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 "wifi_forwarder.h"
-
-#include "frame.h"
-#include "log.h"
-
-static constexpr bool kDebugTraffic = false;
-static constexpr bool kDebugBeaconTraffic = false;
-
-// How many seconds to keep aliases alive for. Since this is used to keep track
-// of randomized MAC addresses they will expire after a while. Set the value
-// pretty high to ensure that we don't accidentally lose entries just because
-// there's not a lot of frames going through.
-static constexpr auto kAliasesCacheTimeout = std::chrono::hours(8);
-
-WifiForwarder::WifiForwarder()
- : mAliases(kAliasesCacheTimeout)
- , mLocalConnection([this](std::unique_ptr<Frame> frame) {
- forwardFrame(std::move(frame), RadioType::Local);
- },
- [this](FrameInfo& info) { onAck(info, true); },
- [this](FrameInfo& info) { onAck(info, false); })
- , mRemoteConnection([this](std::unique_ptr<Frame> frame) {
- forwardFrame(std::move(frame), RadioType::Remote);
- },
- [this](FrameInfo& info) { onAck(info, true); },
- [this](FrameInfo& info) { onAck(info, false); }) {
-}
-
-Result WifiForwarder::init() {
- auto now = Pollable::Clock::now();
- Result res = mRemoteConnection.init();
- if (!res) {
- // It's OK if this fails, the emulator might not have been started with
- // this feature enabled. If it's not enabled we'll try again later. If
- // this does not succeed we don't need to perform the rest of the
- // initialization either. Just let WiFi work the same as normal.
- ALOGE("RemoteConnection failed to initialize: %s", res.c_str());
- mInitDeadline = now + std::chrono::minutes(1);
- return Result::success();
- }
-
- mAliases.setCurrentTime(now);
- res = mLocalConnection.init(now);
- if (!res) {
- return res;
- }
- mDeadline = now + std::chrono::seconds(1);
- return Result::success();
-}
-
-void WifiForwarder::getPollData(std::vector<pollfd>* fds) const {
- int fd = mLocalConnection.getFd();
- if (fd >= 0) {
- struct pollfd pfd = { fd, POLLIN, 0 };
- fds->push_back(pfd);
- }
- fd = mRemoteConnection.getFd();
- if (fd >= 0) {
- struct pollfd pfd = { fd, POLLIN, 0 };
- fds->push_back(pfd);
- }
-}
-
-Pollable::Timestamp WifiForwarder::getTimeout() const {
- if (mRemoteConnection.getFd() == -1) {
- return mInitDeadline;
- }
- return std::min(mLocalConnection.getTimeout(), mDeadline);
-}
-
-bool WifiForwarder::onReadAvailable(int fd, int* /*status*/) {
- if (fd == mRemoteConnection.getFd()) {
- mRemoteConnection.receive();
- } else if (fd == mLocalConnection.getFd()) {
- mLocalConnection.receive();
- }
- return true;
-}
-
-bool WifiForwarder::onClose(int /*fd*/, int* /*status*/) {
- ALOGE("WifiForwarder socket closed unexpectedly");
- return false;
-}
-
-bool WifiForwarder::onTimeout(Timestamp now, int* /*status*/) {
- bool success = true;
- if (now >= mInitDeadline) {
- Result res = init();
- success = res.isSuccess();
- if (mRemoteConnection.getFd() == -1) {
- // Remote connection not set up by init, try again later
- mInitDeadline = now + std::chrono::minutes(1);
- }
- }
- mLocalConnection.onTimeout(now);
- if (now >= mDeadline) {
- mDeadline += std::chrono::seconds(1);
- mAliases.setCurrentTime(now);
- mAliases.expireEntries();
- }
- return success;
-}
-
-const char* WifiForwarder::radioTypeToStr(RadioType type) const {
- switch (type) {
- case RadioType::Unknown:
- return "Unknown";
- case RadioType::Local:
- return "Local";
- case RadioType::Remote:
- return "Remote";
- }
-}
-
-void WifiForwarder::onAck(FrameInfo& info, bool success) {
- RadioType type = mRadios[info.transmitter()];
- if (type == RadioType::Remote) {
- if (kDebugTraffic) {
- ALOGE("] ACK -] " PRIMAC " [ %" PRIu64 " ] success: %s",
- MACARG(info.transmitter()), info.cookie(),
- success ? "true" : "false");
- }
- if (!mRemoteConnection.ackFrame(info, success)) {
- ALOGE("WifiForwarder failed to ack remote frame");
- }
- } else if (type == RadioType::Local) {
- if (kDebugTraffic) {
- ALOGE("> ACK -> " PRIMAC " [ %" PRIu64 " ] success: %s",
- MACARG(info.transmitter()), info.cookie(),
- success ? "true" : "false");
- }
- if (!mLocalConnection.ackFrame(info, success)) {
- ALOGE("WifiForwarder failed to ack local frame");
- }
- } else {
- ALOGE("Unknown transmitter in ack: " PRIMAC,
- MACARG(info.transmitter()));
- }
-}
-
-void WifiForwarder::forwardFrame(std::unique_ptr<Frame> frame,
- RadioType sourceType) {
- if (kDebugTraffic) {
- if (!frame->isBeacon() || kDebugBeaconTraffic) {
- bool isRemote = sourceType == RadioType::Remote;
- ALOGE("%c " PRIMAC " -%c " PRIMAC " %s",
- isRemote ? '[' : '<', isRemote ? ']' : '>',
- MACARG(frame->source()),
- MACARG(frame->destination()),
- frame->str().c_str());
- }
- }
-
- const MacAddress& source = frame->source();
- const MacAddress& transmitter = frame->transmitter();
- const MacAddress& destination = frame->destination();
- auto& currentType = mRadios[transmitter];
- if (currentType != RadioType::Unknown && currentType != sourceType) {
- ALOGE("Replacing type for MAC " PRIMAC " of type %s with type %s, "
- "this might indicate duplicate MACs on different emulators",
- MACARG(source), radioTypeToStr(currentType),
- radioTypeToStr(sourceType));
- }
- currentType = sourceType;
- mAliases[source] = transmitter;
-
- bool isMulticast = destination.isMulticast();
- bool sendOnRemote = isMulticast;
- for (const auto& radio : mRadios) {
- const MacAddress& radioAddress = radio.first;
- RadioType radioType = radio.second;
- if (radioAddress == transmitter) {
- // Don't send back to the transmitter
- continue;
- }
- if (sourceType == RadioType::Remote && radioType == RadioType::Remote) {
- // Don't forward frames back to the remote, the remote will have
- // taken care of this.
- continue;
- }
- bool forward = false;
- if (isMulticast || destination == radioAddress) {
- // The frame is either multicast or directly intended for this
- // radio. Forward it.
- forward = true;
- } else {
- auto alias = mAliases.find(destination);
- if (alias != mAliases.end() && alias->second == radioAddress) {
- // The frame is destined for an address that is a known alias
- // for this radio.
- forward = true;
- }
- }
- uint32_t seq = 0;
- if (forward) {
- switch (radioType) {
- case RadioType::Unknown:
- ALOGE("Attempted to forward frame to unknown radio type");
- break;
- case RadioType::Local:
- if (kDebugTraffic) {
- if (!frame->isBeacon() || kDebugBeaconTraffic) {
- ALOGE("> " PRIMAC " -> " PRIMAC " %s",
- MACARG(frame->source()),
- MACARG(frame->destination()),
- frame->str().c_str());
- }
- }
- if (isMulticast) {
- // Clone the frame, it might be reused
- seq = mLocalConnection.cloneFrame(*frame, radioAddress);
- } else {
- // This frame has a specific destination, move it
- seq = mLocalConnection.transferFrame(std::move(frame),
- radioAddress);
- // Return so that we don't accidentally reuse the frame.
- // This should be safe now because it's a unicast frame
- // so it should not be sent to multiple radios.
- return;
- }
- break;
- case RadioType::Remote:
- sendOnRemote = true;
- break;
- }
- }
- }
- if (sendOnRemote && sourceType != RadioType::Remote) {
- if (kDebugTraffic) {
- if (!frame->isBeacon() || kDebugBeaconTraffic) {
- ALOGE("] " PRIMAC " -] " PRIMAC " %s",
- MACARG(frame->source()),
- MACARG(frame->destination()),
- frame->str().c_str());
- }
- }
- // This is either a multicast message or destined for a radio known to
- // be a remote. No need to send multiple times to a remote, the remote
- // will handle that on its own.
- mRemoteConnection.sendFrame(std::move(frame));
- }
-}
diff --git a/network/wifi_forwarder/wifi_forwarder.h b/network/wifi_forwarder/wifi_forwarder.h
deleted file mode 100644
index dfe57d88..00000000
--- a/network/wifi_forwarder/wifi_forwarder.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright 2019, 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.
- */
-
-#pragma once
-
-#include "cache.h"
-#include "frame.h"
-#include "local_connection.h"
-#include "macaddress.h"
-#include "pollable.h"
-#include "remote_connection.h"
-#include "result.h"
-
-#include <unordered_map>
-
-class WifiForwarder : public Pollable {
-public:
- WifiForwarder();
- virtual ~WifiForwarder() = default;
- Result init();
-
- // Pollable interface
- void getPollData(std::vector<pollfd>* fds) const override;
- Timestamp getTimeout() const override;
- bool onReadAvailable(int fd, int* status) override;
- bool onClose(int fd, int* status) override;
- bool onTimeout(Timestamp now, int* status) override;
-private:
- enum class RadioType {
- Unknown,
- Local,
- Remote
- };
-
- const char* radioTypeToStr(RadioType type) const;
-
- void onAck(FrameInfo& info, bool success);
-
- void forwardFrame(std::unique_ptr<Frame> frame, RadioType sourceType);
-
- std::unordered_map<MacAddress, RadioType> mRadios;
- Cache<MacAddress, MacAddress> mAliases;
- LocalConnection mLocalConnection;
- RemoteConnection mRemoteConnection;
- Pollable::Timestamp mInitDeadline = Pollable::Timestamp::max();
- Pollable::Timestamp mDeadline = Pollable::Timestamp::max();
-};
-
diff --git a/power/Android.mk b/power/Android.mk
index 27f325c5..3466c540 100644
--- a/power/Android.mk
+++ b/power/Android.mk
@@ -29,6 +29,7 @@ LOCAL_SHARED_LIBRARIES := \
libbase \
libcutils \
libhidlbase \
+ libhidltransport \
liblog \
libutils \
android.hardware.power@1.1 \
diff --git a/ril/Android.mk b/ril/Android.mk
index a5423cef..cb5f31a9 100644
--- a/ril/Android.mk
+++ b/ril/Android.mk
@@ -9,7 +9,6 @@ LOCAL_SRC_FILES:= \
reference-ril.c \
atchannel.c \
if_monitor.cpp \
- ipv6_monitor.cpp \
misc.c \
at_tok.c
diff --git a/ril/if_monitor.cpp b/ril/if_monitor.cpp
index 87681f57..289477d2 100644
--- a/ril/if_monitor.cpp
+++ b/ril/if_monitor.cpp
@@ -16,9 +16,7 @@
#include "if_monitor.h"
-#include <arpa/inet.h>
#include <errno.h>
-#include <ifaddrs.h>
#include <linux/rtnetlink.h>
#include <net/if.h>
#include <poll.h>
@@ -32,7 +30,6 @@
#include <mutex>
#include <thread>
#include <unordered_map>
-#include <unordered_set>
#include <vector>
#define LOG_TAG "RIL-IFMON"
@@ -59,18 +56,6 @@ static size_t addrLength(int addrFamily) {
}
}
-static const void* getSockAddrData(const struct sockaddr* addr) {
- switch (addr->sa_family) {
- case AF_INET:
- return &reinterpret_cast<const struct sockaddr_in*>(addr)->sin_addr;
- case AF_INET6:
- return
- &reinterpret_cast<const struct sockaddr_in6*>(addr)->sin6_addr;
- default:
- return nullptr;
- }
-}
-
bool operator==(const struct ifAddress& left, const struct ifAddress& right) {
// The prefix length does not factor in to whether two addresses are the
// same or not. Only the family and the address data. This matches the
@@ -148,75 +133,32 @@ public:
mThread = std::make_unique<std::thread>([this]() { run(); });
}
- void requestAddresses() {
- struct ifaddrs* addresses = nullptr;
-
- if (getifaddrs(&addresses) != 0) {
- RLOGE("Unable to retrieve list of interfaces, cannot get initial "
- "interface addresses: %s", strerror(errno));
- return;
- }
-
- for (struct ifaddrs* cur = addresses; cur; cur = cur->ifa_next) {
- if (cur->ifa_name == nullptr ||
- cur->ifa_addr == nullptr ||
- cur->ifa_netmask == nullptr) {
- // Interface doesn't have all the information we need. Rely on
- // the netlink notification to catch this interface later if it
- // is configured correctly.
- continue;
- }
- if (cur->ifa_flags & IFF_LOOPBACK) {
- // Not interested in loopback devices, they will never be radio
- // interfaces.
- continue;
- }
- unsigned int ifIndex = if_nametoindex(cur->ifa_name);
- if (ifIndex == 0) {
- RLOGE("Encountered interface %s with no index: %s",
- cur->ifa_name, strerror(errno));
- continue;
- }
- ifAddress addr;
- addr.family = cur->ifa_addr->sa_family;
- addr.prefix = getPrefix(cur->ifa_netmask);
- memcpy(addr.addr,
- getSockAddrData(cur->ifa_addr),
- addrLength(cur->ifa_addr->sa_family));
- mAddresses[ifIndex].push_back(addr);
- }
- freeifaddrs(addresses);
-
- if (mOnAddressChangeCallback) {
- for (const auto& ifAddr : mAddresses) {
- mOnAddressChangeCallback(ifAddr.first,
- ifAddr.second.data(),
- ifAddr.second.size());
+ void requestAddress() {
+ struct {
+ struct nlmsghdr hdr;
+ struct ifaddrmsg msg;
+ char padding[16];
+ } request;
+
+ memset(&request, 0, sizeof(request));
+ request.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(request.msg));
+ request.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ROOT;
+ request.hdr.nlmsg_type = RTM_GETADDR;
+
+ int status = ::send(mSocketFd, &request, request.hdr.nlmsg_len, 0);
+ if (status < 0 ||
+ static_cast<unsigned int>(status) != request.hdr.nlmsg_len) {
+ if (status < 0) {
+ RLOGE("Failed to send netlink request: %s", strerror(errno));
+ } else {
+ RLOGE("Short send only sent %d out of %d bytes",
+ status, (int)request.hdr.nlmsg_len);
}
}
}
- int getPrefix(const struct sockaddr* addr) {
- // This uses popcnt, a built-in instruction on some CPUs, to count
- // the number of bits in a 32-bit word. The number of bits in a netmask
- // equals the width of the prefix. For example a netmask of
- // 255.255.255.0 has 24 bits set and that's also its width.
- if (addr->sa_family == AF_INET) {
- auto v4 = reinterpret_cast<const struct sockaddr_in*>(addr);
- return __builtin_popcount(v4->sin_addr.s_addr);
- } else if (addr->sa_family == AF_INET6) {
- auto v6 = reinterpret_cast<const struct sockaddr_in6*>(addr);
- // Copy to our own array to avoid aliasing
- uint64_t words[2];
- memcpy(words, v6->sin6_addr.s6_addr, sizeof(words));
- return __builtin_popcountll(words[0]) +
- __builtin_popcountll(words[1]);
- }
- return 0;
- }
-
void run() {
- requestAddresses();
+ requestAddress();
std::vector<struct pollfd> fds(2);
fds[0].events = POLLIN;
@@ -309,16 +251,11 @@ private:
RLOGE("Received message type %d", (int)hdr->nlmsg_type);
break;
}
- hdr = NLMSG_NEXT(hdr, length);
+ NLMSG_NEXT(hdr, length);
}
}
}
- std::string getInterfaceName(unsigned int ifIndex) {
- char buffer[IF_NAMESIZE] = { '\0' };
- return if_indextoname(ifIndex, buffer);
- }
-
void handleAddressChange(const struct nlmsghdr* hdr) {
if (!mOnAddressChangeCallback) {
return;
diff --git a/ril/ipv6_monitor.cpp b/ril/ipv6_monitor.cpp
deleted file mode 100644
index 8d577bc4..00000000
--- a/ril/ipv6_monitor.cpp
+++ /dev/null
@@ -1,496 +0,0 @@
-/*
- * Copyright 2019, 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 "ipv6_monitor.h"
-
-#include <errno.h>
-#include <linux/filter.h>
-#include <net/if.h>
-#include <netinet/ether.h>
-#include <netinet/icmp6.h>
-#include <netinet/ip6.h>
-#include <poll.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <array>
-#include <mutex>
-#include <string>
-#include <thread>
-#include <unordered_set>
-#include <vector>
-
-#define LOG_TAG "RIL-IPV6MON"
-#include <utils/Log.h>
-
-static constexpr size_t kReadBufferSize = 32768;
-
-static constexpr size_t kRecursiveDnsOptHeaderSize = 8;
-
-static constexpr size_t kControlClient = 0;
-static constexpr size_t kControlServer = 1;
-
-static constexpr char kMonitorAckCommand = '\1';
-static constexpr char kMonitorStopCommand = '\2';
-
-// The amount of time to wait before trying to initialize interface again if
-// it's not ready when rild starts.
-static constexpr int kDeferredTimeoutMilliseconds = 1000;
-
-bool operator==(const in6_addr& left, const in6_addr& right) {
- return ::memcmp(left.s6_addr, right.s6_addr, sizeof(left.s6_addr)) == 0;
-}
-
-bool operator!=(const in6_addr& left, const in6_addr& right) {
- return ::memcmp(left.s6_addr, right.s6_addr, sizeof(left.s6_addr)) != 0;
-}
-
-template<class T>
-static inline void hash_combine(size_t& seed, const T& value) {
- std::hash<T> hasher;
- seed ^= hasher(value) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
-}
-
-namespace std {
-template<> struct hash<in6_addr> {
- size_t operator()(const in6_addr& ad) const {
- size_t seed = 0;
- hash_combine(seed, *reinterpret_cast<const uint32_t*>(&ad.s6_addr[0]));
- hash_combine(seed, *reinterpret_cast<const uint32_t*>(&ad.s6_addr[4]));
- hash_combine(seed, *reinterpret_cast<const uint32_t*>(&ad.s6_addr[8]));
- hash_combine(seed, *reinterpret_cast<const uint32_t*>(&ad.s6_addr[12]));
- return seed;
- }
-};
-} // namespace std
-
-static constexpr uint32_t kIpTypeOffset = offsetof(ip6_hdr, ip6_nxt);
-static constexpr uint32_t kIcmpTypeOffset = sizeof(ip6_hdr) +
- offsetof(icmp6_hdr, icmp6_type);
-
-// This is BPF program that will filter out anything that is not an NDP router
-// advertisement. It's a very basic assembler syntax. The jumps indicate how
-// many instructions to jump in addition to the automatic increment of the
-// program counter. So a jump statement with a zero means to go to the next
-// instruction, a value of 3 means that the next instruction will be the 4th
-// after the current one.
-static const struct sock_filter kNdpFilter[] = {
- // Load byte at absolute address kIpTypeOffset
- BPF_STMT(BPF_LD | BPF_B | BPF_ABS, kIpTypeOffset),
- // Jump, if byte is IPPROTO_ICMPV6 jump 0 instructions, if not jump 3.
- BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, IPPROTO_ICMPV6, 0, 3),
- // Load byte at absolute address kIcmpTypeOffset
- BPF_STMT(BPF_LD | BPF_B | BPF_ABS, kIcmpTypeOffset),
- // Jump, if byte is ND_ROUTER_ADVERT jump 0 instructions, if not jump 1
- BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, ND_ROUTER_ADVERT, 0, 1),
- // Return the number of bytes to accept, accept all of them
- BPF_STMT(BPF_RET | BPF_K, std::numeric_limits<uint32_t>::max()),
- // Accept zero bytes, this is where the failed jumps go
- BPF_STMT(BPF_RET | BPF_K, 0)
-};
-static constexpr size_t kNdpFilterSize =
- sizeof(kNdpFilter) / sizeof(kNdpFilter[0]);
-
-class Ipv6Monitor {
-public:
- Ipv6Monitor(const char* interfaceName);
- ~Ipv6Monitor();
-
- enum class InitResult {
- Error,
- Deferred,
- Success,
- };
- InitResult init();
- void setCallback(ipv6MonitorCallback callback);
- void runAsync();
- void stop();
-
-private:
- InitResult initInterfaces();
- void run();
- void onReadAvailable();
-
- ipv6MonitorCallback mMonitorCallback;
-
- in6_addr mGateway;
- std::unordered_set<in6_addr> mDnsServers;
-
- std::unique_ptr<std::thread> mThread;
- std::mutex mThreadMutex;
-
- std::string mInterfaceName;
- int mSocketFd;
- int mControlSocket[2];
- int mPollTimeout = -1;
- bool mFullyInitialized = false;
-};
-
-Ipv6Monitor::Ipv6Monitor(const char* interfaceName) :
- mMonitorCallback(nullptr),
- mInterfaceName(interfaceName),
- mSocketFd(-1) {
- memset(&mGateway, 0, sizeof(mGateway));
- mControlSocket[0] = -1;
- mControlSocket[1] = -1;
-}
-
-Ipv6Monitor::~Ipv6Monitor() {
- for (int& fd : mControlSocket) {
- if (fd != -1) {
- ::close(fd);
- fd = -1;
- }
- }
- if (mSocketFd != -1) {
- ::close(mSocketFd);
- mSocketFd = -1;
- }
-}
-
-Ipv6Monitor::InitResult Ipv6Monitor::init() {
- if (mSocketFd != -1) {
- RLOGE("Ipv6Monitor already initialized");
- return InitResult::Error;
- }
-
- if (::socketpair(AF_UNIX, SOCK_DGRAM, 0, mControlSocket) != 0) {
- RLOGE("Ipv6Monitor failed to create control socket pair: %s",
- strerror(errno));
- return InitResult::Error;
- }
-
- mSocketFd = ::socket(AF_PACKET, SOCK_DGRAM | SOCK_CLOEXEC, ETH_P_IPV6);
- if (mSocketFd == -1) {
- RLOGE("Ipv6Monitor failed to open socket: %s", strerror(errno));
- return InitResult::Error;
- }
- // If interface initialization fails we'll retry later
- return initInterfaces();
-}
-
-void Ipv6Monitor::setCallback(ipv6MonitorCallback callback) {
- mMonitorCallback = callback;
-}
-
-Ipv6Monitor::InitResult Ipv6Monitor::initInterfaces() {
- if (mFullyInitialized) {
- RLOGE("Ipv6Monitor already initialized");
- return InitResult::Error;
- }
- struct ifreq request;
- memset(&request, 0, sizeof(request));
- strlcpy(request.ifr_name, mInterfaceName.c_str(), sizeof(request.ifr_name));
-
- // Set the ALLMULTI flag so we can capture multicast traffic
- int status = ::ioctl(mSocketFd, SIOCGIFFLAGS, &request);
- if (status != 0) {
- if (errno == ENODEV) {
- // It is not guaranteed that the network is entirely set up by the
- // time rild has started. If that's the case the radio interface
- // might not be up yet, try again later.
- RLOGE("Ipv6Monitor could not initialize %s yet, retrying later",
- mInterfaceName.c_str());
- mPollTimeout = kDeferredTimeoutMilliseconds;
- return InitResult::Deferred;
- }
- RLOGE("Ipv6Monitor failed to get interface flags for %s: %s",
- mInterfaceName.c_str(), strerror(errno));
- return InitResult::Error;
- }
-
- if ((request.ifr_flags & IFF_ALLMULTI) == 0) {
- // The flag is not set, we have to make another call
- request.ifr_flags |= IFF_ALLMULTI;
-
- status = ::ioctl(mSocketFd, SIOCSIFFLAGS, &request);
- if (status != 0) {
- RLOGE("Ipv6Monitor failed to set interface flags for %s: %s",
- mInterfaceName.c_str(), strerror(errno));
- return InitResult::Error;
- }
- }
-
- // Add a BPF filter to the socket so that we only receive the specific
- // type of packet we're interested in. Otherwise we will receive ALL
- // traffic on this interface.
- struct sock_fprog filter;
- filter.len = kNdpFilterSize;
- // The API doesn't have const but it's not going to modify it so this is OK
- filter.filter = const_cast<struct sock_filter*>(kNdpFilter);
- status = ::setsockopt(mSocketFd,
- SOL_SOCKET,
- SO_ATTACH_FILTER,
- &filter,
- sizeof(filter));
- if (status != 0) {
- RLOGE("Ipv6Monitor failed to set socket filter: %s", strerror(errno));
- return InitResult::Error;
- }
-
- // Get the hardware address of the interface into a sockaddr struct for bind
- struct sockaddr_ll ethAddr;
- memset(&ethAddr, 0, sizeof(ethAddr));
- ethAddr.sll_family = AF_PACKET;
- ethAddr.sll_protocol = htons(ETH_P_IPV6);
- ethAddr.sll_ifindex = if_nametoindex(mInterfaceName.c_str());
- if (ethAddr.sll_ifindex == 0) {
- RLOGE("Ipv6Monitor failed to find index for %s: %s",
- mInterfaceName.c_str(), strerror(errno));
- return InitResult::Error;
- }
-
- status = ::ioctl(mSocketFd, SIOCGIFHWADDR, &request);
- if (status != 0) {
- RLOGE("Ipv6Monitor failed to get hardware address for %s: %s",
- mInterfaceName.c_str(), strerror(errno));
- return InitResult::Error;
- }
- memcpy(ethAddr.sll_addr, request.ifr_addr.sa_data, ETH_ALEN);
-
- // Now bind to the hardware address
- status = ::bind(mSocketFd,
- reinterpret_cast<const struct sockaddr*>(&ethAddr),
- sizeof(ethAddr));
- if (status != 0) {
- RLOGE("Ipv6Monitor failed to bind to %s hardware address: %s",
- mInterfaceName.c_str(), strerror(errno));
- return InitResult::Error;
- }
- mFullyInitialized = true;
- return InitResult::Success;
-}
-
-void Ipv6Monitor::runAsync() {
- std::unique_lock<std::mutex> lock(mThreadMutex);
- mThread = std::make_unique<std::thread>([this]() { run(); });
-}
-
-void Ipv6Monitor::stop() {
- std::unique_lock<std::mutex> lock(mThreadMutex);
- if (!mThread) {
- return;
- }
- ::write(mControlSocket[kControlClient], &kMonitorStopCommand, 1);
- char ack = -1;
- while (ack != kMonitorAckCommand) {
- ::read(mControlSocket[kControlClient], &ack, sizeof(ack));
- }
- mThread->join();
- mThread.reset();
-}
-
-void Ipv6Monitor::run() {
- std::array<struct pollfd, 2> fds;
- fds[0].events = POLLIN;
- fds[0].fd = mControlSocket[kControlServer];
- fds[1].events = POLLIN;
- fds[1].fd = mSocketFd;
-
- bool running = true;
- while (running) {
- int status = ::poll(fds.data(), fds.size(), mPollTimeout);
- if (status < 0) {
- if (errno == EINTR) {
- // Interrupted, keep going
- continue;
- }
- // An error occurred
- RLOGE("Ipv6Monitor fatal failure polling failed; %s",
- strerror(errno));
- break;
- } else if (status == 0) {
- // Timeout, nothing to read
- if (!mFullyInitialized) {
- InitResult result = initInterfaces();
- switch (result) {
- case InitResult::Error:
- // Something went wrong this time and we can't recover
- running = false;
- break;
- case InitResult::Deferred:
- // We need to keep waiting and then try again
- mPollTimeout = kDeferredTimeoutMilliseconds;
- break;
- case InitResult::Success:
- // Interfaces are initialized, no need to timeout again
- mPollTimeout = -1;
- break;
- }
- }
- continue;
- }
-
- if (fds[0].revents & POLLIN) {
- // Control message received
- char command = -1;
- if (::read(mControlSocket[kControlServer],
- &command,
- sizeof(command)) == 1) {
- if (command == kMonitorStopCommand) {
- break;
- }
- }
- } else if (fds[1].revents & POLLIN) {
- onReadAvailable();
- }
- }
- ::write(mControlSocket[kControlServer], &kMonitorAckCommand, 1);
-}
-
-void Ipv6Monitor::onReadAvailable() {
- char buffer[kReadBufferSize];
-
- ssize_t bytesRead = 0;
- while (true) {
- bytesRead = ::recv(mSocketFd, buffer, sizeof(buffer), 0);
- if (bytesRead < 0) {
- if (errno == EINTR) {
- // Interrupted, try again right away
- continue;
- }
- if (errno != EAGAIN && errno != EWOULDBLOCK) {
- // Do not report an error for the above error codes, they are
- // part of the normal turn of events. We just need to try again
- // later when we run into those errors.
- RLOGE("Ipv6Monitor failed to receive data: %s",
- strerror(errno));
- }
- return;
- }
- break;
- }
-
- if (mMonitorCallback == nullptr) {
- // No point in doing anything, we have read the data so the socket
- // buffer doesn't fill up and that's all we can do.
- return;
- }
-
- if (static_cast<size_t>(bytesRead) < sizeof(ip6_hdr) + sizeof(icmp6_hdr)) {
- // This message cannot be an ICMPv6 packet, ignore it
- return;
- }
-
- auto ipv6 = reinterpret_cast<const ip6_hdr*>(buffer);
- uint8_t version = (ipv6->ip6_vfc & 0xF0) >> 4;
- if (version != 6 || ipv6->ip6_nxt != IPPROTO_ICMPV6) {
- // This message is not an IPv6 packet or not an ICMPv6 packet, ignore it
- return;
- }
-
- // The ICMP header starts right after the IPv6 header
- auto icmp = reinterpret_cast<const icmp6_hdr*>(buffer + sizeof(ip6_hdr));
- if (icmp->icmp6_code != 0) {
- // All packets we care about have an icmp code of zero.
- return;
- }
-
- if (icmp->icmp6_type != ND_ROUTER_ADVERT) {
- // We only care about router advertisements
- return;
- }
-
- // At this point we know it's a valid packet, let's look inside
-
- // The gateway is the same as the source in the IP header
- in6_addr gateway = ipv6->ip6_src;
-
- // Search through the options for DNS servers
- const char* options = buffer + sizeof(ip6_hdr) + sizeof(nd_router_advert);
- const nd_opt_hdr* option = reinterpret_cast<const nd_opt_hdr*>(options);
-
- std::vector<in6_addr> dnsServers;
- const nd_opt_hdr* nextOpt = nullptr;
- for (const nd_opt_hdr* opt = option; opt; opt = nextOpt) {
- auto nextOptLoc =
- reinterpret_cast<const char*>(opt) + opt->nd_opt_len * 8u;
- if (nextOptLoc > buffer + bytesRead) {
- // Not enough room for this option, abort
- break;
- }
- if (nextOptLoc < buffer + bytesRead) {
- nextOpt = reinterpret_cast<const nd_opt_hdr*>(nextOptLoc);
- } else {
- nextOpt = nullptr;
- }
- if (opt->nd_opt_type != 25 || opt->nd_opt_len < 1) {
- // Not an RNDSS option, skip it
- continue;
- }
-
- size_t numEntries = (opt->nd_opt_len - 1) / 2;
- const char* addrLoc = reinterpret_cast<const char*>(opt);
- addrLoc += kRecursiveDnsOptHeaderSize;
- auto addrs = reinterpret_cast<const in6_addr*>(addrLoc);
-
- for (size_t i = 0; i < numEntries; ++i) {
- dnsServers.push_back(addrs[i]);
- }
- }
-
- bool changed = false;
- if (gateway != mGateway) {
- changed = true;
- mGateway = gateway;
- }
-
- for (const auto& dns : dnsServers) {
- if (mDnsServers.find(dns) == mDnsServers.end()) {
- mDnsServers.insert(dns);
- changed = true;
- }
- }
-
- if (changed) {
- mMonitorCallback(&gateway, dnsServers.data(), dnsServers.size());
- }
-}
-
-extern "C"
-struct ipv6Monitor* ipv6MonitorCreate(const char* interfaceName) {
- auto monitor = std::make_unique<Ipv6Monitor>(interfaceName);
- if (!monitor || monitor->init() == Ipv6Monitor::InitResult::Error) {
- return nullptr;
- }
- return reinterpret_cast<struct ipv6Monitor*>(monitor.release());
-}
-
-extern "C"
-void ipv6MonitorFree(struct ipv6Monitor* ipv6Monitor) {
- auto monitor = reinterpret_cast<Ipv6Monitor*>(ipv6Monitor);
- delete monitor;
-}
-
-extern "C"
-void ipv6MonitorSetCallback(struct ipv6Monitor* ipv6Monitor,
- ipv6MonitorCallback callback) {
- auto monitor = reinterpret_cast<Ipv6Monitor*>(ipv6Monitor);
- monitor->setCallback(callback);
-}
-
-extern "C"
-void ipv6MonitorRunAsync(struct ipv6Monitor* ipv6Monitor) {
- auto monitor = reinterpret_cast<Ipv6Monitor*>(ipv6Monitor);
- monitor->runAsync();
-}
-
-extern "C"
-void ipv6MonitorStop(struct ipv6Monitor* ipv6Monitor) {
- auto monitor = reinterpret_cast<Ipv6Monitor*>(ipv6Monitor);
- monitor->stop();
-}
-
diff --git a/ril/ipv6_monitor.h b/ril/ipv6_monitor.h
deleted file mode 100644
index b58402dd..00000000
--- a/ril/ipv6_monitor.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright 2019, 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.
- */
-
-#pragma once
-
-#include <netinet/in.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct ipv6Monitor;
-
-// A callback for when the IPv6 configuration changes.
-typedef void (*ipv6MonitorCallback)(const struct in6_addr* /*gateway*/,
- const struct in6_addr* /*dns servers*/,
- size_t /*number of dns servers */);
-
-// Create an IPv6 monitor that will monitor |interfaceName| for IPv6 router
-// advertisements. The monitor will trigger a callback if the gateway and/or
-// DNS servers provided by router advertisements change at any point.
-struct ipv6Monitor* ipv6MonitorCreate(const char* interfaceName);
-void ipv6MonitorFree(struct ipv6Monitor* monitor);
-
-void ipv6MonitorSetCallback(struct ipv6Monitor* monitor,
- ipv6MonitorCallback callback);
-void ipv6MonitorRunAsync(struct ipv6Monitor* monitor);
-void ipv6MonitorStop(struct ipv6Monitor* monitor);
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-
diff --git a/ril/reference-ril.c b/ril/reference-ril.c
index 85662312..48ad12cb 100644
--- a/ril/reference-ril.c
+++ b/ril/reference-ril.c
@@ -45,17 +45,11 @@
#include <netinet/in.h>
#include "if_monitor.h"
-#include "ipv6_monitor.h"
#include "ril.h"
#define LOG_TAG "RIL"
#include <utils/Log.h>
-#define MAX(x, y) ({\
- __typeof__(x) _x = (x); \
- __typeof__(y) _y = (y); \
- _x > _y ? _x : _y; })
-
static void *noopRemoveWarning( void *a ) { return a; }
#define RIL_UNUSED_PARM(a) noopRemoveWarning((void *)&(a));
@@ -279,13 +273,9 @@ static int s_mnc = 0;
static int s_lac = 0;
static int s_cid = 0;
-// A string containing all IP addresses of the radio interface
-static char s_if_addresses[8192];
-// A string containing the IPv6 gateway of the radio interface
-static char s_ipv6_gateway[INET6_ADDRSTRLEN];
-// A string containing the IPv6 DNS servers of the radio interface
-static char s_ipv6_dns[8192];
-static pthread_mutex_t s_addresses_mutex = PTHREAD_MUTEX_INITIALIZER;
+// A string containing all the IPv6 addresses of the radio interface
+static char s_ipv6_addresses[8192];
+static pthread_mutex_t s_ipv6_addresses_mutex = PTHREAD_MUTEX_INITIALIZER;
static void pollSIMState (void *param);
static void setRadioState(RIL_RadioState newState);
@@ -628,8 +618,6 @@ static void requestOrSendDataCallList(RIL_Token *t)
char propValue[PROP_VALUE_MAX];
bool hasWifi = hasWifiCapability();
const char* radioInterfaceName = getRadioInterfaceName(hasWifi);
- char ipv6Gateway[INET6_ADDRSTRLEN];
- char ipv6Dns[8192];
err = at_send_command_multiline ("AT+CGACT?", "+CGACT:", &p_response);
if (err != 0 || p_response->success == 0) {
@@ -747,23 +735,24 @@ static void requestOrSendDataCallList(RIL_Token *t)
if (err < 0)
goto error;
- pthread_mutex_lock(&s_addresses_mutex);
+ pthread_mutex_lock(&s_ipv6_addresses_mutex);
- // Extra space for null terminator
- int addresses_size = MAX(strlen(out), strlen(s_if_addresses)) + 1;
+ // Extra space for null terminator and separating space
+ int addresses_size = strlen(out) + strlen(s_ipv6_addresses) + 2;
responses[i].addresses = alloca(addresses_size);
- if (*s_if_addresses) {
- // Interface addresses exist, use them.
- strlcpy(responses[i].addresses, s_if_addresses, addresses_size);
+ if (*s_ipv6_addresses) {
+ // IPv6 addresses exist, add them
+ snprintf(responses[i].addresses, addresses_size,
+ "%s %s",
+ hasWifi ? RADIO0_IPV4_ADDRESS : out,
+ s_ipv6_addresses);
} else {
- // No known interface address, use whatever the modem provided
- strlcpy(responses[i].addresses, out, addresses_size);
+ // Only provide the IPv4 address
+ strlcpy(responses[i].addresses,
+ hasWifi ? RADIO0_IPV4_ADDRESS : out,
+ addresses_size);
}
-
- strlcpy(ipv6Gateway, s_ipv6_gateway, sizeof(ipv6Gateway));
- strlcpy(ipv6Dns, s_ipv6_dns, sizeof(ipv6Dns));
-
- pthread_mutex_unlock(&s_addresses_mutex);
+ pthread_mutex_unlock(&s_ipv6_addresses_mutex);
if (isInEmulator()) {
/* We are in the emulator - the dns servers are listed
@@ -780,15 +769,12 @@ static void requestOrSendDataCallList(RIL_Token *t)
int nn;
char propName[PROP_NAME_MAX];
char propValue[PROP_VALUE_MAX];
- char* gateways = NULL;
- size_t gatewaysSize = 0;
dnslist[0] = 0;
for (nn = 1; nn <= 4; nn++) {
/* Probe net.eth0.dns<n> */
- snprintf(propName, sizeof propName, "net.%s.dns%d",
- radioInterfaceName, nn);
+ snprintf(propName, sizeof propName, "net.eth0.dns%d", nn);
/* Ignore if undefined */
if (property_get(propName, propValue, "") <= 0) {
@@ -802,8 +788,7 @@ static void requestOrSendDataCallList(RIL_Token *t)
}
for (nn = 1; nn <= 4; ++nn) {
/* Probe net.eth0.ipv6dns<n> for IPv6 DNS servers */
- snprintf(propName, sizeof propName, "net.%s.ipv6dns%d",
- radioInterfaceName, nn);
+ snprintf(propName, sizeof propName, "net.eth0.ipv6dns%d", nn);
/* Ignore if undefined */
if (property_get(propName, propValue, "") <= 0) {
continue;
@@ -815,31 +800,13 @@ static void requestOrSendDataCallList(RIL_Token *t)
responses[i].dnses = dnslist;
- /* There is only one gateway in the emulator. */
- snprintf(propName, sizeof propName, "net.%s.gw",
- radioInterfaceName);
-
- gatewaysSize = strlen(ipv6Gateway);
- if (property_get(propName, propValue, "") > 0) {
- if (gatewaysSize > 0) {
- // Room for a separating space
- ++gatewaysSize;
- }
- gatewaysSize += strlen(propValue);
- }
- if (gatewaysSize > 0) {
- // Room for a terminating null byte
- ++gatewaysSize;
- responses[i].gateways = alloca(gatewaysSize);
- if (ipv6Gateway[0]) {
- strlcpy(responses[i].gateways, ipv6Gateway, gatewaysSize);
- }
- if (propValue[0]) {
- if (responses[i].gateways[0] != '\0') {
- strlcat(responses[i].gateways, " ", gatewaysSize);
- }
- strlcat(responses[i].gateways, propValue, gatewaysSize);
- }
+ /* There is only one gateway in the emulator. If WiFi is
+ * configured the interface visible to RIL will be behind a NAT
+ * where the gateway is different. */
+ if (hasWifi) {
+ responses[i].gateways = "192.168.200.1";
+ } else if (property_get("net.eth0.gw", propValue, "") > 0) {
+ responses[i].gateways = propValue;
} else {
responses[i].gateways = "";
}
@@ -856,14 +823,13 @@ static void requestOrSendDataCallList(RIL_Token *t)
at_response_free(p_response);
- if (t != NULL) {
+ if (t != NULL)
RIL_onRequestComplete(*t, RIL_E_SUCCESS, responses,
n * sizeof(RIL_Data_Call_Response_v11));
- } else {
+ else
RIL_onUnsolicitedResponse(RIL_UNSOL_DATA_CALL_LIST_CHANGED,
responses,
n * sizeof(RIL_Data_Call_Response_v11));
- }
return;
@@ -3984,18 +3950,22 @@ static void onInterfaceAddressChange(unsigned int ifIndex,
return;
}
- pthread_mutex_lock(&s_addresses_mutex);
+ pthread_mutex_lock(&s_ipv6_addresses_mutex);
// Clear out any existing addresses, we receive a full set of addresses
// that are going to replace the existing ones.
- s_if_addresses[0] = '\0';
- currentLoc = s_if_addresses;
- remaining = sizeof(s_if_addresses);
+ s_ipv6_addresses[0] = '\0';
+ currentLoc = s_ipv6_addresses;
+ remaining = sizeof(s_ipv6_addresses);
for (i = 0; i < numAddresses; ++i) {
+ if (addresses[i].family != AF_INET6) {
+ // Only care about IPv6 addresses
+ continue;
+ }
char address[INET6_ADDRSTRLEN];
if (inet_ntop(addresses[i].family, &addresses[i].addr,
address, sizeof(address))) {
int printed = 0;
- if (s_if_addresses[0]) {
+ if (s_ipv6_addresses[0]) {
// We've already printed something, separate them
if (remaining < 1) {
continue;
@@ -4013,38 +3983,7 @@ static void onInterfaceAddressChange(unsigned int ifIndex,
RLOGE("Unable to convert address to string for if %s", ifName);
}
}
- pthread_mutex_unlock(&s_addresses_mutex);
-
- // Send unsolicited call list change to notify upper layers about the new
- // addresses
- requestOrSendDataCallList(NULL);
-}
-
-static void onIpv6Change(const struct in6_addr* gateway,
- const struct in6_addr* dnsServers,
- size_t numDnsServers) {
- char* dnsLoc = s_ipv6_dns;
- size_t remaining = sizeof(s_ipv6_dns);
- char address[INET6_ADDRSTRLEN];
-
- pthread_mutex_lock(&s_addresses_mutex);
-
- inet_ntop(AF_INET6, gateway, s_ipv6_gateway, sizeof(s_ipv6_gateway));
-
- s_ipv6_dns[0] = '\0';
- for (size_t i = 0; i < numDnsServers; ++i) {
- if (inet_ntop(AF_INET6, &dnsServers[i], address, sizeof(address))) {
- size_t len = strlcat(s_ipv6_dns, address, sizeof(s_ipv6_dns));
- if (i + 1 < numDnsServers && len + 1 < sizeof(s_ipv6_dns)) {
- // There's more to come and there's room for more, separate
- // multiple DNS servers by a space.
- s_ipv6_dns[len] = ' ';
- s_ipv6_dns[len + 1] = '\0';
- }
- }
- }
-
- pthread_mutex_unlock(&s_addresses_mutex);
+ pthread_mutex_unlock(&s_ipv6_addresses_mutex);
// Send unsolicited call list change to notify upper layers about the new
// addresses
@@ -4056,20 +3995,14 @@ mainLoop(void *param __unused)
{
int fd;
int ret;
- bool hasWifi = hasWifiCapability();
- const char* radioInterfaceName = getRadioInterfaceName(hasWifi);
- struct ifMonitor* ifMonitor = ifMonitorCreate();
- struct ipv6Monitor* ipv6Monitor = ipv6MonitorCreate(radioInterfaceName);
+ struct ifMonitor* monitor = ifMonitorCreate();
AT_DUMP("== ", "entering mainLoop()", -1 );
at_set_on_reader_closed(onATReaderClosed);
at_set_on_timeout(onATTimeout);
- ifMonitorSetCallback(ifMonitor, &onInterfaceAddressChange);
- ifMonitorRunAsync(ifMonitor);
-
- ipv6MonitorSetCallback(ipv6Monitor, &onIpv6Change);
- ipv6MonitorRunAsync(ipv6Monitor);
+ ifMonitorSetCallback(monitor, &onInterfaceAddressChange);
+ ifMonitorRunAsync(monitor);
for (;;) {
fd = -1;
@@ -4119,11 +4052,8 @@ mainLoop(void *param __unused)
RLOGI("Re-opening after close");
}
- ifMonitorStop(ifMonitor);
- ifMonitorFree(ifMonitor);
-
- ipv6MonitorStop(ipv6Monitor);
- ipv6MonitorFree(ipv6Monitor);
+ ifMonitorStop(monitor);
+ ifMonitorFree(monitor);
return NULL;
}
diff --git a/sepolicy/common/OWNERS b/sepolicy/common/OWNERS
index e6fbbd47..ff296774 100644
--- a/sepolicy/common/OWNERS
+++ b/sepolicy/common/OWNERS
@@ -3,7 +3,6 @@ bowgotsai@google.com
jbires@google.com
jeffv@google.com
jgalenson@google.com
-nnk@google.com
sspatil@google.com
tomcherry@google.com
trong@google.com
diff --git a/sepolicy/common/bootanim.te b/sepolicy/common/bootanim.te
index 4d011e10..bc84ee73 100644
--- a/sepolicy/common/bootanim.te
+++ b/sepolicy/common/bootanim.te
@@ -4,7 +4,6 @@ allow bootanim ashmem_device:chr_file execute;
dontaudit bootanim system_data_file:dir read;
allow bootanim graphics_device:chr_file { read ioctl open };
-allow bootanim gpu_device:chr_file { read ioctl open };
typeattribute bootanim system_writes_vendor_properties_violators;
set_prop(bootanim, qemu_prop)
diff --git a/sepolicy/common/bug_map b/sepolicy/common/bug_map
deleted file mode 100644
index 839b49e6..00000000
--- a/sepolicy/common/bug_map
+++ /dev/null
@@ -1,17 +0,0 @@
-hal_wifi_default default_prop file b/131598173
-hal_wifi_default vendor_default_prop property_service b/131598173
-init unlabeled dir b/131596633
-init vendor_toolbox_exec file b/132695863
-installd device file b/131595213
-kernel kernel system b/131597442
-netd device file b/131598170
-platform_app vendor_default_prop file b/130684647
-priv_app property_socket sock_file b/131598844
-priv_app varrun_file dir b/131598844
-storaged device file b/131598843
-toolbox unlabeled dir b/131599097
-toolbox toolbox capability b/131599097
-ueventd metadata_file dir b/131594529
-vendor_init exported2_default_prop property_service b/131601458
-init serial_device chr_file b/134145307
-gsid device file b/133324244
diff --git a/sepolicy/common/dhcpclient.te b/sepolicy/common/dhcpclient.te
index cff44712..f1ba3f02 100644
--- a/sepolicy/common/dhcpclient.te
+++ b/sepolicy/common/dhcpclient.te
@@ -8,14 +8,14 @@ net_domain(dhcpclient)
allow dhcpclient execns:fd use;
set_prop(dhcpclient, net_eth0_prop);
-set_prop(dhcpclient, net_radio0_prop);
dontaudit dhcpclient kernel:system module_request;
allow dhcpclient self:capability { net_admin net_raw };
-allow dhcpclient self:netlink_route_socket { ioctl write nlmsg_write };
+allow dhcpclient self:udp_socket create;
+allow dhcpclient self:netlink_route_socket { write nlmsg_write };
allow dhcpclient varrun_file:dir search;
allow dhcpclient self:packet_socket { create bind write read };
-allowxperm dhcpclient self:netlink_route_socket ioctl { SIOCGIFFLAGS
- SIOCSIFFLAGS
- SIOCSIFMTU
- SIOCGIFINDEX
- SIOCGIFHWADDR };
+allowxperm dhcpclient self:udp_socket ioctl { SIOCSIFFLAGS
+ SIOCSIFADDR
+ SIOCSIFNETMASK
+ SIOCSIFMTU
+ SIOCGIFHWADDR };
diff --git a/sepolicy/common/dhcprelay.te b/sepolicy/common/dhcprelay.te
deleted file mode 100644
index 4c4ffdf5..00000000
--- a/sepolicy/common/dhcprelay.te
+++ /dev/null
@@ -1,21 +0,0 @@
-# DHCP relay
-type dhcprelay, domain;
-type dhcprelay_exec, exec_type, vendor_file_type, file_type;
-
-init_daemon_domain(dhcprelay)
-net_domain(dhcprelay)
-
-allow dhcprelay execns:fd use;
-
-set_prop(dhcprelay, net_eth0_prop);
-dontaudit dhcprelay kernel:system module_request;
-allow dhcprelay self:capability { net_admin net_bind_service net_raw };
-allow dhcprelay self:udp_socket create;
-allow dhcprelay self:netlink_route_socket { write nlmsg_write };
-allow dhcprelay varrun_file:dir search;
-allow dhcprelay self:packet_socket { create bind write read };
-allowxperm dhcprelay self:udp_socket ioctl { SIOCSIFFLAGS
- SIOCSIFADDR
- SIOCSIFNETMASK
- SIOCSIFMTU
- SIOCGIFHWADDR };
diff --git a/sepolicy/common/dhcpserver.te b/sepolicy/common/dhcpserver.te
new file mode 100644
index 00000000..7e8ba263
--- /dev/null
+++ b/sepolicy/common/dhcpserver.te
@@ -0,0 +1,12 @@
+# DHCP server
+type dhcpserver, domain;
+type dhcpserver_exec, exec_type, vendor_file_type, file_type;
+
+init_daemon_domain(dhcpserver)
+net_domain(dhcpserver)
+
+allow dhcpserver execns:fd use;
+
+get_prop(dhcpserver, net_eth0_prop);
+allow dhcpserver self:udp_socket { ioctl create setopt bind };
+allow dhcpserver self:capability { net_raw net_bind_service };
diff --git a/sepolicy/common/execns.te b/sepolicy/common/execns.te
index 265fb835..24eee410 100644
--- a/sepolicy/common/execns.te
+++ b/sepolicy/common/execns.te
@@ -15,6 +15,9 @@ domain_auto_trans(init, execns_exec, execns);
# Allow dhcpclient to be run by execns in its own domain
domain_auto_trans(execns, dhcpclient_exec, dhcpclient);
+# Allow dhcpserver to be run by execns in its own domain
+domain_auto_trans(execns, dhcpserver_exec, dhcpserver);
+
# Allow hostapd_nohidl to be run by execns in its own domain
domain_auto_trans(execns, hostapd_nohidl_exec, hostapd_nohidl);
diff --git a/sepolicy/common/file_contexts b/sepolicy/common/file_contexts
index 6bcc6732..c1350f94 100644
--- a/sepolicy/common/file_contexts
+++ b/sepolicy/common/file_contexts
@@ -15,9 +15,6 @@
/dev/goldfish_sync u:object_r:qemu_device:s0
/dev/goldfish_address_space u:object_r:qemu_device:s0
/dev/qemu_.* u:object_r:qemu_device:s0
-/dev/dri/card0 u:object_r:gpu_device:s0
-/dev/dri/controlD64 u:object_r:gpu_device:s0
-/dev/dri/renderD128 u:object_r:gpu_device:s0
/dev/ttyGF[0-9]* u:object_r:serial_device:s0
/dev/ttyS2 u:object_r:console_device:s0
/vendor/bin/init\.ranchu-core\.sh u:object_r:goldfish_setup_exec:s0
@@ -26,17 +23,16 @@
/vendor/bin/qemu-props u:object_r:qemu_props_exec:s0
/vendor/bin/createns u:object_r:createns_exec:s0
/vendor/bin/execns u:object_r:execns_exec:s0
-/vendor/bin/ip u:object_r:goldfish_ip_exec:s0
+/vendor/bin/ipv6proxy u:object_r:ipv6proxy_exec:s0
/vendor/bin/iw u:object_r:goldfish_iw_exec:s0
/vendor/bin/dhcpclient u:object_r:dhcpclient_exec:s0
+/vendor/bin/dhcpserver u:object_r:dhcpserver_exec:s0
/vendor/bin/hostapd_nohidl u:object_r:hostapd_nohidl_exec:s0
/vendor/bin/netmgr u:object_r:netmgr_exec:s0
-/vendor/bin/wifi_forwarder u:object_r:wifi_forwarder_exec:s0
/vendor/bin/hw/android\.hardware\.drm@1\.0-service\.widevine u:object_r:hal_drm_widevine_exec:s0
/vendor/bin/hw/android\.hardware\.drm@1\.2-service\.widevine u:object_r:hal_drm_widevine_exec:s0
/vendor/bin/hw/android\.hardware\.drm@1\.2-service\.clearkey u:object_r:hal_drm_clearkey_exec:s0
-/vendor/bin/hw/android\.hardware\.gatekeeper@1\.0-service.software u:object_r:hal_gatekeeper_default_exec:s0
/vendor/bin/hw/android\.hardware\.keymaster@4\.0-strongbox-service u:object_r:hal_keymaster_default_exec:s0
/vendor/bin/hw/android\.hardware\.health@2\.0-service.goldfish u:object_r:hal_health_default_exec:s0
/vendor/bin/hw/android\.hardware\.power@1\.1-service.ranchu u:object_r:hal_power_default_exec:s0
@@ -57,8 +53,6 @@
/vendor/lib(64)?/libGLESv1_enc\.so u:object_r:same_process_hal_file:s0
/vendor/lib(64)?/libGLESv2_enc\.so u:object_r:same_process_hal_file:s0
/vendor/lib(64)?/libvulkan_enc\.so u:object_r:same_process_hal_file:s0
-/vendor/lib(64)?/libandroidemu\.so u:object_r:same_process_hal_file:s0
-/vendor/lib(64)?/libdrm.so u:object_r:same_process_hal_file:s0
# data
/data/vendor/mediadrm(/.*)? u:object_r:mediadrm_vendor_data_file:s0
diff --git a/sepolicy/common/goldfish_ip.te b/sepolicy/common/goldfish_ip.te
deleted file mode 100644
index c914596a..00000000
--- a/sepolicy/common/goldfish_ip.te
+++ /dev/null
@@ -1,5 +0,0 @@
-type goldfish_ip, domain;
-type goldfish_ip_exec, exec_type, vendor_file_type, file_type;
-
-init_daemon_domain(goldfish_ip)
-net_domain(goldfish_ip)
diff --git a/sepolicy/common/goldfish_setup.te b/sepolicy/common/goldfish_setup.te
index e3071f75..187d0558 100644
--- a/sepolicy/common/goldfish_setup.te
+++ b/sepolicy/common/goldfish_setup.te
@@ -14,7 +14,6 @@ allowxperm goldfish_setup self:udp_socket ioctl priv_sock_ioctls;
wakelock_use(goldfish_setup);
allow goldfish_setup vendor_shell_exec:file { rx_file_perms };
#============= goldfish_setup ==============
-allow goldfish_setup goldfish_ip_exec:file execute_no_trans;
allow goldfish_setup goldfish_iw_exec:file execute_no_trans;
# Set system properties to start services
@@ -34,6 +33,10 @@ allow goldfish_setup system_data_file:dir getattr;
allow goldfish_setup kernel:system module_request;
set_prop(goldfish_setup, qemu_prop);
get_prop(goldfish_setup, net_share_prop);
+# Allow goldfish_setup to run /system/bin/ip and /system/bin/iw
+# TODO(b/113124961): clean up this Treble violation.
+typeattribute goldfish_setup vendor_executes_system_violators;
+allow goldfish_setup system_file:file rx_file_perms;
# Allow goldfish_setup to run init.wifi.sh
allow goldfish_setup goldfish_setup_exec:file execute_no_trans;
#Allow goldfish_setup to run createns in its own domain
@@ -49,5 +52,4 @@ allow goldfish_setup createns:lnk_file { read };
# Allow goldfish_setup to copy the hostapd conf template to the vendor data dir
allow goldfish_setup hostapd_data_file:file create_file_perms;
allow goldfish_setup hostapd_data_file:dir rw_dir_perms;
-#allow goldfish_setup system_file:file { execute getattr open read };
-dontaudit goldfish_setup self:capability dac_override;
+allow goldfish_setup system_file:file { execute getattr open read };
diff --git a/sepolicy/common/hal_drm_clearkey.te b/sepolicy/common/hal_drm_clearkey.te
index 5632c3b2..976b9fab 100644
--- a/sepolicy/common/hal_drm_clearkey.te
+++ b/sepolicy/common/hal_drm_clearkey.te
@@ -7,3 +7,5 @@ init_daemon_domain(hal_drm_clearkey)
hal_server_domain(hal_drm_clearkey, hal_drm)
vndbinder_use(hal_drm_clearkey);
+
+allow hal_drm_clearkey { appdomain -isolated_app }:fd use;
diff --git a/sepolicy/common/hal_drm_widevine.te b/sepolicy/common/hal_drm_widevine.te
index 8478ee83..81984109 100644
--- a/sepolicy/common/hal_drm_widevine.te
+++ b/sepolicy/common/hal_drm_widevine.te
@@ -6,6 +6,7 @@ type hal_drm_widevine_exec, exec_type, vendor_file_type, file_type;
init_daemon_domain(hal_drm_widevine)
allow hal_drm mediacodec:fd use;
+allow hal_drm { appdomain -isolated_app }:fd use;
vndbinder_use(hal_drm_widevine);
hal_client_domain(hal_drm_widevine, hal_graphics_composer);
diff --git a/sepolicy/common/hal_graphics_allocator_default.te b/sepolicy/common/hal_graphics_allocator_default.te
index 527cabdb..c57e4522 100644
--- a/sepolicy/common/hal_graphics_allocator_default.te
+++ b/sepolicy/common/hal_graphics_allocator_default.te
@@ -1,6 +1,4 @@
allow hal_graphics_allocator_default graphics_device:dir search;
-allow hal_graphics_allocator_default graphics_device:chr_file { ioctl open read write map rw_file_perms };
-allow hal_graphics_allocator_default gpu_device:dir search;
-allow hal_graphics_allocator_default gpu_device:chr_file { ioctl open read write map rw_file_perms };
+allow hal_graphics_allocator_default graphics_device:chr_file { ioctl open read write };
allow hal_graphics_allocator_default dumpstate:fd use;
allow hal_graphics_allocator_default dumpstate:fifo_file write;
diff --git a/sepolicy/common/hal_graphics_composer_default.te b/sepolicy/common/hal_graphics_composer_default.te
index 3b0c862f..e9205cda 100644
--- a/sepolicy/common/hal_graphics_composer_default.te
+++ b/sepolicy/common/hal_graphics_composer_default.te
@@ -1,4 +1,3 @@
#============= hal_graphics_composer_default ==============
allow hal_graphics_composer_default vndbinder_device:chr_file { ioctl open read write map };
-allow hal_graphics_composer_default graphics_device:chr_file { ioctl open read write map };
-allow hal_graphics_composer_default gpu_device:chr_file { ioctl open read write map };
+
diff --git a/sepolicy/common/ipv6proxy.te b/sepolicy/common/ipv6proxy.te
new file mode 100644
index 00000000..a6315016
--- /dev/null
+++ b/sepolicy/common/ipv6proxy.te
@@ -0,0 +1,18 @@
+# IPv6 proxying
+type ipv6proxy, domain;
+type ipv6proxy_exec, exec_type, vendor_file_type, file_type;
+
+init_daemon_domain(ipv6proxy)
+net_domain(ipv6proxy)
+
+# Allow ipv6proxy to be run by execns in its own domain
+domain_auto_trans(execns, ipv6proxy_exec, ipv6proxy);
+allow ipv6proxy execns:fd use;
+
+set_prop(ipv6proxy, net_eth0_prop);
+dontaudit ipv6proxy kernel:system module_request;
+allow ipv6proxy self:capability { sys_admin sys_module net_admin net_raw };
+allow ipv6proxy self:packet_socket { bind create read };
+allow ipv6proxy self:netlink_route_socket nlmsg_write;
+allow ipv6proxy varrun_file:dir search;
+allowxperm ipv6proxy self:udp_socket ioctl { SIOCSIFFLAGS SIOCGIFHWADDR };
diff --git a/sepolicy/common/mediacodec.te b/sepolicy/common/mediacodec.te
index 41241a3f..acf4e59b 100644
--- a/sepolicy/common/mediacodec.te
+++ b/sepolicy/common/mediacodec.te
@@ -1,4 +1 @@
allow mediacodec system_file:dir { open read };
-allow mediacodec vendor_data_file:dir search;
-allow mediacodec vendor_data_file:file { open read getattr };
-allow mediacodec vendor_data_file:lnk_file read;
diff --git a/sepolicy/common/netmgr.te b/sepolicy/common/netmgr.te
index c7abcb92..96caf82f 100644
--- a/sepolicy/common/netmgr.te
+++ b/sepolicy/common/netmgr.te
@@ -7,31 +7,25 @@ net_domain(netmgr)
allow netmgr execns:fd use;
-# Set property to indicate bridging is complete
-set_prop(netmgr, vendor_net);
# Set ctrl.restart property to restart hostapd when config changes
set_prop(netmgr, ctl_default_prop);
# Modify hostapd config file
-allow netmgr hostapd_data_file:file create_file_perms;
+allow netmgr hostapd_data_file:file rw_file_perms;
allow netmgr hostapd_data_file:dir rw_dir_perms;
# Assign addresses to new interfaces as hostapd brings them up
allow netmgr self:capability { net_raw net_admin };
-allow netmgr self:socket { create };
-allow netmgr self:unix_dgram_socket ioctl;
-allow netmgr self:packet_socket { ioctl getopt map };
+allow netmgr self:socket { create ioctl };
+allow netmgr self:packet_socket { ioctl getopt };
allow netmgr self:udp_socket { ioctl };
allow netmgr proc_net:file { read getattr open };
-allowxperm netmgr self:unix_dgram_socket ioctl { SIOCETHTOOL };
-allowxperm netmgr self:udp_socket ioctl { SIOCSIFFLAGS
- SIOCBRADDBR
- SIOCBRADDIF
- SIOCBRDELIF };
+allowxperm netmgr self:socket ioctl { SIOCETHTOOL };
+allowxperm netmgr self:udp_socket ioctl { SIOCSIFADDR SIOCSIFNETMASK SIOCSIFBRDADDR };
allowxperm netmgr self:packet_socket ioctl { SIOCGIFINDEX SIOCGIFHWADDR };
-# Allow netmgr to run ip and modify route table to block unblock traffic
-allow netmgr goldfish_ip_exec:file execute_no_trans;
-allow netmgr self:netlink_route_socket nlmsg_write;
+# Allow netmgr to run iptables to block and unblock network traffic
+# TODO(b/113124961): clean up this Treble violation.
+typeattribute netmgr vendor_executes_system_violators;
+allow netmgr system_file:file execute_no_trans;
+allow netmgr system_file:file lock;
# Packet socket for wifi forwarding
allow netmgr self:packet_socket { bind create read setopt write };
-allow netmgr kernel:system module_request;
-allow netmgr self:capability sys_module;
diff --git a/sepolicy/common/property.te b/sepolicy/common/property.te
index 40461057..3593a39d 100644
--- a/sepolicy/common/property.te
+++ b/sepolicy/common/property.te
@@ -2,6 +2,4 @@ type qemu_prop, property_type;
type qemu_cmdline, property_type;
type radio_noril_prop, property_type;
type net_eth0_prop, property_type;
-type net_radio0_prop, property_type;
type net_share_prop, property_type;
-type vendor_net, property_type;
diff --git a/sepolicy/common/property_contexts b/sepolicy/common/property_contexts
index 86f01149..4a82974f 100644
--- a/sepolicy/common/property_contexts
+++ b/sepolicy/common/property_contexts
@@ -1,11 +1,9 @@
qemu. u:object_r:qemu_prop:s0
qemu.cmdline u:object_r:qemu_cmdline:s0
vendor.qemu u:object_r:qemu_prop:s0
-vendor.network u:object_r:vendor_net:s0
ro.emu. u:object_r:qemu_prop:s0
ro.emulator. u:object_r:qemu_prop:s0
ro.radio.noril u:object_r:radio_noril_prop:s0
net.eth0. u:object_r:net_eth0_prop:s0
-net.radio0. u:object_r:net_radio0_prop:s0
net.shared_net_ip u:object_r:net_share_prop:s0
ro.zygote.disable_gl_preload u:object_r:qemu_prop:s0
diff --git a/sepolicy/common/radio.te b/sepolicy/common/radio.te
index 38faf6fa..742d3b2d 100644
--- a/sepolicy/common/radio.te
+++ b/sepolicy/common/radio.te
@@ -1,4 +1,3 @@
# Allow the radio to read these properties, they only have an SELinux label in
# the emulator.
get_prop(radio, net_eth0_prop);
-allow radio net_radio0_prop:file { getattr read open map };
diff --git a/sepolicy/common/rild.te b/sepolicy/common/rild.te
index c17fa5e7..ea183739 100644
--- a/sepolicy/common/rild.te
+++ b/sepolicy/common/rild.te
@@ -1,10 +1,3 @@
# Allow rild to read these properties, they only have an SELinux label in the
# emulator.
get_prop(rild, net_eth0_prop);
-get_prop(rild, net_radio0_prop);
-
-# IPv6 router advertisement detection
-allow rild self:packet_socket { bind create ioctl read setopt };
-allowxperm rild self:packet_socket ioctl { SIOCGIFFLAGS
- SIOCSIFFLAGS
- SIOCGIFHWADDR };
diff --git a/sepolicy/common/surfaceflinger.te b/sepolicy/common/surfaceflinger.te
index 575ec1bd..2bba8a78 100644
--- a/sepolicy/common/surfaceflinger.te
+++ b/sepolicy/common/surfaceflinger.te
@@ -1,6 +1,5 @@
allow surfaceflinger self:process execmem;
allow surfaceflinger ashmem_device:chr_file execute;
-allow surfaceflinger gpu_device:chr_file { ioctl open read write map };
typeattribute surfaceflinger system_writes_vendor_properties_violators;
set_prop(surfaceflinger, qemu_prop)
diff --git a/sepolicy/common/wifi_forwarder.te b/sepolicy/common/wifi_forwarder.te
deleted file mode 100644
index 3eb7bbac..00000000
--- a/sepolicy/common/wifi_forwarder.te
+++ /dev/null
@@ -1,11 +0,0 @@
-# Wifi forwarder
-type wifi_forwarder, domain;
-type wifi_forwarder_exec, exec_type, vendor_file_type, file_type;
-
-init_daemon_domain(wifi_forwarder)
-net_domain(wifi_forwarder)
-
-allow wifi_forwarder self:capability { net_admin };
-# Generic netlink socket for wifi forwarding
-allow wifi_forwarder self:netlink_generic_socket { bind create getattr setopt read write };
-
diff --git a/sepolicy/x86/OWNERS b/sepolicy/x86/OWNERS
index e6fbbd47..ff296774 100644
--- a/sepolicy/x86/OWNERS
+++ b/sepolicy/x86/OWNERS
@@ -3,7 +3,6 @@ bowgotsai@google.com
jbires@google.com
jeffv@google.com
jgalenson@google.com
-nnk@google.com
sspatil@google.com
tomcherry@google.com
trong@google.com
diff --git a/tnc/Android.bp b/tnc/Android.bp
deleted file mode 100644
index fb0236fd..00000000
--- a/tnc/Android.bp
+++ /dev/null
@@ -1,32 +0,0 @@
-//
-// Copyright (C) 2018 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.
-//
-
-cc_binary {
- name: "tnc",
- vendor: true,
- cflags: [
- "-Wall",
- "-Werror",
- ],
- srcs: [
- "main.cpp",
- ],
- shared_libs: [
- "libcutils",
- "liblog",
- ],
-}
-
diff --git a/tnc/main.cpp b/tnc/main.cpp
deleted file mode 100644
index d6ffd116..00000000
--- a/tnc/main.cpp
+++ /dev/null
@@ -1,217 +0,0 @@
-
-#include <errno.h>
-#include <netdb.h>
-#include <net/if.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/ioctl.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <initializer_list>
-
-static void usage(const char* program) {
- fprintf(stderr, "Usage: %s [-s|-c|-b] <ip> <port>\n", program);
-}
-
-enum class Mode {
- Bridge,
- Client,
- Server,
-};
-
-bool resolve(const char* name, const char* port, struct addrinfo** addrs) {
- struct addrinfo hints;
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = AF_UNSPEC;
- hints.ai_socktype = SOCK_DGRAM;
-
- int res = ::getaddrinfo(name, port, &hints, addrs);
- if (res != 0) {
- fprintf(stderr, "ERROR: Unable to resolve '%s' and port '%s': %s\n",
- name, port, gai_strerror(res));
- return false;
- }
- return true;
-}
-
-int runClient(struct addrinfo* addrs) {
- int fd = -1;
- for (struct addrinfo* addr = addrs; addr != nullptr; addr = addr->ai_next) {
- fd = ::socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
- if (fd < 0) {
- continue;
- }
- if (::connect(fd, addr->ai_addr, addr->ai_addrlen) == 0) {
- break;
- }
- ::close(fd);
- }
- ::freeaddrinfo(addrs);
- if (fd < 0) {
- fprintf(stderr, "Unable to connect to server\n");
- return 1;
- }
- if (::send(fd, "boop", 4, 0) != 4) {
- ::close(fd);
- fprintf(stderr, "Failed to send message to server\n");
- return 1;
- }
- ::close(fd);
- return 0;
-}
-
-int runServer(struct addrinfo* addrs) {
- int fd = -1;
- for (struct addrinfo* addr = addrs; addr != nullptr; addr = addr->ai_next) {
- fd = ::socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
- if (fd < 0) {
- continue;
- }
- if (::bind(fd, addr->ai_addr, addr->ai_addrlen) == 0) {
- break;
- }
- ::close(fd);
- }
- ::freeaddrinfo(addrs);
- if (fd < 0) {
- fprintf(stderr, "Unable to bind to address\n");
- return 1;
- }
- char buffer[1024];
- for (;;) {
- struct sockaddr_storage addr;
- socklen_t addrSize = sizeof(addr);
- ssize_t bytesRead = recvfrom(fd, buffer, sizeof(buffer), 0,
- reinterpret_cast<struct sockaddr*>(&addr),
- &addrSize);
- if (bytesRead < 0) {
- if (errno == EINTR) {
- continue;
- }
- fprintf(stderr, "Error receiving on socket: %s\n", strerror(errno));
- ::close(fd);
- return 1;
- } else if (bytesRead == 0) {
- fprintf(stderr, "Socket unexpectedly closed\n");
- ::close(fd);
- return 1;
- }
- printf("Received message from client '%*s'\n",
- static_cast<int>(bytesRead), buffer);
- }
-}
-
-static const char kBridgeName[] = "br0";
-
-static int configureBridge() {
- int fd = ::socket(AF_LOCAL, SOCK_STREAM, 0);
- if (fd < 0) {
- fprintf(stderr, "ERROR: Could not open bridge socket: %s\n",
- strerror(errno));
- return 1;
- }
-
- int res = ::ioctl(fd, SIOCBRADDBR, kBridgeName);
- if (res < 0) {
- fprintf(stderr, "ERROR: cannot create bridge: %s\n", strerror(errno));
- ::close(fd);
- return 1;
- }
-
- for (const auto& ifName : { "eth0", "wlan1", "radio0-peer" }) {
- struct ifreq request;
- memset(&request, 0, sizeof(request));
- request.ifr_ifindex = if_nametoindex(ifName);
- if (request.ifr_ifindex == 0) {
- fprintf(stderr, "ERROR: Unable to get interface index for %s\n",
- ifName);
- ::close(fd);
- return 1;
- }
- strlcpy(request.ifr_name, kBridgeName, sizeof(request.ifr_name));
- res = ::ioctl(fd, SIOCBRADDIF, &request);
- if (res < 0) {
- fprintf(stderr, "ERROR: cannot add if %s to bridge: %s\n",
- ifName, strerror(errno));
- ::close(fd);
- return 1;
- }
- }
-
- struct ifreq request;
- memset(&request, 0, sizeof(request));
- request.ifr_ifindex = if_nametoindex(kBridgeName);
- if (request.ifr_ifindex == 0) {
- fprintf(stderr, "ERROR: Unable to get interface index for %s\n",
- kBridgeName);
- ::close(fd);
- return 1;
- }
- strlcpy(request.ifr_name, kBridgeName, sizeof(request.ifr_name));
- res = ::ioctl(fd, SIOCGIFFLAGS, &request);
- if (res != 0) {
- fprintf(stderr, "ERROR: Unable to get interface index for %s\n",
- kBridgeName);
- ::close(fd);
- return 1;
- }
- if ((request.ifr_flags & IFF_UP) == 0) {
- // Bridge is not up, it needs to be up to work
- request.ifr_flags |= IFF_UP;
- res = ::ioctl(fd, SIOCSIFFLAGS, &request);
- if (res != 0) {
- fprintf(stderr, "ERROR: Unable to set interface flags for %s\n",
- kBridgeName);
- ::close(fd);
- return 1;
- }
- }
-
- ::close(fd);
- return 0;
-}
-
-int main(int argc, char* argv[]) {
- if (argc < 2) {
- usage(argv[0]);
- return 1;
- }
-
- Mode mode;
- if (strcmp("-b", argv[1]) == 0) {
- mode = Mode::Bridge;
- } else if (strcmp("-c", argv[1]) == 0) {
- mode = Mode::Client;
- } else if (strcmp("-s", argv[1]) == 0) {
- mode = Mode::Server;
- } else {
- fprintf(stderr, "ERROR: Invalid option '%s'\n", argv[1]);
- usage(argv[0]);
- return 1;
- }
-
- struct addrinfo* addrs = nullptr;
- if (mode == Mode::Client || mode == Mode::Server) {
- if (argc != 4) {
- usage(argv[0]);
- return 1;
- }
- if (!resolve(argv[2], argv[3], &addrs)) {
- usage(argv[0]);
- return 1;
- }
- }
-
- switch (mode) {
- case Mode::Bridge:
- return configureBridge();
- case Mode::Client:
- return runClient(addrs);
- case Mode::Server:
- return runServer(addrs);
- }
-}
-
diff --git a/tools/Android.bp b/tools/Android.bp
deleted file mode 100644
index 8cb1ad02..00000000
--- a/tools/Android.bp
+++ /dev/null
@@ -1,30 +0,0 @@
-//
-// Copyright (C) 2019 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.
-//
-
-python_binary_host {
- name: "mk_combined_img",
- srcs: ["mk_combined_img.py"],
- main: "mk_combined_img.py",
- version: {
- py2: {
- enabled: true,
- embedded_launcher: true,
- },
- py3: {
- enabled: false,
- },
- },
-}
diff --git a/tools/Android.mk b/tools/Android.mk
deleted file mode 100644
index 928fc9d0..00000000
--- a/tools/Android.mk
+++ /dev/null
@@ -1,97 +0,0 @@
-#
-# Copyright 2019 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.
-#
-
-ifneq ($(filter generic_% generic, $(TARGET_DEVICE)),)
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-EMU_EXTRA_FILES := \
- $(PRODUCT_OUT)/system-qemu-config.txt \
- $(PRODUCT_OUT)/ramdisk.img \
- $(PRODUCT_OUT)/misc_info.txt \
-
-ifeq ($(filter sdk_gphone_%, $(TARGET_PRODUCT)),)
-ifeq ($(TARGET_BUILD_VARIANT),user)
-EMU_EXTRA_FILES += device/generic/goldfish/data/etc/user/advancedFeatures.ini
-else
-EMU_EXTRA_FILES += device/generic/goldfish/data/etc/advancedFeatures.ini
-endif
-else
-ifeq ($(TARGET_BUILD_VARIANT),user)
-EMU_EXTRA_FILES += device/generic/goldfish/data/etc/google/user/advancedFeatures.ini
-else
-EMU_EXTRA_FILES += device/generic/goldfish/data/etc/google/userdebug/advancedFeatures.ini
-endif
-endif
-
-EMU_EXTRA_FILES += device/generic/goldfish/data/etc/config.ini
-EMU_EXTRA_FILES += device/generic/goldfish/data/etc/encryptionkey.img
-EMU_EXTRA_FILES += device/generic/goldfish/data/etc/userdata.img
-
-name := emu-extra-linux-system-images-$(FILE_NAME_TAG)
-
-EMU_EXTRA_TARGET := $(PRODUCT_OUT)/$(name).zip
-
-EMULATOR_KERNEL_ARCH := $(TARGET_ARCH)
-EMULATOR_KERNEL_DIST_NAME := kernel-ranchu
-EMULATOR_KERNEL_VERSION := 3.18
-
-# Use 64-bit kernel even for 32-bit Android
-ifeq ($(TARGET_ARCH), x86)
-EMULATOR_KERNEL_ARCH := x86_64
-EMULATOR_KERNEL_DIST_NAME := kernel-ranchu-64
-endif
-ifeq ($(TARGET_ARCH), arm)
-EMULATOR_KERNEL_ARCH := arm64
-EMULATOR_KERNEL_DIST_NAME := kernel-ranchu-64
-endif
-
-# Below should be the same as PRODUCT_KERNEL_VERSION set in
-# device/generic/goldfish/arm*-vendor.mk
-ifneq ($(filter $(TARGET_ARCH), arm arm64),)
-EMULATOR_KERNEL_VERSION := 4.4
-endif
-# Below should be the same as PRODUCT_KERNEL_VERSION set in
-# device/generic/goldfish/x86*-vendor.mk
-ifneq ($(filter $(TARGET_ARCH), x86 x86_64),)
-EMULATOR_KERNEL_VERSION := 4.14
-endif
-
-EMULATOR_KERNEL_FILE := prebuilts/qemu-kernel/$(EMULATOR_KERNEL_ARCH)/$(EMULATOR_KERNEL_VERSION)/kernel-qemu2
-
-$(EMU_EXTRA_TARGET): PRIVATE_PACKAGE_SRC := \
- $(call intermediates-dir-for, PACKAGING, emu_extra_target)
-
-$(EMU_EXTRA_TARGET): $(EMU_EXTRA_FILES) $(EMULATOR_KERNEL_FILE) $(AVBTOOL) $(SOONG_ZIP)
- @echo "Package: $@"
- rm -rf $@ $(PRIVATE_PACKAGE_SRC)
- mkdir -p $(PRIVATE_PACKAGE_SRC)/$(TARGET_ARCH)/prebuilts/qemu-kernel/$(TARGET_ARCH)
- touch $(PRIVATE_PACKAGE_SRC)/$(TARGET_ARCH)/prebuilts/qemu-kernel/$(TARGET_ARCH)/kernel-qemu
- $(foreach f,$(EMU_EXTRA_FILES), cp $(f) $(PRIVATE_PACKAGE_SRC)/$(TARGET_ARCH)/$(notdir $(f)) &&) true
- cp $(EMULATOR_KERNEL_FILE) $(PRIVATE_PACKAGE_SRC)/$(TARGET_ARCH)/${EMULATOR_KERNEL_DIST_NAME}
- cp -r $(PRODUCT_OUT)/data $(PRIVATE_PACKAGE_SRC)/$(TARGET_ARCH)
- mkdir -p $(PRIVATE_PACKAGE_SRC)/$(TARGET_ARCH)/system
- cp $(PRODUCT_OUT)/system/build.prop $(PRIVATE_PACKAGE_SRC)/$(TARGET_ARCH)/system
- $(AVBTOOL) make_vbmeta_image --flag 2 --padding_size 4096 --output $(PRIVATE_PACKAGE_SRC)/$(TARGET_ARCH)/vbmeta-disabled.img
- $(SOONG_ZIP) -o $@ -C $(PRIVATE_PACKAGE_SRC) -D $(PRIVATE_PACKAGE_SRC)/$(TARGET_ARCH)
-
-.PHONY: emu_extra_imgs
-emu_extra_imgs: $(EMU_EXTRA_TARGET)
-
-$(call dist-for-goals, emu_extra_imgs, $(EMU_EXTRA_TARGET))
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
-endif
diff --git a/tools/extract_head_tail.sh b/tools/extract_head_tail.sh
deleted file mode 100755
index 5941da74..00000000
--- a/tools/extract_head_tail.sh
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/bin/bash
-
-set -e
-
-if [ "$#" -ne 3 ]; then
- echo "$0 src.img head.img tail.img" >&2
- exit 1
-fi
-
-srcimg=$1
-headimg=$2
-tailimg=$3
-
-disksize=$(stat -c %s $srcimg)
-
-mycount=`expr $disksize \/ 1024 \/ 1024 - 1`
-
-dd if=$srcimg of=$headimg ibs=1M obs=1M count=1
-dd if=$srcimg of=$tailimg ibs=1M obs=1M count=1 skip=$mycount
-#dd if=/dev/zero of=file.txt count=3083 bs=1M
diff --git a/tools/mk_combined_img.py b/tools/mk_combined_img.py
index 1e35dc67..1b7bbff0 100755
--- a/tools/mk_combined_img.py
+++ b/tools/mk_combined_img.py
@@ -1,33 +1,26 @@
#!/usr/bin/python
-
-from __future__ import print_function
-
-import argparse
-import codecs
-import operator
-import os
import sys
+import os
from subprocess import Popen, PIPE
from tempfile import mkstemp
+import argparse
+import operator
def check_sparse(filename):
magic = 3978755898
with open(filename, 'rb') as i:
word = i.read(4)
- if magic == int(codecs.encode(word[::-1], 'hex'), 16):
+ if magic == int(word[::-1].encode('hex'), 16):
return True
return False
-
def shell_command(comm_list):
- command = Popen(comm_list, stdout=PIPE, stderr=PIPE)
- command.communicate()
- command.wait()
+ command = Popen(comm_list)
+ execute = command.wait()
if command.returncode != 0:
sys.exit(1)
-
def parse_input(input_file):
parsed_lines = list()
lines = input_file.readlines()
@@ -46,27 +39,24 @@ def parse_input(input_file):
num_used = set()
for line in parsed_lines:
partition_info = dict()
- partition_info["path"] = line[0]
+ partition_info["path"] = line[0]
partition_info["label"] = line[1]
- # round up by 1M
- sizeByMb = str((1024 * 1024 - 1 + os.path.getsize(line[0])) / 1024 / 1024)
- partition_info["sizeByMb"] = sizeByMb
try:
partition_info["num"] = int(line[2])
except ValueError:
- print("'%s' cannot be converted to int" % (line[2]))
+ print "'%s' cannot be converted to int" % (line[2])
sys.exit(1)
# check if the partition number is out of range
if partition_info["num"] > len(lines) or partition_info["num"] < 0:
- print("Invalid partition number: %d, range [1..%d]" % \
- (partition_info["num"], len(lines)))
+ print "Invalid partition number: %d, range [1..%d]" % \
+ (partition_info["num"], len(lines))
sys.exit(1)
# check if the partition number is duplicated
if partition_info["num"] in num_used:
- print("Duplicated partition number:%d" % (partition_info["num"]))
+ print "Duplicated partition number:%d" % (partition["num"])
sys.exit(1)
num_used.add(partition_info["num"])
partitions.append(partition_info)
@@ -74,47 +64,42 @@ def parse_input(input_file):
partitions.sort(key=operator.itemgetter("num"))
return partitions
-
def write_partition(partition, output_file, offset):
# $ dd if=/path/to/image of=/path/to/output conv=notrunc,sync \
# ibs=1024k obs=1024k seek=<offset>
- dd_comm = ['dd', 'if=' + partition["path"], 'of=' + output_file, 'conv=notrunc,sync',
- 'ibs=1024k', 'obs=1024k', 'seek=' + str(offset)]
+ dd_comm = ['dd', 'if='+partition["path"], 'of='+output_file,'conv=notrunc,sync',
+ 'ibs=1024k','obs=1024k', 'seek='+str(offset)]
shell_command(dd_comm)
return
-
def unsparse_partition(partition):
# if the input image is in sparse format, unsparse it
simg2img = os.environ.get('SIMG2IMG', 'simg2img')
- print("Unsparsing %s" % (partition["path"]), end=' ')
+ print "Unsparsing %s" % (partition["path"]),
partition["fd"], temp_file = mkstemp()
shell_command([simg2img, partition["path"], temp_file])
partition["path"] = temp_file
- print("Done")
+ print "Done"
return
-
def clear_partition_table(filename):
sgdisk = os.environ.get('SGDISK', 'sgdisk')
- print("%s --clear %s" % (sgdisk, filename))
+ print "%s --clear %s" % (sgdisk, filename)
shell_command([sgdisk, '--clear', filename])
return
-
def add_partition(partition, output_file):
sgdisk = os.environ.get('SGDISK', 'sgdisk')
num = str(partition["num"])
- new_comm = '--new=' + num + ':' + partition["start"] + ':' + partition["end"]
- type_comm = '--type=' + num + ':8300'
- name_comm = '--change-name=' + num + ':' + partition["label"]
+ new_comm = '--new='+num+':'+partition["start"]+':'+partition["end"]
+ type_comm = '--type='+num+':8300'
+ name_comm = '--change-name='+num+':'+partition["label"]
# build partition table in order. for example:
# $ sgdisk --new=1:2048:5244927 --type=1:8300 --change-name=1:system \
# /path/to/output
shell_command([sgdisk, new_comm, type_comm, name_comm, output_file])
return
-
def main():
# check usage:
parser = argparse.ArgumentParser()
@@ -123,19 +108,15 @@ def main():
default="image_config")
parser.add_argument("-o", "--output",
type=str, help="output filename",
- default=os.environ.get("OUT", ".") + "/combined.img")
+ default=os.environ.get("OUT", ".")+"/combined.img")
args = parser.parse_args()
output_filename = os.path.expandvars(args.output)
- # remove the output_filename.qcow2
- print("removing " + output_filename + ".qcow2")
- shell_command(['rm', '-rf', output_filename + ".qcow2"])
-
# check input file
config_filename = args.input
if not os.path.exists(config_filename):
- print("Invalid config file name " + config_filename)
+ print "Invalid config file name " + config_filename
sys.exit(1)
# read input file
@@ -143,57 +124,29 @@ def main():
partitions = parse_input(config)
config.close()
- # take a shortcut in build environment
- if os.path.exists(output_filename) and len(partitions) == 2:
- print("updating " + output_filename + " ...")
- shell_command(['dd', "if=" + partitions[0]["path"], "of=" + output_filename,
- "conv=notrunc,sync", "ibs=1024k", "obs=1024k", "seek=1"])
- shell_command(['dd', "if=" + partitions[1]["path"], "of=" + output_filename,
- "conv=notrunc,sync", "ibs=1024k", "obs=1024k", "seek=2"])
- print("done")
- sys.exit(0)
- elif len(partitions) == 2:
- gptprefix = partitions[0]["sizeByMb"] + "_" + partitions[1]["sizeByMb"]
- prebuilt_gpt_dir = os.path.dirname(os.path.abspath( __file__ )) + "/prebuilt/gpt/" + gptprefix
- gpt_head = prebuilt_gpt_dir + "/head.img"
- gpt_tail = prebuilt_gpt_dir + "/head.img"
- if os.path.exists(gpt_head) and os.path.exists(gpt_tail):
- print("found prebuilt gpt header and footer, use it")
- shell_command(['dd', "if=" + gpt_head, "of=" + output_filename, "bs=1024k",
- "conv=notrunc,sync", "count=1"])
- shell_command(['dd', "if=" + partitions[0]["path"], "of=" + output_filename,
- "bs=1024k", "conv=notrunc,sync", "seek=1"])
- shell_command(['dd', "if=" + partitions[1]["path"], "of=" + output_filename,
- "bs=1024k", "conv=notrunc,sync", "seek=" + str(1 + int(partitions[0]["sizeByMb"]))])
- shell_command(['dd', "if=" + gpt_tail, "of=" + output_filename,
- "bs=1024k", "conv=notrunc,sync",
- "seek=" + str(1 + int(partitions[0]["sizeByMb"]) + int(partitions[1]["sizeByMb"]))])
- print("done")
- sys.exit(0)
-
# combine the images
# add padding
- shell_command(['dd', 'if=/dev/zero', 'of=' + output_filename, 'ibs=1024k', 'count=1'])
+ shell_command(['dd', 'if=/dev/zero', 'of='+output_filename, 'ibs=1024k', 'count=1'])
for partition in partitions:
offset = os.path.getsize(output_filename)
- partition["start"] = str(offset // 512)
+ partition["start"] = str(offset / 512)
# dectect sparse file format
if check_sparse(partition["path"]):
unsparse_partition(partition)
# TODO: extract the partition if the image file is already formatted
- write_partition(partition, output_filename, offset // 1024 // 1024)
+ write_partition(partition, output_filename, offset/1024/1024)
offset = os.path.getsize(output_filename)
- partition["end"] = str(offset // 512 - 1)
+ partition["end"] = str(offset / 512 - 1)
# add padding
# $ dd if=/dev/zero of=/path/to/output conv=notrunc bs=1 \
# count=1024k seek=<offset>
- offset = os.path.getsize(output_filename) // 1024 // 1024
- shell_command(['dd', 'if=/dev/zero', 'of=' + output_filename,
- 'conv=notrunc', 'bs=1024k', 'count=1', 'seek=' + str(offset)])
+ offset = os.path.getsize(output_filename) / 1024 / 1024
+ shell_command(['dd', 'if=/dev/zero', 'of='+output_filename,
+ 'conv=notrunc', 'bs=1024k', 'count=1', 'seek='+str(offset)])
# make partition table
# $ sgdisk --clear /path/to/output
@@ -206,6 +159,6 @@ def main():
os.close(partition["fd"])
os.remove(partition["path"])
-
if __name__ == "__main__":
main()
+
diff --git a/tools/mk_qemu_image.sh b/tools/mk_qemu_image.sh
index 87e0a8a3..0f26173c 100755
--- a/tools/mk_qemu_image.sh
+++ b/tools/mk_qemu_image.sh
@@ -32,7 +32,14 @@ fi
dd if=/dev/zero of=$target ibs=1024k count=1 > /dev/null 2>&1
dd if=$srcimg of=$target conv=notrunc,sync ibs=1024k obs=1024k seek=1 > /dev/null 2>&1
unamestr=`uname`
+if [[ "$unamestr" == 'Linux' ]]; then
curdisksize=$(stat -c %s $target)
+elif [[ "$unamestr" == 'Darwin' ]]; then
+curdisksize=$(stat -f %z $target)
+else
+echo "Cannot determine OS type, quit"
+exit 1
+fi
dd if=/dev/zero of=$target conv=notrunc bs=1 count=1024k seek=$curdisksize > /dev/null 2>&1
diff --git a/tools/mk_vbmeta_boot_params.sh b/tools/mk_vbmeta_boot_params.sh
index e436923a..17a39e8e 100755
--- a/tools/mk_vbmeta_boot_params.sh
+++ b/tools/mk_vbmeta_boot_params.sh
@@ -2,7 +2,7 @@
if [ $# -ne 3 ]; then
echo "Usage: $0 <vbmeta.img> <system.img> <VbmetaBootParams.textproto>"
- exit 0
+ exit 1
fi
# Example Output from 'avbtool calculate_vbmeta_digest --image $OUT/vbmeta.img':
@@ -42,11 +42,14 @@ readonly TARGET=$3
# Extract the digest
readonly VBMETA_DIGEST=$(${AVBTOOL:-avbtool} calculate_vbmeta_digest --image $VBMETAIMG)
+echo "digest is $VBMETA_DIGEST"
readonly INFO_OUTPUT=$(${AVBTOOL:-avbtool} info_image --image $VBMETAIMG | grep "^Algorithm:")
+echo "output is $INFO_OUTPUT"
# Extract the algorithm
readonly ALG_OUTPUT=$(echo $INFO_OUTPUT | grep "Algorithm:")
+echo \"$ALG_OUTPUT\"
readonly ALG_SPLIT=($(echo $ALG_OUTPUT | tr ' ' '\n'))
readonly ORG_ALGORITHM=${ALG_SPLIT[1]}
@@ -56,6 +59,7 @@ else
die "Don't know anything about $ORG_ALGORITHM"
fi
+echo "hash algorithm is $VBMETA_HASH_ALG"
# extract the size
@@ -73,6 +77,7 @@ SYSMETA_SIZE=$(get_bytes $SYSIMG "VBMeta size:")
VBMETA_SIZE=$(expr $HEADER_SIZE + $AUTHEN_SIZE + $AUX_SIZE + $SYSMETA_SIZE)
+echo "vbmeta size $VBMETA_SIZE"
HEADER_COMMENT="# androidboot.vbmeta.size=$VBMETA_SIZE androidboot.vbmeta.hash_alg=$VBMETA_HASH_ALG androidboot.vbmeta.digest=$VBMETA_DIGEST"
diff --git a/tools/prebuilt/gpt/1_3080/head.img b/tools/prebuilt/gpt/1_3080/head.img
deleted file mode 100644
index f16ea54e..00000000
--- a/tools/prebuilt/gpt/1_3080/head.img
+++ /dev/null
Binary files differ
diff --git a/tools/prebuilt/gpt/1_3080/tail.img b/tools/prebuilt/gpt/1_3080/tail.img
deleted file mode 100644
index 2f698290..00000000
--- a/tools/prebuilt/gpt/1_3080/tail.img
+++ /dev/null
Binary files differ
diff --git a/ueventd.goldfish.rc b/ueventd.goldfish.rc
index 0335d0b1..8674767a 100644
--- a/ueventd.goldfish.rc
+++ b/ueventd.goldfish.rc
@@ -4,3 +4,4 @@
/dev/goldfish_pipe 0666 system system
/dev/goldfish_address_space 0666 system system
/dev/ttyS* 0666 system system
+/proc 0666 system system
diff --git a/ueventd.ranchu.rc b/ueventd.ranchu.rc
index db426342..0ad6230b 100644
--- a/ueventd.ranchu.rc
+++ b/ueventd.ranchu.rc
@@ -2,8 +2,6 @@
/dev/qemu_trace 0666 system system
/dev/goldfish_pipe 0666 system system
/dev/ttyS* 0666 system system
+/proc 0666 system system
/dev/goldfish_sync 0666 system system
/dev/goldfish_address_space 0666 system system
-/dev/dri/card0 0660 system graphics
-/dev/dri/controlD64 0660 system graphics
-/dev/dri/renderD128 0666 system graphics
diff --git a/vendor.mk b/vendor.mk
index 2daf114c..16e7e50e 100644
--- a/vendor.mk
+++ b/vendor.mk
@@ -17,45 +17,31 @@
# This file is to configure vendor/data partitions of emulator-related products
#
-ifeq ($(QEMU_DISABLE_AVB),true)
- ifeq ($(QEMU_USE_SYSTEM_EXT_PARTITIONS),true)
- PRODUCT_COPY_FILES += \
- device/generic/goldfish/data/etc/dummy.vbmeta.img:$(PRODUCT_OUT)/vbmeta.img \
- device/generic/goldfish/fstab.ranchu.initrd.noavb.ex:$(TARGET_COPY_OUT_RAMDISK)/fstab.ranchu \
- device/generic/goldfish/fstab.ranchu.noavb.ex:$(TARGET_COPY_OUT_VENDOR)/etc/fstab.ranchu
- else
- PRODUCT_COPY_FILES += \
- device/generic/goldfish/data/etc/dummy.vbmeta.img:$(PRODUCT_OUT)/vbmeta.img \
- device/generic/goldfish/fstab.ranchu.initrd.noavb:$(TARGET_COPY_OUT_RAMDISK)/fstab.ranchu \
- device/generic/goldfish/fstab.ranchu.noavb:$(TARGET_COPY_OUT_VENDOR)/etc/fstab.ranchu
- endif
-endif
-
-ifeq ($(QEMU_USE_SYSTEM_EXT_PARTITIONS),true)
-PRODUCT_COPY_FILES += \
- device/generic/goldfish/fstab.ranchu.initrd.ex:$(TARGET_COPY_OUT_RAMDISK)/fstab.ranchu \
- device/generic/goldfish/fstab.ranchu.ex:$(TARGET_COPY_OUT_VENDOR)/etc/fstab.ranchu
-endif
-
-
-DISABLE_RILD_OEM_HOOK := true
-
-DEVICE_MANIFEST_FILE := device/generic/goldfish/manifest.xml
-
# Device modules
PRODUCT_PACKAGES += \
vulkan.ranchu \
gralloc.goldfish \
gralloc.goldfish.default \
gralloc.ranchu \
- libandroidemu \
+ libGLESv1_CM_emulation \
+ lib_renderControl_enc \
+ libEGL_emulation \
+ libGLESv2_enc \
+ libvulkan_enc \
libOpenglCodecCommon \
libOpenglSystemCommon \
+ libGLESv2_emulation \
+ libGLESv1_enc \
libEGL_swiftshader \
libGLESv1_CM_swiftshader \
libGLESv2_swiftshader \
libgoldfish-ril \
qemu-props \
+ camera.goldfish \
+ camera.goldfish.jpeg \
+ camera.ranchu \
+ camera.ranchu.jpeg \
+ gatekeeper.ranchu \
gps.goldfish \
gps.ranchu \
fingerprint.goldfish \
@@ -64,8 +50,9 @@ PRODUCT_PACKAGES += \
power.goldfish \
power.ranchu \
fingerprint.ranchu \
- android.hardware.graphics.composer@2.3-impl \
- android.hardware.graphics.composer@2.3-service \
+ sensors.ranchu \
+ android.hardware.graphics.composer@2.1-impl \
+ android.hardware.graphics.composer@2.1-service \
android.hardware.graphics.allocator@2.0-service \
android.hardware.graphics.allocator@2.0-impl \
android.hardware.graphics.mapper@2.0-impl \
@@ -76,23 +63,10 @@ PRODUCT_PACKAGES += \
android.hardware.wifi@1.0-service \
android.hardware.biometrics.fingerprint@2.1-service \
sh_vendor \
- ip_vendor \
iw_vendor \
audio.r_submix.default \
local_time.default \
- SdkSetup \
- MultiDisplayProvider
-
-ifneq ($(BUILD_EMULATOR_OPENGL),false)
-PRODUCT_PACKAGES += \
- libGLESv1_CM_emulation \
- lib_renderControl_enc \
- libEGL_emulation \
- libGLESv2_enc \
- libvulkan_enc \
- libGLESv2_emulation \
- libGLESv1_enc
-endif
+ SdkSetup
PRODUCT_PACKAGES += \
android.hardware.audio@4.0-impl:32 \
@@ -105,8 +79,8 @@ PRODUCT_PACKAGES += \
android.hardware.health@2.0-service.goldfish
PRODUCT_PACKAGES += \
- android.hardware.keymaster@4.0-impl \
- android.hardware.keymaster@4.0-service
+ android.hardware.keymaster@3.0-impl \
+ android.hardware.keymaster@3.0-service
PRODUCT_PACKAGES += \
DisplayCutoutEmulationEmu01Overlay
@@ -115,16 +89,12 @@ ifneq ($(EMULATOR_VENDOR_NO_GNSS),true)
PRODUCT_PACKAGES += \
android.hardware.gnss@1.0-service \
android.hardware.gnss@1.0-impl
-DEVICE_MANIFEST_FILE += device/generic/goldfish/manifest.gnss.xml
endif
-ifneq ($(EMULATOR_VENDOR_NO_SENSORS),true)
+
PRODUCT_PACKAGES += \
android.hardware.sensors@1.0-impl \
- android.hardware.sensors@1.0-service \
- sensors.ranchu
-DEVICE_MANIFEST_FILE += device/generic/goldfish/manifest.sensors.xml
-endif
+ android.hardware.sensors@1.0-service
PRODUCT_PACKAGES += \
android.hardware.drm@1.0-service \
@@ -137,41 +107,42 @@ PRODUCT_PACKAGES += \
PRODUCT_PROPERTY_OVERRIDES += ro.control_privapp_permissions=enforce
PRODUCT_PROPERTY_OVERRIDES += ro.hardware.power=ranchu
+PRODUCT_PROPERTY_OVERRIDES += ro.crypto.volume.filenames_mode=aes-256-cts
PRODUCT_PROPERTY_OVERRIDES += persist.sys.zram_enabled=1 \
-ifneq ($(EMULATOR_VENDOR_NO_CAMERA),true)
PRODUCT_PACKAGES += \
camera.device@1.0-impl \
android.hardware.camera.provider@2.4-service \
android.hardware.camera.provider@2.4-impl \
- camera.goldfish \
- camera.goldfish.jpeg \
- camera.ranchu \
- camera.ranchu.jpeg
-DEVICE_MANIFEST_FILE += device/generic/goldfish/manifest.camera.xml
-endif
PRODUCT_PACKAGES += \
- android.hardware.gatekeeper@1.0-service.software
+ android.hardware.gatekeeper@1.0-impl \
+ android.hardware.gatekeeper@1.0-service
# WiFi: vendor side
PRODUCT_PACKAGES += \
createns \
dhcpclient \
+ dhcpserver \
execns \
hostapd \
hostapd_nohidl \
+ ipv6proxy \
netmgr \
- wifi_forwarder \
wpa_supplicant \
PRODUCT_PACKAGES += android.hardware.thermal@2.0-service.mock
+# Needed for /system/priv-app/SdkSetup/SdkSetup.apk to pass CTS android.permission2.cts.PrivappPermissionsTest.
+PRODUCT_COPY_FILES += \
+ device/generic/goldfish/data/etc/permissions/privapp-permissions-goldfish.xml:$(TARGET_COPY_OUT_SYSTEM)/etc/permissions/privapp-permissions-goldfish.xml
+
# Goldfish does not support ION needed for Codec 2.0
PRODUCT_PROPERTY_OVERRIDES += \
debug.stagefright.ccodec=0
+
PRODUCT_COPY_FILES += \
device/generic/goldfish/fstab.ranchu.initrd:$(TARGET_COPY_OUT_RAMDISK)/fstab.ranchu \
device/generic/goldfish/data/etc/apns-conf.xml:data/misc/apns/apns-conf.xml \
@@ -183,8 +154,6 @@ PRODUCT_COPY_FILES += \
device/generic/goldfish/fstab.ranchu:$(TARGET_COPY_OUT_VENDOR)/etc/fstab.ranchu \
device/generic/goldfish/ueventd.ranchu.rc:$(TARGET_COPY_OUT_VENDOR)/ueventd.rc \
device/generic/goldfish/input/goldfish_rotary.idc:$(TARGET_COPY_OUT_VENDOR)/usr/idc/goldfish_rotary.idc \
- device/generic/goldfish/input/qwerty2.idc:$(TARGET_COPY_OUT_VENDOR)/usr/idc/qwerty2.idc \
- device/generic/goldfish/input/qwerty.kl:$(TARGET_COPY_OUT_VENDOR)/usr/keylayout/qwerty.kl \
device/generic/goldfish/input/virtio_input_multi_touch_1.idc:$(TARGET_COPY_OUT_VENDOR)/usr/idc/virtio_input_multi_touch_1.idc \
device/generic/goldfish/input/virtio_input_multi_touch_2.idc:$(TARGET_COPY_OUT_VENDOR)/usr/idc/virtio_input_multi_touch_2.idc \
device/generic/goldfish/input/virtio_input_multi_touch_3.idc:$(TARGET_COPY_OUT_VENDOR)/usr/idc/virtio_input_multi_touch_3.idc \
@@ -196,6 +165,7 @@ PRODUCT_COPY_FILES += \
device/generic/goldfish/input/virtio_input_multi_touch_9.idc:$(TARGET_COPY_OUT_VENDOR)/usr/idc/virtio_input_multi_touch_9.idc \
device/generic/goldfish/input/virtio_input_multi_touch_10.idc:$(TARGET_COPY_OUT_VENDOR)/usr/idc/virtio_input_multi_touch_10.idc \
device/generic/goldfish/input/virtio_input_multi_touch_11.idc:$(TARGET_COPY_OUT_VENDOR)/usr/idc/virtio_input_multi_touch_11.idc \
+ device/generic/goldfish/manifest.xml:$(TARGET_COPY_OUT_VENDOR)/manifest.xml \
device/generic/goldfish/data/etc/config.ini:config.ini \
device/generic/goldfish/wifi/simulated_hostapd.conf:$(TARGET_COPY_OUT_VENDOR)/etc/simulated_hostapd.conf \
device/generic/goldfish/wifi/wpa_supplicant.conf:$(TARGET_COPY_OUT_VENDOR)/etc/wifi/wpa_supplicant.conf \
@@ -206,8 +176,7 @@ PRODUCT_COPY_FILES += \
device/generic/goldfish/camera/media_profiles.xml:$(TARGET_COPY_OUT_VENDOR)/etc/media_profiles_V1_0.xml \
frameworks/av/media/libstagefright/data/media_codecs_google_audio.xml:$(TARGET_COPY_OUT_VENDOR)/etc/media_codecs_google_audio.xml \
frameworks/av/media/libstagefright/data/media_codecs_google_telephony.xml:$(TARGET_COPY_OUT_VENDOR)/etc/media_codecs_google_telephony.xml \
- device/generic/goldfish/camera/media_codecs_google_video_default.xml:data/vendor/etc/media_codecs_google_video_default.xml \
- device/generic/goldfish/camera/media_codecs_google_video_v2.xml:data/vendor/etc/media_codecs_google_video_v2.xml \
+ device/generic/goldfish/camera/media_codecs_google_video.xml:$(TARGET_COPY_OUT_VENDOR)/etc/media_codecs_google_video.xml \
device/generic/goldfish/camera/media_codecs.xml:$(TARGET_COPY_OUT_VENDOR)/etc/media_codecs.xml \
device/generic/goldfish/camera/media_codecs_performance.xml:$(TARGET_COPY_OUT_VENDOR)/etc/media_codecs_performance.xml \
frameworks/native/data/etc/android.hardware.touchscreen.multitouch.jazzhand.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.touchscreen.multitouch.jazzhand.xml \
@@ -215,11 +184,8 @@ PRODUCT_COPY_FILES += \
frameworks/native/data/etc/android.hardware.camera.autofocus.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.camera.autofocus.xml \
frameworks/native/data/etc/android.hardware.camera.full.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.camera.full.xml \
frameworks/native/data/etc/android.hardware.fingerprint.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.fingerprint.xml \
- frameworks/native/data/etc/android.hardware.vulkan.level-1.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.vulkan.level.xml \
- frameworks/native/data/etc/android.hardware.vulkan.compute-0.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.vulkan.compute.xml \
- frameworks/native/data/etc/android.hardware.vulkan.version-1_1.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.vulkan.version.xml \
frameworks/native/data/etc/android.software.autofill.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.software.autofill.xml \
- frameworks/native/data/etc/android.software.verified_boot.xml:${TARGET_COPY_OUT_PRODUCT}/etc/permissions/android.software.verified_boot.xml \
+ frameworks/native/data/etc/android.software.verified_boot.xml:system/etc/permissions/android.software.verified_boot.xml \
frameworks/av/media/libeffects/data/audio_effects.xml:$(TARGET_COPY_OUT_VENDOR)/etc/audio_effects.xml \
device/generic/goldfish/audio_policy.conf:$(TARGET_COPY_OUT_VENDOR)/etc/audio_policy.conf \
frameworks/av/services/audiopolicy/config/audio_policy_configuration_generic.xml:$(TARGET_COPY_OUT_VENDOR)/etc/audio_policy_configuration.xml \
@@ -228,4 +194,3 @@ PRODUCT_COPY_FILES += \
frameworks/av/services/audiopolicy/config/audio_policy_volumes.xml:$(TARGET_COPY_OUT_VENDOR)/etc/audio_policy_volumes.xml \
frameworks/av/services/audiopolicy/config/default_volume_tables.xml:$(TARGET_COPY_OUT_VENDOR)/etc/default_volume_tables.xml \
frameworks/av/services/audiopolicy/config/surround_sound_configuration_5_0.xml:$(TARGET_COPY_OUT_VENDOR)/etc/surround_sound_configuration_5_0.xml \
- device/generic/goldfish/data/etc/permissions/privapp-permissions-goldfish.xml:$(TARGET_COPY_OUT_PRODUCT)/etc/permissions/privapp-permissions-goldfish.xml
diff --git a/wifi/createns/createns.cpp b/wifi/createns/createns.cpp
index 95aff530..66f6dd3d 100644
--- a/wifi/createns/createns.cpp
+++ b/wifi/createns/createns.cpp
@@ -103,8 +103,8 @@ static bool writeNamespacePid(const char* name, pid_t pid) {
path += ".pid";
Fd fd(::open(path.c_str(),
- O_CREAT | O_TRUNC | O_WRONLY | O_CLOEXEC,
- S_IRUSR | S_IWUSR | S_IRGRP));
+ O_CREAT | O_EXCL | O_WRONLY | O_CLOEXEC,
+ S_IRUSR | S_IRGRP | S_IROTH));
if (fd.get() == -1) {
ALOGE("Unable to create file '%s': %s", path.c_str(), strerror(errno));
return false;
@@ -223,7 +223,6 @@ int main(int argc, char* argv[]) {
ALOGE("Failed to create pipe: %s", strerror(errno));
return 1;
}
-
Fd readPipe(fds[0]);
Fd writePipe(fds[1]);
@@ -240,8 +239,7 @@ int main(int argc, char* argv[]) {
}
{
// Open and then immediately close the fd
- Fd fd(::open(path.c_str(), O_CREAT | O_TRUNC | O_RDONLY | O_CLOEXEC,
- S_IRUSR | S_IWUSR | S_IRGRP));
+ Fd fd(::open(path.c_str(), O_CREAT | O_EXCL | O_RDONLY | O_CLOEXEC, 0));
if (fd.get() == -1) {
ALOGE("Failed to open file %s: %s", path.c_str(), strerror(errno));
return 1;
diff --git a/wifi/init.wifi.sh b/wifi/init.wifi.sh
index fd84d12d..ff64e91f 100755
--- a/wifi/init.wifi.sh
+++ b/wifi/init.wifi.sh
@@ -42,43 +42,70 @@
#
NAMESPACE="router"
+rm -rf /data/vendor/var/run/netns/${NAMESPACE}
+rm -rf /data/vendor/var/run/netns/${NAMESPACE}.pid
+# Lower the MTU of the WiFi interface to prevent issues with packet injection.
+# The MTU of the WiFi monitor interface cannot be higher than 1500 but injection
+# requires extra space for injection headers which count against the MTU. So if
+# a 1500 byte payload needs to be injected it will fail because with the
+# additional headers the total amount of data will exceed 1500 bytes. This way
+# the payload is restricted to a smaller size that should leave room for the
+# injection headers.
+/system/bin/ip link set wlan0 mtu 1400
createns ${NAMESPACE}
+# If this is a clean boot we need to copy the hostapd configuration file to the
+# data partition where netmgr can change it if needed. If it already exists we
+# need to preserve the existing settings.
+if [ ! -f /data/vendor/wifi/hostapd/hostapd.conf ]; then
+ cp /vendor/etc/simulated_hostapd.conf /data/vendor/wifi/hostapd/hostapd.conf
+ chown wifi:wifi /data/vendor/wifi/hostapd/hostapd.conf
+ chmod 660 /data/vendor/wifi/hostapd/hostapd.conf
+fi
+
# createns will have created a file that contains the process id (pid) of a
# process running in the network namespace. This pid is needed for some commands
# to access the namespace.
-PID=$(</data/vendor/var/run/netns/${NAMESPACE}.pid)
+PID=$(cat /data/vendor/var/run/netns/${NAMESPACE}.pid)
-/vendor/bin/ip link set eth0 netns ${PID}
+# Move the WiFi monitor interface to the other namespace and bring it up. This
+# is what we use for injecting WiFi frames from the outside world.
+/system/bin/ip link set hwsim0 netns ${PID}
+execns ${NAMESPACE} /system/bin/ip link set hwsim0 up
-/vendor/bin/ip link add radio0 type veth peer name radio0-peer netns ${PID}
+# Start the network manager as soon as possible after the namespace is available.
+# This ensures that anything that follows is properly managed and monitored.
+setprop ctl.start netmgr
+/system/bin/ip link set eth0 netns ${PID}
+/system/bin/ip link add radio0 type veth peer name radio0-peer
+/system/bin/ip link set radio0-peer netns ${PID}
# Enable privacy addresses for radio0, this is done by the framework for wlan0
sysctl -wq net.ipv6.conf.radio0.use_tempaddr=2
-
-execns ${NAMESPACE} /vendor/bin/ip link set radio0-peer up
-
-execns ${NAMESPACE} /vendor/bin/ip link set eth0 up
-
-/vendor/bin/ip link set radio0 up
-
-execns ${NAMESPACE} /vendor/bin/ip link set wlan1 up
-
+/system/bin/ip addr add 192.168.200.2/24 broadcast 192.168.200.255 dev radio0
+execns ${NAMESPACE} /system/bin/ip addr add 192.168.200.1/24 dev radio0-peer
+execns ${NAMESPACE} sysctl -wq net.ipv6.conf.all.forwarding=1
+execns ${NAMESPACE} /system/bin/ip link set radio0-peer up
+# Start the dhcp client for eth0 to acquire an address
+setprop ctl.start dhcpclient_rtr
+# Create iptables entries. -w will cause an indefinite wait for the exclusive
+# lock. Without this flag iptables can sporadically fail if something else is
+# modifying the iptables at the same time. -W indicates the number of micro-
+# seconds between each retry. The default is one second which seems like a long
+# time. Keep this short so we don't slow down startup too much.
+execns ${NAMESPACE} /system/bin/iptables -w -W 50000 -t nat -A POSTROUTING -s 192.168.232.0/21 -o eth0 -j MASQUERADE
+execns ${NAMESPACE} /system/bin/iptables -w -W 50000 -t nat -A POSTROUTING -s 192.168.200.0/24 -o eth0 -j MASQUERADE
/vendor/bin/iw phy phy1 set netns $PID
-setprop ctl.start netmgr
-
-setprop ctl.start wifi_forwarder
-
-# If this is a clean boot we need to copy the hostapd configuration file to the
-# data partition where netmgr can change it if needed. If it already exists we
-# need to preserve the existing settings.
-if [ ! -f /data/vendor/wifi/hostapd/hostapd.conf ]; then
- cp /vendor/etc/simulated_hostapd.conf /data/vendor/wifi/hostapd/hostapd.conf
- chown wifi:wifi /data/vendor/wifi/hostapd/hostapd.conf
- chmod 660 /data/vendor/wifi/hostapd/hostapd.conf
-fi
-
+execns ${NAMESPACE} /system/bin/ip addr add 192.168.232.1/21 dev wlan1
+execns ${NAMESPACE} /system/bin/ip link set wlan1 mtu 1400
+execns ${NAMESPACE} /system/bin/ip link set wlan1 up
+# Start the IPv6 proxy that will enable use of IPv6 in the main namespace
+setprop ctl.start ipv6proxy
+execns ${NAMESPACE} sysctl -wq net.ipv4.ip_forward=1
# Start hostapd, the access point software
setprop ctl.start emu_hostapd
+# Start DHCP server for the wifi interface
+setprop ctl.start dhcpserver
+/system/bin/ip link set radio0 up
diff --git a/wifi/ipv6proxy/Android.mk b/wifi/ipv6proxy/Android.mk
new file mode 100644
index 00000000..a1695d6c
--- /dev/null
+++ b/wifi/ipv6proxy/Android.mk
@@ -0,0 +1,24 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ address.cpp \
+ interface.cpp \
+ log.cpp \
+ main.cpp \
+ namespace.cpp \
+ packet.cpp \
+ proxy.cpp \
+ router.cpp \
+ socket.cpp \
+
+
+LOCAL_CPPFLAGS += -Werror
+LOCAL_SHARED_LIBRARIES := libcutils liblog
+LOCAL_PROPRIETARY_MODULE := true
+LOCAL_MODULE := ipv6proxy
+
+LOCAL_MODULE_CLASS := EXECUTABLES
+
+include $(BUILD_EXECUTABLE)
diff --git a/wifi/ipv6proxy/address.cpp b/wifi/ipv6proxy/address.cpp
new file mode 100644
index 00000000..def9c7b8
--- /dev/null
+++ b/wifi/ipv6proxy/address.cpp
@@ -0,0 +1,109 @@
+/*
+ * 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 "address.h"
+
+#include <arpa/inet.h>
+#include <errno.h>
+#include <linux/if_ether.h>
+#include <linux/if_packet.h>
+#include <netdb.h>
+#include <net/if.h>
+#include <string.h>
+#include <sys/ioctl.h>
+
+#include "socket.h"
+
+std::string addrToStr(const struct in6_addr& addr) {
+ char buf[INET6_ADDRSTRLEN];
+ if (inet_ntop(AF_INET6, &addr, buf, sizeof(buf)) == nullptr) {
+ return "[unknown]";
+ }
+ return buf;
+}
+
+Address::Address() {
+ mStorage.reserve(sizeof(struct sockaddr_storage));
+}
+
+Address::Address(const struct sockaddr_nl& address)
+ : mStorage(sizeof(address)) {
+ memcpy(mStorage.data(), &address, sizeof(address));
+}
+Address::Address(const struct sockaddr_in6& address)
+ : mStorage(sizeof(address)) {
+ memcpy(mStorage.data(), &address, sizeof(address));
+}
+
+Address::Address(struct in6_addr address)
+ : mStorage(sizeof(struct sockaddr_in6)) {
+ auto sockaddr = reinterpret_cast<struct sockaddr_in6*>(mStorage.data());
+ sockaddr->sin6_family = AF_INET6;
+ sockaddr->sin6_addr = address;
+}
+
+void Address::reset() {
+ mStorage.resize(sizeof(struct sockaddr_storage));
+}
+
+Result Address::resolveInet(const std::string& address) {
+ struct addrinfo hints;
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_INET6;
+ hints.ai_socktype = SOCK_RAW;
+ struct addrinfo* addrinfo;
+ int res = ::getaddrinfo(address.c_str(), nullptr, &hints, &addrinfo);
+ if (res != 0) {
+ return Result::error(gai_strerror(res));
+ }
+ mStorage.resize(addrinfo->ai_addrlen);
+ memcpy(mStorage.data(), addrinfo->ai_addr, mStorage.size());
+ freeaddrinfo(addrinfo);
+
+ return Result::success();
+}
+
+Result Address::resolveEth(const std::string& interfaceName) {
+ mStorage.resize(sizeof(struct sockaddr_ll));
+ memset(mStorage.data(), 0, mStorage.size());
+ auto addr = reinterpret_cast<struct sockaddr_ll*>(mStorage.data());
+ addr->sll_family = AF_PACKET;
+ addr->sll_protocol = htons(ETH_P_IPV6);
+
+ unsigned int index = if_nametoindex(interfaceName.c_str());
+ if (index == 0) {
+ return Result::error(strerror(errno));
+ }
+ addr->sll_ifindex = index;
+
+ struct ifreq request;
+ memset(&request, 0, sizeof(request));
+ strncpy(request.ifr_name, interfaceName.c_str(), sizeof(request.ifr_name));
+ request.ifr_name[sizeof(request.ifr_name) - 1] = '\0';
+
+ Socket socket;
+ Result res = socket.open(AF_INET, SOCK_DGRAM, IPPROTO_IP);
+ if (!res) {
+ return res;
+ }
+ int status = ::ioctl(socket.get(), SIOCGIFHWADDR, &request);
+ if (status != 0) {
+ return Result::error(strerror(errno));
+ }
+ memcpy(addr->sll_addr, request.ifr_addr.sa_data, 6);
+
+ return Result::success();
+}
diff --git a/wifi/ipv6proxy/address.h b/wifi/ipv6proxy/address.h
new file mode 100644
index 00000000..f9cec0bd
--- /dev/null
+++ b/wifi/ipv6proxy/address.h
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ */
+#pragma once
+
+#include "result.h"
+
+#include <linux/netlink.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <string>
+#include <vector>
+
+// Convert an IPv6 address struct to a string for debugging purposes
+std::string addrToStr(const struct in6_addr& addr);
+
+// Represents any kind of address in a struct sockaddr.
+class Address {
+public:
+ Address();
+ explicit Address(const struct sockaddr_nl& address);
+ explicit Address(const struct sockaddr_in6& address);
+ explicit Address(struct in6_addr address);
+
+ template<typename T>
+ const T* get() const {
+ return reinterpret_cast<const T*>(mStorage.data());
+ }
+
+ template<typename T>
+ T* get() {
+ return reinterpret_cast<T*>(mStorage.data());
+ }
+
+ ssize_t size() const { return mStorage.size(); }
+
+ // Reset the address to be the max size possible for an address
+ void reset();
+
+ // Resolve |address| into an IPv6 address. |address| may be either a domain
+ // name or just a string containing a numeric address.
+ Result resolveInet(const std::string& address);
+ // Resolve |interfaceName| into a link layer address. This can be used to
+ // create a struct sockaddr_nl that can be used to listen on the given
+ // interface at the link layer.
+ Result resolveEth(const std::string& interfaceName);
+private:
+ std::vector<char> mStorage;
+};
+
diff --git a/wifi/ipv6proxy/interface.cpp b/wifi/ipv6proxy/interface.cpp
new file mode 100644
index 00000000..e9597ab5
--- /dev/null
+++ b/wifi/ipv6proxy/interface.cpp
@@ -0,0 +1,143 @@
+/*
+ * 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 "interface.h"
+
+#include <errno.h>
+#include <linux/if_ether.h>
+#include <net/if.h>
+#include <string.h>
+#include <sys/ioctl.h>
+
+#include "log.h"
+
+Interface::Interface(const std::string& name) : mName(name) {
+}
+
+bool Interface::init() {
+ // setAllMulti will set the ALLMULTI flag for the interface, this allows us
+ // to capture all the traffic needed to perform proxying.
+ return setAllMulti() &&
+ resolveAddresses() &&
+ configureIpSocket() &&
+ configureIcmpSocket();
+}
+
+bool Interface::setAllMulti() {
+ struct ifreq request;
+ memset(&request, 0, sizeof(request));
+ strncpy(request.ifr_name, mName.c_str(), sizeof(request.ifr_name));
+ request.ifr_name[sizeof(request.ifr_name) - 1] = '\0';
+
+ Socket socket;
+ Result res = socket.open(AF_INET, SOCK_DGRAM, IPPROTO_IP);
+ if (!res) {
+ loge("Failed to open IP socket for interface %s: %s\n",
+ mName.c_str(), strerror(errno));
+ return false;
+ }
+ int status = ::ioctl(socket.get(), SIOCGIFFLAGS, &request);
+ if (status != 0) {
+ loge("Failed to get interface flags for %s: %s\n",
+ mName.c_str(), strerror(errno));
+ return false;
+ }
+
+ if ((request.ifr_flags & IFF_ALLMULTI) != 0) {
+ // AllMulti is already enabled, nothing to do
+ return true;
+ }
+
+ request.ifr_flags |= IFF_ALLMULTI;
+
+ status = ::ioctl(socket.get(), SIOCSIFFLAGS, &request);
+ if (status != 0) {
+ loge("Failed to enable AllMulti flag for %s: %s\n",
+ mName.c_str(), strerror(errno));
+ return false;
+ }
+ return true;
+}
+
+bool Interface::resolveAddresses() {
+ Result res = mLinkAddr.resolveEth(mName);
+ if (!res) {
+ loge("Unable to resolve interface %s: %s\n",
+ mName.c_str(), res.c_str());
+ return false;
+ }
+ mIndex = if_nametoindex(mName.c_str());
+ if (mIndex == 0) {
+ loge("Unable to get interface index for '%s': %s\n",
+ mName.c_str(), strerror(errno));
+ return false;
+ }
+ return true;
+}
+
+bool Interface::configureIcmpSocket() {
+ Result res = mIcmpSocket.open(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
+ if (!res) {
+ loge("Error opening socket: %s\n", res.c_str());
+ return false;
+ }
+
+ // The ICMP messages we are going to send need a hop limit of 255 to be
+ // accepted.
+ res = mIcmpSocket.setMulticastHopLimit(255);
+ if (!res) {
+ loge("Error setting socket hop limit: %s\n", res.c_str());
+ return false;
+ }
+ res = mIcmpSocket.setUnicastHopLimit(255);
+ if (!res) {
+ loge("Error setting socket hop limit: %s\n", res.c_str());
+ return false;
+ }
+
+ // We only care about one specific interface
+ res = mIcmpSocket.setInterface(mName);
+ if (!res) {
+ loge("Error socket interface: %s\n", res.c_str());
+ return false;
+ }
+
+ // Make sure the socket allows transparent proxying, this allows sending of
+ // packets with a source address that is different from the interface.
+ res = mIcmpSocket.setTransparent(true);
+ if (!res) {
+ loge("Error socket interface: %s\n", res.c_str());
+ return false;
+ }
+
+ return true;
+}
+
+bool Interface::configureIpSocket() {
+ Result res = mIpSocket.open(AF_PACKET, SOCK_DGRAM, ETH_P_IPV6);
+ if (!res) {
+ loge("Error opening socket: %s\n", res.c_str());
+ return false;
+ }
+
+ res = mIpSocket.bind(mLinkAddr);
+ if (!res) {
+ loge("Error binding socket: %s\n", res.c_str());
+ return false;
+ }
+ return true;
+}
+
diff --git a/wifi/ipv6proxy/interface.h b/wifi/ipv6proxy/interface.h
new file mode 100644
index 00000000..e6e5d78a
--- /dev/null
+++ b/wifi/ipv6proxy/interface.h
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+#pragma once
+
+#include <stdint.h>
+#include <string>
+
+#include "address.h"
+#include "socket.h"
+
+// A class that contains the information used by the proxy that is specific to a
+// single interface. This includes the name and index of the interface as well
+// as the sockets used to send and receive data on the interface.
+//
+// The class also contains the functionality needed to initialized and configure
+// the interface, sockets and addresses.
+class Interface {
+public:
+ explicit Interface(const std::string& name);
+
+ bool init();
+
+ const std::string& name() const { return mName; }
+ uint32_t index() const { return mIndex; }
+ Socket& ipSocket() { return mIpSocket; }
+ Socket& icmpSocket() { return mIcmpSocket; }
+ const Address& linkAddr() const { return mLinkAddr; }
+
+private:
+ bool setAllMulti();
+ bool resolveAddresses();
+ bool configureIcmpSocket();
+ bool configureIpSocket();
+
+ std::string mName;
+ uint32_t mIndex;
+ Socket mIpSocket;
+ Socket mIcmpSocket;
+ Address mLinkAddr;
+};
+
diff --git a/wifi/ipv6proxy/log.cpp b/wifi/ipv6proxy/log.cpp
new file mode 100644
index 00000000..a23b0621
--- /dev/null
+++ b/wifi/ipv6proxy/log.cpp
@@ -0,0 +1,65 @@
+/*
+ * 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 "log.h"
+
+#ifndef ANDROID
+#include <stdarg.h>
+#ifdef USE_LOG_TIMESTAMPS
+#include <time.h>
+#endif // USE_LOG_TIMESTAMPS
+
+static void vlogf(FILE* stream, const char* fmt, va_list args) {
+#ifdef USE_LOG_TIMESTAMPS
+ struct timespec ts;
+ struct tm localTime;
+ static bool newLine = true;
+ if (newLine && clock_gettime(CLOCK_REALTIME, &ts) == 0) {
+ time_t now = ts.tv_sec;
+ if (localtime_r(&now, &localTime)) {
+ char format[32];
+ char timestamp[1024];
+ snprintf(format, sizeof(format), "[%%T.%03lld] ", (long long)(ts.tv_nsec) / 1000000);
+ strftime(timestamp, sizeof(timestamp), format, &localTime);
+ fprintf(stream, "%s ", timestamp);
+ }
+ }
+ newLine = (fmt[strlen(fmt) - 1] == '\n');
+#endif // USE_LOG_TIMESTAMPS
+ vfprintf(stream, fmt, args);
+}
+
+static void logf(FILE* stream, const char* fmt, ...) {
+ va_list args;
+ va_start(args, fmt);
+ vlogf(stream, fmt, args);
+ va_end(args);
+}
+
+void loge(const char* fmt, ...) {
+ va_list args;
+ va_start(args, fmt);
+ vlogf(stderr, fmt, args);
+ va_end(args);
+}
+
+void logd(const char* fmt, ...) {
+ va_list args;
+ va_start(args, fmt);
+ vlogf(stdout, fmt, args);
+ va_end(args);
+}
+#endif // !ANDROID
diff --git a/wifi/ipv6proxy/log.h b/wifi/ipv6proxy/log.h
new file mode 100644
index 00000000..53e89350
--- /dev/null
+++ b/wifi/ipv6proxy/log.h
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+#pragma once
+
+#ifdef ANDROID
+
+#define LOG_TAG "ipv6proxy"
+#include <log/log.h>
+
+#define loge(...) ALOGE(__VA_ARGS__)
+#define logd(...) ALOGD(__VA_ARGS__)
+
+#else
+#include <stdio.h>
+
+void loge(const char* fmt, ...);
+void logd(const char* fmt, ...);
+
+#endif
diff --git a/wifi/ipv6proxy/main.cpp b/wifi/ipv6proxy/main.cpp
new file mode 100644
index 00000000..91445caf
--- /dev/null
+++ b/wifi/ipv6proxy/main.cpp
@@ -0,0 +1,111 @@
+/*
+ * 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 <vector>
+
+#include <string.h>
+
+#include "log.h"
+#include "namespace.h"
+#include "proxy.h"
+
+void usage(const char* program) {
+ loge("Usage: %s -n [namespace|pid] -o <outer if> -i <inner ifs>\n",
+ program);
+ loge(" -o Outer interface that connects to an existing IPv6 network.\n"
+ " -i Comma separated list of inner interfaces that would like\n"
+ " to access the IPv6 network available on the outer interface.\n"
+ " -n Optional parameter that causes the proxy to run in the given\n"
+ " network namespace. If a name is given instead of a PID the\n"
+ " namespace is expected to be set up by iproute2 or with a\n"
+ " similar approach where the namespace is linked in\n"
+ " /var/run/netns. A PID is assumed if the argument is numeric.\n"
+ " If providing a PID the same namespace that the PID is\n"
+ " running in will be used. In this scenario there is no\n"
+ " requirement for a file in /var/run/netns.\n"
+ "\n"
+ " The proxy will ensure that router solicitations from inner\n"
+ " interfaces are forwarded to the outer interface and that\n"
+ " router advertisements from the outer interface are forwarded\n"
+ " to the inner interfaces. In addition to this neighbor\n"
+ " solicitations and advertisements will also be forwarded in a\n"
+ " way that enables IPv6 connectivity and routes will be set up\n"
+ " for source addresses on the inner interfaces so that replies\n"
+ " can reach those sources as expected.\n"
+ );
+}
+
+static std::vector<const char*> splitString(char* str, char delimiter) {
+ std::vector<const char*> parts;
+ char* part = nullptr;
+ do {
+ parts.push_back(str);
+ part = strchr(str, delimiter);
+ if (part != nullptr) {
+ *part = '\0';
+ str = part + 1;
+ }
+ } while (part != nullptr);
+ return parts;
+}
+
+int main(int argc, char* argv[]) {
+ char* inner = nullptr;
+ const char* outer = nullptr;
+ const char* netNamespace = nullptr;
+ for (int i = 1; i < argc; ++i) {
+ if (strcmp(argv[i], "-o") == 0) {
+ outer = argv[++i];
+ } else if (strcmp(argv[i], "-i") == 0) {
+ inner = argv[++i];
+ } else if (strcmp(argv[i], "-h") == 0 ||
+ strcmp(argv[i], "--help") == 0) {
+ usage(argv[0]);
+ return 1;
+ } else if (strcmp(argv[i], "-n") == 0) {
+ netNamespace = argv[++i];
+ } else {
+ loge("ERROR: Unknown argument '%s'\n\n", argv[i]);
+ usage(argv[0]);
+ return 1;
+ }
+ }
+ bool error = false;
+ if (inner == nullptr) {
+ loge("ERROR: Missing inner interface\n");
+ error = true;
+ }
+ if (outer == nullptr) {
+ loge("ERROR: Missing outer interface\n");
+ error = true;
+ }
+ if (netNamespace) {
+ if (!setNetworkNamespace(netNamespace)) {
+ error = true;
+ }
+ }
+ if (error) {
+ usage(argv[0]);
+ return 1;
+ }
+
+ std::vector<const char*> innerInterfaces = splitString(inner, ',');
+
+ Proxy proxy(outer, innerInterfaces.begin(), innerInterfaces.end());
+
+ return proxy.run();
+}
+
diff --git a/wifi/ipv6proxy/message.h b/wifi/ipv6proxy/message.h
new file mode 100644
index 00000000..9b35daeb
--- /dev/null
+++ b/wifi/ipv6proxy/message.h
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+#pragma once
+
+class Message {
+public:
+
+ size_t size() const { return mSize; }
+ size_t capacity() const { return sizeof(mData); }
+ const char* data() const { return mData; }
+ char* data() { return mData; }
+
+ void setSize(size_t size) { mSize = size; }
+
+protected:
+ char mData[8192];
+ size_t mSize;
+};
+
diff --git a/wifi/ipv6proxy/namespace.cpp b/wifi/ipv6proxy/namespace.cpp
new file mode 100644
index 00000000..04841c29
--- /dev/null
+++ b/wifi/ipv6proxy/namespace.cpp
@@ -0,0 +1,80 @@
+/*
+ * 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 "namespace.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <linux/limits.h>
+#include <sched.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "log.h"
+
+static const char kNetNsDir[] = "/data/vendor/var/run/netns";
+
+// Set the current namespace to that of the /proc/<pid>/ns/net provided in
+// |path|. This may be a link or mount point for that same file, anything that
+// when opened will be an fd usable by setns is fine.
+static bool setNamespaceFromPath(const char* path) {
+ int nsFd = open(path, O_RDONLY | O_CLOEXEC);
+ if (nsFd == -1) {
+ loge("Cannot open network namespace at '%s': %s\n",
+ path, strerror(errno));
+ return false;
+ }
+
+ if (setns(nsFd, CLONE_NEWNET) == -1) {
+ loge("Cannot set network namespace at '%s': %s\n",
+ path, strerror(errno));
+ close(nsFd);
+ return false;
+ }
+ close(nsFd);
+ return true;
+}
+
+bool setNetworkNamespace(const char* ns) {
+ // There is a file in the net namespace dir (usually /var/run/netns) with
+ // the same name as the namespace. This file is bound to /proc/<pid>/ns/net
+ // by the 'ip' command when the namespace is created. This allows us to
+ // access the file of a process running in that network namespace without
+ // knowing its pid, knowing the namespace name is enough.
+ //
+ // We are going to call setns which requires a file descriptor to that proc
+ // file in /proc/<pid>/net. The process has to already be running in that
+ // namespace. Since the file in the net namespace dir has been bound to
+ // such a file already we just have to open /var/run/netns/<namespace> and
+ // we have the required file descriptor.
+ char nsPath[PATH_MAX];
+ snprintf(nsPath, sizeof(nsPath), "%s/%s", kNetNsDir, ns);
+ return setNamespaceFromPath(nsPath);
+}
+
+bool setNetworkNamespace(pid_t pid) {
+ // If we know the pid we can create the path to the /proc file right away
+ // and use that when we call setns.
+ char nsPath[PATH_MAX];
+ static_assert(sizeof(pid_t) <= sizeof(unsigned long long),
+ "Cast requires sizeof(pid_t) <= sizeof(unsigned long long)");
+ snprintf(nsPath, sizeof(nsPath), "/proc/%llu/ns/net/",
+ static_cast<unsigned long long>(pid));
+ return setNamespaceFromPath(nsPath);
+}
+
diff --git a/network/wifi_forwarder/hash.h b/wifi/ipv6proxy/namespace.h
index ecd8c23a..8a703741 100644
--- a/network/wifi_forwarder/hash.h
+++ b/wifi/ipv6proxy/namespace.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2019, The Android Open Source Project
+ * 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.
@@ -13,14 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
#pragma once
-#include <functional>
+#include <sys/types.h>
-template<class T>
-inline void hash_combine(size_t& seed, const T& value) {
- std::hash<T> hasher;
- seed ^= hasher(value) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
-}
+// Move the process into the namespace |ns|
+bool setNetworkNamespace(const char* ns);
+// Move the process into the same namespace as the process |pid| is in.
+bool setNetworkNamespace(pid_t pid);
diff --git a/wifi/ipv6proxy/packet.cpp b/wifi/ipv6proxy/packet.cpp
new file mode 100644
index 00000000..fa15a758
--- /dev/null
+++ b/wifi/ipv6proxy/packet.cpp
@@ -0,0 +1,134 @@
+/*
+ * 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 "packet.h"
+
+#include "address.h"
+
+Packet::Packet(Message& message)
+ : mMessage(message),
+ mType(Type::Other),
+ mIp(nullptr),
+ mIcmp(nullptr),
+ mFirstOpt(nullptr) {
+ if (message.size() < sizeof(ip6_hdr) + sizeof(icmp6_hdr)) {
+ mType = Type::Other;
+ return;
+ }
+ mIp = reinterpret_cast<const ip6_hdr*>(message.data());
+ uint8_t version = (mIp->ip6_vfc & 0xF0) >> 4;
+ if (version != 6 || mIp->ip6_nxt != IPPROTO_ICMPV6) {
+ mType = Type::Other;
+ return;
+ }
+
+ size_t size = message.size() - sizeof(ip6_hdr);
+ char* data = message.data() + sizeof(ip6_hdr);
+ mIcmp = reinterpret_cast<const icmp6_hdr*>(data);
+ if (mIcmp->icmp6_code != 0) {
+ // All messages we care about have a code of zero
+ mType = Type::Other;
+ return;
+ }
+
+ size_t headerSize = 0;
+ switch (mIcmp->icmp6_type) {
+ case ND_ROUTER_SOLICIT:
+ headerSize = sizeof(nd_router_solicit);
+ mType = Type::RouterSolicitation;
+ break;
+ case ND_ROUTER_ADVERT:
+ headerSize = sizeof(nd_router_advert);
+ mType = Type::RouterAdvertisement;
+ break;
+ case ND_NEIGHBOR_SOLICIT:
+ headerSize = sizeof(nd_neighbor_solicit);
+ mType = Type::NeighborSolicitation;
+ break;
+ case ND_NEIGHBOR_ADVERT:
+ headerSize = sizeof(nd_neighbor_advert);
+ mType = Type::NeighborAdvertisement;
+ break;
+ default:
+ mType = Type::Other;
+ return;
+ }
+ if (size < headerSize) {
+ mType = Type::Other;
+ return;
+ }
+
+ // We might have options
+ char* options = data + headerSize;
+ if (options + sizeof(nd_opt_hdr) < data + size) {
+ nd_opt_hdr* option = reinterpret_cast<nd_opt_hdr*>(options);
+ // Option length is in units of 8 bytes, multiply by 8 to get bytes
+ if (options + option->nd_opt_len * 8u <= data + size) {
+ mFirstOpt = option;
+ }
+ }
+}
+
+std::string Packet::description() const {
+ char buffer[256];
+ switch (mType) {
+ case Type::NeighborSolicitation: {
+ auto ns = reinterpret_cast<const nd_neighbor_solicit*>(icmp());
+ snprintf(buffer, sizeof(buffer), "Neighbor Solicitation for %s",
+ addrToStr(ns->nd_ns_target).c_str());
+ return buffer;
+ }
+ case Type::NeighborAdvertisement: {
+ auto na = reinterpret_cast<const nd_neighbor_advert*>(icmp());
+ snprintf(buffer, sizeof(buffer),
+ "Neighbor Advertisement for %s",
+ addrToStr(na->nd_na_target).c_str());
+ return buffer;
+ }
+ case Type::RouterSolicitation:
+ return "Router Solicitation";
+ case Type::RouterAdvertisement:
+ return "Router Advertisement";
+ default:
+ break;
+ }
+ return "[unknown]";
+}
+
+nd_opt_hdr* Packet::firstOpt() {
+ return mFirstOpt;
+}
+
+nd_opt_hdr* Packet::nextOpt(nd_opt_hdr* currentHeader) {
+ char* end = mMessage.data() + mMessage.size();
+ char* current = reinterpret_cast<char*>(currentHeader);
+ if (currentHeader < mFirstOpt || current >= end) {
+ // The provided header does not belong to this packet info.
+ return nullptr;
+ }
+ char* next = current + currentHeader->nd_opt_len * 8u;
+ if (next >= end) {
+ // The next header points passed the message data
+ return nullptr;
+ }
+ nd_opt_hdr* nextHeader = reinterpret_cast<nd_opt_hdr*>(next);
+ if (next + nextHeader->nd_opt_len * 8u > end) {
+ // The next option extends beyond the message data
+ return nullptr;
+ }
+ return nextHeader;
+}
+
diff --git a/wifi/ipv6proxy/packet.h b/wifi/ipv6proxy/packet.h
new file mode 100644
index 00000000..49e69d4c
--- /dev/null
+++ b/wifi/ipv6proxy/packet.h
@@ -0,0 +1,72 @@
+/*
+ * 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.
+ */
+#pragma once
+
+#include <netinet/icmp6.h>
+#include <netinet/ip6.h>
+
+#include <string>
+#include <vector>
+
+#include "message.h"
+
+class Packet {
+public:
+ enum class Type {
+ NeighborSolicitation,
+ NeighborAdvertisement,
+ RouterSolicitation,
+ RouterAdvertisement,
+ Other
+ };
+
+ explicit Packet(Message& message);
+
+ // Create a string that can be used for debug purposes to describe
+ // what type of packet and potentially its target for certain types.
+ std::string description() const;
+
+ // Full size including IP header
+ size_t fullSize() const {
+ return mMessage.size();
+ }
+ // Remaining size including ICMPv6 header but excluding IP header
+ size_t icmpSize() const {
+ return mMessage.size() - sizeof(ip6_hdr);
+ }
+
+ Type type() const {
+ return mType;
+ }
+ const ip6_hdr* ip() const {
+ return mIp;
+ }
+ const icmp6_hdr* icmp() const {
+ return mIcmp;
+ }
+
+ nd_opt_hdr* firstOpt();
+ nd_opt_hdr* nextOpt(nd_opt_hdr* currentHeader);
+
+private:
+ Message& mMessage;
+ Type mType;
+
+ const ip6_hdr* mIp;
+ const icmp6_hdr* mIcmp;
+ nd_opt_hdr* mFirstOpt;
+};
+
diff --git a/wifi/ipv6proxy/proxy.cpp b/wifi/ipv6proxy/proxy.cpp
new file mode 100644
index 00000000..cb19ff7d
--- /dev/null
+++ b/wifi/ipv6proxy/proxy.cpp
@@ -0,0 +1,262 @@
+/*
+ * 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 "proxy.h"
+
+#include <arpa/inet.h>
+#include <errno.h>
+#include <linux/if_packet.h>
+#include <poll.h>
+#include <signal.h>
+
+#include <cutils/properties.h>
+
+#include "log.h"
+#include "message.h"
+#include "packet.h"
+#include "result.h"
+
+// The prefix length for an address of a single unique node
+static const uint8_t kNodePrefixLength = 128;
+static const size_t kLinkAddressSize = 6;
+static const size_t kRecursiveDnsOptHeaderSize = 8;
+
+// Rewrite the link address of a neighbor discovery option to the link address
+// of |interface|. This can be either a source or target link address as
+// specified by |optionType|. The valid values are ND_OPT_TARGET_LINKADDR and
+// ND_OPT_SOURCE_LINKADDR. This will modify the message data inside |packet|.
+static void rewriteLinkAddressOption(Packet& packet,
+ const Interface& interface,
+ int optionType) {
+ for (nd_opt_hdr* opt = packet.firstOpt(); opt; opt = packet.nextOpt(opt)) {
+ if (opt->nd_opt_type == optionType) {
+ auto src = interface.linkAddr().get<sockaddr_ll>();
+ auto dest = reinterpret_cast<char*>(opt) + sizeof(nd_opt_hdr);
+ memcpy(dest, src->sll_addr, kLinkAddressSize);
+ }
+ }
+}
+
+static void extractRecursiveDnsServers(Packet& packet) {
+ for (nd_opt_hdr* opt = packet.firstOpt(); opt; opt = packet.nextOpt(opt)) {
+ if (opt->nd_opt_type != 25 || opt->nd_opt_len < 1) {
+ // Not a RNDSS option, skip it
+ continue;
+ }
+ size_t numEntries = (opt->nd_opt_len - 1) / 2;
+ //Found number of entries, dump each address
+ const char* option = reinterpret_cast<const char*>(opt);
+ option += kRecursiveDnsOptHeaderSize;
+ auto dnsServers = reinterpret_cast<const struct in6_addr*>(option);
+
+ std::vector<std::string> validServers;
+ for (size_t i = 0; i < numEntries; ++i) {
+ char buffer[INET6_ADDRSTRLEN];
+ if (inet_ntop(AF_INET6, &dnsServers[i], buffer, sizeof(buffer))) {
+ validServers.push_back(buffer);
+ } else {
+ loge("Failed to convert RDNSS to string\n");
+ }
+ }
+
+ auto server = validServers.begin();
+ char propName[PROP_NAME_MAX];
+ char propValue[PROP_VALUE_MAX];
+ for (int i = 1; i <= 4; ++i) {
+ snprintf(propName, sizeof(propName), "net.eth0.ipv6dns%d", i);
+ if (server != validServers.end()) {
+ property_set(propName, server->c_str());
+ ++server;
+ } else {
+ // Clear the property if it's no longer a valid server, don't
+ // want to leave old servers around
+ property_set(propName, "");
+ }
+ }
+ }
+}
+
+int Proxy::run() {
+ sigset_t blockMask, originalMask;
+ int status = ::sigfillset(&blockMask);
+ if (status != 0) {
+ loge("Unable to fill signal set: %s\n", strerror(errno));
+ return 1;
+ }
+ status = ::sigprocmask(SIG_SETMASK, &blockMask, &originalMask);
+ if (status != 0) {
+ loge("Unable to set signal mask: %s\n", strerror(errno));
+ return 1;
+ }
+ // Init outer interface and router
+ if (!mOuterIf.init() || !mRouter.init()) {
+ return 1;
+ }
+ // Init all inner interfaces
+ for (size_t i = 0; i < mInnerIfs.size(); ++i) {
+ if (!mInnerIfs[i].init()) {
+ return 1;
+ }
+ }
+
+ // Create list of FDs to poll, we're only looking for input (POLLIN)
+ std::vector<pollfd> fds(mInnerIfs.size() + 1);
+ fds[0].fd = mOuterIf.ipSocket().get();
+ fds[0].events = POLLIN;
+ for (size_t i = 0; i < mInnerIfs.size(); ++i) {
+ fds[i + 1].fd = mInnerIfs[i].ipSocket().get();
+ fds[i + 1].events = POLLIN;
+ }
+
+ Message message;
+ while (status >= 0) {
+ status = ::ppoll(fds.data(), fds.size(), nullptr, &originalMask);
+ if (status > 0) {
+ // Something available to read
+ for (const struct pollfd& fd : fds) {
+ if (receiveIfPossible(fd, mOuterIf.ipSocket(), &message)) {
+ // Received a message on the outer interface
+ handleOuterMessage(message);
+ } else {
+ for (auto& inner : mInnerIfs) {
+ if (receiveIfPossible(fd, inner.ipSocket(), &message)) {
+ // Received a message on the inner interface
+ handleInnerMessage(inner, message);
+ }
+ }
+ }
+ }
+ }
+ }
+ loge("Polling failed: %s\n", strerror(errno));
+ return 1;
+}
+
+bool Proxy::receiveIfPossible(const pollfd& fd,
+ Socket& socket,
+ Message* message) {
+ // Check if it's actually the socket we're interested in
+ if (fd.fd != socket.get()) {
+ return false;
+ }
+ // Check if there is something to read on this socket
+ if ((fd.revents & POLLIN) == 0) {
+ return false;
+ }
+
+ // Receive the message and place the data in the message parameter
+ Result res = socket.receive(message);
+ if (!res) {
+ loge("Error receiving on socket: %s\n", res.c_str());
+ return false;
+ }
+ return true;
+}
+
+void Proxy::handleOuterMessage(Message& message) {
+ Packet packet(message);
+ uint32_t options = kForwardOnly;
+ switch (packet.type()) {
+ case Packet::Type::RouterAdvertisement:
+ extractRecursiveDnsServers(packet);
+ options = kRewriteSourceLink | kSetDefaultGateway;
+ break;
+ case Packet::Type::NeighborSolicitation:
+ options = kSpoofSource;
+ break;
+ case Packet::Type::NeighborAdvertisement:
+ options = kRewriteTargetLink;
+ break;
+ default:
+ return;
+ }
+ for (auto& inner : mInnerIfs) {
+ forward(mOuterIf, inner, packet, options);
+ }
+}
+
+void Proxy::handleInnerMessage(const Interface& inner, Message& message) {
+ Packet packet(message);
+ uint32_t options = kForwardOnly;
+ switch (packet.type()) {
+ case Packet::Type::RouterSolicitation:
+ options = kSpoofSource;
+ break;
+ case Packet::Type::NeighborSolicitation:
+ options = kSpoofSource | kAddRoute;
+ break;
+ case Packet::Type::NeighborAdvertisement:
+ options = kRewriteTargetLink | kSpoofSource | kAddRoute;
+ break;
+ default:
+ return;
+ }
+ forward(inner, mOuterIf, packet, options);
+}
+
+void Proxy::forward(const Interface& from,
+ Interface& to,
+ Packet& packet,
+ uint32_t options) {
+ if (mLogDebug) {
+ logd("Forwarding %s from %s/%s to %s/%s\n",
+ packet.description().c_str(),
+ from.name().c_str(), addrToStr(packet.ip()->ip6_src).c_str(),
+ to.name().c_str(), addrToStr(packet.ip()->ip6_dst).c_str());
+ }
+
+ if (options & kRewriteTargetLink) {
+ rewriteLinkAddressOption(packet, to, ND_OPT_TARGET_LINKADDR);
+ }
+ if (options & kRewriteSourceLink) {
+ rewriteLinkAddressOption(packet, to, ND_OPT_SOURCE_LINKADDR);
+ }
+
+ Result res = Result::success();
+ if (options & kSpoofSource) {
+ // Spoof the source of the packet so that it appears to originate from
+ // the same source that we see.
+ res = to.icmpSocket().sendFrom(packet.ip()->ip6_src,
+ packet.ip()->ip6_dst,
+ packet.icmp(),
+ packet.icmpSize());
+ } else {
+ res = to.icmpSocket().sendTo(packet.ip()->ip6_dst,
+ packet.icmp(),
+ packet.icmpSize());
+ }
+ if (!res) {
+ loge("Failed to forward %s from %s to %s: %s\n",
+ packet.description().c_str(),
+ from.name().c_str(), to.name().c_str(),
+ res.c_str());
+ }
+
+ if (options & kAddRoute) {
+ mRouter.addRoute(packet.ip()->ip6_src, kNodePrefixLength, from.index());
+ }
+ if (packet.type() == Packet::Type::RouterAdvertisement &&
+ options & kSetDefaultGateway) {
+ // Set the default gateway from this router advertisement. This is
+ // needed so that packets that are forwarded as a result of proxying
+ // actually have somewhere to go.
+ if (!mRouter.setDefaultGateway(packet.ip()->ip6_src, from.index())) {
+ loge("Failed to set default gateway %s\n",
+ addrToStr(packet.ip()->ip6_src).c_str());
+ }
+ }
+}
+
diff --git a/wifi/ipv6proxy/proxy.h b/wifi/ipv6proxy/proxy.h
new file mode 100644
index 00000000..51791373
--- /dev/null
+++ b/wifi/ipv6proxy/proxy.h
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ */
+#pragma once
+
+#include <string>
+#include <vector>
+
+#include "interface.h"
+#include "router.h"
+
+struct pollfd;
+class Message;
+class Packet;
+class Socket;
+
+class Proxy {
+public:
+ template<typename Iter>
+ Proxy(std::string outerInterfaceName,
+ Iter innerInterfacesBegin, Iter innerInterfacesEnd)
+ : mOuterIf(outerInterfaceName),
+ mLogDebug(false) {
+
+ for (Iter i = innerInterfacesBegin; i != innerInterfacesEnd; ++i) {
+ mInnerIfs.emplace_back(*i);
+ }
+ }
+
+ int run();
+
+private:
+ enum ForwardOpt {
+ kForwardOnly = 0,
+ kRewriteTargetLink = (1 << 0),
+ kRewriteSourceLink = (1 << 1),
+ kSpoofSource = (1 << 2),
+ kAddRoute = (1 << 3),
+ kSetDefaultGateway = (1 << 4)
+ };
+
+ bool receiveIfPossible(const pollfd&, Socket& socket, Message* message);
+
+ void handleOuterMessage(Message& message);
+ void handleInnerMessage(const Interface& inner, Message& message);
+ void forward(const Interface& from, Interface& to,
+ Packet& packet, uint32_t options);
+
+ std::vector<Interface> mInnerIfs;
+ Interface mOuterIf;
+
+ Router mRouter;
+ bool mLogDebug;
+};
+
diff --git a/network/wifi_forwarder/result.h b/wifi/ipv6proxy/result.h
index 5087e146..5cd2b035 100644
--- a/network/wifi_forwarder/result.h
+++ b/wifi/ipv6proxy/result.h
@@ -15,40 +15,28 @@
*/
#pragma once
-#include <stdio.h>
-#include <stdarg.h>
-
-#include <string>
-
class Result {
public:
static Result success() {
return Result(true);
}
- // Construct a result indicating an error.
- static Result error(std::string message) {
+ // Construct a result indicating an error. NOTE: the data in |message| will
+ // NOT be copied. It must be kept alive for as long as its intended to be
+ // used. This way the object is kept light-weight.
+ static Result error(const char* message) {
return Result(message);
}
- static Result error(const char* format, ...) {
- char buffer[1024];
- va_list args;
- va_start(args, format);
- vsnprintf(buffer, sizeof(buffer), format, args);
- va_end(args);
- buffer[sizeof(buffer) - 1] = '\0';
- return Result(std::string(buffer));
- }
bool isSuccess() const { return mSuccess; }
bool operator!() const { return !mSuccess; }
- const char* c_str() const { return mMessage.c_str(); }
+ const char* c_str() const { return mMessage; }
private:
explicit Result(bool success) : mSuccess(success) { }
- explicit Result(std::string message)
+ explicit Result(const char* message)
: mMessage(message), mSuccess(false) {
}
- std::string mMessage;
+ const char* mMessage;
bool mSuccess;
};
diff --git a/wifi/ipv6proxy/router.cpp b/wifi/ipv6proxy/router.cpp
new file mode 100644
index 00000000..be505c92
--- /dev/null
+++ b/wifi/ipv6proxy/router.cpp
@@ -0,0 +1,154 @@
+/*
+ * 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 "router.h"
+
+#include <linux/rtnetlink.h>
+#include <stddef.h>
+#include <string.h>
+
+#include "address.h"
+#include "log.h"
+
+template<class Request>
+static void addRouterAttribute(Request& r,
+ int type,
+ const void* data,
+ size_t size) {
+ // Calculate the offset into the character buffer where the RTA data lives
+ // We use offsetof on the buffer to get it. This avoids undefined behavior
+ // by casting the buffer (which is safe because it's char) instead of the
+ // Request struct.(which is undefined because of aliasing)
+ size_t offset = NLMSG_ALIGN(r.hdr.nlmsg_len) - offsetof(Request, buf);
+ auto attr = reinterpret_cast<struct rtattr*>(r.buf + offset);
+ attr->rta_type = type;
+ attr->rta_len = RTA_LENGTH(size);
+ memcpy(RTA_DATA(attr), data, size);
+
+ // Update the message length to include the router attribute.
+ r.hdr.nlmsg_len = NLMSG_ALIGN(r.hdr.nlmsg_len) + RTA_ALIGN(attr->rta_len);
+}
+
+bool Router::init() {
+ // Create a netlink socket to the router
+ Result res = mSocket.open(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
+ if (!res) {
+ loge("Unable to open netlink socket: %s\n", res.c_str());
+ return false;
+ }
+ return true;
+}
+
+bool Router::addNeighbor(const struct in6_addr& address,
+ unsigned int interfaceIndex) {
+ struct Request {
+ struct nlmsghdr hdr;
+ struct ndmsg msg;
+ char buf[256];
+ } request;
+
+ memset(&request, 0, sizeof(request));
+
+ unsigned short msgLen = NLMSG_LENGTH(sizeof(request.msg));
+ // Set up a request to create a new neighbor
+ request.hdr.nlmsg_len = msgLen;
+ request.hdr.nlmsg_type = RTM_NEWNEIGH;
+ request.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE;
+
+ // The neighbor is a permanent IPv6 proxy
+ request.msg.ndm_family = AF_INET6;
+ request.msg.ndm_state = NUD_PERMANENT;
+ request.msg.ndm_flags = NTF_PROXY;
+ request.msg.ndm_ifindex = interfaceIndex;
+
+ addRouterAttribute(request, NDA_DST, &address, sizeof(address));
+
+ return sendNetlinkMessage(&request, request.hdr.nlmsg_len);
+}
+
+bool Router::addRoute(const struct in6_addr& address,
+ uint8_t bits,
+ uint32_t ifaceIndex) {
+ struct Request {
+ struct nlmsghdr hdr;
+ struct rtmsg msg;
+ char buf[256];
+ } request;
+
+ memset(&request, 0, sizeof(request));
+
+ // Set up a request to create a new route
+ request.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(request.msg));
+ request.hdr.nlmsg_type = RTM_NEWROUTE;
+ request.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE;
+
+ request.msg.rtm_family = AF_INET6;
+ request.msg.rtm_dst_len = bits;
+ request.msg.rtm_table = RT_TABLE_MAIN;
+ request.msg.rtm_protocol = RTPROT_RA;
+ request.msg.rtm_scope = RT_SCOPE_UNIVERSE;
+ request.msg.rtm_type = RTN_UNICAST;
+
+ addRouterAttribute(request, RTA_DST, &address, sizeof(address));
+ addRouterAttribute(request, RTA_OIF, &ifaceIndex, sizeof(ifaceIndex));
+
+ return sendNetlinkMessage(&request, request.hdr.nlmsg_len);
+}
+
+bool Router::setDefaultGateway(const struct in6_addr& address,
+ unsigned int ifaceIndex) {
+ struct Request {
+ struct nlmsghdr hdr;
+ struct rtmsg msg;
+ char buf[256];
+ } request;
+
+ memset(&request, 0, sizeof(request));
+
+ // Set up a request to create a new route
+ request.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(request.msg));
+ request.hdr.nlmsg_type = RTM_NEWROUTE;
+ request.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE;
+
+ request.msg.rtm_family = AF_INET6;
+ request.msg.rtm_dst_len = 0;
+ request.msg.rtm_src_len = 0;
+ request.msg.rtm_table = RT_TABLE_MAIN;
+ request.msg.rtm_protocol = RTPROT_RA;
+ request.msg.rtm_scope = RT_SCOPE_UNIVERSE;
+ request.msg.rtm_type = RTN_UNICAST;
+
+ struct in6_addr anyAddress;
+ memset(&anyAddress, 0, sizeof(anyAddress));
+ addRouterAttribute(request, RTA_GATEWAY, &address, sizeof(address));
+ addRouterAttribute(request, RTA_OIF, &ifaceIndex, sizeof(ifaceIndex));
+ addRouterAttribute(request, RTA_SRC, &anyAddress, sizeof(anyAddress));
+
+ return sendNetlinkMessage(&request, request.hdr.nlmsg_len);
+}
+
+bool Router::sendNetlinkMessage(const void* data, size_t size) {
+ struct sockaddr_nl netlinkAddress;
+ memset(&netlinkAddress, 0, sizeof(netlinkAddress));
+ netlinkAddress.nl_family = AF_NETLINK;
+ Result res = mSocket.sendTo(netlinkAddress, data, size);
+ if (!res) {
+ loge("Unable to send on netlink socket: %s\n", res.c_str());
+ return false;
+ }
+ return true;
+}
+
diff --git a/wifi/ipv6proxy/router.h b/wifi/ipv6proxy/router.h
new file mode 100644
index 00000000..66e896ff
--- /dev/null
+++ b/wifi/ipv6proxy/router.h
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ */
+#pragma once
+
+#include <stdint.h>
+
+#include <netinet/in.h>
+
+#include "socket.h"
+
+class Router {
+public:
+ // Initialize the router, this has to be called before any other methods can
+ // be called. It only needs to be called once.
+ bool init();
+
+ // Indicate that |address| is a neighbor to this node and that it is
+ // accessible on the interface with index |interfaceIndex|.
+ bool addNeighbor(const struct in6_addr& address, uint32_t interfaceIndex);
+
+ // Add a route to |address|/|bits| on interface |interfaceIndex|. The
+ // |bits| parameter indicates the bitmask of the address, for example in
+ // the routing entry 2001:db8::/32 the |bits| parameter would be 32.
+ bool addRoute(const struct in6_addr& address,
+ uint8_t bits,
+ uint32_t interfaceIndex);
+
+ // Set the default gateway route to |address| on interface with index
+ // |interfaceIndex|. Overwrites any existing default gateway with the same
+ // address.
+ bool setDefaultGateway(const struct in6_addr& address,
+ unsigned int interfaceIndex);
+private:
+ bool sendNetlinkMessage(const void* data, size_t size);
+
+ // Netlink socket for setting up neighbors and routes
+ Socket mSocket;
+};
+
diff --git a/wifi/ipv6proxy/socket.cpp b/wifi/ipv6proxy/socket.cpp
new file mode 100644
index 00000000..3b678161
--- /dev/null
+++ b/wifi/ipv6proxy/socket.cpp
@@ -0,0 +1,272 @@
+/*
+ * 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 "socket.h"
+
+#include <errno.h>
+#include <string.h>
+
+#include <linux/in6.h>
+#include <net/ethernet.h>
+#include <netinet/in.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <unistd.h>
+
+#include "address.h"
+#include "message.h"
+
+Socket::Socket() : mState(State::New), mSocket(-1) {
+}
+
+Socket::Socket(Socket&& other) noexcept : mState(other.mState), mSocket(other.mSocket) {
+ other.mSocket = -1;
+ other.mState = State::Moved;
+}
+
+Socket::~Socket() {
+ if (mSocket != -1) {
+ close(mSocket);
+ mSocket = -1;
+ }
+ mState = State::Destructed;
+}
+
+Socket& Socket::operator=(Socket&& other) noexcept {
+ if (mSocket != -1) {
+ close(mSocket);
+ }
+ mSocket = other.mSocket;
+ mState = other.mState;
+ other.mSocket = -1;
+ other.mState = State::Moved;
+
+ return *this;
+}
+
+Result Socket::open(int domain, int type, int protocol) {
+ if (mState != State::New) {
+ return Result::error("open called on socket in invalid state");
+ }
+ mSocket = ::socket(domain, type | SOCK_CLOEXEC, protocol);
+ if (mSocket == -1) {
+ return Result::error(strerror(errno));
+ }
+ mState = State::Open;
+ return Result::success();
+}
+
+Result Socket::setInterface(const std::string& interface) {
+ if (mState != State::Open) {
+ return Result::error("attempting to set option in invalid state");
+ }
+ int res = ::setsockopt(mSocket, SOL_SOCKET, SO_BINDTODEVICE,
+ interface.c_str(), interface.size());
+
+ return res == -1 ? Result::error(strerror(errno)) : Result::success();
+}
+
+Result Socket::setMulticastHopLimit(int hopLimit) {
+ if (mState != State::Open) {
+ return Result::error("attempting to set option in invalid state");
+ }
+ int res = ::setsockopt(mSocket, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
+ &hopLimit, sizeof(hopLimit));
+
+ return res == -1 ? Result::error(strerror(errno)) : Result::success();
+}
+
+Result Socket::setUnicastHopLimit(int hopLimit) {
+ if (mState != State::Open) {
+ return Result::error("attempting to set option in invalid state");
+ }
+ int res = ::setsockopt(mSocket, IPPROTO_IPV6, IPV6_UNICAST_HOPS,
+ &hopLimit, sizeof(hopLimit));
+
+ return res == -1 ? Result::error(strerror(errno)) : Result::success();
+}
+
+Result Socket::setTransparent(bool transparent) {
+ if (mState != State::Open) {
+ return Result::error("attempting to set option in invalid state");
+ }
+ int v = transparent ? 1 : 0;
+ int res = ::setsockopt(mSocket, IPPROTO_IPV6, IPV6_TRANSPARENT,
+ &v, sizeof(v));
+
+ return res == -1 ? Result::error(strerror(errno)) : Result::success();
+}
+
+Result Socket::bind(const Address& address) {
+ if (mState != State::Open) {
+ return Result::error("bind called on socket in invalid state");
+ }
+
+ int res = ::bind(mSocket, address.get<sockaddr>(), address.size());
+ if (res == -1) {
+ return Result::error(strerror(errno));
+ }
+
+ mState = State::Bound;
+ return Result::success();
+}
+
+Result Socket::receive(Message* receivingMessage) {
+ if (receivingMessage == nullptr) {
+ return Result::error("No receivingMessage provided");
+ }
+ if (mState != State::Bound) {
+ return Result::error("Attempt to receive on a socket that isn't bound");
+ }
+
+ ssize_t rxBytes = ::recv(mSocket,
+ receivingMessage->data(),
+ receivingMessage->capacity(),
+ 0);
+ if (rxBytes < 0) {
+ return Result::error(strerror(errno));
+ }
+
+ receivingMessage->setSize(static_cast<size_t>(rxBytes));
+ return Result::success();
+}
+
+Result Socket::receiveFrom(Message* receivingMessage, Address* from) {
+ if (receivingMessage == nullptr) {
+ return Result::error("No receivingMessage provided");
+ }
+ if (from == nullptr) {
+ return Result::error("No from address provided");
+ }
+ if (mState != State::Bound) {
+ return Result::error("Attempt to receive on a socket that isn't bound");
+ }
+
+ from->reset();
+ sockaddr* source = from->get<sockaddr>();
+ socklen_t sourceLen = from->size();
+ ssize_t rxBytes = ::recvfrom(mSocket,
+ receivingMessage->data(),
+ receivingMessage->capacity(),
+ 0,
+ source,
+ &sourceLen);
+ if (rxBytes < 0) {
+ return Result::error(strerror(errno));
+ }
+
+ receivingMessage->setSize(static_cast<size_t>(rxBytes));
+ return Result::success();
+}
+
+Result Socket::send(const void* data, size_t size) {
+ if (mState != State::Bound && mState != State::Open) {
+ return Result::error("Attempt to send on a socket in invalid state");
+ }
+
+ int res = ::send(mSocket, data, size, 0);
+ if (res == -1) {
+ return Result::error(strerror(errno));
+ }
+ return Result::success();
+}
+
+Result Socket::sendTo(const sockaddr& destination,
+ size_t destinationSize,
+ const void* data,
+ size_t size) {
+ if (mState != State::Bound && mState != State::Open) {
+ return Result::error("Attempt to send on a socket in invalid state");
+ }
+
+ int res = ::sendto(mSocket, data, size, 0, &destination, destinationSize);
+ if (res == -1) {
+ return Result::error(strerror(errno));
+ }
+ return Result::success();
+}
+
+Result Socket::sendTo(const in6_addr& destination,
+ const void* data,
+ size_t size) {
+ sockaddr_in6 addr;
+ memset(&addr, 0, sizeof(addr));
+ addr.sin6_family = AF_INET6;
+ addr.sin6_addr = destination;
+ return sendTo(*reinterpret_cast<sockaddr*>(&addr),
+ sizeof(addr),
+ data,
+ size);
+}
+
+Result Socket::sendFrom(const struct in6_addr& fromAddress,
+ const sockaddr& destination,
+ size_t destinationSize,
+ const void* data,
+ size_t size) {
+ struct msghdr messageHeader;
+ memset(&messageHeader, 0, sizeof(messageHeader));
+ // Even when sending this struct requires a non-const pointer, even when
+ // it's only going to be read. Do a const_cast instead of creating a
+ // method signature with illogical const-behavior.
+ messageHeader.msg_name = const_cast<struct sockaddr*>(&destination);
+ messageHeader.msg_namelen = destinationSize;
+
+ struct iovec iov;
+ messageHeader.msg_iov = &iov;
+ messageHeader.msg_iovlen = 1;
+
+ memset(&iov, 0, sizeof(iov));
+ iov.iov_base = const_cast<void*>(data);
+ iov.iov_len = size;
+
+ char control[CMSG_SPACE(sizeof(struct in6_pktinfo))] = { 0 };
+ messageHeader.msg_control = control;
+ messageHeader.msg_controllen = sizeof(control);
+
+ struct cmsghdr* controlHeader = CMSG_FIRSTHDR(&messageHeader);
+ controlHeader->cmsg_level = IPPROTO_IPV6;
+ controlHeader->cmsg_type = IPV6_PKTINFO;
+ controlHeader->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
+
+ auto packetInfoData = CMSG_DATA(controlHeader);
+ auto packetInfo = reinterpret_cast<struct in6_pktinfo*>(packetInfoData);
+ packetInfo->ipi6_addr = fromAddress;
+
+ int res = ::sendmsg(mSocket, &messageHeader, 0);
+ if (res == -1) {
+ int error = errno;
+ printf("sendmsg failed: %d\n", error);
+ return Result::error(strerror(error));
+ }
+ return Result::success();
+}
+
+Result Socket::sendFrom(const in6_addr& fromAddress,
+ const in6_addr& destination,
+ const void* data,
+ size_t size) {
+ sockaddr_in6 addr;
+ memset(&addr, 0, sizeof(addr));
+ addr.sin6_family = AF_INET6;
+ addr.sin6_addr = destination;
+
+ return sendFrom(fromAddress,
+ *reinterpret_cast<sockaddr*>(&addr),
+ sizeof(addr),
+ data,
+ size);
+}
diff --git a/wifi/ipv6proxy/socket.h b/wifi/ipv6proxy/socket.h
new file mode 100644
index 00000000..9cbdda31
--- /dev/null
+++ b/wifi/ipv6proxy/socket.h
@@ -0,0 +1,156 @@
+/*
+ * 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.
+ */
+#pragma once
+
+#include "result.h"
+
+#include <netinet/in.h>
+
+#include <stdint.h>
+#include <string>
+
+class Address;
+class Message;
+
+class Socket {
+public:
+ enum class Domain {
+ IpV4,
+ IpV6,
+ Packet,
+ };
+
+ enum class Type {
+ Stream, // A streaming protocol, use this with Infer for TCP
+ Datagram, // A datagram protocol, use this with Infer for UDP
+ Raw, // A raw socket
+ };
+ enum class Protocol {
+ Infer, // Infer the protocol from the type, such as TCP for Stream
+ Ip, // Internet Protocol for raw sockets
+ IcmpV6, // ICMPv6 control protocol for Raw sockets
+ EthIpV6, // Ethernet packets containing IPV6, for packet sockets
+ };
+
+ // Construct an empty socket object, next use open() to start using it
+ Socket();
+ // Move construct a socket, The constructed socket will be in the same state
+ // that |other| is. After this |other| will be in an undefined state and
+ // should no longer be used.
+ Socket(Socket&& other) noexcept;
+ ~Socket();
+
+ // Move the |other| socket object into this one. If this object has an open
+ // socket it will be closed first. After that this object will have the
+ // same state that |other| did. |other| will be left in an undefined state
+ // and should not be used.
+ Socket& operator=(Socket&& other) noexcept;
+
+ int get() const { return mSocket; }
+
+ Result open(int domain, int type, int protocol);
+
+ /** Options, these must be called between open and bind **/
+
+ // Bind to a specific interface regardless of the address that the socket
+ // is going to bind to.
+ Result setInterface(const std::string& interface);
+
+ // Set the hop limit for multicast traffic on the socket. Each router hop
+ // decreases this value by one, when it reaches zero the packet is
+ // discarded.
+ Result setMulticastHopLimit(int hopLimit);
+
+ // Set the hop limit for unicast traffic on the socket. Each router hop
+ // decreases this value by one, when it reaches zero the packet is
+ // discarded.
+ Result setUnicastHopLimit(int hopLimit);
+
+ // Configure the socket to be transparent. This allows packets sent to have
+ // a source address that is different from the network interface's source
+ // address.
+ Result setTransparent(bool transparent);
+
+ /** Binding **/
+
+ Result bind(const Address& address);
+
+ /** Sending and receiving **/
+
+ Result receive(Message* receivingMessage);
+ Result receiveFrom(Message* receivingMessage, Address* from);
+
+ Result send(const void* data, size_t size);
+
+ // Send a packet to a specific |destination| of any address type.
+ Result sendTo(const sockaddr& destination,
+ size_t destinationSize,
+ const void* data,
+ size_t size);
+ // Convenience function to send to a specific IPv6 address.
+ Result sendTo(const in6_addr& destination, const void* data, size_t size);
+ // Convenience method to use sendTo with a more specific sockaddr struct
+ // without having to specify the size or do the casting.
+ template<typename T>
+ Result sendTo(const T& destination, const void* data, size_t size) {
+ return sendTo(*reinterpret_cast<const sockaddr*>(&destination),
+ sizeof(destination),
+ data,
+ size);
+ }
+
+ // Send a packet with a specific source IPv6 address to a given
+ // |destination|. Rewriting the source in this manner usually requires root.
+ Result sendFrom(const in6_addr& fromAddress,
+ const sockaddr& destination,
+ size_t destinationSize,
+ const void* data,
+ size_t size);
+ Result sendFrom(const in6_addr& fromAddress,
+ const in6_addr& destination,
+ const void* data,
+ size_t size);
+ // Convenience method to use sendFrom with a more specific sockaddr struct
+ // without having to specify the size or do the casting.
+ template<typename T>
+ Result sendFrom(const in6_addr& fromAddress,
+ const T& destination,
+ const void* data,
+ size_t size) {
+ return sendFrom(fromAddress,
+ *reinterpret_cast<const sockaddr*>(&destination),
+ sizeof(destination),
+ data,
+ size);
+ }
+
+private:
+ // No copy construction or assignment allowed, support move semantics only
+ Socket(const Socket&);
+ Socket& operator=(const Socket&);
+
+ enum class State {
+ New,
+ Open,
+ Bound,
+ Moved,
+ Destructed,
+ };
+
+ State mState;
+ int mSocket;
+};
+
diff --git a/wifi/wpa_supplicant_8_lib/Android.mk b/wifi/wpa_supplicant_8_lib/Android.mk
index 76b09691..d6ee9536 100644
--- a/wifi/wpa_supplicant_8_lib/Android.mk
+++ b/wifi/wpa_supplicant_8_lib/Android.mk
@@ -74,6 +74,7 @@ LOCAL_CFLAGS := $(L_CFLAGS) \
LOCAL_SRC_FILES := $(WPA_SRC_FILE)
LOCAL_C_INCLUDES := \
+ device/google/gce/include \
$(WPA_SUPPL_DIR_INCLUDE)\
include $(BUILD_STATIC_LIBRARY)
diff --git a/x86-vendor.mk b/x86-vendor.mk
index 5fa9dc9d..4a2eb10a 100644
--- a/x86-vendor.mk
+++ b/x86-vendor.mk
@@ -8,7 +8,6 @@ PRODUCT_PROPERTY_OVERRIDES += \
# build quite specifically for the emulator, and might not be
# entirely appropriate to inherit from for on-device configurations.
PRODUCT_COPY_FILES += \
- device/generic/goldfish/data/etc/config.ini.nexus5:config.ini \
device/generic/goldfish/data/etc/advancedFeatures.ini:advancedFeatures.ini \
device/generic/goldfish/data/etc/encryptionkey.img:encryptionkey.img \
prebuilts/qemu-kernel/x86_64/$(PRODUCT_KERNEL_VERSION)/kernel-qemu2:kernel-ranchu-64
@@ -17,9 +16,5 @@ PRODUCT_SDK_ADDON_COPY_FILES += \
device/generic/goldfish/data/etc/encryptionkey.img:images/x86/encryptionkey.img \
prebuilts/qemu-kernel/x86_64/$(PRODUCT_KERNEL_VERSION)/kernel-qemu2:images/x86/kernel-ranchu-64
-PRODUCT_COPY_FILES += \
- device/generic/goldfish/data/etc/x86/emulatorip:$(TARGET_COPY_OUT_VENDOR)/bin/ip
-
-
PRODUCT_SHIPPING_API_LEVEL := 28
TARGET_USES_MKE2FS := true
diff --git a/x86_64-vendor.mk b/x86_64-vendor.mk
index a41a53e3..16ccf6a2 100644
--- a/x86_64-vendor.mk
+++ b/x86_64-vendor.mk
@@ -8,7 +8,6 @@ PRODUCT_PROPERTY_OVERRIDES += \
# build quite specifically for the emulator, and might not be
# entirely appropriate to inherit from for on-device configurations.
PRODUCT_COPY_FILES += \
- device/generic/goldfish/data/etc/config.ini.nexus5:config.ini \
device/generic/goldfish/data/etc/advancedFeatures.ini:advancedFeatures.ini \
device/generic/goldfish/data/etc/encryptionkey.img:encryptionkey.img \
prebuilts/qemu-kernel/x86_64/$(PRODUCT_KERNEL_VERSION)/kernel-qemu2:kernel-ranchu
@@ -17,9 +16,5 @@ PRODUCT_SDK_ADDON_COPY_FILES += \
device/generic/goldfish/data/etc/encryptionkey.img:images/x86_64/encryptionkey.img \
prebuilts/qemu-kernel/x86_64/$(PRODUCT_KERNEL_VERSION)/kernel-qemu2:images/x86_64/kernel-ranchu
-PRODUCT_COPY_FILES += \
- device/generic/goldfish/data/etc/x86/emulatorip:$(TARGET_COPY_OUT_VENDOR)/bin/ip
-
-
PRODUCT_SHIPPING_API_LEVEL := 28
TARGET_USES_MKE2FS := true