aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-04-08 15:59:49 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-04-08 15:59:49 +0000
commit47445d9c634fc411f1076df4c26a15027686186f (patch)
tree771212e2b66984d50d56d0c079925dcddc6d3b32
parent58fee67289addc5ff28409d312d1bf37efd07685 (diff)
parent0ee7d4c9ccedbdf0f16ea16f9c45024d325bbb31 (diff)
downloadcuttlefish-android12-mainline-tzdata2-release.tar.gz
Change-Id: I0550a6b0dc4d73ddbb3d91d52d6d89dacd50695f
-rw-r--r--Android.bp116
-rw-r--r--Android.mk6
-rw-r--r--AndroidProducts.mk14
-rw-r--r--CleanSpec.mk6
-rw-r--r--METADATA3
-rw-r--r--OWNERS1
-rw-r--r--PREUPLOAD.cfg7
-rw-r--r--README.md83
-rw-r--r--TEST_MAPPING6
-rw-r--r--build/Android.bp205
-rw-r--r--build/README.md27
-rw-r--r--build/cvd-host-package.go106
-rw-r--r--common/Android.bp (renamed from host/commands/secure_env/tpm.h)17
-rw-r--r--common/commands/Android.bp (renamed from host/libs/config/host_tools_version.h)15
-rw-r--r--common/frontend/Android.bp (renamed from host/commands/modem_simulator/unittest/main_test.cpp)14
-rw-r--r--common/frontend/socket_vsock_proxy/Android.bp13
-rw-r--r--common/frontend/socket_vsock_proxy/main.cpp123
-rw-r--r--common/libs/Android.bp25
-rw-r--r--common/libs/concurrency/multiplexer.h78
-rw-r--r--common/libs/concurrency/semaphore.h52
-rw-r--r--common/libs/concurrency/thread_annotations.h72
-rw-r--r--common/libs/confui/Android.bp36
-rw-r--r--common/libs/confui/confui.h37
-rw-r--r--common/libs/confui/packet.cpp131
-rw-r--r--common/libs/confui/packet.h71
-rw-r--r--common/libs/confui/protocol.cpp102
-rw-r--r--common/libs/confui/protocol.h63
-rw-r--r--common/libs/confui/utils.h54
-rw-r--r--common/libs/device_config/Android.bp26
-rw-r--r--common/libs/device_config/device_config.cpp45
-rw-r--r--common/libs/device_config/device_config.h67
-rw-r--r--common/libs/device_config/device_config.proto41
-rw-r--r--common/libs/device_config/device_config_shared.h29
-rw-r--r--common/libs/device_config/guest_device_config.cpp48
-rw-r--r--common/libs/device_config/host_device_config.cpp109
-rw-r--r--common/libs/fs/Android.bp14
-rw-r--r--common/libs/fs/TEST_MAPPING8
-rw-r--r--common/libs/fs/shared_buf.cc38
-rw-r--r--common/libs/fs/shared_buf.h24
-rw-r--r--common/libs/fs/shared_fd.cpp110
-rw-r--r--common/libs/fs/shared_fd.h120
-rw-r--r--common/libs/fs/shared_fd_stream.cpp110
-rw-r--r--common/libs/fs/shared_fd_stream.h73
-rw-r--r--common/libs/fs/shared_fd_test.cpp4
-rw-r--r--common/libs/fs/shared_select.h4
-rw-r--r--common/libs/net/Android.bp12
-rw-r--r--common/libs/net/TEST_MAPPING8
-rw-r--r--common/libs/net/netlink_client.cpp4
-rw-r--r--common/libs/net/netlink_client.h4
-rw-r--r--common/libs/net/netlink_request.cpp4
-rw-r--r--common/libs/net/netlink_request.h4
-rw-r--r--common/libs/net/netlink_request_test.cpp26
-rw-r--r--common/libs/net/network_interface.h4
-rw-r--r--common/libs/net/network_interface_manager.cpp4
-rw-r--r--common/libs/net/network_interface_manager.h4
-rw-r--r--common/libs/security/Android.bp61
-rw-r--r--common/libs/security/gatekeeper_channel.cpp98
-rw-r--r--common/libs/security/gatekeeper_channel.h87
-rw-r--r--common/libs/security/keymaster_channel.cpp98
-rw-r--r--common/libs/security/keymaster_channel.h87
-rw-r--r--common/libs/security/keymaster_channel_test.cpp78
-rw-r--r--common/libs/tcp_socket/Android.bp (renamed from host/commands/powerwash_cvd/Android.bp)20
-rw-r--r--common/libs/tcp_socket/tcp_socket.cpp (renamed from common/libs/utils/tcp_socket.cpp)21
-rw-r--r--common/libs/tcp_socket/tcp_socket.h (renamed from common/libs/utils/tcp_socket.h)10
-rw-r--r--common/libs/thread_safe_queue/thread_safe_queue.h (renamed from common/libs/concurrency/thread_safe_queue.h)18
-rw-r--r--common/libs/threads/thread_annotations.h79
-rw-r--r--common/libs/time/Android.bp (renamed from recovery/Android.bp)30
-rw-r--r--common/libs/time/TEST_MAPPING8
-rw-r--r--common/libs/time/monotonic_time.cpp (renamed from common/libs/device_config/device_config_shared.cpp)18
-rw-r--r--common/libs/time/monotonic_time.h19
-rw-r--r--common/libs/time/monotonic_time_test.cpp110
-rw-r--r--common/libs/usbforward/protocol.h153
-rw-r--r--common/libs/utils/Android.bp12
-rw-r--r--common/libs/utils/archive.cpp16
-rw-r--r--common/libs/utils/archive.h4
-rw-r--r--common/libs/utils/base64.cpp51
-rw-r--r--common/libs/utils/cf_endian.h56
-rw-r--r--common/libs/utils/environment.cpp47
-rw-r--r--common/libs/utils/environment.h17
-rw-r--r--common/libs/utils/files.cpp112
-rw-r--r--common/libs/utils/files.h14
-rw-r--r--common/libs/utils/network.cpp206
-rw-r--r--common/libs/utils/network.h23
-rw-r--r--common/libs/utils/size_utils.cpp8
-rw-r--r--common/libs/utils/size_utils.h12
-rw-r--r--common/libs/utils/subprocess.cpp103
-rw-r--r--common/libs/utils/subprocess.h75
-rw-r--r--common/libs/utils/tee_logging.cpp60
-rw-r--r--common/libs/utils/tee_logging.h12
-rw-r--r--common/libs/utils/users.cpp9
-rw-r--r--common/libs/utils/users.h4
-rw-r--r--default-permissions.xml33
-rw-r--r--guest/Android.bp16
-rw-r--r--guest/commands/Android.bp21
-rw-r--r--guest/commands/bt_vhci_forwarder/Android.bp20
-rw-r--r--guest/commands/bt_vhci_forwarder/main.cpp153
-rw-r--r--guest/commands/ip_link_add/Android.bp (renamed from tests/powerwash/Android.bp)20
-rw-r--r--guest/commands/ip_link_add/main.cpp75
-rw-r--r--guest/commands/rename_netiface/Android.bp4
-rw-r--r--guest/commands/rename_netiface/main.cpp10
-rw-r--r--guest/commands/sensor_injection/Android.bp18
-rw-r--r--guest/commands/sensor_injection/main.cpp166
-rw-r--r--guest/commands/setup_wifi/Android.bp4
-rw-r--r--guest/commands/setup_wifi/main.cpp13
-rw-r--r--guest/commands/vport_trigger/Android.bp (renamed from tests/recovery/Android.bp)20
-rw-r--r--guest/commands/vport_trigger/main.cpp86
-rw-r--r--guest/commands/vsoc_input_service/Android.bp5
-rw-r--r--guest/commands/vsoc_input_service/main.cpp2
-rw-r--r--guest/commands/vsoc_input_service/virtual_device_base.cpp3
-rw-r--r--guest/commands/vsoc_input_service/virtual_device_base.h4
-rw-r--r--guest/commands/vsoc_input_service/virtual_keyboard.cpp4
-rw-r--r--guest/commands/vsoc_input_service/virtual_keyboard.h4
-rw-r--r--guest/commands/vsoc_input_service/virtual_power_button.cpp4
-rw-r--r--guest/commands/vsoc_input_service/virtual_power_button.h4
-rw-r--r--guest/commands/vsoc_input_service/virtual_touchscreen.cpp4
-rw-r--r--guest/commands/vsoc_input_service/virtual_touchscreen.h4
-rw-r--r--guest/commands/vsoc_input_service/vsoc_input_service.cpp35
-rw-r--r--guest/commands/vsoc_input_service/vsoc_input_service.h8
-rw-r--r--guest/commands/vsock_logcat/Android.bp (renamed from host/commands/bt_connector/Android.bp)15
-rw-r--r--guest/commands/vsock_logcat/main.cpp142
-rw-r--r--guest/hals/Android.bp20
-rw-r--r--guest/hals/audio/Android.bp4
-rw-r--r--guest/hals/audio/audio_hw.c20
-rw-r--r--guest/hals/bt/OWNERS2
-rw-r--r--guest/hals/bt/data/Android.bp9
-rw-r--r--guest/hals/bt/data/default_commands4
-rw-r--r--guest/hals/bt/remote/Android.bp32
-rw-r--r--guest/hals/bt/remote/android.hardware.bluetooth@1.1-service.remote.rc4
-rw-r--r--guest/hals/bt/remote/remote_bluetooth.cpp195
-rw-r--r--guest/hals/bt/remote/remote_bluetooth.h101
-rw-r--r--guest/hals/bt/remote/service.cpp39
-rw-r--r--guest/hals/camera/Android.mk182
-rw-r--r--guest/hals/camera/CallbackNotifier.cpp313
-rw-r--r--guest/hals/camera/CallbackNotifier.h233
-rw-r--r--guest/hals/camera/CameraConfiguration.cpp300
-rw-r--r--guest/hals/camera/CameraConfiguration.h59
-rw-r--r--guest/hals/camera/Compressor.cpp234
-rw-r--r--guest/hals/camera/Compressor.h77
-rw-r--r--guest/hals/camera/Converters.cpp150
-rw-r--r--guest/hals/camera/Converters.h320
-rw-r--r--guest/hals/camera/EmulatedBaseCamera.cpp86
-rw-r--r--guest/hals/camera/EmulatedBaseCamera.h129
-rw-r--r--guest/hals/camera/EmulatedCamera.cpp1034
-rw-r--r--guest/hals/camera/EmulatedCamera.h407
-rw-r--r--guest/hals/camera/EmulatedCamera2.cpp381
-rw-r--r--guest/hals/camera/EmulatedCamera2.h246
-rw-r--r--guest/hals/camera/EmulatedCamera3.cpp265
-rw-r--r--guest/hals/camera/EmulatedCamera3.h196
-rw-r--r--guest/hals/camera/EmulatedCameraCommon.h57
-rw-r--r--guest/hals/camera/EmulatedCameraDevice.cpp418
-rw-r--r--guest/hals/camera/EmulatedCameraDevice.h553
-rw-r--r--guest/hals/camera/EmulatedCameraFactory.cpp297
-rw-r--r--guest/hals/camera/EmulatedCameraFactory.h191
-rw-r--r--guest/hals/camera/EmulatedCameraHal.cpp57
-rw-r--r--guest/hals/camera/EmulatedCameraHotplugThread.cpp345
-rw-r--r--guest/hals/camera/EmulatedCameraHotplugThread.h74
-rw-r--r--guest/hals/camera/EmulatedFakeCamera.cpp105
-rw-r--r--guest/hals/camera/EmulatedFakeCamera.h74
-rw-r--r--guest/hals/camera/EmulatedFakeCamera2.cpp2606
-rw-r--r--guest/hals/camera/EmulatedFakeCamera2.h421
-rw-r--r--guest/hals/camera/EmulatedFakeCamera3.cpp2661
-rw-r--r--guest/hals/camera/EmulatedFakeCamera3.h289
-rw-r--r--guest/hals/camera/EmulatedFakeCameraDevice.cpp427
-rw-r--r--guest/hals/camera/EmulatedFakeCameraDevice.h192
-rw-r--r--guest/hals/camera/EmulatedQemuCamera.cpp111
-rw-r--r--guest/hals/camera/EmulatedQemuCamera.h72
-rw-r--r--guest/hals/camera/EmulatedQemuCamera2.cpp47
-rw-r--r--guest/hals/camera/EmulatedQemuCamera2.h66
-rw-r--r--guest/hals/camera/EmulatedQemuCameraDevice.cpp251
-rw-r--r--guest/hals/camera/EmulatedQemuCameraDevice.h121
-rw-r--r--guest/hals/camera/Exif.cpp413
-rw-r--r--guest/hals/camera/Exif.h41
-rw-r--r--guest/hals/camera/GrallocModule.h56
-rw-r--r--guest/hals/camera/JpegCompressor.cpp92
-rw-r--r--guest/hals/camera/JpegCompressor.h92
-rw-r--r--guest/hals/camera/JpegStub.cpp67
-rw-r--r--guest/hals/camera/JpegStub.h43
-rw-r--r--guest/hals/camera/PreviewWindow.cpp204
-rw-r--r--guest/hals/camera/PreviewWindow.h165
-rw-r--r--guest/hals/camera/QemuClient.cpp516
-rw-r--r--guest/hals/camera/QemuClient.h433
-rw-r--r--guest/hals/camera/Thumbnail.cpp170
-rw-r--r--guest/hals/camera/Thumbnail.h37
-rw-r--r--guest/hals/camera/VSoCEmulatedCameraHotplugThread.cpp87
-rw-r--r--guest/hals/camera/fake-pipeline2/Base.h63
-rw-r--r--guest/hals/camera/fake-pipeline2/JpegCompressor.cpp286
-rw-r--r--guest/hals/camera/fake-pipeline2/JpegCompressor.h121
-rw-r--r--guest/hals/camera/fake-pipeline2/Scene.cpp436
-rw-r--r--guest/hals/camera/fake-pipeline2/Scene.h178
-rw-r--r--guest/hals/camera/fake-pipeline2/Sensor.cpp591
-rw-r--r--guest/hals/camera/fake-pipeline2/Sensor.h244
-rw-r--r--guest/hals/gatekeeper/OWNERS1
-rw-r--r--guest/hals/gatekeeper/remote/Android.bp55
-rw-r--r--guest/hals/gatekeeper/remote/android.hardware.gatekeeper@1.0-service.remote.rc4
-rw-r--r--guest/hals/gatekeeper/remote/android.hardware.gatekeeper@1.0-service.remote.xml11
-rw-r--r--guest/hals/gatekeeper/remote/remote_gatekeeper.cpp169
-rw-r--r--guest/hals/gatekeeper/remote/remote_gatekeeper.h90
-rw-r--r--guest/hals/gatekeeper/remote/service.cpp61
-rw-r--r--guest/hals/gps/Android.bp (renamed from guest/hals/rild/Android.bp)40
-rw-r--r--guest/hals/gps/gps_thread.cpp200
-rw-r--r--guest/hals/gps/gps_thread.h79
-rw-r--r--guest/hals/gps/gps_vsoc.cpp258
-rw-r--r--guest/hals/gralloc/legacy/Android.mk57
-rw-r--r--guest/hals/gralloc/legacy/gralloc.cpp202
-rw-r--r--guest/hals/gralloc/legacy/gralloc_vsoc_priv.h340
-rw-r--r--guest/hals/gralloc/legacy/mapper.cpp157
-rw-r--r--guest/hals/gralloc/legacy/region_registry.cpp249
-rw-r--r--guest/hals/gralloc/legacy/region_registry.h (renamed from guest/libs/wpa_supplicant_8_lib/driver_cmd_nl80211.h)34
-rw-r--r--guest/hals/health/Android.bp4
-rw-r--r--guest/hals/health/storage/Android.bp15
-rw-r--r--guest/hals/health/storage/Storage.cpp35
-rw-r--r--guest/hals/health/storage/Storage.h35
-rw-r--r--guest/hals/health/storage/android.hardware.health.storage@1.0-service.cuttlefish.rc (renamed from guest/hals/health/storage/android.hardware.health.storage-service.cuttlefish.rc)4
-rw-r--r--guest/hals/health/storage/manifest_android.hardware.health.storage@1.0.cuttlefish.xml (renamed from guest/hals/health/storage/manifest_android.hardware.health.storage.cuttlefish.xml)10
-rw-r--r--guest/hals/health/storage/service.cpp37
-rw-r--r--guest/hals/hwcomposer/common/Android.bp (renamed from host/libs/audio_connector/Android.bp)42
-rw-r--r--guest/hals/hwcomposer/common/base_composer.cpp114
-rw-r--r--guest/hals/hwcomposer/common/base_composer.h53
-rw-r--r--guest/hals/hwcomposer/common/cpu_composer.cpp697
-rw-r--r--guest/hals/hwcomposer/common/cpu_composer.h48
-rw-r--r--guest/hals/hwcomposer/common/drm_utils.cpp180
-rw-r--r--guest/hals/hwcomposer/common/drm_utils.h (renamed from host/commands/metrics/metrics_defs.h)16
-rw-r--r--guest/hals/hwcomposer/common/geometry_utils.cpp41
-rw-r--r--guest/hals/hwcomposer/common/geometry_utils.h (renamed from host/commands/secure_env/tpm_commands.h)12
-rw-r--r--guest/hals/hwcomposer/common/gralloc_utils.cpp529
-rw-r--r--guest/hals/hwcomposer/common/gralloc_utils.h134
-rw-r--r--guest/hals/hwcomposer/common/hwcomposer.cpp574
-rw-r--r--guest/hals/hwcomposer/common/hwcomposer.h33
-rw-r--r--guest/hals/hwcomposer/common/screen_view.cpp38
-rw-r--r--guest/hals/hwcomposer/common/screen_view.h62
-rw-r--r--guest/hals/hwcomposer/common/stats_keeper.cpp260
-rw-r--r--guest/hals/hwcomposer/common/stats_keeper.h224
-rw-r--r--guest/hals/hwcomposer/cutf_cvm/Android.bp100
-rw-r--r--guest/hals/hwcomposer/cutf_cvm/HWC2.cpp2845
-rw-r--r--guest/hals/hwcomposer/cutf_cvm/HWC2.h743
-rw-r--r--guest/hals/hwcomposer/cutf_cvm/MiniFence.cpp (renamed from host/libs/config/kernel_args.h)29
-rw-r--r--guest/hals/hwcomposer/cutf_cvm/MiniFence.h59
-rw-r--r--guest/hals/hwcomposer/cutf_cvm/hwcomposer.cpp52
-rw-r--r--guest/hals/hwcomposer/cutf_cvm/vsocket_screen_view.cpp139
-rw-r--r--guest/hals/hwcomposer/cutf_cvm/vsocket_screen_view.h64
-rw-r--r--guest/hals/keymaster/OWNERS1
-rw-r--r--guest/hals/keymaster/remote/Android.bp53
-rw-r--r--guest/hals/keymaster/remote/android.hardware.keymaster@4.1-service.remote.rc6
-rw-r--r--guest/hals/keymaster/remote/android.hardware.keymaster@4.1-service.remote.xml7
-rw-r--r--guest/hals/keymaster/remote/remote_keymaster.cpp218
-rw-r--r--guest/hals/keymaster/remote/remote_keymaster.h79
-rw-r--r--guest/hals/keymaster/remote/remote_keymaster4_device.cpp631
-rw-r--r--guest/hals/keymaster/remote/remote_keymaster4_device.h110
-rw-r--r--guest/hals/keymaster/remote/service4.cpp66
-rw-r--r--guest/hals/keymint/OWNERS1
-rw-r--r--guest/hals/keymint/remote/Android.bp62
-rw-r--r--guest/hals/keymint/remote/android.hardware.security.keymint-service.remote.rc3
-rw-r--r--guest/hals/keymint/remote/android.hardware.security.keymint-service.remote.xml10
-rw-r--r--guest/hals/keymint/remote/android.hardware.security.secureclock-service.remote.xml6
-rw-r--r--guest/hals/keymint/remote/android.hardware.security.sharedsecret-service.remote.xml6
-rw-r--r--guest/hals/keymint/remote/remote_keymaster.cpp241
-rw-r--r--guest/hals/keymint/remote/remote_keymaster.h95
-rw-r--r--guest/hals/keymint/remote/remote_keymint_device.cpp422
-rw-r--r--guest/hals/keymint/remote/remote_keymint_device.h90
-rw-r--r--guest/hals/keymint/remote/remote_keymint_operation.cpp132
-rw-r--r--guest/hals/keymint/remote/remote_keymint_operation.h69
-rw-r--r--guest/hals/keymint/remote/remote_secure_clock.cpp54
-rw-r--r--guest/hals/keymint/remote/remote_secure_clock.h43
-rw-r--r--guest/hals/keymint/remote/remote_shared_secret.cpp68
-rw-r--r--guest/hals/keymint/remote/remote_shared_secret.h44
-rw-r--r--guest/hals/keymint/remote/service.cpp83
l---------guest/hals/ril/.clang-format1
-rw-r--r--guest/hals/ril/Android.mk51
-rw-r--r--guest/hals/ril/cuttlefish_ril.cpp2609
-rw-r--r--guest/hals/ril/cuttlefish_ril.h (renamed from host/commands/run_cvd/server_loop.h)16
-rw-r--r--guest/hals/ril/libril/Android.mk65
-rw-r--r--guest/hals/ril/libril/RilSapSocket.cpp (renamed from guest/hals/ril/reference-libril/RilSapSocket.cpp)2
-rw-r--r--guest/hals/ril/libril/ril.cpp (renamed from guest/hals/ril/reference-libril/ril.cpp)97
-rw-r--r--guest/hals/ril/libril/ril.h (renamed from guest/hals/ril/reference-libril/ril.h)1049
-rw-r--r--guest/hals/ril/libril/ril_commands.h174
-rw-r--r--guest/hals/ril/libril/ril_event.cpp (renamed from guest/hals/ril/reference-libril/ril_event.cpp)0
-rw-r--r--guest/hals/ril/libril/ril_ex.h (renamed from guest/hals/ril/reference-libril/ril_ex.h)2
-rw-r--r--guest/hals/ril/libril/ril_service.cpp (renamed from guest/hals/ril/reference-libril/ril_service.cpp)3838
-rw-r--r--guest/hals/ril/libril/ril_service.h (renamed from guest/hals/ril/reference-libril/ril_service.h)85
-rw-r--r--guest/hals/ril/libril/ril_unsol_commands.h66
-rw-r--r--guest/hals/ril/libril/sap_service.cpp (renamed from guest/hals/ril/reference-libril/sap_service.cpp)0
-rw-r--r--guest/hals/ril/reference-libril/Android.bp61
-rw-r--r--guest/hals/ril/reference-libril/RilSapSocket.h200
-rw-r--r--guest/hals/ril/reference-libril/RilSocket.h70
-rw-r--r--guest/hals/ril/reference-libril/rilSocketQueue.h167
-rw-r--r--guest/hals/ril/reference-libril/ril_commands.h189
-rw-r--r--guest/hals/ril/reference-libril/ril_config.cpp574
-rw-r--r--guest/hals/ril/reference-libril/ril_config_commands.h24
-rw-r--r--guest/hals/ril/reference-libril/ril_config_unsol_commands.h17
-rw-r--r--guest/hals/ril/reference-libril/ril_event.h52
-rw-r--r--guest/hals/ril/reference-libril/ril_internal.h98
-rw-r--r--guest/hals/ril/reference-libril/ril_unsol_commands.h68
-rw-r--r--guest/hals/ril/reference-libril/sap_service.h33
-rw-r--r--guest/hals/ril/reference-ril/Android.bp67
-rw-r--r--guest/hals/ril/reference-ril/MODULE_LICENSE_APACHE20
-rw-r--r--guest/hals/ril/reference-ril/NOTICE190
-rw-r--r--guest/hals/ril/reference-ril/OWNERS9
-rw-r--r--guest/hals/ril/reference-ril/at_tok.c190
-rw-r--r--guest/hals/ril/reference-ril/at_tok.h32
-rw-r--r--guest/hals/ril/reference-ril/atchannel.c972
-rw-r--r--guest/hals/ril/reference-ril/atchannel.h124
-rw-r--r--guest/hals/ril/reference-ril/base64util.cpp59
-rw-r--r--guest/hals/ril/reference-ril/base64util.h29
-rw-r--r--guest/hals/ril/reference-ril/misc.c50
-rw-r--r--guest/hals/ril/reference-ril/misc.h24
-rw-r--r--guest/hals/ril/reference-ril/reference-ril.c6257
-rw-r--r--guest/hals/rild/Android.mk47
-rw-r--r--guest/hals/rild/rild_cuttlefish.c27
-rw-r--r--guest/hals/rild/rild_cuttlefish.legacy.rc5
-rw-r--r--guest/hals/rild/rild_cuttlefish.rc2
-rw-r--r--guest/libs/wpa_supplicant_8_lib/Android.mk82
-rw-r--r--guest/libs/wpa_supplicant_8_lib/driver_cmd_nl80211.c86
-rw-r--r--guest/monitoring/Android.bp19
-rw-r--r--guest/monitoring/cuttlefish_service/Android.bp30
-rw-r--r--guest/monitoring/cuttlefish_service/Android.mk (renamed from vsoc_x86_only/BoardConfig.mk)27
-rw-r--r--guest/monitoring/cuttlefish_service/java/com/android/google/gce/gceservice/BootReporter.java (renamed from guest/monitoring/cuttlefish_service/java/com/android/google/gce/gceservice/EventReporter.java)15
-rw-r--r--guest/monitoring/cuttlefish_service/java/com/android/google/gce/gceservice/ConnectivityChecker.java24
-rw-r--r--guest/monitoring/cuttlefish_service/java/com/android/google/gce/gceservice/GceService.java71
-rw-r--r--guest/monitoring/cuttlefish_service/java/com/android/google/gce/gceservice/GceWifiManager.java8
-rw-r--r--guest/monitoring/tombstone_transmit/Android.bp4
-rw-r--r--guest/monitoring/tombstone_transmit/tombstone_transmit.cpp2
-rw-r--r--guest/services/suspend_blocker/Android.bp6
-rw-r--r--guest/services/suspend_blocker/suspend_blocker.cpp5
-rw-r--r--host/Android.bp20
-rw-r--r--host/commands/Android.bp28
-rw-r--r--host/commands/adbshell/Android.bp6
-rw-r--r--host/commands/adbshell/main.cpp16
-rw-r--r--host/commands/assemble_cvd/Android.bp45
-rw-r--r--host/commands/assemble_cvd/alloc.cc150
-rw-r--r--host/commands/assemble_cvd/alloc.h41
-rw-r--r--host/commands/assemble_cvd/assemble_cvd.cc235
-rw-r--r--host/commands/assemble_cvd/assembler_defs.h51
-rw-r--r--host/commands/assemble_cvd/boot_config.cc120
-rw-r--r--host/commands/assemble_cvd/boot_image_unpacker.cc156
-rw-r--r--host/commands/assemble_cvd/boot_image_unpacker.h88
-rw-r--r--host/commands/assemble_cvd/boot_image_utils.cc332
-rw-r--r--host/commands/assemble_cvd/boot_image_utils.h38
-rw-r--r--host/commands/assemble_cvd/cdisk_spec.proto (renamed from host/libs/image_aggregator/cdisk_spec.proto)0
-rwxr-xr-xhost/commands/assemble_cvd/cf_bpttool.py1649
-rw-r--r--host/commands/assemble_cvd/clean.cc156
-rw-r--r--host/commands/assemble_cvd/clean.h30
-rw-r--r--host/commands/assemble_cvd/data_image.cc (renamed from host/libs/config/data_image.cpp)84
-rw-r--r--host/commands/assemble_cvd/data_image.h11
-rw-r--r--host/commands/assemble_cvd/disk_flags.cc596
-rw-r--r--host/commands/assemble_cvd/flags.cc1495
-rw-r--r--host/commands/assemble_cvd/flags.h25
-rw-r--r--host/commands/assemble_cvd/image_aggregator.cc325
-rw-r--r--host/commands/assemble_cvd/image_aggregator.h35
-rw-r--r--host/commands/assemble_cvd/mbr.h (renamed from host/libs/config/mbr.h)3
-rw-r--r--host/commands/assemble_cvd/misc_info.cc55
-rw-r--r--host/commands/assemble_cvd/misc_info.h7
-rw-r--r--host/commands/assemble_cvd/super_image_mixer.cc63
-rw-r--r--host/commands/assemble_cvd/super_image_mixer.h12
-rw-r--r--host/commands/bt_connector/OWNERS2
-rw-r--r--host/commands/bt_connector/main.cpp101
-rw-r--r--host/commands/config_server/Android.bp12
-rw-r--r--host/commands/config_server/main.cpp16
-rw-r--r--host/commands/console_forwarder/Android.bp10
-rw-r--r--host/commands/console_forwarder/main.cpp216
-rw-r--r--host/commands/cvd_host_bugreport/main.cc108
-rw-r--r--host/commands/cvd_status/Android.bp11
-rw-r--r--host/commands/cvd_status/cvd_status.cc16
-rw-r--r--host/commands/fetcher/Android.bp47
-rw-r--r--host/commands/fetcher/build_api.cc65
-rw-r--r--host/commands/fetcher/build_api.h11
-rw-r--r--host/commands/fetcher/credential_source.cc5
-rw-r--r--host/commands/fetcher/credential_source.h4
-rw-r--r--host/commands/fetcher/curl_wrapper.cc11
-rw-r--r--host/commands/fetcher/curl_wrapper.h4
-rw-r--r--host/commands/fetcher/fetch_cvd.cc195
-rw-r--r--host/commands/fetcher/install_zip.cc2
-rw-r--r--host/commands/gnss_grpc_proxy/Android.bp91
-rw-r--r--host/commands/gnss_grpc_proxy/gnss_grpc_proxy.cpp235
-rw-r--r--host/commands/gnss_grpc_proxy/gnss_grpc_proxy.proto19
-rw-r--r--host/commands/gnss_grpc_proxy/grpcpp.h68
-rw-r--r--host/commands/kernel_log_monitor/Android.bp23
-rw-r--r--host/commands/kernel_log_monitor/kernel_log_server.cc68
-rw-r--r--host/commands/kernel_log_monitor/kernel_log_server.h27
-rw-r--r--host/commands/kernel_log_monitor/main.cc31
-rw-r--r--host/commands/kernel_log_monitor/utils.cc72
-rw-r--r--host/commands/kernel_log_monitor/utils.h37
-rw-r--r--host/commands/launch/Android.bp16
-rw-r--r--host/commands/launch/filesystem_explorer.cc16
-rw-r--r--host/commands/launch/filesystem_explorer.h2
-rw-r--r--host/commands/launch/flag_forwarder.cc12
-rw-r--r--host/commands/launch/launch_cvd.cc142
-rw-r--r--host/commands/log_tee/Android.bp11
-rw-r--r--host/commands/log_tee/log_tee.cpp23
-rw-r--r--host/commands/logcat_receiver/Android.bp10
-rw-r--r--host/commands/logcat_receiver/main.cpp75
-rw-r--r--host/commands/metrics/Android.bp36
-rw-r--r--host/commands/metrics/metrics.cc56
-rw-r--r--host/commands/metrics/proto/Android.bp63
-rw-r--r--host/commands/metrics/proto/cf_log.proto42
-rw-r--r--host/commands/metrics/proto/cf_metrics_event.proto143
-rw-r--r--host/commands/metrics/proto/clientanalytics.proto21
-rw-r--r--host/commands/metrics/proto/common.proto16
-rw-r--r--host/commands/mk_cdisk/Android.bp41
-rw-r--r--host/commands/mk_cdisk/mk_cdisk.cc146
-rw-r--r--host/commands/modem_simulator/Android.bp126
-rw-r--r--host/commands/modem_simulator/call_service.cpp719
-rw-r--r--host/commands/modem_simulator/call_service.h150
-rw-r--r--host/commands/modem_simulator/cf_device_config.cpp76
-rw-r--r--host/commands/modem_simulator/channel_monitor.cpp279
-rw-r--r--host/commands/modem_simulator/channel_monitor.h97
-rw-r--r--host/commands/modem_simulator/command_parser.cpp125
-rw-r--r--host/commands/modem_simulator/command_parser.h98
-rw-r--r--host/commands/modem_simulator/data_service.cpp344
-rw-r--r--host/commands/modem_simulator/data_service.h63
-rw-r--r--host/commands/modem_simulator/device_config.h38
-rwxr-xr-xhost/commands/modem_simulator/files/iccprofile_for_sim0.xml181
-rwxr-xr-xhost/commands/modem_simulator/files/iccprofile_for_sim0_for_CtsCarrierApiTestCases.xml207
-rw-r--r--host/commands/modem_simulator/files/numeric_operator.xml19
-rw-r--r--host/commands/modem_simulator/main.cpp163
-rw-r--r--host/commands/modem_simulator/misc_service.cpp167
-rw-r--r--host/commands/modem_simulator/misc_service.h44
-rw-r--r--host/commands/modem_simulator/modem_service.cpp147
-rw-r--r--host/commands/modem_simulator/modem_service.h115
-rw-r--r--host/commands/modem_simulator/modem_simulator.cpp161
-rw-r--r--host/commands/modem_simulator/modem_simulator.h68
-rw-r--r--host/commands/modem_simulator/network_service.cpp1266
-rw-r--r--host/commands/modem_simulator/network_service.h320
-rw-r--r--host/commands/modem_simulator/nvram_config.cpp200
-rw-r--r--host/commands/modem_simulator/nvram_config.h94
-rw-r--r--host/commands/modem_simulator/pdu_parser.cpp300
-rw-r--r--host/commands/modem_simulator/pdu_parser.h57
-rw-r--r--host/commands/modem_simulator/sim_service.cpp1697
-rw-r--r--host/commands/modem_simulator/sim_service.h271
-rw-r--r--host/commands/modem_simulator/sms_service.cpp390
-rw-r--r--host/commands/modem_simulator/sms_service.h89
-rw-r--r--host/commands/modem_simulator/stk_service.cpp284
-rw-r--r--host/commands/modem_simulator/stk_service.h76
-rw-r--r--host/commands/modem_simulator/sup_service.cpp320
-rw-r--r--host/commands/modem_simulator/sup_service.h108
-rw-r--r--host/commands/modem_simulator/thread_looper.cpp130
-rw-r--r--host/commands/modem_simulator/thread_looper.h92
-rw-r--r--host/commands/modem_simulator/unittest/command_parser_test.cpp103
-rwxr-xr-xhost/commands/modem_simulator/unittest/iccfile.txt176
-rw-r--r--host/commands/modem_simulator/unittest/pdu_parser_test.cpp55
-rw-r--r--host/commands/modem_simulator/unittest/service_test.cpp774
-rw-r--r--host/commands/powerwash_cvd/powerwash_cvd.cc163
-rw-r--r--host/commands/restart_cvd/Android.bp37
-rw-r--r--host/commands/restart_cvd/restart_cvd.cc164
-rw-r--r--host/commands/run_cvd/Android.bp23
-rw-r--r--host/commands/run_cvd/boot_state_machine.cc110
-rw-r--r--host/commands/run_cvd/boot_state_machine.h53
-rw-r--r--host/commands/run_cvd/kernel_args.cc151
-rw-r--r--host/commands/run_cvd/kernel_args.h (renamed from host/libs/config/bootconfig_args.h)15
-rw-r--r--host/commands/run_cvd/launch.cc532
-rw-r--r--host/commands/run_cvd/launch.h92
-rw-r--r--host/commands/run_cvd/launch_adb.cpp156
-rw-r--r--host/commands/run_cvd/launch_modem.cpp117
-rw-r--r--host/commands/run_cvd/launch_streamer.cpp224
-rw-r--r--host/commands/run_cvd/main.cc384
-rw-r--r--host/commands/run_cvd/pre_launch_initializers.h (renamed from host/frontend/webrtc/lib/audio_sink.h)26
-rw-r--r--host/commands/run_cvd/process_monitor.cc312
-rw-r--r--host/commands/run_cvd/process_monitor.h47
-rw-r--r--host/commands/run_cvd/runner_defs.h12
-rw-r--r--host/commands/run_cvd/server_loop.cpp213
-rw-r--r--host/commands/secure_env/Android.bp77
-rw-r--r--host/commands/secure_env/OWNERS2
-rw-r--r--host/commands/secure_env/composite_serialization.cpp48
-rw-r--r--host/commands/secure_env/composite_serialization.h39
-rw-r--r--host/commands/secure_env/device_tpm.cpp54
-rw-r--r--host/commands/secure_env/device_tpm.h35
-rw-r--r--host/commands/secure_env/encrypted_serializable.cpp300
-rw-r--r--host/commands/secure_env/encrypted_serializable.h59
-rw-r--r--host/commands/secure_env/fragile_tpm_storage.cpp240
-rw-r--r--host/commands/secure_env/fragile_tpm_storage.h60
-rw-r--r--host/commands/secure_env/gatekeeper_responder.cpp62
-rw-r--r--host/commands/secure_env/gatekeeper_responder.h31
-rw-r--r--host/commands/secure_env/gatekeeper_storage.h42
-rw-r--r--host/commands/secure_env/hmac_serializable.cpp127
-rw-r--r--host/commands/secure_env/hmac_serializable.h54
-rw-r--r--host/commands/secure_env/in_process_tpm.cpp156
-rw-r--r--host/commands/secure_env/in_process_tpm.h47
-rw-r--r--host/commands/secure_env/insecure_fallback_storage.cpp149
-rw-r--r--host/commands/secure_env/insecure_fallback_storage.h56
-rw-r--r--host/commands/secure_env/json_serializable.cpp153
-rw-r--r--host/commands/secure_env/json_serializable.h25
-rw-r--r--host/commands/secure_env/keymaster_responder.cpp109
-rw-r--r--host/commands/secure_env/keymaster_responder.h31
-rw-r--r--host/commands/secure_env/primary_key_builder.cpp135
-rw-r--r--host/commands/secure_env/primary_key_builder.h42
-rw-r--r--host/commands/secure_env/secure_env.cpp182
-rw-r--r--host/commands/secure_env/soft_gatekeeper.h168
-rw-r--r--host/commands/secure_env/tpm_attestation_record.cpp81
-rw-r--r--host/commands/secure_env/tpm_attestation_record.h43
-rw-r--r--host/commands/secure_env/tpm_auth.cpp43
-rw-r--r--host/commands/secure_env/tpm_auth.h43
-rw-r--r--host/commands/secure_env/tpm_commands.cpp147
-rw-r--r--host/commands/secure_env/tpm_encrypt_decrypt.cpp100
-rw-r--r--host/commands/secure_env/tpm_encrypt_decrypt.h50
-rw-r--r--host/commands/secure_env/tpm_gatekeeper.cpp242
-rw-r--r--host/commands/secure_env/tpm_gatekeeper.h83
-rw-r--r--host/commands/secure_env/tpm_hmac.cpp155
-rw-r--r--host/commands/secure_env/tpm_hmac.h51
-rw-r--r--host/commands/secure_env/tpm_key_blob_maker.cpp192
-rw-r--r--host/commands/secure_env/tpm_key_blob_maker.h70
-rw-r--r--host/commands/secure_env/tpm_keymaster_context.cpp321
-rw-r--r--host/commands/secure_env/tpm_keymaster_context.h105
-rw-r--r--host/commands/secure_env/tpm_keymaster_enforcement.cpp334
-rw-r--r--host/commands/secure_env/tpm_keymaster_enforcement.h61
-rw-r--r--host/commands/secure_env/tpm_random_source.cpp99
-rw-r--r--host/commands/secure_env/tpm_random_source.h38
-rw-r--r--host/commands/secure_env/tpm_resource_manager.cpp77
-rw-r--r--host/commands/secure_env/tpm_resource_manager.h62
-rw-r--r--host/commands/secure_env/tpm_serialize.cpp84
-rw-r--r--host/commands/secure_env/tpm_serialize.h52
-rw-r--r--host/commands/stop_cvd/Android.bp12
-rw-r--r--host/commands/stop_cvd/main.cc87
-rw-r--r--host/commands/tapsetiff/Android.bp4
-rwxr-xr-xhost/commands/tapsetiff/tapsetiff.py4
-rw-r--r--host/commands/tombstone_receiver/Android.bp10
-rw-r--r--host/commands/tombstone_receiver/main.cpp12
-rw-r--r--host/example_custom_actions/Android.bp28
-rw-r--r--host/example_custom_actions/README.md12
-rw-r--r--host/example_custom_actions/custom_action_config.json25
-rw-r--r--host/example_custom_actions/main.cpp78
-rw-r--r--host/frontend/Android.bp20
-rw-r--r--host/frontend/adb_connector/Android.bp8
-rw-r--r--host/frontend/adb_connector/adb_connection_maintainer.cpp42
-rw-r--r--host/frontend/adb_connector/adb_connection_maintainer.h4
-rw-r--r--host/frontend/adb_connector/main.cpp31
-rw-r--r--host/frontend/gcastv2/https/Android.bp (renamed from host/libs/websocket/Android.bp)38
-rw-r--r--host/frontend/gcastv2/https/BaseConnection.cpp122
-rw-r--r--host/frontend/gcastv2/https/BufferedSocket.cpp (renamed from host/commands/assemble_cvd/disk_flags.h)32
-rw-r--r--host/frontend/gcastv2/https/ClientSocket.cpp244
-rw-r--r--host/frontend/gcastv2/https/HTTPClientConnection.cpp286
-rw-r--r--host/frontend/gcastv2/https/HTTPRequestResponse.cpp174
-rw-r--r--host/frontend/gcastv2/https/HTTPServer.cpp391
-rw-r--r--host/frontend/gcastv2/https/PlainSocket.cpp54
-rw-r--r--host/frontend/gcastv2/https/README5
-rw-r--r--host/frontend/gcastv2/https/RunLoop.cpp448
-rw-r--r--host/frontend/gcastv2/https/SSLSocket.cpp569
-rw-r--r--host/frontend/gcastv2/https/ServerSocket.cpp182
-rw-r--r--host/frontend/gcastv2/https/Support.cpp137
-rw-r--r--host/frontend/gcastv2/https/WebSocketHandler.cpp221
-rwxr-xr-xhost/frontend/gcastv2/https/certs/create_certs.sh (renamed from host/frontend/webrtc_operator/certs/create_certs.sh)6
-rw-r--r--host/frontend/gcastv2/https/certs/server.crt20
-rw-r--r--host/frontend/gcastv2/https/certs/server.key27
-rw-r--r--host/frontend/gcastv2/https/certs/trusted.pem70
-rw-r--r--host/frontend/gcastv2/https/content/index.html19
-rw-r--r--host/frontend/gcastv2/https/include/https/BaseConnection.h61
-rw-r--r--host/frontend/gcastv2/https/include/https/BufferedSocket.h63
-rw-r--r--host/frontend/gcastv2/https/include/https/ClientSocket.h86
-rw-r--r--host/frontend/gcastv2/https/include/https/HTTPClientConnection.h73
-rw-r--r--host/frontend/gcastv2/https/include/https/HTTPRequestResponse.h82
-rw-r--r--host/frontend/gcastv2/https/include/https/HTTPServer.h110
-rw-r--r--host/frontend/gcastv2/https/include/https/PlainSocket.h43
-rw-r--r--host/frontend/gcastv2/https/include/https/RunLoop.h122
-rw-r--r--host/frontend/gcastv2/https/include/https/SSLSocket.h120
-rw-r--r--host/frontend/gcastv2/https/include/https/SafeCallbackable.h50
-rw-r--r--host/frontend/gcastv2/https/include/https/ServerSocket.h71
-rw-r--r--host/frontend/gcastv2/https/include/https/Support.h (renamed from common/libs/utils/base64.h)25
-rw-r--r--host/frontend/gcastv2/https/include/https/WebSocketHandler.h60
-rw-r--r--host/frontend/gcastv2/libsource/Android.bp (renamed from host/commands/cvd_host_bugreport/Android.bp)31
-rw-r--r--host/frontend/gcastv2/libsource/AudioSource.cpp836
-rw-r--r--host/frontend/gcastv2/libsource/FrameBufferSource.cpp415
-rw-r--r--host/frontend/gcastv2/libsource/HostToGuestComms.cpp408
-rw-r--r--host/frontend/gcastv2/libsource/InputSink.cpp218
-rw-r--r--host/frontend/gcastv2/libsource/KeyboardSink.cpp (renamed from host/libs/allocd/resource.cpp)42
-rw-r--r--host/frontend/gcastv2/libsource/StreamingSource.cpp (renamed from host/commands/assemble_cvd/boot_config.h)24
-rw-r--r--host/frontend/gcastv2/libsource/TouchSink.cpp60
-rw-r--r--host/frontend/gcastv2/libsource/include/source/AudioSource.h92
-rw-r--r--host/frontend/gcastv2/libsource/include/source/FrameBufferSource.h81
-rw-r--r--host/frontend/gcastv2/libsource/include/source/HostToGuestComms.h75
-rw-r--r--host/frontend/gcastv2/libsource/include/source/InputSink.h63
-rw-r--r--host/frontend/gcastv2/libsource/include/source/KeyboardSink.h (renamed from host/frontend/webrtc/lib/audio_frame_buffer.h)29
-rw-r--r--host/frontend/gcastv2/libsource/include/source/StreamingSource.h104
-rw-r--r--host/frontend/gcastv2/libsource/include/source/TouchSink.h (renamed from host/frontend/webrtc/adb_handler.h)38
-rw-r--r--host/frontend/gcastv2/webrtc/AdbWebSocketHandler.cpp259
-rw-r--r--host/frontend/gcastv2/webrtc/Android.bp (renamed from host/frontend/webrtc_operator/Android.bp)133
-rw-r--r--host/frontend/gcastv2/webrtc/DTLS.cpp463
-rw-r--r--host/frontend/gcastv2/webrtc/G711Packetizer.cpp77
-rw-r--r--host/frontend/gcastv2/webrtc/Keyboard.cpp (renamed from host/frontend/webrtc/lib/keyboard.cpp)2
-rw-r--r--host/frontend/gcastv2/webrtc/MyWebSocketHandler.cpp721
-rw-r--r--host/frontend/gcastv2/webrtc/OpusPacketizer.cpp75
-rw-r--r--host/frontend/gcastv2/webrtc/Packetizer.cpp113
-rw-r--r--host/frontend/gcastv2/webrtc/RTPSender.cpp582
-rw-r--r--host/frontend/gcastv2/webrtc/RTPSession.cpp142
-rw-r--r--host/frontend/gcastv2/webrtc/RTPSocketHandler.cpp739
-rw-r--r--host/frontend/gcastv2/webrtc/SCTPHandler.cpp529
-rw-r--r--host/frontend/gcastv2/webrtc/SDP.cpp179
-rw-r--r--host/frontend/gcastv2/webrtc/STUNClient.cpp175
-rw-r--r--host/frontend/gcastv2/webrtc/STUNMessage.cpp371
-rw-r--r--host/frontend/gcastv2/webrtc/ServerState.cpp158
-rw-r--r--host/frontend/gcastv2/webrtc/Utils.cpp (renamed from host/frontend/webrtc_operator/utils.cpp)2
-rw-r--r--host/frontend/gcastv2/webrtc/Utils.h (renamed from host/frontend/webrtc_operator/utils.h)0
-rw-r--r--host/frontend/gcastv2/webrtc/VP8Packetizer.cpp93
-rw-r--r--host/frontend/gcastv2/webrtc/assets/index.html30
-rw-r--r--host/frontend/gcastv2/webrtc/assets/js/logcat.js163
-rw-r--r--host/frontend/gcastv2/webrtc/assets/js/receive.js453
-rw-r--r--host/frontend/gcastv2/webrtc/assets/js/viewpane.js29
-rw-r--r--host/frontend/gcastv2/webrtc/assets/style.css29
-rwxr-xr-xhost/frontend/gcastv2/webrtc/certs/create_certs.sh32
-rw-r--r--host/frontend/gcastv2/webrtc/certs/server.crt20
-rw-r--r--host/frontend/gcastv2/webrtc/certs/server.key27
-rw-r--r--host/frontend/gcastv2/webrtc/certs/server.p12bin0 -> 2528 bytes
-rw-r--r--host/frontend/gcastv2/webrtc/certs/trusted.pem70
-rw-r--r--host/frontend/gcastv2/webrtc/include/webrtc/AdbWebSocketHandler.h49
-rw-r--r--host/frontend/gcastv2/webrtc/include/webrtc/DTLS.h101
-rw-r--r--host/frontend/gcastv2/webrtc/include/webrtc/G711Packetizer.h53
-rw-r--r--host/frontend/gcastv2/webrtc/include/webrtc/Keyboard.h (renamed from host/frontend/webrtc/lib/keyboard.h)0
-rw-r--r--host/frontend/gcastv2/webrtc/include/webrtc/MyWebSocketHandler.h111
-rw-r--r--host/frontend/gcastv2/webrtc/include/webrtc/OpusPacketizer.h47
-rw-r--r--host/frontend/gcastv2/webrtc/include/webrtc/Packetizer.h66
-rw-r--r--host/frontend/gcastv2/webrtc/include/webrtc/RTPSender.h98
-rw-r--r--host/frontend/gcastv2/webrtc/include/webrtc/RTPSession.h76
-rw-r--r--host/frontend/gcastv2/webrtc/include/webrtc/RTPSocketHandler.h137
-rw-r--r--host/frontend/gcastv2/webrtc/include/webrtc/SCTPHandler.h52
-rw-r--r--host/frontend/gcastv2/webrtc/include/webrtc/SDP.h79
-rw-r--r--host/frontend/gcastv2/webrtc/include/webrtc/STUNClient.h56
-rw-r--r--host/frontend/gcastv2/webrtc/include/webrtc/STUNMessage.h56
-rw-r--r--host/frontend/gcastv2/webrtc/include/webrtc/ServerState.h79
-rw-r--r--host/frontend/gcastv2/webrtc/include/webrtc/VP8Packetizer.h40
-rw-r--r--host/frontend/gcastv2/webrtc/makefile42
-rw-r--r--host/frontend/gcastv2/webrtc/webRTC.cpp197
-rw-r--r--host/frontend/vnc_server/Android.bp19
-rw-r--r--host/frontend/vnc_server/blackboard.cpp10
-rw-r--r--host/frontend/vnc_server/blackboard.h6
-rw-r--r--host/frontend/vnc_server/frame_buffer_watcher.cpp32
-rw-r--r--host/frontend/vnc_server/frame_buffer_watcher.h15
-rw-r--r--host/frontend/vnc_server/jpeg_compressor.cpp8
-rw-r--r--host/frontend/vnc_server/jpeg_compressor.h4
-rw-r--r--host/frontend/vnc_server/keysyms.h4
-rw-r--r--host/frontend/vnc_server/main.cpp23
-rw-r--r--host/frontend/vnc_server/simulated_hw_composer.cpp123
-rw-r--r--host/frontend/vnc_server/simulated_hw_composer.h20
-rw-r--r--host/frontend/vnc_server/virtual_inputs.cpp266
-rw-r--r--host/frontend/vnc_server/virtual_inputs.h13
-rw-r--r--host/frontend/vnc_server/vnc_client_connection.cpp64
-rw-r--r--host/frontend/vnc_server/vnc_client_connection.h8
-rw-r--r--host/frontend/vnc_server/vnc_server.cpp22
-rw-r--r--host/frontend/vnc_server/vnc_server.h15
-rw-r--r--host/frontend/vnc_server/vnc_utils.h29
-rw-r--r--host/frontend/webrtc/Android.bp140
-rw-r--r--host/frontend/webrtc/adb_handler.cpp113
-rw-r--r--host/frontend/webrtc/audio_handler.cpp481
-rw-r--r--host/frontend/webrtc/audio_handler.h79
-rw-r--r--host/frontend/webrtc/bluetooth_handler.cpp87
-rw-r--r--host/frontend/webrtc/bluetooth_handler.h49
-rw-r--r--host/frontend/webrtc/connection_observer.cpp470
-rw-r--r--host/frontend/webrtc/connection_observer.h65
-rw-r--r--host/frontend/webrtc/cvd_video_frame_buffer.cpp86
-rw-r--r--host/frontend/webrtc/cvd_video_frame_buffer.h59
-rw-r--r--host/frontend/webrtc/display_handler.cpp121
-rw-r--r--host/frontend/webrtc/display_handler.h73
-rw-r--r--host/frontend/webrtc/kernel_log_events_handler.cpp112
-rw-r--r--host/frontend/webrtc/kernel_log_events_handler.h52
-rw-r--r--host/frontend/webrtc/lib/audio_device.cpp247
-rw-r--r--host/frontend/webrtc/lib/audio_device.h144
-rw-r--r--host/frontend/webrtc/lib/audio_source.h40
-rw-r--r--host/frontend/webrtc/lib/audio_track_source_impl.cpp77
-rw-r--r--host/frontend/webrtc/lib/audio_track_source_impl.h87
-rw-r--r--host/frontend/webrtc/lib/client_handler.cpp767
-rw-r--r--host/frontend/webrtc/lib/client_handler.h131
-rw-r--r--host/frontend/webrtc/lib/connection_observer.h58
-rw-r--r--host/frontend/webrtc/lib/local_recorder.cpp288
-rw-r--r--host/frontend/webrtc/lib/local_recorder.h53
-rw-r--r--host/frontend/webrtc/lib/port_range_socket_factory.cpp84
-rw-r--r--host/frontend/webrtc/lib/port_range_socket_factory.h50
-rw-r--r--host/frontend/webrtc/lib/streamer.cpp645
-rw-r--r--host/frontend/webrtc/lib/streamer.h130
-rw-r--r--host/frontend/webrtc/lib/utils.cpp73
-rw-r--r--host/frontend/webrtc/lib/utils.h47
-rw-r--r--host/frontend/webrtc/lib/video_frame_buffer.h39
-rw-r--r--host/frontend/webrtc/lib/video_sink.h34
-rw-r--r--host/frontend/webrtc/lib/video_track_source_impl.cpp80
-rw-r--r--host/frontend/webrtc/lib/video_track_source_impl.h77
-rw-r--r--host/frontend/webrtc/lib/vp8only_encoder_factory.cpp53
-rw-r--r--host/frontend/webrtc/lib/vp8only_encoder_factory.h44
-rw-r--r--host/frontend/webrtc/lib/ws_connection.cpp446
-rw-r--r--host/frontend/webrtc/lib/ws_connection.h72
-rw-r--r--host/frontend/webrtc/main.cpp360
-rw-r--r--host/frontend/webrtc_operator/Readme.md88
-rw-r--r--host/frontend/webrtc_operator/assets/controls.css88
-rw-r--r--host/frontend/webrtc_operator/assets/index.html85
-rw-r--r--host/frontend/webrtc_operator/assets/js/adb.js204
-rw-r--r--host/frontend/webrtc_operator/assets/js/app.js793
-rw-r--r--host/frontend/webrtc_operator/assets/js/cf_webrtc.js460
-rw-r--r--host/frontend/webrtc_operator/assets/js/controls.js38
-rw-r--r--host/frontend/webrtc_operator/assets/js/rootcanal.js74
-rw-r--r--host/frontend/webrtc_operator/assets/style.css177
-rw-r--r--host/frontend/webrtc_operator/certs/server.crt20
-rw-r--r--host/frontend/webrtc_operator/certs/server.key27
-rw-r--r--host/frontend/webrtc_operator/certs/server.p12bin2536 -> 0 bytes
-rw-r--r--host/frontend/webrtc_operator/certs/trusted.pem70
-rw-r--r--host/frontend/webrtc_operator/client_handler.cpp125
-rw-r--r--host/frontend/webrtc_operator/client_handler.h63
-rw-r--r--host/frontend/webrtc_operator/constants/signaling_constants.h43
-rw-r--r--host/frontend/webrtc_operator/device_handler.cpp131
-rw-r--r--host/frontend/webrtc_operator/device_handler.h70
-rw-r--r--host/frontend/webrtc_operator/device_list_handler.cpp48
-rw-r--r--host/frontend/webrtc_operator/device_list_handler.h48
-rw-r--r--host/frontend/webrtc_operator/device_registry.cpp71
-rw-r--r--host/frontend/webrtc_operator/device_registry.h45
-rw-r--r--host/frontend/webrtc_operator/server.cpp71
-rw-r--r--host/frontend/webrtc_operator/server_config.cpp45
-rw-r--r--host/frontend/webrtc_operator/server_config.h33
-rw-r--r--host/frontend/webrtc_operator/signal_handler.cpp100
-rw-r--r--host/frontend/webrtc_operator/signal_handler.h50
-rw-r--r--host/libs/Android.bp21
-rw-r--r--host/libs/allocd/Android.bp75
-rw-r--r--host/libs/allocd/alloc_utils.cpp482
-rw-r--r--host/libs/allocd/alloc_utils.h126
-rw-r--r--host/libs/allocd/allocd.cpp59
-rw-r--r--host/libs/allocd/request.h90
-rw-r--r--host/libs/allocd/resource.h119
-rw-r--r--host/libs/allocd/resource_manager.cpp619
-rw-r--r--host/libs/allocd/resource_manager.h155
-rw-r--r--host/libs/allocd/test/client.cpp170
-rw-r--r--host/libs/allocd/utils.cpp192
-rw-r--r--host/libs/allocd/utils.h64
-rw-r--r--host/libs/audio_connector/buffers.cpp43
-rw-r--r--host/libs/audio_connector/buffers.h92
-rw-r--r--host/libs/audio_connector/commands.cpp79
-rw-r--r--host/libs/audio_connector/commands.h107
-rw-r--r--host/libs/audio_connector/server.cpp357
-rw-r--r--host/libs/audio_connector/server.h113
-rw-r--r--host/libs/audio_connector/shm_layout.h192
-rw-r--r--host/libs/config/Android.bp19
-rw-r--r--host/libs/config/bootconfig_args.cpp169
-rw-r--r--host/libs/config/custom_actions.cpp147
-rw-r--r--host/libs/config/custom_actions.h47
-rw-r--r--host/libs/config/cuttlefish_config.cpp1010
-rw-r--r--host/libs/config/cuttlefish_config.h382
-rw-r--r--host/libs/config/cuttlefish_config_instance.cpp498
-rw-r--r--host/libs/config/data_image.h21
-rw-r--r--host/libs/config/fetcher_config.cpp16
-rw-r--r--host/libs/config/fetcher_config.h5
-rw-r--r--host/libs/config/host_tools_version.cpp82
-rw-r--r--host/libs/config/kernel_args.cpp120
-rw-r--r--host/libs/config/known_paths.cpp79
-rw-r--r--host/libs/config/known_paths.h37
-rw-r--r--host/libs/config/logging.cpp6
-rw-r--r--host/libs/config/logging.h4
-rw-r--r--host/libs/confui/Android.bp61
-rw-r--r--host/libs/confui/Roboto-Medium.ttfbin172064 -> 0 bytes
-rw-r--r--host/libs/confui/Roboto-Regular.ttfbin171676 -> 0 bytes
-rw-r--r--host/libs/confui/Shield.ttfbin1992 -> 0 bytes
-rw-r--r--host/libs/confui/fonts.S21
-rw-r--r--host/libs/confui/host_mode_ctrl.h118
-rw-r--r--host/libs/confui/host_renderer.cc245
-rw-r--r--host/libs/confui/host_renderer.h180
-rw-r--r--host/libs/confui/host_server.cc259
-rw-r--r--host/libs/confui/host_server.h186
-rw-r--r--host/libs/confui/host_utils.cc77
-rw-r--r--host/libs/confui/host_utils.h101
-rw-r--r--host/libs/confui/host_virtual_input.h38
-rw-r--r--host/libs/confui/layouts/fonts.h30
-rw-r--r--host/libs/confui/layouts/layout.h177
-rw-r--r--host/libs/confui/server_common.cc101
-rw-r--r--host/libs/confui/server_common.h56
-rw-r--r--host/libs/confui/session.cc269
-rw-r--r--host/libs/confui/session.h111
-rw-r--r--host/libs/graphics_detector/Android.bp46
-rw-r--r--host/libs/graphics_detector/graphics_detector.cpp604
-rw-r--r--host/libs/graphics_detector/graphics_detector.h45
-rw-r--r--host/libs/graphics_detector/include/EGL/egl.h361
-rw-r--r--host/libs/graphics_detector/include/EGL/eglext.h1409
-rw-r--r--host/libs/graphics_detector/include/EGL/eglplatform.h182
-rw-r--r--host/libs/graphics_detector/include/KHR/khrplatform.h290
-rw-r--r--host/libs/image_aggregator/Android.bp54
-rw-r--r--host/libs/image_aggregator/image_aggregator.cc509
-rw-r--r--host/libs/image_aggregator/image_aggregator.h98
-rw-r--r--host/libs/msg_queue/Android.bp35
-rw-r--r--host/libs/msg_queue/README.md57
-rw-r--r--host/libs/msg_queue/msg_queue.cc96
-rw-r--r--host/libs/msg_queue/msg_queue.h34
-rw-r--r--host/libs/screen_connector/Android.bp20
-rw-r--r--host/libs/screen_connector/screen_connector.cpp40
-rw-r--r--host/libs/screen_connector/screen_connector.h236
-rw-r--r--host/libs/screen_connector/screen_connector_common.h99
-rw-r--r--host/libs/screen_connector/screen_connector_ctrl.h104
-rw-r--r--host/libs/screen_connector/screen_connector_queue.h125
-rw-r--r--host/libs/screen_connector/socket_based_screen_connector.cpp105
-rw-r--r--host/libs/screen_connector/socket_based_screen_connector.h54
-rw-r--r--host/libs/screen_connector/wayland_screen_connector.cpp16
-rw-r--r--host/libs/screen_connector/wayland_screen_connector.h12
-rw-r--r--host/libs/vm_manager/Android.bp16
-rw-r--r--host/libs/vm_manager/crosvm_manager.cpp398
-rw-r--r--host/libs/vm_manager/crosvm_manager.h20
-rw-r--r--host/libs/vm_manager/host_configuration.cpp107
-rw-r--r--host/libs/vm_manager/host_configuration.h28
-rw-r--r--host/libs/vm_manager/qemu_manager.cpp435
-rw-r--r--host/libs/vm_manager/qemu_manager.h18
-rw-r--r--host/libs/vm_manager/vm_manager.cpp183
-rw-r--r--host/libs/vm_manager/vm_manager.h94
-rw-r--r--host/libs/wayland/Android.bp10
-rw-r--r--host/libs/wayland/wayland_compositor.cpp12
-rw-r--r--host/libs/wayland/wayland_compositor.h4
-rw-r--r--host/libs/wayland/wayland_server.cpp22
-rw-r--r--host/libs/wayland/wayland_server.h13
-rw-r--r--host/libs/wayland/wayland_surface.cpp45
-rw-r--r--host/libs/wayland/wayland_surface.h31
-rw-r--r--host/libs/wayland/wayland_surfaces.cpp65
-rw-r--r--host/libs/wayland/wayland_surfaces.h65
-rw-r--r--host/libs/websocket/websocket_handler.cpp70
-rw-r--r--host/libs/websocket/websocket_handler.h66
-rw-r--r--host/libs/websocket/websocket_server.cpp191
-rw-r--r--host/libs/websocket/websocket_server.h60
-rw-r--r--host_package.mk136
-rw-r--r--recovery/recovery_ui.cpp29
-rw-r--r--required_images7
l---------rustfmt.toml1
-rw-r--r--shared/Android.mk (renamed from guest/Android.mk)6
-rw-r--r--shared/BoardConfig.mk176
-rw-r--r--shared/auto/android-info.txt1
-rw-r--r--shared/auto/device.mk22
-rw-r--r--shared/auto/manifest.xml2
-rw-r--r--shared/config/Android.bp33
-rw-r--r--shared/config/Android.mk37
-rw-r--r--shared/config/CleanSpec.mk1
-rw-r--r--shared/config/android.hardware.media.omx@1.0.xml8
-rw-r--r--shared/config/camera_v1.json52
-rw-r--r--shared/config/camera_v3.json52
-rw-r--r--shared/config/config_auto.json6
-rw-r--r--shared/config/config_foldable.json34
-rw-r--r--shared/config/config_phone.json6
-rw-r--r--shared/config/config_tablet.json6
-rw-r--r--shared/config/config_tv.json6
-rw-r--r--shared/config/fstab-erofs.ext418
-rw-r--r--shared/config/fstab-erofs.f2fs18
-rw-r--r--shared/config/fstab.ext410
-rw-r--r--shared/config/fstab.f2fs10
-rwxr-xr-xshared/config/gen_wpa_supplicant_conf.sh20
-rw-r--r--shared/config/init.product.rc11
-rw-r--r--shared/config/init.recovery.rc4
-rw-r--r--shared/config/init.vendor.rc78
-rw-r--r--shared/config/input/Crosvm_Virtio_Multitouch_Touchscreen.idc6
-rw-r--r--shared/config/manifest.xml56
-rw-r--r--shared/config/manifest_android.hardware.bluetooth@1.1-service.xml29
-rw-r--r--shared/config/media_codecs_performance.xml40
-rw-r--r--shared/config/product_manifest.xml19
-rw-r--r--shared/config/spn-conf.xml (renamed from shared/config/system_ext_manifest.xml)8
-rw-r--r--shared/config/task_profiles.json69
-rw-r--r--shared/config/ueventd.rc25
-rw-r--r--shared/device.mk357
-rw-r--r--shared/foldable/android-info.txt1
-rw-r--r--shared/foldable/device_state_configuration.xml37
-rw-r--r--shared/foldable/overlay/frameworks/base/core/res/res/values/config.xml42
-rw-r--r--shared/go/device.mk4
-rw-r--r--shared/go_512/device.mk4
-rw-r--r--shared/overlay/frameworks/base/core/res/res/xml/power_profile.xml2
-rw-r--r--shared/overlay/frameworks/base/packages/SettingsProvider/res/values/defaults.xml1
-rw-r--r--shared/pc/OWNERS3
-rw-r--r--shared/pc/device_vendor.mk28
-rw-r--r--shared/permissions/cuttlefish_excluded_hardware.xml1
-rw-r--r--shared/phone/android-info.txt1
-rw-r--r--shared/phone/device.mk12
-rw-r--r--shared/phone/device_vendor.mk19
-rw-r--r--shared/sepolicy/OWNERS1
-rw-r--r--shared/sepolicy/product/private/file_contexts1
-rw-r--r--shared/sepolicy/product/private/suspend_blocker.te6
-rw-r--r--shared/sepolicy/product/private/tombstone_transmit.te4
-rw-r--r--shared/sepolicy/system_ext/private/con_monitor.te3
-rw-r--r--shared/sepolicy/system_ext/private/flipendo.te1
-rw-r--r--shared/sepolicy/system_ext/private/mediatranscoding.te2
-rw-r--r--shared/sepolicy/system_ext/private/property.te4
-rw-r--r--shared/sepolicy/system_ext/private/property_contexts2
-rw-r--r--shared/sepolicy/system_ext/private/sample_tuner_tis_app.te7
-rw-r--r--shared/sepolicy/system_ext/private/seapp_contexts3
-rw-r--r--shared/sepolicy/vendor/adbd.te2
-rw-r--r--shared/sepolicy/vendor/bt_device.te1
-rw-r--r--shared/sepolicy/vendor/bt_vhci_forwarder.te6
-rw-r--r--shared/sepolicy/vendor/bug_map5
-rw-r--r--shared/sepolicy/vendor/cameraserver.te3
-rw-r--r--shared/sepolicy/vendor/crash_dump.te1
-rw-r--r--shared/sepolicy/vendor/cuttlefish_sensor_injection.te15
-rw-r--r--shared/sepolicy/vendor/device.te1
-rw-r--r--shared/sepolicy/vendor/dumpstate.te4
-rw-r--r--shared/sepolicy/vendor/file.te1
-rw-r--r--shared/sepolicy/vendor/file_contexts93
-rw-r--r--shared/sepolicy/vendor/genfs_contexts92
-rw-r--r--shared/sepolicy/vendor/google/bug_map1
-rw-r--r--shared/sepolicy/vendor/google/gmscore_app.te2
-rw-r--r--shared/sepolicy/vendor/google/hwservice.te2
-rw-r--r--shared/sepolicy/vendor/google/mediaprovider.te1
-rw-r--r--shared/sepolicy/vendor/google/traceur_app.te1
-rw-r--r--shared/sepolicy/vendor/gpuservice.te1
-rw-r--r--shared/sepolicy/vendor/hal_bluetooth_remote.te8
-rw-r--r--shared/sepolicy/vendor/hal_bluetooth_sim.te4
-rw-r--r--shared/sepolicy/vendor/hal_camera_default.te7
-rw-r--r--shared/sepolicy/vendor/hal_gatekeeper_remote.te14
-rw-r--r--shared/sepolicy/vendor/hal_graphics_allocator.te5
-rw-r--r--shared/sepolicy/vendor/hal_graphics_composer.te6
-rw-r--r--shared/sepolicy/vendor/hal_graphics_composer_default.te5
-rw-r--r--shared/sepolicy/vendor/hal_keymaster_remote.te14
-rw-r--r--shared/sepolicy/vendor/hal_keymint_remote.te12
-rw-r--r--shared/sepolicy/vendor/init.te12
-rw-r--r--shared/sepolicy/vendor/ip_link_add.te10
-rw-r--r--shared/sepolicy/vendor/kernel.te19
-rw-r--r--shared/sepolicy/vendor/libcuttlefish_rild.te3
-rw-r--r--shared/sepolicy/vendor/logpersist.te8
-rw-r--r--shared/sepolicy/vendor/property.te3
-rw-r--r--shared/sepolicy/vendor/property_contexts41
-rw-r--r--shared/sepolicy/vendor/radio.te1
-rw-r--r--shared/sepolicy/vendor/recovery.te4
-rw-r--r--shared/sepolicy/vendor/seapp_contexts2
-rw-r--r--shared/sepolicy/vendor/service_contexts7
-rw-r--r--shared/sepolicy/vendor/setup_wifi.te4
-rw-r--r--shared/sepolicy/vendor/shell.te4
-rw-r--r--shared/sepolicy/vendor/socket_vsock_proxy.te2
-rw-r--r--shared/sepolicy/vendor/surfaceflinger.te5
-rw-r--r--shared/sepolicy/vendor/suspend_blocker.te6
-rw-r--r--shared/sepolicy/vendor/system_server.te3
-rw-r--r--shared/sepolicy/vendor/ueventd.te3
-rw-r--r--shared/sepolicy/vendor/update_engine_common.te1
-rw-r--r--shared/sepolicy/vendor/usbforward.te22
-rw-r--r--shared/sepolicy/vendor/vendor_init.te14
-rw-r--r--shared/sepolicy/vendor/vold.te3
-rw-r--r--shared/sepolicy/vendor/vport_trigger.te12
-rw-r--r--shared/sepolicy/vendor/vsoc_input_service.te6
-rw-r--r--shared/sepolicy/vendor/vsock_logcat.te17
-rw-r--r--shared/tv/android-info.txt1
-rw-r--r--shared/tv/device.mk13
-rw-r--r--shared/tv/manifest.xml2
-rw-r--r--shared/tv/overlay/frameworks/base/core/res/res/values/config.xml4
-rw-r--r--shared/tv/sepolicy/vendor/file_contexts1
-rw-r--r--shared/wpa_supplicant_overlay.conf (renamed from shared/config/wpa_supplicant_overlay.conf)0
-rw-r--r--tests/Android.mk (renamed from guest/libs/Android.mk)4
-rw-r--r--tests/graphics/Android.bp33
-rw-r--r--tests/graphics/src/com/android/cuttlefish/tests/GfxstreamEnabledTest.java43
-rw-r--r--tests/hal/Android.bp4
-rw-r--r--tests/hal/hal_implementation_test.cpp101
-rw-r--r--tests/powerwash/src/com/android/cuttlefish/tests/PowerwashTest.java64
-rw-r--r--tests/recovery/AndroidTest.xml21
-rw-r--r--tests/recovery/src/com/android/cuttlefish/tests/RebootRecoveryTest.java39
-rw-r--r--tests/ril/Android.bp31
-rw-r--r--tests/ril/Android.mk39
-rw-r--r--tests/ril/AndroidManifest.xml2
-rwxr-xr-xtests/ril/runtests.sh2
-rw-r--r--tests/ril/src/com/android/cuttlefish/ril/tests/RilE2eTests.java21
-rw-r--r--tests/wifi/Android.bp29
-rw-r--r--tests/wifi/Android.mk35
-rw-r--r--tests/wifi/AndroidManifest.xml2
-rwxr-xr-xtests/wifi/runtests.sh2
-rw-r--r--tests/wifi/src/com/android/cuttlefish/wifi/tests/WifiE2eTests.java10
-rwxr-xr-xtools/create_base_image_arm.sh8
-rwxr-xr-xtools/create_base_image_gce.sh14
-rwxr-xr-xtools/create_base_image_hostlib.sh6
-rw-r--r--tools/play_audio/.gitignore3
-rw-r--r--tools/play_audio/Makefile12
-rw-r--r--tools/play_audio/README.md30
-rw-r--r--tools/play_audio/client_socket.cpp113
-rw-r--r--tools/play_audio/client_socket.h57
-rw-r--r--tools/play_audio/play_audio.cpp109
-rw-r--r--tools/play_audio/sdl_wrapper.cpp75
-rw-r--r--tools/play_audio/sdl_wrapper.h55
-rwxr-xr-xtools/upload_to_gce_and_run.py20
-rwxr-xr-xtools/upload_via_ssh.py6
-rw-r--r--vsoc_arm64/BoardConfig.mk11
-rw-r--r--vsoc_arm64/auto/aosp_cf.mk10
-rw-r--r--vsoc_arm64/auto/overlay/frameworks/base/core/res/res/values/config.xml (renamed from shared/auto/overlay/frameworks/base/core/res/res/values/config.xml)4
-rw-r--r--vsoc_arm64/bootloader.mk22
-rw-r--r--vsoc_arm64/device.mk (renamed from vsoc_arm64/kernel.mk)4
-rw-r--r--vsoc_arm64/phone/aosp_cf.mk16
-rw-r--r--vsoc_arm64/phone/overlay/frameworks/base/core/res/res/values/config.xml (renamed from shared/phone/overlay/frameworks/base/core/res/res/values/config.xml)23
-rw-r--r--vsoc_arm64_only/BoardConfig.mk34
-rw-r--r--vsoc_arm64_only/phone/aosp_cf.mk62
-rw-r--r--vsoc_arm_only/BoardConfig.mk34
-rw-r--r--vsoc_arm_only/bootloader.mk22
-rw-r--r--vsoc_arm_only/phone/aosp_cf.mk71
-rw-r--r--vsoc_x86/BoardConfig.mk11
-rw-r--r--vsoc_x86/auto/device.mk10
-rw-r--r--vsoc_x86/auto/overlay/frameworks/base/core/res/res/values/config.xml (renamed from shared/pc/overlay/frameworks/base/core/res/res/values/config.xml)15
-rw-r--r--vsoc_x86/auto/preinstalled-packages-product-car-cuttlefish.xml121
-rw-r--r--vsoc_x86/device.mk (renamed from vsoc_x86_64/kernel.mk)4
-rw-r--r--vsoc_x86/go_512_phone/device.mk7
-rw-r--r--vsoc_x86/go_phone/device.mk8
-rw-r--r--vsoc_x86/pasan/aosp_cf.mk15
-rw-r--r--vsoc_x86/phone/aosp_cf.mk12
-rw-r--r--vsoc_x86/phone/device.mk (renamed from .clang-format)12
-rw-r--r--vsoc_x86/phone/overlay/frameworks/base/core/res/res/values/config.xml48
-rw-r--r--vsoc_x86/tv/device.mk9
-rw-r--r--vsoc_x86_64/BoardConfig.mk6
-rw-r--r--vsoc_x86_64/auto/OWNERS5
-rw-r--r--vsoc_x86_64/auto/device.mk29
-rw-r--r--vsoc_x86_64/bootloader.mk21
-rw-r--r--vsoc_x86_64/device.mk (renamed from vsoc_arm_only/kernel.mk)4
-rw-r--r--vsoc_x86_64/pc/OWNERS3
-rw-r--r--vsoc_x86_64/pc/aosp_cf.mk52
-rw-r--r--vsoc_x86_64/phone/aosp_cf.mk18
-rw-r--r--vsoc_x86_64/phone/aosp_cf_foldable.mk30
-rw-r--r--vsoc_x86_64/phone/overlay/frameworks/base/core/res/res/values/config.xml48
-rw-r--r--vsoc_x86_64/tv/device.mk29
-rw-r--r--vsoc_x86_64_only/BoardConfig.mk35
-rw-r--r--vsoc_x86_64_only/phone/aosp_cf.mk62
-rw-r--r--vsoc_x86_noapex/aosp_cf_noapex.mk7
-rw-r--r--vsoc_x86_only/kernel.mk18
-rw-r--r--vsoc_x86_only/phone/aosp_cf.mk60
992 files changed, 53839 insertions, 68636 deletions
diff --git a/Android.bp b/Android.bp
index 7ad70eef6..9a59df33d 100644
--- a/Android.bp
+++ b/Android.bp
@@ -13,44 +13,24 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package {
- default_applicable_licenses: ["device_google_cuttlefish_license"],
-}
+subdirs = [
+ "common",
+ "guest",
+ "host",
+]
-// Added automatically by a large-scale-change that took the approach of
-// 'apply every license found to every target'. While this makes sure we respect
-// every license restriction, it may not be entirely correct.
-//
-// e.g. GPL in an MIT project might only apply to the contrib/ directory.
-//
-// Please consider splitting the single license below into multiple licenses,
-// taking care not to lose any license_kind information, and overriding the
-// default license using the 'licenses: [...]' property on targets as needed.
-//
-// For unused files, consider creating a 'fileGroup' with "//visibility:private"
-// to attach the license to, and including a comment whether the files may be
-// used in the current project.
-// See: http://go/android-license-faq
-license {
- name: "device_google_cuttlefish_license",
- visibility: [":__subpackages__"],
- license_kinds: [
- "SPDX-license-identifier-Apache-2.0",
- "SPDX-license-identifier-MIT",
- ],
- // large-scale-change unable to identify any license_text files
+cc_library_headers {
+ name: "cuttlefish_common_headers",
+ vendor: true,
+ export_include_dirs: ["."],
+ host_supported: true,
}
cc_library_headers {
- name: "cuttlefish_common_headers",
- vendor_available: true,
- product_available: true,
+ name: "cuttlefish_common_headers_product",
+ product_specific: true,
export_include_dirs: ["."],
host_supported: true,
- apex_available: [
- "//apex_available:platform",
- "com.android.virt",
- ],
}
cc_defaults {
@@ -71,45 +51,45 @@ cc_defaults {
},
},
cflags: ["-Werror", "-Wall", "-D_FILE_OFFSET_BITS=64"],
- apex_available: [
- "//apex_available:platform",
- "com.android.virt",
- ],
-}
-
-// Defaults for cuttlefish modules that are available only in the guest OS (i.e. cuttlefish running
-// in a guest VM).
-cc_defaults {
- name: "cuttlefish_guest_only",
vendor: true,
- defaults: ["cuttlefish_base"],
}
-// Same as cuttlefish_guest_only, but modules are placed in /product partition.
cc_defaults {
name: "cuttlefish_guest_product_only",
product_specific: true,
+ gnu_extensions: false,
+ header_libs: [
+ "cuttlefish_common_headers_product",
+ ],
+ target: {
+ host: {
+ host_ldlibs: ["-lrt"],
+ cflags: ["-DCUTTLEFISH_HOST"],
+ compile_multilib: "64",
+ },
+ // We don't need Darwin host-side builds
+ darwin: {
+ enabled: false,
+ },
+ },
+ cflags: ["-Werror", "-Wall"],
+}
+
+cc_defaults {
+ name: "cuttlefish_guest_only",
defaults: ["cuttlefish_base"],
}
-// Defaults for cuttlefish modules that are available only in the host-side OS. Here "host" includes
-// both (1) non-Android OS like gLinux or Ubuntu, and (2) Android OS that is capable of running
-// guest VM(s) in it. Note that, in the context of the Android build systm - Soong - (1) is called
-// as "host" and (2) is called as "target". But here, the term "host" is in the context of VMs. If a
-// module is for the host-side VM (either Android or non-Android), "cuttlefish_host" shall be used.
cc_defaults {
- name: "cuttlefish_host",
- host_supported: true, // this "host" means (1)
- device_supported: true, // this is for (2)
- vendor_available: true,
+ name: "cuttlefish_host_only",
+ device_supported: false,
+ host_supported: true,
defaults: ["cuttlefish_base"],
}
-// Same as "cuttlefish_host", but only for non-Android OS.
cc_defaults {
- name: "cuttlefish_buildhost_only",
+ name: "cuttlefish_host_and_guest",
host_supported: true,
- device_supported: false,
defaults: ["cuttlefish_base"],
}
@@ -134,19 +114,30 @@ cc_defaults {
}
cc_defaults {
- name: "cuttlefish_libicuuc",
+ name: "cuttlefish_host_config",
target: {
- host: {
- shared_libs: [
- "libicuuc",
+ linux_glibc: {
+ static_libs: [
+ "libcuttlefish_host_config",
],
},
},
}
cc_defaults {
+ name: "cuttlefish_libicuuc",
+ shared_libs: [
+ "libicuuc",
+ "libandroidicu",
+ ],
+}
+
+cc_defaults {
name: "cuttlefish_health_storage",
defaults: ["enabled_on_q_and_later"],
+ vintf_fragments: [
+ "manifest_android.hardware.health.storage@1.0.cuttlefish.xml",
+ ],
}
java_test_host {
@@ -160,8 +151,3 @@ java_test_host {
test_suites: ["general-tests"],
}
-
-filegroup {
- name: "cf_dtb",
- srcs: ["dtb.img"],
-}
diff --git a/Android.mk b/Android.mk
index 59e98066e..94584ccd6 100644
--- a/Android.mk
+++ b/Android.mk
@@ -20,9 +20,5 @@ include $(LOCAL_PATH)/fetcher.mk
include $(CLEAR_VARS)
include $(LOCAL_PATH)/host_package.mk
+include $(call first-makefiles-under,$(LOCAL_PATH))
endif
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/AndroidProducts.mk b/AndroidProducts.mk
index 8d06ed7d2..0b373117c 100644
--- a/AndroidProducts.mk
+++ b/AndroidProducts.mk
@@ -15,33 +15,21 @@
#
PRODUCT_MAKEFILES := \
- aosp_cf_arm_only_phone:$(LOCAL_DIR)/vsoc_arm_only/phone/aosp_cf.mk \
aosp_cf_arm64_auto:$(LOCAL_DIR)/vsoc_arm64/auto/aosp_cf.mk \
aosp_cf_arm64_phone:$(LOCAL_DIR)/vsoc_arm64/phone/aosp_cf.mk \
- aosp_cf_arm64_only_phone:$(LOCAL_DIR)/vsoc_arm64_only/phone/aosp_cf.mk \
- aosp_cf_x86_64_auto:$(LOCAL_DIR)/vsoc_x86_64/auto/device.mk \
- aosp_cf_x86_64_pc:$(LOCAL_DIR)/vsoc_x86_64/pc/aosp_cf.mk \
aosp_cf_x86_64_phone:$(LOCAL_DIR)/vsoc_x86_64/phone/aosp_cf.mk \
- aosp_cf_x86_64_tv:$(LOCAL_DIR)/vsoc_x86_64/tv/device.mk \
- aosp_cf_x86_64_foldable:$(LOCAL_DIR)/vsoc_x86_64/phone/aosp_cf_foldable.mk \
- aosp_cf_x86_64_only_phone:$(LOCAL_DIR)/vsoc_x86_64_only/phone/aosp_cf.mk \
aosp_cf_x86_auto:$(LOCAL_DIR)/vsoc_x86/auto/device.mk \
aosp_cf_x86_pasan:$(LOCAL_DIR)/vsoc_x86/pasan/aosp_cf.mk \
aosp_cf_x86_phone:$(LOCAL_DIR)/vsoc_x86/phone/aosp_cf.mk \
aosp_cf_x86_phone_noapex:$(LOCAL_DIR)/vsoc_x86_noapex/aosp_cf_noapex.mk \
- aosp_cf_x86_only_phone:$(LOCAL_DIR)/vsoc_x86_only/phone/aosp_cf.mk \
aosp_cf_x86_go_phone:$(LOCAL_DIR)/vsoc_x86/go_phone/device.mk \
aosp_cf_x86_go_512_phone:$(LOCAL_DIR)/vsoc_x86/go_512_phone/device.mk \
aosp_cf_x86_tv:$(LOCAL_DIR)/vsoc_x86/tv/device.mk
-
COMMON_LUNCH_CHOICES := \
aosp_cf_arm64_auto-userdebug \
aosp_cf_arm64_phone-userdebug \
- aosp_cf_x86_64_pc-userdebug \
aosp_cf_x86_64_phone-userdebug \
- aosp_cf_x86_64_foldable-userdebug \
aosp_cf_x86_auto-userdebug \
aosp_cf_x86_phone-userdebug \
- aosp_cf_x86_tv-userdebug \
- aosp_cf_x86_64_tv-userdebug
+ aosp_cf_x86_tv-userdebug
diff --git a/CleanSpec.mk b/CleanSpec.mk
index f23584118..34f1634e6 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -62,9 +62,3 @@ $(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/etc/init/android.hardware.po
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/bin/hw/android.hardware.dumpstate@1.1-service.cuttlefish)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/etc/init/android.hardware.dumpstate@1.1-service.cuttlefish.rc)
-
-$(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/bin/hw/android.hardware.health.storage@1.0-service.cuttlefish)
-$(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/etc/init/android.hardware.health.storage@1.0-service.cuttlefish.rc)
-$(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/etc/vintf/manifest/manifest_android.hardware.health.storage@1.0.cuttlefish.xml)
-
-$(call add-clean-step, rm -rf $(PRODUCT_OUT)/product/apex/com.android.gki.*)
diff --git a/METADATA b/METADATA
deleted file mode 100644
index d97975ca3..000000000
--- a/METADATA
+++ /dev/null
@@ -1,3 +0,0 @@
-third_party {
- license_type: NOTICE
-}
diff --git a/OWNERS b/OWNERS
index a67015839..194402946 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,7 +1,6 @@
# Current team members
adelva@google.com
jemoreira@google.com
-kwstephenkim@google.com
malchev@google.com
muntsinger@google.com
natsu@google.com
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
deleted file mode 100644
index 7ba873b13..000000000
--- a/PREUPLOAD.cfg
+++ /dev/null
@@ -1,7 +0,0 @@
-[Builtin Hooks]
-clang_format = true
-rustfmt = true
-
-[Builtin Hooks Options]
-clang_format = --commit ${PREUPLOAD_COMMIT} --style file --extensions c,h,cc,cpp
-rustfmt = --config-path=rustfmt.toml
diff --git a/README.md b/README.md
index 222089801..531f84051 100644
--- a/README.md
+++ b/README.md
@@ -1,77 +1,52 @@
-# Cuttlefish Getting Started
+# So you want to try cuttlefish?
-## Try Cuttlefish
+1. Download, build, and install the host debian package:
-1. Make sure virtualization with KVM is available.
+```bash
+git clone https://github.com/google/android-cuttlefish
+cd android-cuttlefish
+debuild -i -us -uc -b
+sudo dpkg -i ../cuttlefish-common_*_amd64.deb
+sudo apt-get install -f
+```
- ```bash
- grep -c -w "vmx\|svm" /proc/cpuinfo
- ```
-
- This should return a non-zero value. If running on a cloud machine, this may
- take cloud-vendor-specific steps to enable. For Google Compute Engine
- specifically, see the [GCE guide].
-
- [GCE guide]: https://cloud.google.com/compute/docs/instances/enable-nested-virtualization-vm-instances
-
-2. Download, build, and install the host debian package:
-
- ```bash
- git clone https://github.com/google/android-cuttlefish
- cd android-cuttlefish
- debuild -i -us -uc -b
- sudo dpkg -i ../cuttlefish-common_*_amd64.deb || sudo apt-get install -f
- sudo reboot
- ```
-
- The reboot will trigger installing additional kernel modules and applying
- udev rules.
-
-3. Go to http://ci.android.com/
-4. Enter a branch name. Start with `aosp-master` if you don't know what you're
+2. Go to http://ci.android.com/
+3. Enter a branch name. Start with `aosp-master` if you don't know what you're
looking for
-5. Navigate to `aosp_cf_x86_64_phone` and click on `userdebug` for the latest build
-6. Click on `Artifacts`
-7. Scroll down to the OTA images. These packages look like
- `aosp_cf_x86_64_phone-img-xxxxxx.zip` -- it will always have `img` in the name.
+4. Navigate to `aosp_cf_x86_phone` and click on `userdebug` for the latest build
+5. Click on `Artifacts`
+6. Scroll down to the OTA images. These packages look like
+ `aosp_cf_x86_phone-img-xxxxxx.zip` -- it will always have `img` in the name.
Download this file
-8. Scroll down to `cvd-host_package.tar.gz`. You should always download a host
+7. Scroll down to `cvd-host_package.tar.gz`. You should always download a host
package from the same build as your images.
-9. On your local system, combine the packages:
+8. On your local system, combine the packages:
- ```bash
- mkdir cf
- cd cf
- tar xvf /path/to/cvd-host_package.tar.gz
- unzip /path/to/aosp_cf_x86_64_phone-img-xxxxxx.zip
- ```
+```bash
+mkdir cf
+cd cf
+tar xvf /path/to/cvd-host_package.tar.gz
+unzip /path/to/aosp_cf_x86_phone-img-xxxxxx.zip
+```
-10. Launch cuttlefish with:
+8. Launch cuttlefish with:
`$ HOME=$PWD ./bin/launch_cvd`
-11. Stop cuttlefish with:
+9. Stop cuttlefish with:
`$ HOME=$PWD ./bin/stop_cvd`
-## Debug Cuttlefish
+# So you want to debug cuttlefish?
You can use `adb` to debug it, just like a physical device:
`$ ./bin/adb -e shell`
-## Launch Viewer (WebRTC)
-
-When launching with `---start_webrtc` (the default), you can see a list of all
-available devices at `https://localhost:8443` . For more information, see the
-WebRTC on Cuttlefish
-[documentation](https://source.android.com/setup/create/cuttlefish-ref-webrtc).
-
-## Launch Viewer (VNC)
+# So you want to see cuttlefish?
-When launching with `--start_vnc_server=true` , You can use the
-[TightVNC JViewer](https://www.tightvnc.com/download.php). Once you have
-downloaded the *TightVNC Java Viewer JAR in a ZIP archive*, run it with
+You can use the [TightVNC JViewer](https://www.tightvnc.com/download.php). Once
+you have downloaded the *TightVNC Java Viewer JAR in a ZIP archive*, run it with
`$ java -jar tightvnc-jviewer.jar -ScalingFactor=50 -Tunneling=no -host=localhost -port=6444`
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 4067d2712..8c7bc4ba1 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -2,9 +2,6 @@
"postsubmit" : [
{
"name": "tombstone_transmit_tests"
- },
- {
- "name": "RebootRecoveryTest"
}
],
"presubmit": [
@@ -16,9 +13,6 @@
},
{
"name": "hal_implementation_test"
- },
- {
- "name": "vts_ibase_test"
}
]
}
diff --git a/build/Android.bp b/build/Android.bp
deleted file mode 100644
index d51631334..000000000
--- a/build/Android.bp
+++ /dev/null
@@ -1,205 +0,0 @@
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-bootstrap_go_package {
- name: "cuttlefish-soong-rules",
- pkgPath: "android/soong/cuttlefish",
- deps: [
- "blueprint",
- "soong",
- "soong-android",
- ],
- srcs: [
- "cvd-host-package.go",
- ],
- pluginFor: ["soong_build"],
-}
-
-// Allow cvd-host-package.go to read custom action config variables
-// from ctx.Config().VendorConfig("cvd")
-soong_config_module_type {
- name: "cvd_host_package_customization",
- module_type: "cvd_host_package",
- config_namespace: "cvd",
- value_variables: [
- "launch_configs",
- "custom_action_config",
- "custom_action_servers",
- ],
-}
-
-cvd_host_tools = [
- "android.hardware.automotive.vehicle@2.0-virtualization-grpc-server",
- "adb",
- "adb_connector",
- "adbshell",
- "allocd",
- "allocd_client",
- "assemble_cvd",
- "bt_connector",
- "common_crosvm",
- "config_server",
- "console_forwarder",
- "crosvm",
- "cvd_host_bugreport",
- "cvd_status",
- "extract-ikconfig",
- "extract-vmlinux",
- "fsck.f2fs",
- "gnss_grpc_proxy",
- "kernel_log_monitor",
- "launch_cvd",
- "libgrpc++",
- "libgrpc++_unsecure",
- "log_tee",
- "logcat_receiver",
- "lpmake",
- "lpunpack",
- "lz4",
- "make_f2fs",
- "metrics",
- "mkbootfs",
- "mkbootimg",
- "mkenvimage",
- "modem_simulator",
- "ms-tpm-20-ref",
- "newfs_msdos",
- "powerwash_cvd",
- "restart_cvd",
- "root-canal",
- // TODO(b/186487510): remove libchrome and libbacktrace when ASan-related dependency issue is resolved.
- "libchrome",
- "libbacktrace",
- "run_cvd",
- "secure_env",
- "socket_vsock_proxy",
- "stop_cvd",
- "tapsetiff",
- "tombstone_receiver",
- "toybox",
- "unpack_bootimg",
- "vnc_server",
- "webRTC",
- "webrtc_operator",
-]
-
-cvd_bluetooth_config_files = [
- "controller_properties.json",
- "default_commands",
-]
-
-cvd_host_tests = [
- "cuttlefish_net_tests",
- "modem_simulator_test",
-]
-
-cvd_host_webrtc_assets = [
- "webrtc_adb.js",
- "webrtc_app.js",
- "webrtc_controls.js",
- "webrtc_cf.js",
- "webrtc_index.html",
- "webrtc_rootcanal.js",
- "webrtc_server.crt",
- "webrtc_server.key",
- "webrtc_server.p12",
- "webrtc_style.css",
- "webrtc_controls.css",
- "webrtc_trusted.pem",
-]
-
-cvd_host_model_simulator_files = [
- "iccprofile_for_sim0.xml_host",
- "iccprofile_for_sim0_for_CtsCarrierApiTestCases.xml_host",
- "numeric_operator.xml_host",
-]
-
-cvd_host_seccomp_policy_x86_64 = [
- "9p_device.policy_x86_64",
- "balloon_device.policy_x86_64",
- "block_device.policy_x86_64",
- "cras_audio_device.policy_x86_64",
- "fs_device.policy_x86_64",
- "gpu_device.policy_x86_64",
- "input_device.policy_x86_64",
- "net_device.policy_x86_64",
- "null_audio_device.policy_x86_64",
- "pmem_device.policy_x86_64",
- "rng_device.policy_x86_64",
- "serial.policy_x86_64",
- "tpm_device.policy_x86_64",
- "vfio_device.policy_x86_64",
- "vhost_net_device.policy_x86_64",
- "vhost_vsock_device.policy_x86_64",
- "video_device.policy_x86_64",
- "vios_audio_device.policy_x86_64",
- "wl_device.policy_x86_64",
- "xhci.policy_x86_64",
-]
-
-cvd_host_seccomp_policy_arm64 = [
- "9p_device.policy_aarch64",
- "balloon_device.policy_aarch64",
- "block_device.policy_aarch64",
- "cras_audio_device.policy_aarch64",
- "fs_device.policy_aarch64",
- "gpu_device.policy_aarch64",
- "input_device.policy_aarch64",
- "net_device.policy_aarch64",
- "null_audio_device.policy_aarch64",
- "pmem_device.policy_aarch64",
- "rng_device.policy_aarch64",
- "serial.policy_aarch64",
- "tpm_device.policy_aarch64",
- "vhost_net_device.policy_aarch64",
- "vhost_vsock_device.policy_aarch64",
- "vios_audio_device.policy_aarch64",
- "wl_device.policy_aarch64",
- "xhci.policy_aarch64",
-]
-
-cvd_host_package_customization {
- name: "cvd-host_package",
- deps: cvd_host_tools +
- cvd_host_tests,
- multilib: {
- common: {
- deps: cvd_host_webrtc_assets +
- cvd_host_model_simulator_files +
- cvd_bluetooth_config_files,
- },
- },
-
- arch: {
- x86_64: {
- multilib: {
- common: {
- deps: cvd_host_seccomp_policy_x86_64,
- },
- },
- },
- arm64: {
- multilib: {
- common: {
- deps: cvd_host_seccomp_policy_arm64,
- },
- },
- },
- },
- target: {
- linux_bionic: {
- multilib: {
- common: {
- deps: ["tzdata_host"],
- },
- },
- },
- linux_bionic_x86_64: {
- enabled: false,
- },
- darwin: {
- enabled: false,
- },
- },
-}
diff --git a/build/README.md b/build/README.md
deleted file mode 100644
index dc66c0a96..000000000
--- a/build/README.md
+++ /dev/null
@@ -1,27 +0,0 @@
-## Custom Actions
-
-To add custom actions to the WebRTC control panel, create a custom action config
-JSON file in your virtual device product makefile directory, create a
-`prebuilt_etc_host` module for the JSON file with `sub_dir`
-`cvd_custom_action_config`, then set the build variable
-`SOONG_CONFIG_cvd_custom_action_config` to the name of that module. For example:
-
-```
-Android.bp:
- prebuilt_etc_host {
- name: "my_custom_action_config.json",
- src: "my_custom_action_config.json",
- // The sub_dir must always equal the following value:
- sub_dir: "cvd_custom_action_config",
- }
-
-my_virtual_device.mk:
- SOONG_CONFIG_NAMESPACES += cvd
- SOONG_CONFIG_cvd += custom_action_config
- SOONG_CONFIG_cvd_custom_action_config := my_custom_action_config.json
-```
-
-TODO(b/171709037): Add documentation to source.android.com
-
-See https://source.android.com/setup/create/cuttlefish-control-panel for
-detailed information about the format of the config file.
diff --git a/build/cvd-host-package.go b/build/cvd-host-package.go
deleted file mode 100644
index b025386cd..000000000
--- a/build/cvd-host-package.go
+++ /dev/null
@@ -1,106 +0,0 @@
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package cuttlefish
-
-import (
- "fmt"
- "strings"
-
- "github.com/google/blueprint"
-
- "android/soong/android"
-)
-
-func init() {
- android.RegisterModuleType("cvd_host_package", cvdHostPackageFactory)
-}
-
-type cvdHostPackage struct {
- android.ModuleBase
- android.PackagingBase
-}
-
-func cvdHostPackageFactory() android.Module {
- module := &cvdHostPackage{}
- android.InitPackageModule(module)
- android.InitAndroidArchModule(module, android.HostSupported, android.MultilibFirst)
- module.IgnoreMissingDependencies = true
- return module
-}
-
-type dependencyTag struct {
- blueprint.BaseDependencyTag
- android.InstallAlwaysNeededDependencyTag // to force installation of both "deps" and manually added dependencies
- android.PackagingItemAlwaysDepTag // to force packaging of both "deps" and manually added dependencies
-}
-
-var cvdHostPackageDependencyTag = dependencyTag{}
-
-func (c *cvdHostPackage) DepsMutator(ctx android.BottomUpMutatorContext) {
- c.AddDeps(ctx, cvdHostPackageDependencyTag)
-
- variations := []blueprint.Variation{
- {Mutator: "os", Variation: ctx.Target().Os.String()},
- {Mutator: "arch", Variation: android.Common.String()},
- }
- for _, dep := range strings.Split(
- ctx.Config().VendorConfig("cvd").String("launch_configs"), " ") {
- if ctx.OtherModuleExists(dep) {
- ctx.AddVariationDependencies(variations, cvdHostPackageDependencyTag, dep)
- }
- }
-
- // If cvd_custom_action_config is set, include custom action servers in the
- // host package as specified by cvd_custom_action_servers.
- customActionConfig := ctx.Config().VendorConfig("cvd").String("custom_action_config")
- if customActionConfig != "" && ctx.OtherModuleExists(customActionConfig) {
- ctx.AddVariationDependencies(variations, cvdHostPackageDependencyTag,
- customActionConfig)
- for _, dep := range strings.Split(
- ctx.Config().VendorConfig("cvd").String("custom_action_servers"), " ") {
- if ctx.OtherModuleExists(dep) {
- ctx.AddVariationDependencies(nil, cvdHostPackageDependencyTag, dep)
- }
- }
- }
-}
-
-var pctx = android.NewPackageContext("android/soong/cuttlefish")
-
-func (c *cvdHostPackage) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- zipFile := android.PathForModuleOut(ctx, "package.zip")
- c.CopyDepsToZip(ctx, zipFile)
-
- // Dir where to extract the zip file and construct the final tar.gz from
- packageDir := android.PathForModuleOut(ctx, ".temp")
- builder := android.NewRuleBuilder(pctx, ctx)
- builder.Command().
- BuiltTool("zipsync").
- FlagWithArg("-d ", packageDir.String()).
- Input(zipFile)
-
- output := android.PathForModuleOut(ctx, "package.tar.gz")
- builder.Command().Text("tar Scfz").
- Output(output).
- FlagWithArg("-C ", packageDir.String()).
- Flag("--mtime='2020-01-01'"). // to have reproducible builds
- Text(".")
-
- builder.Command().Text("rm").Flag("-rf").Text(packageDir.String())
-
- builder.Build("cvd_host_package", fmt.Sprintf("Packaging %s", c.BaseModuleName()))
-
- ctx.InstallFile(android.PathForModuleInstall(ctx), c.BaseModuleName()+".tar.gz", output)
-}
diff --git a/host/commands/secure_env/tpm.h b/common/Android.bp
index 201e5e775..2280c23eb 100644
--- a/host/commands/secure_env/tpm.h
+++ b/common/Android.bp
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2020 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,13 +13,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#pragma once
-
-#include <tss2/tss2_tcti.h>
-
-class Tpm {
-public:
- virtual ~Tpm() = default;
-
- virtual TSS2_TCTI_CONTEXT* TctiContext() = 0;
-};
+subdirs = [
+ "commands",
+ "frontend",
+ "libs",
+]
diff --git a/host/libs/config/host_tools_version.h b/common/commands/Android.bp
index 06b075ec0..8264fcc0e 100644
--- a/host/libs/config/host_tools_version.h
+++ b/common/commands/Android.bp
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2020 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,5 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#pragma once
-
-#include <cstdint>
-#include <map>
-#include <string>
-
-namespace cuttlefish {
-
-std::map<std::string, uint32_t> HostToolsCrc();
-
-} // namespace cuttlefish
+subdirs = [
+]
diff --git a/host/commands/modem_simulator/unittest/main_test.cpp b/common/frontend/Android.bp
index 7afadb454..39a4dbb98 100644
--- a/host/commands/modem_simulator/unittest/main_test.cpp
+++ b/common/frontend/Android.bp
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2020 The Android Open Source Project
+// 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.
@@ -13,12 +13,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include <gtest/gtest.h>
-#include <gflags/gflags.h>
-
-DEFINE_int32(instance_number, 1, "modem simulator instance numbers");
-
-int main(int argc, char** argv) {
- ::testing::InitGoogleTest(&argc, argv);
- return RUN_ALL_TESTS();
-}
+subdirs = [
+ "socket_vsock_proxy",
+]
diff --git a/common/frontend/socket_vsock_proxy/Android.bp b/common/frontend/socket_vsock_proxy/Android.bp
index 93354085a..c9684a56c 100644
--- a/common/frontend/socket_vsock_proxy/Android.bp
+++ b/common/frontend/socket_vsock_proxy/Android.bp
@@ -13,10 +13,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
cc_binary {
name: "socket_vsock_proxy",
srcs: [
@@ -26,8 +22,6 @@ cc_binary {
"libbase",
"libcuttlefish_fs",
"libcuttlefish_utils",
- "libcuttlefish_kernel_log_monitor_utils",
- "libjsoncpp",
"liblog",
],
static_libs: [
@@ -37,12 +31,9 @@ cc_binary {
host: {
static_libs: [
"libcuttlefish_host_config",
+ "libjsoncpp",
],
},
},
- // Don't inherit from cuttlefish_host because it is with `vendor_available: true` which isn't
- // compatible with `vendor: true`.
- defaults: ["cuttlefish_base"],
- host_supported: true,
- vendor: true,
+ defaults: ["cuttlefish_host_and_guest"]
}
diff --git a/common/frontend/socket_vsock_proxy/main.cpp b/common/frontend/socket_vsock_proxy/main.cpp
index cf68821bc..78ca85935 100644
--- a/common/frontend/socket_vsock_proxy/main.cpp
+++ b/common/frontend/socket_vsock_proxy/main.cpp
@@ -20,7 +20,6 @@
#include <gflags/gflags.h>
#include "common/libs/fs/shared_fd.h"
-#include "host/commands/kernel_log_monitor/utils.h"
#ifdef CUTTLEFISH_HOST
#include "host/libs/config/logging.h"
@@ -35,21 +34,12 @@ DEFINE_string(server, "",
DEFINE_uint32(tcp_port, 0, "TCP port");
DEFINE_uint32(vsock_port, 0, "vsock port");
DEFINE_uint32(vsock_cid, 0, "Vsock cid to initiate connections to");
-DEFINE_int32(adbd_events_fd, -1, "A file descriptor. If set it will wait for "
- "AdbdStarted boot event from the kernel log "
- "monitor before creating a tcp-vsock tunnel."
- "This option is used by --server=tcp only "
- "when socket_vsock_proxy runs as a host service");
-DEFINE_int32(
- server_fd, -1,
- "A file descriptor. If set the passed file descriptor will be used as the "
- "server and the corresponding port flag will be ignored");
namespace {
// Sends packets, Shutdown(SHUT_WR) on destruction
class SocketSender {
public:
- explicit SocketSender(cuttlefish::SharedFD socket) : socket_{socket} {}
+ explicit SocketSender(cvd::SharedFD socket) : socket_{socket} {}
SocketSender(SocketSender&&) = default;
SocketSender& operator=(SocketSender&&) = default;
@@ -73,8 +63,8 @@ class SocketSender {
socket_->Send(packet + written,
length - written, MSG_NOSIGNAL);
if (just_written <= 0) {
- LOG(WARNING) << "Couldn't write to client: "
- << strerror(socket_->GetErrno());
+ LOG(INFO) << "Couldn't write to client: "
+ << strerror(socket_->GetErrno());
return just_written;
}
written += just_written;
@@ -83,12 +73,12 @@ class SocketSender {
}
private:
- cuttlefish::SharedFD socket_;
+ cvd::SharedFD socket_;
};
class SocketReceiver {
public:
- explicit SocketReceiver(cuttlefish::SharedFD socket) : socket_{socket} {}
+ explicit SocketReceiver(cvd::SharedFD socket) : socket_{socket} {}
SocketReceiver(SocketReceiver&&) = default;
SocketReceiver& operator=(SocketReceiver&&) = default;
@@ -107,7 +97,7 @@ class SocketReceiver {
}
private:
- cuttlefish::SharedFD socket_;
+ cvd::SharedFD socket_;
};
void SocketToVsock(SocketReceiver socket_receiver,
@@ -120,7 +110,7 @@ void SocketToVsock(SocketReceiver socket_receiver,
break;
}
}
- LOG(DEBUG) << "Socket to vsock exiting";
+ LOG(INFO) << "Socket to vsock exiting";
}
void VsockToSocket(SocketSender socket_sender,
@@ -136,63 +126,35 @@ void VsockToSocket(SocketSender socket_sender,
break;
}
}
- LOG(DEBUG) << "Vsock to socket exiting";
+ LOG(INFO) << "Vsock to socket exiting";
}
// One thread for reading from shm and writing into a socket.
// One thread for reading from a socket and writing into shm.
-void HandleConnection(cuttlefish::SharedFD vsock,
- cuttlefish::SharedFD socket) {
+void HandleConnection(cvd::SharedFD vsock,
+ cvd::SharedFD socket) {
auto socket_to_vsock =
std::thread(SocketToVsock, SocketReceiver{socket}, SocketSender{vsock});
VsockToSocket(SocketSender{socket}, SocketReceiver{vsock});
socket_to_vsock.join();
}
-void WaitForAdbdToBeStarted(int events_fd) {
- auto evt_shared_fd = cuttlefish::SharedFD::Dup(events_fd);
- close(events_fd);
- while (evt_shared_fd->IsOpen()) {
- std::optional<monitor::ReadEventResult> read_result =
- monitor::ReadEvent(evt_shared_fd);
- if (!read_result) {
- LOG(ERROR) << "Failed to read a complete kernel log adb event.";
- // The file descriptor can't be trusted anymore, stop waiting and try to
- // connect
- return;
- }
-
- if (read_result->event == monitor::Event::AdbdStarted) {
- LOG(DEBUG) << "Adbd has started in the guest, connecting adb";
- return;
- }
- }
-}
-
-// intented to run as cuttlefish host service
[[noreturn]] void TcpServer() {
- LOG(DEBUG) << "starting TCP server on " << FLAGS_tcp_port
- << " for vsock port " << FLAGS_vsock_port;
- cuttlefish::SharedFD server;
- if (FLAGS_server_fd < 0) {
- server =
- cuttlefish::SharedFD::SocketLocalServer(FLAGS_tcp_port, SOCK_STREAM);
- } else {
- server = cuttlefish::SharedFD::Dup(FLAGS_server_fd);
- close(FLAGS_server_fd);
- }
+ LOG(INFO) << "starting TCP server on " << FLAGS_tcp_port << " for vsock port "
+ << FLAGS_vsock_port;
+ auto server = cvd::SharedFD::SocketLocalServer(FLAGS_tcp_port, SOCK_STREAM);
CHECK(server->IsOpen()) << "Could not start server on " << FLAGS_tcp_port;
- LOG(DEBUG) << "Accepting client connections";
+ LOG(INFO) << "Accepting client connections";
int last_failure_reason = 0;
while (true) {
- auto client_socket = cuttlefish::SharedFD::Accept(*server);
+ auto client_socket = cvd::SharedFD::Accept(*server);
CHECK(client_socket->IsOpen()) << "error creating client socket";
- cuttlefish::SharedFD vsock_socket = cuttlefish::SharedFD::VsockClient(
+ cvd::SharedFD vsock_socket = cvd::SharedFD::VsockClient(
FLAGS_vsock_cid, FLAGS_vsock_port, SOCK_STREAM);
if (vsock_socket->IsOpen()) {
last_failure_reason = 0;
- LOG(DEBUG) << "Connected to vsock:" << FLAGS_vsock_cid << ":"
- << FLAGS_vsock_port;
+ LOG(INFO) << "Connected to vsock:" << FLAGS_vsock_cid << ":"
+ << FLAGS_vsock_port;
} else {
// Don't log if the previous connection failed with the same error
if (last_failure_reason != vsock_socket->GetErrno()) {
@@ -208,9 +170,9 @@ void WaitForAdbdToBeStarted(int events_fd) {
}
}
-cuttlefish::SharedFD OpenSocketConnection() {
+cvd::SharedFD OpenSocketConnection() {
while (true) {
- auto sock = cuttlefish::SharedFD::SocketLocalClient(FLAGS_tcp_port, SOCK_STREAM);
+ auto sock = cvd::SharedFD::SocketLocalClient(FLAGS_tcp_port, SOCK_STREAM);
if (sock->IsOpen()) {
return sock;
}
@@ -231,28 +193,22 @@ bool socketErrorIsRecoverable(int error) {
}
}
-// intended to run inside Android guest
[[noreturn]] void VsockServer() {
- LOG(DEBUG) << "Starting vsock server on " << FLAGS_vsock_port;
- cuttlefish::SharedFD vsock;
- if (FLAGS_server_fd < 0) {
- do {
- vsock = cuttlefish::SharedFD::VsockServer(FLAGS_vsock_port, SOCK_STREAM);
- if (!vsock->IsOpen() && !socketErrorIsRecoverable(vsock->GetErrno())) {
- LOG(ERROR) << "Could not open vsock socket: " << vsock->StrError();
- SleepForever();
- }
- } while (!vsock->IsOpen());
- } else {
- vsock = cuttlefish::SharedFD::Dup(FLAGS_server_fd);
- close(FLAGS_server_fd);
- }
+ LOG(INFO) << "Starting vsock server on " << FLAGS_vsock_port;
+ cvd::SharedFD vsock;
+ do {
+ vsock = cvd::SharedFD::VsockServer(FLAGS_vsock_port, SOCK_STREAM);
+ if (!vsock->IsOpen() && !socketErrorIsRecoverable(vsock->GetErrno())) {
+ LOG(ERROR) << "Could not open vsock socket: " << vsock->StrError();
+ SleepForever();
+ }
+ } while (!vsock->IsOpen());
CHECK(vsock->IsOpen()) << "Could not start server on " << FLAGS_vsock_port;
while (true) {
- LOG(DEBUG) << "waiting for vsock connection";
- auto vsock_client = cuttlefish::SharedFD::Accept(*vsock);
+ LOG(INFO) << "waiting for vsock connection";
+ auto vsock_client = cvd::SharedFD::Accept(*vsock);
CHECK(vsock_client->IsOpen()) << "error creating vsock socket";
- LOG(DEBUG) << "vsock socket accepted";
+ LOG(INFO) << "vsock socket accepted";
auto client = OpenSocketConnection();
CHECK(client->IsOpen()) << "error connecting to guest client";
auto thread = std::thread(HandleConnection, std::move(vsock_client),
@@ -265,23 +221,14 @@ bool socketErrorIsRecoverable(int error) {
int main(int argc, char* argv[]) {
#ifdef CUTTLEFISH_HOST
- cuttlefish::DefaultSubprocessLogging(argv);
+ cvd::DefaultSubprocessLogging(argv);
#else
::android::base::InitLogging(argv, android::base::LogdLogger());
#endif
google::ParseCommandLineFlags(&argc, &argv, true);
- CHECK((FLAGS_server == "tcp" && FLAGS_server_fd >= 0) || FLAGS_tcp_port != 0)
- << "Must specify -tcp_port or -server_fd (with -server=tcp) flag";
- CHECK((FLAGS_server == "vsock" && FLAGS_server_fd >= 0) ||
- FLAGS_vsock_port != 0)
- << "Must specify -vsock_port or -server_fd (with -server=vsock) flag";
-
- if (FLAGS_adbd_events_fd >= 0) {
- LOG(DEBUG) << "Wating AdbdStarted boot event from the kernel log";
- WaitForAdbdToBeStarted(FLAGS_adbd_events_fd);
- }
-
+ CHECK(FLAGS_tcp_port != 0) << "Must specify -tcp_port flag";
+ CHECK(FLAGS_vsock_port != 0) << "Must specify -vsock_port flag";
if (FLAGS_server == "tcp") {
CHECK(FLAGS_vsock_cid != 0) << "Must specify -vsock_cid flag";
TcpServer();
diff --git a/common/libs/Android.bp b/common/libs/Android.bp
new file mode 100644
index 000000000..40b7f0c1d
--- /dev/null
+++ b/common/libs/Android.bp
@@ -0,0 +1,25 @@
+//
+// 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.
+
+subdirs = [
+ "device_config",
+ "fs",
+ "net",
+ "strings",
+ "tcp_socket",
+ "threads",
+ "time",
+ "utils",
+]
diff --git a/common/libs/concurrency/multiplexer.h b/common/libs/concurrency/multiplexer.h
deleted file mode 100644
index 065c1a2f8..000000000
--- a/common/libs/concurrency/multiplexer.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2020 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 <condition_variable>
-#include <memory>
-#include <vector>
-
-#include "common/libs/concurrency/semaphore.h"
-#include "common/libs/concurrency/thread_safe_queue.h"
-
-namespace cuttlefish {
-namespace confui {
-template <typename T>
-class Multiplexer {
- public:
- Multiplexer(int n_qs, int max_elements) : sem_items_{0}, next_{0} {
- auto drop_new = [](typename ThreadSafeQueue<T>::QueueImpl* internal_q) {
- internal_q->pop_front();
- };
- for (int i = 0; i < n_qs; i++) {
- auto queue = std::make_unique<ThreadSafeQueue<T>>(max_elements, drop_new);
- queues_.push_back(std::move(queue));
- }
- }
-
- int GetNewQueueId() {
- CHECK(next_ < queues_.size())
- << "can't get more queues than " << queues_.size();
- return next_++;
- }
-
- void Push(const int idx, T&& t) {
- CheckIdx(idx);
- queues_[idx]->Push(t);
- sem_items_.SemPost();
- }
-
- T Pop() {
- // the idx must have an item!
- // no waiting in fn()!
- sem_items_.SemWait();
- for (auto& q : queues_) {
- if (q->IsEmpty()) {
- continue;
- }
- return q->Pop();
- }
- CHECK(false) << "Multiplexer.Pop() should be able to return an item";
- // must not reach here
- return T{};
- }
-
- private:
- void CheckIdx(const int idx) {
- CHECK(idx >= 0 && idx < queues_.size()) << "queues_ array out of bound";
- }
- // total items across the queues
- Semaphore sem_items_;
- std::vector<std::unique_ptr<ThreadSafeQueue<T>>> queues_;
- int next_;
-};
-} // end of namespace confui
-} // end of namespace cuttlefish
diff --git a/common/libs/concurrency/semaphore.h b/common/libs/concurrency/semaphore.h
deleted file mode 100644
index 5af43a73d..000000000
--- a/common/libs/concurrency/semaphore.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2021 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 <condition_variable>
-#include <functional>
-#include <memory>
-#include <mutex>
-
-namespace cuttlefish {
-class Semaphore {
- public:
- Semaphore(const unsigned int init_val = 0, const unsigned int cap = 30000)
- : count_{init_val}, capacity_{cap} {}
-
- void SemWait() {
- std::unique_lock<std::mutex> lock(mtx_);
- resoure_cv_.wait(lock, [this]() -> bool { return count_ > 0; });
- --count_;
- room_cv_.notify_one();
- }
-
- void SemPost() {
- std::unique_lock<std::mutex> lock(mtx_);
- room_cv_.wait(lock, [this]() -> bool { return count_ <= capacity_; });
- ++count_;
- resoure_cv_.notify_one();
- }
-
- private:
- std::mutex mtx_;
- std::condition_variable resoure_cv_;
- std::condition_variable room_cv_;
- unsigned int count_;
- const unsigned int capacity_; // inclusive upper limit
-};
-
-} // namespace cuttlefish
diff --git a/common/libs/concurrency/thread_annotations.h b/common/libs/concurrency/thread_annotations.h
deleted file mode 100644
index cd568b3c9..000000000
--- a/common/libs/concurrency/thread_annotations.h
+++ /dev/null
@@ -1,72 +0,0 @@
-#pragma once
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#if defined(__SUPPORT_TS_ANNOTATION__) || defined(__clang__)
-#define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x))
-#else
-#define THREAD_ANNOTATION_ATTRIBUTE__(x) // no-op
-#endif
-
-#define CAPABILITY(x) THREAD_ANNOTATION_ATTRIBUTE__(capability(x))
-
-#define SCOPED_CAPABILITY THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable)
-
-#define GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x))
-
-#define PT_GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_by(x))
-
-#define ACQUIRED_BEFORE(...) \
- THREAD_ANNOTATION_ATTRIBUTE__(acquired_before(__VA_ARGS__))
-
-#define ACQUIRED_AFTER(...) \
- THREAD_ANNOTATION_ATTRIBUTE__(acquired_after(__VA_ARGS__))
-
-#define REQUIRES(...) \
- THREAD_ANNOTATION_ATTRIBUTE__(requires_capability(__VA_ARGS__))
-
-#define REQUIRES_SHARED(...) \
- THREAD_ANNOTATION_ATTRIBUTE__(requires_shared_capability(__VA_ARGS__))
-
-#define ACQUIRE(...) \
- THREAD_ANNOTATION_ATTRIBUTE__(acquire_capability(__VA_ARGS__))
-
-#define ACQUIRE_SHARED(...) \
- THREAD_ANNOTATION_ATTRIBUTE__(acquire_shared_capability(__VA_ARGS__))
-
-#define RELEASE(...) \
- THREAD_ANNOTATION_ATTRIBUTE__(release_capability(__VA_ARGS__))
-
-#define RELEASE_SHARED(...) \
- THREAD_ANNOTATION_ATTRIBUTE__(release_shared_capability(__VA_ARGS__))
-
-#define TRY_ACQUIRE(...) \
- THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_capability(__VA_ARGS__))
-
-#define TRY_ACQUIRE_SHARED(...) \
- THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_shared_capability(__VA_ARGS__))
-
-#define EXCLUDES(...) THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(__VA_ARGS__))
-
-#define ASSERT_CAPABILITY(x) THREAD_ANNOTATION_ATTRIBUTE__(assert_capability(x))
-
-#define ASSERT_SHARED_CAPABILITY(x) \
- THREAD_ANNOTATION_ATTRIBUTE__(assert_shared_capability(x))
-
-#define RETURN_CAPABILITY(x) THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x))
-
-#define NO_THREAD_SAFETY_ANALYSIS \
- THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis)
diff --git a/common/libs/confui/Android.bp b/common/libs/confui/Android.bp
deleted file mode 100644
index 13ff2fde3..000000000
--- a/common/libs/confui/Android.bp
+++ /dev/null
@@ -1,36 +0,0 @@
-//
-// Copyright (C) 2021 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-cc_library_static {
- name: "libcuttlefish_confui",
- srcs: [
- "packet.cpp",
- "protocol.cpp",
- ],
- static: {
- static_libs: [
- "libbase",
- "libcuttlefish_fs",
- ],
- shared_libs: [
- "libcrypto", // libcrypto_static is not accessible from all targets
- ],
- },
- defaults: ["cuttlefish_host"],
-}
diff --git a/common/libs/confui/confui.h b/common/libs/confui/confui.h
deleted file mode 100644
index 957fca190..000000000
--- a/common/libs/confui/confui.h
+++ /dev/null
@@ -1,37 +0,0 @@
-//
-// Copyright (C) 2021 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
-
-/**
- * confirmation UI host and guest common library
- *
- * This header should be included by other components outside
- * common/lib/confui. Those inside should use each individual
- * header file(s)
- *
- */
-#include "common/libs/confui/packet.h"
-#include "common/libs/confui/protocol.h"
-#include "common/libs/confui/utils.h"
-
-namespace cuttlefish {
-namespace confui {
-using packet::RecvConfUiMsg;
-using packet::SendAck;
-using packet::SendCmd;
-using packet::SendResponse;
-} // end of namespace confui
-} // end of namespace cuttlefish
diff --git a/common/libs/confui/packet.cpp b/common/libs/confui/packet.cpp
deleted file mode 100644
index d5be03a16..000000000
--- a/common/libs/confui/packet.cpp
+++ /dev/null
@@ -1,131 +0,0 @@
-//
-// Copyright (C) 2021 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 "common/libs/confui/packet.h"
-
-#include <algorithm>
-#include <iostream>
-
-#include <android-base/logging.h>
-#include <android-base/strings.h>
-
-#include "common/libs/confui/protocol.h"
-#include "common/libs/confui/utils.h"
-#include "common/libs/fs/shared_buf.h"
-
-namespace cuttlefish {
-namespace confui {
-namespace packet {
-ConfUiMessage PayloadToConfUiMessage(const std::string& str_to_parse) {
- auto tokens = android::base::Split(str_to_parse, ":");
- ConfUiCheck(tokens.size() >= 3)
- << "PayloadToConfUiMessage takes \"" + str_to_parse + "\""
- << "and does not have 3 tokens";
- std::string msg;
- std::for_each(tokens.begin() + 2, tokens.end() - 1,
- [&msg](auto& token) { msg.append(token + ":"); });
- msg.append(*tokens.rbegin());
- return {tokens[0], tokens[1], msg};
-}
-
-// Use only this function to make a packet to send over the confirmation
-// ui packet layer
-template <typename... Args>
-static Payload ToPayload(const ConfUiCmd cmd, const std::string& session_id,
- Args&&... args) {
- std::string cmd_str = ToString(cmd);
- std::string msg =
- ArgsToString(session_id, ":", cmd_str, ":", std::forward<Args>(args)...);
- PayloadHeader header;
- header.payload_length_ = msg.size();
- return {header, msg};
-}
-
-template <typename... Args>
-static bool WritePayload(SharedFD d, const ConfUiCmd cmd,
- const std::string& session_id, Args&&... args) {
- if (!d->IsOpen()) {
- LOG(ERROR) << "file, socket, etc, is not open to write";
- return false;
- }
- auto [payload, msg] = ToPayload(cmd, session_id, std::forward<Args>(args)...);
-
- auto nwrite =
- WriteAll(d, reinterpret_cast<const char*>(&payload), sizeof(payload));
- if (nwrite != sizeof(payload)) {
- return false;
- }
- nwrite = cuttlefish::WriteAll(d, msg.c_str(), msg.size());
- if (nwrite != msg.size()) {
- return false;
- }
- return true;
-}
-
-static std::optional<ConfUiMessage> ReadPayload(SharedFD s) {
- if (!s->IsOpen()) {
- LOG(ERROR) << "file, socket, etc, is not open to read";
- return std::nullopt;
- }
- PayloadHeader p;
- auto nread = ReadExactBinary(s, &p);
-
- if (nread != sizeof(p)) {
- return std::nullopt;
- }
-
- if (p.payload_length_ == 0) {
- return {{SESSION_ANY, ToString(ConfUiCmd::kUnknown), std::string{""}}};
- }
-
- if (p.payload_length_ >= kMaxPayloadLength) {
- LOG(ERROR) << "Payload length must be less than " << kMaxPayloadLength;
- return std::nullopt;
- }
-
- std::unique_ptr<char[]> buf{new char[p.payload_length_ + 1]};
- nread = ReadExact(s, buf.get(), p.payload_length_);
- buf[p.payload_length_] = 0;
- if (nread != p.payload_length_) {
- return std::nullopt;
- }
- std::string msg_to_parse{buf.get()};
- auto [session_id, type, contents] = PayloadToConfUiMessage(msg_to_parse);
- return {{session_id, type, contents}};
-}
-
-std::optional<ConfUiMessage> RecvConfUiMsg(SharedFD fd) {
- return ReadPayload(fd);
-}
-
-bool SendCmd(SharedFD fd, const std::string& session_id, ConfUiCmd cmd,
- const std::string& additional_info) {
- return WritePayload(fd, cmd, session_id, additional_info);
-}
-
-bool SendAck(SharedFD fd, const std::string& session_id, const bool is_success,
- const std::string& additional_info) {
- return WritePayload(fd, ConfUiCmd::kCliAck, session_id,
- ToCliAckMessage(is_success, additional_info));
-}
-
-bool SendResponse(SharedFD fd, const std::string& session_id,
- const std::string& additional_info) {
- return WritePayload(fd, ConfUiCmd::kCliRespond, session_id, additional_info);
-}
-
-} // end of namespace packet
-} // end of namespace confui
-} // end of namespace cuttlefish
diff --git a/common/libs/confui/packet.h b/common/libs/confui/packet.h
deleted file mode 100644
index 848eb2910..000000000
--- a/common/libs/confui/packet.h
+++ /dev/null
@@ -1,71 +0,0 @@
-//
-// Copyright (C) 2021 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 <cstdint>
-#include <functional>
-#include <optional>
-#include <string>
-#include <tuple>
-
-#include "common/libs/confui/protocol.h"
-#include "common/libs/fs/shared_fd.h"
-
-namespace cuttlefish {
-namespace confui {
-namespace packet {
-/*
- * for communication between Confirmation UI guest and host.
- *
- * Payload is actually the header. When we send/recv, besides Payload,
- * the "payload_length_" bytes should be additionally sent/recv'ed.
- *
- * The payload is assumed to be a text (e.g. char[N])
- * The WritePayload will create the string. When read, however,
- * the receiver should parse it
- *
- * The format we use for confirmation UI is:
- * session_id:type:contents
- *
- * e.g. GooglePay10354:start:my confirmaton message
- */
-struct PayloadHeader {
- std::uint32_t payload_length_;
-};
-
-// PayloadHeader + the message actually being sent
-using Payload = std::tuple<PayloadHeader, std::string>;
-
-// msg will look like "334522:start:Hello I am Here!"
-// this function returns 334522, start, "Hello I am Here!"
-// if no session id is given, it is regarded as SESSION_ANY
-ConfUiMessage PayloadToConfUiMessage(const std::string& str_to_parse);
-
-std::optional<ConfUiMessage> RecvConfUiMsg(SharedFD fd);
-bool SendAck(SharedFD fd, const std::string& session_id, const bool is_success,
- const std::string& additional_info);
-bool SendResponse(SharedFD fd, const std::string& session_id,
- const std::string& additional_info);
-// for HAL
-bool SendCmd(SharedFD fd, const std::string& session_id, ConfUiCmd cmd,
- const std::string& additional_info);
-
-// this is for short messages
-constexpr const ssize_t kMaxPayloadLength = 1000;
-
-} // end of namespace packet
-} // end of namespace confui
-} // end of namespace cuttlefish
diff --git a/common/libs/confui/protocol.cpp b/common/libs/confui/protocol.cpp
deleted file mode 100644
index 67840345a..000000000
--- a/common/libs/confui/protocol.cpp
+++ /dev/null
@@ -1,102 +0,0 @@
-//
-// Copyright (C) 2021 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 "common/libs/confui/protocol.h"
-
-#include <map>
-#include <sstream>
-#include <unordered_map>
-#include <vector>
-
-#include <android-base/strings.h>
-
-#include "common/libs/confui/utils.h"
-
-namespace cuttlefish {
-namespace confui {
-std::string ToDebugString(const ConfUiCmd& cmd, const bool is_debug) {
- std::stringstream ss;
- ss << "of " << Enum2Base(cmd);
- std::string suffix = "";
- if (is_debug) {
- suffix.append(ss.str());
- }
- static std::unordered_map<ConfUiCmd, std::string> look_up_tab{
- {ConfUiCmd::kUnknown, "kUnknown"},
- {ConfUiCmd::kStart, "kStart"},
- {ConfUiCmd::kStop, "kStop"},
- {ConfUiCmd::kCliAck, "kCliAck"},
- {ConfUiCmd::kCliRespond, "kCliRespond"},
- {ConfUiCmd::kAbort, "kAbort"},
- {ConfUiCmd::kSuspend, "kSuspend"},
- {ConfUiCmd::kRestore, "kRestore"},
- {ConfUiCmd::kUserInputEvent, "kUserInputEvent"}};
- if (look_up_tab.find(cmd) != look_up_tab.end()) {
- return look_up_tab[cmd] + suffix;
- }
- return "kUnknown" + suffix;
-}
-
-std::string ToString(const ConfUiCmd& cmd) { return ToDebugString(cmd, false); }
-
-ConfUiCmd ToCmd(std::uint32_t i) {
- std::vector<ConfUiCmd> all_cmds{
- ConfUiCmd::kStart, ConfUiCmd::kStop, ConfUiCmd::kCliAck,
- ConfUiCmd::kCliRespond, ConfUiCmd::kAbort, ConfUiCmd::kSuspend,
- ConfUiCmd::kRestore, ConfUiCmd::kUserInputEvent, ConfUiCmd::kUnknown};
-
- for (auto& cmd : all_cmds) {
- if (i == Enum2Base(cmd)) {
- return cmd;
- }
- }
- return ConfUiCmd::kUnknown;
-}
-
-ConfUiCmd ToCmd(const std::string& cmd_str) {
- static std::map<std::string, ConfUiCmd> cmds = {
- {"kStart", ConfUiCmd::kStart},
- {"kStop", ConfUiCmd::kStop},
- {"kCliAck", ConfUiCmd::kCliAck},
- {"kCliRespond", ConfUiCmd::kCliRespond},
- {"kAbort", ConfUiCmd::kAbort},
- {"kSuspend", ConfUiCmd::kSuspend},
- {"kRestore", ConfUiCmd::kRestore},
- {"kUserInputEvent", ConfUiCmd::kUserInputEvent},
- };
- if (cmds.find(cmd_str) != cmds.end()) {
- return cmds[cmd_str];
- }
- return ConfUiCmd::kUnknown;
-}
-
-std::string ToCliAckMessage(const bool is_success, const std::string& message) {
- std::string header = "error:";
- if (is_success) {
- header = "success:";
- }
- return header + message;
-}
-
-std::string ToCliAckSuccessMsg(const std::string& message) {
- return ToCliAckMessage(true, message);
-}
-
-std::string ToCliAckErrorMsg(const std::string& message) {
- return ToCliAckMessage(false, message);
-}
-
-} // end of namespace confui
-} // end of namespace cuttlefish
diff --git a/common/libs/confui/protocol.h b/common/libs/confui/protocol.h
deleted file mode 100644
index 582b43ef6..000000000
--- a/common/libs/confui/protocol.h
+++ /dev/null
@@ -1,63 +0,0 @@
-//
-// Copyright (C) 2021 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 <cstdint>
-#include <string>
-
-namespace cuttlefish {
-namespace confui {
-// When you update this, please update all the utility functions
-// in conf.cpp: e.g. ToString, etc
-enum class ConfUiCmd : std::uint32_t {
- kUnknown = 100,
- kStart = 111, // start rendering, send confirmation msg, & wait respond
- kStop = 112, // start rendering, send confirmation msg, & wait respond
- kCliAck = 113, // client acknowledged. "error:err_msg" or "success:command"
- kCliRespond = 114, // with "confirm" or "cancel"
- kAbort = 115, // to abort the current session
- kSuspend = 116, // to suspend, so do save the context
- kRestore = 117,
- kUserInputEvent = 200
-};
-
-std::string ToString(const ConfUiCmd& cmd);
-std::string ToDebugString(const ConfUiCmd& cmd, const bool is_debug);
-ConfUiCmd ToCmd(const std::string& cmd_str);
-ConfUiCmd ToCmd(std::uint32_t i);
-
-struct UserResponse {
- using type = std::string;
- constexpr static const auto kConfirm = "user_confirm";
- constexpr static const auto kCancel = "user_cancel";
- constexpr static const auto kUnknown = "user_unknown";
-};
-
-// invalid/ignored session id
-constexpr char SESSION_ANY[] = "";
-
-std::string ToCliAckMessage(const bool is_success, const std::string& message);
-std::string ToCliAckErrorMsg(const std::string& message);
-std::string ToCliAckSuccessMsg(const std::string& message);
-
-struct ConfUiMessage {
- std::string session_id_;
- std::string type_; // cmd, which cmd? ack, response, etc
- std::string msg_;
-};
-
-} // end of namespace confui
-} // end of namespace cuttlefish
diff --git a/common/libs/confui/utils.h b/common/libs/confui/utils.h
deleted file mode 100644
index 2e4ac0432..000000000
--- a/common/libs/confui/utils.h
+++ /dev/null
@@ -1,54 +0,0 @@
-//
-// Copyright (C) 2021 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 <sstream>
-#include <string>
-#include <type_traits>
-#include <vector>
-
-#include <android-base/logging.h>
-
-namespace cuttlefish {
-template <typename T>
-constexpr typename std::underlying_type_t<T> Enum2Base(T t) {
- return static_cast<typename std::underlying_type_t<T>>(t);
-}
-} // end of namespace cuttlefish
-
-namespace cuttlefish {
-namespace confui {
-template <typename Delim, typename... Args>
-std::string ArgsToStringWithDelim(Delim&& delim, Args&&... args) {
- std::stringstream ss;
- ([&ss, &delim](auto& arg) { ss << arg << delim; }(args), ...);
- return ss.str();
-}
-
-// make t... to a single string with no blank in between
-template <typename... Args>
-std::string ArgsToString(Args&&... args) {
- return ArgsToStringWithDelim("", std::forward<Args>(args)...);
-}
-
-// note that no () surrounding LOG(level) << "ConfUI:" is crucial
-#define ConfUiLog(LOG_LEVEL) LOG(LOG_LEVEL) << "ConfUI: "
-
-// TODO(kwstephenkim@google.com): make these look more like LOG(level)
-#define ConfUiCheck(cond) CHECK(cond) << "ConfUI: "
-
-} // end of namespace confui
-} // end of namespace cuttlefish
diff --git a/common/libs/device_config/Android.bp b/common/libs/device_config/Android.bp
index 00a6a0a0d..7ce7395d1 100644
--- a/common/libs/device_config/Android.bp
+++ b/common/libs/device_config/Android.bp
@@ -13,46 +13,25 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-cc_library {
- name: "libcuttlefish_device_config_proto",
- proto: {
- export_proto_headers: true,
- type: "full",
- },
- srcs: [
- "device_config.proto",
- ],
- defaults: ["cuttlefish_host"],
-}
-
cc_library_shared {
name: "libcuttlefish_device_config",
srcs: [
"device_config.cpp",
- "device_config_shared.cpp",
],
shared_libs: [
"libbase",
"liblog",
- "libcuttlefish_device_config_proto",
"libcuttlefish_fs",
"libcuttlefish_utils",
- "libprotobuf-cpp-full",
],
target: {
host: {
srcs: [
"host_device_config.cpp",
],
- shared_libs: [
- "libjsoncpp",
- ],
static_libs: [
"libcuttlefish_host_config",
+ "libjsoncpp",
],
},
android: {
@@ -64,6 +43,5 @@ cc_library_shared {
],
},
},
- export_include_dirs: ["."],
- defaults: ["cuttlefish_host"],
+ defaults: ["cuttlefish_host_and_guest"],
}
diff --git a/common/libs/device_config/device_config.cpp b/common/libs/device_config/device_config.cpp
index 0bbe903e3..c13f869d1 100644
--- a/common/libs/device_config/device_config.cpp
+++ b/common/libs/device_config/device_config.cpp
@@ -21,16 +21,41 @@
#include <android-base/logging.h>
-#include "common/libs/fs/shared_fd_stream.h"
-
-namespace cuttlefish {
-
-bool DeviceConfigHelper::SendDeviceConfig(SharedFD fd) {
- SharedFDOstream stream(fd);
- return device_config_.SerializeToOstream(&stream);
+namespace cvd {
+
+// TODO(jemoreira): Endianness when on arm64 guest and x86 host is a problem
+// Raw data is sent through a vsocket from host to guest, this assert tries to
+// ensure the binary representation of the struct is the same in both sides.
+static constexpr int kRawDataSize = 68 + 16; // ril + screen
+static_assert(sizeof(DeviceConfig::RawData) == kRawDataSize &&
+ std::is_trivial<DeviceConfig::RawData>().value,
+ "DeviceConfigRawData needs to be the same in host and guess, did "
+ "you forget to update the size?");
+
+namespace {
+
+static constexpr auto kDataSize = sizeof(DeviceConfig::RawData);
+
+} // namespace
+
+bool DeviceConfig::SendRawData(cvd::SharedFD fd) {
+ std::size_t sent = 0;
+ auto buffer = reinterpret_cast<uint8_t*>(&data_);
+ while (sent < kDataSize) {
+ auto bytes = fd->Write(buffer + sent, kDataSize - sent);
+ if (bytes < 0) {
+ // Don't log here, let the caller do it.
+ return false;
+ }
+ sent += bytes;
+ }
+ return true;
}
-DeviceConfigHelper::DeviceConfigHelper(const DeviceConfig& device_config)
- : device_config_(device_config) {}
+void DeviceConfig::generate_address_and_prefix() {
+ std::ostringstream ss;
+ ss << ril_ipaddr() << "/" << ril_prefixlen();
+ ril_address_and_prefix_ = ss.str();
+}
-} // namespace cuttlefish
+} // namespace cvd \ No newline at end of file
diff --git a/common/libs/device_config/device_config.h b/common/libs/device_config/device_config.h
index 7655e49e1..0e3680fe6 100644
--- a/common/libs/device_config/device_config.h
+++ b/common/libs/device_config/device_config.h
@@ -16,31 +16,74 @@
#pragma once
+#include <common/libs/fs/shared_fd.h>
+#include <stdint.h>
+
#include <memory>
#include <string>
#include <vector>
-#include "common/libs/fs/shared_fd.h"
-#include "device/google/cuttlefish/common/libs/device_config/device_config.pb.h"
-
#ifdef CUTTLEFISH_HOST
-#include "host/libs/config/cuttlefish_config.h"
+#include <host/libs/config/cuttlefish_config.h>
#endif
-namespace cuttlefish {
+namespace cvd {
-class DeviceConfigHelper {
+class DeviceConfig {
public:
- static std::unique_ptr<DeviceConfigHelper> Get();
+ /**
+ * WARNING: Consider the possibility of different endianness between host and
+ * guest when adding fields of more than one byte to this struct:
+ * This struct is meant to be sent from host to guest so the binary
+ * representation must be the same. There is a static test that checks for
+ * alignment problems, but there is no such thing for endianness.
+ */
+ struct RawData {
+ struct {
+ char ipaddr[16]; // xxx.xxx.xxx.xxx\0 = 16 bytes
+ char gateway[16];
+ char dns[16];
+ char broadcast[16];
+ uint8_t prefixlen;
+ uint8_t reserved[3];
+ } ril;
+ struct {
+ int32_t x_res;
+ int32_t y_res;
+ int32_t dpi;
+ int32_t refresh_rate;
+ } screen;
+ };
+
+ static std::unique_ptr<DeviceConfig> Get();
- const DeviceConfig& GetDeviceConfig() const { return device_config_; }
+ bool SendRawData(cvd::SharedFD fd);
- bool SendDeviceConfig(SharedFD fd);
+ const char* ril_address_and_prefix() const {
+ return ril_address_and_prefix_.c_str();
+ };
+ const char* ril_ipaddr() const { return data_.ril.ipaddr; }
+ const char* ril_gateway() const { return data_.ril.gateway; }
+ const char* ril_dns() const { return data_.ril.dns; }
+ const char* ril_broadcast() const { return data_.ril.broadcast; }
+ int ril_prefixlen() const { return data_.ril.prefixlen; }
+ int32_t screen_x_res() { return data_.screen.x_res; }
+ int32_t screen_y_res() { return data_.screen.y_res; }
+ int32_t screen_dpi() { return data_.screen.dpi; }
+ int32_t screen_refresh_rate() { return data_.screen.refresh_rate; }
private:
- explicit DeviceConfigHelper(const DeviceConfig& device_config);
+ void generate_address_and_prefix();
+#ifdef CUTTLEFISH_HOST
+ DeviceConfig() = default;
+ bool InitializeNetworkConfiguration(const vsoc::CuttlefishConfig& config);
+ void InitializeScreenConfiguration(const vsoc::CuttlefishConfig& config);
+#else
+ explicit DeviceConfig(const RawData& data);
+#endif
- DeviceConfig device_config_;
+ RawData data_;
+ std::string ril_address_and_prefix_;
};
-} // namespace cuttlefish
+} // namespace cvd
diff --git a/common/libs/device_config/device_config.proto b/common/libs/device_config/device_config.proto
deleted file mode 100644
index 4a5a17016..000000000
--- a/common/libs/device_config/device_config.proto
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2020 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.
- */
-
-syntax = "proto3";
-
-package cuttlefish;
-
-message DeviceConfig {
-
- message RILConfig {
- string ipaddr = 1;
- string gateway = 2;
- string dns = 3;
- string broadcast = 4;
- int32 prefixlen = 5;
- };
-
- RILConfig ril_config = 1;
-
- message DisplayConfig {
- int32 width = 1;
- int32 height = 2;
- int32 dpi = 3;
- int32 refresh_rate_hz = 4;
- };
-
- repeated DisplayConfig display_config = 2;
-}
diff --git a/common/libs/device_config/device_config_shared.h b/common/libs/device_config/device_config_shared.h
deleted file mode 100644
index 3176917df..000000000
--- a/common/libs/device_config/device_config_shared.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2021 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 "device/google/cuttlefish/common/libs/device_config/device_config.pb.h"
-
-namespace cuttlefish {
-
-// Minimal version to share with Goldfish which doesn't include additional
-// Cuttlefish headers.
-//
-// TODO(natsu): switch ranchu hwcomposer to drm for display discovery.
-DeviceConfig GetDeviceConfig();
-
-} // namespace cuttlefish \ No newline at end of file
diff --git a/common/libs/device_config/guest_device_config.cpp b/common/libs/device_config/guest_device_config.cpp
index 662074875..0be87be64 100644
--- a/common/libs/device_config/guest_device_config.cpp
+++ b/common/libs/device_config/guest_device_config.cpp
@@ -19,19 +19,18 @@
#include <chrono>
#include <thread>
-#include <android-base/logging.h>
#include <cutils/properties.h>
+#include <android-base/logging.h>
-#include "common/libs/fs/shared_fd_stream.h"
-
-namespace cuttlefish {
+namespace cvd {
namespace {
+static constexpr auto kDataSize = sizeof(DeviceConfig::RawData);
static constexpr int kRetries = 5;
static constexpr int kRetryDelaySeconds = 5;
-bool GetRawFromServer(DeviceConfig* data) {
+bool GetRawFromServer(DeviceConfig::RawData* data) {
auto port_property = "ro.boot.cuttlefish_config_server_port";
auto port = property_get_int64(port_property, -1);
if (port < 0) {
@@ -40,32 +39,41 @@ bool GetRawFromServer(DeviceConfig* data) {
return false;
}
auto config_server =
- SharedFD::VsockClient(2 /*host cid*/,
- static_cast<unsigned int>(port), SOCK_STREAM);
+ cvd::SharedFD::VsockClient(2 /*host cid*/,
+ static_cast<unsigned int>(port), SOCK_STREAM);
if (!config_server->IsOpen()) {
LOG(ERROR) << "Unable to connect to config server: "
<< config_server->StrError();
return false;
}
-
- SharedFDIstream stream(config_server);
- if (!data->ParseFromIstream(&stream)) {
- LOG(ERROR) << "Error reading from config server: "
- << config_server->StrError();
+ uint8_t* buffer = reinterpret_cast<uint8_t*>(data);
+ size_t read_idx = 0;
+ while (read_idx < kDataSize) {
+ auto read = config_server->Read(buffer + read_idx, kDataSize - read_idx);
+ if (read == 0) {
+ LOG(ERROR) << "Unexpected EOF while reading from config server, read "
+ << read_idx << " bytes, expected " << kDataSize;
+ return false;
+ }
+ if (read < 0) {
+ LOG(ERROR) << "Error reading from config server: "
+ << config_server->StrError();
+ return false;
+ }
+ read_idx += read;
}
return true;
}
} // namespace
-std::unique_ptr<DeviceConfigHelper> DeviceConfigHelper::Get() {
- DeviceConfig device_config;
+std::unique_ptr<DeviceConfig> DeviceConfig::Get() {
+ DeviceConfig::RawData data;
int attempts_remaining = 1 + kRetries;
while (attempts_remaining > 0) {
- if (GetRawFromServer(&device_config)) {
- return std::unique_ptr<DeviceConfigHelper>(
- new DeviceConfigHelper(device_config));
+ if (GetRawFromServer(&data)) {
+ return std::unique_ptr<DeviceConfig>(new DeviceConfig(data));
}
std::this_thread::sleep_for(std::chrono::seconds(kRetryDelaySeconds));
@@ -75,4 +83,8 @@ std::unique_ptr<DeviceConfigHelper> DeviceConfigHelper::Get() {
return nullptr;
}
-} // namespace cuttlefish
+DeviceConfig::DeviceConfig(const DeviceConfig::RawData& data) : data_(data) {
+ generate_address_and_prefix();
+}
+
+} // namespace cvd
diff --git a/common/libs/device_config/host_device_config.cpp b/common/libs/device_config/host_device_config.cpp
index 35ec27ff1..65f82f6af 100644
--- a/common/libs/device_config/host_device_config.cpp
+++ b/common/libs/device_config/host_device_config.cpp
@@ -23,7 +23,7 @@
#include "device_config.h"
-namespace cuttlefish {
+namespace cvd {
namespace {
@@ -41,19 +41,18 @@ class NetConfig {
uint8_t ril_prefixlen = -1;
std::string ril_ipaddr;
std::string ril_gateway;
- std::string ril_dns;
+ std::string ril_dns = "8.8.8.8";
std::string ril_broadcast;
- bool ObtainConfig(const std::string& interface, const std::string& dns) {
+ bool ObtainConfig(const std::string& interface) {
bool ret = ParseInterfaceAttributes(interface);
if (ret) {
- ril_dns = dns;
- LOG(DEBUG) << "Network config:";
- LOG(DEBUG) << "ipaddr = " << ril_ipaddr;
- LOG(DEBUG) << "gateway = " << ril_gateway;
- LOG(DEBUG) << "dns = " << ril_dns;
- LOG(DEBUG) << "broadcast = " << ril_broadcast;
- LOG(DEBUG) << "prefix length = " << static_cast<int>(ril_prefixlen);
+ LOG(INFO) << "Network config:";
+ LOG(INFO) << "ipaddr = " << ril_ipaddr;
+ LOG(INFO) << "gateway = " << ril_gateway;
+ LOG(INFO) << "dns = " << ril_dns;
+ LOG(INFO) << "broadcast = " << ril_broadcast;
+ LOG(INFO) << "prefix length = " << static_cast<int>(ril_prefixlen);
}
return ret;
}
@@ -128,62 +127,66 @@ class NetConfig {
}
};
-bool InitializeNetworkConfiguration(const CuttlefishConfig& cuttlefish_config,
- DeviceConfig* device_config) {
- auto instance = cuttlefish_config.ForDefaultInstance();
+inline void CopyChars(char* dest, size_t size, const char* src) {
+ auto res = snprintf(dest, size, "%s", src);
+ if (res >= static_cast<int>(size)) {
+ LOG(ERROR) << "Longer(" << res << ") than expected(" << (size - 1)
+ << ") config string was truncated: " << dest;
+ }
+}
+
+} // namespace
+
+std::unique_ptr<DeviceConfig> DeviceConfig::Get() {
+ auto config = vsoc::CuttlefishConfig::Get();
+ if (!config) return nullptr;
+ std::unique_ptr<DeviceConfig> dev_config(new DeviceConfig());
+ if (!dev_config->InitializeNetworkConfiguration(*config)) {
+ return nullptr;
+ }
+ dev_config->InitializeScreenConfiguration(*config);
+ return dev_config;
+}
+
+bool DeviceConfig::InitializeNetworkConfiguration(
+ const vsoc::CuttlefishConfig& config) {
+ auto instance = config.ForDefaultInstance();
NetConfig netconfig;
// Check the mobile bridge first; this was the traditional way we configured
// the mobile interface. If that fails, it probably means we are using a
// newer version of cuttlefish-common, and we can use the tap device
// directly instead.
- if (!netconfig.ObtainConfig(instance.mobile_bridge_name(),
- cuttlefish_config.ril_dns())) {
- if (!netconfig.ObtainConfig(instance.mobile_tap_name(),
- cuttlefish_config.ril_dns())) {
+ if (!netconfig.ObtainConfig(instance.mobile_bridge_name())) {
+ if (!netconfig.ObtainConfig(instance.mobile_tap_name())) {
LOG(ERROR) << "Unable to obtain the network configuration";
return false;
}
}
- DeviceConfig::RILConfig* ril_config = device_config->mutable_ril_config();
- ril_config->set_ipaddr(netconfig.ril_ipaddr);
- ril_config->set_gateway(netconfig.ril_gateway);
- ril_config->set_dns(netconfig.ril_dns);
- ril_config->set_broadcast(netconfig.ril_broadcast);
- ril_config->set_prefixlen(netconfig.ril_prefixlen);
-
- return true;
-}
-
-void InitializeScreenConfiguration(const CuttlefishConfig& cuttlefish_config,
- DeviceConfig* device_config) {
- for (const auto& cuttlefish_display_config : cuttlefish_config.display_configs()) {
- DeviceConfig::DisplayConfig* device_display_config =
- device_config->add_display_config();
-
- device_display_config->set_width(cuttlefish_display_config.width);
- device_display_config->set_height(cuttlefish_display_config.height);
- device_display_config->set_dpi(cuttlefish_config.dpi());
- device_display_config->set_refresh_rate_hz(cuttlefish_config.refresh_rate_hz());
+ auto res = snprintf(data_.ril.ipaddr, sizeof(data_.ril.ipaddr), "%s",
+ netconfig.ril_ipaddr.c_str());
+ if (res >= (int)sizeof(data_.ril.ipaddr)) {
+ LOG(ERROR) << "Longer than expected config string was truncated: "
+ << data_.ril.ipaddr;
}
-}
+ CopyChars(data_.ril.gateway, sizeof(data_.ril.gateway),
+ netconfig.ril_gateway.c_str());
+ CopyChars(data_.ril.dns, sizeof(data_.ril.dns), netconfig.ril_dns.c_str());
+ CopyChars(data_.ril.broadcast, sizeof(data_.ril.broadcast),
+ netconfig.ril_broadcast.c_str());
+ data_.ril.prefixlen = netconfig.ril_prefixlen;
-} // namespace
+ generate_address_and_prefix();
-std::unique_ptr<DeviceConfigHelper> DeviceConfigHelper::Get() {
- auto cuttlefish_config = CuttlefishConfig::Get();
- if (!cuttlefish_config) {
- return nullptr;
- }
-
- DeviceConfig device_config;
- if (!InitializeNetworkConfiguration(*cuttlefish_config, &device_config)) {
- return nullptr;
- }
- InitializeScreenConfiguration(*cuttlefish_config, &device_config);
+ return true;
+}
- return std::unique_ptr<DeviceConfigHelper>(
- new DeviceConfigHelper(device_config));
+void DeviceConfig::InitializeScreenConfiguration(
+ const vsoc::CuttlefishConfig& config) {
+ data_.screen.x_res = config.x_res();
+ data_.screen.y_res = config.y_res();
+ data_.screen.dpi = config.dpi();
+ data_.screen.refresh_rate = config.refresh_rate_hz();
}
-} // namespace cuttlefish
+} // namespace cvd
diff --git a/common/libs/fs/Android.bp b/common/libs/fs/Android.bp
index c140e0de7..88189dc74 100644
--- a/common/libs/fs/Android.bp
+++ b/common/libs/fs/Android.bp
@@ -13,16 +13,11 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
cc_library {
name: "libcuttlefish_fs",
srcs: [
"shared_buf.cc",
"shared_fd.cpp",
- "shared_fd_stream.cpp",
],
shared: {
shared_libs: [
@@ -43,7 +38,7 @@ cc_library {
exclude_static_libs: ["liblog"],
},
},
- defaults: ["cuttlefish_host"],
+ defaults: ["cuttlefish_host_and_guest"],
}
cc_library_static {
@@ -51,7 +46,6 @@ cc_library_static {
srcs: [
"shared_buf.cc",
"shared_fd.cpp",
- "shared_fd_stream.cpp",
],
shared_libs: [
"libbase",
@@ -61,7 +55,7 @@ cc_library_static {
defaults: ["cuttlefish_guest_product_only"],
}
-cc_test {
+cc_test_host {
name: "libcuttlefish_fs_tests",
srcs: [
"shared_fd_test.cpp",
@@ -72,8 +66,8 @@ cc_test {
],
static_libs: [
"libgmock",
- "libgtest",
+ "libgtest_host",
],
- defaults: ["cuttlefish_host"],
+ defaults: ["cuttlefish_host_only"],
test_suites: ["general-tests"],
}
diff --git a/common/libs/fs/TEST_MAPPING b/common/libs/fs/TEST_MAPPING
new file mode 100644
index 000000000..162fcf6b4
--- /dev/null
+++ b/common/libs/fs/TEST_MAPPING
@@ -0,0 +1,8 @@
+{
+ "presubmit": [
+ {
+ "name": "libcuttlefish_fs_tests",
+ "host": true
+ }
+ ]
+}
diff --git a/common/libs/fs/shared_buf.cc b/common/libs/fs/shared_buf.cc
index 61ff51ef4..5ae1aa2f9 100644
--- a/common/libs/fs/shared_buf.cc
+++ b/common/libs/fs/shared_buf.cc
@@ -22,14 +22,14 @@
#include "common/libs/fs/shared_buf.h"
#include "common/libs/fs/shared_fd.h"
-namespace cuttlefish {
-
namespace {
const size_t BUFF_SIZE = 1 << 14;
} // namespace
+namespace cvd {
+
ssize_t WriteAll(SharedFD fd, const char* buf, size_t size) {
size_t total_written = 0;
ssize_t written = 0;
@@ -94,36 +94,4 @@ ssize_t WriteAll(SharedFD fd, const std::vector<char>& buf) {
return WriteAll(fd, buf.data(), buf.size());
}
-bool SendAll(SharedFD sock, const std::string& msg) {
- ssize_t total_written{};
- if (!sock->IsOpen()) {
- return false;
- }
- while (total_written < static_cast<ssize_t>(msg.size())) {
- auto just_written = sock->Send(msg.c_str() + total_written,
- msg.size() - total_written, MSG_NOSIGNAL);
- if (just_written <= 0) {
- return false;
- }
- total_written += just_written;
- }
- return true;
-}
-
-std::string RecvAll(SharedFD sock, const size_t count) {
- size_t total_read{};
- if (!sock->IsOpen()) {
- return {};
- }
- std::unique_ptr<char[]> data(new char[count]);
- while (total_read < count) {
- auto just_read = sock->Read(data.get() + total_read, count - total_read);
- if (just_read <= 0) {
- return {};
- }
- total_read += just_read;
- }
- return {data.get(), count};
-}
-
-} // namespace cuttlefish
+} // namespace cvd
diff --git a/common/libs/fs/shared_buf.h b/common/libs/fs/shared_buf.h
index eb63174af..f8f86b700 100644
--- a/common/libs/fs/shared_buf.h
+++ b/common/libs/fs/shared_buf.h
@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-#pragma once
#include <string>
#include <thread>
@@ -21,7 +20,7 @@
#include "common/libs/fs/shared_fd.h"
-namespace cuttlefish {
+namespace cvd {
/**
* Reads from fd until it is closed or errors, storing all data in buf.
@@ -119,23 +118,4 @@ ssize_t WriteAllBinary(SharedFD fd, const T* binary_data) {
return WriteAll(fd, (const char*) binary_data, sizeof(*binary_data));
}
-/**
- * Sends contents of msg through sock, checking for socket error conditions
- *
- * On successful Send, returns true
- *
- * If a Send error is encountered, returns false. Some data may have already
- * been written to 'sock' at that point.
- */
-bool SendAll(SharedFD sock, const std::string& msg);
-
-/**
- * Receives 'count' bytes from sock, checking for socket error conditions
- *
- * On successful Recv, returns a string containing the received data
- *
- * If a Recv error is encountered, returns the empty string
- */
-std::string RecvAll(SharedFD sock, const size_t count);
-
-} // namespace cuttlefish
+} // namespace cvd
diff --git a/common/libs/fs/shared_fd.cpp b/common/libs/fs/shared_fd.cpp
index 8b21f0c71..0386dd99e 100644
--- a/common/libs/fs/shared_fd.cpp
+++ b/common/libs/fs/shared_fd.cpp
@@ -32,9 +32,8 @@
// #define ENABLE_GCE_SHARED_FD_LOGGING 1
-namespace cuttlefish {
-
namespace {
+using cvd::SharedFDSet;
void MarkAll(const SharedFDSet& input, fd_set* dest, int* max_index) {
for (SharedFDSet::const_iterator it = input.begin(); it != input.end();
@@ -85,6 +84,8 @@ int memfd_create_wrapper(const char* name, unsigned int flags) {
} // namespace
+namespace cvd {
+
bool FileInstance::CopyFrom(FileInstance& in, size_t length) {
std::vector<char> buffer(8192);
while (length > 0) {
@@ -122,52 +123,6 @@ void FileInstance::Close() {
fd_ = -1;
}
-int FileInstance::ConnectWithTimeout(const struct sockaddr* addr,
- socklen_t addrlen,
- struct timeval* timeout) {
- int original_flags = Fcntl(F_GETFL, 0);
- if (original_flags == -1) {
- LOG(ERROR) << "Could not get current file descriptor flags: " << StrError();
- return -1;
- }
- if (Fcntl(F_SETFL, original_flags | O_NONBLOCK) == -1) {
- LOG(ERROR) << "Failed to set O_NONBLOCK: " << StrError();
- return -1;
- }
- Connect(addr, addrlen); // This will return immediately because of O_NONBLOCK
-
- fd_set fdset;
- FD_ZERO(&fdset);
- FD_SET(fd_, &fdset);
-
- int select_res = select(fd_ + 1, nullptr, &fdset, nullptr, timeout);
-
- if (Fcntl(F_SETFL, original_flags) == -1) {
- LOG(ERROR) << "Failed to restore original flags: " << StrError();
- return -1;
- }
-
- if (select_res != 1) {
- LOG(ERROR) << "Did not connect within the timeout";
- return -1;
- }
-
- int so_error;
- socklen_t len = sizeof(so_error);
- if (GetSockOpt(SOL_SOCKET, SO_ERROR, &so_error, &len) == -1) {
- LOG(ERROR) << "Failed to get socket options: " << StrError();
- return -1;
- }
-
- if (so_error != 0) {
- LOG(ERROR) << "Failure in opening socket: " << so_error;
- errno_ = so_error;
- return -1;
- }
- errno_ = 0;
- return 0;
-}
-
bool FileInstance::IsSet(fd_set* in) const {
if (IsOpen() && FD_ISSET(fd_, in)) {
return true;
@@ -319,26 +274,12 @@ SharedFD SharedFD::Socket(int domain, int socket_type, int protocol) {
}
}
-SharedFD SharedFD::Mkstemp(std::string* path) {
- int fd = mkstemp(path->data());
- if (fd == -1) {
- return SharedFD(std::shared_ptr<FileInstance>(new FileInstance(fd, errno)));
- } else {
- return SharedFD(std::shared_ptr<FileInstance>(new FileInstance(fd, 0)));
- }
-}
-
SharedFD SharedFD::ErrorFD(int error) {
return SharedFD(std::shared_ptr<FileInstance>(new FileInstance(-1, error)));
}
SharedFD SharedFD::SocketLocalClient(const std::string& name, bool abstract,
int in_type) {
- return SocketLocalClient(name, abstract, in_type, 0);
-}
-
-SharedFD SharedFD::SocketLocalClient(const std::string& name, bool abstract,
- int in_type, int timeout_seconds) {
struct sockaddr_un addr;
socklen_t addrlen;
MakeAddress(name.c_str(), abstract, &addr, &addrlen);
@@ -346,9 +287,7 @@ SharedFD SharedFD::SocketLocalClient(const std::string& name, bool abstract,
if (!rval->IsOpen()) {
return rval;
}
- struct timeval timeout = {timeout_seconds, 0};
- auto casted_addr = reinterpret_cast<sockaddr*>(&addr);
- if (rval->ConnectWithTimeout(casted_addr, addrlen, &timeout) == -1) {
+ if (rval->Connect(reinterpret_cast<sockaddr*>(&addr), addrlen) == -1) {
return SharedFD::ErrorFD(rval->GetErrno());
}
return rval;
@@ -358,7 +297,7 @@ SharedFD SharedFD::SocketLocalClient(int port, int type) {
sockaddr_in addr{};
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
- addr.sin_addr.s_addr = htonl(INADDR_ANY);
+ addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
SharedFD rval = SharedFD::Socket(AF_INET, type, 0);
if (!rval->IsOpen()) {
return rval;
@@ -375,7 +314,7 @@ SharedFD SharedFD::SocketLocalServer(int port, int type) {
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
- addr.sin_addr.s_addr = htonl(INADDR_ANY);
+ addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
SharedFD rval = SharedFD::Socket(AF_INET, type, 0);
if(!rval->IsOpen()) {
return rval;
@@ -389,7 +328,7 @@ SharedFD SharedFD::SocketLocalServer(int port, int type) {
LOG(ERROR) << "Bind failed " << rval->StrError();
return SharedFD::ErrorFD(rval->GetErrno());
}
- if (type == SOCK_STREAM || type == SOCK_SEQPACKET) {
+ if (type == SOCK_STREAM) {
if (rval->Listen(4) < 0) {
LOG(ERROR) << "Listen failed " << rval->StrError();
return SharedFD::ErrorFD(rval->GetErrno());
@@ -424,10 +363,9 @@ SharedFD SharedFD::SocketLocalServer(const std::string& name, bool abstract,
/* Only the bottom bits are really the socket type; there are flags too. */
constexpr int SOCK_TYPE_MASK = 0xf;
- auto socket_type = in_type & SOCK_TYPE_MASK;
// Connection oriented sockets: start listening.
- if (socket_type == SOCK_STREAM || socket_type == SOCK_SEQPACKET) {
+ if ((in_type & SOCK_TYPE_MASK) == SOCK_STREAM) {
// Follows the default from socket_local_server
if (rval->Listen(1) == -1) {
LOG(ERROR) << "Listen failed: " << rval->StrError();
@@ -445,7 +383,7 @@ SharedFD SharedFD::SocketLocalServer(const std::string& name, bool abstract,
}
SharedFD SharedFD::VsockServer(unsigned int port, int type) {
- auto vsock = SharedFD::Socket(AF_VSOCK, type, 0);
+ auto vsock = cvd::SharedFD::Socket(AF_VSOCK, type, 0);
if (!vsock->IsOpen()) {
return vsock;
}
@@ -458,7 +396,7 @@ SharedFD SharedFD::VsockServer(unsigned int port, int type) {
LOG(ERROR) << "Bind failed (" << vsock->StrError() << ")";
return SharedFD::ErrorFD(vsock->GetErrno());
}
- if (type == SOCK_STREAM || type == SOCK_SEQPACKET) {
+ if (type == SOCK_STREAM) {
if (vsock->Listen(4) < 0) {
LOG(ERROR) << "Listen failed (" << vsock->StrError() << ")";
return SharedFD::ErrorFD(vsock->GetErrno());
@@ -472,7 +410,7 @@ SharedFD SharedFD::VsockServer(int type) {
}
SharedFD SharedFD::VsockClient(unsigned int cid, unsigned int port, int type) {
- auto vsock = SharedFD::Socket(AF_VSOCK, type, 0);
+ auto vsock = cvd::SharedFD::Socket(AF_VSOCK, type, 0);
if (!vsock->IsOpen()) {
return vsock;
}
@@ -487,28 +425,4 @@ SharedFD SharedFD::VsockClient(unsigned int cid, unsigned int port, int type) {
return vsock;
}
-SharedFD WeakFD::lock() const {
- auto locked_file_instance = value_.lock();
- if (locked_file_instance) {
- return SharedFD(locked_file_instance);
- }
- return SharedFD();
-}
-
-ScopedMMap::ScopedMMap(void* ptr, size_t len) : ptr_(ptr), len_(len) {}
-
-ScopedMMap::ScopedMMap() : ptr_(MAP_FAILED), len_(0) {}
-
-ScopedMMap::ScopedMMap(ScopedMMap&& other)
- : ptr_(other.ptr_), len_(other.len_) {
- other.ptr_ = MAP_FAILED;
- other.len_ = 0;
-}
-
-ScopedMMap::~ScopedMMap() {
- if (ptr_ != MAP_FAILED) {
- munmap(ptr_, len_);
- }
-}
-
-} // namespace cuttlefish
+} // namespace cvd
diff --git a/common/libs/fs/shared_fd.h b/common/libs/fs/shared_fd.h
index e712ab9e6..7bcac6a7b 100644
--- a/common/libs/fs/shared_fd.h
+++ b/common/libs/fs/shared_fd.h
@@ -38,11 +38,8 @@
#include <errno.h>
#include <fcntl.h>
#include <string.h>
-#include <termios.h>
#include <unistd.h>
-#include <android-base/cmsg.h>
-
#include "vm_sockets.h"
/**
@@ -64,7 +61,7 @@
* it makes it easier to convert existing code to SharedFDs and avoids the
* possibility that new POSIX functionality will lead to large refactorings.
*/
-namespace cuttlefish {
+namespace cvd {
class FileInstance;
@@ -112,8 +109,6 @@ class FileInstance;
* reported with a new, closed FileInstance with the errno set.
*/
class SharedFD {
- // Give WeakFD access to the underlying shared_ptr.
- friend class WeakFD;
public:
inline SharedFD();
SharedFD(const std::shared_ptr<FileInstance>& in) : value_(in) {}
@@ -129,14 +124,11 @@ class SharedFD {
static bool Pipe(SharedFD* fd0, SharedFD* fd1);
static SharedFD Event(int initval = 0, int flags = 0);
static SharedFD MemfdCreate(const std::string& name, unsigned int flags = 0);
- static SharedFD Mkstemp(std::string* path);
static bool SocketPair(int domain, int type, int protocol, SharedFD* fd0,
SharedFD* fd1);
static SharedFD Socket(int domain, int socket_type, int protocol);
static SharedFD SocketLocalClient(const std::string& name, bool is_abstract,
int in_type);
- static SharedFD SocketLocalClient(const std::string& name, bool is_abstract,
- int in_type, int timeout_seconds);
static SharedFD SocketLocalClient(int port, int type);
static SharedFD SocketLocalServer(const std::string& name, bool is_abstract,
int in_type, mode_t mode);
@@ -159,9 +151,9 @@ class SharedFD {
std::shared_ptr<FileInstance> operator->() const { return value_; }
- const FileInstance& operator*() const { return *value_; }
+ const cvd::FileInstance& operator*() const { return *value_; }
- FileInstance& operator*() { return *value_; }
+ cvd::FileInstance& operator*() { return *value_; }
private:
static SharedFD ErrorFD(int error);
@@ -170,47 +162,6 @@ class SharedFD {
};
/**
- * A non-owning reference to a FileInstance. The referenced FileInstance needs
- * to be managed by a SharedFD. A WeakFD needs to be converted to a SharedFD to
- * access the underlying FileInstance.
- */
-class WeakFD {
- public:
- WeakFD(SharedFD shared_fd) : value_(shared_fd.value_) {}
-
- // Creates a new SharedFD object that shares ownership of the underlying fd.
- // Callers need to check that the returned SharedFD is open before using it.
- SharedFD lock() const;
-
- private:
- std::weak_ptr<FileInstance> value_;
-};
-
-// Provides RAII semantics for memory mappings, preventing memory leaks. It does
-// not however prevent use-after-free errors since the underlying pointer can be
-// extracted and could survive this object.
-class ScopedMMap {
- public:
- ScopedMMap();
- ScopedMMap(void* ptr, size_t size);
- ScopedMMap(const ScopedMMap& other) = delete;
- ScopedMMap& operator=(const ScopedMMap& other) = delete;
- ScopedMMap(ScopedMMap&& other);
-
- ~ScopedMMap();
-
- void* get() { return ptr_; }
- const void* get() const { return ptr_; }
- size_t len() const { return len_; }
-
- operator bool() const { return ptr_ != MAP_FAILED; }
-
- private:
- void* ptr_ = MAP_FAILED;
- size_t len_;
-};
-
-/**
* Tracks the lifetime of a file descriptor and provides methods to allow
* callers to use the file without knowledge of the underlying descriptor
* number.
@@ -249,9 +200,6 @@ class FileInstance {
return rval;
}
- int ConnectWithTimeout(const struct sockaddr* addr, socklen_t addrlen,
- struct timeval* timeout);
-
void Close();
// Returns true if the entire input was copied.
@@ -367,13 +315,6 @@ class FileInstance {
return rval;
}
- int EventfdRead(eventfd_t* value) {
- errno = 0;
- auto rval = eventfd_read(fd_, value);
- errno_ = errno;
- return rval;
- }
-
ssize_t Send(const void* buf, size_t len, int flags) {
errno = 0;
ssize_t rval = TEMP_FAILURE_RETRY(send(fd_, buf, len, flags));
@@ -388,16 +329,6 @@ class FileInstance {
return rval;
}
- template <typename... Args>
- ssize_t SendFileDescriptors(const void* buf, size_t len, Args&&... sent_fds) {
- std::vector<int> fds;
- android::base::Append(fds, std::forward<int>(sent_fds->fd_)...);
- errno = 0;
- auto ret = android::base::SendFileDescriptorVector(fd_, buf, len, fds);
- errno_ = errno;
- return ret;
- }
-
int Shutdown(int how) {
errno = 0;
int rval = shutdown(fd_, how);
@@ -414,27 +345,6 @@ class FileInstance {
return rval;
}
- int GetSockOpt(int level, int optname, void* optval, socklen_t* optlen) {
- errno = 0;
- int rval = getsockopt(fd_, level, optname, optval, optlen);
- errno_ = errno;
- return rval;
- }
-
- int SetTerminalRaw() {
- errno = 0;
- termios terminal_settings;
- int rval = tcgetattr(fd_, &terminal_settings);
- errno_ = errno;
- if (rval < 0) {
- return rval;
- }
- cfmakeraw(&terminal_settings);
- rval = tcsetattr(fd_, TCSANOW, &terminal_settings);
- errno_ = errno;
- return rval;
- }
-
const char* StrError() const {
errno = 0;
FileInstance* s = const_cast<FileInstance*>(this);
@@ -451,14 +361,6 @@ class FileInstance {
return strerror_buf_;
}
- ScopedMMap MMap(void* addr, size_t length, int prot, int flags,
- off_t offset) {
- errno = 0;
- auto ptr = mmap(addr, length, prot, flags, fd_, offset);
- errno_ = errno;
- return ScopedMMap(ptr, length);
- }
-
ssize_t Truncate(off_t length) {
errno = 0;
ssize_t rval = TEMP_FAILURE_RETRY(ftruncate(fd_, length));
@@ -473,20 +375,6 @@ class FileInstance {
return rval;
}
- int EventfdWrite(eventfd_t value) {
- errno = 0;
- int rval = eventfd_write(fd_, value);
- errno_ = errno;
- return rval;
- }
-
- bool IsATTY() {
- errno = 0;
- int rval = isatty(fd_);
- errno_ = errno;
- return rval;
- }
-
private:
FileInstance(int fd, int in_errno) : fd_(fd), errno_(in_errno) {
// Ensure every file descriptor managed by a FileInstance has the CLOEXEC
@@ -517,6 +405,6 @@ class FileInstance {
inline SharedFD::SharedFD() : value_(FileInstance::ClosedInstance()) {}
-} // namespace cuttlefish
+} // namespace cvd
#endif // CUTTLEFISH_COMMON_COMMON_LIBS_FS_SHARED_FD_H_
diff --git a/common/libs/fs/shared_fd_stream.cpp b/common/libs/fs/shared_fd_stream.cpp
deleted file mode 100644
index 6eef1f55e..000000000
--- a/common/libs/fs/shared_fd_stream.cpp
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2020 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 "common/libs/fs/shared_fd_stream.h"
-
-#include <cstdio>
-#include <streambuf>
-
-#include "common/libs/fs/shared_buf.h"
-
-namespace cuttlefish {
-
-SharedFDStreambuf::SharedFDStreambuf(SharedFD shared_fd)
- : shared_fd_(shared_fd) {}
-
-int SharedFDStreambuf::underflow() {
- if (gptr() < egptr()) {
- return *gptr();
- }
-
- size_t unget_size = 0;
- constexpr size_t bytes_to_read = kBufferSize - kUngetSize;
- if (read_buffer_ == nullptr) {
- read_buffer_ = std::make_unique<char[]>(kBufferSize);
- } else {
- unget_size = std::min(gptr() - eback(), kUngetSize);
- std::memcpy(read_buffer_.get(),
- read_buffer_.get() + kBufferSize - unget_size,
- unget_size);
- }
-
- ssize_t bytes_read = ReadExact(shared_fd_,
- read_buffer_.get() + unget_size,
- bytes_to_read);
-
- setg(read_buffer_.get(),
- read_buffer_.get() + unget_size,
- read_buffer_.get() + unget_size + bytes_read);
-
- if (bytes_read <= 0 || in_avail() == 0) {
- return EOF;
- }
-
- return static_cast<int>(*gptr());
-}
-
-std::streamsize SharedFDStreambuf::xsgetn(char* dst, std::streamsize count) {
- std::streamsize bytes_read = 0;
- while (bytes_read < count) {
- if (in_avail() == 0) {
- if (underflow() == EOF) {
- break;
- }
- }
- std::streamsize buffer_count =
- std::min(static_cast<std::streamsize>(in_avail()), count - bytes_read);
- std::memcpy(dst + bytes_read, gptr(), buffer_count);
- gbump(buffer_count);
- bytes_read += buffer_count;
- }
- return bytes_read;
-}
-
-int SharedFDStreambuf::overflow(int c) {
- if (c != EOF) {
- char z = c;
- if (WriteAll(shared_fd_, &z, 1) != 1) {
- return EOF;
- }
- }
- return c;
-}
-
-std::streamsize SharedFDStreambuf::xsputn(const char* src,
- std::streamsize count) {
- return static_cast<std::streamsize>(
- WriteAll(shared_fd_, src, static_cast<std::size_t>(count)));
-}
-
-int SharedFDStreambuf::pbackfail(int c) {
- if (c != EOF) {
- if (gptr() != eback()) {
- gbump(-1);
- *(gptr()) = c;
- return c;
- }
- }
- return EOF;
-}
-
-SharedFDOstream::SharedFDOstream(SharedFD shared_fd)
- : std::ostream(nullptr), buf_(shared_fd) { rdbuf(&buf_); }
-
-SharedFDIstream::SharedFDIstream(SharedFD shared_fd)
- : std::istream(nullptr), buf_(shared_fd) { rdbuf(&buf_); }
-
-} // namespace cuttlefish \ No newline at end of file
diff --git a/common/libs/fs/shared_fd_stream.h b/common/libs/fs/shared_fd_stream.h
deleted file mode 100644
index d5381d03d..000000000
--- a/common/libs/fs/shared_fd_stream.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2020 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.
- */
-
-// Adapters for using SharedFD as std::istream and std::ostream.
-
-#ifndef CUTTLEFISH_COMMON_COMMON_LIBS_FS_SHARED_FD_STREAM_H_
-#define CUTTLEFISH_COMMON_COMMON_LIBS_FS_SHARED_FD_STREAM_H_
-
-#include <cstdio>
-#include <istream>
-#include <memory>
-#include <ostream>
-#include <streambuf>
-
-#include "common/libs/fs/shared_fd.h"
-
-namespace cuttlefish {
-
-class SharedFDStreambuf : public std::streambuf {
- public:
- SharedFDStreambuf(SharedFD shared_fd);
-
- private:
- // Reading characters from the SharedFD.
- int underflow() override;
- std::streamsize xsgetn(char* dest, std::streamsize count) override;
-
- // Write characters to the SharedFD.
- int overflow(int c) override;
- std::streamsize xsputn(const char* source, std::streamsize count) override;
-
- int pbackfail(int c) override;
-
- private:
- SharedFD shared_fd_;
-
- static constexpr const ptrdiff_t kUngetSize = 128;
- static constexpr const ptrdiff_t kBufferSize = 4096 + kUngetSize;
- std::unique_ptr<char[]> read_buffer_ = nullptr;
-};
-
-class SharedFDIstream : public std::istream {
- public:
- SharedFDIstream(SharedFD shared_fd);
-
- private:
- SharedFDStreambuf buf_;
-};
-
-class SharedFDOstream : public std::ostream {
- public:
- SharedFDOstream(SharedFD shared_fd);
-
- private:
- SharedFDStreambuf buf_;
-};
-
-} // namespace cuttlefish
-
-#endif \ No newline at end of file
diff --git a/common/libs/fs/shared_fd_test.cpp b/common/libs/fs/shared_fd_test.cpp
index ff4365463..7ca620420 100644
--- a/common/libs/fs/shared_fd_test.cpp
+++ b/common/libs/fs/shared_fd_test.cpp
@@ -23,7 +23,7 @@
#include <string>
-namespace cuttlefish {
+using cvd::SharedFD;
char pipe_message[] = "Testing the pipe";
@@ -37,5 +37,3 @@ TEST(SendFD, Basic) {
EXPECT_EQ(sizeof(pipe_message), fds[0]->Read(buf, sizeof(buf)));
EXPECT_EQ(0, strcmp(buf, pipe_message));
}
-
-}
diff --git a/common/libs/fs/shared_select.h b/common/libs/fs/shared_select.h
index 9e0e0abff..d103f1db5 100644
--- a/common/libs/fs/shared_select.h
+++ b/common/libs/fs/shared_select.h
@@ -20,7 +20,7 @@
#include "common/libs/fs/shared_fd.h"
-namespace cuttlefish {
+namespace cvd {
/**
* The SharedFD version of fdset for the Select call.
*
@@ -76,6 +76,6 @@ class SharedFDSet {
int Select(SharedFDSet* read_set, SharedFDSet* write_set,
SharedFDSet* error_set, struct timeval* timeout);
-} // namespace cuttlefish
+} // namespace cvd
#endif // CUTTLEFISH_COMMON_COMMON_LIBS_FS_SHARED_SELECT_H_
diff --git a/common/libs/net/Android.bp b/common/libs/net/Android.bp
index 802141e53..8028c75ed 100644
--- a/common/libs/net/Android.bp
+++ b/common/libs/net/Android.bp
@@ -12,10 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
cc_library_shared {
name: "cuttlefish_net",
srcs: [
@@ -27,10 +23,10 @@ cc_library_shared {
"libcuttlefish_fs",
"libbase",
],
- defaults: ["cuttlefish_host"],
+ defaults: ["cuttlefish_host_and_guest"],
}
-cc_test {
+cc_test_host {
name: "cuttlefish_net_tests",
srcs: [
"netlink_request_test.cpp",
@@ -42,8 +38,8 @@ cc_test {
],
static_libs: [
"libgmock",
- "libgtest",
+ "libgtest_host",
],
- defaults: ["cuttlefish_host"],
+ defaults: ["cuttlefish_host_only"],
test_suites: ["general-tests"],
}
diff --git a/common/libs/net/TEST_MAPPING b/common/libs/net/TEST_MAPPING
new file mode 100644
index 000000000..a06d72a02
--- /dev/null
+++ b/common/libs/net/TEST_MAPPING
@@ -0,0 +1,8 @@
+{
+ "presubmit": [
+ {
+ "name": "cuttlefish_net_tests",
+ "host": true
+ }
+ ]
+}
diff --git a/common/libs/net/netlink_client.cpp b/common/libs/net/netlink_client.cpp
index 7b2404f48..624b1a723 100644
--- a/common/libs/net/netlink_client.cpp
+++ b/common/libs/net/netlink_client.cpp
@@ -24,7 +24,7 @@
#include "common/libs/fs/shared_fd.h"
#include "android-base/logging.h"
-namespace cuttlefish {
+namespace cvd {
namespace {
// NetlinkClient implementation.
// Talks to libnetlink to apply network changes.
@@ -165,4 +165,4 @@ NetlinkClientFactory* NetlinkClientFactory::Default() {
return &factory;
}
-} // namespace cuttlefish
+} // namespace cvd
diff --git a/common/libs/net/netlink_client.h b/common/libs/net/netlink_client.h
index 25ff7f454..c8805c5b7 100644
--- a/common/libs/net/netlink_client.h
+++ b/common/libs/net/netlink_client.h
@@ -21,7 +21,7 @@
#include <string>
#include "common/libs/net/netlink_request.h"
-namespace cuttlefish {
+namespace cvd {
// Abstraction of Netlink client class.
class NetlinkClient {
@@ -50,6 +50,6 @@ class NetlinkClientFactory {
virtual ~NetlinkClientFactory() = default;
};
-} // namespace cuttlefish
+} // namespace cvd
#endif // COMMON_LIBS_NET_NETLINK_CLIENT_H_
diff --git a/common/libs/net/netlink_request.cpp b/common/libs/net/netlink_request.cpp
index 3900e8ad3..bc7c1cfec 100644
--- a/common/libs/net/netlink_request.cpp
+++ b/common/libs/net/netlink_request.cpp
@@ -26,7 +26,7 @@
#include "android-base/logging.h"
-namespace cuttlefish {
+namespace cvd {
namespace {
uint32_t kRequestSequenceNumber = 0;
} // namespace
@@ -126,4 +126,4 @@ size_t NetlinkRequest::RequestLength() const {
return request_.size();
}
-} // namespace cuttlefish
+} // namespace cvd
diff --git a/common/libs/net/netlink_request.h b/common/libs/net/netlink_request.h
index eee231cab..541c04b20 100644
--- a/common/libs/net/netlink_request.h
+++ b/common/libs/net/netlink_request.h
@@ -24,7 +24,7 @@
#include <string>
#include <vector>
-namespace cuttlefish {
+namespace cvd {
// Abstraction of Network link request.
// Used to supply kernel with information about which interface needs to be
// changed, and how.
@@ -108,5 +108,5 @@ class NetlinkRequest {
NetlinkRequest(const NetlinkRequest&) = delete;
NetlinkRequest& operator= (const NetlinkRequest&) = delete;
};
-} // namespace cuttlefish
+} // namespace cvd
#endif // COMMON_LIBS_NET_NETLINK_REQUEST_H_
diff --git a/common/libs/net/netlink_request_test.cpp b/common/libs/net/netlink_request_test.cpp
index 3e2335849..2410b0277 100644
--- a/common/libs/net/netlink_request_test.cpp
+++ b/common/libs/net/netlink_request_test.cpp
@@ -28,7 +28,7 @@ using ::testing::ElementsAreArray;
using ::testing::MatchResultListener;
using ::testing::Return;
-namespace cuttlefish {
+namespace cvd {
namespace {
extern "C" void klog_write(int /* level */, const char* /* format */, ...) {}
@@ -130,7 +130,7 @@ TEST(NetlinkClientTest, BasicStringNode) {
memcpy(&expected.text, kLongString, sizeof(kLongString));
- NetlinkRequest request(RTM_SETLINK, 0);
+ cvd::NetlinkRequest request(RTM_SETLINK, 0);
request.AddString(kDummyTag, kLongString);
EXPECT_THAT(request, RequestDataIs(&expected, sizeof(expected)));
}
@@ -146,7 +146,7 @@ TEST(NetlinkClientTest, BasicIntNode) {
const uint32_t attr_value = kValue;
} expected;
- NetlinkRequest request(RTM_SETLINK, 0);
+ cvd::NetlinkRequest request(RTM_SETLINK, 0);
request.AddInt(kDummyTag, kValue);
EXPECT_THAT(request, RequestDataIs(&expected, sizeof(expected)));
}
@@ -188,7 +188,7 @@ TEST(NetlinkClientTest, AllIntegerTypes) {
uint8_t attr_padding_u8[3] = {0, 0, 0};
} expected = {};
- NetlinkRequest request(RTM_SETLINK, 0);
+ cvd::NetlinkRequest request(RTM_SETLINK, 0);
request.AddInt<int64_t>(kDummyTag, kValue);
request.AddInt<int32_t>(kDummyTag + 1, kValue);
request.AddInt<int16_t>(kDummyTag + 2, kValue);
@@ -215,7 +215,7 @@ TEST(NetlinkClientTest, SingleList) {
const uint32_t attr_value = kValue;
} expected;
- NetlinkRequest request(RTM_SETLINK, 0);
+ cvd::NetlinkRequest request(RTM_SETLINK, 0);
request.PushList(kListTag);
request.AddInt(kDummyTag, kValue);
request.PopList();
@@ -240,7 +240,7 @@ TEST(NetlinkClientTest, NestedList) {
const uint32_t attr_value = kValue;
} expected;
- NetlinkRequest request(RTM_SETLINK, 0);
+ cvd::NetlinkRequest request(RTM_SETLINK, 0);
request.PushList(kList1Tag);
request.PushList(kList2Tag);
request.AddInt(kDummyTag, kValue);
@@ -272,7 +272,7 @@ TEST(NetlinkClientTest, ListSequence) {
const uint32_t attr2_value = kValue2;
} expected;
- NetlinkRequest request(RTM_SETLINK, 0);
+ cvd::NetlinkRequest request(RTM_SETLINK, 0);
request.PushList(kList1Tag);
request.AddInt(kDummy1Tag, kValue1);
request.PopList();
@@ -305,7 +305,7 @@ TEST(NetlinkClientTest, ComplexList) {
const uint32_t attr2_value = kValue2;
} expected;
- NetlinkRequest request(RTM_SETLINK, 0);
+ cvd::NetlinkRequest request(RTM_SETLINK, 0);
request.PushList(kList1Tag);
request.PushList(kList2Tag);
request.AddInt(kDummy1Tag, kValue1);
@@ -317,7 +317,7 @@ TEST(NetlinkClientTest, ComplexList) {
}
TEST(NetlinkClientTest, SimpleNetlinkCreateHeader) {
- NetlinkRequest request(RTM_NEWLINK, NLM_F_CREATE | NLM_F_EXCL);
+ cvd::NetlinkRequest request(RTM_NEWLINK, NLM_F_CREATE | NLM_F_EXCL);
constexpr char kValue[] = "random string";
request.AddString(0, kValue); // Have something to work with.
@@ -331,7 +331,7 @@ TEST(NetlinkClientTest, SimpleNetlinkCreateHeader) {
NLM_F_ACK | NLM_F_CREATE | NLM_F_EXCL | NLM_F_REQUEST,
base_seq));
- NetlinkRequest request2(RTM_NEWLINK, NLM_F_CREATE | NLM_F_EXCL);
+ cvd::NetlinkRequest request2(RTM_NEWLINK, NLM_F_CREATE | NLM_F_EXCL);
request2.AddString(0, kValue); // Have something to work with.
EXPECT_THAT(request2, RequestHeaderIs(
kMsgLength,
@@ -341,7 +341,7 @@ TEST(NetlinkClientTest, SimpleNetlinkCreateHeader) {
}
TEST(NetlinkClientTest, SimpleNetlinkUpdateHeader) {
- NetlinkRequest request(RTM_SETLINK, 0);
+ cvd::NetlinkRequest request(RTM_SETLINK, 0);
constexpr char kValue[] = "random string";
request.AddString(0, kValue); // Have something to work with.
@@ -352,10 +352,10 @@ TEST(NetlinkClientTest, SimpleNetlinkUpdateHeader) {
EXPECT_THAT(request, RequestHeaderIs(
kMsgLength, RTM_SETLINK, NLM_F_REQUEST | NLM_F_ACK, base_seq));
- NetlinkRequest request2(RTM_SETLINK, 0);
+ cvd::NetlinkRequest request2(RTM_SETLINK, 0);
request2.AddString(0, kValue); // Have something to work with.
EXPECT_THAT(request2, RequestHeaderIs(
kMsgLength, RTM_SETLINK, NLM_F_REQUEST | NLM_F_ACK, base_seq + 1));
}
-} // namespace cuttlefish
+} // namespace cvd
diff --git a/common/libs/net/network_interface.h b/common/libs/net/network_interface.h
index 323db5322..2f4430d11 100644
--- a/common/libs/net/network_interface.h
+++ b/common/libs/net/network_interface.h
@@ -18,7 +18,7 @@
#include <string>
-namespace cuttlefish {
+namespace cvd {
// Abstraction of network interfaces.
// This interface provides means to modify network interface parameters.
@@ -111,6 +111,6 @@ class NetworkInterface {
NetworkInterface& operator= (const NetworkInterface&);
};
-} // namespace cuttlefish
+} // namespace cvd
#endif // GUEST_GCE_NETWORK_NETWORK_INTERFACE_H_
diff --git a/common/libs/net/network_interface_manager.cpp b/common/libs/net/network_interface_manager.cpp
index 19371e6b7..b61ba3315 100644
--- a/common/libs/net/network_interface_manager.cpp
+++ b/common/libs/net/network_interface_manager.cpp
@@ -27,7 +27,7 @@
#include "android-base/logging.h"
#include "common/libs/net/network_interface.h"
-namespace cuttlefish {
+namespace cvd {
namespace {
NetlinkRequest BuildLinkRequest(
const NetworkInterface& interface) {
@@ -104,4 +104,4 @@ bool NetworkInterfaceManager::ApplyChanges(const NetworkInterface& iface) {
return nl_client_->Send(BuildAddrRequest(iface));
}
-} // namespace cuttlefish
+} // namespace cvd
diff --git a/common/libs/net/network_interface_manager.h b/common/libs/net/network_interface_manager.h
index 4ade909c5..f28b0ff14 100644
--- a/common/libs/net/network_interface_manager.h
+++ b/common/libs/net/network_interface_manager.h
@@ -22,7 +22,7 @@
#include "common/libs/net/netlink_client.h"
#include "common/libs/net/network_interface.h"
-namespace cuttlefish {
+namespace cvd {
// Network interface manager class.
// - Provides access for existing network interfaces,
@@ -67,6 +67,6 @@ class NetworkInterfaceManager {
NetworkInterfaceManager& operator= (const NetworkInterfaceManager&);
};
-} // namespace cuttlefish
+} // namespace cvd
#endif // COMMON_LIBS_NET_NETWORK_INTERFACE_MANAGER_H_
diff --git a/common/libs/security/Android.bp b/common/libs/security/Android.bp
deleted file mode 100644
index 4f2295161..000000000
--- a/common/libs/security/Android.bp
+++ /dev/null
@@ -1,61 +0,0 @@
-//
-// Copyright (C) 2020 The Android Open-Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-cc_library {
- name: "libcuttlefish_security",
- defaults: ["hidl_defaults", "cuttlefish_host"],
- srcs: [
- "gatekeeper_channel.cpp",
- "keymaster_channel.cpp",
- ],
- header_libs: [
- "libhardware_headers",
- ],
- shared_libs: [
- "libbase",
- "libcuttlefish_fs",
- "libgatekeeper",
- "libkeymaster_messages",
- "liblog",
- ],
-}
-
-cc_test {
- name: "libcuttlefish_security_tests",
- srcs: [
- "keymaster_channel_test.cpp",
- ],
- shared_libs: [
- "libbase",
- "libcuttlefish_fs",
- "libcuttlefish_security",
- "libgatekeeper",
- "libkeymaster_messages",
- "liblog",
- ],
- static_libs: [
- "libgmock",
- "libgtest",
- ],
- defaults: ["cuttlefish_buildhost_only"],
- test_suites: ["general-tests"],
- test_options: {
- unit_test: true,
- },
-}
diff --git a/common/libs/security/gatekeeper_channel.cpp b/common/libs/security/gatekeeper_channel.cpp
deleted file mode 100644
index 7038d6757..000000000
--- a/common/libs/security/gatekeeper_channel.cpp
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright 2020 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 "common/libs/security/gatekeeper_channel.h"
-
-#include <cstdlib>
-
-#include <android-base/logging.h>
-#include "keymaster/android_keymaster_utils.h"
-
-#include "common/libs/fs/shared_buf.h"
-
-namespace cuttlefish {
-
-ManagedGatekeeperMessage CreateGatekeeperMessage(
- uint32_t command, bool is_response, size_t payload_size) {
- auto memory = std::malloc(payload_size + sizeof(GatekeeperRawMessage));
- auto message = reinterpret_cast<GatekeeperRawMessage*>(memory);
- message->cmd = command;
- message->is_response = is_response;
- message->payload_size = payload_size;
- return ManagedGatekeeperMessage(message);
-}
-
-void GatekeeperCommandDestroyer::operator()(GatekeeperRawMessage* ptr) {
- {
- keymaster::Eraser(ptr, sizeof(GatekeeperRawMessage) + ptr->payload_size);
- }
- std::free(ptr);
-}
-
-GatekeeperChannel::GatekeeperChannel(SharedFD input, SharedFD output)
- : input_(input), output_(output) {
-}
-
-bool GatekeeperChannel::SendRequest(
- uint32_t command, const gatekeeper::GateKeeperMessage& message) {
- return SendMessage(command, false, message);
-}
-
-bool GatekeeperChannel::SendResponse(
- uint32_t command, const gatekeeper::GateKeeperMessage& message) {
- return SendMessage(command, true, message);
-}
-
-bool GatekeeperChannel::SendMessage(
- uint32_t command,
- bool is_response,
- const gatekeeper::GateKeeperMessage& message) {
- LOG(DEBUG) << "Sending message with id: " << command;
- auto payload_size = message.GetSerializedSize();
- auto to_send = CreateGatekeeperMessage(command, is_response, payload_size);
- message.Serialize(to_send->payload, to_send->payload + payload_size);
- auto write_size = payload_size + sizeof(GatekeeperRawMessage);
- auto to_send_bytes = reinterpret_cast<const char*>(to_send.get());
- auto written = WriteAll(output_, to_send_bytes, write_size);
- if (written == -1) {
- LOG(ERROR) << "Could not write Gatekeeper Message: " << output_->StrError();
- }
- return written == write_size;
-}
-
-ManagedGatekeeperMessage GatekeeperChannel::ReceiveMessage() {
- struct GatekeeperRawMessage message_header;
- auto read = ReadExactBinary(input_, &message_header);
- if (read != sizeof(GatekeeperRawMessage)) {
- LOG(ERROR) << "Expected " << sizeof(GatekeeperRawMessage) << ", received "
- << read;
- LOG(ERROR) << "Could not read Gatekeeper Message: " << input_->StrError();
- return {};
- }
- LOG(DEBUG) << "Received message with id: " << message_header.cmd;
- auto message = CreateGatekeeperMessage(message_header.cmd,
- message_header.is_response,
- message_header.payload_size);
- auto message_bytes = reinterpret_cast<char*>(message->payload);
- read = ReadExact(input_, message_bytes, message->payload_size);
- if (read != message->payload_size) {
- LOG(ERROR) << "Could not read Gatekeeper Message: " << input_->StrError();
- return {};
- }
- return message;
-}
-
-} // namespace cuttlefish
diff --git a/common/libs/security/gatekeeper_channel.h b/common/libs/security/gatekeeper_channel.h
deleted file mode 100644
index b4222e744..000000000
--- a/common/libs/security/gatekeeper_channel.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright 2020 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 "gatekeeper/gatekeeper_messages.h"
-
-#include "common/libs/fs/shared_fd.h"
-
-#include <memory>
-
-namespace gatekeeper {
-
-/**
- * GatekeeperRawMessage - Header and raw byte payload for a serialized
- * gatekeeper message.
- *
- * @cmd: the command, one of gatekeeper::ENROLL and gatekeeper::VERIFY.
- * @payload: start of the serialized command specific payload
- */
-struct GatekeeperRawMessage {
- uint32_t cmd : 31;
- bool is_response : 1;
- uint32_t payload_size;
- uint8_t payload[0];
-};
-
-} // namespace gatekeeper
-
-namespace cuttlefish {
-
-using gatekeeper::GatekeeperRawMessage;
-
-/**
- * A destroyer for GatekeeperRawMessage instances created with
- * CreateGatekeeperMessage. Wipes memory from the GatekeeperRawMessage instances.
- */
-class GatekeeperCommandDestroyer {
-public:
- void operator()(GatekeeperRawMessage* ptr);
-};
-
-/** An owning pointer for a GatekeeperRawMessage instance. */
-using ManagedGatekeeperMessage =
- std::unique_ptr<GatekeeperRawMessage, GatekeeperCommandDestroyer>;
-
-/**
- * Allocates memory for a GatekeeperRawMessage carrying a message of size
- * `payload_size`.
- */
-ManagedGatekeeperMessage CreateGatekeeperMessage(
- uint32_t command, bool is_response, size_t payload_size);
-
-/*
- * Interface for communication channels that synchronously communicate Gatekeeper
- * IPC/RPC calls. Sends messages over a file descriptor.
- */
-class GatekeeperChannel {
-public:
- GatekeeperChannel(SharedFD input, SharedFD output);
-
- bool SendRequest(uint32_t command,
- const gatekeeper::GateKeeperMessage& message);
- bool SendResponse(uint32_t command,
- const gatekeeper::GateKeeperMessage& message);
- ManagedGatekeeperMessage ReceiveMessage();
-private:
- SharedFD input_;
- SharedFD output_;
- bool SendMessage(uint32_t command, bool response,
- const gatekeeper::GateKeeperMessage& message);
-};
-
-} // namespace cuttlefish
diff --git a/common/libs/security/keymaster_channel.cpp b/common/libs/security/keymaster_channel.cpp
deleted file mode 100644
index 7b3ab8637..000000000
--- a/common/libs/security/keymaster_channel.cpp
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright 2020 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 "keymaster_channel.h"
-
-#include <android-base/logging.h>
-#include "keymaster/android_keymaster_utils.h"
-
-#include "common/libs/fs/shared_buf.h"
-
-namespace cuttlefish {
-
-ManagedKeymasterMessage CreateKeymasterMessage(
- AndroidKeymasterCommand command, bool is_response, size_t payload_size) {
- auto memory = new uint8_t[payload_size + sizeof(keymaster_message)];
- auto message = reinterpret_cast<keymaster_message*>(memory);
- message->cmd = command;
- message->is_response = is_response;
- message->payload_size = payload_size;
- return ManagedKeymasterMessage(message);
-}
-
-void KeymasterCommandDestroyer::operator()(keymaster_message* ptr) {
- {
- keymaster::Eraser(ptr, sizeof(keymaster_message) + ptr->payload_size);
- }
- delete reinterpret_cast<uint8_t*>(ptr);
-}
-
-KeymasterChannel::KeymasterChannel(SharedFD input, SharedFD output)
- : input_(input), output_(output) {
-}
-
-bool KeymasterChannel::SendRequest(
- AndroidKeymasterCommand command, const keymaster::Serializable& message) {
- return SendMessage(command, false, message);
-}
-
-bool KeymasterChannel::SendResponse(
- AndroidKeymasterCommand command, const keymaster::Serializable& message) {
- return SendMessage(command, true, message);
-}
-
-bool KeymasterChannel::SendMessage(
- AndroidKeymasterCommand command,
- bool is_response,
- const keymaster::Serializable& message) {
- auto payload_size = message.SerializedSize();
- LOG(VERBOSE) << "Sending message with id: " << command << " and size "
- << payload_size;
- auto to_send = CreateKeymasterMessage(command, is_response, payload_size);
- message.Serialize(to_send->payload, to_send->payload + payload_size);
- auto write_size = payload_size + sizeof(keymaster_message);
- auto to_send_bytes = reinterpret_cast<const char*>(to_send.get());
- auto written = WriteAll(output_, to_send_bytes, write_size);
- if (written != write_size) {
- LOG(ERROR) << "Could not write Keymaster Message: " << output_->StrError();
- }
- return written == write_size;
-}
-
-ManagedKeymasterMessage KeymasterChannel::ReceiveMessage() {
- struct keymaster_message message_header;
- auto read = ReadExactBinary(input_, &message_header);
- if (read != sizeof(keymaster_message)) {
- LOG(ERROR) << "Expected " << sizeof(keymaster_message) << ", received "
- << read;
- LOG(ERROR) << "Could not read Keymaster Message: " << input_->StrError();
- return {};
- }
- LOG(VERBOSE) << "Received message with id: " << message_header.cmd
- << " and size " << message_header.payload_size;
- auto message = CreateKeymasterMessage(message_header.cmd,
- message_header.is_response,
- message_header.payload_size);
- auto message_bytes = reinterpret_cast<char*>(message->payload);
- read = ReadExact(input_, message_bytes, message->payload_size);
- if (read != message->payload_size) {
- LOG(ERROR) << "Could not read Keymaster Message: " << input_->StrError();
- return {};
- }
- return message;
-}
-
-}
diff --git a/common/libs/security/keymaster_channel.h b/common/libs/security/keymaster_channel.h
deleted file mode 100644
index 49c3843a0..000000000
--- a/common/libs/security/keymaster_channel.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright 2020 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 "keymaster/android_keymaster_messages.h"
-#include "keymaster/serializable.h"
-
-#include "common/libs/fs/shared_fd.h"
-
-#include <memory>
-
-namespace keymaster {
-
-/**
- * keymaster_message - Serial header for communicating with KM server
- * @cmd: the command, one of AndroidKeymasterCommand.
- * @payload: start of the serialized command specific payload
- */
-struct keymaster_message {
- AndroidKeymasterCommand cmd : 31;
- bool is_response : 1;
- uint32_t payload_size;
- uint8_t payload[0];
-};
-
-} // namespace keymaster
-
-namespace cuttlefish {
-
-using keymaster::AndroidKeymasterCommand;
-using keymaster::keymaster_message;
-
-/**
- * A destroyer for keymaster_message instances created with
- * CreateKeymasterMessage. Wipes memory from the keymaster_message instances.
- */
-class KeymasterCommandDestroyer {
-public:
- void operator()(keymaster_message* ptr);
-};
-
-/** An owning pointer for a keymaster_message instance. */
-using ManagedKeymasterMessage =
- std::unique_ptr<keymaster_message, KeymasterCommandDestroyer>;
-
-/**
- * Allocates memory for a keymaster_message carrying a message of size
- * `payload_size`.
- */
-ManagedKeymasterMessage CreateKeymasterMessage(
- AndroidKeymasterCommand command, bool is_response, size_t payload_size);
-
-/*
- * Interface for communication channels that synchronously communicate Keymaster
- * IPC/RPC calls. Sends messages over a file descriptor.
- */
-class KeymasterChannel {
-public:
- KeymasterChannel(SharedFD input, SharedFD output);
-
- bool SendRequest(AndroidKeymasterCommand command,
- const keymaster::Serializable& message);
- bool SendResponse(AndroidKeymasterCommand command,
- const keymaster::Serializable& message);
- ManagedKeymasterMessage ReceiveMessage();
-private:
- SharedFD input_;
- SharedFD output_;
- bool SendMessage(AndroidKeymasterCommand command, bool response,
- const keymaster::Serializable& message);
-};
-
-} // namespace cuttlefish
diff --git a/common/libs/security/keymaster_channel_test.cpp b/common/libs/security/keymaster_channel_test.cpp
deleted file mode 100644
index aed5bed3f..000000000
--- a/common/libs/security/keymaster_channel_test.cpp
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2021 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 <stdlib.h>
-#include <unistd.h>
-
-#include <string>
-
-#include "common/libs/fs/shared_fd.h"
-#include "common/libs/security/keymaster_channel.h"
-#include "gtest/gtest.h"
-
-namespace cuttlefish {
-
-TEST(KeymasterChannel, SendAndReceiveRequest) {
- SharedFD read_fd;
- SharedFD write_fd;
- ASSERT_TRUE(SharedFD::Pipe(&read_fd, &write_fd)) << "Failed to create pipe";
-
- KeymasterChannel channel{read_fd, write_fd};
-
- char buffer[] = {1, 2, 3, 4, 5, 6};
- keymaster::Buffer request(buffer, sizeof(buffer));
-
- ASSERT_TRUE(channel.SendRequest(keymaster::GET_VERSION, request))
- << "Failed to send request";
- auto response = channel.ReceiveMessage();
- EXPECT_EQ(response->cmd, keymaster::GET_VERSION) << "Command mismatch";
- EXPECT_FALSE(response->is_response) << "Request/response mismatch";
-
- keymaster::Buffer read;
- const uint8_t* read_data = response->payload;
- EXPECT_TRUE(read.Deserialize(&read_data, read_data + response->payload_size))
- << "Failed to deserialize request";
- ASSERT_EQ(request.end() - request.begin(), read.end() - read.begin());
- ASSERT_EQ(request.buffer_size(), read.buffer_size());
- ASSERT_TRUE(std::equal(request.begin(), request.end(), read.begin()));
-}
-
-TEST(KeymasterChannel, SendAndReceiveResponse) {
- SharedFD read_fd;
- SharedFD write_fd;
- ASSERT_TRUE(SharedFD::Pipe(&read_fd, &write_fd)) << "Failed to create pipe";
-
- KeymasterChannel channel{read_fd, write_fd};
-
- char buffer[] = {1, 2, 3, 4, 5, 6};
- keymaster::Buffer request(buffer, sizeof(buffer));
-
- ASSERT_TRUE(channel.SendResponse(keymaster::GET_VERSION, request))
- << "Failed to send request";
- auto response = channel.ReceiveMessage();
- EXPECT_EQ(response->cmd, keymaster::GET_VERSION) << "Command mismatch";
- EXPECT_TRUE(response->is_response) << "Request/response mismatch";
-
- keymaster::Buffer read;
- const uint8_t* read_data = response->payload;
- EXPECT_TRUE(read.Deserialize(&read_data, read_data + response->payload_size))
- << "Failed to deserialize request";
- ASSERT_EQ(request.end() - request.begin(), read.end() - read.begin());
- ASSERT_EQ(request.buffer_size(), read.buffer_size());
- ASSERT_TRUE(std::equal(request.begin(), request.end(), read.begin()));
-}
-
-} // namespace cuttlefish
diff --git a/host/commands/powerwash_cvd/Android.bp b/common/libs/tcp_socket/Android.bp
index adaacb903..5b01bab15 100644
--- a/host/commands/powerwash_cvd/Android.bp
+++ b/common/libs/tcp_socket/Android.bp
@@ -13,25 +13,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-cc_binary {
- name: "powerwash_cvd",
+cc_library_shared {
+ name: "cuttlefish_tcp_socket",
srcs: [
- "powerwash_cvd.cc",
+ "tcp_socket.cpp",
],
shared_libs: [
"libbase",
"libcuttlefish_fs",
- "libcuttlefish_utils",
- "libjsoncpp",
- ],
- static_libs: [
- "libcuttlefish_host_config",
- "libcuttlefish_vm_manager",
- "libgflags",
+ "liblog",
],
- defaults: ["cuttlefish_host", "cuttlefish_libicuuc"],
+ defaults: ["cuttlefish_host_and_guest"],
}
diff --git a/common/libs/utils/tcp_socket.cpp b/common/libs/tcp_socket/tcp_socket.cpp
index 3b567254d..2775c290e 100644
--- a/common/libs/utils/tcp_socket.cpp
+++ b/common/libs/tcp_socket/tcp_socket.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "common/libs/utils/tcp_socket.h"
+#include "common/libs/tcp_socket/tcp_socket.h"
#include <netinet/in.h>
#include <sys/socket.h>
@@ -24,12 +24,13 @@
#include <android-base/logging.h>
-namespace cuttlefish {
+using cvd::ClientSocket;
+using cvd::ServerSocket;
ClientSocket::ClientSocket(int port)
: fd_(SharedFD::SocketLocalClient(port, SOCK_STREAM)) {}
-Message ClientSocket::RecvAny(std::size_t length) {
+cvd::Message ClientSocket::RecvAny(std::size_t length) {
Message buf(length);
auto read_count = fd_->Read(buf.data(), buf.size());
if (read_count < 0) {
@@ -44,7 +45,7 @@ bool ClientSocket::closed() const {
return other_side_closed_;
}
-Message ClientSocket::Recv(std::size_t length) {
+cvd::Message ClientSocket::Recv(std::size_t length) {
Message buf(length);
ssize_t total_read = 0;
while (total_read < static_cast<ssize_t>(length)) {
@@ -105,30 +106,28 @@ ClientSocket ServerSocket::Accept() {
return ClientSocket{client};
}
-void AppendInNetworkByteOrder(Message* msg, const std::uint8_t b) {
+void cvd::AppendInNetworkByteOrder(Message* msg, const std::uint8_t b) {
msg->push_back(b);
}
-void AppendInNetworkByteOrder(Message* msg, const std::uint16_t s) {
+void cvd::AppendInNetworkByteOrder(Message* msg, const std::uint16_t s) {
const std::uint16_t n = htons(s);
auto p = reinterpret_cast<const std::uint8_t*>(&n);
msg->insert(msg->end(), p, p + sizeof n);
}
-void AppendInNetworkByteOrder(Message* msg, const std::uint32_t w) {
+void cvd::AppendInNetworkByteOrder(Message* msg, const std::uint32_t w) {
const std::uint32_t n = htonl(w);
auto p = reinterpret_cast<const std::uint8_t*>(&n);
msg->insert(msg->end(), p, p + sizeof n);
}
-void AppendInNetworkByteOrder(Message* msg, const std::int32_t w) {
+void cvd::AppendInNetworkByteOrder(Message* msg, const std::int32_t w) {
std::uint32_t u{};
std::memcpy(&u, &w, sizeof u);
AppendInNetworkByteOrder(msg, u);
}
-void AppendInNetworkByteOrder(Message* msg, const std::string& str) {
+void cvd::AppendInNetworkByteOrder(Message* msg, const std::string& str) {
msg->insert(msg->end(), str.begin(), str.end());
}
-
-}
diff --git a/common/libs/utils/tcp_socket.h b/common/libs/tcp_socket/tcp_socket.h
index 292decd8c..e484f48a7 100644
--- a/common/libs/utils/tcp_socket.h
+++ b/common/libs/tcp_socket/tcp_socket.h
@@ -25,7 +25,7 @@
#include <mutex>
#include <vector>
-namespace cuttlefish {
+namespace cvd {
using Message = std::vector<std::uint8_t>;
class ServerSocket;
@@ -63,9 +63,9 @@ class ClientSocket {
private:
friend ServerSocket;
- explicit ClientSocket(SharedFD fd) : fd_(fd) {}
+ explicit ClientSocket(cvd::SharedFD fd) : fd_(fd) {}
- SharedFD fd_;
+ cvd::SharedFD fd_;
bool other_side_closed_{};
mutable std::mutex closed_lock_;
std::mutex send_lock_;
@@ -81,7 +81,7 @@ class ServerSocket {
ClientSocket Accept();
private:
- SharedFD fd_;
+ cvd::SharedFD fd_;
};
void AppendInNetworkByteOrder(Message* msg, const std::uint8_t b);
@@ -105,4 +105,4 @@ Message CreateMessage(Ts... vals) {
return m;
}
-} // namespace cuttlefish
+} // namespace cvd
diff --git a/common/libs/concurrency/thread_safe_queue.h b/common/libs/thread_safe_queue/thread_safe_queue.h
index 910529976..9970d31c2 100644
--- a/common/libs/concurrency/thread_safe_queue.h
+++ b/common/libs/thread_safe_queue/thread_safe_queue.h
@@ -16,13 +16,13 @@
* limitations under the License.
*/
+#include <mutex>
#include <condition_variable>
#include <deque>
-#include <iterator>
-#include <mutex>
#include <utility>
+#include <iterator>
-namespace cuttlefish {
+namespace cvd {
// Simple queue with Push and Pop capabilities.
// If the max_elements argument is passed to the constructor, and Push is called
// when the queue holds max_elements items, the max_elements_handler is called
@@ -72,16 +72,6 @@ class ThreadSafeQueue {
new_item_.notify_one();
}
- bool IsEmpty() {
- std::lock_guard<std::mutex> guard(m_);
- return items_.empty();
- }
-
- bool IsFull() {
- std::lock_guard<std::mutex> guard(m_);
- return items_.size() == max_elements_;
- }
-
private:
void DropItemsIfAtCapacity() {
if (max_elements_ && max_elements_ == items_.size()) {
@@ -95,4 +85,4 @@ class ThreadSafeQueue {
std::condition_variable new_item_;
QueueImpl items_;
};
-} // namespace cuttlefish
+} // namespace cvd
diff --git a/common/libs/threads/thread_annotations.h b/common/libs/threads/thread_annotations.h
new file mode 100644
index 000000000..3ba67e7ff
--- /dev/null
+++ b/common/libs/threads/thread_annotations.h
@@ -0,0 +1,79 @@
+#pragma once
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if defined(__SUPPORT_TS_ANNOTATION__) || defined(__clang__)
+#define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x))
+#else
+#define THREAD_ANNOTATION_ATTRIBUTE__(x) // no-op
+#endif
+
+#define CAPABILITY(x) \
+ THREAD_ANNOTATION_ATTRIBUTE__(capability(x))
+
+#define SCOPED_CAPABILITY \
+ THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable)
+
+#define GUARDED_BY(x) \
+ THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x))
+
+#define PT_GUARDED_BY(x) \
+ THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_by(x))
+
+#define ACQUIRED_BEFORE(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(acquired_before(__VA_ARGS__))
+
+#define ACQUIRED_AFTER(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(acquired_after(__VA_ARGS__))
+
+#define REQUIRES(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(requires_capability(__VA_ARGS__))
+
+#define REQUIRES_SHARED(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(requires_shared_capability(__VA_ARGS__))
+
+#define ACQUIRE(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(acquire_capability(__VA_ARGS__))
+
+#define ACQUIRE_SHARED(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(acquire_shared_capability(__VA_ARGS__))
+
+#define RELEASE(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(release_capability(__VA_ARGS__))
+
+#define RELEASE_SHARED(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(release_shared_capability(__VA_ARGS__))
+
+#define TRY_ACQUIRE(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_capability(__VA_ARGS__))
+
+#define TRY_ACQUIRE_SHARED(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_shared_capability(__VA_ARGS__))
+
+#define EXCLUDES(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(__VA_ARGS__))
+
+#define ASSERT_CAPABILITY(x) \
+ THREAD_ANNOTATION_ATTRIBUTE__(assert_capability(x))
+
+#define ASSERT_SHARED_CAPABILITY(x) \
+ THREAD_ANNOTATION_ATTRIBUTE__(assert_shared_capability(x))
+
+#define RETURN_CAPABILITY(x) \
+ THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x))
+
+#define NO_THREAD_SAFETY_ANALYSIS \
+ THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis)
diff --git a/recovery/Android.bp b/common/libs/time/Android.bp
index 0923d17cd..972958f2c 100644
--- a/recovery/Android.bp
+++ b/common/libs/time/Android.bp
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2020 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.
@@ -12,27 +12,23 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
-//
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
+cc_library_shared {
+ name: "cuttlefish_time",
+ srcs: [
+ "monotonic_time.cpp",
+ ],
+ defaults: ["cuttlefish_host_and_guest"],
}
-cc_library_static {
- name: "librecovery_ui_cuttlefish",
- owner: "google",
- cflags: [
- "-Wall",
- "-Wextra",
- "-Werror",
- "-pedantic",
- ],
+cc_test_host {
+ name: "monotonic_time_test",
srcs: [
- "recovery_ui.cpp",
+ "monotonic_time_test.cpp",
],
-
shared_libs: [
- "libbase",
- "librecovery_ui",
+ "cuttlefish_time",
],
+ defaults: ["cuttlefish_host_only"],
+ test_suites: ["general-tests"],
}
diff --git a/common/libs/time/TEST_MAPPING b/common/libs/time/TEST_MAPPING
new file mode 100644
index 000000000..4c95014fe
--- /dev/null
+++ b/common/libs/time/TEST_MAPPING
@@ -0,0 +1,8 @@
+{
+ "presubmit": [
+ {
+ "name": "monotonic_time_test",
+ "host": true
+ }
+ ]
+}
diff --git a/common/libs/device_config/device_config_shared.cpp b/common/libs/time/monotonic_time.cpp
index ac4f8b46f..1d7bbd86e 100644
--- a/common/libs/device_config/device_config_shared.cpp
+++ b/common/libs/time/monotonic_time.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,14 +13,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+#include "common/libs/time/monotonic_time.h"
-#include "device_config.h"
+namespace cvd {
+namespace time {
+MonotonicTimePointFactory* MonotonicTimePointFactory::GetInstance() {
+ static MonotonicTimePointFactory factory;
-namespace cuttlefish {
-
-DeviceConfig GetDeviceConfig() {
- const auto device_config_helper = cuttlefish::DeviceConfigHelper::Get();
- return device_config_helper->GetDeviceConfig();
+ return &factory;
}
-
-} // namespace cuttlefish \ No newline at end of file
+} // namespace time
+} // namespace cvd
diff --git a/common/libs/time/monotonic_time.h b/common/libs/time/monotonic_time.h
index 283900159..8f5de1321 100644
--- a/common/libs/time/monotonic_time.h
+++ b/common/libs/time/monotonic_time.h
@@ -18,7 +18,7 @@
#include <stdint.h>
#include <time.h>
-namespace cuttlefish {
+namespace cvd {
namespace time {
static const int64_t kNanosecondsPerSecond = 1000000000;
@@ -226,6 +226,17 @@ class MonotonicTimePoint {
struct timespec ts_;
};
+class MonotonicTimePointFactory {
+ public:
+ static MonotonicTimePointFactory* GetInstance();
+
+ virtual ~MonotonicTimePointFactory() { }
+
+ virtual void FetchCurrentTime(MonotonicTimePoint* dest) const {
+ *dest = MonotonicTimePoint::Now();
+ }
+};
+
class Seconds : public TimeDifference {
public:
explicit Seconds(const TimeDifference& difference) :
@@ -268,7 +279,7 @@ class Nanoseconds : public TimeDifference {
};
} // namespace time
-} // namespace cuttlefish
+} // namespace cvd
/**
* Legacy support for microseconds. Use MonotonicTimePoint in new code.
@@ -276,6 +287,6 @@ class Nanoseconds : public TimeDifference {
static const int64_t kSecsToUsecs = static_cast<int64_t>(1000) * 1000;
static inline int64_t get_monotonic_usecs() {
- return cuttlefish::time::Microseconds(
- cuttlefish::time::MonotonicTimePoint::Now().SinceEpoch()).count();
+ return cvd::time::Microseconds(
+ cvd::time::MonotonicTimePoint::Now().SinceEpoch()).count();
}
diff --git a/common/libs/time/monotonic_time_test.cpp b/common/libs/time/monotonic_time_test.cpp
new file mode 100644
index 000000000..b1c07c928
--- /dev/null
+++ b/common/libs/time/monotonic_time_test.cpp
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "common/libs/time/monotonic_time.h"
+
+#include <gtest/gtest.h>
+#include <algorithm>
+
+using cvd::time::TimeDifference;
+
+class MonotonicTimeTest : public ::testing::Test {
+ public:
+ MonotonicTimeTest() {}
+};
+
+TEST_F(MonotonicTimeTest, TimeDifferenceAdd1) {
+ TimeDifference td1(1, 10, 1);
+ TimeDifference td2(0, 100, 1);
+ EXPECT_EQ((td1+td2).count(), (1)*1000000000 + 110);
+}
+
+TEST_F(MonotonicTimeTest, TimeDifferenceAdd2) {
+ TimeDifference td1(10, 1000, 1);
+ TimeDifference td2(100, 10000, 1);
+ EXPECT_EQ((td1+td2).count(), (110L)*1000000000L + 11000L);
+}
+
+TEST_F(MonotonicTimeTest, TimeDifferenceAdd3) {
+ int64_t scale = 1000;
+ TimeDifference td1(10, 1000, scale);
+ TimeDifference td2(100, 10000, scale);
+ EXPECT_EQ((td1+td2).count(), ((110L)*1000000000L + 11000L)/scale);
+}
+
+TEST_F(MonotonicTimeTest, TimeDifferenceAdd4) {
+ int64_t scale = 1;
+ TimeDifference td1(-10, 1000, scale);
+ TimeDifference td2(100, 10000, scale);
+ EXPECT_EQ((td1+td2).count(), ((90L)*1000000000L + 11000L)/scale);
+}
+
+TEST_F(MonotonicTimeTest, TimeDifferenceAdd5) {
+ int64_t scale1 = 1, scale2 = 1000;
+ TimeDifference td1(-10, 1000, scale1);
+ TimeDifference td2(100, 10000, scale2);
+ EXPECT_EQ((td1+td2).count(), ((90L)*1000000000L + 11000L)/std::min(scale1, scale2));
+}
+
+TEST_F(MonotonicTimeTest, TimeDifferenceAdd6) {
+ int64_t scale1 = 1000, scale2 = 1000;
+ TimeDifference td1(0, 995, scale1);
+ TimeDifference td2(0, 10, scale2);
+ EXPECT_EQ((td1+td2).count(), (1005L)/std::min(scale1, scale2));
+}
+
+TEST_F(MonotonicTimeTest, TimeDifferenceSub1) {
+ int64_t scale = 1;
+ TimeDifference td1(10, 1000, scale);
+ TimeDifference td2(100, 10000, scale);
+ EXPECT_EQ((td2-td1).count(), ((90L)*1000000000L + 9000L)/scale);
+}
+
+TEST_F(MonotonicTimeTest, TimeDifferenceSub2) {
+ int64_t scale = 1;
+ TimeDifference td1(10, 1000, scale);
+ TimeDifference td2(100, 10000, scale);
+ EXPECT_EQ((td1-td2).count(), ((-91L)*1000000000L + 1000000000L - 9000L)/scale);
+}
+
+TEST_F(MonotonicTimeTest, TimeDifferenceSub3) {
+ int64_t scale1 = 1, scale2 = 1000;
+ TimeDifference td1(-10, 1000, scale1);
+ TimeDifference td2(100, 10000, scale2);
+ EXPECT_EQ((td1-td2).count(), ((-111L)*1000000000L + 1000000000L - 9000L)/std::min(scale1, scale2));
+}
+
+TEST_F(MonotonicTimeTest, TimeDifferenceSub4) {
+ int64_t scale1 = 1000, scale2 = 1000;
+ TimeDifference td1(0, 995, scale1);
+ TimeDifference td2(0, 10, scale2);
+ EXPECT_EQ((td1-td2).count(), (985L)/std::min(scale1, scale2));
+}
+
+TEST_F(MonotonicTimeTest, TimeDifferenceComp1) {
+ int64_t scale = 1;
+ TimeDifference td1(10, 10000, scale);
+ TimeDifference td2(100, 10, scale);
+ EXPECT_TRUE((td1 < td2));
+ EXPECT_FALSE(td2 < td1);
+}
+
+TEST_F(MonotonicTimeTest, TimeDifferenceComp2) {
+ int64_t scale = 1;
+ TimeDifference td1(100, 10000, scale);
+ TimeDifference td2(100, 10, scale);
+ EXPECT_TRUE((td2 < td1));
+ EXPECT_FALSE(td1 < td2);
+}
diff --git a/common/libs/usbforward/protocol.h b/common/libs/usbforward/protocol.h
new file mode 100644
index 000000000..c55c3b6f9
--- /dev/null
+++ b/common/libs/usbforward/protocol.h
@@ -0,0 +1,153 @@
+/*
+ * 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>
+
+namespace usb_forward {
+
+// Commands that can be executed over serial port.
+// Use magic value to avoid accidental interpretation of commonly seen numbers.
+enum Command : uint32_t {
+ // Get device list.
+ // Request format:
+ // - RequestHeader{}
+ // Response format:
+ // - ResponseHeader{}
+ // - int32_t(num_devices)
+ // - num_devices times:
+ // - DeviceInfo{}
+ // - DeviceInfo.num_interfaces times:
+ // - InterfaceInfo{}
+ CmdDeviceList = 0xcfad0001,
+
+ // Attach specified device.
+ // Request format:
+ // - RequestHeader{}
+ // - AttachRequestHeader{}
+ // Response format:
+ // - ResponseHeader{}
+ CmdAttach,
+
+ // Execute command on attached USB device.
+ // Request format:
+ // - RequestHeader{}
+ // - ControlTransfer{}
+ // - if transfer direction is host -> device
+ // - uint8_t[ControlTransfer.length] data
+ // Response format:
+ // - ResponseHeader{}
+ // - if transfer direction is device -> host
+ // - int32_t(actual length)
+ // - uint8_t[actual length] bytes
+ CmdControlTransfer,
+
+ // Execute transfer on attached USB device.
+ // Request format:
+ // - RequestHeader{}
+ // - DataTransfer{}
+ // - if transfer direction is host -> device
+ // - uint8_t[DataTransfer.length] data
+ // Response format:
+ // - ResponseHeader{}
+ // - if transfer direction is host -> device
+ // - int32_t(actual length)
+ // - int32_t[actual length] bytes
+ CmdDataTransfer,
+
+ // Heartbeat is used to detect whether device is alive.
+ // This is a trivial request/response mechanism.
+ // Response status indicates whether server is ready.
+ // Request format:
+ // - RequestHeader{}
+ // Response format:
+ // - ResponseHeader{}
+ CmdHeartbeat,
+};
+
+// Status represents command execution result, using USB/IP compatible values.
+enum Status : uint32_t {
+ // StatusSuccess indicates successful command execution.
+ StatusSuccess = 0,
+
+ // StatusFailure indicates error during command execution.
+ StatusFailure = 1
+};
+
+struct RequestHeader {
+ Command command;
+ uint32_t tag;
+};
+
+struct ResponseHeader {
+ Status status;
+ uint32_t tag;
+};
+
+// DeviceInfo describes individual USB device that was found attached to the
+// bus.
+struct DeviceInfo {
+ uint16_t vendor_id;
+ uint16_t product_id;
+ uint16_t dev_version;
+ uint8_t dev_class;
+ uint8_t dev_subclass;
+ uint8_t dev_protocol;
+ uint8_t bus_id;
+ uint8_t dev_id;
+ uint8_t speed;
+ uint8_t num_configurations;
+ uint8_t num_interfaces;
+ uint8_t cur_configuration;
+} __attribute__((packed));
+
+// InterfaceInfo describes individual interface attached to a USB device.
+struct InterfaceInfo {
+ uint8_t if_class;
+ uint8_t if_subclass;
+ uint8_t if_protocol;
+ uint8_t if_reserved;
+} __attribute__((packed));
+
+// AttachRequest specifies which device on which bus needs to be attached.
+struct AttachRequest {
+ uint8_t bus_id;
+ uint8_t dev_id;
+} __attribute__((packed));
+
+// ControlTransfer specifies target bus and device along with USB request.
+struct ControlTransfer {
+ uint8_t bus_id;
+ uint8_t dev_id;
+ uint8_t type;
+ uint8_t cmd;
+ uint16_t value;
+ uint16_t index;
+ uint16_t length;
+ uint32_t timeout;
+} __attribute__((packed));
+
+// DataTransfer is used to exchange data between host and device.
+struct DataTransfer {
+ uint8_t bus_id;
+ uint8_t dev_id;
+ uint8_t endpoint_id;
+ uint8_t is_host_to_device;
+ int32_t length;
+ uint32_t timeout;
+} __attribute__((packed));
+
+} // namespace usb_forward
diff --git a/common/libs/utils/Android.bp b/common/libs/utils/Android.bp
index f8ca5e242..3c7e51918 100644
--- a/common/libs/utils/Android.bp
+++ b/common/libs/utils/Android.bp
@@ -13,10 +13,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
cc_library {
name: "libcuttlefish_utils",
srcs: [
@@ -27,15 +23,12 @@ cc_library {
"files.cpp",
"users.cpp",
"network.cpp",
- "base64.cpp",
- "tcp_socket.cpp",
"tee_logging.cpp",
],
shared: {
shared_libs: [
"libbase",
"libcuttlefish_fs",
- "libcrypto",
],
},
static: {
@@ -43,9 +36,6 @@ cc_library {
"libbase",
"libcuttlefish_fs",
],
- shared_libs: [
- "libcrypto", // libcrypto_static is not accessible from all targets
- ],
},
- defaults: ["cuttlefish_host"],
+ defaults: ["cuttlefish_host_and_guest"],
}
diff --git a/common/libs/utils/archive.cpp b/common/libs/utils/archive.cpp
index 05fbf5f79..10ca95a5c 100644
--- a/common/libs/utils/archive.cpp
+++ b/common/libs/utils/archive.cpp
@@ -24,7 +24,7 @@
#include "common/libs/utils/subprocess.h"
-namespace cuttlefish {
+namespace cvd {
Archive::Archive(const std::string& file) : file(file) {
}
@@ -33,11 +33,11 @@ Archive::~Archive() {
}
std::vector<std::string> Archive::Contents() {
- Command bsdtar_cmd("/usr/bin/bsdtar");
+ cvd::Command bsdtar_cmd("/usr/bin/bsdtar");
bsdtar_cmd.AddParameter("-tf");
bsdtar_cmd.AddParameter(file);
std::string bsdtar_input, bsdtar_output;
- auto bsdtar_ret = RunWithManagedStdio(std::move(bsdtar_cmd), &bsdtar_input,
+ auto bsdtar_ret = cvd::RunWithManagedStdio(std::move(bsdtar_cmd), &bsdtar_input,
&bsdtar_output, nullptr);
if (bsdtar_ret != 0) {
LOG(ERROR) << "`bsdtar -tf \"" << file << "\"` returned " << bsdtar_ret;
@@ -53,7 +53,7 @@ bool Archive::ExtractAll(const std::string& target_directory) {
bool Archive::ExtractFiles(const std::vector<std::string>& to_extract,
const std::string& target_directory) {
- Command bsdtar_cmd("/usr/bin/bsdtar");
+ cvd::Command bsdtar_cmd("/usr/bin/bsdtar");
bsdtar_cmd.AddParameter("-x");
bsdtar_cmd.AddParameter("-v");
bsdtar_cmd.AddParameter("-C");
@@ -64,8 +64,8 @@ bool Archive::ExtractFiles(const std::vector<std::string>& to_extract,
for (const auto& extract : to_extract) {
bsdtar_cmd.AddParameter(extract);
}
- bsdtar_cmd.RedirectStdIO(Subprocess::StdIOChannel::kStdOut,
- Subprocess::StdIOChannel::kStdErr);
+ bsdtar_cmd.RedirectStdIO(cvd::Subprocess::StdIOChannel::kStdOut,
+ cvd::Subprocess::StdIOChannel::kStdErr);
auto bsdtar_ret = bsdtar_cmd.Start().Wait();
if (bsdtar_ret != 0) {
LOG(ERROR) << "bsdtar extraction on \"" << file << "\" returned " << bsdtar_ret;
@@ -74,7 +74,7 @@ bool Archive::ExtractFiles(const std::vector<std::string>& to_extract,
}
std::string Archive::ExtractToMemory(const std::string& path) {
- Command bsdtar_cmd("/usr/bin/bsdtar");
+ cvd::Command bsdtar_cmd("/usr/bin/bsdtar");
bsdtar_cmd.AddParameter("-xf");
bsdtar_cmd.AddParameter(file);
bsdtar_cmd.AddParameter("-O");
@@ -90,4 +90,4 @@ std::string Archive::ExtractToMemory(const std::string& path) {
return stdout;
}
-} // namespace cuttlefish
+} // namespace cvd
diff --git a/common/libs/utils/archive.h b/common/libs/utils/archive.h
index ea548f222..7563ca0d0 100644
--- a/common/libs/utils/archive.h
+++ b/common/libs/utils/archive.h
@@ -18,7 +18,7 @@
#include <string>
#include <vector>
-namespace cuttlefish {
+namespace cvd {
// Operations on archive files
class Archive {
@@ -34,4 +34,4 @@ public:
std::string ExtractToMemory(const std::string& path);
};
-} // namespace cuttlefish
+} // namespace cvd
diff --git a/common/libs/utils/base64.cpp b/common/libs/utils/base64.cpp
deleted file mode 100644
index 1aa09ce07..000000000
--- a/common/libs/utils/base64.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2020 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 "common/libs/utils/base64.h"
-
-#include <openssl/base64.h>
-
-namespace cuttlefish {
-
-bool EncodeBase64(const void *data, size_t size, std::string *out) {
- size_t enc_len = 0;
- auto len_res = EVP_EncodedLength(&enc_len, size);
- if (!len_res) {
- return false;
- }
- out->resize(enc_len);
- auto enc_res = EVP_EncodeBlock(reinterpret_cast<uint8_t *>(out->data()),
- reinterpret_cast<const uint8_t *>(data), size);
- if (enc_res < 0) {
- return false;
- }
- out->resize(enc_res); // Don't count the terminating \0 character
- return true;
-}
-
-bool DecodeBase64(const std::string &data, std::vector<uint8_t> *buffer) {
- size_t out_len;
- auto len_res = EVP_DecodedLength(&out_len, data.size());
- if (!len_res) {
- return false;
- }
- buffer->resize(out_len);
- return EVP_DecodeBase64(buffer->data(), &out_len, out_len,
- reinterpret_cast<const uint8_t *>(data.data()),
- data.size());
-}
-
-} // namespace cuttlefish
diff --git a/common/libs/utils/cf_endian.h b/common/libs/utils/cf_endian.h
deleted file mode 100644
index 6eb5dd192..000000000
--- a/common/libs/utils/cf_endian.h
+++ /dev/null
@@ -1,56 +0,0 @@
-//
-// Copyright (C) 2020 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 <android-base/endian.h>
-
-// The utilities in android-base/endian.h still require the use of regular int
-// types to store values with any endianness, which requires the user to
-// remember to manually do the required conversions, which is prone to errors.
-// The types introduced here allow handling these values safely.
-
-namespace cuttlefish {
-
-#define DECLARE_TYPE(new_type, base_type, to_new, to_base) \
- class new_type { \
- public: \
- new_type() = default; \
- explicit new_type(base_type val) : inner_(to_new(val)) {} \
- new_type(const new_type&) = default; \
- new_type& operator=(const new_type& other) = default; \
- volatile new_type& operator=(const new_type& other) volatile { \
- inner_ = other.inner_; \
- return *this; \
- } \
- base_type as_##base_type() const volatile { return to_base(inner_); } \
- \
- private: \
- base_type inner_; \
- }; \
- static_assert(sizeof(new_type) == sizeof(base_type))
-
-DECLARE_TYPE(Le16, uint16_t, htole16, le16toh);
-DECLARE_TYPE(Le32, uint32_t, htole32, le32toh);
-DECLARE_TYPE(Le64, uint64_t, htole64, le64toh);
-DECLARE_TYPE(Be16, uint16_t, htobe16, be16toh);
-DECLARE_TYPE(Be32, uint32_t, htobe32, be32toh);
-DECLARE_TYPE(Be64, uint64_t, htobe64, be64toh);
-
-#undef DECLARE_TYPE
-
-} // namespace cuttlefish \ No newline at end of file
diff --git a/common/libs/utils/environment.cpp b/common/libs/utils/environment.cpp
index ec2729091..e6cacd002 100644
--- a/common/libs/utils/environment.cpp
+++ b/common/libs/utils/environment.cpp
@@ -15,15 +15,12 @@
*/
#include "common/libs/utils/environment.h"
-#include "common/libs/utils/files.h"
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
-#include <android-base/logging.h>
-
-namespace cuttlefish {
+namespace cvd {
std::string StringFromEnv(const std::string& varname,
const std::string& defval) {
@@ -41,7 +38,7 @@ std::string StringFromEnv(const std::string& varname,
*
* @return arch string on success, "" on failure
*/
-std::string HostArchStr() {
+std::string HostArch() {
static std::string arch;
static bool cached = false;
@@ -51,7 +48,7 @@ std::string HostArchStr() {
cached = true;
// good to check if uname exists and is executable
- // or, guarantee uname is available by dependency list
+ // or, guarantee uname is availabe by dependency list
FILE* pip = popen("uname -m", "r");
if (!pip) {
return std::string{};
@@ -85,40 +82,4 @@ std::string HostArchStr() {
return arch;
}
-Arch HostArch() {
- std::string arch_str = HostArchStr();
- if (arch_str == "aarch64") {
- return Arch::Arm64;
- } else if (arch_str == "arm") {
- return Arch::Arm;
- } else if (arch_str == "x86_64") {
- return Arch::X86_64;
- } else if (arch_str.size() == 4 && arch_str[0] == 'i' && arch_str[2] == '8' &&
- arch_str[3] == '6') {
- return Arch::X86;
- } else {
- LOG(FATAL) << "Unknown host architecture: " << arch_str;
- return Arch::X86;
- }
-}
-
-bool IsHostCompatible(Arch arch) {
- Arch host_arch = HostArch();
- return arch == host_arch || (arch == Arch::Arm && host_arch == Arch::Arm64) ||
- (arch == Arch::X86 && host_arch == Arch::X86_64);
-}
-
-static bool IsRunningInDocker() {
- // if /.dockerenv exists, it's inside a docker container
- static std::string docker_env_path("/.dockerenv");
- static bool ret =
- FileExists(docker_env_path) || DirectoryExists(docker_env_path);
- return ret;
-}
-
-bool IsRunningInContainer() {
- // TODO: add more if we support other containers than docker
- return IsRunningInDocker();
-}
-
-} // namespace cuttlefish
+} // namespace cvd
diff --git a/common/libs/utils/environment.h b/common/libs/utils/environment.h
index 004a8493e..5a83b49bc 100644
--- a/common/libs/utils/environment.h
+++ b/common/libs/utils/environment.h
@@ -17,22 +17,11 @@
#include <string>
-namespace cuttlefish {
-
-enum class Arch {
- Arm,
- Arm64,
- X86,
- X86_64,
-};
+namespace cvd {
std::string StringFromEnv(const std::string& varname,
const std::string& defval);
-std::string HostArchStr();
-Arch HostArch();
-bool IsHostCompatible(Arch arch);
-
-bool IsRunningInContainer();
+std::string HostArch();
-} // namespace cuttlefish
+} // namespace cvd
diff --git a/common/libs/utils/files.cpp b/common/libs/utils/files.cpp
index ea84b3221..833806ffc 100644
--- a/common/libs/utils/files.cpp
+++ b/common/libs/utils/files.cpp
@@ -23,16 +23,11 @@
#include <cstdio>
#include <cstdlib>
#include <fstream>
-#include <libgen.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
-#include <dirent.h>
-#include <vector>
-#include "common/libs/fs/shared_fd.h"
-
-namespace cuttlefish {
+namespace cvd {
bool FileExists(const std::string& path) {
struct stat st;
@@ -43,19 +38,6 @@ bool FileHasContent(const std::string& path) {
return FileSize(path) > 0;
}
-std::vector<std::string> DirectoryContents(const std::string& path) {
- std::vector<std::string> ret;
- std::unique_ptr<DIR, int(*)(DIR*)> dir(opendir(path.c_str()), closedir);
- CHECK(dir != nullptr) << "Could not read from dir \"" << path << "\"";
- if (dir) {
- struct dirent *ent;
- while ((ent = readdir(dir.get()))) {
- ret.push_back(ent->d_name);
- }
- }
- return ret;
-}
-
bool DirectoryExists(const std::string& path) {
struct stat st;
if (stat(path.c_str(), &st) == -1) {
@@ -67,27 +49,6 @@ bool DirectoryExists(const std::string& path) {
return true;
}
-bool IsDirectoryEmpty(const std::string& path) {
- auto direc = ::opendir(path.c_str());
- if (!direc) {
- LOG(ERROR) << "IsDirectoryEmpty test failed with " << path
- << " as it failed to be open" << std::endl;
- return false;
- }
-
- decltype(::readdir(direc)) sub = nullptr;
- int cnt {0};
- while ( (sub = ::readdir(direc)) ) {
- cnt++;
- if (cnt > 2) {
- LOG(ERROR) << "IsDirectoryEmpty test failed with " << path
- << " as it exists but not empty" << std::endl;
- return false;
- }
- }
- return true;
-}
-
std::string AbsolutePath(const std::string& path) {
if (path.empty()) {
return {};
@@ -95,10 +56,6 @@ std::string AbsolutePath(const std::string& path) {
if (path[0] == '/') {
return path;
}
- if (path[0] == '~') {
- LOG(WARNING) << "Tilde expansion in path " << path <<" is not supported";
- return {};
- }
std::array<char, PATH_MAX> buffer{};
if (!realpath(".", buffer.data())) {
@@ -128,7 +85,7 @@ std::chrono::system_clock::time_point FileModificationTime(const std::string& pa
}
bool RenameFile(const std::string& old_name, const std::string& new_name) {
- LOG(DEBUG) << "Renaming " << old_name << " to " << new_name;
+ LOG(INFO) << "Renaming " << old_name << " to " << new_name;
if(rename(old_name.c_str(), new_name.c_str())) {
LOG(ERROR) << "File rename failed due to " << strerror(errno);
return false;
@@ -138,7 +95,7 @@ bool RenameFile(const std::string& old_name, const std::string& new_name) {
}
bool RemoveFile(const std::string& file) {
- LOG(DEBUG) << "Removing " << file;
+ LOG(INFO) << "Removing " << file;
return remove(file.c_str()) == 0;
}
@@ -161,65 +118,4 @@ std::string CurrentDirectory() {
return ret;
}
-FileSizes SparseFileSizes(const std::string& path) {
- auto fd = SharedFD::Open(path, O_RDONLY);
- if (!fd->IsOpen()) {
- LOG(ERROR) << "Could not open \"" << path << "\": " << fd->StrError();
- return {};
- }
- off_t farthest_seek = fd->LSeek(0, SEEK_END);
- LOG(VERBOSE) << "Farthest seek: " << farthest_seek;
- if (farthest_seek == -1) {
- LOG(ERROR) << "Could not lseek in \"" << path << "\": " << fd->StrError();
- return {};
- }
- off_t data_bytes = 0;
- off_t offset = 0;
- while (offset < farthest_seek) {
- off_t new_offset = fd->LSeek(offset, SEEK_HOLE);
- if (new_offset == -1) {
- // ENXIO is returned when there are no more blocks of this type coming.
- if (fd->GetErrno() == ENXIO) {
- break;
- } else {
- LOG(ERROR) << "Could not lseek in \"" << path << "\": " << fd->StrError();
- return {};
- }
- } else {
- data_bytes += new_offset - offset;
- offset = new_offset;
- }
- if (offset >= farthest_seek) {
- break;
- }
- new_offset = fd->LSeek(offset, SEEK_DATA);
- if (new_offset == -1) {
- // ENXIO is returned when there are no more blocks of this type coming.
- if (fd->GetErrno() == ENXIO) {
- break;
- } else {
- LOG(ERROR) << "Could not lseek in \"" << path << "\": " << fd->StrError();
- return {};
- }
- } else {
- offset = new_offset;
- }
- }
- return (FileSizes) { .sparse_size = farthest_seek, .disk_size = data_bytes };
-}
-
-std::string cpp_basename(const std::string& str) {
- char* copy = strdup(str.c_str()); // basename may modify its argument
- std::string ret(basename(copy));
- free(copy);
- return ret;
-}
-
-std::string cpp_dirname(const std::string& str) {
- char* copy = strdup(str.c_str()); // dirname may modify its argument
- std::string ret(dirname(copy));
- free(copy);
- return ret;
-}
-
-} // namespace cuttlefish
+} // namespace cvd
diff --git a/common/libs/utils/files.h b/common/libs/utils/files.h
index ff1c8d336..b2b4d91ef 100644
--- a/common/libs/utils/files.h
+++ b/common/libs/utils/files.h
@@ -20,19 +20,15 @@
#include <chrono>
#include <string>
-namespace cuttlefish {
+namespace cvd {
bool FileExists(const std::string& path);
bool FileHasContent(const std::string& path);
-std::vector<std::string> DirectoryContents(const std::string& path);
bool DirectoryExists(const std::string& path);
-bool IsDirectoryEmpty(const std::string& path);
off_t FileSize(const std::string& path);
bool RemoveFile(const std::string& file);
bool RenameFile(const std::string& old_name, const std::string& new_name);
std::string ReadFile(const std::string& file);
std::chrono::system_clock::time_point FileModificationTime(const std::string& path);
-std::string cpp_dirname(const std::string& str);
-std::string cpp_basename(const std::string& str);
// The returned value may contain .. or . if these are present in the path
// argument.
@@ -40,10 +36,4 @@ std::string cpp_basename(const std::string& str);
std::string AbsolutePath(const std::string& path);
std::string CurrentDirectory();
-
-struct FileSizes {
- off_t sparse_size;
- off_t disk_size;
-};
-FileSizes SparseFileSizes(const std::string& path);
-} // namespace cuttlefish
+} // namespace cvd
diff --git a/common/libs/utils/network.cpp b/common/libs/utils/network.cpp
index d1f5f59a5..f120949f9 100644
--- a/common/libs/utils/network.cpp
+++ b/common/libs/utils/network.cpp
@@ -16,28 +16,22 @@
#include "common/libs/utils/network.h"
-#include <arpa/inet.h>
#include <linux/if.h>
#include <linux/if_tun.h>
-#include <linux/types.h>
-#include <linux/if_packet.h>
-#include <netinet/ip.h>
-#include <netinet/udp.h>
-#include <netinet/ether.h>
#include <string.h>
#include <android-base/strings.h>
#include "android-base/logging.h"
-#include "common/libs/fs/shared_buf.h"
#include "common/libs/utils/environment.h"
#include "common/libs/utils/subprocess.h"
-namespace cuttlefish {
+namespace cvd {
namespace {
static std::string DefaultHostArtifactsPath(const std::string& file_name) {
- return (StringFromEnv("ANDROID_HOST_OUT", StringFromEnv("HOME", ".")) +
+ return (cvd::StringFromEnv("ANDROID_HOST_OUT",
+ cvd::StringFromEnv("HOME", ".")) +
"/") +
file_name;
}
@@ -56,35 +50,6 @@ static std::string DefaultHostArtifactsPath(const std::string& file_name) {
// u16 num_buffers;
// };
static constexpr int SIZE_OF_VIRTIO_NET_HDR_V1 = 12;
-
-bool ParseAddress(const std::string& address, const std::string& separator,
- const std::size_t expected_size, int base, std::uint8_t* out) {
- auto components = android::base::Split(address, separator);
- if (components.size() != expected_size) {
- LOG(ERROR) << "Address \"" << address << "\" had wrong number of parts. "
- << "Had " << components.size() << ", expected " << expected_size;
- return false;
- }
- for (int i = 0; i < expected_size; i++) {
- auto out_part = std::stoi(components[i], nullptr, base);
- if (out_part < 0 || out_part > 255) {
- LOG(ERROR) << "Address part " << i << " (" << out_part
- << "): outside range [0,255]";
- return false;
- }
- out[i] = (std::uint8_t) out_part;
- }
- return true;
-}
-
-bool ParseMacAddress(const std::string& address, std::uint8_t mac[6]) {
- return ParseAddress(address, ":", 6, 16, mac);
-}
-
-bool ParseIpAddress(const std::string& address, std::uint8_t ip[4]) {
- return ParseAddress(address, ".", 4, 10, ip);
-}
-
} // namespace
SharedFD OpenTapInterface(const std::string& interface_name) {
@@ -96,16 +61,16 @@ SharedFD OpenTapInterface(const std::string& interface_name) {
return tap_fd;
}
- if (HostArch() == Arch::Arm64) {
+ if (cvd::HostArch() == "aarch64") {
auto tapsetiff_path = DefaultHostArtifactsPath("bin/tapsetiff");
- Command cmd(tapsetiff_path);
+ cvd::Command cmd(tapsetiff_path);
cmd.AddParameter(tap_fd);
cmd.AddParameter(interface_name.c_str());
int ret = cmd.Start().Wait();
if (ret != 0) {
LOG(ERROR) << "Unable to run tapsetiff.py. Exited with status " << ret;
tap_fd->Close();
- return SharedFD();
+ return cvd::SharedFD();
}
} else {
struct ifreq ifr;
@@ -118,7 +83,7 @@ SharedFD OpenTapInterface(const std::string& interface_name) {
LOG(ERROR) << "Unable to connect to " << interface_name
<< " tap interface: " << tap_fd->StrError();
tap_fd->Close();
- return SharedFD();
+ return cvd::SharedFD();
}
// The interface's configuration may have been modified or just not set
@@ -155,159 +120,4 @@ std::set<std::string> TapInterfacesInUse() {
}
return tap_interfaces;
}
-
-std::vector<DnsmasqDhcp4Lease> ParseDnsmasqLeases(SharedFD lease_file) {
- std::string lease_file_content;
- if (ReadAll(lease_file, &lease_file_content) < 0) {
- LOG(ERROR) << "Could not read lease_file: \"" << lease_file->StrError()
- << "\". This may result in difficulty connecting to guest wifi.";
- return {};
- }
- std::vector<DnsmasqDhcp4Lease> leases;
- auto lease_file_lines = android::base::Split(lease_file_content, "\n");
- for (const auto& line : lease_file_lines) {
- if (line == "") {
- continue;
- }
- auto line_elements = android::base::Split(line, " ");
- if (line_elements.size() != 5) {
- LOG(WARNING) << "Could not parse lease line: \"" << line << "\"\n";
- continue;
- }
- DnsmasqDhcp4Lease lease;
- lease.expiry = std::stoll(line_elements[0]);
- if (!ParseMacAddress(line_elements[1], &lease.mac_address[0])) {
- LOG(WARNING) << "Could not parse MAC address: \'" << line_elements[1]
- << "\"";
- continue;
- }
- if (!ParseIpAddress(line_elements[2], &lease.ip_address[0])) {
- LOG(WARNING) << "Could not parse IP address: " << line_elements[2]
- << "\"";
- }
- lease.hostname = line_elements[3];
- lease.client_id = line_elements[4];
- leases.push_back(lease);
- }
- return leases;
-}
-
-std::ostream& operator<<(std::ostream& out, const DnsmasqDhcp4Lease& lease) {
- out << "DnsmasqDhcp4Lease(lease_time = \"" << std::dec << lease.expiry
- << ", mac_address = \"" << std::hex;
- for (int i = 0; i < 5; i++) {
- out << (int) lease.mac_address[i] << ":";
- }
- out << (int) lease.mac_address[5] << "\", ip_address = \"" << std::dec;
- for (int i = 0; i < 3; i++) {
- out << (int) lease.ip_address[i] << ".";
- }
- return out << (int) lease.ip_address[3] << "\", hostname = \""
- << lease.hostname << "\", client_id = \"" << lease.client_id
- << "\")";
-}
-
-struct __attribute__((packed)) Dhcp4MessageTypeOption {
- std::uint8_t code;
- std::uint8_t len;
- std::uint8_t message_type;
-};
-
-struct __attribute__((packed)) Dhcp4ServerIdentifier {
- std::uint8_t code;
- std::uint8_t len;
- std::uint8_t server_ip[4];
-};
-
-struct __attribute__((packed)) Dhcp4ReleaseMessage {
- std::uint8_t op;
- std::uint8_t htype;
- std::uint8_t hlen;
- std::uint8_t hops;
- __be32 xid;
- __be16 secs;
- __be16 flags;
- std::uint8_t client_ip[4];
- std::uint8_t assigned_ip[4];
- std::uint8_t server_ip[4];
- std::uint8_t gateway_ip[4];
- std::uint8_t client_harware_address[16];
- std::uint8_t server_name[64];
- std::uint8_t boot_filename[128];
- std::uint8_t magic_cookie[4];
- Dhcp4MessageTypeOption message_type;
- Dhcp4ServerIdentifier server_identifier;
- std::uint8_t end_code;
-};
-
-struct __attribute__((packed)) CompleteReleaseFrame {
- std::uint8_t vnet[SIZE_OF_VIRTIO_NET_HDR_V1];
- ether_header eth;
- iphdr ip;
- udphdr udp;
- Dhcp4ReleaseMessage dhcp;
-};
-
-static std::uint16_t ip_checksum(std::uint16_t *buf, std::size_t size) {
- std::uint32_t sum = 0;
- for (std::size_t i = 0; i < size; i++) {
- sum += buf[i];
- }
- sum = (sum >> 16) + (sum & 0xFFFF);
- sum += sum >> 16;
- return (std::uint16_t) ~sum;
-}
-
-bool ReleaseDhcp4(SharedFD tap, const std::uint8_t mac_address[6],
- const std::uint8_t ip_address[4],
- const std::uint8_t dhcp_server_ip[4]) {
- CompleteReleaseFrame frame = {};
- *reinterpret_cast<std::uint16_t*>(&frame.vnet[2]) = // hdr_len, little-endian
- htole16(sizeof(ether_header) + sizeof(iphdr) + sizeof(udphdr));
-
- memcpy(frame.eth.ether_shost, mac_address, 6);
- memset(frame.eth.ether_dhost, 255, 6); // Broadcast
- frame.eth.ether_type = htobe16(ETH_P_IP);
-
- frame.ip.ihl = 5;
- frame.ip.version = 4;
- frame.ip.id = 0;
- frame.ip.ttl = 64; // hops
- frame.ip.protocol = 17; // UDP
- memcpy((std::uint8_t*) &frame.ip.saddr, ip_address, 4);
- frame.ip.daddr = *(std::uint32_t*) dhcp_server_ip;
- frame.ip.tot_len = htobe16(sizeof(frame.ip) + sizeof(frame.udp)
- + sizeof(frame.dhcp));
- iphdr ip_copy = frame.ip; // original, it's in a packed struct
- frame.ip.check = ip_checksum((unsigned short*) &ip_copy,
- sizeof(ip_copy) / sizeof(short));
-
- frame.udp.source = htobe16(68);
- frame.udp.dest = htobe16(67);
- frame.udp.len = htobe16(sizeof(frame.udp) + sizeof(frame.dhcp));
-
- frame.dhcp.op = 1; /* bootrequest */
- frame.dhcp.htype = 1; // Ethernet
- frame.dhcp.hlen = 6; /* mac address length */
- frame.dhcp.xid = rand();
- frame.dhcp.secs = htobe16(3);
- frame.dhcp.flags = 0;
- memcpy(frame.dhcp.client_ip, ip_address, 4);
- memcpy(frame.dhcp.client_harware_address, mac_address, 6);
- std::uint8_t magic_cookie[4] = {99, 130, 83, 99};
- memcpy(frame.dhcp.magic_cookie, magic_cookie, sizeof(magic_cookie));
- frame.dhcp.message_type = { .code = 53, .len = 1, .message_type = 7 };
- frame.dhcp.server_identifier.code = 54;
- frame.dhcp.server_identifier.len = 4;
- memcpy(frame.dhcp.server_identifier.server_ip, dhcp_server_ip, 4);
- frame.dhcp.end_code = 255;
-
- if (tap->Write((void*) &frame, sizeof(frame)) != sizeof(frame)) {
- LOG(ERROR) << "Could not write dhcprelease frame: \"" << tap->StrError()
- << "\". Connecting to wifi will likely not work.";
- return false;
- }
- return true;
-}
-
-} // namespace cuttlefish
+} // namespace cvd
diff --git a/common/libs/utils/network.h b/common/libs/utils/network.h
index 64b562e82..221d88e79 100644
--- a/common/libs/utils/network.h
+++ b/common/libs/utils/network.h
@@ -15,14 +15,12 @@
*/
#pragma once
-#include <cstddef>
#include <set>
#include <string>
-#include <vector>
#include "common/libs/fs/shared_fd.h"
-namespace cuttlefish {
+namespace cvd {
// Creates, or connects to if it already exists, a tap network interface. The
// user needs CAP_NET_ADMIN to create such interfaces or be the owner to connect
// to one.
@@ -30,23 +28,4 @@ SharedFD OpenTapInterface(const std::string& interface_name);
// Returns a list of TAP devices that have open file descriptors
std::set<std::string> TapInterfacesInUse();
-
-struct DnsmasqDhcp4Lease {
- std::uint64_t expiry;
- std::uint8_t mac_address[6];
- std::uint8_t ip_address[4];
- std::string hostname;
- std::string client_id;
-};
-
-// Parses a dnsmasq lease file
-std::vector<DnsmasqDhcp4Lease> ParseDnsmasqLeases(SharedFD lease_file);
-
-std::ostream& operator<<(std::ostream&, const DnsmasqDhcp4Lease&);
-
-// Sends a DHCPRELEASE message over the socket;
-bool ReleaseDhcp4(SharedFD tap, const std::uint8_t mac_address[6],
- const std::uint8_t ip_address[4],
- const std::uint8_t dhcp_server_ip[4]);
-
}
diff --git a/common/libs/utils/size_utils.cpp b/common/libs/utils/size_utils.cpp
index 9f2544552..0f7ed3c07 100644
--- a/common/libs/utils/size_utils.cpp
+++ b/common/libs/utils/size_utils.cpp
@@ -18,11 +18,11 @@
#include <unistd.h>
-namespace cuttlefish {
+namespace cvd {
-uint64_t AlignToPowerOf2(uint64_t val, uint8_t align_log) {
- uint64_t align = 1ULL << align_log;
+uint32_t AlignToPowerOf2(uint32_t val, uint8_t align_log) {
+ uint32_t align = 1 << align_log;
return ((val + (align - 1)) / align) * align;
}
-} // namespace cuttlefish
+} // namespace cvd
diff --git a/common/libs/utils/size_utils.h b/common/libs/utils/size_utils.h
index 625cdd8b9..42044ecf4 100644
--- a/common/libs/utils/size_utils.h
+++ b/common/libs/utils/size_utils.h
@@ -17,15 +17,9 @@
#include <stdint.h>
-namespace cuttlefish {
-
-// Keep the full disk size a multiple of 64k, for crosvm's virtio_blk driver
-constexpr int DISK_SIZE_SHIFT = 16;
-
-// Keep all partitions 4k aligned, for host performance reasons
-constexpr int PARTITION_SIZE_SHIFT = 12;
+namespace cvd {
// Returns the smallest multiple of 2^align_log greater than or equal to val.
-uint64_t AlignToPowerOf2(uint64_t val, uint8_t align_log);
+uint32_t AlignToPowerOf2(uint32_t val, uint8_t align_log);
-} // namespace cuttlefish
+} // namespace cvd
diff --git a/common/libs/utils/subprocess.cpp b/common/libs/utils/subprocess.cpp
index 7c0521934..1b2384069 100644
--- a/common/libs/utils/subprocess.cpp
+++ b/common/libs/utils/subprocess.cpp
@@ -32,15 +32,14 @@
#include "common/libs/fs/shared_buf.h"
-namespace cuttlefish {
namespace {
// If a redirected-to file descriptor was already closed, it's possible that
// some inherited file descriptor duped to this file descriptor and the redirect
// would override that. This function makes sure that doesn't happen.
bool validate_redirects(
- const std::map<Subprocess::StdIOChannel, int>& redirects,
- const std::map<SharedFD, int>& inherited_fds) {
+ const std::map<cvd::Subprocess::StdIOChannel, int>& redirects,
+ const std::map<cvd::SharedFD, int>& inherited_fds) {
// Add the redirected IO channels to a set as integers. This allows converting
// the enum values into integers instead of the other way around.
std::set<int> int_redirects;
@@ -58,7 +57,8 @@ bool validate_redirects(
return true;
}
-void do_redirects(const std::map<Subprocess::StdIOChannel, int>& redirects) {
+void do_redirects(
+ const std::map<cvd::Subprocess::StdIOChannel, int>& redirects) {
for (const auto& entry : redirects) {
auto std_channel = static_cast<int>(entry.first);
auto fd = entry.second;
@@ -74,30 +74,29 @@ std::vector<const char*> ToCharPointers(const std::vector<std::string>& vect) {
ret.push_back(NULL);
return ret;
}
-
-void UnsetEnvironment(const std::unordered_set<std::string>& unenv) {
- for (auto it = unenv.cbegin(); it != unenv.cend(); ++it) {
- unsetenv(it->c_str());
- }
-}
} // namespace
+namespace cvd {
Subprocess::Subprocess(Subprocess&& subprocess)
: pid_(subprocess.pid_),
started_(subprocess.started_),
+ control_socket_(subprocess.control_socket_),
stopper_(subprocess.stopper_) {
// Make sure the moved object no longer controls this subprocess
subprocess.pid_ = -1;
subprocess.started_ = false;
+ subprocess.control_socket_ = SharedFD();
}
Subprocess& Subprocess::operator=(Subprocess&& other) {
pid_ = other.pid_;
started_ = other.started_;
+ control_socket_ = other.control_socket_;
stopper_ = other.stopper_;
other.pid_ = -1;
other.started_ = false;
+ other.control_socket_ = SharedFD();
return *this;
}
@@ -163,6 +162,14 @@ bool KillSubprocess(Subprocess* subprocess) {
}
return true;
}
+Command::ParameterBuilder::~ParameterBuilder() { Build(); }
+void Command::ParameterBuilder::Build() {
+ auto param = stream_.str();
+ stream_ = std::stringstream();
+ if (param.size()) {
+ cmd_->AddParameter(param);
+ }
+}
Command::~Command() {
// Close all inherited file descriptors
@@ -191,8 +198,8 @@ bool Command::BuildParameter(std::stringstream* stream, SharedFD shared_fd) {
return true;
}
-bool Command::RedirectStdIO(Subprocess::StdIOChannel channel,
- SharedFD shared_fd) {
+bool Command::RedirectStdIO(cvd::Subprocess::StdIOChannel channel,
+ cvd::SharedFD shared_fd) {
if (!shared_fd->IsOpen()) {
return false;
}
@@ -212,11 +219,25 @@ bool Command::RedirectStdIO(Subprocess::StdIOChannel channel,
bool Command::RedirectStdIO(Subprocess::StdIOChannel subprocess_channel,
Subprocess::StdIOChannel parent_channel) {
return RedirectStdIO(subprocess_channel,
- SharedFD::Dup(static_cast<int>(parent_channel)));
+ cvd::SharedFD::Dup(static_cast<int>(parent_channel)));
}
Subprocess Command::Start(SubprocessOptions options) const {
auto cmd = ToCharPointers(command_);
+ // The parent socket will get closed on the child on the call to exec, the
+ // child socket will be closed on the parent when this function returns and no
+ // references to the fd are left
+ SharedFD parent_socket, child_socket;
+ if (options.WithControlSocket()) {
+ if (!SharedFD::SocketPair(AF_LOCAL, SOCK_STREAM, 0, &parent_socket,
+ &child_socket)) {
+ LOG(ERROR) << "Unable to create control socket pair: " << strerror(errno);
+ return Subprocess(-1, {});
+ }
+ // Remove FD_CLOEXEC from the child socket, ensure the parent has it
+ child_socket->Fcntl(F_SETFD, 0);
+ parent_socket->Fcntl(F_SETFD, FD_CLOEXEC);
+ }
if (!validate_redirects(redirects_, inherited_fds_)) {
return Subprocess(-1, {});
@@ -247,11 +268,10 @@ Subprocess Command::Start(SubprocessOptions options) const {
// the environment of the child process. To force an empty emvironment for
// the child process pass the address of a pointer to NULL
if (use_parent_env_) {
- UnsetEnvironment(unenv_);
- rval = execvp(cmd[0], const_cast<char* const*>(cmd.data()));
+ rval = execv(cmd[0], const_cast<char* const*>(cmd.data()));
} else {
auto envp = ToCharPointers(env_);
- rval = execvpe(cmd[0], const_cast<char* const*>(cmd.data()),
+ rval = execve(cmd[0], const_cast<char* const*>(cmd.data()),
const_cast<char* const*>(envp.data()));
}
// No need for an if: if exec worked it wouldn't have returned
@@ -262,18 +282,14 @@ Subprocess Command::Start(SubprocessOptions options) const {
if (pid == -1) {
LOG(ERROR) << "fork failed (" << strerror(errno) << ")";
}
- if (options.Verbose()) { // "more verbose", and LOG(DEBUG) > LOG(VERBOSE)
- LOG(DEBUG) << "Started (pid: " << pid << "): " << cmd[0];
- for (int i = 1; cmd[i]; i++) {
- LOG(DEBUG) << cmd[i];
- }
- } else {
- LOG(VERBOSE) << "Started (pid: " << pid << "): " << cmd[0];
- for (int i = 1; cmd[i]; i++) {
- LOG(VERBOSE) << cmd[i];
+ if (options.Verbose()) {
+ LOG(INFO) << "Started (pid: " << pid << "): " << cmd[0];
+ int i = 1;
+ while (cmd[i]) {
+ LOG(INFO) << cmd[i++];
}
}
- return Subprocess(pid, subprocess_stopper_);
+ return Subprocess(pid, parent_socket, subprocess_stopper_);
}
// A class that waits for threads to exit in its destructor.
@@ -295,7 +311,7 @@ int RunWithManagedStdio(Command&& cmd_tmp, const std::string* stdin,
SubprocessOptions options) {
/*
* The order of these declarations is necessary for safety. If the function
- * returns at any point, the Command will be destroyed first, closing all
+ * returns at any point, the cvd::Command will be destroyed first, closing all
* of its references to SharedFDs. This will cause the thread internals to fail
* their reads or writes. The ThreadJoiner then waits for the threads to
* complete, as running the destructor of an active std::thread crashes the
@@ -306,22 +322,22 @@ int RunWithManagedStdio(Command&& cmd_tmp, const std::string* stdin,
*/
std::thread stdin_thread, stdout_thread, stderr_thread;
ThreadJoiner thread_joiner({&stdin_thread, &stdout_thread, &stderr_thread});
- Command cmd = std::move(cmd_tmp);
+ cvd::Command cmd = std::move(cmd_tmp);
bool io_error = false;
if (stdin != nullptr) {
- SharedFD pipe_read, pipe_write;
- if (!SharedFD::Pipe(&pipe_read, &pipe_write)) {
+ cvd::SharedFD pipe_read, pipe_write;
+ if (!cvd::SharedFD::Pipe(&pipe_read, &pipe_write)) {
LOG(ERROR) << "Could not create a pipe to write the stdin of \""
<< cmd.GetShortName() << "\"";
return -1;
}
- if (!cmd.RedirectStdIO(Subprocess::StdIOChannel::kStdIn, pipe_read)) {
+ if (!cmd.RedirectStdIO(cvd::Subprocess::StdIOChannel::kStdIn, pipe_read)) {
LOG(ERROR) << "Could not set stdout of \"" << cmd.GetShortName()
<< "\", was already set.";
return -1;
}
stdin_thread = std::thread([pipe_write, stdin, &io_error]() {
- int written = WriteAll(pipe_write, *stdin);
+ int written = cvd::WriteAll(pipe_write, *stdin);
if (written < 0) {
io_error = true;
LOG(ERROR) << "Error in writing stdin to process";
@@ -329,19 +345,19 @@ int RunWithManagedStdio(Command&& cmd_tmp, const std::string* stdin,
});
}
if (stdout != nullptr) {
- SharedFD pipe_read, pipe_write;
- if (!SharedFD::Pipe(&pipe_read, &pipe_write)) {
+ cvd::SharedFD pipe_read, pipe_write;
+ if (!cvd::SharedFD::Pipe(&pipe_read, &pipe_write)) {
LOG(ERROR) << "Could not create a pipe to read the stdout of \""
<< cmd.GetShortName() << "\"";
return -1;
}
- if (!cmd.RedirectStdIO(Subprocess::StdIOChannel::kStdOut, pipe_write)) {
+ if (!cmd.RedirectStdIO(cvd::Subprocess::StdIOChannel::kStdOut, pipe_write)) {
LOG(ERROR) << "Could not set stdout of \"" << cmd.GetShortName()
<< "\", was already set.";
return -1;
}
stdout_thread = std::thread([pipe_read, stdout, &io_error]() {
- int read = ReadAll(pipe_read, stdout);
+ int read = cvd::ReadAll(pipe_read, stdout);
if (read < 0) {
io_error = true;
LOG(ERROR) << "Error in reading stdout from process";
@@ -349,19 +365,19 @@ int RunWithManagedStdio(Command&& cmd_tmp, const std::string* stdin,
});
}
if (stderr != nullptr) {
- SharedFD pipe_read, pipe_write;
- if (!SharedFD::Pipe(&pipe_read, &pipe_write)) {
+ cvd::SharedFD pipe_read, pipe_write;
+ if (!cvd::SharedFD::Pipe(&pipe_read, &pipe_write)) {
LOG(ERROR) << "Could not create a pipe to read the stderr of \""
<< cmd.GetShortName() << "\"";
return -1;
}
- if (!cmd.RedirectStdIO(Subprocess::StdIOChannel::kStdErr, pipe_write)) {
+ if (!cmd.RedirectStdIO(cvd::Subprocess::StdIOChannel::kStdErr, pipe_write)) {
LOG(ERROR) << "Could not set stderr of \"" << cmd.GetShortName()
<< "\", was already set.";
return -1;
}
stderr_thread = std::thread([pipe_read, stderr, &io_error]() {
- int read = ReadAll(pipe_read, stderr);
+ int read = cvd::ReadAll(pipe_read, stderr);
if (read < 0) {
io_error = true;
LOG(ERROR) << "Error in reading stderr from process";
@@ -373,11 +389,10 @@ int RunWithManagedStdio(Command&& cmd_tmp, const std::string* stdin,
if (!subprocess.Started()) {
return -1;
}
- auto cmd_short_name = cmd.GetShortName();
{
// Force the destructor to run by moving it into a smaller scope.
// This is necessary to close the write end of the pipe.
- Command forceDelete = std::move(cmd);
+ cvd::Command forceDelete = std::move(cmd);
}
int wstatus;
subprocess.Wait(&wstatus, 0);
@@ -389,7 +404,7 @@ int RunWithManagedStdio(Command&& cmd_tmp, const std::string* stdin,
auto join_threads = std::move(thread_joiner);
}
if (io_error) {
- LOG(ERROR) << "IO error communicating with " << cmd_short_name;
+ LOG(ERROR) << "IO error communicating with " << cmd.GetShortName();
return -1;
}
return WEXITSTATUS(wstatus);
@@ -420,4 +435,4 @@ int execute(const std::vector<std::string>& command) {
return subprocess.Wait();
}
-} // namespace cuttlefish
+} // namespace cvd
diff --git a/common/libs/utils/subprocess.h b/common/libs/utils/subprocess.h
index 777a02608..633c9f55e 100644
--- a/common/libs/utils/subprocess.h
+++ b/common/libs/utils/subprocess.h
@@ -21,14 +21,11 @@
#include <map>
#include <sstream>
#include <string>
-#include <unordered_set>
#include <vector>
-#include <android-base/logging.h>
-
#include <common/libs/fs/shared_fd.h>
-namespace cuttlefish {
+namespace cvd {
class Command;
class Subprocess;
class SubprocessOptions;
@@ -46,9 +43,10 @@ class Subprocess {
kStdErr = 2,
};
- Subprocess(pid_t pid, SubprocessStopper stopper = KillSubprocess)
+ Subprocess(pid_t pid, SharedFD control, SubprocessStopper stopper = KillSubprocess)
: pid_(pid),
started_(pid > 0),
+ control_socket_(control),
stopper_(stopper) {}
// The default implementation won't do because we need to reset the pid of the
// moved object.
@@ -64,6 +62,7 @@ class Subprocess {
// fork() succeeded or not, it says nothing about exec or successful
// completion of the command, that's what Wait is for.
bool Started() const { return started_; }
+ SharedFD control_socket() { return control_socket_; }
pid_t pid() const { return pid_; }
bool Stop() { return stopper_(this); }
@@ -75,16 +74,24 @@ class Subprocess {
Subprocess& operator=(const Subprocess&) = delete;
pid_t pid_ = -1;
bool started_ = false;
+ SharedFD control_socket_;
SubprocessStopper stopper_;
};
class SubprocessOptions {
+ bool with_control_socket_;
bool verbose_;
bool exit_with_parent_;
bool in_group_;
public:
- SubprocessOptions() : verbose_(true), exit_with_parent_(true) {}
+ SubprocessOptions() : with_control_socket_(false), verbose_(true),
+ exit_with_parent_(true) {}
+ // If with_control_socket is true the Subprocess instance will have a SharedFD
+ // that enables communication with the child process.
+ void WithControlSocket(bool with_control_socket) {
+ with_control_socket_ = with_control_socket;
+ }
void Verbose(bool verbose) {
verbose_ = verbose;
}
@@ -96,6 +103,7 @@ public:
in_group_ = in_group;
}
+ bool WithControlSocket() const { return with_control_socket_; }
bool Verbose() const { return verbose_; }
bool ExitWithParent() const { return exit_with_parent_; }
bool InGroup() const { return in_group_; }
@@ -120,6 +128,25 @@ class Command {
}
public:
+ class ParameterBuilder {
+ public:
+ ParameterBuilder(Command* cmd) : cmd_(cmd){};
+ ParameterBuilder(ParameterBuilder&& builder) = default;
+ ~ParameterBuilder();
+
+ template <typename T>
+ ParameterBuilder& operator<<(T t) {
+ cmd_->BuildParameter(&stream_, t);
+ return *this;
+ }
+
+ void Build();
+
+ private:
+ cvd::Command* cmd_;
+ std::stringstream stream_;
+ };
+
// Constructs a command object from the path to an executable binary and an
// optional subprocess stopper. When not provided, stopper defaults to sending
// SIGKILL to the subprocess.
@@ -142,14 +169,6 @@ class Command {
use_parent_env_ = false;
env_ = env;
}
-
- // Specify environment variables to be unset from the parent's environment
- // for the subprocesses to be started.
- void UnsetFromEnvironment(const std::vector<std::string>& env) {
- use_parent_env_ = true;
- std::copy(env.cbegin(), env.cend(), std::inserter(unenv_, unenv_.end()));
- }
-
// Adds a single parameter to the command. All arguments are concatenated into
// a single string to form a parameter. If one of those arguments is a
// SharedFD a duplicate of it will be used and won't be closed until the
@@ -164,24 +183,11 @@ class Command {
}
return false;
}
- // Similar to AddParameter, except the args are appended to the last (most
- // recently-added) parameter in the command.
- template <typename... Args>
- bool AppendToLastParameter(Args... args) {
- if (command_.empty()) {
- LOG(ERROR) << "There is no parameter to append to.";
- return false;
- }
- std::stringstream ss;
- if (BuildParameter(&ss, args...)) {
- command_[command_.size()-1] += ss.str();
- return true;
- }
- return false;
- }
+
+ ParameterBuilder GetParameterBuilder() { return ParameterBuilder(this); }
// Redirects the standard IO of the command.
- bool RedirectStdIO(Subprocess::StdIOChannel channel, SharedFD shared_fd);
+ bool RedirectStdIO(Subprocess::StdIOChannel channel, cvd::SharedFD shared_fd);
bool RedirectStdIO(Subprocess::StdIOChannel subprocess_channel,
Subprocess::StdIOChannel parent_channel);
@@ -197,16 +203,15 @@ class Command {
private:
std::vector<std::string> command_;
- std::map<SharedFD, int> inherited_fds_{};
+ std::map<cvd::SharedFD, int> inherited_fds_{};
std::map<Subprocess::StdIOChannel, int> redirects_{};
bool use_parent_env_ = true;
std::vector<std::string> env_{};
- std::unordered_set<std::string> unenv_{};
SubprocessStopper subprocess_stopper_;
};
/*
- * Consumes a Command and runs it, optionally managing the stdio channels.
+ * Consumes a cvd::Command and runs it, optionally managing the stdio channels.
*
* If `stdin` is set, the subprocess stdin will be pipe providing its contents.
* If `stdout` is set, the subprocess stdout will be captured and saved to it.
@@ -217,7 +222,7 @@ class Command {
* If some setup fails, `command` fails to start, or `command` exits due to a
* signal, the return value will be negative.
*/
-int RunWithManagedStdio(Command&& command, const std::string* stdin,
+int RunWithManagedStdio(cvd::Command&& command, const std::string* stdin,
std::string* stdout, std::string* stderr,
SubprocessOptions options = SubprocessOptions());
@@ -229,4 +234,4 @@ int execute(const std::vector<std::string>& command,
const std::vector<std::string>& env);
int execute(const std::vector<std::string>& command);
-} // namespace cuttlefish
+} // namespace cvd
diff --git a/common/libs/utils/tee_logging.cpp b/common/libs/utils/tee_logging.cpp
index 66b46c157..650a81320 100644
--- a/common/libs/utils/tee_logging.cpp
+++ b/common/libs/utils/tee_logging.cpp
@@ -23,14 +23,13 @@
#include <android-base/threads.h>
#include "common/libs/fs/shared_buf.h"
-#include "common/libs/utils/environment.h"
using android::base::GetThreadId;
using android::base::FATAL;
using android::base::LogSeverity;
using android::base::StringPrintf;
-namespace cuttlefish {
+namespace cvd {
static LogSeverity GuessSeverity(
const std::string& env_var, LogSeverity default_value) {
@@ -41,7 +40,8 @@ static LogSeverity GuessSeverity(
using android::base::ERROR;
using android::base::FATAL_WITHOUT_ABORT;
using android::base::FATAL;
- std::string env_value = StringFromEnv(env_var, "");
+ char* env_cstr = getenv(env_var.c_str());
+ std::string env_value(env_cstr == nullptr ? "" : env_cstr);
using android::base::EqualsIgnoreCase;
if (EqualsIgnoreCase(env_value, "VERBOSE")
|| env_value == std::to_string((int) VERBOSE)) {
@@ -74,7 +74,7 @@ LogSeverity ConsoleSeverity() {
}
LogSeverity LogFileSeverity() {
- return GuessSeverity("CF_FILE_SEVERITY", android::base::DEBUG);
+ return GuessSeverity("CF_FILE_SEVERITY", android::base::VERBOSE);
}
TeeLogger::TeeLogger(const std::vector<SeverityTarget>& destinations)
@@ -149,24 +149,6 @@ static std::string StderrOutputGenerator(const struct tm& now, int pid, uint64_t
return output_string;
}
-// TODO(schuffelen): Do something less primitive.
-static std::string StripColorCodes(const std::string& str) {
- std::stringstream sstream;
- bool in_color_code = false;
- for (char c : str) {
- if (c == '\033') {
- in_color_code = true;
- }
- if (!in_color_code) {
- sstream << c;
- }
- if (c == 'm') {
- in_color_code = false;
- }
- }
- return sstream.str();
-}
-
void TeeLogger::operator()(
android::base::LogId,
android::base::LogSeverity severity,
@@ -174,23 +156,15 @@ void TeeLogger::operator()(
const char* file,
unsigned int line,
const char* message) {
+ struct tm now;
+ time_t t = time(nullptr);
+ localtime_r(&t, &now);
+ auto output_string =
+ StderrOutputGenerator(
+ now, getpid(), GetThreadId(), severity, tag, file, line, message);
for (const auto& destination : destinations_) {
- std::string output_string;
- if (destination.metadata_level == MetadataLevel::ONLY_MESSAGE) {
- output_string = message + std::string("\n");
- } else {
- struct tm now;
- time_t t = time(nullptr);
- localtime_r(&t, &now);
- output_string = StderrOutputGenerator(now, getpid(), GetThreadId(),
- severity, tag, file, line, message);
- }
if (severity >= destination.severity) {
- if (destination.target->IsATTY()) {
- WriteAll(destination.target, output_string);
- } else {
- WriteAll(destination.target, StripColorCodes(output_string));
- }
+ cvd::WriteAll(destination.target, output_string);
}
}
}
@@ -200,15 +174,14 @@ static std::vector<SeverityTarget> SeverityTargetsForFiles(
std::vector<SeverityTarget> log_severities;
for (const auto& file : files) {
auto log_file_fd =
- SharedFD::Open(
+ cvd::SharedFD::Open(
file,
O_CREAT | O_WRONLY | O_APPEND,
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
if (!log_file_fd->IsOpen()) {
LOG(FATAL) << "Failed to create log file: " << log_file_fd->StrError();
}
- log_severities.push_back(
- SeverityTarget{LogFileSeverity(), log_file_fd, MetadataLevel::FULL});
+ log_severities.push_back(SeverityTarget {LogFileSeverity(), log_file_fd});
}
return log_severities;
}
@@ -219,10 +192,9 @@ TeeLogger LogToFiles(const std::vector<std::string>& files) {
TeeLogger LogToStderrAndFiles(const std::vector<std::string>& files) {
std::vector<SeverityTarget> log_severities = SeverityTargetsForFiles(files);
- log_severities.push_back(SeverityTarget{ConsoleSeverity(),
- SharedFD::Dup(/* stderr */ 2),
- MetadataLevel::ONLY_MESSAGE});
+ log_severities.push_back(
+ SeverityTarget {ConsoleSeverity(), SharedFD::Dup(/* stderr */ 2)});
return TeeLogger(log_severities);
}
-} // namespace cuttlefish
+} // namespace cvd
diff --git a/common/libs/utils/tee_logging.h b/common/libs/utils/tee_logging.h
index 6306e6224..09d49634c 100644
--- a/common/libs/utils/tee_logging.h
+++ b/common/libs/utils/tee_logging.h
@@ -22,20 +22,14 @@
#include "common/libs/fs/shared_fd.h"
-namespace cuttlefish {
+namespace cvd {
android::base::LogSeverity ConsoleSeverity();
android::base::LogSeverity LogFileSeverity();
-enum class MetadataLevel {
- FULL,
- ONLY_MESSAGE,
-};
-
struct SeverityTarget {
android::base::LogSeverity severity;
- SharedFD target;
- MetadataLevel metadata_level;
+ cvd::SharedFD target;
};
class TeeLogger {
@@ -57,4 +51,4 @@ public:
TeeLogger LogToFiles(const std::vector<std::string>& files);
TeeLogger LogToStderrAndFiles(const std::vector<std::string>& files);
-} // namespace cuttlefish
+} // namespace cvd
diff --git a/common/libs/utils/users.cpp b/common/libs/utils/users.cpp
index 31a4a5e43..cd3898273 100644
--- a/common/libs/utils/users.cpp
+++ b/common/libs/utils/users.cpp
@@ -27,7 +27,6 @@
#include <android-base/logging.h>
-namespace cuttlefish {
namespace {
gid_t GroupIdFromName(const std::string& group_name) {
struct group grp{};
@@ -46,7 +45,7 @@ gid_t GroupIdFromName(const std::string& group_name) {
if (grp_p != nullptr) {
return grp.gr_gid;
} else {
- // Caller may be checking with non-existent group name
+ LOG(ERROR) << "Group " << group_name << " does not exist";
return -1;
}
} else {
@@ -74,7 +73,7 @@ std::vector<gid_t> GetSuplementaryGroups() {
}
} // namespace
-bool InGroup(const std::string& group) {
+bool cvd::InGroup(const std::string& group) {
auto gid = GroupIdFromName(group);
if (gid == static_cast<gid_t>(-1)) {
return false;
@@ -90,6 +89,4 @@ bool InGroup(const std::string& group) {
return true;
}
return false;
-}
-
-} // namespace cuttlefish
+} \ No newline at end of file
diff --git a/common/libs/utils/users.h b/common/libs/utils/users.h
index 16fcbeb11..2fbbdd4a0 100644
--- a/common/libs/utils/users.h
+++ b/common/libs/utils/users.h
@@ -17,8 +17,8 @@
#include <string>
-namespace cuttlefish {
+namespace cvd {
bool InGroup(const std::string& group);
-} // namespace cuttlefish
+} // namespace cvd
diff --git a/default-permissions.xml b/default-permissions.xml
index eb50a4d0c..4b4277066 100644
--- a/default-permissions.xml
+++ b/default-permissions.xml
@@ -42,8 +42,7 @@
-->
<exception
- package="com.google.android.apps.restore"
- sha256-cert-digest="56:BE:13:2B:78:06:56:FE:24:44:CD:34:32:6E:B5:D7:AA:C9:1D:20:96:AB:F0:FE:67:3A:99:27:06:22:EC:87">
+ package="com.google.android.apps.pixelmigrate">
<!-- External storage -->
<permission name="android.permission.READ_EXTERNAL_STORAGE" fixed="false"/>
<permission name="android.permission.WRITE_EXTERNAL_STORAGE" fixed="false"/>
@@ -53,8 +52,9 @@
<!-- Call logs -->
<permission name="android.permission.READ_CALL_LOG" fixed="false"/>
<permission name="android.permission.WRITE_CALL_LOG" fixed="false"/>
- <!-- Used to set up a Wi-Fi P2P network -->
- <permission name="android.permission.ACCESS_FINE_LOCATION" fixed="false"/>
+ <!-- SMS -->
+ <permission name="android.permission.RECEIVE_SMS" fixed="false"/>
+ <permission name="android.permission.READ_PHONE_NUMBERS" fixed="false"/>
</exception>
<exception
@@ -67,6 +67,27 @@
<permission name="android.permission.RECEIVE_SMS" fixed="false"/>
</exception>
+ <exception
+ package="com.google.android.projection.gearhead"
+ sha256-cert-digest="FD:B0:0C:43:DB:DE:8B:51:CB:31:2A:A8:1D:3B:5F:A1:77:13:AD:B9:4B:28:F5:98:D7:7F:8E:B8:9D:AC:EE:DF">
+ <!-- Gearhead legacy -->
+ <permission name="android.permission.ACCESS_FINE_LOCATION" fixed="false"/>
+ <permission name="android.permission.CALL_PHONE" fixed="false"/>
+ <permission name="android.permission.READ_CALL_LOG" fixed="false"/>
+ <permission name="android.permission.READ_CONTACTS" fixed="false"/>
+ <permission name="android.permission.READ_PHONE_STATE" fixed="false"/>
+ <permission name="android.permission.RECEIVE_SMS" fixed="false"/>
+ <permission name="android.permission.RECORD_AUDIO" fixed="false"/>
+ <permission name="android.permission.SEND_SMS" fixed="false"/>
+ <permission name="android.permission.READ_CALENDAR" fixed="false"/>
+ <!-- For Top Gear -->
+ <permission name="android.permission.PROCESS_OUTGOING_CALLS" fixed="false"/>
+ <permission name="android.permission.READ_SMS" fixed="false"/>
+ <permission name="android.permission.RECEIVE_MMS" fixed="false"/>
+ <permission name="android.permission.WRITE_CALL_LOG" fixed="false"/>
+ <permission name="android.permission.ACCESS_COARSE_LOCATION" fixed="false"/>
+ </exception>
+
<exception package="com.google.android.settings.intelligence">
<!-- Calendar -->
<permission name="android.permission.READ_CALENDAR" fixed="true"/>
@@ -75,14 +96,14 @@
<permission name="android.permission.ACCESS_BACKGROUND_LOCATION" fixed="true"/>
</exception>
- <exception package="com.google.android.apps.cbrsnetworkmonitor">
+ <exception package="com.google.android.cbrsnetworkmonitor">
<!-- Location access to create CBRS geofences-->
<permission name="android.permission.ACCESS_FINE_LOCATION" fixed="true"/>
<permission name="android.permission.ACCESS_BACKGROUND_LOCATION" fixed="true"/>
</exception>
<exception package="com.google.android.apps.scone">
- <!-- Location access to determine proximity to a CBRS network coverage area -->
+ <!-- NLP Location access to determine proximity to country border -->
<permission name="android.permission.ACCESS_COARSE_LOCATION" fixed="false"/>
<permission name="android.permission.ACCESS_BACKGROUND_LOCATION" fixed="false"/>
<!-- Used to call ActivityTransition API for Smart OOS & Smart PNO -->
diff --git a/guest/Android.bp b/guest/Android.bp
new file mode 100644
index 000000000..95584bcb9
--- /dev/null
+++ b/guest/Android.bp
@@ -0,0 +1,16 @@
+//
+// 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.
+
+subdirs = ["*"]
diff --git a/guest/commands/Android.bp b/guest/commands/Android.bp
new file mode 100644
index 000000000..088948ba6
--- /dev/null
+++ b/guest/commands/Android.bp
@@ -0,0 +1,21 @@
+//
+// 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.
+
+subdirs = [
+ "vsock_logcat",
+ "ip_link_add",
+ "vport_trigger",
+ "vsoc_input_service",
+]
diff --git a/guest/commands/bt_vhci_forwarder/Android.bp b/guest/commands/bt_vhci_forwarder/Android.bp
deleted file mode 100644
index 72dd7c92e..000000000
--- a/guest/commands/bt_vhci_forwarder/Android.bp
+++ /dev/null
@@ -1,20 +0,0 @@
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-cc_binary {
- name: "bt_vhci_forwarder",
- srcs: [
- "main.cpp",
- ],
- shared_libs: [
- "libbase",
- "libcutils",
- "liblog",
- ],
- static_libs: [
- "libgflags",
- "libbt-rootcanal",
- ],
- defaults: ["cuttlefish_guest_only"]
-}
diff --git a/guest/commands/bt_vhci_forwarder/main.cpp b/guest/commands/bt_vhci_forwarder/main.cpp
deleted file mode 100644
index 5d5fcce42..000000000
--- a/guest/commands/bt_vhci_forwarder/main.cpp
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * Copyright (C) 2021 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 <fcntl.h>
-#include <sys/poll.h>
-#include <sys/uio.h>
-#include <termios.h>
-#include <unistd.h>
-#include <iomanip>
-#include <ios>
-#include <optional>
-
-#include <gflags/gflags.h>
-
-#include "android-base/logging.h"
-
-#include "model/devices/h4_packetizer.h"
-
-// Copied from net/bluetooth/hci.h
-#define HCI_ACLDATA_PKT 0x02
-#define HCI_SCODATA_PKT 0x03
-#define HCI_EVENT_PKT 0x04
-#define HCI_ISODATA_PKT 0x05
-#define HCI_VENDOR_PKT 0xff
-#define HCI_MAX_ACL_SIZE 1024
-#define HCI_MAX_FRAME_SIZE (HCI_MAX_ACL_SIZE + 4)
-
-// Include H4 header byte, and reserve more buffer size in the case of excess
-// packet.
-constexpr const size_t kBufferSize = (HCI_MAX_FRAME_SIZE + 1) * 2;
-
-constexpr const char* kVhciDev = "/dev/vhci";
-DEFINE_string(virtio_console_dev, "", "virtio-console device path");
-
-ssize_t send(int fd_, uint8_t type, const uint8_t* data, size_t length) {
- struct iovec iov[] = {{&type, sizeof(type)},
- {const_cast<uint8_t*>(data), length}};
- ssize_t ret = 0;
- do {
- ret = TEMP_FAILURE_RETRY(writev(fd_, iov, sizeof(iov) / sizeof(iov[0])));
- } while (-1 == ret && EAGAIN == errno);
- if (ret == -1) {
- PLOG(ERROR) << "virtio-console to vhci failed";
- }
- return ret;
-}
-
-ssize_t forward(int from, int to, std::optional<unsigned char> filter_out,
- unsigned char* buf) {
- ssize_t count = TEMP_FAILURE_RETRY(read(from, buf, kBufferSize));
- if (count < 0) {
- PLOG(ERROR) << "read failed";
- return count;
- } else if (count == 0) {
- return count;
- }
- if (filter_out && buf[0] == *filter_out) {
- LOG(INFO) << "ignore 0x" << std::hex << std::setw(2) << std::setfill('0')
- << (unsigned)buf[0] << " packet";
- return 0;
- }
- count = TEMP_FAILURE_RETRY(write(to, buf, count));
- if (count < 0) {
- PLOG(ERROR) << "write failed, type: 0x" << std::hex << std::setw(2)
- << std::setfill('0') << (unsigned)buf[0];
- }
- return count;
-}
-
-ssize_t forward(int from, int to, unsigned char* buf) {
- return forward(from, to, std::nullopt, buf);
-}
-
-int setTerminalRaw(int fd_) {
- termios terminal_settings;
- int rval = tcgetattr(fd_, &terminal_settings);
- if (rval < 0) {
- return rval;
- }
- cfmakeraw(&terminal_settings);
- rval = tcsetattr(fd_, TCSANOW, &terminal_settings);
- return rval;
-}
-
-int main(int argc, char** argv) {
- gflags::ParseCommandLineFlags(&argc, &argv, true);
-
- int vhci_fd = open(kVhciDev, O_RDWR);
- int virtio_fd = open(FLAGS_virtio_console_dev.c_str(), O_RDWR);
- setTerminalRaw(virtio_fd);
-
- struct pollfd fds[2];
-
- fds[0].fd = vhci_fd;
- fds[0].events = POLLIN;
- fds[1].fd = virtio_fd;
- fds[1].events = POLLIN;
- unsigned char buf[kBufferSize];
-
- auto h4 = test_vendor_lib::H4Packetizer(
- virtio_fd,
- [](const std::vector<uint8_t>& /* raw_command */) {
- LOG(ERROR)
- << "Unexpected command: command pkt shouldn't be sent as response.";
- },
- [vhci_fd](const std::vector<uint8_t>& raw_event) {
- send(vhci_fd, HCI_EVENT_PKT, raw_event.data(), raw_event.size());
- },
- [vhci_fd](const std::vector<uint8_t>& raw_acl) {
- send(vhci_fd, HCI_ACLDATA_PKT, raw_acl.data(), raw_acl.size());
- },
- [vhci_fd](const std::vector<uint8_t>& raw_sco) {
- send(vhci_fd, HCI_SCODATA_PKT, raw_sco.data(), raw_sco.size());
- },
- [vhci_fd](const std::vector<uint8_t>& raw_iso) {
- send(vhci_fd, HCI_ISODATA_PKT, raw_iso.data(), raw_iso.size());
- },
- []() { LOG(INFO) << "HCI socket device disconnected"; });
-
- while (true) {
- int ret = TEMP_FAILURE_RETRY(poll(fds, 2, -1));
- if (ret < 0) {
- PLOG(ERROR) << "poll failed";
- continue;
- }
- if (fds[0].revents & (POLLIN | POLLERR)) {
- // TODO(b/182245475) Ignore HCI_VENDOR_PKT
- // because root-canal cannot handle it.
- ssize_t c = forward(vhci_fd, virtio_fd, HCI_VENDOR_PKT, buf);
- if (c < 0) {
- PLOG(ERROR) << "vhci to virtio-console failed";
- }
- }
-
- if (fds[1].revents & (POLLIN | POLLERR)) {
- // 'virtio-console to vhci' depends on H4Packetizer because vhci expects
- // full packet, but the data from virtio-console could be partial.
- h4.OnDataReady(virtio_fd);
- }
- }
-} \ No newline at end of file
diff --git a/tests/powerwash/Android.bp b/guest/commands/ip_link_add/Android.bp
index 6ef1c9242..6c155f0b7 100644
--- a/tests/powerwash/Android.bp
+++ b/guest/commands/ip_link_add/Android.bp
@@ -1,4 +1,5 @@
-// Copyright (C) 2020 The Android Open Source Project
+//
+// 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.
@@ -12,19 +13,14 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-java_test_host {
- name: "PowerwashTest",
+cc_binary {
+ name: "ip_link_add",
srcs: [
- "src/**/*.java",
- ],
- test_suites: [
- "device-tests",
+ "main.cpp",
],
- libs: [
- "tradefed",
+ shared_libs: [
+ "cuttlefish_net",
],
+ defaults: ["cuttlefish_guest_only"]
}
diff --git a/guest/commands/ip_link_add/main.cpp b/guest/commands/ip_link_add/main.cpp
new file mode 100644
index 000000000..5b0779807
--- /dev/null
+++ b/guest/commands/ip_link_add/main.cpp
@@ -0,0 +1,75 @@
+/*
+ * 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.
+ */
+
+#include "common/libs/net/netlink_client.h"
+#include "common/libs/net/netlink_request.h"
+#include "common/libs/net/network_interface.h"
+#include "common/libs/net/network_interface_manager.h"
+
+#include <linux/rtnetlink.h>
+#include <net/if.h>
+#include <iostream>
+#include <string>
+
+int main(int argc, char *argv[]) {
+ if (!((argc == 5 && std::string(argv[1]) == "vlan") ||
+ (argc == 4 && std::string(argv[1]) == "virt_wifi"))) {
+ std::cerr << "usages:\n";
+ std::cerr << " " << argv[0] << " vlan [ethA] [ethB] [index]\n";
+ std::cerr << " " << argv[0] << " virt_wifi [ethA] [ethB]\n";
+ return -1;
+ }
+ const char *const name = argv[2];
+ int32_t index = if_nametoindex(name);
+ if (index == 0) {
+ fprintf(stderr, "%s: invalid interface name '%s'\n", argv[2], name);
+ return -2;
+ }
+ const char *const new_name = argv[3];
+ auto factory = cvd::NetlinkClientFactory::Default();
+ std::unique_ptr<cvd::NetlinkClient> nl(factory->New(NETLINK_ROUTE));
+
+ // http://maz-programmersdiary.blogspot.com/2011/09/netlink-sockets.html
+ cvd::NetlinkRequest link_add_request(RTM_NEWLINK, NLM_F_REQUEST|NLM_F_ACK|0x600);
+ link_add_request.Append(ifinfomsg {
+ .ifi_change = 0xFFFFFFFF,
+ });
+ link_add_request.AddString(IFLA_IFNAME, std::string(new_name));
+ link_add_request.AddInt(IFLA_LINK, index);
+
+ link_add_request.PushList(IFLA_LINKINFO);
+ link_add_request.AddString(IFLA_INFO_KIND, argv[1]);
+ link_add_request.PushList(IFLA_INFO_DATA);
+ if (std::string(argv[1]) == "vlan") {
+ uint16_t vlan_index = atoi(argv[4]);
+ link_add_request.AddInt(IFLA_VLAN_ID, vlan_index);
+ }
+ link_add_request.PopList();
+ link_add_request.PopList();
+
+ nl->Send(link_add_request);
+
+ cvd::NetlinkRequest bring_up_backing_request(RTM_SETLINK, NLM_F_REQUEST|NLM_F_ACK|0x600);
+ bring_up_backing_request.Append(ifinfomsg {
+ .ifi_index = index,
+ .ifi_flags = IFF_UP,
+ .ifi_change = 0xFFFFFFFF,
+ });
+
+ nl->Send(bring_up_backing_request);
+
+ return 0;
+}
diff --git a/guest/commands/rename_netiface/Android.bp b/guest/commands/rename_netiface/Android.bp
index f7b71be0f..b93a46589 100644
--- a/guest/commands/rename_netiface/Android.bp
+++ b/guest/commands/rename_netiface/Android.bp
@@ -14,10 +14,6 @@
// limitations under the License.
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
cc_binary {
name: "rename_netiface",
srcs: [
diff --git a/guest/commands/rename_netiface/main.cpp b/guest/commands/rename_netiface/main.cpp
index b48184d7c..370310761 100644
--- a/guest/commands/rename_netiface/main.cpp
+++ b/guest/commands/rename_netiface/main.cpp
@@ -35,11 +35,11 @@ int main(int argc, char *argv[]) {
return -2;
}
const char *const new_name = argv[2];
- auto factory = cuttlefish::NetlinkClientFactory::Default();
- std::unique_ptr<cuttlefish::NetlinkClient> nl(factory->New(NETLINK_ROUTE));
- std::unique_ptr<cuttlefish::NetworkInterfaceManager> nm(
- cuttlefish::NetworkInterfaceManager::New(factory));
- std::unique_ptr<cuttlefish::NetworkInterface> ni(nm->Open(new_name, name));
+ auto factory = cvd::NetlinkClientFactory::Default();
+ std::unique_ptr<cvd::NetlinkClient> nl(factory->New(NETLINK_ROUTE));
+ std::unique_ptr<cvd::NetworkInterfaceManager> nm(
+ cvd::NetworkInterfaceManager::New(factory));
+ std::unique_ptr<cvd::NetworkInterface> ni(nm->Open(new_name, name));
bool res = false;
if (ni) {
ni->SetName(new_name);
diff --git a/guest/commands/sensor_injection/Android.bp b/guest/commands/sensor_injection/Android.bp
deleted file mode 100644
index a29250ac4..000000000
--- a/guest/commands/sensor_injection/Android.bp
+++ /dev/null
@@ -1,18 +0,0 @@
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-cc_binary {
- name: "cuttlefish_sensor_injection",
- srcs: ["main.cpp"],
- shared_libs: [
- "android.hardware.sensors@1.0",
- "android.hardware.sensors@2.1",
- "libbase",
- "libbinder",
- "libhidlbase",
- "liblog",
- "libutils",
- ],
- defaults: ["cuttlefish_guest_only"],
-}
diff --git a/guest/commands/sensor_injection/main.cpp b/guest/commands/sensor_injection/main.cpp
deleted file mode 100644
index 6eadb4a23..000000000
--- a/guest/commands/sensor_injection/main.cpp
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * Copyright (C) 2021 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 <android-base/chrono_utils.h>
-#include <android-base/logging.h>
-#include <binder/IServiceManager.h>
-#include <utils/StrongPointer.h>
-#include <utils/SystemClock.h>
-
-#include <thread>
-
-#include "android/hardware/sensors/2.1/ISensors.h"
-
-using android::sp;
-using android::hardware::sensors::V1_0::OperationMode;
-using android::hardware::sensors::V1_0::Result;
-using android::hardware::sensors::V1_0::SensorStatus;
-using android::hardware::sensors::V2_1::Event;
-using android::hardware::sensors::V2_1::ISensors;
-using android::hardware::sensors::V2_1::SensorInfo;
-using android::hardware::sensors::V2_1::SensorType;
-
-sp<ISensors> startSensorInjection() {
- const sp<ISensors> sensors = ISensors::getService();
- if (sensors == nullptr) {
- LOG(FATAL) << "Unable to get ISensors.";
- }
-
- // Place the ISensors HAL into DATA_INJECTION mode so that we can
- // inject events.
- Result result = sensors->setOperationMode(OperationMode::DATA_INJECTION);
- if (result != Result::OK) {
- LOG(FATAL) << "Unable to set ISensors operation mode to DATA_INJECTION: "
- << toString(result);
- }
-
- return sensors;
-}
-
-int getSensorHandle(SensorType type, const sp<ISensors> sensors) {
- // Find the first available sensor of the given type.
- int handle = -1;
- const auto& getSensorsList_result =
- sensors->getSensorsList_2_1([&](const auto& list) {
- for (const SensorInfo& sensor : list) {
- if (sensor.type == type) {
- handle = sensor.sensorHandle;
- break;
- }
- }
- });
- if (!getSensorsList_result.isOk()) {
- LOG(FATAL) << "Unable to get ISensors sensors list: "
- << getSensorsList_result.description();
- }
- if (handle == -1) {
- LOG(FATAL) << "Unable to find sensor.";
- }
- return handle;
-}
-
-void endSensorInjection(const sp<ISensors> sensors) {
- // Return the ISensors HAL back to NORMAL mode.
- Result result = sensors->setOperationMode(OperationMode::NORMAL);
- if (result != Result::OK) {
- LOG(FATAL) << "Unable to set sensors operation mode to NORMAL: "
- << toString(result);
- }
-}
-
-// Inject ACCELEROMETER events to corresponding to a given physical
-// device orientation: portrait or landscape.
-void InjectOrientation(bool portrait) {
- sp<ISensors> sensors = startSensorInjection();
- int handle = getSensorHandle(SensorType::ACCELEROMETER, sensors);
-
- // Create a base ISensors accelerometer event.
- Event event;
- event.sensorHandle = handle;
- event.sensorType = SensorType::ACCELEROMETER;
- if (portrait) {
- event.u.vec3.x = 0;
- event.u.vec3.y = 9.2;
- } else {
- event.u.vec3.x = 9.2;
- event.u.vec3.y = 0;
- }
- event.u.vec3.z = 3.5;
- event.u.vec3.status = SensorStatus::ACCURACY_HIGH;
-
- // Repeatedly inject accelerometer events. The WindowManager orientation
- // listener responds to sustained accelerometer data, not just a single event.
- android::base::Timer timer;
- Result result;
- while (timer.duration() < 1s) {
- event.timestamp = android::elapsedRealtimeNano();
- result = sensors->injectSensorData_2_1(event);
- if (result != Result::OK) {
- LOG(FATAL) << "Unable to inject ISensors accelerometer event: "
- << toString(result);
- }
- std::this_thread::sleep_for(10ms);
- }
-
- endSensorInjection(sensors);
-}
-
-// Inject a single HINGE_ANGLE event at the given angle.
-void InjectHingeAngle(int angle) {
- sp<ISensors> sensors = startSensorInjection();
- int handle = getSensorHandle(SensorType::HINGE_ANGLE, sensors);
-
- // Create a base ISensors hinge_angle event.
- Event event;
- event.sensorHandle = handle;
- event.sensorType = SensorType::HINGE_ANGLE;
- event.u.scalar = angle;
- event.u.vec3.status = SensorStatus::ACCURACY_HIGH;
- event.timestamp = android::elapsedRealtimeNano();
- Result result = sensors->injectSensorData_2_1(event);
- if (result != Result::OK) {
- LOG(FATAL) << "Unable to inject HINGE_ANGLE data: " << toString(result);
- }
-
- endSensorInjection(sensors);
-}
-
-int main(int argc, char** argv) {
- if (argc == 2) {
- LOG(FATAL) << "Expected command line args 'rotate <portrait|landscape>' or "
- "'hinge_angle <value>'";
- }
-
- if (!strcmp(argv[1], "rotate")) {
- bool portrait = true;
- if (!strcmp(argv[2], "portrait")) {
- portrait = true;
- } else if (!strcmp(argv[2], "landscape")) {
- portrait = false;
- } else {
- LOG(FATAL) << "Expected command line arg 'portrait' or 'landscape'";
- }
- InjectOrientation(portrait);
- } else if (!strcmp(argv[1], "hinge_angle")) {
- int angle = std::stoi(argv[2]);
- if (angle < 0 || angle > 360) {
- LOG(FATAL) << "Bad hinge_angle value: " << argv[2];
- }
- InjectHingeAngle(angle);
- } else {
- LOG(FATAL) << "Unknown arg: " << argv[1];
- }
-}
diff --git a/guest/commands/setup_wifi/Android.bp b/guest/commands/setup_wifi/Android.bp
index 21472b1cb..e578af272 100644
--- a/guest/commands/setup_wifi/Android.bp
+++ b/guest/commands/setup_wifi/Android.bp
@@ -14,10 +14,6 @@
// limitations under the License.
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
cc_binary {
name: "setup_wifi",
srcs: [
diff --git a/guest/commands/setup_wifi/main.cpp b/guest/commands/setup_wifi/main.cpp
index 0a07c97ea..494a76731 100644
--- a/guest/commands/setup_wifi/main.cpp
+++ b/guest/commands/setup_wifi/main.cpp
@@ -46,10 +46,11 @@ static std::array<unsigned char, 6> str_to_mac(const std::string& mac_str) {
return mac;
}
+// TODO(schuffelen): Merge this with the ip_link_add binary.
int CreateWifiWrapper(const std::string& source,
const std::string& destination) {
- auto factory = cuttlefish::NetlinkClientFactory::Default();
- std::unique_ptr<cuttlefish::NetlinkClient> nl(factory->New(NETLINK_ROUTE));
+ auto factory = cvd::NetlinkClientFactory::Default();
+ std::unique_ptr<cvd::NetlinkClient> nl(factory->New(NETLINK_ROUTE));
LOG(INFO) << "Setting " << source << " mac address to " << FLAGS_mac_address;
int32_t index = if_nametoindex(source.c_str());
@@ -58,7 +59,7 @@ int CreateWifiWrapper(const std::string& source,
// https://elixir.bootlin.com/linux/v5.4.44/source/net/core/rtnetlink.c#L2460
// Setting the address seems to work better on the underlying ethernet device,
// and this mac address is inherited by the virt_wifi device.
- cuttlefish::NetlinkRequest fix_mac_request(
+ cvd::NetlinkRequest fix_mac_request(
RTM_SETLINK, NLM_F_REQUEST|NLM_F_ACK|0x600);
fix_mac_request.Append(ifinfomsg {
.ifi_index = index,
@@ -72,7 +73,7 @@ int CreateWifiWrapper(const std::string& source,
}
// http://maz-programmersdiary.blogspot.com/2011/09/netlink-sockets.html
- cuttlefish::NetlinkRequest link_add_request(RTM_NEWLINK,
+ cvd::NetlinkRequest link_add_request(RTM_NEWLINK,
NLM_F_REQUEST|NLM_F_ACK|0x600);
link_add_request.Append(ifinfomsg {
.ifi_change = 0xFFFFFFFF,
@@ -96,7 +97,7 @@ int CreateWifiWrapper(const std::string& source,
return -3;
}
- cuttlefish::NetlinkRequest bring_up_backing_request(RTM_SETLINK,
+ cvd::NetlinkRequest bring_up_backing_request(RTM_SETLINK,
NLM_F_REQUEST|NLM_F_ACK|0x600);
bring_up_backing_request.Append(ifinfomsg {
.ifi_index = index,
@@ -115,7 +116,7 @@ int CreateWifiWrapper(const std::string& source,
int RenameNetwork(const std::string& name, const std::string& new_name) {
static auto net_manager =
- cuttlefish::NetworkInterfaceManager::New(cuttlefish::NetlinkClientFactory::Default());
+ cvd::NetworkInterfaceManager::New(cvd::NetlinkClientFactory::Default());
auto connection = net_manager->Open(name, "ignore");
if (!connection) {
LOG(ERROR) << "setup_network: could not open " << name << " on device.";
diff --git a/tests/recovery/Android.bp b/guest/commands/vport_trigger/Android.bp
index c361a0e9e..621b9c5d5 100644
--- a/tests/recovery/Android.bp
+++ b/guest/commands/vport_trigger/Android.bp
@@ -1,4 +1,5 @@
-// Copyright (C) 2020 The Android Open Source Project
+//
+// 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.
@@ -12,19 +13,14 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-java_test_host {
- name: "RebootRecoveryTest",
+cc_binary {
+ name: "vport_trigger",
srcs: [
- "src/**/*.java",
- ],
- test_suites: [
- "device-tests",
+ "main.cpp",
],
- libs: [
- "tradefed",
+ shared_libs: [
+ "libcutils",
],
+ defaults: ["cuttlefish_guest_only"]
}
diff --git a/guest/commands/vport_trigger/main.cpp b/guest/commands/vport_trigger/main.cpp
new file mode 100644
index 000000000..b8d88671d
--- /dev/null
+++ b/guest/commands/vport_trigger/main.cpp
@@ -0,0 +1,86 @@
+/*
+ * 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.
+ */
+
+#include <cutils/properties.h>
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <dirent.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <climits>
+#include <cerrno>
+#include <string>
+
+// Taken from android::base, which wasn't available on platform versions
+// earlier than nougat.
+
+static bool ReadFdToString(int fd, std::string* content) {
+ content->clear();
+ char buf[BUFSIZ];
+ ssize_t n;
+ while ((n = TEMP_FAILURE_RETRY(read(fd, &buf[0], sizeof(buf)))) > 0) {
+ content->append(buf, n);
+ }
+ return (n == 0) ? true : false;
+}
+
+static bool ReadFileToString(const std::string& path, std::string* content,
+ bool follow_symlinks) {
+ int flags = O_RDONLY | O_CLOEXEC | (follow_symlinks ? 0 : O_NOFOLLOW);
+ int fd = TEMP_FAILURE_RETRY(open(path.c_str(), flags));
+ if (fd == -1) {
+ return false;
+ }
+ bool result = ReadFdToString(fd, content);
+ close(fd);
+ return result;
+}
+
+int main(int argc __unused, char *argv[] __unused) {
+ const char sysfs_base[] = "/sys/class/virtio-ports/";
+ DIR *dir = opendir(sysfs_base);
+ if (dir) {
+ dirent *dp;
+ while ((dp = readdir(dir)) != nullptr) {
+ std::string dirname = dp->d_name;
+ std::string sysfs(sysfs_base + dirname + "/name");
+ struct stat st;
+ if (stat(sysfs.c_str(), &st)) {
+ continue;
+ }
+ std::string content;
+ if (!ReadFileToString(sysfs, &content, true)) {
+ continue;
+ }
+ if (content.empty()) {
+ continue;
+ }
+ content.erase(content.end() - 1);
+ // Leaves 32-11=22 characters for the port name from QEMU.
+ std::string dev("/dev/" + dirname);
+ std::string propname("vendor.ser." + content);
+ property_set(propname.c_str(), dev.c_str());
+ // Property was renamed; this is for compatibility
+ std::string legacy_propname("sys.cf.ser." + content);
+ property_set(legacy_propname.c_str(), dev.c_str());
+ }
+ }
+ return 0;
+}
diff --git a/guest/commands/vsoc_input_service/Android.bp b/guest/commands/vsoc_input_service/Android.bp
index 79ac9898c..01e07d8d7 100644
--- a/guest/commands/vsoc_input_service/Android.bp
+++ b/guest/commands/vsoc_input_service/Android.bp
@@ -14,10 +14,6 @@
// limitations under the License.
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
cc_binary {
name: "vsoc_input_service",
srcs: [
@@ -33,7 +29,6 @@ cc_binary {
],
shared_libs: [
"libcuttlefish_device_config",
- "libcuttlefish_device_config_proto",
"libcuttlefish_fs",
"libbase",
"liblog",
diff --git a/guest/commands/vsoc_input_service/main.cpp b/guest/commands/vsoc_input_service/main.cpp
index 65d6c6c92..c9e93ede7 100644
--- a/guest/commands/vsoc_input_service/main.cpp
+++ b/guest/commands/vsoc_input_service/main.cpp
@@ -21,7 +21,7 @@
int main(int argc, char* argv[]) {
gflags::ParseCommandLineFlags(&argc, &argv, true);
- cuttlefish_input_service::VSoCInputService service;
+ vsoc_input_service::VSoCInputService service;
if (!service.SetUpDevices()) {
return -1;
}
diff --git a/guest/commands/vsoc_input_service/virtual_device_base.cpp b/guest/commands/vsoc_input_service/virtual_device_base.cpp
index b96ee39e6..9adcb957c 100644
--- a/guest/commands/vsoc_input_service/virtual_device_base.cpp
+++ b/guest/commands/vsoc_input_service/virtual_device_base.cpp
@@ -18,14 +18,13 @@
#include <android-base/logging.h>
#include <errno.h>
-#include <fcntl.h>
#include <inttypes.h>
#include <string.h>
#include <unistd.h>
#include "log/log.h"
-using cuttlefish_input_service::VirtualDeviceBase;
+using vsoc_input_service::VirtualDeviceBase;
namespace {
diff --git a/guest/commands/vsoc_input_service/virtual_device_base.h b/guest/commands/vsoc_input_service/virtual_device_base.h
index 2932753a9..d25e0e4da 100644
--- a/guest/commands/vsoc_input_service/virtual_device_base.h
+++ b/guest/commands/vsoc_input_service/virtual_device_base.h
@@ -22,7 +22,7 @@
#include <functional>
#include <vector>
-namespace cuttlefish_input_service {
+namespace vsoc_input_service {
class VirtualDeviceBase {
public:
@@ -48,4 +48,4 @@ class VirtualDeviceBase {
int fd_ = -1;
};
-} // namespace cuttlefish_input_service
+} // namespace vsoc_input_service
diff --git a/guest/commands/vsoc_input_service/virtual_keyboard.cpp b/guest/commands/vsoc_input_service/virtual_keyboard.cpp
index 7ffcea5df..80cf0e079 100644
--- a/guest/commands/vsoc_input_service/virtual_keyboard.cpp
+++ b/guest/commands/vsoc_input_service/virtual_keyboard.cpp
@@ -16,7 +16,7 @@
#include "virtual_keyboard.h"
-namespace cuttlefish_input_service {
+namespace vsoc_input_service {
VirtualKeyboard::VirtualKeyboard()
: VirtualDeviceBase("VSoC keyboard", 0x6008) {}
@@ -63,4 +63,4 @@ const std::vector<const uint32_t>& VirtualKeyboard::GetKeys() const {
return keys;
}
-} // namespace cuttlefish_input_service
+} // namespace vsoc_input_service
diff --git a/guest/commands/vsoc_input_service/virtual_keyboard.h b/guest/commands/vsoc_input_service/virtual_keyboard.h
index 0dd1f42de..b3436990a 100644
--- a/guest/commands/vsoc_input_service/virtual_keyboard.h
+++ b/guest/commands/vsoc_input_service/virtual_keyboard.h
@@ -17,7 +17,7 @@
#include "virtual_device_base.h"
-namespace cuttlefish_input_service {
+namespace vsoc_input_service {
class VirtualKeyboard : public VirtualDeviceBase {
public:
@@ -28,4 +28,4 @@ class VirtualKeyboard : public VirtualDeviceBase {
const std::vector<const uint32_t>& GetKeys() const override;
};
-} // namespace cuttlefish_input_service
+} // namespace vsoc_input_service
diff --git a/guest/commands/vsoc_input_service/virtual_power_button.cpp b/guest/commands/vsoc_input_service/virtual_power_button.cpp
index 595630bdf..d1758e04a 100644
--- a/guest/commands/vsoc_input_service/virtual_power_button.cpp
+++ b/guest/commands/vsoc_input_service/virtual_power_button.cpp
@@ -16,7 +16,7 @@
#include "virtual_power_button.h"
-namespace cuttlefish_input_service {
+namespace vsoc_input_service {
VirtualPowerButton::VirtualPowerButton()
: VirtualDeviceBase("VSoC power button", 0x6007) {}
@@ -30,4 +30,4 @@ const std::vector<const uint32_t>& VirtualPowerButton::GetKeys() const {
return keys;
}
-} // namespace cuttlefish_input_service
+} // namespace vsoc_input_service
diff --git a/guest/commands/vsoc_input_service/virtual_power_button.h b/guest/commands/vsoc_input_service/virtual_power_button.h
index 95811db2f..220bfdce3 100644
--- a/guest/commands/vsoc_input_service/virtual_power_button.h
+++ b/guest/commands/vsoc_input_service/virtual_power_button.h
@@ -17,7 +17,7 @@
#include "virtual_device_base.h"
-namespace cuttlefish_input_service {
+namespace vsoc_input_service {
class VirtualPowerButton : public VirtualDeviceBase {
public:
@@ -28,4 +28,4 @@ class VirtualPowerButton : public VirtualDeviceBase {
const std::vector<const uint32_t>& GetKeys() const override;
};
-} // namespace cuttlefish_input_service
+} // namespace vsoc_input_service
diff --git a/guest/commands/vsoc_input_service/virtual_touchscreen.cpp b/guest/commands/vsoc_input_service/virtual_touchscreen.cpp
index c67857330..72a0d3fd2 100644
--- a/guest/commands/vsoc_input_service/virtual_touchscreen.cpp
+++ b/guest/commands/vsoc_input_service/virtual_touchscreen.cpp
@@ -16,7 +16,7 @@
#include "virtual_touchscreen.h"
-namespace cuttlefish_input_service {
+namespace vsoc_input_service {
const std::vector<const uint32_t>& VirtualTouchScreen::GetEventTypes() const {
static const std::vector<const uint32_t> evt_types{EV_ABS, EV_KEY};
@@ -43,4 +43,4 @@ VirtualTouchScreen::VirtualTouchScreen(uint32_t width, uint32_t height)
dev_.absmax[ABS_Y] = height;
}
-} // namespace cuttlefish_input_service
+} // namespace vsoc_input_service
diff --git a/guest/commands/vsoc_input_service/virtual_touchscreen.h b/guest/commands/vsoc_input_service/virtual_touchscreen.h
index a32bcb532..9ac806eb9 100644
--- a/guest/commands/vsoc_input_service/virtual_touchscreen.h
+++ b/guest/commands/vsoc_input_service/virtual_touchscreen.h
@@ -17,7 +17,7 @@
#include "virtual_device_base.h"
-namespace cuttlefish_input_service {
+namespace vsoc_input_service {
class VirtualTouchScreen : public VirtualDeviceBase {
public:
@@ -30,4 +30,4 @@ class VirtualTouchScreen : public VirtualDeviceBase {
virtual const std::vector<const uint32_t>& GetAbs() const;
};
-} // namespace cuttlefish_input_service
+} // namespace vsoc_input_service
diff --git a/guest/commands/vsoc_input_service/vsoc_input_service.cpp b/guest/commands/vsoc_input_service/vsoc_input_service.cpp
index 6d39a811d..4e2cc914a 100644
--- a/guest/commands/vsoc_input_service/vsoc_input_service.cpp
+++ b/guest/commands/vsoc_input_service/vsoc_input_service.cpp
@@ -22,19 +22,19 @@
#include <thread>
-#include <android-base/logging.h>
#include <gflags/gflags.h>
-#include <log/log.h>
+#include "log/log.h"
+#include <android-base/logging.h>
#include "common/libs/fs/shared_fd.h"
#include "common/libs/device_config/device_config.h"
-using cuttlefish::input_events::InputEvent;
-using cuttlefish_input_service::VirtualDeviceBase;
-using cuttlefish_input_service::VirtualKeyboard;
-using cuttlefish_input_service::VirtualPowerButton;
-using cuttlefish_input_service::VirtualTouchScreen;
-using cuttlefish_input_service::VSoCInputService;
+using vsoc::input_events::InputEvent;
+using vsoc_input_service::VirtualDeviceBase;
+using vsoc_input_service::VirtualKeyboard;
+using vsoc_input_service::VirtualPowerButton;
+using vsoc_input_service::VirtualTouchScreen;
+using vsoc_input_service::VSoCInputService;
DEFINE_uint32(keyboard_port, 0, "keyboard vsock port");
DEFINE_uint32(touch_port, 0, "keyboard vsock port");
@@ -61,19 +61,14 @@ bool VSoCInputService::SetUpDevices() {
return false;
}
- auto config_helper = cuttlefish::DeviceConfigHelper::Get();
- if (!config_helper) {
+ auto config = cvd::DeviceConfig::Get();
+ if (!config) {
LOG(ERROR) << "Failed to open device config";
return false;
}
- const auto& device_config = config_helper->GetDeviceConfig();
- CHECK_GE(device_config.display_config_size(), 1);
- const auto& display_config = device_config.display_config(0);
-
virtual_touchscreen_.reset(
- new VirtualTouchScreen(display_config.width(),
- display_config.height()));
+ new VirtualTouchScreen(config->screen_x_res(), config->screen_y_res()));
if (!virtual_touchscreen_->SetUp()) {
return false;
}
@@ -82,12 +77,12 @@ bool VSoCInputService::SetUpDevices() {
}
bool VSoCInputService::ProcessEvents() {
- cuttlefish::SharedFD keyboard_fd;
- cuttlefish::SharedFD touch_fd;
+ cvd::SharedFD keyboard_fd;
+ cvd::SharedFD touch_fd;
LOG(INFO) << "Connecting to the keyboard at " << FLAGS_keyboard_port;
if (FLAGS_keyboard_port) {
- keyboard_fd = cuttlefish::SharedFD::VsockClient(2, FLAGS_keyboard_port, SOCK_STREAM);
+ keyboard_fd = cvd::SharedFD::VsockClient(2, FLAGS_keyboard_port, SOCK_STREAM);
if (!keyboard_fd->IsOpen()) {
LOG(ERROR) << "Could not connect to the keyboard at vsock:2:" << FLAGS_keyboard_port;
}
@@ -95,7 +90,7 @@ bool VSoCInputService::ProcessEvents() {
}
LOG(INFO) << "Connecting to the touchscreen at " << FLAGS_keyboard_port;
if (FLAGS_touch_port) {
- touch_fd = cuttlefish::SharedFD::VsockClient(2, FLAGS_touch_port, SOCK_STREAM);
+ touch_fd = cvd::SharedFD::VsockClient(2, FLAGS_touch_port, SOCK_STREAM);
if (!touch_fd->IsOpen()) {
LOG(ERROR) << "Could not connect to the touch at vsock:2:" << FLAGS_touch_port;
}
diff --git a/guest/commands/vsoc_input_service/vsoc_input_service.h b/guest/commands/vsoc_input_service/vsoc_input_service.h
index d8aea81ad..edf196dee 100644
--- a/guest/commands/vsoc_input_service/vsoc_input_service.h
+++ b/guest/commands/vsoc_input_service/vsoc_input_service.h
@@ -21,7 +21,7 @@
#include "virtual_power_button.h"
#include "virtual_touchscreen.h"
-namespace cuttlefish {
+namespace vsoc {
namespace input_events {
struct InputEvent {
@@ -31,9 +31,9 @@ struct InputEvent {
};
} // namespace input_events
-} // namespace cuttlefish
+} // namespace vsoc
-namespace cuttlefish_input_service {
+namespace vsoc_input_service {
class VSoCInputService {
public:
@@ -46,4 +46,4 @@ class VSoCInputService {
std::shared_ptr<VirtualTouchScreen> virtual_touchscreen_;
};
-} // namespace cuttlefish_input_service
+} // namespace vsoc_input_service
diff --git a/host/commands/bt_connector/Android.bp b/guest/commands/vsock_logcat/Android.bp
index d617eaa37..bebea59ca 100644
--- a/host/commands/bt_connector/Android.bp
+++ b/guest/commands/vsock_logcat/Android.bp
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2021 The Android Open Source Project
+// 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.
@@ -14,25 +14,20 @@
// limitations under the License.
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
cc_binary {
- name: "bt_connector",
+ name: "vsock_logcat",
srcs: [
"main.cpp",
],
shared_libs: [
"libbase",
+ "libcutils",
"libcuttlefish_fs",
- "libjsoncpp",
- "liblog",
"libcuttlefish_utils",
+ "liblog",
],
static_libs: [
- "libcuttlefish_host_config",
"libgflags",
],
- defaults: ["cuttlefish_buildhost_only"]
+ defaults: ["cuttlefish_guest_only"]
}
diff --git a/guest/commands/vsock_logcat/main.cpp b/guest/commands/vsock_logcat/main.cpp
new file mode 100644
index 000000000..70c7a505e
--- /dev/null
+++ b/guest/commands/vsock_logcat/main.cpp
@@ -0,0 +1,142 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "vsock_logcat"
+
+#include <string.h>
+
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <fstream>
+#include <sstream>
+#include <string>
+
+#include <cutils/properties.h>
+#include <gflags/gflags.h>
+#include <android-base/logging.h>
+
+#include "common/libs/fs/shared_fd.h"
+#include "common/libs/utils/files.h"
+#include "common/libs/utils/subprocess.h"
+
+DEFINE_uint32(
+ port,
+ static_cast<uint32_t>(property_get_int64("ro.boot.vsock_logcat_port", 0)),
+ "VSOCK port to send logcat output to");
+DEFINE_uint32(cid, 2, "VSOCK CID to send logcat output to");
+DEFINE_string(pipe_name, "/dev/cf_logcat_pipe",
+ "The path for the named pipe logcat will write to");
+
+namespace {
+
+constexpr char kLogcatExitMsg[] = "\nDetected exit of logcat process\n\n";
+
+class ServiceStatus {
+ public:
+ static const char* kServiceStatusProperty;
+ static const char* kStatusStarted;
+ static const char* kStatusFailed;
+
+ ServiceStatus() {
+ // This can fail if the property isn't set (the first time it runs), so
+ // ignore the result.
+ property_get(kServiceStatusProperty, status_, kStatusStarted);
+ }
+
+ bool Set(const char* status) {
+ auto ret = property_set(kServiceStatusProperty, status);
+
+ if (ret == 0) {
+ strcpy(status_, status);
+ return true;
+ }
+ return false;
+ }
+
+ const char* Get() { return status_; }
+
+ private:
+ char status_[PROP_VALUE_MAX];
+};
+
+const char* ServiceStatus::kServiceStatusProperty = "vendor.vsock_logcat_status";
+const char* ServiceStatus::kStatusStarted = "started";
+const char* ServiceStatus::kStatusFailed = "failed";
+
+void LogFailed(const std::string& msg, ServiceStatus* status) {
+ // Only log if status is not failed, ensuring it logs once per fail.
+ if (strcmp(status->Get(), ServiceStatus::kStatusFailed) != 0) {
+ LOG(ERROR) << msg;
+ std::ofstream kmsg;
+ kmsg.open("/dev/kmsg");
+ kmsg << LOG_TAG << ": " << msg;
+ kmsg << "";
+ kmsg.close();
+ }
+ auto ret = status->Set(ServiceStatus::kStatusFailed);
+ if (!ret) {
+ LOG(ERROR) << "Unable to set value of property: "
+ << ServiceStatus::kServiceStatusProperty;
+ }
+}
+} // namespace
+
+int main(int argc, char** argv) {
+ gflags::ParseCommandLineFlags(&argc, &argv, true);
+
+ CHECK(FLAGS_port != 0) << "Port flag is required";
+
+ ServiceStatus status;
+
+ auto log_fd = cvd::SharedFD::VsockClient(FLAGS_cid, FLAGS_port, SOCK_STREAM);
+ if (!log_fd->IsOpen()) {
+ std::ostringstream msg;
+ msg << "Unable to connect to vsock:" << FLAGS_cid << ":" << FLAGS_port
+ << ": " << log_fd->StrError();
+ LogFailed(msg.str(), &status);
+ return 1;
+ }
+ auto ret = status.Set(ServiceStatus::kStatusStarted);
+ if (!ret) {
+ LOG(ERROR) << "Unable to set value of property: "
+ << ServiceStatus::kServiceStatusProperty;
+ }
+
+ if (cvd::FileExists(FLAGS_pipe_name)) {
+ LOG(WARNING) << "The file " << FLAGS_pipe_name << " already exists. Deleting...";
+ cvd::RemoveFile(FLAGS_pipe_name);
+ }
+ auto pipe = mkfifo(FLAGS_pipe_name.c_str(), 0600);
+ if (pipe != 0) {
+ LOG(FATAL) << "unable to create pipe: " << strerror(errno);
+ }
+ property_set("vendor.ser.cf-logcat", FLAGS_pipe_name.c_str());
+ while (1) {
+ auto conn = cvd::SharedFD::Open(FLAGS_pipe_name.c_str(), O_RDONLY);
+ while (conn->IsOpen()) {
+ char buff[4096];
+ auto read = conn->Read(buff, sizeof(buff));
+ if (read) {
+ log_fd->Write(buff, read);
+ } else {
+ conn->Close();
+ }
+ }
+ log_fd->Write(kLogcatExitMsg, sizeof(kLogcatExitMsg) - 1);
+ }
+}
diff --git a/guest/hals/Android.bp b/guest/hals/Android.bp
new file mode 100644
index 000000000..6d01e72e8
--- /dev/null
+++ b/guest/hals/Android.bp
@@ -0,0 +1,20 @@
+//
+// 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.
+
+subdirs = [
+ "gps",
+ "health",
+ "hwcomposer",
+]
diff --git a/guest/hals/audio/Android.bp b/guest/hals/audio/Android.bp
index c6faae790..93a74558a 100644
--- a/guest/hals/audio/Android.bp
+++ b/guest/hals/audio/Android.bp
@@ -12,10 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
cc_library_shared {
name: "audio.primary.cutf",
relative_install_path: "hw",
diff --git a/guest/hals/audio/audio_hw.c b/guest/hals/audio/audio_hw.c
index 51110d7db..7db1ec1ac 100644
--- a/guest/hals/audio/audio_hw.c
+++ b/guest/hals/audio/audio_hw.c
@@ -45,10 +45,11 @@
#define PCM_CARD 0
#define PCM_DEVICE 0
-#define OUT_PERIOD_MS 10
+
+#define OUT_PERIOD_MS 15
#define OUT_PERIOD_COUNT 4
-#define IN_PERIOD_MS 10
+#define IN_PERIOD_MS 15
#define IN_PERIOD_COUNT 4
struct generic_audio_device {
@@ -738,8 +739,7 @@ static int refine_output_parameters(uint32_t *sample_rate, audio_format_t *forma
static int refine_input_parameters(uint32_t *sample_rate, audio_format_t *format, audio_channel_mask_t *channel_mask)
{
- // Crosvm only supports 48kHz streams for input
- static const uint32_t sample_rates [] = {48000};
+ static const uint32_t sample_rates [] = {8000, 11025, 16000, 22050, 44100, 48000};
static const int sample_rates_count = sizeof(sample_rates)/sizeof(uint32_t);
bool inval = false;
// Only PCM_16_bit is supported. If this is changed, stereo to mono drop
@@ -1322,12 +1322,6 @@ static char * adev_get_parameters(const struct audio_hw_device *dev,
return strdup("");
}
-static int adev_get_audio_port(struct audio_hw_device *dev,
- struct audio_port *port)
-{
- return 0;
-}
-
static int adev_init_check(const struct audio_hw_device *dev)
{
return 0;
@@ -1445,12 +1439,9 @@ static int adev_open_input_stream(struct audio_hw_device *dev,
struct generic_audio_device *adev = (struct generic_audio_device *)dev;
struct generic_stream_in *in;
int ret = 0;
- uint32_t orig_sample_rate = config->sample_rate;
- audio_format_t orig_audio_format = config->format;
- audio_channel_mask_t orig_channel_mask = config->channel_mask;
if (refine_input_parameters(&config->sample_rate, &config->format, &config->channel_mask)) {
ALOGE("Error opening input stream format %d, channel_mask %04x, sample_rate %u",
- orig_audio_format, orig_channel_mask, orig_sample_rate);
+ config->format, config->channel_mask, config->sample_rate);
ret = -EINVAL;
goto error;
}
@@ -1782,7 +1773,6 @@ static int adev_open(const hw_module_t* module, const char* name,
adev->device.get_mic_mute = adev_get_mic_mute;
adev->device.set_parameters = adev_set_parameters; // no op
adev->device.get_parameters = adev_get_parameters; // no op
- adev->device.get_audio_port = adev_get_audio_port; // no op
adev->device.get_input_buffer_size = adev_get_input_buffer_size;
adev->device.open_output_stream = adev_open_output_stream;
adev->device.close_output_stream = adev_close_output_stream;
diff --git a/guest/hals/bt/OWNERS b/guest/hals/bt/OWNERS
deleted file mode 100644
index e8a4a0030..000000000
--- a/guest/hals/bt/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-include platform/system/bt:/OWNERS
-jeongik@google.com \ No newline at end of file
diff --git a/guest/hals/bt/data/Android.bp b/guest/hals/bt/data/Android.bp
deleted file mode 100644
index 845223f1e..000000000
--- a/guest/hals/bt/data/Android.bp
+++ /dev/null
@@ -1,9 +0,0 @@
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-prebuilt_etc_host {
- name: "default_commands",
- src: "default_commands",
- sub_dir: "rootcanal/data",
-}
diff --git a/guest/hals/bt/data/default_commands b/guest/hals/bt/data/default_commands
deleted file mode 100644
index 918291584..000000000
--- a/guest/hals/bt/data/default_commands
+++ /dev/null
@@ -1,4 +0,0 @@
-add beacon be:ac:01:55:00:01 1000
-add_device_to_phy 0 1
-add beacon be:ac:01:55:00:02 1000
-add_device_to_phy 1 1 \ No newline at end of file
diff --git a/guest/hals/bt/remote/Android.bp b/guest/hals/bt/remote/Android.bp
deleted file mode 100644
index 5ad483ab4..000000000
--- a/guest/hals/bt/remote/Android.bp
+++ /dev/null
@@ -1,32 +0,0 @@
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-cc_binary {
- name: "android.hardware.bluetooth@1.1-service.remote",
- defaults: ["cuttlefish_guest_only", "hidl_defaults"],
- vendor: true,
- relative_install_path: "hw",
- srcs: [
- "remote_bluetooth.cpp",
- "service.cpp",
- ],
-
- shared_libs: [
- "android.hardware.bluetooth@1.0",
- "android.hardware.bluetooth@1.1",
- "libcuttlefish_fs",
- "libbase",
- "libhidlbase",
- "libutils",
- "liblog",
- "libcutils",
- "libprotobuf-cpp-lite",
- ],
- static_libs: [
- "libbt-rootcanal",
- "libbt-rootcanal-types",
- "async_fd_watcher",
- ],
- init_rc: ["android.hardware.bluetooth@1.1-service.remote.rc"],
-}
diff --git a/guest/hals/bt/remote/android.hardware.bluetooth@1.1-service.remote.rc b/guest/hals/bt/remote/android.hardware.bluetooth@1.1-service.remote.rc
deleted file mode 100644
index f4ed9e24b..000000000
--- a/guest/hals/bt/remote/android.hardware.bluetooth@1.1-service.remote.rc
+++ /dev/null
@@ -1,4 +0,0 @@
-service vendor.bluetooth-1-1 /vendor/bin/hw/android.hardware.bluetooth@1.1-service.remote
- class hal
- user bluetooth
- group bluetooth
diff --git a/guest/hals/bt/remote/remote_bluetooth.cpp b/guest/hals/bt/remote/remote_bluetooth.cpp
deleted file mode 100644
index dbcede306..000000000
--- a/guest/hals/bt/remote/remote_bluetooth.cpp
+++ /dev/null
@@ -1,195 +0,0 @@
-//
-// Copyright 2021 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-#define LOG_TAG "android.hardware.bluetooth@1.1.remote"
-
-#include "remote_bluetooth.h"
-
-#include <cutils/properties.h>
-#include <fcntl.h>
-#include <netdb.h>
-#include <netinet/in.h>
-#include <poll.h>
-#include <string.h>
-#include <sys/uio.h>
-#include <termios.h>
-#include <utils/Log.h>
-#include "log/log.h"
-
-namespace {
-int SetTerminalRaw(int fd) {
- termios terminal_settings;
- int rval = tcgetattr(fd, &terminal_settings);
- if (rval < 0) {
- return rval;
- }
- cfmakeraw(&terminal_settings);
- rval = tcsetattr(fd, TCSANOW, &terminal_settings);
- return rval;
-}
-} // namespace
-
-namespace android {
-namespace hardware {
-namespace bluetooth {
-namespace V1_1 {
-namespace remote {
-
-using ::android::hardware::hidl_vec;
-
-class BluetoothDeathRecipient : public hidl_death_recipient {
- public:
- BluetoothDeathRecipient(const sp<IBluetoothHci> hci) : mHci(hci) {}
-
- void serviceDied(
- uint64_t /* cookie */,
- const wp<::android::hidl::base::V1_0::IBase>& /* who */) override {
- LOG(ERROR)
- << "BluetoothDeathRecipient::serviceDied - Bluetooth service died";
- has_died_ = true;
- mHci->close();
- }
- sp<IBluetoothHci> mHci;
- bool getHasDied() const { return has_died_; }
- void setHasDied(bool has_died) { has_died_ = has_died; }
-
- private:
- bool has_died_;
-};
-
-BluetoothHci::BluetoothHci(const std::string& dev_path)
- : death_recipient_(new BluetoothDeathRecipient(this)),
- dev_path_(dev_path) {}
-
-Return<void> BluetoothHci::initialize(
- const sp<V1_0::IBluetoothHciCallbacks>& cb) {
- return initialize_impl(cb, nullptr);
-}
-
-Return<void> BluetoothHci::initialize_1_1(
- const sp<V1_1::IBluetoothHciCallbacks>& cb) {
- return initialize_impl(cb, cb);
-}
-
-Return<void> BluetoothHci::initialize_impl(
- const sp<V1_0::IBluetoothHciCallbacks>& cb,
- const sp<V1_1::IBluetoothHciCallbacks>& cb_1_1) {
- LOG(INFO) << __func__;
-
- cb_ = cb;
- cb_1_1_ = cb_1_1;
- fd_ = open(dev_path_.c_str(), O_RDWR);
- if (fd_ < 0) {
- LOG(FATAL) << "Could not connect to bt: " << fd_;
- }
- if (int ret = SetTerminalRaw(fd_) < 0) {
- LOG(FATAL) << "Could not make " << fd_ << " a raw terminal: " << ret;
- }
-
- if (cb == nullptr) {
- LOG(ERROR)
- << "cb == nullptr! -> Unable to call initializationComplete(ERR)";
- return Void();
- }
-
- death_recipient_->setHasDied(false);
- auto link_ret = cb->linkToDeath(death_recipient_, 0);
-
- unlink_cb_ = [this, cb](sp<BluetoothDeathRecipient>& death_recipient) {
- if (death_recipient->getHasDied())
- LOG(INFO) << "Skipping unlink call, service died.";
- else {
- auto ret = cb->unlinkToDeath(death_recipient);
- if (!ret.isOk()) {
- CHECK(death_recipient_->getHasDied())
- << "Error calling unlink, but no death notification.";
- }
- }
- };
-
- auto init_ret = cb->initializationComplete(V1_0::Status::SUCCESS);
- if (!init_ret.isOk()) {
- CHECK(death_recipient_->getHasDied())
- << "Error sending init callback, but no death notification.";
- }
- h4_ = test_vendor_lib::H4Packetizer(
- fd_,
- [](const std::vector<uint8_t>& /* raw_command */) {
- LOG_ALWAYS_FATAL("Unexpected command!");
- },
- [this](const std::vector<uint8_t>& raw_event) {
- cb_->hciEventReceived(hidl_vec<uint8_t>(raw_event));
- },
- [this](const std::vector<uint8_t>& raw_acl) {
- cb_->hciEventReceived(hidl_vec<uint8_t>(raw_acl));
- },
- [this](const std::vector<uint8_t>& raw_sco) {
- cb_->hciEventReceived(hidl_vec<uint8_t>(raw_sco));
- },
- [this](const std::vector<uint8_t>& raw_iso) {
- if (cb_1_1_) {
- cb_1_1_->hciEventReceived(hidl_vec<uint8_t>(raw_iso));
- }
- },
- []() { LOG(INFO) << "HCI socket device disconnected"; });
- fd_watcher_.WatchFdForNonBlockingReads(
- fd_, [this](int fd) { h4_.OnDataReady(fd); });
- return Void();
-}
-
-Return<void> BluetoothHci::close() {
- LOG(INFO) << __func__;
- fd_watcher_.StopWatchingFileDescriptors();
- ::close(fd_);
-
- return Void();
-}
-
-Return<void> BluetoothHci::sendHciCommand(const hidl_vec<uint8_t>& packet) {
- send(test_vendor_lib::PacketType::COMMAND, packet);
- return Void();
-}
-
-Return<void> BluetoothHci::sendAclData(const hidl_vec<uint8_t>& packet) {
- send(test_vendor_lib::PacketType::ACL, packet);
- return Void();
-}
-
-Return<void> BluetoothHci::sendScoData(const hidl_vec<uint8_t>& packet) {
- send(test_vendor_lib::PacketType::SCO, packet);
- return Void();
-}
-
-Return<void> BluetoothHci::sendIsoData(const hidl_vec<uint8_t>& packet) {
- send(test_vendor_lib::PacketType::ISO, packet);
- return Void();
-}
-
-void BluetoothHci::send(test_vendor_lib::PacketType type,
- const ::android::hardware::hidl_vec<uint8_t>& v) {
- h4_.Send(static_cast<uint8_t>(type), v.data(), v.size());
-}
-
-/* Fallback to shared library if there is no service. */
-IBluetoothHci* HIDL_FETCH_IBluetoothHci(const char* /* name */) {
- return new BluetoothHci();
-}
-
-} // namespace remote
-} // namespace V1_1
-} // namespace bluetooth
-} // namespace hardware
-} // namespace android
diff --git a/guest/hals/bt/remote/remote_bluetooth.h b/guest/hals/bt/remote/remote_bluetooth.h
deleted file mode 100644
index a7aa24cea..000000000
--- a/guest/hals/bt/remote/remote_bluetooth.h
+++ /dev/null
@@ -1,101 +0,0 @@
-//
-// Copyright 2021 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 <android/hardware/bluetooth/1.1/IBluetoothHci.h>
-
-#include <android-base/logging.h>
-#include <hidl/MQDescriptor.h>
-#include <string>
-#include "async_fd_watcher.h"
-#include "model/devices/h4_packetizer.h"
-
-namespace android {
-namespace hardware {
-namespace bluetooth {
-namespace V1_1 {
-namespace remote {
-
-class BluetoothDeathRecipient;
-
-// This Bluetooth HAL implementation is connected with the root-canal process in
-// the host side via virtio-console device(refer to dev_path_). It receives and
-// deliver responses and requests from/to Bluetooth HAL.
-class BluetoothHci : public IBluetoothHci {
- public:
- // virtio-console device connected with root-canal in the host side.
- BluetoothHci(const std::string& dev_path = "/dev/hvc5");
-
- ::android::hardware::Return<void> initialize(
- const sp<V1_0::IBluetoothHciCallbacks>& cb) override;
- ::android::hardware::Return<void> initialize_1_1(
- const sp<V1_1::IBluetoothHciCallbacks>& cb) override;
-
- ::android::hardware::Return<void> sendHciCommand(
- const ::android::hardware::hidl_vec<uint8_t>& packet) override;
-
- ::android::hardware::Return<void> sendAclData(
- const ::android::hardware::hidl_vec<uint8_t>& packet) override;
-
- ::android::hardware::Return<void> sendScoData(
- const ::android::hardware::hidl_vec<uint8_t>& packet) override;
-
- ::android::hardware::Return<void> sendIsoData(
- const ::android::hardware::hidl_vec<uint8_t>& packet) override;
-
- ::android::hardware::Return<void> close() override;
-
- static void OnPacketReady();
-
- static BluetoothHci* get();
-
- private:
- int fd_{-1};
- ::android::sp<V1_0::IBluetoothHciCallbacks> cb_ = nullptr;
- ::android::sp<V1_1::IBluetoothHciCallbacks> cb_1_1_ = nullptr;
-
- test_vendor_lib::H4Packetizer h4_{fd_,
- [](const std::vector<uint8_t>&) {},
- [](const std::vector<uint8_t>&) {},
- [](const std::vector<uint8_t>&) {},
- [](const std::vector<uint8_t>&) {},
- [](const std::vector<uint8_t>&) {},
- [] {}};
-
- ::android::hardware::Return<void> initialize_impl(
- const sp<V1_0::IBluetoothHciCallbacks>& cb,
- const sp<V1_1::IBluetoothHciCallbacks>& cb_1_1);
-
- sp<BluetoothDeathRecipient> death_recipient_;
-
- const std::string dev_path_;
-
- std::function<void(sp<BluetoothDeathRecipient>&)> unlink_cb_;
-
- ::android::hardware::bluetooth::async::AsyncFdWatcher fd_watcher_;
-
- void send(test_vendor_lib::PacketType type,
- const ::android::hardware::hidl_vec<uint8_t>& packet);
-};
-
-extern "C" IBluetoothHci* HIDL_FETCH_IBluetoothHci(const char* name);
-
-} // namespace remote
-} // namespace V1_1
-} // namespace bluetooth
-} // namespace hardware
-} // namespace android
diff --git a/guest/hals/bt/remote/service.cpp b/guest/hals/bt/remote/service.cpp
deleted file mode 100644
index 10ed3bc5a..000000000
--- a/guest/hals/bt/remote/service.cpp
+++ /dev/null
@@ -1,39 +0,0 @@
-//
-// Copyright 2021 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-#define LOG_TAG "android.hardware.bluetooth@1.1-service.remote"
-
-#include <android/hardware/bluetooth/1.1/IBluetoothHci.h>
-#include <hidl/HidlSupport.h>
-#include <hidl/HidlTransportSupport.h>
-
-#include "remote_bluetooth.h"
-
-using ::android::sp;
-using ::android::hardware::configureRpcThreadpool;
-using ::android::hardware::joinRpcThreadpool;
-using ::android::hardware::bluetooth::V1_1::IBluetoothHci;
-using ::android::hardware::bluetooth::V1_1::remote::BluetoothHci;
-
-int main(int /* argc */, char** /* argv */) {
- sp<IBluetoothHci> bluetooth = new BluetoothHci();
- configureRpcThreadpool(1, true);
- android::status_t status = bluetooth->registerAsService();
- if (status == android::OK)
- joinRpcThreadpool();
- else
- LOG(ERROR) << "Could not register as a service!";
-}
diff --git a/guest/hals/camera/Android.mk b/guest/hals/camera/Android.mk
new file mode 100644
index 000000000..994d82fa1
--- /dev/null
+++ b/guest/hals/camera/Android.mk
@@ -0,0 +1,182 @@
+# Copyright (C) 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+# Emulator camera module########################################################
+
+emulator_camera_module_relative_path := hw
+emulator_camera_cflags := -fno-short-enums $(VSOC_VERSION_CFLAGS)
+emulator_camera_cflags += \
+ -std=gnu++17 \
+ -Wall \
+ -Werror
+
+emulator_camera_shared_libraries := \
+ libbase \
+ libbinder \
+ libexif \
+ liblog \
+ libutils \
+ libcutils \
+ libui \
+ libdl \
+ libjpeg \
+ libcamera_metadata \
+ libhardware
+
+ifeq (0, $(shell test $(PLATFORM_SDK_VERSION) -lt 27; echo $$?))
+emulator_camera_shared_libraries += libcamera_client
+else
+emulator_camera_static_libraries += android.hardware.camera.common@1.0-helper
+endif
+
+ifeq (0, $(shell test $(PLATFORM_SDK_VERSION) -le 22; echo $$?))
+emulator_camera_shared_libraries += libjsoncpp
+else
+emulator_camera_static_libraries += libjsoncpp
+endif
+
+
+emulator_camera_static_libraries += android.hardware.camera.common@1.0-helper
+
+ifeq (0, $(shell test $(PLATFORM_SDK_VERSION) -le 26; echo $$?))
+emulator_camera_static_libraries += libyuv_static
+else
+emulator_camera_static_libraries += libyuv
+endif
+
+emulator_camera_c_includes := \
+ device/google/cuttlefish \
+ frameworks/native/include/media/hardware \
+ $(call include-path-for, camera) \
+
+emulator_camera_src := \
+ CameraConfiguration.cpp \
+ EmulatedCameraHal.cpp \
+ EmulatedCameraFactory.cpp \
+ EmulatedBaseCamera.cpp \
+ EmulatedCamera.cpp \
+ EmulatedCameraDevice.cpp \
+ EmulatedFakeCamera.cpp \
+ EmulatedFakeCameraDevice.cpp \
+ Exif.cpp \
+ Thumbnail.cpp \
+ Converters.cpp \
+ PreviewWindow.cpp \
+ CallbackNotifier.cpp \
+ JpegCompressor.cpp
+emulated_camera2_src := \
+ VSoCEmulatedCameraHotplugThread.cpp \
+ EmulatedCamera2.cpp \
+ EmulatedFakeCamera2.cpp \
+ fake-pipeline2/Scene.cpp \
+ fake-pipeline2/Sensor.cpp \
+ fake-pipeline2/JpegCompressor.cpp
+emulated_camera3_src := \
+ EmulatedCamera3.cpp \
+ EmulatedFakeCamera3.cpp
+
+
+emulated_camera2_stub_src := \
+ StubEmulatedCamera2.cpp \
+ StubEmulatedFakeCamera2.cpp
+
+enable_emulated_camera3 = $(shell test $(PLATFORM_SDK_VERSION) -ge 23 && echo yes)
+enable_emulated_camera2 = $(shell test $(PLATFORM_SDK_VERSION) -ge 19 && echo yes)
+
+# Emulated camera - cuttlefish / vbox_x86 build###################################
+#
+ifeq (0, $(shell test $(PLATFORM_SDK_VERSION) -ge 24; echo $$?))
+emulator_camera_c_includes += external/libjpeg-turbo
+else
+emulator_camera_c_includes += external/jpeg
+endif
+
+ifeq (0, $(shell test $(PLATFORM_SDK_VERSION) -ge 21; echo $$?))
+LOCAL_MODULE_RELATIVE_PATH := ${emulator_camera_module_relative_path}
+else
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/${emulator_camera_module_relative_path}
+endif
+ifeq (true, $(TARGET_TRANSLATE_2ND_ARCH))
+LOCAL_MULTILIB := first
+endif
+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} ${emulator_camera_ext_src} \
+ $(if $(enable_emulated_camera2),$(emulated_camera2_src),) \
+ $(if $(enable_emulated_camera3),$(emulated_camera3_src),)
+
+LOCAL_MODULE := camera.cutf
+LOCAL_MODULE_TAGS := optional
+LOCAL_VENDOR_MODULE := true
+
+include $(BUILD_SHARED_LIBRARY)
+
+# JPEG stub#####################################################################
+
+include $(CLEAR_VARS)
+
+jpeg_module_relative_path := hw
+jpeg_cflags := \
+ -fno-short-enums \
+ -Wall \
+ -Werror
+
+jpeg_shared_libraries := \
+ libcutils \
+ libexif \
+ liblog \
+ libjpeg \
+
+jpeg_c_includes := external/libexif \
+ frameworks/native/include
+ifeq (0, $(shell test $(PLATFORM_SDK_VERSION) -ge 24; echo $$?))
+jpeg_c_includes += external/libjpeg-turbo
+else
+jpeg_c_includes += external/jpeg
+endif
+
+jpeg_src := \
+ Compressor.cpp \
+ JpegStub.cpp \
+
+# JPEG stub - cuttlefish build####################################################
+
+ifeq (true, $(TARGET_TRANSLATE_2ND_ARCH))
+LOCAL_MULTILIB := first
+endif
+
+LOCAL_C_INCLUDES += ${jpeg_c_includes}
+LOCAL_SRC_FILES := ${jpeg_src}
+
+LOCAL_MODULE_RELATIVE_PATH := ${jpeg_module_relative_path}
+LOCAL_CFLAGS += ${jpeg_cflags}
+
+LOCAL_SHARED_LIBRARIES := ${jpeg_shared_libraries}
+
+LOCAL_C_INCLUDES += ${jpeg_c_includes}
+LOCAL_SRC_FILES := ${jpeg_src}
+
+LOCAL_MODULE := camera.cutf.jpeg
+LOCAL_MODULE_TAGS := optional
+LOCAL_VENDOR_MODULE := true
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/guest/hals/camera/CallbackNotifier.cpp b/guest/hals/camera/CallbackNotifier.cpp
new file mode 100644
index 000000000..765d4e7d9
--- /dev/null
+++ b/guest/hals/camera/CallbackNotifier.cpp
@@ -0,0 +1,313 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+/*
+ * Contains implementation of a class CallbackNotifier that manages callbacks
+ * set via set_callbacks, enable_msg_type, and disable_msg_type camera HAL API.
+ */
+
+#define LOG_NDEBUG 0
+#define LOG_TAG "EmulatedCamera_CallbackNotifier"
+#include "CallbackNotifier.h"
+#include <MetadataBufferType.h>
+#include <log/log.h>
+#include "EmulatedCameraDevice.h"
+#include "JpegCompressor.h"
+#include "Exif.h"
+#include "Thumbnail.h"
+
+namespace android {
+
+/* String representation of camera messages. */
+static const char* lCameraMessages[] = {"CAMERA_MSG_ERROR",
+ "CAMERA_MSG_SHUTTER",
+ "CAMERA_MSG_FOCUS",
+ "CAMERA_MSG_ZOOM",
+ "CAMERA_MSG_PREVIEW_FRAME",
+ "CAMERA_MSG_VIDEO_FRAME",
+ "CAMERA_MSG_POSTVIEW_FRAME",
+ "CAMERA_MSG_RAW_IMAGE",
+ "CAMERA_MSG_COMPRESSED_IMAGE",
+ "CAMERA_MSG_RAW_IMAGE_NOTIFY",
+ "CAMERA_MSG_PREVIEW_METADATA"};
+static const int lCameraMessagesNum = sizeof(lCameraMessages) / sizeof(char*);
+
+/* Builds an array of strings for the given set of messages.
+ * Param:
+ * msg - Messages to get strings for,
+ * strings - Array where to save strings
+ * max - Maximum number of entries in the array.
+ * Return:
+ * Number of strings saved into the 'strings' array.
+ */
+static int GetMessageStrings(uint32_t msg, const char** strings, int max) {
+ int index = 0;
+ int out = 0;
+ while (msg != 0 && out < max && index < lCameraMessagesNum) {
+ while ((msg & 0x1) == 0 && index < lCameraMessagesNum) {
+ msg >>= 1;
+ index++;
+ }
+ if ((msg & 0x1) != 0 && index < lCameraMessagesNum) {
+ strings[out] = lCameraMessages[index];
+ out++;
+ msg >>= 1;
+ index++;
+ }
+ }
+
+ return out;
+}
+
+/* Logs messages, enabled by the mask. */
+static void PrintMessages(uint32_t msg) {
+ const char* strs[lCameraMessagesNum];
+ const int translated = GetMessageStrings(msg, strs, lCameraMessagesNum);
+ for (int n = 0; n < translated; n++) {
+ ALOGV(" %s", strs[n]);
+ }
+}
+
+CallbackNotifier::CallbackNotifier()
+ : mNotifyCB(NULL),
+ mDataCB(NULL),
+ mDataCBTimestamp(NULL),
+ mGetMemoryCB(NULL),
+ mCBOpaque(NULL),
+ mLastFrameTimestamp(0),
+ mFrameRefreshFreq(0),
+ mMessageEnabler(0),
+ mJpegQuality(90),
+ mVideoRecEnabled(false),
+ mTakingPicture(false) {}
+
+CallbackNotifier::~CallbackNotifier() {}
+
+/****************************************************************************
+ * Camera API
+ ***************************************************************************/
+
+void CallbackNotifier::setCallbacks(
+ camera_notify_callback notify_cb, camera_data_callback data_cb,
+ camera_data_timestamp_callback data_cb_timestamp,
+ camera_request_memory get_memory, void* user) {
+ ALOGV("%s: %p, %p, %p, %p (%p)", __FUNCTION__, notify_cb, data_cb,
+ data_cb_timestamp, get_memory, user);
+
+ Mutex::Autolock locker(&mObjectLock);
+ mNotifyCB = notify_cb;
+ mDataCB = data_cb;
+ mDataCBTimestamp = data_cb_timestamp;
+ mGetMemoryCB = get_memory;
+ mCBOpaque = user;
+}
+
+void CallbackNotifier::enableMessage(uint msg_type) {
+ ALOGV("%s: msg_type = 0x%x", __FUNCTION__, msg_type);
+ PrintMessages(msg_type);
+
+ Mutex::Autolock locker(&mObjectLock);
+ mMessageEnabler |= msg_type;
+ ALOGV("**** Currently enabled messages:");
+ PrintMessages(mMessageEnabler);
+}
+
+void CallbackNotifier::disableMessage(uint msg_type) {
+ ALOGV("%s: msg_type = 0x%x", __FUNCTION__, msg_type);
+ PrintMessages(msg_type);
+
+ Mutex::Autolock locker(&mObjectLock);
+ mMessageEnabler &= ~msg_type;
+ ALOGV("**** Currently enabled messages:");
+ PrintMessages(mMessageEnabler);
+}
+
+status_t CallbackNotifier::enableVideoRecording(int fps) {
+ ALOGV("%s: FPS = %d", __FUNCTION__, fps);
+
+ Mutex::Autolock locker(&mObjectLock);
+ mVideoRecEnabled = true;
+ mLastFrameTimestamp = 0;
+ mFrameRefreshFreq = 1000000000LL / fps;
+
+ return NO_ERROR;
+}
+
+void CallbackNotifier::disableVideoRecording() {
+ ALOGV("%s:", __FUNCTION__);
+
+ Mutex::Autolock locker(&mObjectLock);
+ mVideoRecEnabled = false;
+ mLastFrameTimestamp = 0;
+ mFrameRefreshFreq = 0;
+}
+
+void CallbackNotifier::releaseRecordingFrame(const void* opaque) {
+ List<camera_memory_t*>::iterator it = mCameraMemoryTs.begin();
+ for (; it != mCameraMemoryTs.end(); ++it) {
+ if ((*it)->data == opaque) {
+ (*it)->release(*it);
+ mCameraMemoryTs.erase(it);
+ break;
+ }
+ }
+}
+
+status_t CallbackNotifier::storeMetaDataInBuffers(bool enable) {
+ // Return error if metadata is request, otherwise silently agree.
+ return enable ? INVALID_OPERATION : NO_ERROR;
+}
+
+/****************************************************************************
+ * Public API
+ ***************************************************************************/
+
+void CallbackNotifier::cleanupCBNotifier() {
+ Mutex::Autolock locker(&mObjectLock);
+ mMessageEnabler = 0;
+ mNotifyCB = NULL;
+ mDataCB = NULL;
+ mDataCBTimestamp = NULL;
+ mGetMemoryCB = NULL;
+ mCBOpaque = NULL;
+ mLastFrameTimestamp = 0;
+ mFrameRefreshFreq = 0;
+ mJpegQuality = 90;
+ mVideoRecEnabled = false;
+ mTakingPicture = false;
+}
+
+void CallbackNotifier::onNextFrameAvailable(const void* frame,
+ nsecs_t timestamp,
+ EmulatedCameraDevice* camera_dev) {
+ if (isMessageEnabled(CAMERA_MSG_VIDEO_FRAME) && isVideoRecordingEnabled() &&
+ isNewVideoFrameTime(timestamp)) {
+ camera_memory_t* cam_buff =
+ mGetMemoryCB(-1, camera_dev->getFrameBufferSize(), 1, mCBOpaque);
+ if (NULL != cam_buff && NULL != cam_buff->data) {
+ memcpy(cam_buff->data, frame, camera_dev->getFrameBufferSize());
+ mDataCBTimestamp(timestamp, CAMERA_MSG_VIDEO_FRAME, cam_buff, 0,
+ mCBOpaque);
+
+ mCameraMemoryTs.push_back(cam_buff);
+ } else {
+ ALOGE("%s: Memory failure in CAMERA_MSG_VIDEO_FRAME", __FUNCTION__);
+ }
+ }
+
+ if (isMessageEnabled(CAMERA_MSG_PREVIEW_FRAME)) {
+ camera_memory_t* cam_buff =
+ mGetMemoryCB(-1, camera_dev->getFrameBufferSize(), 1, mCBOpaque);
+ if (NULL != cam_buff && NULL != cam_buff->data) {
+ memcpy(cam_buff->data, frame, camera_dev->getFrameBufferSize());
+ mDataCB(CAMERA_MSG_PREVIEW_FRAME, cam_buff, 0, NULL, mCBOpaque);
+ cam_buff->release(cam_buff);
+ } else {
+ ALOGE("%s: Memory failure in CAMERA_MSG_PREVIEW_FRAME", __FUNCTION__);
+ }
+ }
+
+ if (mTakingPicture) {
+ /* This happens just once. */
+ mTakingPicture = false;
+ /* The sequence of callbacks during picture taking is:
+ * - CAMERA_MSG_SHUTTER
+ * - CAMERA_MSG_RAW_IMAGE_NOTIFY
+ * - CAMERA_MSG_COMPRESSED_IMAGE
+ */
+ if (isMessageEnabled(CAMERA_MSG_SHUTTER)) {
+ mNotifyCB(CAMERA_MSG_SHUTTER, 0, 0, mCBOpaque);
+ }
+ if (isMessageEnabled(CAMERA_MSG_RAW_IMAGE_NOTIFY)) {
+ mNotifyCB(CAMERA_MSG_RAW_IMAGE_NOTIFY, 0, 0, mCBOpaque);
+ }
+ if (isMessageEnabled(CAMERA_MSG_COMPRESSED_IMAGE)) {
+ /* Compress the frame to JPEG. Note that when taking pictures, we
+ * have requested camera device to provide us with NV21 frames. */
+ NV21JpegCompressor compressor;
+ const CameraParameters* cameraParameters = camera_dev->getCameraParameters();
+ if (cameraParameters == nullptr) {
+ ALOGE("%s: Could not get camera parameters to take picture.", __FUNCTION__);
+ return;
+ }
+
+ ExifData* exifData = createExifData(*cameraParameters);
+
+ // Create a thumbnail and place the pointer and size in the EXIF
+ // data structure. This transfers ownership to the EXIF data and
+ // the memory will be deallocated in the freeExifData call below.
+ int width = camera_dev->getFrameWidth();
+ int height = camera_dev->getFrameHeight();
+ int thumbWidth = cameraParameters->getInt(
+ CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH);
+ int thumbHeight = cameraParameters->getInt(
+ CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT);
+ if (thumbWidth > 0 && thumbHeight > 0) {
+ if (!createThumbnail(static_cast<const unsigned char*>(frame),
+ width, height, thumbWidth, thumbHeight,
+ mJpegQuality, exifData)) {
+ // Not really a fatal error, we'll just keep going
+ ALOGE("%s: Failed to create thumbnail for image",
+ __FUNCTION__);
+ }
+ }
+
+ status_t res = compressor.compressRawImage(frame, exifData, mJpegQuality, width, height);
+ if (res == NO_ERROR) {
+ camera_memory_t* jpeg_buff =
+ mGetMemoryCB(-1, compressor.getCompressedSize(), 1, mCBOpaque);
+ if (NULL != jpeg_buff && NULL != jpeg_buff->data) {
+ compressor.getCompressedImage(jpeg_buff->data);
+ mDataCB(CAMERA_MSG_COMPRESSED_IMAGE, jpeg_buff, 0, NULL, mCBOpaque);
+ jpeg_buff->release(jpeg_buff);
+ } else {
+ ALOGE("%s: Memory failure in CAMERA_MSG_VIDEO_FRAME", __FUNCTION__);
+ }
+ } else {
+ ALOGE("%s: Compression failure in CAMERA_MSG_VIDEO_FRAME",
+ __FUNCTION__);
+ }
+ freeExifData(exifData);
+ }
+ }
+}
+
+void CallbackNotifier::onCameraDeviceError(int err) {
+ if (isMessageEnabled(CAMERA_MSG_ERROR) && mNotifyCB != NULL) {
+ mNotifyCB(CAMERA_MSG_ERROR, err, 0, mCBOpaque);
+ }
+}
+
+void CallbackNotifier::onCameraFocusAcquired() {
+ if (isMessageEnabled(CAMERA_MSG_FOCUS) && mNotifyCB != NULL) {
+ mNotifyCB(CAMERA_MSG_FOCUS, 1, 0, mCBOpaque);
+ }
+}
+
+/****************************************************************************
+ * Private API
+ ***************************************************************************/
+
+bool CallbackNotifier::isNewVideoFrameTime(nsecs_t timestamp) {
+ Mutex::Autolock locker(&mObjectLock);
+ if ((timestamp - mLastFrameTimestamp) >= mFrameRefreshFreq) {
+ mLastFrameTimestamp = timestamp;
+ return true;
+ }
+ return false;
+}
+
+}; /* namespace android */
diff --git a/guest/hals/camera/CallbackNotifier.h b/guest/hals/camera/CallbackNotifier.h
new file mode 100644
index 000000000..38a59798c
--- /dev/null
+++ b/guest/hals/camera/CallbackNotifier.h
@@ -0,0 +1,233 @@
+/*
+ * Copyright (C) 2011 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 HW_EMULATOR_CAMERA_CALLBACK_NOTIFIER_H
+#define HW_EMULATOR_CAMERA_CALLBACK_NOTIFIER_H
+
+/*
+ * Contains declaration of a class CallbackNotifier that manages callbacks set
+ * via set_callbacks, enable_msg_type, and disable_msg_type camera HAL API.
+ */
+
+#include <hardware/camera.h>
+#include <utils/List.h>
+#include <utils/Mutex.h>
+#include <utils/Timers.h>
+
+namespace android {
+
+class EmulatedCameraDevice;
+
+/* Manages callbacks set via set_callbacks, enable_msg_type, and
+ * disable_msg_type camera HAL API.
+ *
+ * Objects of this class are contained in EmulatedCamera objects, and handle
+ * relevant camera API callbacks.
+ * Locking considerations. Apparently, it's not allowed to call callbacks
+ * registered in this class, while holding a lock: recursion is quite possible,
+ * which will cause a deadlock.
+ */
+class CallbackNotifier {
+ public:
+ /* Constructs CallbackNotifier instance. */
+ CallbackNotifier();
+
+ /* Destructs CallbackNotifier instance. */
+ ~CallbackNotifier();
+
+ /****************************************************************************
+ * Camera API
+ ***************************************************************************/
+
+ public:
+ /* Actual handler for camera_device_ops_t::set_callbacks callback.
+ * This method is called by the containing emulated camera object when it is
+ * handing the camera_device_ops_t::set_callbacks callback.
+ */
+ void setCallbacks(camera_notify_callback notify_cb,
+ camera_data_callback data_cb,
+ camera_data_timestamp_callback data_cb_timestamp,
+ camera_request_memory get_memory, void* user);
+
+ /* Actual handler for camera_device_ops_t::enable_msg_type callback.
+ * This method is called by the containing emulated camera object when it is
+ * handing the camera_device_ops_t::enable_msg_type callback.
+ */
+ void enableMessage(uint msg_type);
+
+ /* Actual handler for camera_device_ops_t::disable_msg_type callback.
+ * This method is called by the containing emulated camera object when it is
+ * handing the camera_device_ops_t::disable_msg_type callback.
+ */
+ void disableMessage(uint msg_type);
+
+ /* Actual handler for camera_device_ops_t::store_meta_data_in_buffers
+ * callback. This method is called by the containing emulated camera object
+ * when it is handing the camera_device_ops_t::store_meta_data_in_buffers
+ * callback.
+ * Return:
+ * NO_ERROR on success, or an appropriate error status.
+ */
+ status_t storeMetaDataInBuffers(bool enable);
+
+ /* Enables video recording.
+ * This method is called by the containing emulated camera object when it is
+ * handing the camera_device_ops_t::start_recording callback.
+ * Param:
+ * fps - Video frame frequency. This parameter determins when a frame
+ * received via onNextFrameAvailable call will be pushed through the
+ * callback.
+ * Return:
+ * NO_ERROR on success, or an appropriate error status.
+ */
+ status_t enableVideoRecording(int fps);
+
+ /* Disables video recording.
+ * This method is called by the containing emulated camera object when it is
+ * handing the camera_device_ops_t::stop_recording callback.
+ */
+ void disableVideoRecording();
+
+ /* Releases video frame, sent to the framework.
+ * This method is called by the containing emulated camera object when it is
+ * handing the camera_device_ops_t::release_recording_frame callback.
+ */
+ void releaseRecordingFrame(const void* opaque);
+
+ /* Actual handler for camera_device_ops_t::msg_type_enabled callback.
+ * This method is called by the containing emulated camera object when it is
+ * handing the camera_device_ops_t::msg_type_enabled callback.
+ * Note: this method doesn't grab a lock while checking message status, since
+ * upon exit the status would be undefined anyway. So, grab a lock before
+ * calling this method if you care about persisting a defined message status.
+ * Return:
+ * 0 if message is disabled, or non-zero value, if message is enabled.
+ */
+ inline int isMessageEnabled(uint msg_type) {
+ return mMessageEnabler & msg_type;
+ }
+
+ /* Checks id video recording is enabled.
+ * This method is called by the containing emulated camera object when it is
+ * handing the camera_device_ops_t::recording_enabled callback.
+ * Note: this method doesn't grab a lock while checking video recordin status,
+ * since upon exit the status would be undefined anyway. So, grab a lock
+ * before calling this method if you care about persisting of a defined video
+ * recording status.
+ * Return:
+ * true if video recording is enabled, or false if it is disabled.
+ */
+ inline bool isVideoRecordingEnabled() { return mVideoRecEnabled; }
+
+ /****************************************************************************
+ * Public API
+ ***************************************************************************/
+
+ public:
+ /* Resets the callback notifier. */
+ void cleanupCBNotifier();
+
+ /* Next frame is available in the camera device.
+ * This is a notification callback that is invoked by the camera device when
+ * a new frame is available.
+ * Note that most likely this method is called in context of a worker thread
+ * that camera device has created for frame capturing.
+ * Param:
+ * frame - Captured frame, or NULL if camera device didn't pull the frame
+ * yet. If NULL is passed in this parameter use GetCurrentFrame method
+ * of the camera device class to obtain the next frame. Also note that
+ * the size of the frame that is passed here (as well as the frame
+ * returned from the GetCurrentFrame method) is defined by the current
+ * frame settings (width + height + pixel format) for the camera device.
+ * timestamp - Frame's timestamp.
+ * camera_dev - Camera device instance that delivered the frame.
+ */
+ void onNextFrameAvailable(const void* frame, nsecs_t timestamp,
+ EmulatedCameraDevice* camera_dev);
+
+ /* Entry point for notifications that occur in camera device.
+ * Param:
+ * err - CAMERA_ERROR_XXX error code.
+ */
+ void onCameraDeviceError(int err);
+
+ /* Reports focus operation completion to camera client.
+ */
+ void onCameraFocusAcquired();
+
+ /* Sets, or resets taking picture state.
+ * This state control whether or not to notify the framework about compressed
+ * image, shutter, and other picture related events.
+ */
+ void setTakingPicture(bool taking) { mTakingPicture = taking; }
+
+ /* Sets JPEG quality used to compress frame during picture taking. */
+ void setJpegQuality(int jpeg_quality) { mJpegQuality = jpeg_quality; }
+
+ /****************************************************************************
+ * Private API
+ ***************************************************************************/
+
+ protected:
+ /* Checks if it's time to push new video frame.
+ * Note that this method must be called while object is locked.
+ * Param:
+ * timestamp - Timestamp for the new frame. */
+ bool isNewVideoFrameTime(nsecs_t timestamp);
+
+ /****************************************************************************
+ * Data members
+ ***************************************************************************/
+
+ protected:
+ /* Locks this instance for data change. */
+ Mutex mObjectLock;
+
+ /*
+ * Callbacks, registered in set_callbacks.
+ */
+
+ camera_notify_callback mNotifyCB;
+ camera_data_callback mDataCB;
+ camera_data_timestamp_callback mDataCBTimestamp;
+ camera_request_memory mGetMemoryCB;
+ void* mCBOpaque;
+
+ /* video frame queue for the CameraHeapMemory destruction */
+ List<camera_memory_t*> mCameraMemoryTs;
+
+ /* Timestamp when last frame has been delivered to the framework. */
+ nsecs_t mLastFrameTimestamp;
+
+ /* Video frequency in nanosec. */
+ nsecs_t mFrameRefreshFreq;
+
+ /* Message enabler. */
+ uint32_t mMessageEnabler;
+
+ /* JPEG quality used to compress frame during picture taking. */
+ int mJpegQuality;
+
+ /* Video recording status. */
+ bool mVideoRecEnabled;
+
+ /* Picture taking status. */
+ bool mTakingPicture;
+};
+
+}; /* namespace android */
+
+#endif /* HW_EMULATOR_CAMERA_CALLBACK_NOTIFIER_H */
diff --git a/guest/hals/camera/CameraConfiguration.cpp b/guest/hals/camera/CameraConfiguration.cpp
new file mode 100644
index 000000000..32ac3327e
--- /dev/null
+++ b/guest/hals/camera/CameraConfiguration.cpp
@@ -0,0 +1,300 @@
+/*
+ * 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 "CameraConfiguration.h"
+
+#define LOG_TAG "CameraConfiguration"
+
+#include <android-base/file.h>
+#include <android-base/strings.h>
+#include <log/log.h>
+#include <json/json.h>
+#include <json/reader.h>
+#include <stdlib.h>
+
+namespace cvd {
+namespace {
+////////////////////// Device Personality keys //////////////////////
+//
+// **** Camera ****
+//
+// Example segment (transcribed to constants):
+//
+// kCameraDefinitionsKey: [
+// {
+// kCameraDefinitionOrientationKey: "front",
+// kCameraDefinitionHalVersionKey: "1",
+// kCameraDefinitionResolutionsKey: [
+// {
+// kCameraDefinitionResolutionWidthKey: "1600",
+// kCameraDefinitionResolutionHeightKey: "1200",
+// },
+// {
+// kCameraDefinitionResolutionWidthKey: "1280",
+// kCameraDefinitionResolutionHeightKey: "800",
+// }
+// ]
+// },
+// {
+// kCameraDefinitionOrientationKey: "back",
+// kCameraDefinitionHalVersionKey: "1",
+// kCameraDefinitionResolutionsKey: [
+// {
+// kCameraDefinitionResolutionWidthKey: "1024",
+// kCameraDefinitionResolutionHeightKey: "768",
+// },
+// {
+// kCameraDefinitionResolutionWidthKey: "800",
+// kCameraDefinitionResolutionHeightKey: "600",
+// }
+// ]
+// }
+// ]
+//
+
+// Location of the camera configuration files.
+const char* const kConfigurationFileLocation = "/vendor/etc/config/camera.json";
+
+//
+// Array of camera definitions for all cameras available on the device (array).
+// Top Level Key.
+const char* const kCameraDefinitionsKey = "camera_definitions";
+
+// Camera orientation of currently defined camera (string).
+// Currently supported values:
+// - "back",
+// - "front".
+const char* const kCameraDefinitionOrientationKey = "orientation";
+
+// Camera HAL version of currently defined camera (int).
+// Currently supported values:
+// - 1 (Camera HALv1)
+// - 2 (Camera HALv2)
+// - 3 (Camera HALv3)
+const char* const kCameraDefinitionHalVersionKey = "hal_version";
+
+// Array of resolutions supported by camera (array).
+const char* const kCameraDefinitionResolutionsKey = "resolutions";
+
+// Width of currently defined resolution (int).
+// Must be divisible by 8.
+const char* const kCameraDefinitionResolutionWidthKey = "width";
+
+// Height of currently defined resolution (int).
+// Must be divisible by 8.
+const char* const kCameraDefinitionResolutionHeightKey = "height";
+
+// Convert string value to camera orientation.
+bool ValueToCameraOrientation(const std::string& value,
+ CameraDefinition::Orientation* orientation) {
+ if (value == "back") {
+ *orientation = CameraDefinition::kBack;
+ return true;
+ } else if (value == "front") {
+ *orientation = CameraDefinition::kFront;
+ return true;
+ }
+ ALOGE("%s: Invalid camera orientation: %s.", __FUNCTION__, value.c_str());
+ return false;
+}
+
+// Convert string value to camera HAL version.
+bool ValueToCameraHalVersion(const std::string& value,
+ CameraDefinition::HalVersion* hal_version) {
+ int temp;
+ char* endptr;
+
+ temp = strtol(value.c_str(), &endptr, 10);
+ if (endptr != value.c_str() + value.size()) {
+ ALOGE("%s: Invalid camera HAL version. Expected number, got %s.",
+ __FUNCTION__, value.c_str());
+ return false;
+ }
+
+ switch (temp) {
+ case 1:
+ *hal_version = CameraDefinition::kHalV1;
+ break;
+
+ case 2:
+ *hal_version = CameraDefinition::kHalV2;
+ break;
+
+ case 3:
+ *hal_version = CameraDefinition::kHalV3;
+ break;
+
+ default:
+ ALOGE("%s: Invalid camera HAL version. Version %d not supported.",
+ __FUNCTION__, temp);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValueToCameraResolution(const std::string& width,
+ const std::string& height,
+ CameraDefinition::Resolution* resolution) {
+ char* endptr;
+
+ resolution->width = strtol(width.c_str(), &endptr, 10);
+ if (endptr != width.c_str() + width.size()) {
+ ALOGE("%s: Invalid camera resolution width. Expected number, got %s.",
+ __FUNCTION__, width.c_str());
+ return false;
+ }
+
+ resolution->height = strtol(height.c_str(), &endptr, 10);
+ if (endptr != height.c_str() + height.size()) {
+ ALOGE("%s: Invalid camera resolution height. Expected number, got %s.",
+ __FUNCTION__, height.c_str());
+ return false;
+ }
+
+ // Validate width and height parameters are sane.
+ if (resolution->width <= 0 || resolution->height <= 0) {
+ ALOGE("%s: Invalid camera resolution: %dx%d", __FUNCTION__,
+ resolution->width, resolution->height);
+ return false;
+ }
+
+ // Validate width and height divisible by 8.
+ if ((resolution->width & 7) != 0 || (resolution->height & 7) != 0) {
+ ALOGE(
+ "%s: Invalid camera resolution: width and height must be "
+ "divisible by 8, got %dx%d (%dx%d).",
+ __FUNCTION__, resolution->width, resolution->height,
+ resolution->width & 7, resolution->height & 7);
+ return false;
+ }
+
+ return true;
+}
+
+// Process camera definitions.
+// Returns true, if definitions were sane.
+bool ConfigureCameras(const Json::Value& value,
+ std::vector<CameraDefinition>* cameras) {
+ if (!value.isObject()) {
+ ALOGE("%s: Configuration root is not an object", __FUNCTION__);
+ return false;
+ }
+
+ if (!value.isMember(kCameraDefinitionsKey)) return true;
+ for (Json::ValueConstIterator iter = value[kCameraDefinitionsKey].begin();
+ iter != value[kCameraDefinitionsKey].end(); ++iter) {
+ cameras->push_back(CameraDefinition());
+ CameraDefinition& camera = cameras->back();
+
+ if (!iter->isObject()) {
+ ALOGE("%s: Camera definition is not an object", __FUNCTION__);
+ continue;
+ }
+
+ // Camera without orientation -> invalid setting.
+ if (!iter->isMember(kCameraDefinitionOrientationKey)) {
+ ALOGE("%s: Invalid camera definition: key %s is missing.", __FUNCTION__,
+ kCameraDefinitionOrientationKey);
+ return false;
+ }
+
+ if (!ValueToCameraOrientation(
+ (*iter)[kCameraDefinitionOrientationKey].asString(),
+ &camera.orientation))
+ return false;
+
+ // Camera without HAL version -> invalid setting.
+ if (!(*iter).isMember(kCameraDefinitionHalVersionKey)) {
+ ALOGE("%s: Invalid camera definition: key %s is missing.", __FUNCTION__,
+ kCameraDefinitionHalVersionKey);
+ return false;
+ }
+
+ if (!ValueToCameraHalVersion(
+ (*iter)[kCameraDefinitionHalVersionKey].asString(),
+ &camera.hal_version))
+ return false;
+
+ // Camera without resolutions -> invalid setting.
+ if (!iter->isMember(kCameraDefinitionResolutionsKey)) {
+ ALOGE("%s: Invalid camera definition: key %s is missing.", __FUNCTION__,
+ kCameraDefinitionResolutionsKey);
+ return false;
+ }
+
+ const Json::Value& json_resolutions =
+ (*iter)[kCameraDefinitionResolutionsKey];
+
+ // Resolutions not an array, or an empty array -> invalid setting.
+ if (!json_resolutions.isArray() || json_resolutions.empty()) {
+ ALOGE("%s: Invalid camera definition: %s is not an array or is empty.",
+ __FUNCTION__, kCameraDefinitionResolutionsKey);
+ return false;
+ }
+
+ // Process all resolutions.
+ for (Json::ValueConstIterator json_res_iter = json_resolutions.begin();
+ json_res_iter != json_resolutions.end(); ++json_res_iter) {
+ // Check presence of width and height keys.
+ if (!json_res_iter->isObject()) {
+ ALOGE("%s: Camera resolution item is not an object", __FUNCTION__);
+ continue;
+ }
+ if (!json_res_iter->isMember(kCameraDefinitionResolutionWidthKey) ||
+ !json_res_iter->isMember(kCameraDefinitionResolutionHeightKey)) {
+ ALOGE(
+ "%s: Invalid camera resolution: keys %s and %s are both required.",
+ __FUNCTION__, kCameraDefinitionResolutionWidthKey,
+ kCameraDefinitionResolutionHeightKey);
+ return false;
+ }
+
+ camera.resolutions.push_back(CameraDefinition::Resolution());
+ CameraDefinition::Resolution& resolution = camera.resolutions.back();
+
+ if (!ValueToCameraResolution(
+ (*json_res_iter)[kCameraDefinitionResolutionWidthKey].asString(),
+ (*json_res_iter)[kCameraDefinitionResolutionHeightKey].asString(),
+ &resolution))
+ return false;
+ }
+ }
+
+ return true;
+}
+} // namespace
+
+bool CameraConfiguration::Init() {
+ cameras_.clear();
+ std::string config;
+ if (!android::base::ReadFileToString(kConfigurationFileLocation, &config)) {
+ ALOGE("%s: Could not open configuration file: %s", __FUNCTION__,
+ kConfigurationFileLocation);
+ return false;
+ }
+
+ Json::Reader config_reader;
+ Json::Value root;
+ if (!config_reader.parse(config, root)) {
+ ALOGE("Could not parse configuration file: %s",
+ config_reader.getFormattedErrorMessages().c_str());
+ return false;
+ }
+
+ return ConfigureCameras(root, &cameras_);
+}
+
+} // namespace cvd
diff --git a/guest/hals/camera/CameraConfiguration.h b/guest/hals/camera/CameraConfiguration.h
new file mode 100644
index 000000000..983963b1f
--- /dev/null
+++ b/guest/hals/camera/CameraConfiguration.h
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+#ifndef GUEST_HALS_CAMERA_CAMERACONFIGURATION_H_
+#define GUEST_HALS_CAMERA_CAMERACONFIGURATION_H_
+
+#undef max
+#undef min
+#include <algorithm>
+#include <vector>
+
+namespace cvd {
+
+// Camera properties and features.
+struct CameraDefinition {
+ // Camera facing direction.
+ enum Orientation { kFront, kBack };
+
+ // Camera recognized HAL versions.
+ enum HalVersion { kHalV1, kHalV2, kHalV3 };
+
+ struct Resolution {
+ int width;
+ int height;
+ };
+
+ Orientation orientation;
+ HalVersion hal_version;
+ std::vector<Resolution> resolutions;
+};
+
+class CameraConfiguration {
+ public:
+ CameraConfiguration() {}
+ ~CameraConfiguration() {}
+
+ const std::vector<CameraDefinition>& cameras() const { return cameras_; }
+
+ bool Init();
+
+ private:
+ std::vector<CameraDefinition> cameras_;
+};
+
+} // namespace cvd
+
+#endif // GUEST_HALS_CAMERA_CAMERACONFIGURATION_H_
diff --git a/guest/hals/camera/Compressor.cpp b/guest/hals/camera/Compressor.cpp
new file mode 100644
index 000000000..3fe0bd6c3
--- /dev/null
+++ b/guest/hals/camera/Compressor.cpp
@@ -0,0 +1,234 @@
+/*
+* Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Compressor.h"
+
+#define LOG_NDEBUG 0
+#define LOG_TAG "EmulatedCamera_JPEGStub_Compressor"
+#include <log/log.h>
+#include <libexif/exif-data.h>
+
+Compressor::Compressor() {
+
+}
+
+bool Compressor::compress(const unsigned char* data,
+ int width, int height, int quality,
+ ExifData* exifData) {
+ if (!configureCompressor(width, height, quality)) {
+ // The method will have logged a more detailed error message than we can
+ // provide here so just return.
+ return false;
+ }
+
+ return compressData(data, exifData);
+}
+
+const std::vector<uint8_t>& Compressor::getCompressedData() const {
+ return mDestManager.mBuffer;
+}
+
+bool Compressor::configureCompressor(int width, int height, int quality) {
+ mCompressInfo.err = jpeg_std_error(&mErrorManager);
+ // NOTE! DANGER! Do not construct any non-trivial objects below setjmp!
+ // The compiler will not generate code to destroy them during the return
+ // below so they will leak. Additionally, do not place any calls to libjpeg
+ // that can fail above this line or any error will cause undefined behavior.
+ if (setjmp(mErrorManager.mJumpBuffer)) {
+ // This is where the error handler will jump in case setup fails
+ // The error manager will ALOG an appropriate error message
+ return false;
+ }
+
+ jpeg_create_compress(&mCompressInfo);
+
+ mCompressInfo.image_width = width;
+ mCompressInfo.image_height = height;
+ mCompressInfo.input_components = 3;
+ mCompressInfo.in_color_space = JCS_YCbCr;
+ jpeg_set_defaults(&mCompressInfo);
+
+ jpeg_set_quality(&mCompressInfo, quality, TRUE);
+ // It may seem weird to set color space here again but this will also set
+ // other fields. These fields might be overwritten by jpeg_set_defaults
+ jpeg_set_colorspace(&mCompressInfo, JCS_YCbCr);
+ mCompressInfo.raw_data_in = TRUE;
+ mCompressInfo.dct_method = JDCT_IFAST;
+ // Set sampling factors
+ mCompressInfo.comp_info[0].h_samp_factor = 2;
+ mCompressInfo.comp_info[0].v_samp_factor = 2;
+ mCompressInfo.comp_info[1].h_samp_factor = 1;
+ mCompressInfo.comp_info[1].v_samp_factor = 1;
+ mCompressInfo.comp_info[2].h_samp_factor = 1;
+ mCompressInfo.comp_info[2].v_samp_factor = 1;
+
+ mCompressInfo.dest = &mDestManager;
+
+ 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];
+ const uint8_t* cr[8];
+ const uint8_t** planes[3] = { y, cb, cr };
+
+ int i, offset;
+ int width = mCompressInfo.image_width;
+ int height = mCompressInfo.image_height;
+ const uint8_t* yPlanar = data;
+ 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
+ // below so they will leak. Additionally, do not place any calls to libjpeg
+ // that can fail above this line or any error will cause undefined behavior.
+ if (setjmp(mErrorManager.mJumpBuffer)) {
+ // This is where the error handler will jump in case compression fails
+ // The error manager will ALOG an appropriate error message
+ return false;
+ }
+
+ jpeg_start_compress(&mCompressInfo, TRUE);
+
+ attachExifData(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
+ y[i] = yPlanar + (mCompressInfo.next_scanline + i) * width;
+
+ // construct u row and v row
+ if ((i & 1) == 0) {
+ // height and width are both halved because of downsampling
+ 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);
+ }
+
+ jpeg_finish_compress(&mCompressInfo);
+ jpeg_destroy_compress(&mCompressInfo);
+
+ return true;
+}
+
+bool Compressor::attachExifData(ExifData* exifData) {
+ if (exifData == nullptr) {
+ // This is not an error, we don't require EXIF data
+ return true;
+ }
+
+ // Save the EXIF data to memory
+ unsigned char* rawData = nullptr;
+ unsigned int size = 0;
+ exif_data_save_data(exifData, &rawData, &size);
+ if (rawData == nullptr) {
+ ALOGE("Failed to create EXIF data block");
+ return false;
+ }
+
+ jpeg_write_marker(&mCompressInfo, JPEG_APP0 + 1, rawData, size);
+ free(rawData);
+ return true;
+}
+
+Compressor::ErrorManager::ErrorManager() {
+ error_exit = &onJpegError;
+}
+
+void Compressor::ErrorManager::onJpegError(j_common_ptr cinfo) {
+ // NOTE! Do not construct any non-trivial objects in this method at the top
+ // scope. Their destructors will not be called. If you do need such an
+ // object create a local scope that does not include the longjmp call,
+ // that ensures the object is destroyed before longjmp is called.
+ ErrorManager* errorManager = reinterpret_cast<ErrorManager*>(cinfo->err);
+
+ // Format and log error message
+ char errorMessage[JMSG_LENGTH_MAX];
+ (*errorManager->format_message)(cinfo, errorMessage);
+ errorMessage[sizeof(errorMessage) - 1] = '\0';
+ ALOGE("JPEG compression error: %s", errorMessage);
+ jpeg_destroy(cinfo);
+
+ // And through the looking glass we go
+ longjmp(errorManager->mJumpBuffer, 1);
+}
+
+Compressor::DestinationManager::DestinationManager() {
+ init_destination = &initDestination;
+ empty_output_buffer = &emptyOutputBuffer;
+ term_destination = &termDestination;
+}
+
+void Compressor::DestinationManager::initDestination(j_compress_ptr cinfo) {
+ auto manager = reinterpret_cast<DestinationManager*>(cinfo->dest);
+
+ // Start out with some arbitrary but not too large buffer size
+ manager->mBuffer.resize(16 * 1024);
+ manager->next_output_byte = &manager->mBuffer[0];
+ manager->free_in_buffer = manager->mBuffer.size();
+}
+
+boolean Compressor::DestinationManager::emptyOutputBuffer(
+ j_compress_ptr cinfo) {
+ auto manager = reinterpret_cast<DestinationManager*>(cinfo->dest);
+
+ // Keep doubling the size of the buffer for a very low, amortized
+ // performance cost of the allocations
+ size_t oldSize = manager->mBuffer.size();
+ manager->mBuffer.resize(oldSize * 2);
+ manager->next_output_byte = &manager->mBuffer[oldSize];
+ manager->free_in_buffer = manager->mBuffer.size() - oldSize;
+ return manager->free_in_buffer != 0;
+}
+
+void Compressor::DestinationManager::termDestination(j_compress_ptr cinfo) {
+ auto manager = reinterpret_cast<DestinationManager*>(cinfo->dest);
+
+ // Resize down to the exact size of the output, that is remove as many
+ // bytes as there are left in the buffer
+ manager->mBuffer.resize(manager->mBuffer.size() - manager->free_in_buffer);
+}
+
diff --git a/guest/hals/camera/Compressor.h b/guest/hals/camera/Compressor.h
new file mode 100644
index 000000000..10f5e805a
--- /dev/null
+++ b/guest/hals/camera/Compressor.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CUTTLEFISH_CAMERA_JPEG_STUB_COMPRESSOR_H
+#define CUTTLEFISH_CAMERA_JPEG_STUB_COMPRESSOR_H
+
+#include <setjmp.h>
+#include <stdlib.h>
+extern "C" {
+#include <jpeglib.h>
+#include <jerror.h>
+}
+
+#include <vector>
+
+struct _ExifData;
+typedef _ExifData ExifData;
+
+class Compressor {
+public:
+ Compressor();
+
+ /* Compress |data| which represents raw NV21 encoded data of dimensions
+ * |width| * |height|. |exifData| is optional EXIF data that will be
+ * attached to the compressed data if present, set to null if not needed.
+ */
+ bool compress(const unsigned char* data,
+ int width, int height, int quality,
+ ExifData* exifData);
+
+ /* Get a reference to the compressed data, this will return an empty vector
+ * if compress has not been called yet
+ */
+ const std::vector<unsigned char>& getCompressedData() const;
+
+private:
+ struct DestinationManager : jpeg_destination_mgr {
+ DestinationManager();
+
+ static void initDestination(j_compress_ptr cinfo);
+ static boolean emptyOutputBuffer(j_compress_ptr cinfo);
+ static void termDestination(j_compress_ptr cinfo);
+
+ std::vector<unsigned char> mBuffer;
+ };
+ struct ErrorManager : jpeg_error_mgr {
+ ErrorManager();
+
+ static void onJpegError(j_common_ptr cinfo);
+
+ jmp_buf mJumpBuffer;
+ };
+
+ jpeg_compress_struct mCompressInfo;
+ DestinationManager mDestManager;
+ ErrorManager mErrorManager;
+
+ bool configureCompressor(int width, int height, int quality);
+ bool compressData(const unsigned char* data, ExifData* exifData);
+ bool attachExifData(ExifData* exifData);
+};
+
+#endif // CUTTLEFISH_CAMERA_JPEG_STUB_COMPRESSOR_H
+
diff --git a/guest/hals/camera/Converters.cpp b/guest/hals/camera/Converters.cpp
new file mode 100644
index 000000000..7553d9591
--- /dev/null
+++ b/guest/hals/camera/Converters.cpp
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+/*
+ * Contains implemenation of framebuffer conversion routines.
+ */
+
+#define LOG_NDEBUG 0
+#define LOG_TAG "EmulatedCamera_Converter"
+#include "Converters.h"
+#include <log/log.h>
+
+namespace android {
+
+static void _YUV420SToRGB565(const uint8_t* Y, const uint8_t* U,
+ const uint8_t* V, int dUV, uint16_t* rgb,
+ int width, int height) {
+ const uint8_t* U_pos = U;
+ const uint8_t* V_pos = V;
+
+ for (int y = 0; y < height; y++) {
+ for (int x = 0; x < width; x += 2, U += dUV, V += dUV) {
+ const uint8_t nU = *U;
+ const uint8_t nV = *V;
+ *rgb = YUVToRGB565(*Y, nU, nV);
+ Y++;
+ rgb++;
+ *rgb = YUVToRGB565(*Y, nU, nV);
+ Y++;
+ rgb++;
+ }
+ if (y & 0x1) {
+ U_pos = U;
+ V_pos = V;
+ } else {
+ U = U_pos;
+ V = V_pos;
+ }
+ }
+}
+
+static void _YUV420SToRGB32(const uint8_t* Y, const uint8_t* U,
+ const uint8_t* V, int dUV, uint32_t* rgb, int width,
+ int height) {
+ const uint8_t* U_pos = U;
+ const uint8_t* V_pos = V;
+
+ for (int y = 0; y < height; y++) {
+ for (int x = 0; x < width; x += 2, U += dUV, V += dUV) {
+ const uint8_t nU = *U;
+ const uint8_t nV = *V;
+ *rgb = YUVToRGB32(*Y, nU, nV);
+ Y++;
+ rgb++;
+ *rgb = YUVToRGB32(*Y, nU, nV);
+ Y++;
+ rgb++;
+ }
+ if (y & 0x1) {
+ U_pos = U;
+ V_pos = V;
+ } else {
+ U = U_pos;
+ V = V_pos;
+ }
+ }
+}
+
+void YV12ToRGB565(const void* yv12, void* rgb, int width, int height) {
+ const int pix_total = width * height;
+ const uint8_t* Y = reinterpret_cast<const uint8_t*>(yv12);
+ const uint8_t* U = Y + pix_total;
+ const uint8_t* V = U + pix_total / 4;
+ _YUV420SToRGB565(Y, U, V, 1, reinterpret_cast<uint16_t*>(rgb), width, height);
+}
+
+void YV12ToRGB32(const void* yv12, void* rgb, int width, int height) {
+ const int pix_total = width * height;
+ const uint8_t* Y = reinterpret_cast<const uint8_t*>(yv12);
+ const uint8_t* V = Y + pix_total;
+ const uint8_t* U = V + pix_total / 4;
+ _YUV420SToRGB32(Y, U, V, 1, reinterpret_cast<uint32_t*>(rgb), width, height);
+}
+
+void YU12ToRGB32(const void* yu12, void* rgb, int width, int height) {
+ const int pix_total = width * height;
+ const uint8_t* Y = reinterpret_cast<const uint8_t*>(yu12);
+ const uint8_t* U = Y + pix_total;
+ const uint8_t* V = U + pix_total / 4;
+ _YUV420SToRGB32(Y, U, V, 1, reinterpret_cast<uint32_t*>(rgb), width, height);
+}
+
+/* Common converter for YUV 4:2:0 interleaved to RGB565.
+ * y, u, and v point to Y,U, and V panes, where U and V values are interleaved.
+ */
+static void _NVXXToRGB565(const uint8_t* Y, const uint8_t* U, const uint8_t* V,
+ uint16_t* rgb, int width, int height) {
+ _YUV420SToRGB565(Y, U, V, 2, rgb, width, height);
+}
+
+/* Common converter for YUV 4:2:0 interleaved to RGB32.
+ * y, u, and v point to Y,U, and V panes, where U and V values are interleaved.
+ */
+static void _NVXXToRGB32(const uint8_t* Y, const uint8_t* U, const uint8_t* V,
+ uint32_t* rgb, int width, int height) {
+ _YUV420SToRGB32(Y, U, V, 2, rgb, width, height);
+}
+
+void NV12ToRGB565(const void* nv12, void* rgb, int width, int height) {
+ const int pix_total = width * height;
+ const uint8_t* y = reinterpret_cast<const uint8_t*>(nv12);
+ _NVXXToRGB565(y, y + pix_total, y + pix_total + 1,
+ reinterpret_cast<uint16_t*>(rgb), width, height);
+}
+
+void NV12ToRGB32(const void* nv12, void* rgb, int width, int height) {
+ const int pix_total = width * height;
+ const uint8_t* y = reinterpret_cast<const uint8_t*>(nv12);
+ _NVXXToRGB32(y, y + pix_total, y + pix_total + 1,
+ reinterpret_cast<uint32_t*>(rgb), width, height);
+}
+
+void NV21ToRGB565(const void* nv21, void* rgb, int width, int height) {
+ const int pix_total = width * height;
+ const uint8_t* y = reinterpret_cast<const uint8_t*>(nv21);
+ _NVXXToRGB565(y, y + pix_total + 1, y + pix_total,
+ reinterpret_cast<uint16_t*>(rgb), width, height);
+}
+
+void NV21ToRGB32(const void* nv21, void* rgb, int width, int height) {
+ const int pix_total = width * height;
+ const uint8_t* y = reinterpret_cast<const uint8_t*>(nv21);
+ _NVXXToRGB32(y, y + pix_total + 1, y + pix_total,
+ reinterpret_cast<uint32_t*>(rgb), width, height);
+}
+
+}; /* namespace android */
diff --git a/guest/hals/camera/Converters.h b/guest/hals/camera/Converters.h
new file mode 100644
index 000000000..9d7f6a9ad
--- /dev/null
+++ b/guest/hals/camera/Converters.h
@@ -0,0 +1,320 @@
+/*
+ * Copyright (C) 2011 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 HW_EMULATOR_CAMERA_CONVERTERS_H
+#define HW_EMULATOR_CAMERA_CONVERTERS_H
+
+#include <endian.h>
+
+#ifndef __BYTE_ORDER
+#error "could not determine byte order"
+#endif
+
+/*
+ * Contains declaration of framebuffer conversion routines.
+ *
+ * NOTE: RGB and big/little endian considerations. Wherewer in this code RGB
+ * pixels are represented as WORD, or DWORD, the color order inside the
+ * WORD / DWORD matches the one that would occur if that WORD / DWORD would have
+ * been read from the typecasted framebuffer:
+ *
+ * const uint32_t rgb = *reinterpret_cast<const uint32_t*>(framebuffer);
+ *
+ * So, if this code runs on the little endian CPU, red color in 'rgb' would be
+ * masked as 0x000000ff, and blue color would be masked as 0x00ff0000, while if
+ * the code runs on a big endian CPU, the red color in 'rgb' would be masked as
+ * 0xff000000, and blue color would be masked as 0x0000ff00,
+ */
+
+namespace android {
+
+/*
+ * RGB565 color masks
+ */
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+static const uint16_t kRed5 = 0x001f;
+static const uint16_t kGreen6 = 0x07e0;
+static const uint16_t kBlue5 = 0xf800;
+#else // __BYTE_ORDER
+static const uint16_t kRed5 = 0xf800;
+static const uint16_t kGreen6 = 0x07e0;
+static const uint16_t kBlue5 = 0x001f;
+#endif // __BYTE_ORDER
+static const uint32_t kBlack16 = 0x0000;
+static const uint32_t kWhite16 = kRed5 | kGreen6 | kBlue5;
+
+/*
+ * RGB32 color masks
+ */
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+static const uint32_t kRed8 = 0x000000ff;
+static const uint32_t kGreen8 = 0x0000ff00;
+static const uint32_t kBlue8 = 0x00ff0000;
+#else // __BYTE_ORDER
+static const uint32_t kRed8 = 0x00ff0000;
+static const uint32_t kGreen8 = 0x0000ff00;
+static const uint32_t kBlue8 = 0x000000ff;
+#endif // __BYTE_ORDER
+static const uint32_t kBlack32 = 0x00000000;
+static const uint32_t kWhite32 = kRed8 | kGreen8 | kBlue8;
+
+/*
+ * Extracting, and saving color bytes from / to WORD / DWORD RGB.
+ */
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+/* Extract red, green, and blue bytes from RGB565 word. */
+#define R16(rgb) static_cast<uint8_t>(rgb & kRed5)
+#define G16(rgb) static_cast<uint8_t>((rgb & kGreen6) >> 5)
+#define B16(rgb) static_cast<uint8_t>((rgb & kBlue5) >> 11)
+/* Make 8 bits red, green, and blue, extracted from RGB565 word. */
+#define R16_32(rgb) \
+ static_cast<uint8_t>(((rgb & kRed5) << 3) | ((rgb & kRed5) >> 2))
+#define G16_32(rgb) \
+ static_cast<uint8_t>(((rgb & kGreen6) >> 3) | ((rgb & kGreen6) >> 9))
+#define B16_32(rgb) \
+ static_cast<uint8_t>(((rgb & kBlue5) >> 8) | ((rgb & kBlue5) >> 14))
+/* Extract red, green, and blue bytes from RGB32 dword. */
+#define R32(rgb) static_cast<uint8_t>(rgb & kRed8)
+#define G32(rgb) static_cast<uint8_t>(((rgb & kGreen8) >> 8) & 0xff)
+#define B32(rgb) static_cast<uint8_t>(((rgb & kBlue8) >> 16) & 0xff)
+/* Build RGB565 word from red, green, and blue bytes. */
+#define RGB565(r, g, b) \
+ static_cast<uint16_t>((((static_cast<uint16_t>(b) << 6) | g) << 5) | r)
+/* Build RGB32 dword from red, green, and blue bytes. */
+#define RGB32(r, g, b) \
+ static_cast<uint32_t>((((static_cast<uint32_t>(b) << 8) | g) << 8) | r)
+#else // __BYTE_ORDER
+/* Extract red, green, and blue bytes from RGB565 word. */
+#define R16(rgb) static_cast<uint8_t>((rgb & kRed5) >> 11)
+#define G16(rgb) static_cast<uint8_t>((rgb & kGreen6) >> 5)
+#define B16(rgb) static_cast<uint8_t>(rgb & kBlue5)
+/* Make 8 bits red, green, and blue, extracted from RGB565 word. */
+#define R16_32(rgb) \
+ static_cast<uint8_t>(((rgb & kRed5) >> 8) | ((rgb & kRed5) >> 14))
+#define G16_32(rgb) \
+ static_cast<uint8_t>(((rgb & kGreen6) >> 3) | ((rgb & kGreen6) >> 9))
+#define B16_32(rgb) \
+ static_cast<uint8_t>(((rgb & kBlue5) << 3) | ((rgb & kBlue5) >> 2))
+/* Extract red, green, and blue bytes from RGB32 dword. */
+#define R32(rgb) static_cast<uint8_t>((rgb & kRed8) >> 16)
+#define G32(rgb) static_cast<uint8_t>((rgb & kGreen8) >> 8)
+#define B32(rgb) static_cast<uint8_t>(rgb & kBlue8)
+/* Build RGB565 word from red, green, and blue bytes. */
+#define RGB565(r, g, b) \
+ static_cast<uint16_t>((((static_cast<uint16_t>(r) << 6) | g) << 5) | b)
+/* Build RGB32 dword from red, green, and blue bytes. */
+#define RGB32(r, g, b) \
+ static_cast<uint32_t>((((static_cast<uint32_t>(r) << 8) | g) << 8) | b)
+#endif // __BYTE_ORDER
+
+/* An union that simplifies breaking 32 bit RGB into separate R, G, and B
+ * colors.
+ */
+typedef union RGB32_t {
+ uint32_t color;
+ struct {
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ uint8_t r;
+ uint8_t g;
+ uint8_t b;
+ uint8_t a;
+#else // __BYTE_ORDER
+ uint8_t a;
+ uint8_t b;
+ uint8_t g;
+ uint8_t r;
+#endif // __BYTE_ORDER
+ };
+} RGB32_t;
+
+/* Clips a value to the unsigned 0-255 range, treating negative values as zero.
+ */
+static __inline__ int clamp(int x) {
+ if (x > 255) return 255;
+ if (x < 0) return 0;
+ return x;
+}
+
+/********************************************************************************
+ * Basics of RGB -> YUV conversion
+ *******************************************************************************/
+
+/*
+ * RGB -> YUV conversion macros
+ */
+#define RGB2Y(r, g, b) \
+ (uint8_t)(((66 * (r) + 129 * (g) + 25 * (b) + 128) >> 8) + 16)
+#define RGB2U(r, g, b) \
+ (uint8_t)(((-38 * (r)-74 * (g) + 112 * (b) + 128) >> 8) + 128)
+#define RGB2V(r, g, b) \
+ (uint8_t)(((112 * (r)-94 * (g)-18 * (b) + 128) >> 8) + 128)
+
+/* Converts R8 G8 B8 color to YUV. */
+static __inline__ void R8G8B8ToYUV(uint8_t r, uint8_t g, uint8_t b, uint8_t* y,
+ uint8_t* u, uint8_t* v) {
+ *y = RGB2Y((int)r, (int)g, (int)b);
+ *u = RGB2U((int)r, (int)g, (int)b);
+ *v = RGB2V((int)r, (int)g, (int)b);
+}
+
+/* Converts RGB565 color to YUV. */
+static __inline__ void RGB565ToYUV(uint16_t rgb, uint8_t* y, uint8_t* u,
+ uint8_t* v) {
+ R8G8B8ToYUV(R16_32(rgb), G16_32(rgb), B16_32(rgb), y, u, v);
+}
+
+/* Converts RGB32 color to YUV. */
+static __inline__ void RGB32ToYUV(uint32_t rgb, uint8_t* y, uint8_t* u,
+ uint8_t* v) {
+ RGB32_t rgb_c;
+ rgb_c.color = rgb;
+ R8G8B8ToYUV(rgb_c.r, rgb_c.g, rgb_c.b, y, u, v);
+}
+
+/********************************************************************************
+ * Basics of YUV -> RGB conversion.
+ * Note that due to the fact that guest uses RGB only on preview window, and the
+ * RGB format that is used is RGB565, we can limit YUV -> RGB conversions to
+ * RGB565 only.
+ *******************************************************************************/
+
+/*
+ * YUV -> RGB conversion macros
+ */
+
+/* "Optimized" macros that take specialy prepared Y, U, and V values:
+ * C = Y - 16
+ * D = U - 128
+ * E = V - 128
+ */
+#define YUV2RO(C, D, E) clamp((298 * (C) + 409 * (E) + 128) >> 8)
+#define YUV2GO(C, D, E) clamp((298 * (C)-100 * (D)-208 * (E) + 128) >> 8)
+#define YUV2BO(C, D, E) clamp((298 * (C) + 516 * (D) + 128) >> 8)
+
+/*
+ * Main macros that take the original Y, U, and V values
+ */
+#define YUV2R(y, u, v) clamp((298 * ((y)-16) + 409 * ((v)-128) + 128) >> 8)
+#define YUV2G(y, u, v) \
+ clamp((298 * ((y)-16) - 100 * ((u)-128) - 208 * ((v)-128) + 128) >> 8)
+#define YUV2B(y, u, v) clamp((298 * ((y)-16) + 516 * ((u)-128) + 128) >> 8)
+
+/* Converts YUV color to RGB565. */
+static __inline__ uint16_t YUVToRGB565(int y, int u, int v) {
+ /* Calculate C, D, and E values for the optimized macro. */
+ y -= 16;
+ u -= 128;
+ v -= 128;
+ const uint16_t r = (YUV2RO(y, u, v) >> 3) & 0x1f;
+ const uint16_t g = (YUV2GO(y, u, v) >> 2) & 0x3f;
+ const uint16_t b = (YUV2BO(y, u, v) >> 3) & 0x1f;
+ return RGB565(r, g, b);
+}
+
+/* Converts YUV color to RGB32. */
+static __inline__ uint32_t YUVToRGB32(int y, int u, int v) {
+ /* Calculate C, D, and E values for the optimized macro. */
+ y -= 16;
+ u -= 128;
+ v -= 128;
+ RGB32_t rgb;
+ rgb.r = YUV2RO(y, u, v) & 0xff;
+ rgb.g = YUV2GO(y, u, v) & 0xff;
+ rgb.b = YUV2BO(y, u, v) & 0xff;
+ return rgb.color;
+}
+
+/* YUV pixel descriptor. */
+struct YUVPixel {
+ uint8_t Y;
+ uint8_t U;
+ uint8_t V;
+
+ inline YUVPixel() : Y(0), U(0), V(0) {}
+
+ inline explicit YUVPixel(uint16_t rgb565) { RGB565ToYUV(rgb565, &Y, &U, &V); }
+
+ inline explicit YUVPixel(uint32_t rgb32) { RGB32ToYUV(rgb32, &Y, &U, &V); }
+
+ inline void get(uint8_t* pY, uint8_t* pU, uint8_t* pV) const {
+ *pY = Y;
+ *pU = U;
+ *pV = V;
+ }
+};
+
+/* Converts an YV12 framebuffer to RGB565 framebuffer.
+ * Param:
+ * yv12 - YV12 framebuffer.
+ * rgb - RGB565 framebuffer.
+ * width, height - Dimensions for both framebuffers.
+ */
+void YV12ToRGB565(const void* yv12, void* rgb, int width, int height);
+
+/* Converts an YV12 framebuffer to RGB32 framebuffer.
+ * Param:
+ * yv12 - YV12 framebuffer.
+ * rgb - RGB32 framebuffer.
+ * width, height - Dimensions for both framebuffers.
+ */
+void YV12ToRGB32(const void* yv12, void* rgb, int width, int height);
+
+/* Converts an YU12 framebuffer to RGB32 framebuffer.
+ * Param:
+ * yu12 - YU12 framebuffer.
+ * rgb - RGB32 framebuffer.
+ * width, height - Dimensions for both framebuffers.
+ */
+void YU12ToRGB32(const void* yu12, void* rgb, int width, int height);
+
+/* Converts an NV12 framebuffer to RGB565 framebuffer.
+ * Param:
+ * nv12 - NV12 framebuffer.
+ * rgb - RGB565 framebuffer.
+ * width, height - Dimensions for both framebuffers.
+ */
+void NV12ToRGB565(const void* nv12, void* rgb, int width, int height);
+
+/* Converts an NV12 framebuffer to RGB32 framebuffer.
+ * Param:
+ * nv12 - NV12 framebuffer.
+ * rgb - RGB32 framebuffer.
+ * width, height - Dimensions for both framebuffers.
+ */
+void NV12ToRGB32(const void* nv12, void* rgb, int width, int height);
+
+/* Converts an NV21 framebuffer to RGB565 framebuffer.
+ * Param:
+ * nv21 - NV21 framebuffer.
+ * rgb - RGB565 framebuffer.
+ * width, height - Dimensions for both framebuffers.
+ */
+void NV21ToRGB565(const void* nv21, void* rgb, int width, int height);
+
+/* Converts an NV21 framebuffer to RGB32 framebuffer.
+ * Param:
+ * nv21 - NV21 framebuffer.
+ * rgb - RGB32 framebuffer.
+ * width, height - Dimensions for both framebuffers.
+ */
+void NV21ToRGB32(const void* nv21, void* rgb, int width, int height);
+
+}; /* namespace android */
+
+#endif /* HW_EMULATOR_CAMERA_CONVERTERS_H */
diff --git a/guest/hals/camera/EmulatedBaseCamera.cpp b/guest/hals/camera/EmulatedBaseCamera.cpp
new file mode 100644
index 000000000..8ef553a1b
--- /dev/null
+++ b/guest/hals/camera/EmulatedBaseCamera.cpp
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+/*
+ * Contains implementation of a class EmulatedBaseCamera that encapsulates
+ * functionality common to all emulated camera device versions ("fake",
+ * "webcam", "video file", "cam2.0" etc.). Instances of this class (for each
+ * emulated camera) are created during the construction of the
+ * EmulatedCameraFactory instance. This class serves as an entry point for all
+ * camera API calls that are common across all versions of the
+ * camera_device_t/camera_module_t structures.
+ */
+
+#define LOG_NDEBUG 0
+#define LOG_TAG "EmulatedCamera_BaseCamera"
+#include <log/log.h>
+
+#include "EmulatedBaseCamera.h"
+
+namespace android {
+
+EmulatedBaseCamera::EmulatedBaseCamera(int cameraId, uint32_t cameraVersion,
+ struct hw_device_t* device,
+ struct hw_module_t* module)
+ : mCameraInfo(NULL),
+ mCameraID(cameraId),
+ mCameraDeviceVersion(cameraVersion) {
+ /*
+ * Initialize camera_device descriptor for this object.
+ */
+
+ /* Common header */
+ device->tag = HARDWARE_DEVICE_TAG;
+ device->version = cameraVersion;
+ device->module = module;
+ device->close = NULL; // Must be filled in by child implementation
+}
+
+EmulatedBaseCamera::~EmulatedBaseCamera() {}
+
+status_t EmulatedBaseCamera::getCameraInfo(struct camera_info* info) {
+ ALOGV("%s", __FUNCTION__);
+
+ info->device_version = mCameraDeviceVersion;
+ if (mCameraDeviceVersion >= HARDWARE_DEVICE_API_VERSION(2, 0)) {
+ info->static_camera_characteristics = mCameraInfo;
+ } else {
+ info->static_camera_characteristics = (camera_metadata_t*)0xcafef00d;
+ }
+
+ return NO_ERROR;
+}
+
+status_t EmulatedBaseCamera::plugCamera() {
+ ALOGE("%s: not supported", __FUNCTION__);
+ return INVALID_OPERATION;
+}
+
+status_t EmulatedBaseCamera::unplugCamera() {
+ ALOGE("%s: not supported", __FUNCTION__);
+ return INVALID_OPERATION;
+}
+
+camera_device_status_t EmulatedBaseCamera::getHotplugStatus() {
+ return CAMERA_DEVICE_STATUS_PRESENT;
+}
+
+status_t EmulatedBaseCamera::setTorchMode(bool /* enabled */) {
+ ALOGE("%s: not supported", __FUNCTION__);
+ return INVALID_OPERATION;
+}
+
+} /* namespace android */
diff --git a/guest/hals/camera/EmulatedBaseCamera.h b/guest/hals/camera/EmulatedBaseCamera.h
new file mode 100644
index 000000000..ba4b98e8c
--- /dev/null
+++ b/guest/hals/camera/EmulatedBaseCamera.h
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2012 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 HW_EMULATOR_CAMERA_EMULATED_BASE_CAMERA_H
+#define HW_EMULATOR_CAMERA_EMULATED_BASE_CAMERA_H
+
+#include <hardware/camera_common.h>
+#include <utils/Errors.h>
+#include "CameraConfiguration.h"
+#include <CameraParameters.h>
+using ::android::hardware::camera::common::V1_0::helper::CameraParameters;
+
+namespace android {
+
+/*
+ * Contains declaration of a class EmulatedBaseCamera that encapsulates
+ * functionality common to all emulated camera device versions ("fake",
+ * "webcam", "video file", etc.). Instances of this class (for each emulated
+ * camera) are created during the construction of the EmulatedCameraFactory
+ * instance. This class serves as an entry point for all camera API calls that
+ * are common across all versions of the camera_device_t/camera_module_t
+ * structures.
+ */
+
+class EmulatedBaseCamera {
+ public:
+ EmulatedBaseCamera(int cameraId, uint32_t cameraVersion,
+ struct hw_device_t* device, struct hw_module_t* module);
+
+ virtual ~EmulatedBaseCamera();
+
+ /****************************************************************************
+ * Public API
+ ***************************************************************************/
+
+ public:
+ /* Initializes EmulatedCamera instance.
+ * Return:
+ * NO_ERROR on success, or an appropriate error status on failure.
+ */
+ virtual status_t Initialize(const cvd::CameraDefinition& params) = 0;
+
+ /****************************************************************************
+ * Camera API implementation
+ ***************************************************************************/
+
+ public:
+ /* Creates connection to the emulated camera device.
+ * This method is called in response to hw_module_methods_t::open callback.
+ * NOTE: When this method is called the object is locked.
+ * Note that failures in this method are reported as negative EXXX statuses.
+ */
+ virtual status_t connectCamera(hw_device_t** device) = 0;
+
+ /* Plug the connection for the emulated camera. Until it's plugged in
+ * calls to connectCamera should fail with -ENODEV.
+ */
+ virtual status_t plugCamera();
+
+ /* Unplug the connection from underneath the emulated camera.
+ * This is similar to closing the camera, except that
+ * all function calls into the camera device will return
+ * -EPIPE errors until the camera is reopened.
+ */
+ virtual status_t unplugCamera();
+
+ virtual camera_device_status_t getHotplugStatus();
+
+ /* Closes connection to the emulated camera.
+ * This method is called in response to camera_device::close callback.
+ * NOTE: When this method is called the object is locked.
+ * Note that failures in this method are reported as negative EXXX statuses.
+ */
+ virtual status_t closeCamera() = 0;
+
+ /* Gets camera information.
+ * This method is called in response to camera_module_t::get_camera_info
+ * callback.
+ * NOTE: When this method is called the object is locked.
+ * Note that failures in this method are reported as negative EXXX statuses.
+ */
+ virtual status_t getCameraInfo(struct camera_info* info) = 0;
+
+ /* Gets camera parameters.
+ * This method is called to collect metadata for (currently) taken picture.
+ */
+ virtual const CameraParameters* getCameraParameters() {
+ return NULL;
+ }
+
+ /* Set torch mode.
+ * This method is called in response to camera_module_t::set_torch_mode
+ * callback.
+ */
+ virtual status_t setTorchMode(bool enabled);
+
+ /****************************************************************************
+ * Data members
+ ***************************************************************************/
+
+ protected:
+ /* Fixed camera information for camera2 devices. Must be valid to access if
+ * mCameraDeviceVersion is >= HARDWARE_DEVICE_API_VERSION(2,0) */
+ camera_metadata_t* mCameraInfo;
+
+ /* Zero-based ID assigned to this camera. */
+ int mCameraID;
+
+ private:
+ /* Version of the camera device HAL implemented by this camera */
+ int mCameraDeviceVersion;
+};
+
+} /* namespace android */
+
+#endif /* HW_EMULATOR_CAMERA_EMULATED_BASE_CAMERA_H */
diff --git a/guest/hals/camera/EmulatedCamera.cpp b/guest/hals/camera/EmulatedCamera.cpp
new file mode 100644
index 000000000..e48d5795c
--- /dev/null
+++ b/guest/hals/camera/EmulatedCamera.cpp
@@ -0,0 +1,1034 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+/*
+ * Contains implementation of a class EmulatedCamera that encapsulates
+ * functionality common to all emulated cameras ("fake", "webcam", "video file",
+ * etc.). Instances of this class (for each emulated camera) are created during
+ * the construction of the EmulatedCameraFactory instance. This class serves as
+ * an entry point for all camera API calls that defined by camera_device_ops_t
+ * API.
+ */
+
+#define LOG_NDEBUG 0
+#define LOG_TAG "EmulatedCamera_Camera"
+#include <log/log.h>
+#include "EmulatedCamera.h"
+//#include "EmulatedFakeCameraDevice.h"
+#include "Converters.h"
+
+/* Defines whether we should trace parameter changes. */
+#define DEBUG_PARAM 1
+
+namespace android {
+namespace {
+const char* kSupportedFlashModes[] = {
+ CameraParameters::FLASH_MODE_OFF, CameraParameters::FLASH_MODE_AUTO,
+ CameraParameters::FLASH_MODE_ON, CameraParameters::FLASH_MODE_RED_EYE,
+ CameraParameters::FLASH_MODE_TORCH, NULL};
+
+std::string BuildParameterValue(const char** value_array) {
+ std::string result;
+
+ for (int index = 0; value_array[index] != NULL; ++index) {
+ if (index) result.append(",");
+ result.append(value_array[index]);
+ }
+ return result;
+}
+
+bool CheckParameterValue(const char* value, const char** supported_values) {
+ for (int index = 0; supported_values[index] != NULL; ++index) {
+ if (!strcmp(value, supported_values[index])) return true;
+ }
+ return false;
+}
+
+} // namespace
+
+#if DEBUG_PARAM
+/* Calculates and logs parameter changes.
+ * Param:
+ * current - Current set of camera parameters.
+ * new_par - String representation of new parameters.
+ */
+static void PrintParamDiff(const CameraParameters& current,
+ const char* new_par);
+#else
+#define PrintParamDiff(current, new_par) (void(0))
+#endif /* DEBUG_PARAM */
+
+EmulatedCamera::EmulatedCamera(int cameraId, struct hw_module_t* module)
+ : EmulatedBaseCamera(cameraId, HARDWARE_DEVICE_API_VERSION(1, 0), &common,
+ module),
+ mPreviewWindow(),
+ mCallbackNotifier() {
+ /* camera_device v1 fields. */
+ common.close = EmulatedCamera::close;
+ ops = &mDeviceOps;
+ priv = this;
+}
+
+EmulatedCamera::~EmulatedCamera() {}
+
+/****************************************************************************
+ * Public API
+ ***************************************************************************/
+
+status_t EmulatedCamera::Initialize(const cvd::CameraDefinition&) {
+ /* Preview formats supported by this HAL. */
+ char preview_formats[1024];
+ snprintf(preview_formats, sizeof(preview_formats), "%s,%s,%s",
+ CameraParameters::PIXEL_FORMAT_YUV420SP,
+ CameraParameters::PIXEL_FORMAT_YUV420P,
+ CameraParameters::PIXEL_FORMAT_RGBA8888);
+
+ /*
+ * Fake required parameters.
+ */
+
+ mParameters.set(CameraParameters::KEY_SUPPORTED_JPEG_THUMBNAIL_SIZES,
+ "320x240,0x0");
+
+ mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH, "512");
+ mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT, "384");
+ mParameters.set(CameraParameters::KEY_JPEG_QUALITY, "90");
+ mParameters.set(CameraParameters::KEY_FOCAL_LENGTH, "4.31");
+ mParameters.set(CameraParameters::KEY_HORIZONTAL_VIEW_ANGLE, "54.8");
+ mParameters.set(CameraParameters::KEY_VERTICAL_VIEW_ANGLE, "42.5");
+ mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY, "90");
+
+ /* Preview format settings used here are related to panoramic view only. It's
+ * not related to the preview window that works only with RGB frames, which
+ * is explicitly stated when set_buffers_geometry is called on the preview
+ * window object. */
+ mParameters.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FORMATS,
+ preview_formats);
+ mParameters.setPreviewFormat(CameraParameters::PIXEL_FORMAT_YUV420SP);
+
+ /* We don't relay on the actual frame rates supported by the camera device,
+ * since we will emulate them through timeouts in the emulated camera device
+ * worker thread. */
+ mParameters.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES,
+ "30,24,20,15,10,5");
+ mParameters.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FPS_RANGE,
+ "(5000,30000),(15000,15000),(30000,30000)");
+ mParameters.set(CameraParameters::KEY_PREVIEW_FPS_RANGE, "5000,30000");
+ mParameters.setPreviewFrameRate(30000);
+
+ /* Only PIXEL_FORMAT_YUV420P is accepted by video framework in emulator! */
+ mParameters.set(CameraParameters::KEY_VIDEO_FRAME_FORMAT,
+ CameraParameters::PIXEL_FORMAT_YUV420P);
+ mParameters.set(CameraParameters::KEY_SUPPORTED_PICTURE_FORMATS,
+ CameraParameters::PIXEL_FORMAT_JPEG);
+ mParameters.setPictureFormat(CameraParameters::PIXEL_FORMAT_JPEG);
+
+ /* Set exposure compensation. */
+ mParameters.set(CameraParameters::KEY_MAX_EXPOSURE_COMPENSATION, "6");
+ mParameters.set(CameraParameters::KEY_MIN_EXPOSURE_COMPENSATION, "-6");
+ mParameters.set(CameraParameters::KEY_EXPOSURE_COMPENSATION_STEP, "0.5");
+ mParameters.set(CameraParameters::KEY_EXPOSURE_COMPENSATION, "0");
+
+ /* Sets the white balance modes and the device-dependent scale factors. */
+ char supported_white_balance[1024];
+ snprintf(supported_white_balance, sizeof(supported_white_balance),
+ "%s,%s,%s,%s", CameraParameters::WHITE_BALANCE_AUTO,
+ CameraParameters::WHITE_BALANCE_INCANDESCENT,
+ CameraParameters::WHITE_BALANCE_DAYLIGHT,
+ CameraParameters::WHITE_BALANCE_TWILIGHT);
+ mParameters.set(CameraParameters::KEY_SUPPORTED_WHITE_BALANCE,
+ supported_white_balance);
+ mParameters.set(CameraParameters::KEY_WHITE_BALANCE,
+ CameraParameters::WHITE_BALANCE_AUTO);
+ getCameraDevice()->initializeWhiteBalanceModes(
+ CameraParameters::WHITE_BALANCE_AUTO, 1.0f, 1.0f);
+ getCameraDevice()->initializeWhiteBalanceModes(
+ CameraParameters::WHITE_BALANCE_INCANDESCENT, 1.38f, 0.60f);
+ getCameraDevice()->initializeWhiteBalanceModes(
+ CameraParameters::WHITE_BALANCE_DAYLIGHT, 1.09f, 0.92f);
+ getCameraDevice()->initializeWhiteBalanceModes(
+ CameraParameters::WHITE_BALANCE_TWILIGHT, 0.92f, 1.22f);
+ getCameraDevice()->setWhiteBalanceMode(CameraParameters::WHITE_BALANCE_AUTO);
+
+ /*
+ * Not supported features
+ */
+ mParameters.set(CameraParameters::KEY_SUPPORTED_FOCUS_MODES,
+ CameraParameters::FOCUS_MODE_FIXED);
+ mParameters.set(CameraParameters::KEY_FOCUS_MODE,
+ CameraParameters::FOCUS_MODE_FIXED);
+ mParameters.set(CameraParameters::KEY_SUPPORTED_FLASH_MODES,
+ BuildParameterValue(kSupportedFlashModes).c_str());
+ mParameters.set(CameraParameters::KEY_FLASH_MODE,
+ CameraParameters::FLASH_MODE_OFF);
+ mParameters.set(CameraParameters::KEY_FOCUS_DISTANCES, "0.1,0.1,0.1");
+ mParameters.set(CameraParameters::KEY_MAX_NUM_DETECTED_FACES_HW, "0");
+ mParameters.set(CameraParameters::KEY_MAX_NUM_DETECTED_FACES_SW, "0");
+ mParameters.set(CameraParameters::KEY_ZOOM_RATIOS, "100");
+ mParameters.set(CameraParameters::KEY_ZOOM_SUPPORTED,
+ CameraParameters::FALSE);
+ mParameters.set(CameraParameters::KEY_SMOOTH_ZOOM_SUPPORTED,
+ CameraParameters::FALSE);
+ mParameters.set(CameraParameters::KEY_ZOOM, "0");
+ mParameters.set(CameraParameters::KEY_MAX_ZOOM, "0");
+
+ return NO_ERROR;
+}
+
+void EmulatedCamera::onNextFrameAvailable(const void* frame, nsecs_t timestamp,
+ EmulatedCameraDevice* camera_dev) {
+ /* Notify the preview window first. */
+ mPreviewWindow.onNextFrameAvailable(frame, timestamp, camera_dev);
+
+ /* Notify callback notifier next. */
+ mCallbackNotifier.onNextFrameAvailable(frame, timestamp, camera_dev);
+}
+
+void EmulatedCamera::onCameraDeviceError(int err) {
+ /* Errors are reported through the callback notifier */
+ mCallbackNotifier.onCameraDeviceError(err);
+}
+
+void EmulatedCamera::onCameraFocusAcquired() {
+ mCallbackNotifier.onCameraFocusAcquired();
+}
+
+/****************************************************************************
+ * Camera API implementation.
+ ***************************************************************************/
+
+status_t EmulatedCamera::connectCamera(hw_device_t** device) {
+ ALOGV("%s", __FUNCTION__);
+
+ status_t res = EINVAL;
+ EmulatedCameraDevice* const camera_dev = getCameraDevice();
+ ALOGE_IF(camera_dev == NULL, "%s: No camera device instance.", __FUNCTION__);
+
+ if (camera_dev != NULL) {
+ /* Connect to the camera device. */
+ res = getCameraDevice()->connectDevice();
+ if (res == NO_ERROR) {
+ *device = &common;
+ }
+ }
+
+ return -res;
+}
+
+status_t EmulatedCamera::closeCamera() {
+ ALOGV("%s", __FUNCTION__);
+
+ return cleanupCamera();
+}
+
+status_t EmulatedCamera::getCameraInfo(struct camera_info* info) {
+ ALOGV("%s", __FUNCTION__);
+
+ const char* valstr = NULL;
+
+ valstr = mParameters.get(EmulatedCamera::FACING_KEY);
+ if (valstr != NULL) {
+ if (strcmp(valstr, EmulatedCamera::FACING_FRONT) == 0) {
+ info->facing = CAMERA_FACING_FRONT;
+ } else if (strcmp(valstr, EmulatedCamera::FACING_BACK) == 0) {
+ info->facing = CAMERA_FACING_BACK;
+ }
+ } else {
+ info->facing = CAMERA_FACING_BACK;
+ }
+
+ valstr = mParameters.get(EmulatedCamera::ORIENTATION_KEY);
+ if (valstr != NULL) {
+ info->orientation = atoi(valstr);
+ } else {
+ info->orientation = 0;
+ }
+
+ info->resource_cost = 100;
+ info->conflicting_devices = NULL;
+ info->conflicting_devices_length = 0;
+
+ return EmulatedBaseCamera::getCameraInfo(info);
+}
+
+const CameraParameters* EmulatedCamera::getCameraParameters() {
+ return &mParameters;
+}
+
+status_t EmulatedCamera::setPreviewWindow(struct preview_stream_ops* window) {
+ /* Callback should return a negative errno. */
+ return -mPreviewWindow.setPreviewWindow(window,
+ mParameters.getPreviewFrameRate());
+}
+
+void EmulatedCamera::setCallbacks(
+ camera_notify_callback notify_cb, camera_data_callback data_cb,
+ camera_data_timestamp_callback data_cb_timestamp,
+ camera_request_memory get_memory, void* user) {
+ mCallbackNotifier.setCallbacks(notify_cb, data_cb, data_cb_timestamp,
+ get_memory, user);
+}
+
+void EmulatedCamera::enableMsgType(int32_t msg_type) {
+ mCallbackNotifier.enableMessage(msg_type);
+}
+
+void EmulatedCamera::disableMsgType(int32_t msg_type) {
+ mCallbackNotifier.disableMessage(msg_type);
+}
+
+int EmulatedCamera::isMsgTypeEnabled(int32_t msg_type) {
+ return mCallbackNotifier.isMessageEnabled(msg_type);
+}
+
+status_t EmulatedCamera::startPreview() {
+ /* Callback should return a negative errno. */
+ return -doStartPreview();
+}
+
+void EmulatedCamera::stopPreview() { doStopPreview(); }
+
+int EmulatedCamera::isPreviewEnabled() {
+ return mPreviewWindow.isPreviewEnabled();
+}
+
+status_t EmulatedCamera::storeMetaDataInBuffers(int enable) {
+ /* Callback should return a negative errno. */
+ return -mCallbackNotifier.storeMetaDataInBuffers(enable);
+}
+
+status_t EmulatedCamera::startRecording() {
+ /* Callback should return a negative errno. */
+ return -mCallbackNotifier.enableVideoRecording(
+ mParameters.getPreviewFrameRate());
+}
+
+void EmulatedCamera::stopRecording() {
+ mCallbackNotifier.disableVideoRecording();
+}
+
+int EmulatedCamera::isRecordingEnabled() {
+ return mCallbackNotifier.isVideoRecordingEnabled();
+}
+
+void EmulatedCamera::releaseRecordingFrame(const void* opaque) {
+ mCallbackNotifier.releaseRecordingFrame(opaque);
+}
+
+status_t EmulatedCamera::setAutoFocus() {
+ ALOGV("%s", __FUNCTION__);
+
+ /* Trigger auto-focus. Focus response cannot be sent directly from here. */
+ getCameraDevice()->startAutoFocus();
+
+ /* TODO: Future enhancements. */
+ return NO_ERROR;
+}
+
+status_t EmulatedCamera::cancelAutoFocus() {
+ ALOGV("%s", __FUNCTION__);
+
+ /* TODO: Future enhancements. */
+ return NO_ERROR;
+}
+
+status_t EmulatedCamera::takePicture() {
+ ALOGV("%s", __FUNCTION__);
+
+ status_t res;
+ int width, height;
+ uint32_t org_fmt;
+
+ /* Collect frame info for the picture. */
+ mParameters.getPictureSize(&width, &height);
+ const char* pix_fmt = mParameters.getPictureFormat();
+ if (strcmp(pix_fmt, CameraParameters::PIXEL_FORMAT_YUV420P) == 0) {
+ org_fmt = V4L2_PIX_FMT_YUV420;
+ } else if (strcmp(pix_fmt, CameraParameters::PIXEL_FORMAT_RGBA8888) == 0) {
+ org_fmt = V4L2_PIX_FMT_RGB32;
+ } else if (strcmp(pix_fmt, CameraParameters::PIXEL_FORMAT_YUV420SP) == 0) {
+ org_fmt = V4L2_PIX_FMT_NV21;
+ } else if (strcmp(pix_fmt, CameraParameters::PIXEL_FORMAT_JPEG) == 0) {
+ /* We only have JPEG converted for NV21 format. */
+ org_fmt = V4L2_PIX_FMT_NV21;
+ } else {
+ ALOGE("%s: Unsupported pixel format %s", __FUNCTION__, pix_fmt);
+ return EINVAL;
+ }
+ /* Get JPEG quality. */
+ int jpeg_quality = mParameters.getInt(CameraParameters::KEY_JPEG_QUALITY);
+ if (jpeg_quality <= 0) {
+ jpeg_quality = 90; /* Fall back to default. */
+ }
+
+ /*
+ * Make sure preview is not running, and device is stopped before taking
+ * picture.
+ */
+
+ const bool preview_on = mPreviewWindow.isPreviewEnabled();
+ if (preview_on) {
+ doStopPreview();
+ }
+
+ /* Camera device should have been stopped when the shutter message has been
+ * enabled. */
+ EmulatedCameraDevice* const camera_dev = getCameraDevice();
+ if (camera_dev->isStarted()) {
+ ALOGW("%s: Camera device is started", __FUNCTION__);
+ camera_dev->stopDeliveringFrames();
+ camera_dev->stopDevice();
+ }
+
+ /* Compute target FPS rate.
+ * Pretend to simulate generation of (max_fps_rate) */
+ int min_fps_rate, max_fps_rate;
+ mParameters.getPreviewFpsRange(&min_fps_rate, &max_fps_rate);
+
+ /*
+ * Take the picture now.
+ */
+
+ /* Start camera device for the picture frame. */
+ ALOGD("Starting camera for picture: %.4s(%s)[%dx%d]",
+ reinterpret_cast<const char*>(&org_fmt), pix_fmt, width, height);
+ res = camera_dev->startDevice(width, height, org_fmt, max_fps_rate);
+ if (res != NO_ERROR) {
+ if (preview_on) {
+ doStartPreview();
+ }
+ return res;
+ }
+
+ /* Deliver one frame only. */
+ mCallbackNotifier.setJpegQuality(jpeg_quality);
+ mCallbackNotifier.setTakingPicture(true);
+ res = camera_dev->startDeliveringFrames(true);
+ if (res != NO_ERROR) {
+ mCallbackNotifier.setTakingPicture(false);
+ if (preview_on) {
+ doStartPreview();
+ }
+ }
+ return res;
+}
+
+status_t EmulatedCamera::cancelPicture() {
+ ALOGV("%s", __FUNCTION__);
+
+ return NO_ERROR;
+}
+
+status_t EmulatedCamera::setParameters(const char* parms) {
+ ALOGV("%s", __FUNCTION__);
+ PrintParamDiff(mParameters, parms);
+
+ CameraParameters new_param;
+ String8 str8_param(parms);
+ new_param.unflatten(str8_param);
+
+ /*
+ * Check if requested dimensions are valid.
+ */
+ if (!CheckParameterValue(new_param.get(CameraParameters::KEY_FLASH_MODE),
+ kSupportedFlashModes)) {
+ ALOGE("%s: Unsupported flash mode: %s", __FUNCTION__,
+ new_param.get(CameraParameters::KEY_FLASH_MODE));
+ return -EINVAL;
+ }
+ if (strcmp(new_param.get(CameraParameters::KEY_FOCUS_MODE),
+ CameraParameters::FOCUS_MODE_FIXED)) {
+ ALOGE("%s: Unsupported flash mode: %s", __FUNCTION__,
+ new_param.get(CameraParameters::KEY_FOCUS_MODE));
+ return -EINVAL;
+ }
+
+ int preview_width, preview_height;
+ new_param.getPreviewSize(&preview_width, &preview_height);
+ if (preview_width <= 0 || preview_height <= 0) return -EINVAL;
+
+ /*
+ * Check for new exposure compensation parameter.
+ */
+ int new_exposure_compensation =
+ new_param.getInt(CameraParameters::KEY_EXPOSURE_COMPENSATION);
+ const int min_exposure_compensation =
+ new_param.getInt(CameraParameters::KEY_MIN_EXPOSURE_COMPENSATION);
+ const int max_exposure_compensation =
+ new_param.getInt(CameraParameters::KEY_MAX_EXPOSURE_COMPENSATION);
+
+ // Checks if the exposure compensation change is supported.
+ if ((min_exposure_compensation != 0) || (max_exposure_compensation != 0)) {
+ if (new_exposure_compensation > max_exposure_compensation) {
+ new_exposure_compensation = max_exposure_compensation;
+ }
+ if (new_exposure_compensation < min_exposure_compensation) {
+ new_exposure_compensation = min_exposure_compensation;
+ }
+
+ const int current_exposure_compensation =
+ mParameters.getInt(CameraParameters::KEY_EXPOSURE_COMPENSATION);
+ if (current_exposure_compensation != new_exposure_compensation) {
+ const float exposure_value =
+ new_exposure_compensation *
+ new_param.getFloat(CameraParameters::KEY_EXPOSURE_COMPENSATION_STEP);
+
+ getCameraDevice()->setExposureCompensation(exposure_value);
+ }
+ }
+
+ const char* new_white_balance =
+ new_param.get(CameraParameters::KEY_WHITE_BALANCE);
+ const char* supported_white_balance =
+ new_param.get(CameraParameters::KEY_SUPPORTED_WHITE_BALANCE);
+
+ if ((supported_white_balance != NULL) && (new_white_balance != NULL) &&
+ (strstr(supported_white_balance, new_white_balance) != NULL)) {
+ const char* current_white_balance =
+ mParameters.get(CameraParameters::KEY_WHITE_BALANCE);
+ if ((current_white_balance == NULL) ||
+ (strcmp(current_white_balance, new_white_balance) != 0)) {
+ ALOGV("Setting white balance to %s", new_white_balance);
+ getCameraDevice()->setWhiteBalanceMode(new_white_balance);
+ }
+ }
+
+ mParameters = new_param;
+
+ return NO_ERROR;
+}
+
+/* A dumb variable indicating "no params" / error on the exit from
+ * EmulatedCamera::getParameters(). */
+static char lNoParam = '\0';
+char* EmulatedCamera::getParameters() {
+ String8 params(mParameters.flatten());
+ char* ret_str =
+ reinterpret_cast<char*>(malloc(sizeof(char) * (params.length() + 1)));
+ memset(ret_str, 0, params.length() + 1);
+ if (ret_str != NULL) {
+ strncpy(ret_str, params.string(), params.length() + 1);
+ return ret_str;
+ } else {
+ ALOGE("%s: Unable to allocate string for %s", __FUNCTION__,
+ params.string());
+ /* Apparently, we can't return NULL fron this routine. */
+ return &lNoParam;
+ }
+}
+
+void EmulatedCamera::putParameters(char* params) {
+ /* This method simply frees parameters allocated in getParameters(). */
+ if (params != NULL && params != &lNoParam) {
+ free(params);
+ }
+}
+
+status_t EmulatedCamera::sendCommand(int32_t cmd, int32_t arg1, int32_t arg2) {
+ ALOGV("%s: cmd = %d, arg1 = %d, arg2 = %d", __FUNCTION__, cmd, arg1, arg2);
+
+ switch (cmd) {
+ case CAMERA_CMD_START_FACE_DETECTION:
+ case CAMERA_CMD_STOP_FACE_DETECTION:
+ return -EINVAL;
+ }
+
+ /* TODO: Future enhancements. */
+ return 0;
+}
+
+void EmulatedCamera::releaseCamera() {
+ ALOGV("%s", __FUNCTION__);
+
+ cleanupCamera();
+}
+
+status_t EmulatedCamera::dumpCamera(int /*fd*/) {
+ ALOGV("%s", __FUNCTION__);
+
+ /* TODO: Future enhancements. */
+ return -EINVAL;
+}
+
+/****************************************************************************
+ * Preview management.
+ ***************************************************************************/
+
+status_t EmulatedCamera::doStartPreview() {
+ ALOGV("%s", __FUNCTION__);
+
+ EmulatedCameraDevice* camera_dev = getCameraDevice();
+ if (camera_dev->isStarted()) {
+ camera_dev->stopDeliveringFrames();
+ camera_dev->stopDevice();
+ }
+
+ status_t res = mPreviewWindow.startPreview();
+ if (res != NO_ERROR) {
+ return res;
+ }
+
+ /* Make sure camera device is connected. */
+ if (!camera_dev->isConnected()) {
+ res = camera_dev->connectDevice();
+ if (res != NO_ERROR) {
+ mPreviewWindow.stopPreview();
+ return res;
+ }
+ }
+
+ int width, height;
+ /* Lets see what should we use for frame width, and height. */
+ if (mParameters.get(CameraParameters::KEY_VIDEO_SIZE) != NULL) {
+ mParameters.getVideoSize(&width, &height);
+ } else {
+ mParameters.getPreviewSize(&width, &height);
+ }
+ /* Lets see what should we use for the frame pixel format. Note that there
+ * are two parameters that define pixel formats for frames sent to the
+ * application via notification callbacks:
+ * - KEY_VIDEO_FRAME_FORMAT, that is used when recording video, and
+ * - KEY_PREVIEW_FORMAT, that is used for preview frame notification.
+ * We choose one or the other, depending on "recording-hint" property set by
+ * the framework that indicating intention: video, or preview. */
+ const char* pix_fmt = NULL;
+ const char* is_video = mParameters.get(EmulatedCamera::RECORDING_HINT_KEY);
+ if (is_video == NULL) {
+ is_video = CameraParameters::FALSE;
+ }
+ if (strcmp(is_video, CameraParameters::TRUE) == 0) {
+ /* Video recording is requested. Lets see if video frame format is set. */
+ pix_fmt = mParameters.get(CameraParameters::KEY_VIDEO_FRAME_FORMAT);
+ }
+ /* If this was not video recording, or video frame format is not set, lets
+ * use preview pixel format for the main framebuffer. */
+ if (pix_fmt == NULL) {
+ pix_fmt = mParameters.getPreviewFormat();
+ }
+ if (pix_fmt == NULL) {
+ ALOGE("%s: Unable to obtain video format", __FUNCTION__);
+ mPreviewWindow.stopPreview();
+ return EINVAL;
+ }
+
+ /* Convert framework's pixel format to the FOURCC one. */
+ uint32_t org_fmt;
+ if (strcmp(pix_fmt, CameraParameters::PIXEL_FORMAT_YUV420P) == 0) {
+ org_fmt = V4L2_PIX_FMT_YUV420;
+ } else if (strcmp(pix_fmt, CameraParameters::PIXEL_FORMAT_RGBA8888) == 0) {
+ org_fmt = V4L2_PIX_FMT_RGB32;
+ } else if (strcmp(pix_fmt, CameraParameters::PIXEL_FORMAT_YUV420SP) == 0) {
+ org_fmt = V4L2_PIX_FMT_NV21;
+ } else {
+ ALOGE("%s: Unsupported pixel format %s", __FUNCTION__, pix_fmt);
+ mPreviewWindow.stopPreview();
+ return EINVAL;
+ }
+
+ /* Fetch the desired frame rate. */
+ int min_fps_rate, max_fps_rate;
+ mParameters.getPreviewFpsRange(&min_fps_rate, &max_fps_rate);
+
+ ALOGD("Starting camera: %dx%d -> %.4s(%s)", width, height,
+ reinterpret_cast<const char*>(&org_fmt), pix_fmt);
+ res = camera_dev->startDevice(width, height, org_fmt, max_fps_rate);
+ if (res != NO_ERROR) {
+ mPreviewWindow.stopPreview();
+ return res;
+ }
+
+ res = camera_dev->startDeliveringFrames(false);
+ if (res != NO_ERROR) {
+ camera_dev->stopDevice();
+ mPreviewWindow.stopPreview();
+ }
+
+ return res;
+}
+
+status_t EmulatedCamera::doStopPreview() {
+ ALOGV("%s", __FUNCTION__);
+
+ status_t res = NO_ERROR;
+ if (mPreviewWindow.isPreviewEnabled()) {
+ /* Stop the camera. */
+ if (getCameraDevice()->isStarted()) {
+ getCameraDevice()->stopDeliveringFrames();
+ res = getCameraDevice()->stopDevice();
+ }
+
+ if (res == NO_ERROR) {
+ /* Disable preview as well. */
+ mPreviewWindow.stopPreview();
+ }
+ }
+
+ return NO_ERROR;
+}
+
+/****************************************************************************
+ * Private API.
+ ***************************************************************************/
+
+status_t EmulatedCamera::cleanupCamera() {
+ status_t res = NO_ERROR;
+
+ /* If preview is running - stop it. */
+ res = doStopPreview();
+ if (res != NO_ERROR) {
+ return -res;
+ }
+
+ /* Stop and disconnect the camera device. */
+ EmulatedCameraDevice* const camera_dev = getCameraDevice();
+ if (camera_dev != NULL) {
+ if (camera_dev->isStarted()) {
+ camera_dev->stopDeliveringFrames();
+ res = camera_dev->stopDevice();
+ if (res != NO_ERROR) {
+ return -res;
+ }
+ }
+ if (camera_dev->isConnected()) {
+ res = camera_dev->disconnectDevice();
+ if (res != NO_ERROR) {
+ return -res;
+ }
+ }
+ }
+
+ mCallbackNotifier.cleanupCBNotifier();
+
+ return NO_ERROR;
+}
+
+/****************************************************************************
+ * Camera API callbacks as defined by camera_device_ops structure.
+ *
+ * Callbacks here simply dispatch the calls to an appropriate method inside
+ * EmulatedCamera instance, defined by the 'dev' parameter.
+ ***************************************************************************/
+
+int EmulatedCamera::set_preview_window(struct camera_device* dev,
+ struct preview_stream_ops* window) {
+ EmulatedCamera* ec = reinterpret_cast<EmulatedCamera*>(dev->priv);
+ if (ec == NULL) {
+ ALOGE("%s: Unexpected NULL camera device", __FUNCTION__);
+ return -EINVAL;
+ }
+ return ec->setPreviewWindow(window);
+}
+
+void EmulatedCamera::set_callbacks(
+ struct camera_device* dev, camera_notify_callback notify_cb,
+ camera_data_callback data_cb,
+ camera_data_timestamp_callback data_cb_timestamp,
+ camera_request_memory get_memory, void* user) {
+ EmulatedCamera* ec = reinterpret_cast<EmulatedCamera*>(dev->priv);
+ if (ec == NULL) {
+ ALOGE("%s: Unexpected NULL camera device", __FUNCTION__);
+ return;
+ }
+ ec->setCallbacks(notify_cb, data_cb, data_cb_timestamp, get_memory, user);
+}
+
+void EmulatedCamera::enable_msg_type(struct camera_device* dev,
+ int32_t msg_type) {
+ EmulatedCamera* ec = reinterpret_cast<EmulatedCamera*>(dev->priv);
+ if (ec == NULL) {
+ ALOGE("%s: Unexpected NULL camera device", __FUNCTION__);
+ return;
+ }
+ ec->enableMsgType(msg_type);
+}
+
+void EmulatedCamera::disable_msg_type(struct camera_device* dev,
+ int32_t msg_type) {
+ EmulatedCamera* ec = reinterpret_cast<EmulatedCamera*>(dev->priv);
+ if (ec == NULL) {
+ ALOGE("%s: Unexpected NULL camera device", __FUNCTION__);
+ return;
+ }
+ ec->disableMsgType(msg_type);
+}
+
+int EmulatedCamera::msg_type_enabled(struct camera_device* dev,
+ int32_t msg_type) {
+ EmulatedCamera* ec = reinterpret_cast<EmulatedCamera*>(dev->priv);
+ if (ec == NULL) {
+ ALOGE("%s: Unexpected NULL camera device", __FUNCTION__);
+ return -EINVAL;
+ }
+ return ec->isMsgTypeEnabled(msg_type);
+}
+
+int EmulatedCamera::start_preview(struct camera_device* dev) {
+ EmulatedCamera* ec = reinterpret_cast<EmulatedCamera*>(dev->priv);
+ if (ec == NULL) {
+ ALOGE("%s: Unexpected NULL camera device", __FUNCTION__);
+ return -EINVAL;
+ }
+ return ec->startPreview();
+}
+
+void EmulatedCamera::stop_preview(struct camera_device* dev) {
+ EmulatedCamera* ec = reinterpret_cast<EmulatedCamera*>(dev->priv);
+ if (ec == NULL) {
+ ALOGE("%s: Unexpected NULL camera device", __FUNCTION__);
+ return;
+ }
+ ec->stopPreview();
+}
+
+int EmulatedCamera::preview_enabled(struct camera_device* dev) {
+ EmulatedCamera* ec = reinterpret_cast<EmulatedCamera*>(dev->priv);
+ if (ec == NULL) {
+ ALOGE("%s: Unexpected NULL camera device", __FUNCTION__);
+ return -EINVAL;
+ }
+ return ec->isPreviewEnabled();
+}
+
+int EmulatedCamera::store_meta_data_in_buffers(struct camera_device* dev,
+ int enable) {
+ EmulatedCamera* ec = reinterpret_cast<EmulatedCamera*>(dev->priv);
+ if (ec == NULL) {
+ ALOGE("%s: Unexpected NULL camera device", __FUNCTION__);
+ return -EINVAL;
+ }
+ return ec->storeMetaDataInBuffers(enable);
+}
+
+int EmulatedCamera::start_recording(struct camera_device* dev) {
+ EmulatedCamera* ec = reinterpret_cast<EmulatedCamera*>(dev->priv);
+ if (ec == NULL) {
+ ALOGE("%s: Unexpected NULL camera device", __FUNCTION__);
+ return -EINVAL;
+ }
+ return ec->startRecording();
+}
+
+void EmulatedCamera::stop_recording(struct camera_device* dev) {
+ EmulatedCamera* ec = reinterpret_cast<EmulatedCamera*>(dev->priv);
+ if (ec == NULL) {
+ ALOGE("%s: Unexpected NULL camera device", __FUNCTION__);
+ return;
+ }
+ ec->stopRecording();
+}
+
+int EmulatedCamera::recording_enabled(struct camera_device* dev) {
+ EmulatedCamera* ec = reinterpret_cast<EmulatedCamera*>(dev->priv);
+ if (ec == NULL) {
+ ALOGE("%s: Unexpected NULL camera device", __FUNCTION__);
+ return -EINVAL;
+ }
+ return ec->isRecordingEnabled();
+}
+
+void EmulatedCamera::release_recording_frame(struct camera_device* dev,
+ const void* opaque) {
+ EmulatedCamera* ec = reinterpret_cast<EmulatedCamera*>(dev->priv);
+ if (ec == NULL) {
+ ALOGE("%s: Unexpected NULL camera device", __FUNCTION__);
+ return;
+ }
+ ec->releaseRecordingFrame(opaque);
+}
+
+int EmulatedCamera::auto_focus(struct camera_device* dev) {
+ EmulatedCamera* ec = reinterpret_cast<EmulatedCamera*>(dev->priv);
+ if (ec == NULL) {
+ ALOGE("%s: Unexpected NULL camera device", __FUNCTION__);
+ return -EINVAL;
+ }
+ return ec->setAutoFocus();
+}
+
+int EmulatedCamera::cancel_auto_focus(struct camera_device* dev) {
+ EmulatedCamera* ec = reinterpret_cast<EmulatedCamera*>(dev->priv);
+ if (ec == NULL) {
+ ALOGE("%s: Unexpected NULL camera device", __FUNCTION__);
+ return -EINVAL;
+ }
+ return ec->cancelAutoFocus();
+}
+
+int EmulatedCamera::take_picture(struct camera_device* dev) {
+ EmulatedCamera* ec = reinterpret_cast<EmulatedCamera*>(dev->priv);
+ if (ec == NULL) {
+ ALOGE("%s: Unexpected NULL camera device", __FUNCTION__);
+ return -EINVAL;
+ }
+ return ec->takePicture();
+}
+
+int EmulatedCamera::cancel_picture(struct camera_device* dev) {
+ EmulatedCamera* ec = reinterpret_cast<EmulatedCamera*>(dev->priv);
+ if (ec == NULL) {
+ ALOGE("%s: Unexpected NULL camera device", __FUNCTION__);
+ return -EINVAL;
+ }
+ return ec->cancelPicture();
+}
+
+int EmulatedCamera::set_parameters(struct camera_device* dev,
+ const char* parms) {
+ EmulatedCamera* ec = reinterpret_cast<EmulatedCamera*>(dev->priv);
+ if (ec == NULL) {
+ ALOGE("%s: Unexpected NULL camera device", __FUNCTION__);
+ return -EINVAL;
+ }
+ return ec->setParameters(parms);
+}
+
+char* EmulatedCamera::get_parameters(struct camera_device* dev) {
+ EmulatedCamera* ec = reinterpret_cast<EmulatedCamera*>(dev->priv);
+ if (ec == NULL) {
+ ALOGE("%s: Unexpected NULL camera device", __FUNCTION__);
+ return NULL;
+ }
+ return ec->getParameters();
+}
+
+void EmulatedCamera::put_parameters(struct camera_device* dev, char* params) {
+ EmulatedCamera* ec = reinterpret_cast<EmulatedCamera*>(dev->priv);
+ if (ec == NULL) {
+ ALOGE("%s: Unexpected NULL camera device", __FUNCTION__);
+ return;
+ }
+ ec->putParameters(params);
+}
+
+int EmulatedCamera::send_command(struct camera_device* dev, int32_t cmd,
+ int32_t arg1, int32_t arg2) {
+ EmulatedCamera* ec = reinterpret_cast<EmulatedCamera*>(dev->priv);
+ if (ec == NULL) {
+ ALOGE("%s: Unexpected NULL camera device", __FUNCTION__);
+ return -EINVAL;
+ }
+ return ec->sendCommand(cmd, arg1, arg2);
+}
+
+void EmulatedCamera::release(struct camera_device* dev) {
+ EmulatedCamera* ec = reinterpret_cast<EmulatedCamera*>(dev->priv);
+ if (ec == NULL) {
+ ALOGE("%s: Unexpected NULL camera device", __FUNCTION__);
+ return;
+ }
+ ec->releaseCamera();
+}
+
+int EmulatedCamera::dump(struct camera_device* dev, int fd) {
+ EmulatedCamera* ec = reinterpret_cast<EmulatedCamera*>(dev->priv);
+ if (ec == NULL) {
+ ALOGE("%s: Unexpected NULL camera device", __FUNCTION__);
+ return -EINVAL;
+ }
+ return ec->dumpCamera(fd);
+}
+
+int EmulatedCamera::close(struct hw_device_t* device) {
+ EmulatedCamera* ec = reinterpret_cast<EmulatedCamera*>(
+ reinterpret_cast<struct camera_device*>(device)->priv);
+ if (ec == NULL) {
+ ALOGE("%s: Unexpected NULL camera device", __FUNCTION__);
+ return -EINVAL;
+ }
+ return ec->closeCamera();
+}
+
+/****************************************************************************
+ * Static initializer for the camera callback API
+ ****************************************************************************/
+
+camera_device_ops_t EmulatedCamera::mDeviceOps = {
+ EmulatedCamera::set_preview_window,
+ EmulatedCamera::set_callbacks,
+ EmulatedCamera::enable_msg_type,
+ EmulatedCamera::disable_msg_type,
+ EmulatedCamera::msg_type_enabled,
+ EmulatedCamera::start_preview,
+ EmulatedCamera::stop_preview,
+ EmulatedCamera::preview_enabled,
+ EmulatedCamera::store_meta_data_in_buffers,
+ EmulatedCamera::start_recording,
+ EmulatedCamera::stop_recording,
+ EmulatedCamera::recording_enabled,
+ EmulatedCamera::release_recording_frame,
+ EmulatedCamera::auto_focus,
+ EmulatedCamera::cancel_auto_focus,
+ EmulatedCamera::take_picture,
+ EmulatedCamera::cancel_picture,
+ EmulatedCamera::set_parameters,
+ EmulatedCamera::get_parameters,
+ EmulatedCamera::put_parameters,
+ EmulatedCamera::send_command,
+ EmulatedCamera::release,
+ EmulatedCamera::dump};
+
+/****************************************************************************
+ * Common keys
+ ***************************************************************************/
+
+const char EmulatedCamera::FACING_KEY[] = "prop-facing";
+const char EmulatedCamera::ORIENTATION_KEY[] = "prop-orientation";
+const char EmulatedCamera::RECORDING_HINT_KEY[] = "recording-hint";
+
+/****************************************************************************
+ * Common string values
+ ***************************************************************************/
+
+const char EmulatedCamera::FACING_BACK[] = "back";
+const char EmulatedCamera::FACING_FRONT[] = "front";
+
+/****************************************************************************
+ * Parameter debugging helpers
+ ***************************************************************************/
+
+#if DEBUG_PARAM
+static void PrintParamDiff(const CameraParameters& current,
+ const char* new_par) {
+ char tmp[2048];
+ const char* wrk = new_par;
+
+ /* Divided with ';' */
+ const char* next = strchr(wrk, ';');
+ while (next != NULL) {
+ snprintf(tmp, sizeof(tmp), "%.*s", (int)(intptr_t)(next - wrk), wrk);
+ /* in the form key=value */
+ char* val = strchr(tmp, '=');
+ if (val != NULL) {
+ *val = '\0';
+ val++;
+ const char* in_current = current.get(tmp);
+ if (in_current != NULL) {
+ if (strcmp(in_current, val)) {
+ ALOGD("=== Value changed: %s: %s -> %s", tmp, in_current, val);
+ }
+ } else {
+ ALOGD("+++ New parameter: %s=%s", tmp, val);
+ }
+ } else {
+ ALOGW("No value separator in %s", tmp);
+ }
+ wrk = next + 1;
+ next = strchr(wrk, ';');
+ }
+}
+#endif /* DEBUG_PARAM */
+
+}; /* namespace android */
diff --git a/guest/hals/camera/EmulatedCamera.h b/guest/hals/camera/EmulatedCamera.h
new file mode 100644
index 000000000..a2de643ef
--- /dev/null
+++ b/guest/hals/camera/EmulatedCamera.h
@@ -0,0 +1,407 @@
+/*
+ * Copyright (C) 2011 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 HW_EMULATOR_CAMERA_EMULATED_CAMERA_H
+#define HW_EMULATOR_CAMERA_EMULATED_CAMERA_H
+
+/*
+ * Contains declaration of a class EmulatedCamera that encapsulates
+ * functionality common to all version 1.0 emulated camera devices ("fake",
+ * "webcam", "video file", etc.). Instances of this class (for each emulated
+ * camera) are created during the construction of the EmulatedCameraFactory
+ * instance. This class serves as an entry point for all camera API calls that
+ * defined by camera_device_ops_t API.
+ */
+
+#include <CameraParameters.h>
+using ::android::hardware::camera::common::V1_0::helper::CameraParameters;
+using ::android::hardware::camera::common::V1_0::helper::Size;
+
+#include "CallbackNotifier.h"
+#include "EmulatedBaseCamera.h"
+#include "EmulatedCameraDevice.h"
+#include "PreviewWindow.h"
+
+namespace android {
+
+/* Encapsulates functionality common to all version 1.0 emulated camera devices
+ * ("fake", "webcam", "file stream", etc.).
+ *
+ * Note that EmulatedCameraFactory instantiates object of this class just once,
+ * when EmulatedCameraFactory instance gets constructed. Connection to /
+ * disconnection from the actual camera device is handled by calls to
+ * connectDevice(), and closeCamera() methods of this class that are ivoked in
+ * response to hw_module_methods_t::open, and camera_device::close callbacks.
+ */
+class EmulatedCamera : public camera_device, public EmulatedBaseCamera {
+ public:
+ /* Constructs EmulatedCamera instance.
+ * Param:
+ * cameraId - Zero based camera identifier, which is an index of the camera
+ * instance in camera factory's array.
+ * module - Emulated camera HAL module descriptor.
+ */
+ EmulatedCamera(int cameraId, struct hw_module_t* module);
+
+ /* Destructs EmulatedCamera instance. */
+ virtual ~EmulatedCamera();
+
+ /****************************************************************************
+ * Abstract API
+ ***************************************************************************/
+
+ public:
+ /* Gets emulated camera device used by this instance of the emulated camera.
+ */
+ virtual EmulatedCameraDevice* getCameraDevice() = 0;
+
+ /****************************************************************************
+ * Public API
+ ***************************************************************************/
+
+ public:
+ /** Override of base class method */
+ virtual status_t Initialize(const cvd::CameraDefinition& properties);
+
+ /* Next frame is available in the camera device.
+ * This is a notification callback that is invoked by the camera device when
+ * a new frame is available.
+ * Note that most likely this method is called in context of a worker thread
+ * that camera device has created for frame capturing.
+ * Param:
+ * frame - Captured frame, or NULL if camera device didn't pull the frame
+ * yet. If NULL is passed in this parameter use GetCurrentFrame method
+ * of the camera device class to obtain the next frame. Also note that
+ * the size of the frame that is passed here (as well as the frame
+ * returned from the GetCurrentFrame method) is defined by the current
+ * frame settings (width + height + pixel format) for the camera device.
+ * timestamp - Frame's timestamp.
+ * camera_dev - Camera device instance that delivered the frame.
+ */
+ virtual void onNextFrameAvailable(const void* frame, nsecs_t timestamp,
+ EmulatedCameraDevice* camera_dev);
+
+ /* Entry point for notifications that occur in camera device.
+ * Param:
+ * err - CAMERA_ERROR_XXX error code.
+ */
+ virtual void onCameraDeviceError(int err);
+
+ /* Device acquired focus.
+ * This is a notification callback that is invoked by the camera device
+ * when focusing operation (requested by client) completes.
+ */
+ virtual void onCameraFocusAcquired();
+
+ /****************************************************************************
+ * Camera API implementation
+ ***************************************************************************/
+
+ public:
+ /** Override of base class method */
+ virtual status_t connectCamera(hw_device_t** device);
+
+ /** Override of base class method */
+ virtual status_t closeCamera();
+
+ /** Override of base class method */
+ virtual status_t getCameraInfo(struct camera_info* info);
+
+ /** Override of base class method */
+ virtual const CameraParameters* getCameraParameters() override;
+
+ /****************************************************************************
+ * Camera API implementation.
+ * These methods are called from the camera API callback routines.
+ ***************************************************************************/
+
+ protected:
+ /* Actual handler for camera_device_ops_t::set_preview_window callback.
+ * NOTE: When this method is called the object is locked.
+ * Note that failures in this method are reported as negave EXXX statuses.
+ */
+ virtual status_t setPreviewWindow(struct preview_stream_ops* window);
+
+ /* Actual handler for camera_device_ops_t::set_callbacks callback.
+ * NOTE: When this method is called the object is locked.
+ */
+ virtual void setCallbacks(camera_notify_callback notify_cb,
+ camera_data_callback data_cb,
+ camera_data_timestamp_callback data_cb_timestamp,
+ camera_request_memory get_memory, void* user);
+
+ /* Actual handler for camera_device_ops_t::enable_msg_type callback.
+ * NOTE: When this method is called the object is locked.
+ */
+ virtual void enableMsgType(int32_t msg_type);
+
+ /* Actual handler for camera_device_ops_t::disable_msg_type callback.
+ * NOTE: When this method is called the object is locked.
+ */
+ virtual void disableMsgType(int32_t msg_type);
+
+ /* Actual handler for camera_device_ops_t::msg_type_enabled callback.
+ * NOTE: When this method is called the object is locked.
+ * Return:
+ * 0 if message(s) is (are) disabled, != 0 if enabled.
+ */
+ virtual int isMsgTypeEnabled(int32_t msg_type);
+
+ /* Actual handler for camera_device_ops_t::start_preview callback.
+ * NOTE: When this method is called the object is locked.
+ * Note that failures in this method are reported as negave EXXX statuses.
+ */
+ virtual status_t startPreview();
+
+ /* Actual handler for camera_device_ops_t::stop_preview callback.
+ * NOTE: When this method is called the object is locked.
+ */
+ virtual void stopPreview();
+
+ /* Actual handler for camera_device_ops_t::preview_enabled callback.
+ * NOTE: When this method is called the object is locked.
+ * Return:
+ * 0 if preview is disabled, != 0 if enabled.
+ */
+ virtual int isPreviewEnabled();
+
+ /* Actual handler for camera_device_ops_t::store_meta_data_in_buffers
+ * callback. NOTE: When this method is called the object is locked. Note that
+ * failures in this method are reported as negave EXXX statuses.
+ */
+ virtual status_t storeMetaDataInBuffers(int enable);
+
+ /* Actual handler for camera_device_ops_t::start_recording callback.
+ * NOTE: When this method is called the object is locked.
+ * Note that failures in this method are reported as negave EXXX statuses.
+ */
+ virtual status_t startRecording();
+
+ /* Actual handler for camera_device_ops_t::stop_recording callback.
+ * NOTE: When this method is called the object is locked.
+ */
+ virtual void stopRecording();
+
+ /* Actual handler for camera_device_ops_t::recording_enabled callback.
+ * NOTE: When this method is called the object is locked.
+ * Return:
+ * 0 if recording is disabled, != 0 if enabled.
+ */
+ virtual int isRecordingEnabled();
+
+ /* Actual handler for camera_device_ops_t::release_recording_frame callback.
+ * NOTE: When this method is called the object is locked.
+ */
+ virtual void releaseRecordingFrame(const void* opaque);
+
+ /* Actual handler for camera_device_ops_t::auto_focus callback.
+ * NOTE: When this method is called the object is locked.
+ * Note that failures in this method are reported as negave EXXX statuses.
+ */
+ virtual status_t setAutoFocus();
+
+ /* Actual handler for camera_device_ops_t::cancel_auto_focus callback.
+ * NOTE: When this method is called the object is locked.
+ * Note that failures in this method are reported as negave EXXX statuses.
+ */
+ virtual status_t cancelAutoFocus();
+
+ /* Actual handler for camera_device_ops_t::take_picture callback.
+ * NOTE: When this method is called the object is locked.
+ * Note that failures in this method are reported as negave EXXX statuses.
+ */
+ virtual status_t takePicture();
+
+ /* Actual handler for camera_device_ops_t::cancel_picture callback.
+ * NOTE: When this method is called the object is locked.
+ * Note that failures in this method are reported as negave EXXX statuses.
+ */
+ virtual status_t cancelPicture();
+
+ /* Actual handler for camera_device_ops_t::set_parameters callback.
+ * NOTE: When this method is called the object is locked.
+ * Note that failures in this method are reported as negave EXXX statuses.
+ */
+ virtual status_t setParameters(const char* parms);
+
+ /* Actual handler for camera_device_ops_t::get_parameters callback.
+ * NOTE: When this method is called the object is locked.
+ * Return:
+ * Flattened parameters string. The caller will free the buffer allocated
+ * for the string by calling camera_device_ops_t::put_parameters callback.
+ */
+ virtual char* getParameters();
+
+ /* Actual handler for camera_device_ops_t::put_parameters callback.
+ * Called to free the string returned from camera_device_ops_t::get_parameters
+ * callback. There is nothing more to it: the name of the callback is just
+ * misleading.
+ * NOTE: When this method is called the object is locked.
+ */
+ virtual void putParameters(char* params);
+
+ /* Actual handler for camera_device_ops_t::send_command callback.
+ * NOTE: When this method is called the object is locked.
+ * Note that failures in this method are reported as negave EXXX statuses.
+ */
+ virtual status_t sendCommand(int32_t cmd, int32_t arg1, int32_t arg2);
+
+ /* Actual handler for camera_device_ops_t::release callback.
+ * NOTE: When this method is called the object is locked.
+ */
+ virtual void releaseCamera();
+
+ /* Actual handler for camera_device_ops_t::dump callback.
+ * NOTE: When this method is called the object is locked.
+ * Note that failures in this method are reported as negave EXXX statuses.
+ */
+ virtual status_t dumpCamera(int fd);
+
+ /****************************************************************************
+ * Preview management.
+ ***************************************************************************/
+
+ protected:
+ /* Starts preview.
+ * Note that when this method is called mPreviewWindow may be NULL,
+ * indicating that framework has an intention to start displaying video
+ * frames, but didn't create the preview window yet.
+ * Return:
+ * NO_ERROR on success, or an appropriate error status on failure.
+ */
+ virtual status_t doStartPreview();
+
+ /* Stops preview.
+ * This method reverts DoStartPreview.
+ * Return:
+ * NO_ERROR on success, or an appropriate error status on failure.
+ */
+ virtual status_t doStopPreview();
+
+ /****************************************************************************
+ * Private API.
+ ***************************************************************************/
+
+ protected:
+ /* Cleans up camera when released. */
+ virtual status_t cleanupCamera();
+
+ /****************************************************************************
+ * Camera API callbacks as defined by camera_device_ops structure.
+ * See hardware/libhardware/include/hardware/camera.h for information on
+ * each of these callbacks. Implemented in this class, these callbacks simply
+ * dispatch the call into an instance of EmulatedCamera class defined by the
+ * 'camera_device' parameter.
+ ***************************************************************************/
+
+ private:
+ static int set_preview_window(struct camera_device* dev,
+ struct preview_stream_ops* window);
+
+ static void set_callbacks(struct camera_device* dev,
+ camera_notify_callback notify_cb,
+ camera_data_callback data_cb,
+ camera_data_timestamp_callback data_cb_timestamp,
+ camera_request_memory get_memory, void* user);
+
+ static void enable_msg_type(struct camera_device* dev, int32_t msg_type);
+
+ static void disable_msg_type(struct camera_device* dev, int32_t msg_type);
+
+ static int msg_type_enabled(struct camera_device* dev, int32_t msg_type);
+
+ static int start_preview(struct camera_device* dev);
+
+ static void stop_preview(struct camera_device* dev);
+
+ static int preview_enabled(struct camera_device* dev);
+
+ static int store_meta_data_in_buffers(struct camera_device* dev, int enable);
+
+ static int start_recording(struct camera_device* dev);
+
+ static void stop_recording(struct camera_device* dev);
+
+ static int recording_enabled(struct camera_device* dev);
+
+ static void release_recording_frame(struct camera_device* dev,
+ const void* opaque);
+
+ static int auto_focus(struct camera_device* dev);
+
+ static int cancel_auto_focus(struct camera_device* dev);
+
+ static int take_picture(struct camera_device* dev);
+
+ static int cancel_picture(struct camera_device* dev);
+
+ static int set_parameters(struct camera_device* dev, const char* parms);
+
+ static char* get_parameters(struct camera_device* dev);
+
+ static void put_parameters(struct camera_device* dev, char* params);
+
+ static int send_command(struct camera_device* dev, int32_t cmd, int32_t arg1,
+ int32_t arg2);
+
+ static void release(struct camera_device* dev);
+
+ static int dump(struct camera_device* dev, int fd);
+
+ static int close(struct hw_device_t* device);
+
+ /****************************************************************************
+ * Data members
+ ***************************************************************************/
+
+ protected:
+ /* Locks this instance for parameters, state, etc. change. */
+ Mutex mObjectLock;
+
+ /* Camera parameters. */
+ CameraParameters mParameters;
+
+ /* Preview window. */
+ PreviewWindow mPreviewWindow;
+
+ /* Callback notifier. */
+ CallbackNotifier mCallbackNotifier;
+
+ private:
+ /* Registered callbacks implementing camera API. */
+ static camera_device_ops_t mDeviceOps;
+
+ /****************************************************************************
+ * Common keys
+ ***************************************************************************/
+
+ public:
+ static const char FACING_KEY[];
+ static const char ORIENTATION_KEY[];
+ static const char RECORDING_HINT_KEY[];
+
+ /****************************************************************************
+ * Common string values
+ ***************************************************************************/
+
+ /* Possible values for FACING_KEY */
+ static const char FACING_BACK[];
+ static const char FACING_FRONT[];
+};
+
+}; /* namespace android */
+
+#endif /* HW_EMULATOR_CAMERA_EMULATED_CAMERA_H */
diff --git a/guest/hals/camera/EmulatedCamera2.cpp b/guest/hals/camera/EmulatedCamera2.cpp
new file mode 100644
index 000000000..ccb8006f9
--- /dev/null
+++ b/guest/hals/camera/EmulatedCamera2.cpp
@@ -0,0 +1,381 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+/*
+ * Contains implementation of a class EmulatedCamera that encapsulates
+ * functionality common to all version 2.0 emulated camera devices. Instances
+ * of this class (for each emulated camera) are created during the construction
+ * of the EmulatedCameraFactory instance. This class serves as an entry point
+ * for all camera API calls that defined by camera2_device_ops_t API.
+ */
+
+#define LOG_NDEBUG 0
+#define LOG_TAG "EmulatedCamera2_Camera"
+#include <log/log.h>
+
+#include "EmulatedCamera2.h"
+#include "system/camera_metadata.h"
+
+namespace android {
+
+/* Constructs EmulatedCamera2 instance.
+ * Param:
+ * cameraId - Zero based camera identifier, which is an index of the camera
+ * instance in camera factory's array.
+ * module - Emulated camera HAL module descriptor.
+ */
+EmulatedCamera2::EmulatedCamera2(int cameraId, struct hw_module_t *module)
+ : EmulatedBaseCamera(cameraId, CAMERA_DEVICE_API_VERSION_2_0, &common,
+ module) {
+ common.close = EmulatedCamera2::close;
+ ops = &sDeviceOps;
+ priv = this;
+
+ mNotifyCb = NULL;
+
+ mRequestQueueSrc = NULL;
+ mFrameQueueDst = NULL;
+
+ mVendorTagOps.get_camera_vendor_section_name =
+ EmulatedCamera2::get_camera_vendor_section_name;
+ mVendorTagOps.get_camera_vendor_tag_name =
+ EmulatedCamera2::get_camera_vendor_tag_name;
+ mVendorTagOps.get_camera_vendor_tag_type =
+ EmulatedCamera2::get_camera_vendor_tag_type;
+ mVendorTagOps.parent = this;
+
+ mStatusPresent = true;
+}
+
+/* Destructs EmulatedCamera2 instance. */
+EmulatedCamera2::~EmulatedCamera2() {}
+
+/****************************************************************************
+ * Abstract API
+ ***************************************************************************/
+
+/****************************************************************************
+ * Public API
+ ***************************************************************************/
+
+status_t EmulatedCamera2::Initialize(const cvd::CameraDefinition & /*props*/) {
+ return NO_ERROR;
+}
+
+/****************************************************************************
+ * Camera API implementation
+ ***************************************************************************/
+
+status_t EmulatedCamera2::connectCamera(hw_device_t **device) {
+ *device = &common;
+ return NO_ERROR;
+}
+
+status_t EmulatedCamera2::closeCamera() { return NO_ERROR; }
+
+status_t EmulatedCamera2::getCameraInfo(struct camera_info *info) {
+ return EmulatedBaseCamera::getCameraInfo(info);
+}
+
+/****************************************************************************
+ * Camera Device API implementation.
+ * These methods are called from the camera API callback routines.
+ ***************************************************************************/
+
+/** Request input queue */
+
+int EmulatedCamera2::requestQueueNotify() { return INVALID_OPERATION; }
+
+/** Count of requests in flight */
+int EmulatedCamera2::getInProgressCount() { return INVALID_OPERATION; }
+
+/** Cancel all captures in flight */
+int EmulatedCamera2::flushCapturesInProgress() { return INVALID_OPERATION; }
+
+/** Construct a default request for a given use case */
+int EmulatedCamera2::constructDefaultRequest(int /*request_template*/,
+ camera_metadata_t ** /*request*/) {
+ return INVALID_OPERATION;
+}
+
+/** Output stream creation and management */
+
+int EmulatedCamera2::allocateStream(uint32_t /*width*/, uint32_t /*height*/,
+ int /*format*/,
+ const camera2_stream_ops_t * /*stream_ops*/,
+ uint32_t * /*stream_id*/,
+ uint32_t * /*format_actual*/,
+ uint32_t * /*usage*/,
+ uint32_t * /*max_buffers*/) {
+ return INVALID_OPERATION;
+}
+
+int EmulatedCamera2::registerStreamBuffers(uint32_t /*stream_id*/,
+ int /*num_buffers*/,
+ buffer_handle_t * /*buffers*/) {
+ return INVALID_OPERATION;
+}
+
+int EmulatedCamera2::releaseStream(uint32_t /*stream_id*/) {
+ return INVALID_OPERATION;
+}
+
+/** Reprocessing input stream management */
+
+int EmulatedCamera2::allocateReprocessStream(
+ uint32_t /*width*/, uint32_t /*height*/, uint32_t /*format*/,
+ const camera2_stream_in_ops_t * /*reprocess_stream_ops*/,
+ uint32_t * /*stream_id*/, uint32_t * /*consumer_usage*/,
+ uint32_t * /*max_buffers*/) {
+ return INVALID_OPERATION;
+}
+
+int EmulatedCamera2::allocateReprocessStreamFromStream(
+ uint32_t /*output_stream_id*/,
+ const camera2_stream_in_ops_t * /*reprocess_stream_ops*/,
+ uint32_t * /*stream_id*/) {
+ return INVALID_OPERATION;
+}
+
+int EmulatedCamera2::releaseReprocessStream(uint32_t /*stream_id*/) {
+ return INVALID_OPERATION;
+}
+
+/** 3A triggering */
+
+int EmulatedCamera2::triggerAction(uint32_t /*trigger_id*/, int /*ext1*/,
+ int /*ext2*/) {
+ return INVALID_OPERATION;
+}
+
+/** Custom tag query methods */
+
+const char *EmulatedCamera2::getVendorSectionName(uint32_t /*tag*/) {
+ return NULL;
+}
+
+const char *EmulatedCamera2::getVendorTagName(uint32_t /*tag*/) { return NULL; }
+
+int EmulatedCamera2::getVendorTagType(uint32_t /*tag*/) { return -1; }
+
+/** Debug methods */
+
+int EmulatedCamera2::dump(int /*fd*/) { return INVALID_OPERATION; }
+
+/****************************************************************************
+ * Private API.
+ ***************************************************************************/
+
+/****************************************************************************
+ * Camera API callbacks as defined by camera2_device_ops structure. See
+ * hardware/libhardware/include/hardware/camera2.h for information on each
+ * of these callbacks. Implemented in this class, these callbacks simply
+ * dispatch the call into an instance of EmulatedCamera2 class defined by the
+ * 'camera_device2' parameter, or set a member value in the same.
+ ***************************************************************************/
+
+EmulatedCamera2 *getInstance(const camera2_device_t *d) {
+ const EmulatedCamera2 *cec = static_cast<const EmulatedCamera2 *>(d);
+ return const_cast<EmulatedCamera2 *>(cec);
+}
+
+int EmulatedCamera2::set_request_queue_src_ops(
+ const camera2_device_t *d,
+ const camera2_request_queue_src_ops *queue_src_ops) {
+ EmulatedCamera2 *ec = getInstance(d);
+ ec->mRequestQueueSrc = queue_src_ops;
+ return NO_ERROR;
+}
+
+int EmulatedCamera2::notify_request_queue_not_empty(const camera2_device_t *d) {
+ EmulatedCamera2 *ec = getInstance(d);
+ return ec->requestQueueNotify();
+}
+
+int EmulatedCamera2::set_frame_queue_dst_ops(
+ const camera2_device_t *d,
+ const camera2_frame_queue_dst_ops *queue_dst_ops) {
+ EmulatedCamera2 *ec = getInstance(d);
+ ec->mFrameQueueDst = queue_dst_ops;
+ return NO_ERROR;
+}
+
+int EmulatedCamera2::get_in_progress_count(const camera2_device_t *d) {
+ EmulatedCamera2 *ec = getInstance(d);
+ return ec->getInProgressCount();
+}
+
+int EmulatedCamera2::flush_captures_in_progress(const camera2_device_t *d) {
+ EmulatedCamera2 *ec = getInstance(d);
+ return ec->flushCapturesInProgress();
+}
+
+int EmulatedCamera2::construct_default_request(const camera2_device_t *d,
+ int request_template,
+ camera_metadata_t **request) {
+ EmulatedCamera2 *ec = getInstance(d);
+ return ec->constructDefaultRequest(request_template, request);
+}
+
+int EmulatedCamera2::allocate_stream(const camera2_device_t *d, uint32_t width,
+ uint32_t height, int format,
+ const camera2_stream_ops_t *stream_ops,
+ uint32_t *stream_id,
+ uint32_t *format_actual, uint32_t *usage,
+ uint32_t *max_buffers) {
+ EmulatedCamera2 *ec = getInstance(d);
+ return ec->allocateStream(width, height, format, stream_ops, stream_id,
+ format_actual, usage, max_buffers);
+}
+
+int EmulatedCamera2::register_stream_buffers(const camera2_device_t *d,
+ uint32_t stream_id,
+ int num_buffers,
+ buffer_handle_t *buffers) {
+ EmulatedCamera2 *ec = getInstance(d);
+ return ec->registerStreamBuffers(stream_id, num_buffers, buffers);
+}
+int EmulatedCamera2::release_stream(const camera2_device_t *d,
+ uint32_t stream_id) {
+ EmulatedCamera2 *ec = getInstance(d);
+ return ec->releaseStream(stream_id);
+}
+
+int EmulatedCamera2::allocate_reprocess_stream(
+ const camera2_device_t *d, uint32_t width, uint32_t height, uint32_t format,
+ const camera2_stream_in_ops_t *reprocess_stream_ops, uint32_t *stream_id,
+ uint32_t *consumer_usage, uint32_t *max_buffers) {
+ EmulatedCamera2 *ec = getInstance(d);
+ return ec->allocateReprocessStream(width, height, format,
+ reprocess_stream_ops, stream_id,
+ consumer_usage, max_buffers);
+}
+
+int EmulatedCamera2::allocate_reprocess_stream_from_stream(
+ const camera2_device_t *d, uint32_t output_stream_id,
+ const camera2_stream_in_ops_t *reprocess_stream_ops, uint32_t *stream_id) {
+ EmulatedCamera2 *ec = getInstance(d);
+ return ec->allocateReprocessStreamFromStream(output_stream_id,
+ reprocess_stream_ops, stream_id);
+}
+
+int EmulatedCamera2::release_reprocess_stream(const camera2_device_t *d,
+ uint32_t stream_id) {
+ EmulatedCamera2 *ec = getInstance(d);
+ return ec->releaseReprocessStream(stream_id);
+}
+
+int EmulatedCamera2::trigger_action(const camera2_device_t *d,
+ uint32_t trigger_id, int ext1, int ext2) {
+ EmulatedCamera2 *ec = getInstance(d);
+ return ec->triggerAction(trigger_id, ext1, ext2);
+}
+
+int EmulatedCamera2::set_notify_callback(const camera2_device_t *d,
+ camera2_notify_callback notify_cb,
+ void *user) {
+ EmulatedCamera2 *ec = getInstance(d);
+ Mutex::Autolock l(ec->mMutex);
+ ec->mNotifyCb = notify_cb;
+ ec->mNotifyUserPtr = user;
+ return NO_ERROR;
+}
+
+int EmulatedCamera2::get_instance_metadata(
+ const struct camera2_device *d, camera_metadata **instance_metadata) {
+ EmulatedCamera2 *ec = getInstance(d);
+ if (!ec) {
+ return INVALID_OPERATION;
+ }
+ *instance_metadata = ec->mCameraInfo;
+ return NO_ERROR;
+}
+
+int EmulatedCamera2::get_metadata_vendor_tag_ops(const camera2_device_t *d,
+ vendor_tag_query_ops_t **ops) {
+ EmulatedCamera2 *ec = getInstance(d);
+ *ops = static_cast<vendor_tag_query_ops_t *>(&ec->mVendorTagOps);
+ return NO_ERROR;
+}
+
+const char *EmulatedCamera2::get_camera_vendor_section_name(
+ const vendor_tag_query_ops_t *v, uint32_t tag) {
+ EmulatedCamera2 *ec = static_cast<const TagOps *>(v)->parent;
+ return ec->getVendorSectionName(tag);
+}
+
+const char *EmulatedCamera2::get_camera_vendor_tag_name(
+ const vendor_tag_query_ops_t *v, uint32_t tag) {
+ EmulatedCamera2 *ec = static_cast<const TagOps *>(v)->parent;
+ return ec->getVendorTagName(tag);
+}
+
+int EmulatedCamera2::get_camera_vendor_tag_type(const vendor_tag_query_ops_t *v,
+ uint32_t tag) {
+ EmulatedCamera2 *ec = static_cast<const TagOps *>(v)->parent;
+ return ec->getVendorTagType(tag);
+}
+
+int EmulatedCamera2::dump(const camera2_device_t *d, int fd) {
+ EmulatedCamera2 *ec = getInstance(d);
+ return ec->dump(fd);
+}
+
+int EmulatedCamera2::close(struct hw_device_t *device) {
+ EmulatedCamera2 *ec = static_cast<EmulatedCamera2 *>(
+ reinterpret_cast<camera2_device_t *>(device));
+ if (ec == NULL) {
+ ALOGE("%s: Unexpected NULL camera2 device", __FUNCTION__);
+ return -EINVAL;
+ }
+ return ec->closeCamera();
+}
+
+void EmulatedCamera2::sendNotification(int32_t msgType, int32_t ext1,
+ int32_t ext2, int32_t ext3) {
+ camera2_notify_callback notifyCb;
+ {
+ Mutex::Autolock l(mMutex);
+ notifyCb = mNotifyCb;
+ }
+ if (notifyCb != NULL) {
+ notifyCb(msgType, ext1, ext2, ext3, mNotifyUserPtr);
+ }
+}
+
+camera2_device_ops_t EmulatedCamera2::sDeviceOps = {
+ EmulatedCamera2::set_request_queue_src_ops,
+ EmulatedCamera2::notify_request_queue_not_empty,
+ EmulatedCamera2::set_frame_queue_dst_ops,
+ EmulatedCamera2::get_in_progress_count,
+ EmulatedCamera2::flush_captures_in_progress,
+ EmulatedCamera2::construct_default_request,
+ EmulatedCamera2::allocate_stream,
+ EmulatedCamera2::register_stream_buffers,
+ EmulatedCamera2::release_stream,
+ EmulatedCamera2::allocate_reprocess_stream,
+ EmulatedCamera2::allocate_reprocess_stream_from_stream,
+ EmulatedCamera2::release_reprocess_stream,
+ EmulatedCamera2::trigger_action,
+ EmulatedCamera2::set_notify_callback,
+ EmulatedCamera2::get_metadata_vendor_tag_ops,
+ EmulatedCamera2::dump,
+#ifdef CAMERA_DEVICE_API_VERSION_2_1
+ EmulatedCamera2::get_instance_metadata,
+#endif
+};
+
+}; /* namespace android */
diff --git a/guest/hals/camera/EmulatedCamera2.h b/guest/hals/camera/EmulatedCamera2.h
new file mode 100644
index 000000000..ad8b11382
--- /dev/null
+++ b/guest/hals/camera/EmulatedCamera2.h
@@ -0,0 +1,246 @@
+/*
+ * Copyright (C) 2012 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 HW_EMULATOR_CAMERA_EMULATED_CAMERA2_H
+#define HW_EMULATOR_CAMERA_EMULATED_CAMERA2_H
+
+/*
+ * Contains declaration of a class EmulatedCamera that encapsulates
+ * functionality common to all version 2.0 emulated camera devices. Instances
+ * of this class (for each emulated camera) are created during the construction
+ * of the EmulatedCameraFactory instance. This class serves as an entry point
+ * for all camera API calls that defined by camera2_device_ops_t API.
+ */
+
+#include <utils/Mutex.h>
+#include <utils/Thread.h>
+#include "EmulatedBaseCamera.h"
+#include "hardware/camera2.h"
+#include "system/camera_metadata.h"
+
+namespace android {
+
+/* Encapsulates functionality common to all version 2.0 emulated camera devices
+ *
+ * Note that EmulatedCameraFactory instantiates object of this class just once,
+ * when EmulatedCameraFactory instance gets constructed. Connection to /
+ * disconnection from the actual camera device is handled by calls to
+ * connectDevice(), and closeCamera() methods of this class that are invoked in
+ * response to hw_module_methods_t::open, and camera_device::close callbacks.
+ */
+class EmulatedCamera2 : public camera2_device, public EmulatedBaseCamera {
+ public:
+ /* Constructs EmulatedCamera2 instance.
+ * Param:
+ * cameraId - Zero based camera identifier, which is an index of the camera
+ * instance in camera factory's array.
+ * module - Emulated camera HAL module descriptor.
+ */
+ EmulatedCamera2(int cameraId, struct hw_module_t *module);
+
+ /* Destructs EmulatedCamera2 instance. */
+ virtual ~EmulatedCamera2();
+
+ /****************************************************************************
+ * Abstract API
+ ***************************************************************************/
+
+ public:
+ /****************************************************************************
+ * Public API
+ ***************************************************************************/
+
+ public:
+ virtual status_t Initialize(const cvd::CameraDefinition &props);
+
+ /****************************************************************************
+ * Camera module API and generic hardware device API implementation
+ ***************************************************************************/
+
+ public:
+ virtual status_t connectCamera(hw_device_t **device);
+
+ virtual status_t closeCamera();
+
+ virtual status_t getCameraInfo(struct camera_info *info) = 0;
+
+ /****************************************************************************
+ * Camera API implementation.
+ * These methods are called from the camera API callback routines.
+ ***************************************************************************/
+
+ protected:
+ /** Request input queue notification */
+ virtual int requestQueueNotify();
+
+ /** Count of requests in flight */
+ virtual int getInProgressCount();
+
+ /** Cancel all captures in flight */
+ virtual int flushCapturesInProgress();
+
+ virtual int constructDefaultRequest(int request_template,
+ camera_metadata_t **request);
+
+ /** Output stream creation and management */
+ virtual int allocateStream(uint32_t width, uint32_t height, int format,
+ const camera2_stream_ops_t *stream_ops,
+ uint32_t *stream_id, uint32_t *format_actual,
+ uint32_t *usage, uint32_t *max_buffers);
+
+ virtual int registerStreamBuffers(uint32_t stream_id, int num_buffers,
+ buffer_handle_t *buffers);
+
+ virtual int releaseStream(uint32_t stream_id);
+
+ /** Input stream creation and management */
+ virtual int allocateReprocessStream(
+ uint32_t width, uint32_t height, uint32_t format,
+ const camera2_stream_in_ops_t *reprocess_stream_ops, uint32_t *stream_id,
+ uint32_t *consumer_usage, uint32_t *max_buffers);
+
+ virtual int allocateReprocessStreamFromStream(
+ uint32_t output_stream_id,
+ const camera2_stream_in_ops_t *reprocess_stream_ops, uint32_t *stream_id);
+
+ virtual int releaseReprocessStream(uint32_t stream_id);
+
+ /** 3A action triggering */
+ virtual int triggerAction(uint32_t trigger_id, int32_t ext1, int32_t ext2);
+
+ /** Custom tag definitions */
+ virtual const char *getVendorSectionName(uint32_t tag);
+ virtual const char *getVendorTagName(uint32_t tag);
+ virtual int getVendorTagType(uint32_t tag);
+
+ /** Debug methods */
+
+ virtual int dump(int fd);
+
+ /****************************************************************************
+ * Camera API callbacks as defined by camera2_device_ops structure. See
+ * hardware/libhardware/include/hardware/camera2.h for information on each
+ * of these callbacks. Implemented in this class, these callbacks simply
+ * dispatch the call into an instance of EmulatedCamera2 class defined in
+ * the 'camera_device2' parameter.
+ ***************************************************************************/
+
+ private:
+ /** Input request queue */
+ static int set_request_queue_src_ops(
+ const camera2_device_t *,
+ const camera2_request_queue_src_ops *queue_src_ops);
+ static int notify_request_queue_not_empty(const camera2_device_t *);
+
+ /** Output frame queue */
+ static int set_frame_queue_dst_ops(
+ const camera2_device_t *,
+ const camera2_frame_queue_dst_ops *queue_dst_ops);
+
+ /** In-progress request management */
+ static int get_in_progress_count(const camera2_device_t *);
+
+ static int get_instance_metadata(const struct camera2_device *,
+ camera_metadata **);
+
+ static int flush_captures_in_progress(const camera2_device_t *);
+
+ /** Request template creation */
+ static int construct_default_request(const camera2_device_t *,
+ int request_template,
+ camera_metadata_t **request);
+
+ /** Stream management */
+ static int allocate_stream(const camera2_device_t *, uint32_t width,
+ uint32_t height, int format,
+ const camera2_stream_ops_t *stream_ops,
+ uint32_t *stream_id, uint32_t *format_actual,
+ uint32_t *usage, uint32_t *max_buffers);
+
+ static int register_stream_buffers(const camera2_device_t *,
+ uint32_t stream_id, int num_buffers,
+ buffer_handle_t *buffers);
+
+ static int release_stream(const camera2_device_t *, uint32_t stream_id);
+
+ static int allocate_reprocess_stream(
+ const camera2_device_t *, uint32_t width, uint32_t height,
+ uint32_t format, const camera2_stream_in_ops_t *reprocess_stream_ops,
+ uint32_t *stream_id, uint32_t *consumer_usage, uint32_t *max_buffers);
+
+ static int allocate_reprocess_stream_from_stream(
+ const camera2_device_t *, uint32_t output_stream_id,
+ const camera2_stream_in_ops_t *reprocess_stream_ops, uint32_t *stream_id);
+
+ static int release_reprocess_stream(const camera2_device_t *,
+ uint32_t stream_id);
+
+ /** 3A triggers*/
+ static int trigger_action(const camera2_device_t *, uint32_t trigger_id,
+ int ext1, int ext2);
+
+ /** Notifications to application */
+ static int set_notify_callback(const camera2_device_t *,
+ camera2_notify_callback notify_cb, void *user);
+
+ /** Vendor metadata registration */
+ static int get_metadata_vendor_tag_ops(const camera2_device_t *,
+ vendor_tag_query_ops_t **ops);
+ // for get_metadata_vendor_tag_ops
+ static const char *get_camera_vendor_section_name(
+ const vendor_tag_query_ops_t *, uint32_t tag);
+ static const char *get_camera_vendor_tag_name(const vendor_tag_query_ops_t *,
+ uint32_t tag);
+ static int get_camera_vendor_tag_type(const vendor_tag_query_ops_t *,
+ uint32_t tag);
+
+ static int dump(const camera2_device_t *, int fd);
+
+ /** For hw_device_t ops */
+ static int close(struct hw_device_t *device);
+
+ /****************************************************************************
+ * Data members shared with implementations
+ ***************************************************************************/
+ protected:
+ /** Mutex for calls through camera2 device interface */
+ Mutex mMutex;
+
+ bool mStatusPresent;
+
+ const camera2_request_queue_src_ops *mRequestQueueSrc;
+ const camera2_frame_queue_dst_ops *mFrameQueueDst;
+
+ struct TagOps : public vendor_tag_query_ops {
+ EmulatedCamera2 *parent;
+ };
+ TagOps mVendorTagOps;
+
+ void sendNotification(int32_t msgType, int32_t ext1, int32_t ext2,
+ int32_t ext3);
+
+ /****************************************************************************
+ * Data members
+ ***************************************************************************/
+ private:
+ static camera2_device_ops_t sDeviceOps;
+ camera2_notify_callback mNotifyCb;
+ void *mNotifyUserPtr;
+};
+
+}; /* namespace android */
+
+#endif /* HW_EMULATOR_CAMERA_EMULATED_CAMERA2_H */
diff --git a/guest/hals/camera/EmulatedCamera3.cpp b/guest/hals/camera/EmulatedCamera3.cpp
new file mode 100644
index 000000000..8b8921a25
--- /dev/null
+++ b/guest/hals/camera/EmulatedCamera3.cpp
@@ -0,0 +1,265 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+/**
+ * Contains implementation of a class EmulatedCamera that encapsulates
+ * functionality common to all version 3.0 emulated camera devices. Instances
+ * of this class (for each emulated camera) are created during the construction
+ * of the EmulatedCameraFactory instance. This class serves as an entry point
+ * for all camera API calls that defined by camera3_device_ops_t API.
+ */
+
+#define LOG_NDEBUG 0
+#define LOG_TAG "EmulatedCamera3_Camera"
+#include <log/log.h>
+
+#include "EmulatedCamera3.h"
+#include "system/camera_metadata.h"
+
+namespace android {
+
+/**
+ * Constructs EmulatedCamera3 instance.
+ * Param:
+ * cameraId - Zero based camera identifier, which is an index of the camera
+ * instance in camera factory's array.
+ * module - Emulated camera HAL module descriptor.
+ */
+EmulatedCamera3::EmulatedCamera3(int cameraId, struct hw_module_t* module)
+ : EmulatedBaseCamera(cameraId, CAMERA_DEVICE_API_VERSION_3_3, &common,
+ module),
+ mStatus(STATUS_ERROR) {
+ common.close = EmulatedCamera3::close;
+ ops = &sDeviceOps;
+
+ mCallbackOps = NULL;
+}
+
+/* Destructs EmulatedCamera3 instance. */
+EmulatedCamera3::~EmulatedCamera3() {}
+
+/****************************************************************************
+ * Abstract API
+ ***************************************************************************/
+
+/****************************************************************************
+ * Public API
+ ***************************************************************************/
+
+status_t EmulatedCamera3::Initialize(const cvd::CameraDefinition& /*params*/) {
+ ALOGV("%s", __FUNCTION__);
+
+ mStatus = STATUS_CLOSED;
+ return NO_ERROR;
+}
+
+/****************************************************************************
+ * Camera API implementation
+ ***************************************************************************/
+
+status_t EmulatedCamera3::connectCamera(hw_device_t** device) {
+ ALOGV("%s", __FUNCTION__);
+ if (device == NULL) return BAD_VALUE;
+
+ if (mStatus != STATUS_CLOSED) {
+ ALOGE("%s: Trying to open a camera in state %d!", __FUNCTION__, mStatus);
+ return INVALID_OPERATION;
+ }
+
+ *device = &common;
+ mStatus = STATUS_OPEN;
+ return NO_ERROR;
+}
+
+status_t EmulatedCamera3::closeCamera() {
+ mStatus = STATUS_CLOSED;
+ return NO_ERROR;
+}
+
+status_t EmulatedCamera3::getCameraInfo(struct camera_info* info) {
+ return EmulatedBaseCamera::getCameraInfo(info);
+}
+
+/****************************************************************************
+ * Camera Device API implementation.
+ * These methods are called from the camera API callback routines.
+ ***************************************************************************/
+
+status_t EmulatedCamera3::initializeDevice(
+ const camera3_callback_ops* callbackOps) {
+ if (callbackOps == NULL) {
+ ALOGE("%s: NULL callback ops provided to HAL!", __FUNCTION__);
+ return BAD_VALUE;
+ }
+
+ if (mStatus != STATUS_OPEN) {
+ ALOGE("%s: Trying to initialize a camera in state %d!", __FUNCTION__,
+ mStatus);
+ return INVALID_OPERATION;
+ }
+
+ mCallbackOps = callbackOps;
+ mStatus = STATUS_READY;
+
+ return NO_ERROR;
+}
+
+status_t EmulatedCamera3::configureStreams(
+ camera3_stream_configuration* /*streamList*/) {
+ ALOGE("%s: Not implemented", __FUNCTION__);
+ return INVALID_OPERATION;
+}
+
+status_t EmulatedCamera3::registerStreamBuffers(
+ const camera3_stream_buffer_set* /*bufferSet*/) {
+ ALOGE("%s: Not implemented", __FUNCTION__);
+ return INVALID_OPERATION;
+}
+
+const camera_metadata_t* EmulatedCamera3::constructDefaultRequestSettings(
+ int /*type*/) {
+ ALOGE("%s: Not implemented", __FUNCTION__);
+ return NULL;
+}
+
+status_t EmulatedCamera3::processCaptureRequest(
+ camera3_capture_request* /*request*/) {
+ ALOGE("%s: Not implemented", __FUNCTION__);
+ return INVALID_OPERATION;
+}
+
+status_t EmulatedCamera3::flush() {
+ ALOGE("%s: Not implemented", __FUNCTION__);
+ return INVALID_OPERATION;
+}
+
+/** Debug methods */
+
+void EmulatedCamera3::dump(int /*fd*/) {
+ ALOGE("%s: Not implemented", __FUNCTION__);
+ return;
+}
+
+/****************************************************************************
+ * Protected API. Callbacks to the framework.
+ ***************************************************************************/
+
+void EmulatedCamera3::sendCaptureResult(camera3_capture_result_t* result) {
+ mCallbackOps->process_capture_result(mCallbackOps, result);
+}
+
+void EmulatedCamera3::sendNotify(camera3_notify_msg_t* msg) {
+ mCallbackOps->notify(mCallbackOps, msg);
+}
+
+/****************************************************************************
+ * Private API.
+ ***************************************************************************/
+
+/****************************************************************************
+ * Camera API callbacks as defined by camera3_device_ops structure. See
+ * hardware/libhardware/include/hardware/camera3.h for information on each
+ * of these callbacks. Implemented in this class, these callbacks simply
+ * dispatch the call into an instance of EmulatedCamera3 class defined by the
+ * 'camera_device3' parameter, or set a member value in the same.
+ ***************************************************************************/
+
+EmulatedCamera3* getInstance(const camera3_device_t* d) {
+ const EmulatedCamera3* cec = static_cast<const EmulatedCamera3*>(d);
+ return const_cast<EmulatedCamera3*>(cec);
+}
+
+int EmulatedCamera3::initialize(const struct camera3_device* d,
+ const camera3_callback_ops_t* callback_ops) {
+ EmulatedCamera3* ec = getInstance(d);
+ return ec->initializeDevice(callback_ops);
+}
+
+int EmulatedCamera3::configure_streams(
+ const struct camera3_device* d,
+ camera3_stream_configuration_t* stream_list) {
+ EmulatedCamera3* ec = getInstance(d);
+ return ec->configureStreams(stream_list);
+}
+
+int EmulatedCamera3::register_stream_buffers(
+ const struct camera3_device* d,
+ const camera3_stream_buffer_set_t* buffer_set) {
+ EmulatedCamera3* ec = getInstance(d);
+ return ec->registerStreamBuffers(buffer_set);
+}
+
+int EmulatedCamera3::process_capture_request(
+ const struct camera3_device* d, camera3_capture_request_t* request) {
+ EmulatedCamera3* ec = getInstance(d);
+ return ec->processCaptureRequest(request);
+}
+
+const camera_metadata_t* EmulatedCamera3::construct_default_request_settings(
+ const camera3_device_t* d, int type) {
+ EmulatedCamera3* ec = getInstance(d);
+ return ec->constructDefaultRequestSettings(type);
+}
+
+void EmulatedCamera3::dump(const camera3_device_t* d, int fd) {
+ EmulatedCamera3* ec = getInstance(d);
+ ec->dump(fd);
+}
+
+int EmulatedCamera3::flush(const camera3_device_t* d) {
+ EmulatedCamera3* ec = getInstance(d);
+ return ec->flush();
+}
+
+int EmulatedCamera3::close(struct hw_device_t* device) {
+ EmulatedCamera3* ec = static_cast<EmulatedCamera3*>(
+ reinterpret_cast<camera3_device_t*>(device));
+ if (ec == NULL) {
+ ALOGE("%s: Unexpected NULL camera3 device", __FUNCTION__);
+ return BAD_VALUE;
+ }
+ return ec->closeCamera();
+}
+
+camera3_device_ops_t EmulatedCamera3::sDeviceOps = {
+ EmulatedCamera3::initialize,
+ EmulatedCamera3::configure_streams,
+ /* DEPRECATED: register_stream_buffers */ nullptr,
+ EmulatedCamera3::construct_default_request_settings,
+ EmulatedCamera3::process_capture_request,
+ /* DEPRECATED: get_metadata_vendor_tag_ops */ nullptr,
+ EmulatedCamera3::dump,
+ EmulatedCamera3::flush,
+#ifdef CAMERA_DEVICE_API_VERSION_3_6
+ /*UNUSED: signal_stream_flush*/nullptr,
+ /*UNUSED: is_reconfiguration_required*/nullptr,
+#endif
+ {0}};
+
+const char* EmulatedCamera3::sAvailableCapabilitiesStrings[NUM_CAPABILITIES] = {
+ "BACKWARD_COMPATIBLE",
+ "MANUAL_SENSOR",
+ "MANUAL_POST_PROCESSING",
+ "RAW",
+ "PRIVATE_REPROCESSING",
+ "READ_SENSOR_SETTINGS",
+ "BURST_CAPTURE",
+ "YUV_REPROCESSING",
+ "DEPTH_OUTPUT",
+ "CONSTRAINED_HIGH_SPEED_VIDEO",
+ "FULL_LEVEL"};
+
+}; /* namespace android */
diff --git a/guest/hals/camera/EmulatedCamera3.h b/guest/hals/camera/EmulatedCamera3.h
new file mode 100644
index 000000000..92fbb4d77
--- /dev/null
+++ b/guest/hals/camera/EmulatedCamera3.h
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2013 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 HW_EMULATOR_CAMERA_EMULATED_CAMERA3_H
+#define HW_EMULATOR_CAMERA_EMULATED_CAMERA3_H
+
+/**
+ * Contains declaration of a class EmulatedCamera that encapsulates
+ * functionality common to all version 3.0 emulated camera devices. Instances
+ * of this class (for each emulated camera) are created during the construction
+ * of the EmulatedCameraFactory instance. This class serves as an entry point
+ * for all camera API calls that defined by camera3_device_ops_t API.
+ */
+
+#include "EmulatedBaseCamera.h"
+#include "hardware/camera3.h"
+#include "system/camera_metadata.h"
+
+namespace android {
+
+/**
+ * Encapsulates functionality common to all version 3.0 emulated camera devices
+ *
+ * Note that EmulatedCameraFactory instantiates an object of this class just
+ * once, when EmulatedCameraFactory instance gets constructed. Connection to /
+ * disconnection from the actual camera device is handled by calls to
+ * connectDevice(), and closeCamera() methods of this class that are invoked in
+ * response to hw_module_methods_t::open, and camera_device::close callbacks.
+ */
+class EmulatedCamera3 : public camera3_device, public EmulatedBaseCamera {
+ public:
+ /* Constructs EmulatedCamera3 instance.
+ * Param:
+ * cameraId - Zero based camera identifier, which is an index of the camera
+ * instance in camera factory's array.
+ * module - Emulated camera HAL module descriptor.
+ */
+ EmulatedCamera3(int cameraId, struct hw_module_t *module);
+
+ /* Destructs EmulatedCamera2 instance. */
+ virtual ~EmulatedCamera3();
+
+ /* List of all defined capabilities plus useful HW levels */
+ enum AvailableCapabilities {
+ BACKWARD_COMPATIBLE,
+ MANUAL_SENSOR,
+ MANUAL_POST_PROCESSING,
+ RAW,
+ PRIVATE_REPROCESSING,
+ READ_SENSOR_SETTINGS,
+ BURST_CAPTURE,
+ YUV_REPROCESSING,
+ DEPTH_OUTPUT,
+ CONSTRAINED_HIGH_SPEED_VIDEO,
+ // Levels
+ FULL_LEVEL,
+
+ NUM_CAPABILITIES
+ };
+
+ // Char strings for above enum, with size NUM_CAPABILITIES
+ static const char *sAvailableCapabilitiesStrings[];
+
+ /****************************************************************************
+ * Abstract API
+ ***************************************************************************/
+
+ public:
+ /****************************************************************************
+ * Public API
+ ***************************************************************************/
+
+ public:
+ virtual status_t Initialize(const cvd::CameraDefinition &params);
+
+ /****************************************************************************
+ * Camera module API and generic hardware device API implementation
+ ***************************************************************************/
+
+ public:
+ virtual status_t connectCamera(hw_device_t **device);
+
+ virtual status_t closeCamera();
+
+ virtual status_t getCameraInfo(struct camera_info *info);
+
+ /****************************************************************************
+ * Camera API implementation.
+ * These methods are called from the camera API callback routines.
+ ***************************************************************************/
+
+ protected:
+ virtual status_t initializeDevice(const camera3_callback_ops *callbackOps);
+
+ virtual status_t configureStreams(camera3_stream_configuration *streamList);
+
+ virtual status_t registerStreamBuffers(
+ const camera3_stream_buffer_set *bufferSet);
+
+ virtual const camera_metadata_t *constructDefaultRequestSettings(int type);
+
+ virtual status_t processCaptureRequest(camera3_capture_request *request);
+
+ virtual status_t flush();
+
+ /** Debug methods */
+
+ virtual void dump(int fd);
+
+ /****************************************************************************
+ * Camera API callbacks as defined by camera3_device_ops structure. See
+ * hardware/libhardware/include/hardware/camera3.h for information on each
+ * of these callbacks. Implemented in this class, these callbacks simply
+ * dispatch the call into an instance of EmulatedCamera3 class defined in
+ * the 'camera_device3' parameter.
+ ***************************************************************************/
+
+ private:
+ /** Startup */
+ static int initialize(const struct camera3_device *,
+ const camera3_callback_ops_t *callback_ops);
+
+ /** Stream configuration and buffer registration */
+
+ static int configure_streams(const struct camera3_device *,
+ camera3_stream_configuration_t *stream_list);
+
+ static int register_stream_buffers(
+ const struct camera3_device *,
+ const camera3_stream_buffer_set_t *buffer_set);
+
+ /** Template request settings provision */
+
+ static const camera_metadata_t *construct_default_request_settings(
+ const struct camera3_device *, int type);
+
+ /** Submission of capture requests to HAL */
+
+ static int process_capture_request(const struct camera3_device *,
+ camera3_capture_request_t *request);
+
+ static void dump(const camera3_device_t *, int fd);
+
+ static int flush(const camera3_device_t *);
+
+ /** For hw_device_t ops */
+ static int close(struct hw_device_t *device);
+
+ /****************************************************************************
+ * Data members shared with implementations
+ ***************************************************************************/
+ protected:
+ enum {
+ // State at construction time, and after a device operation error
+ STATUS_ERROR = 0,
+ // State after startup-time init and after device instance close
+ STATUS_CLOSED,
+ // State after being opened, before device instance init
+ STATUS_OPEN,
+ // State after device instance initialization
+ STATUS_READY,
+ // State while actively capturing data
+ STATUS_ACTIVE
+ } mStatus;
+
+ /**
+ * Callbacks back to the framework
+ */
+
+ void sendCaptureResult(camera3_capture_result_t *result);
+ void sendNotify(camera3_notify_msg_t *msg);
+
+ /****************************************************************************
+ * Data members
+ ***************************************************************************/
+ private:
+ static camera3_device_ops_t sDeviceOps;
+ const camera3_callback_ops_t *mCallbackOps;
+};
+
+}; /* namespace android */
+
+#endif /* HW_EMULATOR_CAMERA_EMULATED_CAMERA3_H */
diff --git a/guest/hals/camera/EmulatedCameraCommon.h b/guest/hals/camera/EmulatedCameraCommon.h
new file mode 100644
index 000000000..0ec75011d
--- /dev/null
+++ b/guest/hals/camera/EmulatedCameraCommon.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2011 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 HW_EMULATOR_CAMERA_EMULATED_CAMERA_COMMON_H
+#define HW_EMULATOR_CAMERA_EMULATED_CAMERA_COMMON_H
+
+/*
+ * Contains common declarations that are used across the camera emulation.
+ */
+
+#include <hardware/camera.h>
+#include <linux/videodev2.h>
+
+/* A helper class that tracks a routine execution.
+ * Basically, it dumps an enry message in its constructor, and an exit message
+ * in its destructor. Use LOGRE() macro (declared bellow) to create instances
+ * of this class at the beginning of the tracked routines / methods.
+ */
+class HWERoutineTracker {
+ public:
+ /* Constructor that prints an "entry" trace message. */
+ explicit HWERoutineTracker(const char* name) : mName(name) {
+ ALOGV("Entering %s", mName);
+ }
+
+ /* Destructor that prints a "leave" trace message. */
+ ~HWERoutineTracker() { ALOGV("Leaving %s", mName); }
+
+ private:
+ /* Stores the routine name. */
+ const char* mName;
+};
+
+/* Logs an execution of a routine / method. */
+#define LOGRE() HWERoutineTracker hwertracker_##__LINE__(__FUNCTION__)
+
+/*
+ * min / max macros
+ */
+
+#define min(a, b) (((a) < (b)) ? (a) : (b))
+#define max(a, b) (((a) > (b)) ? (a) : (b))
+
+#endif /* HW_EMULATOR_CAMERA_EMULATED_CAMERA_COMMON_H */
diff --git a/guest/hals/camera/EmulatedCameraDevice.cpp b/guest/hals/camera/EmulatedCameraDevice.cpp
new file mode 100644
index 000000000..d741b737c
--- /dev/null
+++ b/guest/hals/camera/EmulatedCameraDevice.cpp
@@ -0,0 +1,418 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+/*
+ * Contains implementation of an abstract class EmulatedCameraDevice that
+ * defines functionality expected from an emulated physical camera device:
+ * - Obtaining and setting camera parameters
+ * - Capturing frames
+ * - Streaming video
+ * - etc.
+ */
+
+#define LOG_NDEBUG 0
+#define LOG_TAG "EmulatedCamera_Device"
+#include "EmulatedCameraDevice.h"
+#include <log/log.h>
+#include <sys/select.h>
+#include <algorithm>
+#include <cmath>
+#include "EmulatedCamera.h"
+
+namespace android {
+
+const float GAMMA_CORRECTION = 2.2f;
+EmulatedCameraDevice::EmulatedCameraDevice(EmulatedCamera* camera_hal)
+ : mObjectLock(),
+ mCurFrameTimestamp(0),
+ mCameraHAL(camera_hal),
+ mCurrentFrame(NULL),
+ mExposureCompensation(1.0f),
+ mWhiteBalanceScale(NULL),
+ mIsFocusing(false),
+ mSupportedWhiteBalanceScale(),
+ mState(ECDS_CONSTRUCTED) {}
+
+EmulatedCameraDevice::~EmulatedCameraDevice() {
+ ALOGV("EmulatedCameraDevice destructor");
+ if (mCurrentFrame != NULL) {
+ delete[] mCurrentFrame;
+ }
+ for (size_t i = 0; i < mSupportedWhiteBalanceScale.size(); ++i) {
+ if (mSupportedWhiteBalanceScale.valueAt(i) != NULL) {
+ delete[] mSupportedWhiteBalanceScale.valueAt(i);
+ }
+ }
+}
+
+/****************************************************************************
+ * Emulated camera device public API
+ ***************************************************************************/
+
+status_t EmulatedCameraDevice::Initialize() {
+ if (isInitialized()) {
+ ALOGW("%s: Emulated camera device is already initialized: mState = %d",
+ __FUNCTION__, mState);
+ return NO_ERROR;
+ }
+
+ /* Instantiate worker thread object. */
+ mWorkerThread = new WorkerThread(this);
+ if (getWorkerThread() == NULL) {
+ ALOGE("%s: Unable to instantiate worker thread object", __FUNCTION__);
+ return ENOMEM;
+ }
+
+ mState = ECDS_INITIALIZED;
+
+ return NO_ERROR;
+}
+
+status_t EmulatedCameraDevice::startDeliveringFrames(bool one_burst) {
+ ALOGV("%s", __FUNCTION__);
+
+ if (!isStarted()) {
+ ALOGE("%s: Device is not started", __FUNCTION__);
+ return EINVAL;
+ }
+
+ /* Frames will be delivered from the thread routine. */
+ const status_t res = startWorkerThread(one_burst);
+ ALOGE_IF(res != NO_ERROR, "%s: startWorkerThread failed", __FUNCTION__);
+ return res;
+}
+
+status_t EmulatedCameraDevice::stopDeliveringFrames() {
+ ALOGV("%s", __FUNCTION__);
+
+ if (!isStarted()) {
+ ALOGW("%s: Device is not started", __FUNCTION__);
+ return NO_ERROR;
+ }
+
+ const status_t res = stopWorkerThread();
+ ALOGE_IF(res != NO_ERROR, "%s: startWorkerThread failed", __FUNCTION__);
+ return res;
+}
+
+void EmulatedCameraDevice::setExposureCompensation(const float ev) {
+ ALOGV("%s", __FUNCTION__);
+
+ if (!isStarted()) {
+ ALOGW("%s: Fake camera device is not started.", __FUNCTION__);
+ }
+
+ mExposureCompensation = std::pow(2.0f, ev / GAMMA_CORRECTION);
+ ALOGV("New exposure compensation is %f", mExposureCompensation);
+}
+
+void EmulatedCameraDevice::initializeWhiteBalanceModes(const char* mode,
+ const float r_scale,
+ const float b_scale) {
+ ALOGV("%s with %s, %f, %f", __FUNCTION__, mode, r_scale, b_scale);
+ float* value = new float[3];
+ value[0] = r_scale;
+ value[1] = 1.0f;
+ value[2] = b_scale;
+ mSupportedWhiteBalanceScale.add(String8(mode), value);
+}
+
+void EmulatedCameraDevice::setWhiteBalanceMode(const char* mode) {
+ ALOGV("%s with white balance %s", __FUNCTION__, mode);
+ mWhiteBalanceScale = mSupportedWhiteBalanceScale.valueFor(String8(mode));
+}
+
+void EmulatedCameraDevice::startAutoFocus() { mIsFocusing = true; }
+
+/* Computes the pixel value after adjusting the white balance to the current
+ * one. The input the y, u, v channel of the pixel and the adjusted value will
+ * be stored in place. The adjustment is done in RGB space.
+ */
+void EmulatedCameraDevice::changeWhiteBalance(uint8_t& y, uint8_t& u,
+ uint8_t& v) const {
+ float r_scale = mWhiteBalanceScale[0];
+ float b_scale = mWhiteBalanceScale[2];
+ int r = static_cast<float>(YUV2R(y, u, v)) / r_scale;
+ int g = YUV2G(y, u, v);
+ int b = static_cast<float>(YUV2B(y, u, v)) / b_scale;
+
+ y = RGB2Y(r, g, b);
+ u = RGB2U(r, g, b);
+ v = RGB2V(r, g, b);
+}
+
+void EmulatedCameraDevice::simulateAutoFocus() {
+ if (mIsFocusing) {
+ ALOGV("%s: Simulating auto-focus", __FUNCTION__);
+ mCameraHAL->onCameraFocusAcquired();
+ mIsFocusing = false;
+ }
+}
+
+status_t EmulatedCameraDevice::getCurrentPreviewFrame(void* buffer) {
+ if (!isStarted()) {
+ ALOGE("%s: Device is not started", __FUNCTION__);
+ return EINVAL;
+ }
+ if (mCurrentFrame == NULL || buffer == NULL) {
+ ALOGE("%s: No framebuffer", __FUNCTION__);
+ return EINVAL;
+ }
+
+ /* In emulation the framebuffer is never RGB. */
+ switch (mPixelFormat) {
+ case V4L2_PIX_FMT_YVU420:
+ YV12ToRGB32(mCurrentFrame, buffer, mFrameWidth, mFrameHeight);
+ return NO_ERROR;
+ case V4L2_PIX_FMT_YUV420:
+ YU12ToRGB32(mCurrentFrame, buffer, mFrameWidth, mFrameHeight);
+ return NO_ERROR;
+ case V4L2_PIX_FMT_NV21:
+ NV21ToRGB32(mCurrentFrame, buffer, mFrameWidth, mFrameHeight);
+ return NO_ERROR;
+ case V4L2_PIX_FMT_NV12:
+ NV12ToRGB32(mCurrentFrame, buffer, mFrameWidth, mFrameHeight);
+ return NO_ERROR;
+
+ default:
+ ALOGE("%s: Unknown pixel format %.4s", __FUNCTION__,
+ reinterpret_cast<const char*>(&mPixelFormat));
+ return EINVAL;
+ }
+}
+
+/****************************************************************************
+ * Emulated camera device private API
+ ***************************************************************************/
+
+status_t EmulatedCameraDevice::commonStartDevice(int width, int height,
+ uint32_t pix_fmt, int fps) {
+ /* Validate pixel format, and calculate framebuffer size at the same time. */
+ switch (pix_fmt) {
+ case V4L2_PIX_FMT_YVU420:
+ case V4L2_PIX_FMT_YUV420:
+ case V4L2_PIX_FMT_NV21:
+ case V4L2_PIX_FMT_NV12:
+ mFrameBufferSize = (width * height * 12) / 8;
+ break;
+
+ default:
+ ALOGE("%s: Unknown pixel format %.4s", __FUNCTION__,
+ reinterpret_cast<const char*>(&pix_fmt));
+ return EINVAL;
+ }
+
+ /* Cache framebuffer info. */
+ mFrameWidth = width;
+ mFrameHeight = height;
+ mPixelFormat = pix_fmt;
+ mTotalPixels = width * height;
+ mTargetFps = fps;
+
+ /* Allocate framebuffer. */
+ mCurrentFrame = new uint8_t[mFrameBufferSize];
+ if (mCurrentFrame == NULL) {
+ ALOGE("%s: Unable to allocate framebuffer", __FUNCTION__);
+ return ENOMEM;
+ }
+ ALOGV("%s: Allocated %p %zu bytes for %d pixels in %.4s[%dx%d] frame",
+ __FUNCTION__, mCurrentFrame, mFrameBufferSize, mTotalPixels,
+ reinterpret_cast<const char*>(&mPixelFormat), mFrameWidth,
+ mFrameHeight);
+ return NO_ERROR;
+}
+
+void EmulatedCameraDevice::commonStopDevice() {
+ mFrameWidth = mFrameHeight = mTotalPixels = 0;
+ mPixelFormat = 0;
+ mTargetFps = 0;
+
+ if (mCurrentFrame != NULL) {
+ delete[] mCurrentFrame;
+ mCurrentFrame = NULL;
+ }
+}
+
+const CameraParameters* EmulatedCameraDevice::getCameraParameters() {
+ return mCameraHAL->getCameraParameters();
+}
+
+/****************************************************************************
+ * Worker thread management.
+ ***************************************************************************/
+
+status_t EmulatedCameraDevice::startWorkerThread(bool one_burst) {
+ ALOGV("%s", __FUNCTION__);
+
+ if (!isInitialized()) {
+ ALOGE("%s: Emulated camera device is not initialized", __FUNCTION__);
+ return EINVAL;
+ }
+
+ const status_t res = getWorkerThread()->startThread(one_burst);
+ ALOGE_IF(res != NO_ERROR, "%s: Unable to start worker thread", __FUNCTION__);
+ return res;
+}
+
+status_t EmulatedCameraDevice::stopWorkerThread() {
+ ALOGV("%s", __FUNCTION__);
+
+ if (!isInitialized()) {
+ ALOGE("%s: Emulated camera device is not initialized", __FUNCTION__);
+ return EINVAL;
+ }
+
+ const status_t res = getWorkerThread()->stopThread();
+ ALOGE_IF(res != NO_ERROR, "%s: Unable to stop worker thread", __FUNCTION__);
+ return res;
+}
+
+bool EmulatedCameraDevice::inWorkerThread() {
+ /* This will end the thread loop, and will terminate the thread. Derived
+ * classes must override this method. */
+ return false;
+}
+
+/****************************************************************************
+ * Worker thread implementation.
+ ***************************************************************************/
+
+status_t EmulatedCameraDevice::WorkerThread::readyToRun() {
+ ALOGV("Starting emulated camera device worker thread...");
+
+ ALOGW_IF(mThreadControl >= 0 || mControlFD >= 0,
+ "%s: Thread control FDs are opened", __FUNCTION__);
+ /* Create a pair of FDs that would be used to control the thread. */
+ int thread_fds[2];
+ status_t ret;
+ Mutex::Autolock lock(mCameraDevice->mObjectLock);
+ if (pipe(thread_fds) == 0) {
+ mThreadControl = thread_fds[1];
+ mControlFD = thread_fds[0];
+ ALOGV("Emulated device's worker thread has been started.");
+ ret = NO_ERROR;
+ } else {
+ ALOGE("%s: Unable to create thread control FDs: %d -> %s", __FUNCTION__,
+ errno, strerror(errno));
+ ret = errno;
+ }
+
+ mSetup.signal();
+ return ret;
+}
+
+status_t EmulatedCameraDevice::WorkerThread::stopThread() {
+ ALOGV("Stopping emulated camera device's worker thread...");
+
+ status_t res = EINVAL;
+
+ // Limit the scope of the Autolock
+ {
+ // If thread is running and readyToRun() has not finished running,
+ // then wait until it is done.
+ Mutex::Autolock lock(mCameraDevice->mObjectLock);
+ if (isRunning() && (mThreadControl < 0 || mControlFD < 0)) {
+ mSetup.wait(mCameraDevice->mObjectLock);
+ }
+ }
+
+ if (mThreadControl >= 0) {
+ /* Send "stop" message to the thread loop. */
+ const ControlMessage msg = THREAD_STOP;
+ const int wres =
+ TEMP_FAILURE_RETRY(write(mThreadControl, &msg, sizeof(msg)));
+ if (wres == sizeof(msg)) {
+ /* Stop the thread, and wait till it's terminated. */
+ res = requestExitAndWait();
+ if (res == NO_ERROR) {
+ /* Close control FDs. */
+ if (mThreadControl >= 0) {
+ close(mThreadControl);
+ mThreadControl = -1;
+ }
+ if (mControlFD >= 0) {
+ close(mControlFD);
+ mControlFD = -1;
+ }
+ ALOGV("Emulated camera device's worker thread has been stopped.");
+ } else {
+ ALOGE("%s: requestExitAndWait failed: %d -> %s", __FUNCTION__, res,
+ strerror(-res));
+ }
+ } else {
+ ALOGE("%s: Unable to send THREAD_STOP message: %d -> %s", __FUNCTION__,
+ errno, strerror(errno));
+ res = errno ? errno : EINVAL;
+ }
+ } else {
+ ALOGE("%s: Thread control FDs are not opened", __FUNCTION__);
+ }
+
+ return res;
+}
+
+EmulatedCameraDevice::WorkerThread::SelectRes
+EmulatedCameraDevice::WorkerThread::Select(int fd, int timeout) {
+ fd_set fds[1];
+ struct timeval tv, *tvp = NULL;
+
+ mCameraDevice->simulateAutoFocus();
+
+ const int fd_num = (fd >= 0) ? std::max(fd, mControlFD) + 1 : mControlFD + 1;
+ FD_ZERO(fds);
+ FD_SET(mControlFD, fds);
+ if (fd >= 0) {
+ FD_SET(fd, fds);
+ }
+ if (timeout) {
+ tv.tv_sec = timeout / 1000000;
+ tv.tv_usec = timeout % 1000000;
+ tvp = &tv;
+ }
+ int res = TEMP_FAILURE_RETRY(select(fd_num, fds, NULL, NULL, tvp));
+ if (res < 0) {
+ ALOGE("%s: select returned %d and failed: %d -> %s", __FUNCTION__, res,
+ errno, strerror(errno));
+ return ERROR;
+ } else if (res == 0) {
+ /* Timeout. */
+ return TIMEOUT;
+ } else if (FD_ISSET(mControlFD, fds)) {
+ /* A control event. Lets read the message. */
+ ControlMessage msg;
+ res = TEMP_FAILURE_RETRY(read(mControlFD, &msg, sizeof(msg)));
+ if (res != sizeof(msg)) {
+ ALOGE("%s: Unexpected message size %d, or an error %d -> %s",
+ __FUNCTION__, res, errno, strerror(errno));
+ return ERROR;
+ }
+ /* THREAD_STOP is the only message expected here. */
+ if (msg == THREAD_STOP) {
+ ALOGV("%s: THREAD_STOP message is received", __FUNCTION__);
+ return EXIT_THREAD;
+ } else {
+ ALOGE("Unknown worker thread message %d", msg);
+ return ERROR;
+ }
+ } else {
+ /* Must be an FD. */
+ ALOGW_IF(fd < 0 || !FD_ISSET(fd, fds), "%s: Undefined 'select' result",
+ __FUNCTION__);
+ return READY;
+ }
+}
+
+}; /* namespace android */
diff --git a/guest/hals/camera/EmulatedCameraDevice.h b/guest/hals/camera/EmulatedCameraDevice.h
new file mode 100644
index 000000000..ab654eb35
--- /dev/null
+++ b/guest/hals/camera/EmulatedCameraDevice.h
@@ -0,0 +1,553 @@
+/*
+ * Copyright (C) 2011 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 HW_EMULATOR_CAMERA_EMULATED_CAMERA_DEVICE_H
+#define HW_EMULATOR_CAMERA_EMULATED_CAMERA_DEVICE_H
+
+/*
+ * Contains declaration of an abstract class EmulatedCameraDevice that defines
+ * functionality expected from an emulated physical camera device:
+ * - Obtaining and setting camera device parameters
+ * - Capturing frames
+ * - Streaming video
+ * - etc.
+ */
+
+#include <utils/KeyedVector.h>
+#include <utils/String8.h>
+#include <utils/threads.h>
+#include "Converters.h"
+#include "EmulatedCameraCommon.h"
+
+#include <CameraParameters.h>
+
+using ::android::hardware::camera::common::V1_0::helper::CameraParameters;
+
+namespace android {
+
+class EmulatedCamera;
+
+/* Encapsulates an abstract class EmulatedCameraDevice that defines
+ * functionality expected from an emulated physical camera device:
+ * - Obtaining and setting camera device parameters
+ * - Capturing frames
+ * - Streaming video
+ * - etc.
+ */
+class EmulatedCameraDevice {
+ public:
+ /* Constructs EmulatedCameraDevice instance.
+ * Param:
+ * camera_hal - Emulated camera that implements the camera HAL API, and
+ * manages (contains) this object.
+ */
+ explicit EmulatedCameraDevice(EmulatedCamera* camera_hal);
+
+ /* Destructs EmulatedCameraDevice instance. */
+ virtual ~EmulatedCameraDevice();
+
+ /***************************************************************************
+ * Emulated camera device abstract interface
+ **************************************************************************/
+
+ public:
+ /* Connects to the camera device.
+ * This method must be called on an initialized instance of this class.
+ * Return:
+ * NO_ERROR on success, or an appropriate error status.
+ */
+ virtual status_t connectDevice() = 0;
+
+ /* Disconnects from the camera device.
+ * Return:
+ * NO_ERROR on success, or an appropriate error status. If this method is
+ * called for already disconnected, or uninitialized instance of this class,
+ * a successful status must be returned from this method. If this method is
+ * called for an instance that is in the "started" state, this method must
+ * return a failure.
+ */
+ virtual status_t disconnectDevice() = 0;
+
+ /* Starts the camera device.
+ * This method tells the camera device to start capturing frames of the given
+ * dimensions for the given pixel format. Note that this method doesn't start
+ * the delivery of the captured frames to the emulated camera. Call
+ * startDeliveringFrames method to start delivering frames. This method must
+ * be called on a connected instance of this class. If it is called on a
+ * disconnected instance, this method must return a failure.
+ * Param:
+ * width, height - Frame dimensions to use when capturing video frames.
+ * pix_fmt - Pixel format to use when capturing video frames.
+ * fps - Target rate of frames per second.
+ * Return:
+ * NO_ERROR on success, or an appropriate error status.
+ */
+ virtual status_t startDevice(int width, int height, uint32_t pix_fmt,
+ int fps) = 0;
+
+ /* Stops the camera device.
+ * This method tells the camera device to stop capturing frames. Note that
+ * this method doesn't stop delivering frames to the emulated camera. Always
+ * call stopDeliveringFrames prior to calling this method.
+ * Return:
+ * NO_ERROR on success, or an appropriate error status. If this method is
+ * called for an object that is not capturing frames, or is disconnected,
+ * or is uninitialized, a successful status must be returned from this
+ * method.
+ */
+ virtual status_t stopDevice() = 0;
+
+ /***************************************************************************
+ * Emulated camera device public API
+ **************************************************************************/
+
+ public:
+ /* Initializes EmulatedCameraDevice instance.
+ * Derived classes should override this method in order to cache static
+ * properties of the physical device (list of supported pixel formats, frame
+ * sizes, etc.) If this method is called on an already initialized instance,
+ * it must return a successful status.
+ * Return:
+ * NO_ERROR on success, or an appropriate error status.
+ */
+ virtual status_t Initialize();
+
+ /* Initializes the white balance modes parameters.
+ * The parameters are passed by each individual derived camera API to
+ * represent that different camera manufacturers may have different
+ * preferences on the white balance parameters. Green channel in the RGB
+ * color space is fixed to keep the luminance to be reasonably constant.
+ *
+ * Param:
+ * mode the text describing the current white balance mode
+ * r_scale the scale factor for the R channel in RGB space
+ * b_scale the scale factor for the B channel in RGB space.
+ */
+ void initializeWhiteBalanceModes(const char* mode, const float r_scale,
+ const float b_scale);
+
+ /* Starts delivering frames captured from the camera device.
+ * This method will start the worker thread that would be pulling frames from
+ * the camera device, and will deliver the pulled frames back to the emulated
+ * camera via onNextFrameAvailable callback. This method must be called on a
+ * connected instance of this class with a started camera device. If it is
+ * called on a disconnected instance, or camera device has not been started,
+ * this method must return a failure.
+ * Param:
+ * one_burst - Controls how many frames should be delivered. If this
+ * parameter is 'true', only one captured frame will be delivered to the
+ * emulated camera. If this parameter is 'false', frames will keep
+ * coming until stopDeliveringFrames method is called. Typically, this
+ * parameter is set to 'true' only in order to obtain a single frame
+ * that will be used as a "picture" in takePicture method of the
+ * emulated camera.
+ * Return:
+ * NO_ERROR on success, or an appropriate error status.
+ */
+ virtual status_t startDeliveringFrames(bool one_burst);
+
+ /* Stops delivering frames captured from the camera device.
+ * This method will stop the worker thread started by startDeliveringFrames.
+ * Return:
+ * NO_ERROR on success, or an appropriate error status.
+ */
+ virtual status_t stopDeliveringFrames();
+
+ /* Sets the exposure compensation for the camera device.
+ */
+ void setExposureCompensation(const float ev);
+
+ /* Sets the white balance mode for the device.
+ */
+ void setWhiteBalanceMode(const char* mode);
+
+ /* Initiates focus operation.
+ */
+ virtual void startAutoFocus();
+
+ /* Gets current framebuffer, converted into preview frame format.
+ * This method must be called on a connected instance of this class with a
+ * started camera device. If it is called on a disconnected instance, or
+ * camera device has not been started, this method must return a failure.
+ * Note that this method should be called only after at least one frame has
+ * been captured and delivered. Otherwise it will return garbage in the
+ * preview frame buffer. Typically, this method shuld be called from
+ * onNextFrameAvailable callback.
+ * Param:
+ * buffer - Buffer, large enough to contain the entire preview frame.
+ * Return:
+ * NO_ERROR on success, or an appropriate error status.
+ */
+ virtual status_t getCurrentPreviewFrame(void* buffer);
+
+ /* Gets width of the frame obtained from the physical device.
+ * Return:
+ * Width of the frame obtained from the physical device. Note that value
+ * returned from this method is valid only in case if camera device has been
+ * started.
+ */
+ inline int getFrameWidth() const {
+ ALOGE_IF(!isStarted(), "%s: Device is not started", __FUNCTION__);
+ return mFrameWidth;
+ }
+
+ /* Gets height of the frame obtained from the physical device.
+ * Return:
+ * Height of the frame obtained from the physical device. Note that value
+ * returned from this method is valid only in case if camera device has been
+ * started.
+ */
+ inline int getFrameHeight() const {
+ ALOGE_IF(!isStarted(), "%s: Device is not started", __FUNCTION__);
+ return mFrameHeight;
+ }
+
+ /* Gets byte size of the current frame buffer.
+ * Return:
+ * Byte size of the frame buffer. Note that value returned from this method
+ * is valid only in case if camera device has been started.
+ */
+ inline size_t getFrameBufferSize() const {
+ ALOGE_IF(!isStarted(), "%s: Device is not started", __FUNCTION__);
+ return mFrameBufferSize;
+ }
+
+ /* Gets number of pixels in the current frame buffer.
+ * Return:
+ * Number of pixels in the frame buffer. Note that value returned from this
+ * method is valid only in case if camera device has been started.
+ */
+ inline int getPixelNum() const {
+ ALOGE_IF(!isStarted(), "%s: Device is not started", __FUNCTION__);
+ return mTotalPixels;
+ }
+
+ /* Gets pixel format of the frame that camera device streams to this class.
+ * Throughout camera framework, there are three different forms of pixel
+ * format representation:
+ * - Original format, as reported by the actual camera device. Values for
+ * this format are declared in bionic/libc/kernel/common/linux/videodev2.h
+ * - String representation as defined in CameraParameters::PIXEL_FORMAT_XXX
+ * strings in frameworks/base/include/camera/CameraParameters.h
+ * - HAL_PIXEL_FORMAT_XXX format, as defined in
+ * system/core/include/system/graphics.h Since emulated camera device gets its
+ * data from the actual device, it gets pixel format in the original form. And
+ * that's the pixel format representation that will be returned from this
+ * method. HAL components will need to translate value returned from this
+ * method to the appropriate form. This method must be called only on started
+ * instance of this class, since it's applicable only when camera device is
+ * ready to stream frames. Param: pix_fmt - Upon success contains the original
+ * pixel format. Return: Current framebuffer's pixel format. Note that value
+ * returned from this method is valid only in case if camera device has been
+ * started.
+ */
+ inline uint32_t getOriginalPixelFormat() const {
+ ALOGE_IF(!isStarted(), "%s: Device is not started", __FUNCTION__);
+ return mPixelFormat;
+ }
+
+ /* Gets image metadata (from HAL).
+ * Return:
+ * Filled in ImageMetadata structure (in/out parameter).
+ */
+ const CameraParameters* getCameraParameters();
+
+ /*
+ * State checkers.
+ */
+
+ inline bool isInitialized() const {
+ /* Instance is initialized when the worker thread has been successfuly
+ * created (but not necessarily started). */
+ return mWorkerThread.get() != NULL && mState != ECDS_CONSTRUCTED;
+ }
+ inline bool isConnected() const {
+ /* Instance is connected when its status is either"connected", or
+ * "started". */
+ return mState == ECDS_CONNECTED || mState == ECDS_STARTED;
+ }
+ inline bool isStarted() const { return mState == ECDS_STARTED; }
+
+ /****************************************************************************
+ * Emulated camera device private API
+ ***************************************************************************/
+ protected:
+ /* Performs common validation and calculation of startDevice parameters.
+ * Param:
+ * width, height, pix_fmt, fps - Parameters passed to startDevice method.
+ * Return:
+ * NO_ERROR on success, or an appropriate error status.
+ */
+ virtual status_t commonStartDevice(int width, int height, uint32_t pix_fmt,
+ int fps);
+
+ /* Performs common cleanup on stopDevice.
+ * This method will undo what commonStartDevice had done.
+ */
+ virtual void commonStopDevice();
+
+ /** Computes a luminance value after taking the exposure compensation.
+ * value into account.
+ *
+ * Param:
+ * inputY - The input luminance value.
+ * Return:
+ * The luminance value after adjusting the exposure compensation.
+ */
+ inline uint8_t changeExposure(const uint8_t& inputY) const {
+ return static_cast<uint8_t>(
+ clamp(static_cast<float>(inputY) * mExposureCompensation));
+ }
+
+ /** Simulates focusing and reports completion to the client.
+ */
+ void simulateAutoFocus();
+
+ /** Computes the pixel value in YUV space after adjusting to the current
+ * white balance mode.
+ */
+ void changeWhiteBalance(uint8_t& y, uint8_t& u, uint8_t& v) const;
+
+ /****************************************************************************
+ * Worker thread management.
+ * Typicaly when emulated camera device starts capturing frames from the
+ * actual device, it does that in a worker thread created in StartCapturing,
+ * and terminated in StopCapturing. Since this is such a typical scenario,
+ * it makes sence to encapsulate worker thread management in the base class
+ * for all emulated camera devices.
+ ***************************************************************************/
+
+ protected:
+ /* Starts the worker thread.
+ * Typically, worker thread is started from startDeliveringFrames method of
+ * this class.
+ * Param:
+ * one_burst - Controls how many times thread loop should run. If this
+ * parameter is 'true', thread routine will run only once If this
+ * parameter is 'false', thread routine will run until stopWorkerThread
+ * method is called. See startDeliveringFrames for more info.
+ * Return:
+ * NO_ERROR on success, or an appropriate error status.
+ */
+ virtual status_t startWorkerThread(bool one_burst);
+
+ /* Stops the worker thread.
+ * Note that this method will always wait for the worker thread to terminate.
+ * Typically, worker thread is started from stopDeliveringFrames method of
+ * this class.
+ * Return:
+ * NO_ERROR on success, or an appropriate error status.
+ */
+ virtual status_t stopWorkerThread();
+
+ /* Implementation of the worker thread routine.
+ * In the default implementation of the worker thread routine we simply
+ * return 'false' forcing the thread loop to exit, and the thread to
+ * terminate. Derived class should override that method to provide there the
+ * actual frame delivery.
+ * Return:
+ * true To continue thread loop (this method will be called again), or false
+ * to exit the thread loop and to terminate the thread.
+ */
+ virtual bool inWorkerThread();
+
+ /* Encapsulates a worker thread used by the emulated camera device.
+ */
+ friend class WorkerThread;
+ class WorkerThread : public Thread {
+ /****************************************************************************
+ * Public API
+ ***************************************************************************/
+
+ public:
+ inline explicit WorkerThread(EmulatedCameraDevice* camera_dev)
+ : Thread(true), // Callbacks may involve Java calls.
+ mCameraDevice(camera_dev),
+ mThreadControl(-1),
+ mControlFD(-1) {}
+
+ inline ~WorkerThread() {
+ ALOGW_IF(mThreadControl >= 0 || mControlFD >= 0,
+ "%s: Control FDs are opened in the destructor", __FUNCTION__);
+ if (mThreadControl >= 0) {
+ close(mThreadControl);
+ }
+ if (mControlFD >= 0) {
+ close(mControlFD);
+ }
+ }
+
+ /* Starts the thread
+ * Param:
+ * one_burst - Controls how many times thread loop should run. If
+ * this parameter is 'true', thread routine will run only once
+ * If this parameter is 'false', thread routine will run until
+ * stopThread method is called. See startWorkerThread for more
+ * info.
+ * Return:
+ * NO_ERROR on success, or an appropriate error status.
+ */
+ inline status_t startThread(bool one_burst) {
+ mOneBurst = one_burst;
+ return run("Camera_startThread", ANDROID_PRIORITY_URGENT_DISPLAY, 0);
+ }
+
+ /* Overriden base class method.
+ * It is overriden in order to provide one-time initialization just
+ * prior to starting the thread routine.
+ */
+ status_t readyToRun();
+
+ /* Stops the thread. */
+ status_t stopThread();
+
+ /* Values returned from the Select method of this class. */
+ enum SelectRes {
+ /* A timeout has occurred. */
+ TIMEOUT,
+ /* Data are available for read on the provided FD. */
+ READY,
+ /* Thread exit request has been received. */
+ EXIT_THREAD,
+ /* An error has occurred. */
+ ERROR
+ };
+
+ /* Select on an FD event, keeping in mind thread exit message.
+ * Param:
+ * fd - File descriptor on which to wait for an event. This
+ * parameter may be negative. If it is negative this method will
+ * only wait on a control message to the thread.
+ * timeout - Timeout in microseconds. 0 indicates no timeout (wait
+ * forever).
+ * Return:
+ * See SelectRes enum comments.
+ */
+ SelectRes Select(int fd, int timeout);
+
+ /****************************************************************************
+ * Private API
+ ***************************************************************************/
+
+ private:
+ /* Implements abstract method of the base Thread class. */
+ bool threadLoop() {
+ /* Simply dispatch the call to the containing camera device. */
+ if (mCameraDevice->inWorkerThread()) {
+ /* Respect "one burst" parameter (see startThread). */
+ return !mOneBurst;
+ } else {
+ return false;
+ }
+ }
+
+ /* Containing camera device object. */
+ EmulatedCameraDevice* mCameraDevice;
+
+ /* FD that is used to send control messages into the thread. */
+ int mThreadControl;
+
+ /* FD that thread uses to receive control messages. */
+ int mControlFD;
+
+ /* Controls number of times the thread loop runs.
+ * See startThread for more information. */
+ bool mOneBurst;
+
+ /* Enumerates control messages that can be sent into the thread. */
+ enum ControlMessage {
+ /* Stop the thread. */
+ THREAD_STOP
+ };
+
+ Condition mSetup;
+ };
+
+ /* Worker thread accessor. */
+ inline WorkerThread* getWorkerThread() const { return mWorkerThread.get(); }
+
+ /****************************************************************************
+ * Data members
+ ***************************************************************************/
+
+ protected:
+ /* Locks this instance for parameters, state, etc. change. */
+ Mutex mObjectLock;
+
+ /* Worker thread that is used in frame capturing. */
+ sp<WorkerThread> mWorkerThread;
+
+ /* Timestamp of the current frame. */
+ nsecs_t mCurFrameTimestamp;
+
+ /* Emulated camera object containing this instance. */
+ EmulatedCamera* mCameraHAL;
+
+ /* Framebuffer containing the current frame. */
+ uint8_t* mCurrentFrame;
+
+ /*
+ * Framebuffer properties.
+ */
+
+ /* Byte size of the framebuffer. */
+ size_t mFrameBufferSize;
+
+ /* Original pixel format (one of the V4L2_PIX_FMT_XXX values, as defined in
+ * bionic/libc/kernel/common/linux/videodev2.h */
+ uint32_t mPixelFormat;
+
+ /* Frame width */
+ int mFrameWidth;
+
+ /* Frame height */
+ int mFrameHeight;
+
+ /* Total number of pixels */
+ int mTotalPixels;
+
+ /* Requested FPS rate */
+ int mTargetFps;
+
+ /* Exposure compensation value */
+ float mExposureCompensation;
+
+ float* mWhiteBalanceScale;
+
+ bool mIsFocusing;
+
+ DefaultKeyedVector<String8, float*> mSupportedWhiteBalanceScale;
+
+ /* Defines possible states of the emulated camera device object.
+ */
+ enum EmulatedCameraDeviceState {
+ /* Object has been constructed. */
+ ECDS_CONSTRUCTED,
+ /* Object has been initialized. */
+ ECDS_INITIALIZED,
+ /* Object has been connected to the physical device. */
+ ECDS_CONNECTED,
+ /* Camera device has been started. */
+ ECDS_STARTED,
+ };
+
+ /* Object state. */
+ EmulatedCameraDeviceState mState;
+};
+
+}; /* namespace android */
+
+#endif /* HW_EMULATOR_CAMERA_EMULATED_CAMERA_DEVICE_H */
diff --git a/guest/hals/camera/EmulatedCameraFactory.cpp b/guest/hals/camera/EmulatedCameraFactory.cpp
new file mode 100644
index 000000000..009e19436
--- /dev/null
+++ b/guest/hals/camera/EmulatedCameraFactory.cpp
@@ -0,0 +1,297 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+/*
+ * Contains implementation of a class EmulatedCameraFactory that manages cameras
+ * available for emulation.
+ */
+
+#define LOG_NDEBUG 0
+#define LOG_TAG "EmulatedCamera_Factory"
+#include <log/log.h>
+#include <cutils/properties.h>
+#include "EmulatedFakeCamera.h"
+
+#include "EmulatedCameraHotplugThread.h"
+#include "EmulatedFakeCamera2.h"
+
+#include "EmulatedFakeCamera3.h"
+
+#include "EmulatedCameraFactory.h"
+
+extern camera_module_t HAL_MODULE_INFO_SYM;
+
+namespace android {
+EmulatedCameraFactory& EmulatedCameraFactory::Instance() {
+ static EmulatedCameraFactory* factory = new EmulatedCameraFactory;
+ return *factory;
+}
+
+EmulatedCameraFactory::EmulatedCameraFactory()
+ : mCallbacks(NULL)
+{
+ mCameraConfiguration.Init();
+ const std::vector<cvd::CameraDefinition>& cameras =
+ mCameraConfiguration.cameras();
+ for (size_t camera_index = 0; camera_index < cameras.size(); ++camera_index) {
+ mCameraDefinitions.push(cameras[camera_index]);
+ /* Reserve a spot for camera, but don't create just yet. */
+ mEmulatedCameras.push(NULL);
+ }
+
+ ALOGV("%zu cameras are being emulated.", getEmulatedCameraNum());
+
+ /* Create hotplug thread */
+ {
+ mHotplugThread = new EmulatedCameraHotplugThread(getEmulatedCameraNum());
+ mHotplugThread->run("EmulatedCameraHotplugThread");
+ }
+}
+
+EmulatedBaseCamera* EmulatedCameraFactory::getOrCreateFakeCamera(
+ size_t cameraId) {
+ std::lock_guard lock(mEmulatedCamerasMutex);
+
+ if (cameraId >= getEmulatedCameraNum()) {
+ ALOGE("%s: Invalid camera ID: %zu", __FUNCTION__, cameraId);
+ return NULL;
+ }
+
+ if (mEmulatedCameras[cameraId] != NULL) {
+ return mEmulatedCameras[cameraId];
+ }
+
+ const cvd::CameraDefinition& definition = mCameraDefinitions[cameraId];
+ bool is_back_facing =
+ (definition.orientation == cvd::CameraDefinition::kBack);
+
+ EmulatedBaseCamera* camera;
+ /* Create, and initialize the fake camera */
+ switch (definition.hal_version) {
+ case cvd::CameraDefinition::kHalV1:
+ camera = new EmulatedFakeCamera(cameraId, is_back_facing,
+ &HAL_MODULE_INFO_SYM.common);
+ break;
+ case cvd::CameraDefinition::kHalV2:
+ camera = new EmulatedFakeCamera2(cameraId, is_back_facing,
+ &HAL_MODULE_INFO_SYM.common);
+ break;
+ case cvd::CameraDefinition::kHalV3:
+ camera = new EmulatedFakeCamera3(cameraId, is_back_facing,
+ &HAL_MODULE_INFO_SYM.common);
+ break;
+ default:
+ ALOGE("%s: Unsupported camera hal version requested: %d", __FUNCTION__,
+ definition.hal_version);
+ return NULL;
+ }
+
+ ALOGI("%s: Camera device %zu hal version is %d", __FUNCTION__, cameraId,
+ definition.hal_version);
+ int res = camera->Initialize(definition);
+
+ if (res != NO_ERROR) {
+ ALOGE("%s: Unable to intialize camera %zu: %s (%d)", __FUNCTION__, cameraId,
+ strerror(-res), res);
+ delete camera;
+ return NULL;
+ }
+
+ ALOGI("%s: Inserting camera", __FUNCTION__);
+ mEmulatedCameras.replaceAt(camera, cameraId);
+ ALOGI("%s: Done", __FUNCTION__);
+ return camera;
+}
+
+EmulatedCameraFactory::~EmulatedCameraFactory() {
+ for (size_t n = 0; n < mEmulatedCameras.size(); n++) {
+ if (mEmulatedCameras[n] != NULL) {
+ delete mEmulatedCameras[n];
+ }
+ }
+
+ if (mHotplugThread != NULL) {
+ mHotplugThread->requestExit();
+ mHotplugThread->join();
+ }
+}
+
+/****************************************************************************
+ * Camera HAL API handlers.
+ *
+ * Each handler simply verifies existence of an appropriate EmulatedBaseCamera
+ * instance, and dispatches the call to that instance.
+ *
+ ***************************************************************************/
+
+int EmulatedCameraFactory::cameraDeviceOpen(int camera_id,
+ hw_device_t** device) {
+ ALOGV("%s: id = %d", __FUNCTION__, camera_id);
+
+ *device = NULL;
+
+ EmulatedBaseCamera* camera = getOrCreateFakeCamera(camera_id);
+ if (camera == NULL) return -EINVAL;
+
+ return camera->connectCamera(device);
+}
+
+int EmulatedCameraFactory::getCameraInfo(int camera_id,
+ struct camera_info* info) {
+ ALOGV("%s: id = %d", __FUNCTION__, camera_id);
+
+ EmulatedBaseCamera* camera = getOrCreateFakeCamera(camera_id);
+ if (camera == NULL) return -EINVAL;
+
+ return camera->getCameraInfo(info);
+}
+
+int EmulatedCameraFactory::setCallbacks(
+ const camera_module_callbacks_t* callbacks) {
+ ALOGV("%s: callbacks = %p", __FUNCTION__, callbacks);
+
+ mCallbacks = callbacks;
+
+ return OK;
+}
+
+void EmulatedCameraFactory::getVendorTagOps(vendor_tag_ops_t* ops) {
+ ALOGV("%s: ops = %p", __FUNCTION__, ops);
+
+ // No vendor tags defined for emulator yet, so not touching ops
+}
+
+int EmulatedCameraFactory::setTorchMode(const char* camera_id, bool enabled) {
+ ALOGV("%s: camera_id = %s, enabled =%d", __FUNCTION__, camera_id, enabled);
+
+ EmulatedBaseCamera* camera = getOrCreateFakeCamera(atoi(camera_id));
+ if (camera == NULL) return -EINVAL;
+
+ return camera->setTorchMode(enabled);
+}
+
+/****************************************************************************
+ * Camera HAL API callbacks.
+ ***************************************************************************/
+
+int EmulatedCameraFactory::device_open(const hw_module_t* module,
+ const char* name, hw_device_t** device) {
+ /*
+ * Simply verify the parameters, and dispatch the call inside the
+ * EmulatedCameraFactory instance.
+ */
+
+ if (module != &HAL_MODULE_INFO_SYM.common) {
+ ALOGE("%s: Invalid module %p expected %p", __FUNCTION__, module,
+ &HAL_MODULE_INFO_SYM.common);
+ return -EINVAL;
+ }
+ if (name == NULL) {
+ ALOGE("%s: NULL name is not expected here", __FUNCTION__);
+ return -EINVAL;
+ }
+
+ return EmulatedCameraFactory::Instance().cameraDeviceOpen(atoi(name), device);
+}
+
+int EmulatedCameraFactory::get_number_of_cameras(void) {
+ return EmulatedCameraFactory::Instance().getEmulatedCameraNum();
+}
+
+int EmulatedCameraFactory::get_camera_info(int camera_id,
+ struct camera_info* info) {
+ return EmulatedCameraFactory::Instance().getCameraInfo(camera_id, info);
+}
+
+int EmulatedCameraFactory::set_callbacks(
+ const camera_module_callbacks_t* callbacks) {
+ return EmulatedCameraFactory::Instance().setCallbacks(callbacks);
+}
+
+void EmulatedCameraFactory::get_vendor_tag_ops(vendor_tag_ops_t* ops) {
+ EmulatedCameraFactory::Instance().getVendorTagOps(ops);
+}
+
+int EmulatedCameraFactory::open_legacy(const struct hw_module_t* /*module*/,
+ const char* /*id*/,
+ uint32_t /*halVersion*/,
+ struct hw_device_t** /*device*/) {
+ // Not supporting legacy open
+ return -ENOSYS;
+}
+
+int EmulatedCameraFactory::set_torch_mode(const char* camera_id, bool enabled) {
+ return EmulatedCameraFactory::Instance().setTorchMode(camera_id, enabled);
+}
+
+/********************************************************************************
+ * Internal API
+ *******************************************************************************/
+
+void EmulatedCameraFactory::onStatusChanged(int cameraId, int newStatus) {
+ EmulatedBaseCamera* cam = getOrCreateFakeCamera(cameraId);
+ if (!cam) {
+ ALOGE("%s: Invalid camera ID %d", __FUNCTION__, cameraId);
+ return;
+ }
+
+ /**
+ * (Order is important)
+ * Send the callback first to framework, THEN close the camera.
+ */
+
+ if (newStatus == cam->getHotplugStatus()) {
+ ALOGW("%s: Ignoring transition to the same status", __FUNCTION__);
+ return;
+ }
+
+ const camera_module_callbacks_t* cb = mCallbacks;
+ if (cb != NULL && cb->camera_device_status_change != NULL) {
+ cb->camera_device_status_change(cb, cameraId, newStatus);
+ }
+
+ if (newStatus == CAMERA_DEVICE_STATUS_NOT_PRESENT) {
+ cam->unplugCamera();
+ } else if (newStatus == CAMERA_DEVICE_STATUS_PRESENT) {
+ cam->plugCamera();
+ }
+}
+
+void EmulatedCameraFactory::onTorchModeStatusChanged(int cameraId,
+ int newStatus) {
+ EmulatedBaseCamera* cam = getOrCreateFakeCamera(cameraId);
+ if (!cam) {
+ ALOGE("%s: Invalid camera ID %d", __FUNCTION__, cameraId);
+ return;
+ }
+
+ const camera_module_callbacks_t* cb = mCallbacks;
+ if (cb != NULL && cb->torch_mode_status_change != NULL) {
+ char id[10];
+ sprintf(id, "%d", cameraId);
+ cb->torch_mode_status_change(cb, id, newStatus);
+ }
+}
+
+/********************************************************************************
+ * Initializer for the static member structure.
+ *******************************************************************************/
+
+/* Entry point for camera HAL API. */
+struct hw_module_methods_t EmulatedCameraFactory::mCameraModuleMethods = {
+ .open = EmulatedCameraFactory::device_open};
+
+}; /* namespace android */
diff --git a/guest/hals/camera/EmulatedCameraFactory.h b/guest/hals/camera/EmulatedCameraFactory.h
new file mode 100644
index 000000000..f86ae1ca5
--- /dev/null
+++ b/guest/hals/camera/EmulatedCameraFactory.h
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2011 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 HW_EMULATOR_CAMERA_EMULATED_CAMERA_FACTORY_H
+#define HW_EMULATOR_CAMERA_EMULATED_CAMERA_FACTORY_H
+
+#include <mutex>
+
+#include <utils/RefBase.h>
+
+#include <utils/Vector.h>
+#include "CameraConfiguration.h"
+#include "EmulatedBaseCamera.h"
+#include "common/libs/threads/thread_annotations.h"
+
+namespace android {
+
+class EmulatedCameraHotplugThread;
+
+/*
+ * Contains declaration of a class EmulatedCameraFactory that manages cameras
+ * available for the emulation. A global instance of this class is statically
+ * instantiated and initialized when camera emulation HAL is loaded.
+ */
+
+/* Class EmulatedCameraFactoryManages cameras available for the emulation.
+ *
+ * When the global static instance of this class is created on the module load,
+ * it enumerates cameras available for the emulation by connecting to the
+ * emulator's 'camera' service. For every camera found out there it creates an
+ * instance of an appropriate class, and stores it an in array of emulated
+ * cameras. In addition to the cameras reported by the emulator, a fake camera
+ * emulator is always created, so there is always at least one camera that is
+ * available.
+ *
+ * Instance of this class is also used as the entry point for the camera HAL
+ * API, including:
+ * - hw_module_methods_t::open entry point
+ * - camera_module_t::get_number_of_cameras entry point
+ * - camera_module_t::get_camera_info entry point
+ *
+ */
+class EmulatedCameraFactory {
+ public:
+ /* Constructs EmulatedCameraFactory instance.
+ * In this constructor the factory will create and initialize a list of
+ * emulated cameras. All errors that occur on this constructor are reported
+ * via mConstructedOK data member of this class.
+ */
+ EmulatedCameraFactory();
+
+ /* Destructs EmulatedCameraFactory instance. */
+ ~EmulatedCameraFactory();
+
+ /****************************************************************************
+ * Camera HAL API handlers.
+ ***************************************************************************/
+
+ public:
+ /* Returns a (singleton) instance of the EmulatedCameraFactory.
+ */
+ static EmulatedCameraFactory& Instance();
+
+ /* Opens (connects to) a camera device.
+ * This method is called in response to hw_module_methods_t::open callback.
+ */
+ int cameraDeviceOpen(int camera_id, hw_device_t** device);
+
+ /* Gets emulated camera information.
+ * This method is called in response to camera_module_t::get_camera_info
+ * callback.
+ */
+ int getCameraInfo(int camera_id, struct camera_info* info);
+
+ /* Sets emulated camera callbacks.
+ * This method is called in response to camera_module_t::set_callbacks
+ * callback.
+ */
+ int setCallbacks(const camera_module_callbacks_t* callbacks);
+
+ /* Fill in vendor tags for the module
+ * This method is called in response to camera_module_t::get_vendor_tag_ops
+ * callback.
+ */
+ void getVendorTagOps(vendor_tag_ops_t* ops);
+
+ int setTorchMode(const char* camera_id, bool enabled);
+
+ /****************************************************************************
+ * Camera HAL API callbacks.
+ ***************************************************************************/
+
+ public:
+ /* camera_module_t::get_number_of_cameras callback entry point. */
+ static int get_number_of_cameras(void);
+
+ /* camera_module_t::get_camera_info callback entry point. */
+ static int get_camera_info(int camera_id, struct camera_info* info);
+
+ /* camera_module_t::set_callbacks callback entry point. */
+ static int set_callbacks(const camera_module_callbacks_t* callbacks);
+
+ /* camera_module_t::get_vendor_tag_ops callback entry point */
+ static void get_vendor_tag_ops(vendor_tag_ops_t* ops);
+
+ /* camera_module_t::open_legacy callback entry point */
+ static int open_legacy(const struct hw_module_t* module, const char* id,
+ uint32_t halVersion, struct hw_device_t** device);
+
+ static int set_torch_mode(const char* camera_id, bool enabled);
+
+ private:
+ /* hw_module_methods_t::open callback entry point. */
+ static int device_open(const hw_module_t* module, const char* name,
+ hw_device_t** device);
+
+ /****************************************************************************
+ * Public API.
+ ***************************************************************************/
+
+ public:
+ /* Gets fake camera orientation. */
+ int getFakeCameraOrientation() {
+ /* TODO: Have a boot property that controls that. */
+ return 90;
+ }
+
+ /* Gets number of emulated cameras.
+ */
+ inline size_t getEmulatedCameraNum() const {
+ return mCameraDefinitions.size();
+ }
+
+ void onStatusChanged(int cameraId, int newStatus);
+
+ void onTorchModeStatusChanged(int cameraId, int newStatus);
+
+ /****************************************************************************
+ * Private API
+ ***************************************************************************/
+
+ private:
+ /* Create new or return existing fake camera based on camera definition
+ * found in mCameraDefinitions.
+ * Returns NULL if cameraId is not valid (= not a valid index of
+ * mCameraDefinitions)
+ */
+ EmulatedBaseCamera* getOrCreateFakeCamera(size_t cameraId);
+
+ /****************************************************************************
+ * Data members.
+ ***************************************************************************/
+
+ private:
+ /* Array of cameras available for the emulation. */
+ Vector<EmulatedBaseCamera*> mEmulatedCameras;
+
+ /* Guards access to mEmulatedCameras. */
+ std::mutex mEmulatedCamerasMutex;
+
+ /* Camera callbacks (for status changing) */
+ const camera_module_callbacks_t* mCallbacks;
+
+ /* Hotplug thread (to call onStatusChanged) */
+ sp<EmulatedCameraHotplugThread> mHotplugThread;
+
+ /* Back- and front camera properties accessed from the vsoc device. */
+ cvd::CameraConfiguration mCameraConfiguration;
+ Vector<cvd::CameraDefinition> mCameraDefinitions;
+
+ public:
+ /* Contains device open entry point, as required by HAL API. */
+ static struct hw_module_methods_t mCameraModuleMethods;
+};
+
+}; /* namespace android */
+
+#endif /* HW_EMULATOR_CAMERA_EMULATED_CAMERA_FACTORY_H */
diff --git a/guest/hals/camera/EmulatedCameraHal.cpp b/guest/hals/camera/EmulatedCameraHal.cpp
new file mode 100644
index 000000000..2aba50ae7
--- /dev/null
+++ b/guest/hals/camera/EmulatedCameraHal.cpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+/*
+ * Contains implementation of the camera HAL layer in the system running
+ * under the emulator.
+ *
+ * This file contains only required HAL header, which directs all the API calls
+ * to the EmulatedCameraFactory class implementation, wich is responsible for
+ * managing emulated cameras.
+ */
+
+#include "EmulatedCameraFactory.h"
+
+/*
+ * Required HAL header.
+ */
+camera_module_t HAL_MODULE_INFO_SYM = {
+ .common = {
+ .tag = HARDWARE_MODULE_TAG,
+ .module_api_version =
+ CAMERA_MODULE_API_VERSION_2_4,
+ .hal_api_version = HARDWARE_HAL_API_VERSION,
+ .id = CAMERA_HARDWARE_MODULE_ID,
+ .name = "Emulated Camera Module",
+ .author = "The Android Open Source Project",
+ .methods = &
+ android::EmulatedCameraFactory::mCameraModuleMethods,
+ .dso = NULL,
+ .reserved = {0},
+ },
+ .get_number_of_cameras =
+ android::EmulatedCameraFactory::get_number_of_cameras,
+ .get_camera_info =
+ android::EmulatedCameraFactory::get_camera_info,
+ .set_callbacks =
+ android::EmulatedCameraFactory::set_callbacks,
+ .get_vendor_tag_ops =
+ android::EmulatedCameraFactory::get_vendor_tag_ops,
+ .open_legacy =
+ android::EmulatedCameraFactory::open_legacy,
+ .set_torch_mode =
+ android::EmulatedCameraFactory::set_torch_mode,
+};
diff --git a/guest/hals/camera/EmulatedCameraHotplugThread.cpp b/guest/hals/camera/EmulatedCameraHotplugThread.cpp
new file mode 100644
index 000000000..34a4c1582
--- /dev/null
+++ b/guest/hals/camera/EmulatedCameraHotplugThread.cpp
@@ -0,0 +1,345 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#define LOG_NDEBUG 0
+#define LOG_TAG "EmulatedCamera_HotplugThread"
+#include <log/log.h>
+
+#include <fcntl.h>
+#include <sys/inotify.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "EmulatedCameraFactory.h"
+#include "EmulatedCameraHotplugThread.h"
+
+#define FAKE_HOTPLUG_FILE "/data/misc/media/emulator.camera.hotplug"
+
+#define EVENT_SIZE (sizeof(struct inotify_event))
+#define EVENT_BUF_LEN (1024 * (EVENT_SIZE + 16))
+
+#define SubscriberInfo EmulatedCameraHotplugThread::SubscriberInfo
+
+namespace android {
+
+EmulatedCameraHotplugThread::EmulatedCameraHotplugThread(
+ size_t totalCameraCount)
+ : Thread(/*canCallJava*/ false) {
+ mRunning = true;
+ mInotifyFd = 0;
+
+ for (size_t id = 0; id < totalCameraCount; ++id) {
+ if (createFileIfNotExists(id)) {
+ mSubscribedCameraIds.push_back(id);
+ }
+ }
+}
+
+EmulatedCameraHotplugThread::~EmulatedCameraHotplugThread() {}
+
+status_t EmulatedCameraHotplugThread::requestExitAndWait() {
+ ALOGE("%s: Not implemented. Use requestExit + join instead", __FUNCTION__);
+ return INVALID_OPERATION;
+}
+
+void EmulatedCameraHotplugThread::requestExit() {
+ Mutex::Autolock al(mMutex);
+
+ ALOGV("%s: Requesting thread exit", __FUNCTION__);
+ mRunning = false;
+
+ bool rmWatchFailed = false;
+ Vector<SubscriberInfo>::iterator it;
+ for (it = mSubscribers.begin(); it != mSubscribers.end(); ++it) {
+ if (inotify_rm_watch(mInotifyFd, it->WatchID) == -1) {
+ ALOGE(
+ "%s: Could not remove watch for camID '%d',"
+ " error: '%s' (%d)",
+ __FUNCTION__, it->CameraID, strerror(errno), errno);
+
+ rmWatchFailed = true;
+ } else {
+ ALOGV("%s: Removed watch for camID '%d'", __FUNCTION__, it->CameraID);
+ }
+ }
+
+ if (rmWatchFailed) { // unlikely
+ // Give the thread a fighting chance to error out on the next
+ // read
+ if (close(mInotifyFd) == -1) {
+ ALOGE("%s: close failure error: '%s' (%d)", __FUNCTION__, strerror(errno),
+ errno);
+ }
+ }
+
+ ALOGV("%s: Request exit complete.", __FUNCTION__);
+}
+
+status_t EmulatedCameraHotplugThread::readyToRun() {
+ Mutex::Autolock al(mMutex);
+
+ mInotifyFd = -1;
+
+ do {
+ ALOGV("%s: Initializing inotify", __FUNCTION__);
+
+ mInotifyFd = inotify_init();
+ if (mInotifyFd == -1) {
+ ALOGE("%s: inotify_init failure error: '%s' (%d)", __FUNCTION__,
+ strerror(errno), errno);
+ mRunning = false;
+ break;
+ }
+
+ /**
+ * For each fake camera file, add a watch for when
+ * the file is closed (if it was written to)
+ */
+ Vector<int>::const_iterator it, end;
+ it = mSubscribedCameraIds.begin();
+ end = mSubscribedCameraIds.end();
+ for (; it != end; ++it) {
+ int cameraId = *it;
+ if (!addWatch(cameraId)) {
+ mRunning = false;
+ break;
+ }
+ }
+ } while (false);
+
+ if (!mRunning) {
+ status_t err = -errno;
+
+ if (mInotifyFd != -1) {
+ close(mInotifyFd);
+ }
+
+ return err;
+ }
+
+ return OK;
+}
+
+bool EmulatedCameraHotplugThread::threadLoop() {
+ // If requestExit was already called, mRunning will be false
+ while (mRunning) {
+ char buffer[EVENT_BUF_LEN];
+ int length = TEMP_FAILURE_RETRY(read(mInotifyFd, buffer, EVENT_BUF_LEN));
+
+ if (length < 0) {
+ ALOGE("%s: Error reading from inotify FD, error: '%s' (%d)", __FUNCTION__,
+ strerror(errno), errno);
+ mRunning = false;
+ break;
+ }
+
+ ALOGV("%s: Read %d bytes from inotify FD", __FUNCTION__, length);
+
+ int i = 0;
+ while (i < length) {
+ inotify_event* event = (inotify_event*)&buffer[i];
+
+ if (event->mask & IN_IGNORED) {
+ Mutex::Autolock al(mMutex);
+ if (!mRunning) {
+ ALOGV("%s: Shutting down thread", __FUNCTION__);
+ break;
+ } else {
+ ALOGE("%s: File was deleted, aborting", __FUNCTION__);
+ mRunning = false;
+ break;
+ }
+ } else if (event->mask & IN_CLOSE_WRITE) {
+ int cameraId = getCameraId(event->wd);
+
+ if (cameraId < 0) {
+ ALOGE("%s: Got bad camera ID from WD '%d", __FUNCTION__, event->wd);
+ } else {
+ // Check the file for the new hotplug event
+ String8 filePath = getFilePath(cameraId);
+ /**
+ * NOTE: we carefully avoid getting an inotify
+ * for the same exact file because it's opened for
+ * read-only, but our inotify is for write-only
+ */
+ int newStatus = readFile(filePath);
+
+ if (newStatus < 0) {
+ mRunning = false;
+ break;
+ }
+
+ int halStatus = newStatus ? CAMERA_DEVICE_STATUS_PRESENT
+ : CAMERA_DEVICE_STATUS_NOT_PRESENT;
+ EmulatedCameraFactory::Instance().onStatusChanged(cameraId,
+ halStatus);
+ }
+
+ } else {
+ ALOGW("%s: Unknown mask 0x%x", __FUNCTION__, event->mask);
+ }
+
+ i += EVENT_SIZE + event->len;
+ }
+ }
+
+ if (!mRunning) {
+ close(mInotifyFd);
+ return false;
+ }
+
+ return true;
+}
+
+String8 EmulatedCameraHotplugThread::getFilePath(int cameraId) const {
+ return String8::format(FAKE_HOTPLUG_FILE ".%d", cameraId);
+}
+
+bool EmulatedCameraHotplugThread::createFileIfNotExists(int cameraId) const {
+ String8 filePath = getFilePath(cameraId);
+ // make sure this file exists and we have access to it
+ int fd =
+ TEMP_FAILURE_RETRY(open(filePath.string(), O_WRONLY | O_CREAT | O_TRUNC,
+ /* mode = ug+rwx */ S_IRWXU | S_IRWXG));
+ if (fd == -1) {
+ ALOGE("%s: Could not create file '%s', error: '%s' (%d)", __FUNCTION__,
+ filePath.string(), strerror(errno), errno);
+ return false;
+ }
+
+ // File has '1' by default since we are plugged in by default
+ if (TEMP_FAILURE_RETRY(write(fd, "1\n", /*count*/ 2)) == -1) {
+ ALOGE("%s: Could not write '1' to file '%s', error: '%s' (%d)",
+ __FUNCTION__, filePath.string(), strerror(errno), errno);
+ return false;
+ }
+
+ close(fd);
+ return true;
+}
+
+int EmulatedCameraHotplugThread::getCameraId(String8 filePath) const {
+ Vector<int>::const_iterator it, end;
+ it = mSubscribedCameraIds.begin();
+ end = mSubscribedCameraIds.end();
+ for (; it != end; ++it) {
+ String8 camPath = getFilePath(*it);
+
+ if (camPath == filePath) {
+ return *it;
+ }
+ }
+
+ return NAME_NOT_FOUND;
+}
+
+int EmulatedCameraHotplugThread::getCameraId(int wd) const {
+ for (size_t i = 0; i < mSubscribers.size(); ++i) {
+ if (mSubscribers[i].WatchID == wd) {
+ return mSubscribers[i].CameraID;
+ }
+ }
+
+ return NAME_NOT_FOUND;
+}
+
+SubscriberInfo* EmulatedCameraHotplugThread::getSubscriberInfo(int cameraId) {
+ for (size_t i = 0; i < mSubscribers.size(); ++i) {
+ if (mSubscribers[i].CameraID == cameraId) {
+ return (SubscriberInfo*)&mSubscribers[i];
+ }
+ }
+
+ return NULL;
+}
+
+bool EmulatedCameraHotplugThread::addWatch(int cameraId) {
+ String8 camPath = getFilePath(cameraId);
+ int wd = inotify_add_watch(mInotifyFd, camPath.string(), IN_CLOSE_WRITE);
+
+ if (wd == -1) {
+ ALOGE("%s: Could not add watch for '%s', error: '%s' (%d)", __FUNCTION__,
+ camPath.string(), strerror(errno), errno);
+
+ mRunning = false;
+ return false;
+ }
+
+ ALOGV("%s: Watch added for camID='%d', wd='%d'", __FUNCTION__, cameraId, wd);
+
+ SubscriberInfo si = {cameraId, wd};
+ mSubscribers.push_back(si);
+
+ return true;
+}
+
+bool EmulatedCameraHotplugThread::removeWatch(int cameraId) {
+ SubscriberInfo* si = getSubscriberInfo(cameraId);
+
+ if (!si) return false;
+
+ if (inotify_rm_watch(mInotifyFd, si->WatchID) == -1) {
+ ALOGE("%s: Could not remove watch for camID '%d', error: '%s' (%d)",
+ __FUNCTION__, cameraId, strerror(errno), errno);
+
+ return false;
+ }
+
+ Vector<SubscriberInfo>::iterator it;
+ for (it = mSubscribers.begin(); it != mSubscribers.end(); ++it) {
+ if (it->CameraID == cameraId) {
+ break;
+ }
+ }
+
+ if (it != mSubscribers.end()) {
+ mSubscribers.erase(it);
+ }
+
+ return true;
+}
+
+int EmulatedCameraHotplugThread::readFile(String8 filePath) const {
+ int fd = TEMP_FAILURE_RETRY(open(filePath.string(), O_RDONLY, /*mode*/ 0));
+ if (fd == -1) {
+ ALOGE("%s: Could not open file '%s', error: '%s' (%d)", __FUNCTION__,
+ filePath.string(), strerror(errno), errno);
+ return -1;
+ }
+
+ char buffer[1];
+ int length;
+
+ length = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
+
+ int retval;
+
+ ALOGV("%s: Read file '%s', length='%d', buffer='%c'", __FUNCTION__,
+ filePath.string(), length, buffer[0]);
+
+ if (length == 0) { // EOF
+ retval = 0; // empty file is the same thing as 0
+ } else if (buffer[0] == '0') {
+ retval = 0;
+ } else { // anything non-empty that's not beginning with '0'
+ retval = 1;
+ }
+
+ close(fd);
+
+ return retval;
+}
+
+} // namespace android
diff --git a/guest/hals/camera/EmulatedCameraHotplugThread.h b/guest/hals/camera/EmulatedCameraHotplugThread.h
new file mode 100644
index 000000000..bc288895f
--- /dev/null
+++ b/guest/hals/camera/EmulatedCameraHotplugThread.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2013 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 HW_EMULATOR_CAMERA_EMULATED_CAMERA_HOTPLUG_H
+#define HW_EMULATOR_CAMERA_EMULATED_CAMERA_HOTPLUG_H
+
+/**
+ * This class emulates hotplug events by inotifying on a file, specific
+ * to a camera ID. When the file changes between 1/0 the hotplug
+ * status goes between PRESENT and NOT_PRESENT.
+ *
+ * Refer to FAKE_HOTPLUG_FILE in EmulatedCameraHotplugThread.cpp
+ */
+
+#include <utils/String8.h>
+#include <utils/Vector.h>
+#include "EmulatedCamera2.h"
+
+namespace android {
+class EmulatedCameraHotplugThread : public Thread {
+ public:
+ EmulatedCameraHotplugThread(size_t totalCameraCount);
+ ~EmulatedCameraHotplugThread();
+
+ virtual void requestExit();
+ virtual status_t requestExitAndWait();
+
+ private:
+ virtual status_t readyToRun();
+ virtual bool threadLoop();
+
+ struct SubscriberInfo {
+ int CameraID;
+ int WatchID;
+ };
+
+ bool addWatch(int cameraId);
+ bool removeWatch(int cameraId);
+ SubscriberInfo* getSubscriberInfo(int cameraId);
+
+ int getCameraId(String8 filePath) const;
+ int getCameraId(int wd) const;
+
+ String8 getFilePath(int cameraId) const;
+ int readFile(String8 filePath) const;
+
+ bool createFileIfNotExists(int cameraId) const;
+
+ Vector<int> mSubscribedCameraIds;
+ Vector<SubscriberInfo> mSubscribers;
+
+ // variables above are unguarded:
+ // -- accessed in thread loop or in constructor only
+
+ Mutex mMutex;
+
+ bool mRunning; // guarding only when it's important
+};
+} // namespace android
+
+#endif
diff --git a/guest/hals/camera/EmulatedFakeCamera.cpp b/guest/hals/camera/EmulatedFakeCamera.cpp
new file mode 100644
index 000000000..4153fd7a0
--- /dev/null
+++ b/guest/hals/camera/EmulatedFakeCamera.cpp
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+/*
+ * Contains implementation of a class EmulatedFakeCamera that encapsulates
+ * functionality of a fake camera.
+ */
+
+#define LOG_NDEBUG 0
+#define LOG_TAG "EmulatedCamera_FakeCamera"
+#include "EmulatedFakeCamera.h"
+#include <log/log.h>
+#include <cutils/properties.h>
+#undef min
+#undef max
+#include <algorithm>
+#include <sstream>
+#include <string>
+#include "EmulatedCameraFactory.h"
+
+namespace android {
+
+EmulatedFakeCamera::EmulatedFakeCamera(int cameraId, bool facingBack,
+ struct hw_module_t* module)
+ : EmulatedCamera(cameraId, module),
+ mFacingBack(facingBack),
+ mFakeCameraDevice(this) {}
+
+EmulatedFakeCamera::~EmulatedFakeCamera() {}
+
+/****************************************************************************
+ * Public API overrides
+ ***************************************************************************/
+
+status_t EmulatedFakeCamera::Initialize(const cvd::CameraDefinition& params) {
+ status_t res = mFakeCameraDevice.Initialize();
+ if (res != NO_ERROR) {
+ return res;
+ }
+
+ const char* facing =
+ mFacingBack ? EmulatedCamera::FACING_BACK : EmulatedCamera::FACING_FRONT;
+
+ mParameters.set(EmulatedCamera::FACING_KEY, facing);
+ ALOGD("%s: Fake camera is facing %s", __FUNCTION__, facing);
+
+ mParameters.set(EmulatedCamera::ORIENTATION_KEY,
+ EmulatedCameraFactory::Instance().getFakeCameraOrientation());
+
+ res = EmulatedCamera::Initialize(params);
+ if (res != NO_ERROR) {
+ return res;
+ }
+
+ /*
+ * Parameters provided by the camera device.
+ */
+
+ /* 352x288 and 320x240 frame dimensions are required by the framework for
+ * video mode preview and video recording. */
+ std::ostringstream resolutions;
+ for (size_t index = 0; index < params.resolutions.size(); ++index) {
+ if (resolutions.str().size()) {
+ resolutions << ",";
+ }
+ resolutions << params.resolutions[index].width << "x"
+ << params.resolutions[index].height;
+ }
+
+ mParameters.set(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES,
+ resolutions.str().c_str());
+ mParameters.set(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES,
+ resolutions.str().c_str());
+ mParameters.setPreviewSize(640, 480);
+ mParameters.setPictureSize(640, 480);
+
+ mParameters.set(CameraParameters::KEY_SUPPORTED_ANTIBANDING,
+ CameraParameters::ANTIBANDING_AUTO);
+ mParameters.set(CameraParameters::KEY_ANTIBANDING,
+ CameraParameters::ANTIBANDING_AUTO);
+ mParameters.set(CameraParameters::KEY_SUPPORTED_EFFECTS,
+ CameraParameters::EFFECT_NONE);
+ mParameters.set(CameraParameters::KEY_EFFECT, CameraParameters::EFFECT_NONE);
+
+ return NO_ERROR;
+}
+
+EmulatedCameraDevice* EmulatedFakeCamera::getCameraDevice() {
+ return &mFakeCameraDevice;
+}
+
+}; /* namespace android */
diff --git a/guest/hals/camera/EmulatedFakeCamera.h b/guest/hals/camera/EmulatedFakeCamera.h
new file mode 100644
index 000000000..5afba3fad
--- /dev/null
+++ b/guest/hals/camera/EmulatedFakeCamera.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2011 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 HW_EMULATOR_CAMERA_EMULATED_FAKE_CAMERA_H
+#define HW_EMULATOR_CAMERA_EMULATED_FAKE_CAMERA_H
+
+/*
+ * Contains declaration of a class EmulatedFakeCamera that encapsulates
+ * functionality of a fake camera. This class is nothing more than a placeholder
+ * for EmulatedFakeCameraDevice instance.
+ */
+
+#include "EmulatedCamera.h"
+#include "EmulatedFakeCameraDevice.h"
+
+namespace android {
+
+/* Encapsulates functionality of a fake camera.
+ * This class is nothing more than a placeholder for EmulatedFakeCameraDevice
+ * instance that emulates a fake camera device.
+ */
+class EmulatedFakeCamera : public EmulatedCamera {
+ public:
+ /* Constructs EmulatedFakeCamera instance. */
+ EmulatedFakeCamera(int cameraId, bool facingBack, struct hw_module_t* module);
+
+ /* Destructs EmulatedFakeCamera instance. */
+ ~EmulatedFakeCamera();
+
+ /****************************************************************************
+ * EmulatedCamera virtual overrides.
+ ***************************************************************************/
+
+ public:
+ /* Initializes EmulatedFakeCamera instance. */
+ status_t Initialize(const cvd::CameraDefinition& params);
+
+ /****************************************************************************
+ * EmulatedCamera abstract API implementation.
+ ***************************************************************************/
+
+ protected:
+ /* Gets emulated camera device ised by this instance of the emulated camera.
+ */
+ EmulatedCameraDevice* getCameraDevice();
+
+ /****************************************************************************
+ * Data memebers.
+ ***************************************************************************/
+
+ protected:
+ /* Facing back (true) or front (false) switch. */
+ bool mFacingBack;
+
+ /* Contained fake camera device object. */
+ EmulatedFakeCameraDevice mFakeCameraDevice;
+};
+
+}; /* namespace android */
+
+#endif /* HW_EMULATOR_CAMERA_EMULATED_FAKE_CAMERA_H */
diff --git a/guest/hals/camera/EmulatedFakeCamera2.cpp b/guest/hals/camera/EmulatedFakeCamera2.cpp
new file mode 100644
index 000000000..393adf1ef
--- /dev/null
+++ b/guest/hals/camera/EmulatedFakeCamera2.cpp
@@ -0,0 +1,2606 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+/*
+ * Contains implementation of a class EmulatedFakeCamera2 that encapsulates
+ * functionality of an advanced fake camera.
+ */
+
+#include <inttypes.h>
+
+#include <algorithm>
+#include <cstdint>
+#include <iterator>
+
+#define LOG_NDEBUG 0
+#define LOG_TAG "EmulatedCamera_FakeCamera2"
+#include <utils/Log.h>
+
+#include "EmulatedCameraFactory.h"
+#include "EmulatedFakeCamera2.h"
+#include "GrallocModule.h"
+
+#define ERROR_CAMERA_NOT_PRESENT -EPIPE
+
+#define CAMERA2_EXT_TRIGGER_TESTING_DISCONNECT 0xFFFFFFFF
+
+template <typename T, size_t N>
+char (&ArraySizeHelper(T (&array)[N]))[N];
+
+template <typename T, size_t N>
+char (&ArraySizeHelper(const T (&array)[N]))[N];
+
+#define arraysize(array) (sizeof(ArraySizeHelper(array)))
+
+namespace android {
+
+const int64_t USEC = 1000LL;
+const int64_t MSEC = USEC * 1000LL;
+const int64_t SEC = MSEC * 1000LL;
+
+const uint32_t EmulatedFakeCamera2::kAvailableFormats[] = {
+ HAL_PIXEL_FORMAT_RAW16,
+ HAL_PIXEL_FORMAT_BLOB, HAL_PIXEL_FORMAT_RGBA_8888,
+ // HAL_PIXEL_FORMAT_YV12,
+ HAL_PIXEL_FORMAT_YCrCb_420_SP};
+
+const uint32_t EmulatedFakeCamera2::kAvailableRawSizes[2] = {
+ 640, 480
+ // mSensorWidth, mSensorHeight
+};
+
+const uint64_t EmulatedFakeCamera2::kAvailableRawMinDurations[1] = {
+ static_cast<uint64_t>(Sensor::kFrameDurationRange[0])};
+
+const uint32_t EmulatedFakeCamera2::kAvailableProcessedSizesBack[4] = {
+ 640, 480, 320, 240
+ // mSensorWidth, mSensorHeight
+};
+
+const uint32_t EmulatedFakeCamera2::kAvailableProcessedSizesFront[4] = {
+ 320, 240, 160, 120
+ // mSensorWidth, mSensorHeight
+};
+
+const uint64_t EmulatedFakeCamera2::kAvailableProcessedMinDurations[1] = {
+ static_cast<uint64_t>(Sensor::kFrameDurationRange[0])};
+
+const uint32_t EmulatedFakeCamera2::kAvailableJpegSizesBack[2] = {
+ 640, 480
+ // mSensorWidth, mSensorHeight
+};
+
+const uint32_t EmulatedFakeCamera2::kAvailableJpegSizesFront[2] = {
+ 320, 240
+ // mSensorWidth, mSensorHeight
+};
+
+const uint64_t EmulatedFakeCamera2::kAvailableJpegMinDurations[1] = {
+ static_cast<uint64_t>(Sensor::kFrameDurationRange[0])};
+
+EmulatedFakeCamera2::EmulatedFakeCamera2(int cameraId, bool facingBack,
+ struct hw_module_t *module)
+ : EmulatedCamera2(cameraId, module),
+ mFacingBack(facingBack),
+ mIsConnected(false) {
+ ALOGD("Constructing emulated fake camera 2 facing %s",
+ facingBack ? "back" : "front");
+}
+
+EmulatedFakeCamera2::~EmulatedFakeCamera2() {
+ if (mCameraInfo != NULL) {
+ free_camera_metadata(mCameraInfo);
+ }
+}
+
+/****************************************************************************
+ * Public API overrides
+ ***************************************************************************/
+
+status_t EmulatedFakeCamera2::Initialize(const cvd::CameraDefinition &params) {
+ status_t res;
+
+ for (size_t index = 0; index < params.resolutions.size(); ++index) {
+ mAvailableRawSizes.push_back(params.resolutions[index].width);
+ mAvailableRawSizes.push_back(params.resolutions[index].height);
+ mAvailableProcessedSizes.push_back(params.resolutions[index].width);
+ mAvailableProcessedSizes.push_back(params.resolutions[index].height);
+ mAvailableJpegSizes.push_back(params.resolutions[index].width);
+ mAvailableJpegSizes.push_back(params.resolutions[index].height);
+ }
+
+ // Find max width/height
+ int32_t width = 0, height = 0;
+ for (size_t index = 0; index < params.resolutions.size(); ++index) {
+ if (width <= params.resolutions[index].width &&
+ height <= params.resolutions[index].height) {
+ width = params.resolutions[index].width;
+ height = params.resolutions[index].height;
+ }
+ }
+ if (width < 640 || height < 480) {
+ width = 640;
+ height = 480;
+ }
+ mSensorWidth = width;
+ mSensorHeight = height;
+
+ /* TODO(ender): probably should drop this. */
+ std::copy(kAvailableRawSizes,
+ kAvailableRawSizes + arraysize(kAvailableRawSizes),
+ std::back_inserter(mAvailableRawSizes));
+
+ if (params.orientation == cvd::CameraDefinition::kFront) {
+ std::copy(kAvailableProcessedSizesFront,
+ kAvailableProcessedSizesFront +
+ arraysize(kAvailableProcessedSizesFront),
+ std::back_inserter(mAvailableProcessedSizes));
+ std::copy(kAvailableJpegSizesFront,
+ kAvailableJpegSizesFront + arraysize(kAvailableJpegSizesFront),
+ std::back_inserter(mAvailableJpegSizes));
+ } else {
+ std::copy(
+ kAvailableProcessedSizesBack,
+ kAvailableProcessedSizesBack + arraysize(kAvailableProcessedSizesBack),
+ mAvailableProcessedSizes.begin());
+ std::copy(kAvailableJpegSizesBack,
+ kAvailableJpegSizesBack + arraysize(kAvailableJpegSizesBack),
+ mAvailableJpegSizes.begin());
+ }
+
+ res = constructStaticInfo(&mCameraInfo, true);
+ if (res != OK) {
+ ALOGE("%s: Unable to allocate static info: %s (%d)", __FUNCTION__,
+ strerror(-res), res);
+ return res;
+ }
+ res = constructStaticInfo(&mCameraInfo, false);
+ if (res != OK) {
+ ALOGE("%s: Unable to fill in static info: %s (%d)", __FUNCTION__,
+ strerror(-res), res);
+ return res;
+ }
+ if (res != OK) return res;
+
+ mNextStreamId = 1;
+ mNextReprocessStreamId = 1;
+ mRawStreamCount = 0;
+ mProcessedStreamCount = 0;
+ mJpegStreamCount = 0;
+ mReprocessStreamCount = 0;
+
+ return NO_ERROR;
+}
+
+/****************************************************************************
+ * Camera module API overrides
+ ***************************************************************************/
+
+status_t EmulatedFakeCamera2::connectCamera(hw_device_t **device) {
+ status_t res;
+ ALOGV("%s", __FUNCTION__);
+
+ {
+ Mutex::Autolock l(mMutex);
+ if (!mStatusPresent) {
+ ALOGE("%s: Camera ID %d is unplugged", __FUNCTION__, mCameraID);
+ return -ENODEV;
+ }
+ }
+
+ mConfigureThread = new ConfigureThread(this);
+ mReadoutThread = new ReadoutThread(this);
+ mControlThread = new ControlThread(this);
+ mSensor = new Sensor(mSensorWidth, mSensorHeight);
+ mJpegCompressor = new JpegCompressor();
+
+ mNextStreamId = 1;
+ mNextReprocessStreamId = 1;
+
+ res = mSensor->startUp();
+ if (res != NO_ERROR) return res;
+
+ res = mConfigureThread->run("EmulatedFakeCamera2::configureThread");
+ if (res != NO_ERROR) return res;
+
+ res = mReadoutThread->run("EmulatedFakeCamera2::readoutThread");
+ if (res != NO_ERROR) return res;
+
+ res = mControlThread->run("EmulatedFakeCamera2::controlThread");
+ if (res != NO_ERROR) return res;
+
+ status_t ret = EmulatedCamera2::connectCamera(device);
+
+ if (ret >= 0) {
+ mIsConnected = true;
+ }
+
+ return ret;
+}
+
+status_t EmulatedFakeCamera2::plugCamera() {
+ {
+ Mutex::Autolock l(mMutex);
+
+ if (!mStatusPresent) {
+ ALOGI("%s: Plugged back in", __FUNCTION__);
+ mStatusPresent = true;
+ }
+ }
+
+ return NO_ERROR;
+}
+
+status_t EmulatedFakeCamera2::unplugCamera() {
+ {
+ Mutex::Autolock l(mMutex);
+
+ if (mStatusPresent) {
+ ALOGI("%s: Unplugged camera", __FUNCTION__);
+ mStatusPresent = false;
+ }
+ }
+
+ return closeCamera();
+}
+
+camera_device_status_t EmulatedFakeCamera2::getHotplugStatus() {
+ Mutex::Autolock l(mMutex);
+ return mStatusPresent ? CAMERA_DEVICE_STATUS_PRESENT
+ : CAMERA_DEVICE_STATUS_NOT_PRESENT;
+}
+
+status_t EmulatedFakeCamera2::closeCamera() {
+ {
+ Mutex::Autolock l(mMutex);
+
+ status_t res;
+ ALOGV("%s", __FUNCTION__);
+
+ if (!mIsConnected) {
+ return NO_ERROR;
+ }
+
+ res = mSensor->shutDown();
+ if (res != NO_ERROR) {
+ ALOGE("%s: Unable to shut down sensor: %d", __FUNCTION__, res);
+ return res;
+ }
+
+ mConfigureThread->requestExit();
+ mReadoutThread->requestExit();
+ mControlThread->requestExit();
+ mJpegCompressor->cancel();
+ }
+
+ // give up the lock since we will now block and the threads
+ // can call back into this object
+ mConfigureThread->join();
+ mReadoutThread->join();
+ mControlThread->join();
+
+ ALOGV("%s exit", __FUNCTION__);
+
+ {
+ Mutex::Autolock l(mMutex);
+ mIsConnected = false;
+ }
+
+ return NO_ERROR;
+}
+
+status_t EmulatedFakeCamera2::getCameraInfo(struct camera_info *info) {
+ info->facing = mFacingBack ? CAMERA_FACING_BACK : CAMERA_FACING_FRONT;
+ info->orientation =
+ EmulatedCameraFactory::Instance().getFakeCameraOrientation();
+ return EmulatedCamera2::getCameraInfo(info);
+}
+
+/****************************************************************************
+ * Camera device API overrides
+ ***************************************************************************/
+
+/** Request input queue */
+
+int EmulatedFakeCamera2::requestQueueNotify() {
+ ALOGV("Request queue notification received");
+
+ ALOG_ASSERT(mRequestQueueSrc != NULL,
+ "%s: Request queue src not set, but received queue notification!",
+ __FUNCTION__);
+ ALOG_ASSERT(mFrameQueueDst != NULL,
+ "%s: Request queue src not set, but received queue notification!",
+ __FUNCTION__);
+ ALOG_ASSERT(mStreams.size() != 0,
+ "%s: No streams allocated, but received queue notification!",
+ __FUNCTION__);
+ return mConfigureThread->newRequestAvailable();
+}
+
+int EmulatedFakeCamera2::getInProgressCount() {
+ Mutex::Autolock l(mMutex);
+
+ if (!mStatusPresent) {
+ ALOGW("%s: Camera was physically disconnected", __FUNCTION__);
+ return ERROR_CAMERA_NOT_PRESENT;
+ }
+
+ int requestCount = 0;
+ requestCount += mConfigureThread->getInProgressCount();
+ requestCount += mReadoutThread->getInProgressCount();
+ requestCount += mJpegCompressor->isBusy() ? 1 : 0;
+
+ return requestCount;
+}
+
+int EmulatedFakeCamera2::constructDefaultRequest(int request_template,
+ camera_metadata_t **request) {
+ if (request == NULL) return BAD_VALUE;
+ if (request_template < 0 || request_template >= CAMERA2_TEMPLATE_COUNT) {
+ return BAD_VALUE;
+ }
+
+ {
+ Mutex::Autolock l(mMutex);
+ if (!mStatusPresent) {
+ ALOGW("%s: Camera was physically disconnected", __FUNCTION__);
+ return ERROR_CAMERA_NOT_PRESENT;
+ }
+ }
+
+ status_t res;
+ // Pass 1, calculate size and allocate
+ res = constructDefaultRequest(request_template, request, true);
+ if (res != OK) {
+ return res;
+ }
+ // Pass 2, build request
+ res = constructDefaultRequest(request_template, request, false);
+ if (res != OK) {
+ ALOGE("Unable to populate new request for template %d", request_template);
+ }
+
+ return res;
+}
+
+int EmulatedFakeCamera2::allocateStream(
+ uint32_t width, uint32_t height, int format,
+ const camera2_stream_ops_t *stream_ops, uint32_t *stream_id,
+ uint32_t *format_actual, uint32_t *usage, uint32_t *max_buffers) {
+ Mutex::Autolock l(mMutex);
+
+ if (!mStatusPresent) {
+ ALOGW("%s: Camera was physically disconnected", __FUNCTION__);
+ return ERROR_CAMERA_NOT_PRESENT;
+ }
+
+ // Temporary shim until FORMAT_ZSL is removed
+ if (format == CAMERA2_HAL_PIXEL_FORMAT_ZSL) {
+ format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
+ }
+
+ if (format != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
+ unsigned int numFormats = sizeof(kAvailableFormats) / sizeof(uint32_t);
+ unsigned int formatIdx = 0;
+ for (; formatIdx < numFormats; formatIdx++) {
+ if (format == (int)kAvailableFormats[formatIdx]) break;
+ }
+ if (formatIdx == numFormats) {
+ ALOGE("%s: Format 0x%x is not supported", __FUNCTION__, format);
+ return BAD_VALUE;
+ }
+ }
+
+ const uint32_t *availableSizes;
+ size_t availableSizeCount;
+ switch (format) {
+ case HAL_PIXEL_FORMAT_RAW16:
+ availableSizes = &mAvailableRawSizes.front();
+ availableSizeCount = mAvailableRawSizes.size();
+ break;
+ case HAL_PIXEL_FORMAT_BLOB:
+ availableSizes = &mAvailableJpegSizes.front();
+ availableSizeCount = mAvailableJpegSizes.size();
+ break;
+ case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
+ case HAL_PIXEL_FORMAT_RGBA_8888:
+ case HAL_PIXEL_FORMAT_YV12:
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+ availableSizes = &mAvailableProcessedSizes.front();
+ availableSizeCount = mAvailableProcessedSizes.size();
+ break;
+ default:
+ ALOGE("%s: Unknown format 0x%x", __FUNCTION__, format);
+ return BAD_VALUE;
+ }
+
+ unsigned int resIdx = 0;
+ for (; resIdx < availableSizeCount; resIdx++) {
+ if (availableSizes[resIdx * 2] == width &&
+ availableSizes[resIdx * 2 + 1] == height)
+ break;
+ }
+ if (resIdx == availableSizeCount) {
+ ALOGE("%s: Format 0x%x does not support resolution %d, %d", __FUNCTION__,
+ format, width, height);
+ return BAD_VALUE;
+ }
+
+ switch (format) {
+ case HAL_PIXEL_FORMAT_RAW16:
+ if (mRawStreamCount >= kMaxRawStreamCount) {
+ ALOGE("%s: Cannot allocate another raw stream (%d already allocated)",
+ __FUNCTION__, mRawStreamCount);
+ return INVALID_OPERATION;
+ }
+ mRawStreamCount++;
+ break;
+ case HAL_PIXEL_FORMAT_BLOB:
+ if (mJpegStreamCount >= kMaxJpegStreamCount) {
+ ALOGE("%s: Cannot allocate another JPEG stream (%d already allocated)",
+ __FUNCTION__, mJpegStreamCount);
+ return INVALID_OPERATION;
+ }
+ mJpegStreamCount++;
+ break;
+ default:
+ if (mProcessedStreamCount >= kMaxProcessedStreamCount) {
+ ALOGE(
+ "%s: Cannot allocate another processed stream (%d already "
+ "allocated)",
+ __FUNCTION__, mProcessedStreamCount);
+ return INVALID_OPERATION;
+ }
+ mProcessedStreamCount++;
+ }
+
+ Stream newStream;
+ newStream.ops = stream_ops;
+ newStream.width = width;
+ newStream.height = height;
+ newStream.format = format;
+ // TODO: Query stride from gralloc
+ newStream.stride = width;
+
+ mStreams.add(mNextStreamId, newStream);
+
+ *stream_id = mNextStreamId;
+ if (format_actual) *format_actual = format;
+ *usage = GRALLOC_USAGE_HW_CAMERA_WRITE;
+ *max_buffers = kMaxBufferCount;
+
+ ALOGV("Stream allocated: %d, %d x %d, 0x%x. U: %x, B: %d", *stream_id, width,
+ height, format, *usage, *max_buffers);
+
+ mNextStreamId++;
+ return NO_ERROR;
+}
+
+int EmulatedFakeCamera2::registerStreamBuffers(uint32_t stream_id,
+ int num_buffers,
+ buffer_handle_t * /*buffers*/) {
+ Mutex::Autolock l(mMutex);
+
+ if (!mStatusPresent) {
+ ALOGW("%s: Camera was physically disconnected", __FUNCTION__);
+ return ERROR_CAMERA_NOT_PRESENT;
+ }
+
+ ALOGV("%s: Stream %d registering %d buffers", __FUNCTION__, stream_id,
+ num_buffers);
+ // Need to find out what the final concrete pixel format for our stream is
+ // Assumes that all buffers have the same format.
+ if (num_buffers < 1) {
+ ALOGE("%s: Stream %d only has %d buffers!", __FUNCTION__, stream_id,
+ num_buffers);
+ return BAD_VALUE;
+ }
+
+ ssize_t streamIndex = mStreams.indexOfKey(stream_id);
+ if (streamIndex < 0) {
+ ALOGE("%s: Unknown stream id %d!", __FUNCTION__, stream_id);
+ return BAD_VALUE;
+ }
+
+ Stream &stream = mStreams.editValueAt(streamIndex);
+
+ int finalFormat = stream.format;
+
+ if (finalFormat == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
+ finalFormat = HAL_PIXEL_FORMAT_RGBA_8888;
+ }
+
+ ALOGV("%s: Stream %d format set to %x, previously %x", __FUNCTION__,
+ stream_id, finalFormat, stream.format);
+
+ stream.format = finalFormat;
+
+ return NO_ERROR;
+}
+
+int EmulatedFakeCamera2::releaseStream(uint32_t stream_id) {
+ Mutex::Autolock l(mMutex);
+
+ ssize_t streamIndex = mStreams.indexOfKey(stream_id);
+ if (streamIndex < 0) {
+ ALOGE("%s: Unknown stream id %d!", __FUNCTION__, stream_id);
+ return BAD_VALUE;
+ }
+
+ if (isStreamInUse(stream_id)) {
+ ALOGE("%s: Cannot release stream %d; in use!", __FUNCTION__, stream_id);
+ return BAD_VALUE;
+ }
+
+ switch (mStreams.valueAt(streamIndex).format) {
+ case HAL_PIXEL_FORMAT_RAW16:
+ mRawStreamCount--;
+ break;
+ case HAL_PIXEL_FORMAT_BLOB:
+ mJpegStreamCount--;
+ break;
+ default:
+ mProcessedStreamCount--;
+ break;
+ }
+
+ mStreams.removeItemsAt(streamIndex);
+
+ return NO_ERROR;
+}
+
+int EmulatedFakeCamera2::allocateReprocessStreamFromStream(
+ uint32_t output_stream_id, const camera2_stream_in_ops_t *stream_ops,
+ uint32_t *stream_id) {
+ Mutex::Autolock l(mMutex);
+
+ if (!mStatusPresent) {
+ ALOGW("%s: Camera was physically disconnected", __FUNCTION__);
+ return ERROR_CAMERA_NOT_PRESENT;
+ }
+
+ ssize_t baseStreamIndex = mStreams.indexOfKey(output_stream_id);
+ if (baseStreamIndex < 0) {
+ ALOGE("%s: Unknown output stream id %d!", __FUNCTION__, output_stream_id);
+ return BAD_VALUE;
+ }
+
+ const Stream &baseStream = mStreams[baseStreamIndex];
+
+ // We'll reprocess anything we produced
+
+ if (mReprocessStreamCount >= kMaxReprocessStreamCount) {
+ ALOGE("%s: Cannot allocate another reprocess stream (%d already allocated)",
+ __FUNCTION__, mReprocessStreamCount);
+ return INVALID_OPERATION;
+ }
+ mReprocessStreamCount++;
+
+ ReprocessStream newStream;
+ newStream.ops = stream_ops;
+ newStream.width = baseStream.width;
+ newStream.height = baseStream.height;
+ newStream.format = baseStream.format;
+ newStream.stride = baseStream.stride;
+ newStream.sourceStreamId = output_stream_id;
+
+ *stream_id = mNextReprocessStreamId;
+ mReprocessStreams.add(mNextReprocessStreamId, newStream);
+
+ ALOGV("Reprocess stream allocated: %d: %d, %d, 0x%x. Parent stream: %d",
+ *stream_id, newStream.width, newStream.height, newStream.format,
+ output_stream_id);
+
+ mNextReprocessStreamId++;
+ return NO_ERROR;
+}
+
+int EmulatedFakeCamera2::releaseReprocessStream(uint32_t stream_id) {
+ Mutex::Autolock l(mMutex);
+
+ ssize_t streamIndex = mReprocessStreams.indexOfKey(stream_id);
+ if (streamIndex < 0) {
+ ALOGE("%s: Unknown reprocess stream id %d!", __FUNCTION__, stream_id);
+ return BAD_VALUE;
+ }
+
+ if (isReprocessStreamInUse(stream_id)) {
+ ALOGE("%s: Cannot release reprocessing stream %d; in use!", __FUNCTION__,
+ stream_id);
+ return BAD_VALUE;
+ }
+
+ mReprocessStreamCount--;
+ mReprocessStreams.removeItemsAt(streamIndex);
+
+ return NO_ERROR;
+}
+
+int EmulatedFakeCamera2::triggerAction(uint32_t trigger_id, int32_t ext1,
+ int32_t ext2) {
+ Mutex::Autolock l(mMutex);
+
+ if (trigger_id == CAMERA2_EXT_TRIGGER_TESTING_DISCONNECT) {
+ ALOGI("%s: Disconnect trigger - camera must be closed", __FUNCTION__);
+ mStatusPresent = false;
+
+ EmulatedCameraFactory::Instance().onStatusChanged(
+ mCameraID, CAMERA_DEVICE_STATUS_NOT_PRESENT);
+ }
+
+ if (!mStatusPresent) {
+ ALOGW("%s: Camera was physically disconnected", __FUNCTION__);
+ return ERROR_CAMERA_NOT_PRESENT;
+ }
+
+ return mControlThread->triggerAction(trigger_id, ext1, ext2);
+}
+
+/** Shutdown and debug methods */
+
+int EmulatedFakeCamera2::dump(int fd) {
+ String8 result;
+
+ result.appendFormat(" Camera HAL device: EmulatedFakeCamera2\n");
+ result.appendFormat(" Streams:\n");
+ for (size_t i = 0; i < mStreams.size(); i++) {
+ int id = mStreams.keyAt(i);
+ const Stream &s = mStreams.valueAt(i);
+ result.appendFormat(" Stream %d: %d x %d, format 0x%x, stride %d\n",
+ id, s.width, s.height, s.format, s.stride);
+ }
+
+ write(fd, result.string(), result.size());
+
+ return NO_ERROR;
+}
+
+void EmulatedFakeCamera2::signalError() {
+ // TODO: Let parent know so we can shut down cleanly
+ ALOGE("Worker thread is signaling a serious error");
+}
+
+/** Pipeline control worker thread methods */
+
+EmulatedFakeCamera2::ConfigureThread::ConfigureThread(
+ EmulatedFakeCamera2 *parent)
+ : Thread(false), mParent(parent), mRequestCount(0), mNextBuffers(NULL) {
+ mRunning = false;
+}
+
+EmulatedFakeCamera2::ConfigureThread::~ConfigureThread() {}
+
+status_t EmulatedFakeCamera2::ConfigureThread::readyToRun() {
+ Mutex::Autolock lock(mInputMutex);
+
+ ALOGV("Starting up ConfigureThread");
+ mRequest = NULL;
+ mActive = false;
+ mRunning = true;
+
+ mInputSignal.signal();
+ return NO_ERROR;
+}
+
+status_t EmulatedFakeCamera2::ConfigureThread::waitUntilRunning() {
+ Mutex::Autolock lock(mInputMutex);
+ if (!mRunning) {
+ ALOGV("Waiting for configure thread to start");
+ mInputSignal.wait(mInputMutex);
+ }
+ return OK;
+}
+
+status_t EmulatedFakeCamera2::ConfigureThread::newRequestAvailable() {
+ waitUntilRunning();
+
+ Mutex::Autolock lock(mInputMutex);
+
+ mActive = true;
+ mInputSignal.signal();
+
+ return OK;
+}
+
+bool EmulatedFakeCamera2::ConfigureThread::isStreamInUse(uint32_t id) {
+ Mutex::Autolock lock(mInternalsMutex);
+
+ if (mNextBuffers == NULL) return false;
+ for (size_t i = 0; i < mNextBuffers->size(); i++) {
+ if ((*mNextBuffers)[i].streamId == (int)id) return true;
+ }
+ return false;
+}
+
+int EmulatedFakeCamera2::ConfigureThread::getInProgressCount() {
+ Mutex::Autolock lock(mInputMutex);
+ return mRequestCount;
+}
+
+bool EmulatedFakeCamera2::ConfigureThread::threadLoop() {
+ status_t res;
+
+ // Check if we're currently processing or just waiting
+ {
+ Mutex::Autolock lock(mInputMutex);
+ if (!mActive) {
+ // Inactive, keep waiting until we've been signaled
+ status_t res;
+ res = mInputSignal.waitRelative(mInputMutex, kWaitPerLoop);
+ if (res != NO_ERROR && res != TIMED_OUT) {
+ ALOGE("%s: Error waiting for input requests: %d", __FUNCTION__, res);
+ return false;
+ }
+ if (!mActive) return true;
+ ALOGV("New request available");
+ }
+ // Active
+ }
+
+ if (mRequest == NULL) {
+ Mutex::Autolock il(mInternalsMutex);
+
+ ALOGV("Configure: Getting next request");
+ res = mParent->mRequestQueueSrc->dequeue_request(mParent->mRequestQueueSrc,
+ &mRequest);
+ if (res != NO_ERROR) {
+ ALOGE("%s: Error dequeuing next request: %d", __FUNCTION__, res);
+ mParent->signalError();
+ return false;
+ }
+ if (mRequest == NULL) {
+ ALOGV("Configure: Request queue empty, going inactive");
+ // No requests available, go into inactive mode
+ Mutex::Autolock lock(mInputMutex);
+ mActive = false;
+ return true;
+ } else {
+ Mutex::Autolock lock(mInputMutex);
+ mRequestCount++;
+ }
+
+ camera_metadata_entry_t type;
+ res = find_camera_metadata_entry(mRequest, ANDROID_REQUEST_TYPE, &type);
+ if (res != NO_ERROR) {
+ ALOGE("%s: error reading request type", __FUNCTION__);
+ mParent->signalError();
+ return false;
+ }
+ bool success = false;
+ ;
+ switch (type.data.u8[0]) {
+ case ANDROID_REQUEST_TYPE_CAPTURE:
+ success = setupCapture();
+ break;
+ case ANDROID_REQUEST_TYPE_REPROCESS:
+ success = setupReprocess();
+ break;
+ default:
+ ALOGE("%s: Unexpected request type %d", __FUNCTION__, type.data.u8[0]);
+ mParent->signalError();
+ break;
+ }
+ if (!success) return false;
+ }
+
+ if (mWaitingForReadout) {
+ bool readoutDone;
+ readoutDone = mParent->mReadoutThread->waitForReady(kWaitPerLoop);
+ if (!readoutDone) return true;
+
+ if (mNextNeedsJpeg) {
+ ALOGV("Configure: Waiting for JPEG compressor");
+ } else {
+ ALOGV("Configure: Waiting for sensor");
+ }
+ mWaitingForReadout = false;
+ }
+
+ if (mNextNeedsJpeg) {
+ bool jpegDone;
+ jpegDone = mParent->mJpegCompressor->waitForDone(kWaitPerLoop);
+ if (!jpegDone) return true;
+
+ ALOGV("Configure: Waiting for sensor");
+ mNextNeedsJpeg = false;
+ }
+
+ if (mNextIsCapture) {
+ return configureNextCapture();
+ } else {
+ return configureNextReprocess();
+ }
+}
+
+bool EmulatedFakeCamera2::ConfigureThread::setupCapture() {
+ status_t res;
+
+ mNextIsCapture = true;
+ // Get necessary parameters for sensor config
+ mParent->mControlThread->processRequest(mRequest);
+
+ camera_metadata_entry_t streams;
+ res = find_camera_metadata_entry(mRequest, ANDROID_REQUEST_OUTPUT_STREAMS,
+ &streams);
+ if (res != NO_ERROR) {
+ ALOGE("%s: error reading output stream tag", __FUNCTION__);
+ mParent->signalError();
+ return false;
+ }
+
+ mNextBuffers = new Buffers;
+ mNextNeedsJpeg = false;
+ ALOGV("Configure: Setting up buffers for capture");
+ for (size_t i = 0; i < streams.count; i++) {
+ int streamId = streams.data.i32[i];
+ const Stream &s = mParent->getStreamInfo(streamId);
+ if (s.format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
+ ALOGE(
+ "%s: Stream %d does not have a concrete pixel format, but "
+ "is included in a request!",
+ __FUNCTION__, streamId);
+ mParent->signalError();
+ return false;
+ }
+ StreamBuffer b;
+ b.streamId = streamId; // streams.data.u8[i];
+ b.width = s.width;
+ b.height = s.height;
+ b.format = s.format;
+ b.stride = s.stride;
+ mNextBuffers->push_back(b);
+ ALOGV(
+ "Configure: Buffer %zu: Stream %d, %d x %d, format 0x%x, "
+ "stride %d",
+ i, b.streamId, b.width, b.height, b.format, b.stride);
+ if (b.format == HAL_PIXEL_FORMAT_BLOB) {
+ mNextNeedsJpeg = true;
+ }
+ }
+
+ camera_metadata_entry_t e;
+ res = find_camera_metadata_entry(mRequest, ANDROID_REQUEST_FRAME_COUNT, &e);
+ if (res != NO_ERROR) {
+ ALOGE("%s: error reading frame count tag: %s (%d)", __FUNCTION__,
+ strerror(-res), res);
+ mParent->signalError();
+ return false;
+ }
+ mNextFrameNumber = *e.data.i32;
+
+ res = find_camera_metadata_entry(mRequest, ANDROID_SENSOR_EXPOSURE_TIME, &e);
+ if (res != NO_ERROR) {
+ ALOGE("%s: error reading exposure time tag: %s (%d)", __FUNCTION__,
+ strerror(-res), res);
+ mParent->signalError();
+ return false;
+ }
+ mNextExposureTime = *e.data.i64;
+
+ res = find_camera_metadata_entry(mRequest, ANDROID_SENSOR_FRAME_DURATION, &e);
+ if (res != NO_ERROR) {
+ ALOGE("%s: error reading frame duration tag", __FUNCTION__);
+ mParent->signalError();
+ return false;
+ }
+ mNextFrameDuration = *e.data.i64;
+
+ if (mNextFrameDuration < mNextExposureTime + Sensor::kMinVerticalBlank) {
+ mNextFrameDuration = mNextExposureTime + Sensor::kMinVerticalBlank;
+ }
+ res = find_camera_metadata_entry(mRequest, ANDROID_SENSOR_SENSITIVITY, &e);
+ if (res != NO_ERROR) {
+ ALOGE("%s: error reading sensitivity tag", __FUNCTION__);
+ mParent->signalError();
+ return false;
+ }
+ mNextSensitivity = *e.data.i32;
+
+ // Start waiting on readout thread
+ mWaitingForReadout = true;
+ ALOGV("Configure: Waiting for readout thread");
+
+ return true;
+}
+
+bool EmulatedFakeCamera2::ConfigureThread::configureNextCapture() {
+ bool vsync = mParent->mSensor->waitForVSync(kWaitPerLoop);
+ if (!vsync) return true;
+
+ Mutex::Autolock il(mInternalsMutex);
+ ALOGV("Configure: Configuring sensor for capture %d", mNextFrameNumber);
+ mParent->mSensor->setExposureTime(mNextExposureTime);
+ mParent->mSensor->setFrameDuration(mNextFrameDuration);
+ mParent->mSensor->setSensitivity(mNextSensitivity);
+
+ getBuffers();
+
+ ALOGV("Configure: Done configure for capture %d", mNextFrameNumber);
+ mParent->mReadoutThread->setNextOperation(true, mRequest, mNextBuffers);
+ mParent->mSensor->setDestinationBuffers(mNextBuffers);
+
+ mRequest = NULL;
+ mNextBuffers = NULL;
+
+ Mutex::Autolock lock(mInputMutex);
+ mRequestCount--;
+
+ return true;
+}
+
+bool EmulatedFakeCamera2::ConfigureThread::setupReprocess() {
+ status_t res;
+
+ mNextNeedsJpeg = true;
+ mNextIsCapture = false;
+
+ camera_metadata_entry_t reprocessStreams;
+ res = find_camera_metadata_entry(mRequest, ANDROID_REQUEST_INPUT_STREAMS,
+ &reprocessStreams);
+ if (res != NO_ERROR) {
+ ALOGE("%s: error reading output stream tag", __FUNCTION__);
+ mParent->signalError();
+ return false;
+ }
+
+ mNextBuffers = new Buffers;
+
+ ALOGV("Configure: Setting up input buffers for reprocess");
+ for (size_t i = 0; i < reprocessStreams.count; i++) {
+ int streamId = reprocessStreams.data.i32[i];
+ const ReprocessStream &s = mParent->getReprocessStreamInfo(streamId);
+ if (s.format != HAL_PIXEL_FORMAT_RGB_888) {
+ ALOGE("%s: Only ZSL reprocessing supported!", __FUNCTION__);
+ mParent->signalError();
+ return false;
+ }
+ StreamBuffer b;
+ b.streamId = -streamId;
+ b.width = s.width;
+ b.height = s.height;
+ b.format = s.format;
+ b.stride = s.stride;
+ mNextBuffers->push_back(b);
+ }
+
+ camera_metadata_entry_t streams;
+ res = find_camera_metadata_entry(mRequest, ANDROID_REQUEST_OUTPUT_STREAMS,
+ &streams);
+ if (res != NO_ERROR) {
+ ALOGE("%s: error reading output stream tag", __FUNCTION__);
+ mParent->signalError();
+ return false;
+ }
+
+ ALOGV("Configure: Setting up output buffers for reprocess");
+ for (size_t i = 0; i < streams.count; i++) {
+ int streamId = streams.data.i32[i];
+ const Stream &s = mParent->getStreamInfo(streamId);
+ if (s.format != HAL_PIXEL_FORMAT_BLOB) {
+ // TODO: Support reprocess to YUV
+ ALOGE("%s: Non-JPEG output stream %d for reprocess not supported",
+ __FUNCTION__, streamId);
+ mParent->signalError();
+ return false;
+ }
+ StreamBuffer b;
+ b.streamId = streams.data.u8[i];
+ b.width = s.width;
+ b.height = s.height;
+ b.format = s.format;
+ b.stride = s.stride;
+ mNextBuffers->push_back(b);
+ ALOGV(
+ "Configure: Buffer %zu: Stream %d, %d x %d, format 0x%x, "
+ "stride %d",
+ i, b.streamId, b.width, b.height, b.format, b.stride);
+ }
+
+ camera_metadata_entry_t e;
+ res = find_camera_metadata_entry(mRequest, ANDROID_REQUEST_FRAME_COUNT, &e);
+ if (res != NO_ERROR) {
+ ALOGE("%s: error reading frame count tag: %s (%d)", __FUNCTION__,
+ strerror(-res), res);
+ mParent->signalError();
+ return false;
+ }
+ mNextFrameNumber = *e.data.i32;
+
+ return true;
+}
+
+bool EmulatedFakeCamera2::ConfigureThread::configureNextReprocess() {
+ Mutex::Autolock il(mInternalsMutex);
+
+ getBuffers();
+
+ ALOGV("Configure: Done configure for reprocess %d", mNextFrameNumber);
+ mParent->mReadoutThread->setNextOperation(false, mRequest, mNextBuffers);
+
+ mRequest = NULL;
+ mNextBuffers = NULL;
+
+ Mutex::Autolock lock(mInputMutex);
+ mRequestCount--;
+
+ return true;
+}
+
+bool EmulatedFakeCamera2::ConfigureThread::getBuffers() {
+ status_t res;
+ /** Get buffers to fill for this frame */
+ for (size_t i = 0; i < mNextBuffers->size(); i++) {
+ StreamBuffer &b = mNextBuffers->editItemAt(i);
+
+ if (b.streamId > 0) {
+ ALOGV("Configure: Dequeing buffer from stream %d", b.streamId);
+ Stream s = mParent->getStreamInfo(b.streamId);
+ res = s.ops->dequeue_buffer(s.ops, &(b.buffer));
+ if (res != NO_ERROR || b.buffer == NULL) {
+ ALOGE("%s: Unable to dequeue buffer from stream %d: %s (%d)",
+ __FUNCTION__, b.streamId, strerror(-res), res);
+ mParent->signalError();
+ return false;
+ }
+
+ /* Lock the buffer from the perspective of the graphics mapper */
+ res = GrallocModule::getInstance().lock(
+ *(b.buffer), GRALLOC_USAGE_HW_CAMERA_WRITE, 0, 0, s.width, s.height,
+ (void **)&(b.img));
+
+ if (res != NO_ERROR) {
+ ALOGE("%s: grbuffer_mapper.lock failure: %s (%d)", __FUNCTION__,
+ strerror(-res), res);
+ s.ops->cancel_buffer(s.ops, b.buffer);
+ mParent->signalError();
+ return false;
+ }
+ } else {
+ ALOGV("Configure: Acquiring buffer from reprocess stream %d",
+ -b.streamId);
+ ReprocessStream s = mParent->getReprocessStreamInfo(-b.streamId);
+ res = s.ops->acquire_buffer(s.ops, &(b.buffer));
+ if (res != NO_ERROR || b.buffer == NULL) {
+ ALOGE(
+ "%s: Unable to acquire buffer from reprocess stream %d: "
+ "%s (%d)",
+ __FUNCTION__, -b.streamId, strerror(-res), res);
+ mParent->signalError();
+ return false;
+ }
+
+ /* Lock the buffer from the perspective of the graphics mapper */
+ res = GrallocModule::getInstance().lock(
+ *(b.buffer), GRALLOC_USAGE_HW_CAMERA_READ, 0, 0, s.width, s.height,
+ (void **)&(b.img));
+ if (res != NO_ERROR) {
+ ALOGE("%s: grbuffer_mapper.lock failure: %s (%d)", __FUNCTION__,
+ strerror(-res), res);
+ s.ops->release_buffer(s.ops, b.buffer);
+ mParent->signalError();
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+EmulatedFakeCamera2::ReadoutThread::ReadoutThread(EmulatedFakeCamera2 *parent)
+ : Thread(false),
+ mParent(parent),
+ mRunning(false),
+ mActive(false),
+ mRequestCount(0),
+ mRequest(NULL),
+ mBuffers(NULL) {
+ mInFlightQueue = new InFlightQueue[kInFlightQueueSize];
+ mInFlightHead = 0;
+ mInFlightTail = 0;
+}
+
+EmulatedFakeCamera2::ReadoutThread::~ReadoutThread() {
+ delete[] mInFlightQueue;
+}
+
+status_t EmulatedFakeCamera2::ReadoutThread::readyToRun() {
+ Mutex::Autolock lock(mInputMutex);
+ ALOGV("Starting up ReadoutThread");
+ mRunning = true;
+ mInputSignal.signal();
+ return NO_ERROR;
+}
+
+status_t EmulatedFakeCamera2::ReadoutThread::waitUntilRunning() {
+ Mutex::Autolock lock(mInputMutex);
+ if (!mRunning) {
+ ALOGV("Waiting for readout thread to start");
+ mInputSignal.wait(mInputMutex);
+ }
+ return OK;
+}
+
+bool EmulatedFakeCamera2::ReadoutThread::waitForReady(nsecs_t timeout) {
+ status_t res;
+ Mutex::Autolock lock(mInputMutex);
+ while (!readyForNextCapture()) {
+ res = mReadySignal.waitRelative(mInputMutex, timeout);
+ if (res == TIMED_OUT) return false;
+ if (res != OK) {
+ ALOGE("%s: Error waiting for ready: %s (%d)", __FUNCTION__,
+ strerror(-res), res);
+ return false;
+ }
+ }
+ return true;
+}
+
+bool EmulatedFakeCamera2::ReadoutThread::readyForNextCapture() {
+ return (mInFlightTail + 1) % kInFlightQueueSize != mInFlightHead;
+}
+
+void EmulatedFakeCamera2::ReadoutThread::setNextOperation(
+ bool isCapture, camera_metadata_t *request, Buffers *buffers) {
+ Mutex::Autolock lock(mInputMutex);
+ if (!readyForNextCapture()) {
+ ALOGE("In flight queue full, dropping captures");
+ mParent->signalError();
+ return;
+ }
+ mInFlightQueue[mInFlightTail].isCapture = isCapture;
+ mInFlightQueue[mInFlightTail].request = request;
+ mInFlightQueue[mInFlightTail].buffers = buffers;
+ mInFlightTail = (mInFlightTail + 1) % kInFlightQueueSize;
+ mRequestCount++;
+
+ if (!mActive) {
+ mActive = true;
+ mInputSignal.signal();
+ }
+}
+
+bool EmulatedFakeCamera2::ReadoutThread::isStreamInUse(uint32_t id) {
+ // acquire in same order as threadLoop
+ Mutex::Autolock iLock(mInternalsMutex);
+ Mutex::Autolock lock(mInputMutex);
+
+ size_t i = mInFlightHead;
+ while (i != mInFlightTail) {
+ for (size_t j = 0; j < mInFlightQueue[i].buffers->size(); j++) {
+ if ((*(mInFlightQueue[i].buffers))[j].streamId == (int)id) return true;
+ }
+ i = (i + 1) % kInFlightQueueSize;
+ }
+
+ if (mBuffers != NULL) {
+ for (i = 0; i < mBuffers->size(); i++) {
+ if ((*mBuffers)[i].streamId == (int)id) return true;
+ }
+ }
+
+ return false;
+}
+
+int EmulatedFakeCamera2::ReadoutThread::getInProgressCount() {
+ Mutex::Autolock lock(mInputMutex);
+
+ return mRequestCount;
+}
+
+bool EmulatedFakeCamera2::ReadoutThread::threadLoop() {
+ static const nsecs_t kWaitPerLoop = 10000000L; // 10 ms
+ status_t res;
+ int32_t frameNumber;
+
+ // Check if we're currently processing or just waiting
+ {
+ Mutex::Autolock lock(mInputMutex);
+ if (!mActive) {
+ // Inactive, keep waiting until we've been signaled
+ res = mInputSignal.waitRelative(mInputMutex, kWaitPerLoop);
+ if (res != NO_ERROR && res != TIMED_OUT) {
+ ALOGE("%s: Error waiting for capture requests: %d", __FUNCTION__, res);
+ mParent->signalError();
+ return false;
+ }
+ if (!mActive) return true;
+ }
+ // Active, see if we need a new request
+ if (mRequest == NULL) {
+ if (mInFlightHead == mInFlightTail) {
+ // Go inactive
+ ALOGV("Waiting for sensor data");
+ mActive = false;
+ return true;
+ } else {
+ Mutex::Autolock iLock(mInternalsMutex);
+ mReadySignal.signal();
+ mIsCapture = mInFlightQueue[mInFlightHead].isCapture;
+ mRequest = mInFlightQueue[mInFlightHead].request;
+ mBuffers = mInFlightQueue[mInFlightHead].buffers;
+ mInFlightQueue[mInFlightHead].request = NULL;
+ mInFlightQueue[mInFlightHead].buffers = NULL;
+ mInFlightHead = (mInFlightHead + 1) % kInFlightQueueSize;
+ ALOGV("Ready to read out request %p, %zu buffers", mRequest,
+ mBuffers->size());
+ }
+ }
+ }
+
+ // Active with request, wait on sensor to complete
+
+ nsecs_t captureTime;
+
+ if (mIsCapture) {
+ bool gotFrame;
+ gotFrame = mParent->mSensor->waitForNewFrame(kWaitPerLoop, &captureTime);
+
+ if (!gotFrame) return true;
+ }
+
+ Mutex::Autolock iLock(mInternalsMutex);
+
+ camera_metadata_entry_t entry;
+ if (!mIsCapture) {
+ res =
+ find_camera_metadata_entry(mRequest, ANDROID_SENSOR_TIMESTAMP, &entry);
+ if (res != NO_ERROR) {
+ ALOGE("%s: error reading reprocessing timestamp: %s (%d)", __FUNCTION__,
+ strerror(-res), res);
+ mParent->signalError();
+ return false;
+ }
+ captureTime = entry.data.i64[0];
+ }
+
+ res =
+ find_camera_metadata_entry(mRequest, ANDROID_REQUEST_FRAME_COUNT, &entry);
+ if (res != NO_ERROR) {
+ ALOGE("%s: error reading frame count tag: %s (%d)", __FUNCTION__,
+ strerror(-res), res);
+ mParent->signalError();
+ return false;
+ }
+ frameNumber = *entry.data.i32;
+
+ res = find_camera_metadata_entry(mRequest, ANDROID_REQUEST_METADATA_MODE,
+ &entry);
+ if (res != NO_ERROR) {
+ ALOGE("%s: error reading metadata mode tag: %s (%d)", __FUNCTION__,
+ strerror(-res), res);
+ mParent->signalError();
+ return false;
+ }
+
+ // Got sensor data and request, construct frame and send it out
+ ALOGV("Readout: Constructing metadata and frames for request %d",
+ frameNumber);
+
+ if (*entry.data.u8 == ANDROID_REQUEST_METADATA_MODE_FULL) {
+ ALOGV("Readout: Metadata requested, constructing");
+
+ camera_metadata_t *frame = NULL;
+
+ size_t frame_entries = get_camera_metadata_entry_count(mRequest);
+ size_t frame_data = get_camera_metadata_data_count(mRequest);
+
+ // TODO: Dynamically calculate based on enabled statistics, etc
+ frame_entries += 10;
+ frame_data += 100;
+
+ res = mParent->mFrameQueueDst->dequeue_frame(
+ mParent->mFrameQueueDst, frame_entries, frame_data, &frame);
+
+ if (res != NO_ERROR || frame == NULL) {
+ ALOGE("%s: Unable to dequeue frame metadata buffer", __FUNCTION__);
+ mParent->signalError();
+ return false;
+ }
+
+ res = append_camera_metadata(frame, mRequest);
+ if (res != NO_ERROR) {
+ ALOGE("Unable to append request metadata");
+ }
+
+ if (mIsCapture) {
+ add_camera_metadata_entry(frame, ANDROID_SENSOR_TIMESTAMP, &captureTime,
+ 1);
+
+ collectStatisticsMetadata(frame);
+ // TODO: Collect all final values used from sensor in addition to
+ // timestamp
+ }
+
+ ALOGV("Readout: Enqueue frame %d", frameNumber);
+ mParent->mFrameQueueDst->enqueue_frame(mParent->mFrameQueueDst, frame);
+ }
+ ALOGV("Readout: Free request");
+ res = mParent->mRequestQueueSrc->free_request(mParent->mRequestQueueSrc,
+ mRequest);
+ if (res != NO_ERROR) {
+ ALOGE("%s: Unable to return request buffer to queue: %d", __FUNCTION__,
+ res);
+ mParent->signalError();
+ return false;
+ }
+ mRequest = NULL;
+
+ int compressedBufferIndex = -1;
+ ALOGV("Readout: Processing %zu buffers", mBuffers->size());
+ for (size_t i = 0; i < mBuffers->size(); i++) {
+ const StreamBuffer &b = (*mBuffers)[i];
+ ALOGV("Readout: Buffer %zu: Stream %d, %d x %d, format 0x%x, stride %d",
+ i, b.streamId, b.width, b.height, b.format, b.stride);
+ if (b.streamId > 0) {
+ if (b.format == HAL_PIXEL_FORMAT_BLOB) {
+ // Assumes only one BLOB buffer type per capture
+ compressedBufferIndex = i;
+ } else {
+ ALOGV("Readout: Sending image buffer %zu (%p) to output stream %d",
+ i, (void *)*(b.buffer), b.streamId);
+ GrallocModule::getInstance().unlock(*(b.buffer));
+ const Stream &s = mParent->getStreamInfo(b.streamId);
+ res = s.ops->enqueue_buffer(s.ops, captureTime, b.buffer);
+ if (res != OK) {
+ ALOGE("Error enqueuing image buffer %p: %s (%d)", b.buffer,
+ strerror(-res), res);
+ mParent->signalError();
+ }
+ }
+ }
+ }
+
+ if (compressedBufferIndex == -1) {
+ delete mBuffers;
+ } else {
+ ALOGV("Readout: Starting JPEG compression for buffer %d, stream %d",
+ compressedBufferIndex, (*mBuffers)[compressedBufferIndex].streamId);
+ mJpegTimestamp = captureTime;
+ // Takes ownership of mBuffers
+ mParent->mJpegCompressor->start(mBuffers, this);
+ }
+ mBuffers = NULL;
+
+ Mutex::Autolock l(mInputMutex);
+ mRequestCount--;
+ ALOGV("Readout: Done with request %d", frameNumber);
+ return true;
+}
+
+void EmulatedFakeCamera2::ReadoutThread::onJpegDone(
+ const StreamBuffer &jpegBuffer, bool success) {
+ if (!success) {
+ ALOGE("%s: Error queueing compressed image buffer %p", __FUNCTION__,
+ jpegBuffer.buffer);
+ mParent->signalError();
+ return;
+ }
+
+ // Write to JPEG output stream
+ ALOGV("%s: Compression complete, pushing to stream %d", __FUNCTION__,
+ jpegBuffer.streamId);
+
+ GrallocModule::getInstance().unlock(*(jpegBuffer.buffer));
+ const Stream &s = mParent->getStreamInfo(jpegBuffer.streamId);
+ s.ops->enqueue_buffer(s.ops, mJpegTimestamp, jpegBuffer.buffer);
+}
+
+void EmulatedFakeCamera2::ReadoutThread::onJpegInputDone(
+ const StreamBuffer &inputBuffer) {
+ status_t res;
+ GrallocModule::getInstance().unlock(*(inputBuffer.buffer));
+ const ReprocessStream &s =
+ mParent->getReprocessStreamInfo(-inputBuffer.streamId);
+ res = s.ops->release_buffer(s.ops, inputBuffer.buffer);
+ if (res != OK) {
+ ALOGE("Error releasing reprocess buffer %p: %s (%d)", inputBuffer.buffer,
+ strerror(-res), res);
+ mParent->signalError();
+ }
+}
+
+status_t EmulatedFakeCamera2::ReadoutThread::collectStatisticsMetadata(
+ camera_metadata_t *frame) {
+ // Completely fake face rectangles, don't correspond to real faces in scene
+ ALOGV("Readout: Collecting statistics metadata");
+
+ status_t res;
+ camera_metadata_entry_t entry;
+ res = find_camera_metadata_entry(frame, ANDROID_STATISTICS_FACE_DETECT_MODE,
+ &entry);
+ if (res != OK) {
+ ALOGE("%s: Unable to find face detect mode!", __FUNCTION__);
+ return BAD_VALUE;
+ }
+
+ if (entry.data.u8[0] == ANDROID_STATISTICS_FACE_DETECT_MODE_OFF) return OK;
+
+ // The coordinate system for the face regions is the raw sensor pixel
+ // coordinates. Here, we map from the scene coordinates (0-19 in both axis)
+ // to raw pixels, for the scene defined in fake-pipeline2/Scene.cpp. We
+ // approximately place two faces on top of the windows of the house. No
+ // actual faces exist there, but might one day. Note that this doesn't
+ // account for the offsets used to account for aspect ratio differences, so
+ // the rectangles don't line up quite right.
+ const size_t numFaces = 2;
+ int32_t rects[numFaces * 4] = {
+ static_cast<int32_t>(mParent->mSensorWidth * 10 / 20),
+ static_cast<int32_t>(mParent->mSensorHeight * 15 / 20),
+ static_cast<int32_t>(mParent->mSensorWidth * 12 / 20),
+ static_cast<int32_t>(mParent->mSensorHeight * 17 / 20),
+
+ static_cast<int32_t>(mParent->mSensorWidth * 16 / 20),
+ static_cast<int32_t>(mParent->mSensorHeight * 15 / 20),
+ static_cast<int32_t>(mParent->mSensorWidth * 18 / 20),
+ static_cast<int32_t>(mParent->mSensorHeight * 17 / 20)};
+ // To simulate some kind of real detection going on, we jitter the rectangles
+ // on each frame by a few pixels in each dimension.
+ for (size_t i = 0; i < numFaces * 4; i++) {
+ rects[i] += (int32_t)(((float)rand() / (float)RAND_MAX) * 6 - 3);
+ }
+ // The confidence scores (0-100) are similarly jittered.
+ uint8_t scores[numFaces] = {85, 95};
+ for (size_t i = 0; i < numFaces; i++) {
+ scores[i] += (int32_t)(((float)rand() / (float)RAND_MAX) * 10 - 5);
+ }
+
+ res = add_camera_metadata_entry(frame, ANDROID_STATISTICS_FACE_RECTANGLES,
+ rects, numFaces * 4);
+ if (res != OK) {
+ ALOGE("%s: Unable to add face rectangles!", __FUNCTION__);
+ return BAD_VALUE;
+ }
+
+ res = add_camera_metadata_entry(frame, ANDROID_STATISTICS_FACE_SCORES, scores,
+ numFaces);
+ if (res != OK) {
+ ALOGE("%s: Unable to add face scores!", __FUNCTION__);
+ return BAD_VALUE;
+ }
+
+ if (entry.data.u8[0] == ANDROID_STATISTICS_FACE_DETECT_MODE_SIMPLE) return OK;
+
+ // Advanced face detection options - add eye/mouth coordinates. The
+ // coordinates in order are (leftEyeX, leftEyeY, rightEyeX, rightEyeY,
+ // mouthX, mouthY). The mapping is the same as the face rectangles.
+ int32_t features[numFaces * 6] = {
+ static_cast<int32_t>(mParent->mSensorWidth * 10.5 / 20),
+ static_cast<int32_t>(mParent->mSensorHeight * 16 / 20),
+ static_cast<int32_t>(mParent->mSensorWidth * 11.5 / 20),
+ static_cast<int32_t>(mParent->mSensorHeight * 16 / 20),
+ static_cast<int32_t>(mParent->mSensorWidth * 11 / 20),
+ static_cast<int32_t>(mParent->mSensorHeight * 16.5 / 20),
+
+ static_cast<int32_t>(mParent->mSensorWidth * 16.5 / 20),
+ static_cast<int32_t>(mParent->mSensorHeight * 16 / 20),
+ static_cast<int32_t>(mParent->mSensorWidth * 17.5 / 20),
+ static_cast<int32_t>(mParent->mSensorHeight * 16 / 20),
+ static_cast<int32_t>(mParent->mSensorWidth * 17 / 20),
+ static_cast<int32_t>(mParent->mSensorHeight * 16.5 / 20),
+ };
+ // Jitter these a bit less than the rects
+ for (size_t i = 0; i < numFaces * 6; i++) {
+ features[i] += (int32_t)(((float)rand() / (float)RAND_MAX) * 4 - 2);
+ }
+ // These are unique IDs that are used to identify each face while it's
+ // visible to the detector (if a face went away and came back, it'd get a
+ // new ID).
+ int32_t ids[numFaces] = {100, 200};
+
+ res = add_camera_metadata_entry(frame, ANDROID_STATISTICS_FACE_LANDMARKS,
+ features, numFaces * 6);
+ if (res != OK) {
+ ALOGE("%s: Unable to add face landmarks!", __FUNCTION__);
+ return BAD_VALUE;
+ }
+
+ res = add_camera_metadata_entry(frame, ANDROID_STATISTICS_FACE_IDS, ids,
+ numFaces);
+ if (res != OK) {
+ ALOGE("%s: Unable to add face scores!", __FUNCTION__);
+ return BAD_VALUE;
+ }
+
+ return OK;
+}
+
+EmulatedFakeCamera2::ControlThread::ControlThread(EmulatedFakeCamera2 *parent)
+ : Thread(false), mParent(parent) {
+ mRunning = false;
+}
+
+EmulatedFakeCamera2::ControlThread::~ControlThread() {}
+
+status_t EmulatedFakeCamera2::ControlThread::readyToRun() {
+ Mutex::Autolock lock(mInputMutex);
+
+ ALOGV("Starting up ControlThread");
+ mRunning = true;
+ mStartAf = false;
+ mCancelAf = false;
+ mStartPrecapture = false;
+
+ mControlMode = ANDROID_CONTROL_MODE_AUTO;
+
+ mEffectMode = ANDROID_CONTROL_EFFECT_MODE_OFF;
+ mSceneMode = ANDROID_CONTROL_SCENE_MODE_FACE_PRIORITY;
+
+ mAfMode = ANDROID_CONTROL_AF_MODE_AUTO;
+ mAfModeChange = false;
+
+ mAeMode = ANDROID_CONTROL_AE_MODE_ON;
+ mAwbMode = ANDROID_CONTROL_AWB_MODE_AUTO;
+
+ mAfTriggerId = 0;
+ mPrecaptureTriggerId = 0;
+
+ mAfState = ANDROID_CONTROL_AF_STATE_INACTIVE;
+ mAeState = ANDROID_CONTROL_AE_STATE_INACTIVE;
+ mAwbState = ANDROID_CONTROL_AWB_STATE_INACTIVE;
+
+ mExposureTime = kNormalExposureTime;
+
+ mInputSignal.signal();
+ return NO_ERROR;
+}
+
+status_t EmulatedFakeCamera2::ControlThread::waitUntilRunning() {
+ Mutex::Autolock lock(mInputMutex);
+ if (!mRunning) {
+ ALOGV("Waiting for control thread to start");
+ mInputSignal.wait(mInputMutex);
+ }
+ return OK;
+}
+
+// Override android.control.* fields with 3A values before sending request to
+// sensor
+status_t EmulatedFakeCamera2::ControlThread::processRequest(
+ camera_metadata_t *request) {
+ Mutex::Autolock lock(mInputMutex);
+ // TODO: Add handling for all android.control.* fields here
+ camera_metadata_entry_t mode;
+ status_t res;
+
+#define READ_IF_OK(res, what, def) (((res) == OK) ? (what) : (uint8_t)(def))
+
+ res = find_camera_metadata_entry(request, ANDROID_CONTROL_MODE, &mode);
+ mControlMode = READ_IF_OK(res, mode.data.u8[0], ANDROID_CONTROL_MODE_OFF);
+
+ // disable all 3A
+ if (mControlMode == ANDROID_CONTROL_MODE_OFF) {
+ mEffectMode = ANDROID_CONTROL_EFFECT_MODE_OFF;
+ mSceneMode = ANDROID_CONTROL_SCENE_MODE_DISABLED;
+ mAfMode = ANDROID_CONTROL_AF_MODE_OFF;
+ mAeLock = ANDROID_CONTROL_AE_LOCK_ON;
+ mAeMode = ANDROID_CONTROL_AE_MODE_OFF;
+ mAfModeChange = true;
+ mStartAf = false;
+ mCancelAf = true;
+ mAeState = ANDROID_CONTROL_AE_STATE_INACTIVE;
+ mAwbMode = ANDROID_CONTROL_AWB_MODE_OFF;
+ return res;
+ }
+
+ res = find_camera_metadata_entry(request, ANDROID_CONTROL_EFFECT_MODE, &mode);
+ mEffectMode =
+ READ_IF_OK(res, mode.data.u8[0], ANDROID_CONTROL_EFFECT_MODE_OFF);
+
+ res = find_camera_metadata_entry(request, ANDROID_CONTROL_SCENE_MODE, &mode);
+ mSceneMode =
+ READ_IF_OK(res, mode.data.u8[0], ANDROID_CONTROL_SCENE_MODE_DISABLED);
+
+ res = find_camera_metadata_entry(request, ANDROID_CONTROL_AF_MODE, &mode);
+ if (mAfMode != mode.data.u8[0]) {
+ ALOGV("AF new mode: %d, old mode %d", mode.data.u8[0], mAfMode);
+ mAfMode = mode.data.u8[0];
+ mAfModeChange = true;
+ mStartAf = false;
+ mCancelAf = false;
+ }
+
+ res = find_camera_metadata_entry(request, ANDROID_CONTROL_AE_MODE, &mode);
+ mAeMode = READ_IF_OK(res, mode.data.u8[0], ANDROID_CONTROL_AE_MODE_OFF);
+
+ res = find_camera_metadata_entry(request, ANDROID_CONTROL_AE_LOCK, &mode);
+ uint8_t aeLockVal =
+ READ_IF_OK(res, mode.data.u8[0], ANDROID_CONTROL_AE_LOCK_ON);
+ bool aeLock = (aeLockVal == ANDROID_CONTROL_AE_LOCK_ON);
+ if (mAeLock && !aeLock) {
+ mAeState = ANDROID_CONTROL_AE_STATE_INACTIVE;
+ }
+ mAeLock = aeLock;
+
+ res = find_camera_metadata_entry(request, ANDROID_CONTROL_AWB_MODE, &mode);
+ mAwbMode = READ_IF_OK(res, mode.data.u8[0], ANDROID_CONTROL_AWB_MODE_OFF);
+
+ // TODO: Override more control fields
+
+ if (mAeMode != ANDROID_CONTROL_AE_MODE_OFF) {
+ camera_metadata_entry_t exposureTime;
+ res = find_camera_metadata_entry(request, ANDROID_SENSOR_EXPOSURE_TIME,
+ &exposureTime);
+ if (res == OK) {
+ exposureTime.data.i64[0] = mExposureTime;
+ }
+ }
+
+#undef READ_IF_OK
+
+ return OK;
+}
+
+status_t EmulatedFakeCamera2::ControlThread::triggerAction(uint32_t msgType,
+ int32_t ext1,
+ int32_t ext2) {
+ ALOGV("%s: Triggering %d (%d, %d)", __FUNCTION__, msgType, ext1, ext2);
+ Mutex::Autolock lock(mInputMutex);
+ switch (msgType) {
+ case CAMERA2_TRIGGER_AUTOFOCUS:
+ mAfTriggerId = ext1;
+ mStartAf = true;
+ mCancelAf = false;
+ break;
+ case CAMERA2_TRIGGER_CANCEL_AUTOFOCUS:
+ mAfTriggerId = ext1;
+ mStartAf = false;
+ mCancelAf = true;
+ break;
+ case CAMERA2_TRIGGER_PRECAPTURE_METERING:
+ mPrecaptureTriggerId = ext1;
+ mStartPrecapture = true;
+ break;
+ default:
+ ALOGE("%s: Unknown action triggered: %d (arguments %d %d)", __FUNCTION__,
+ msgType, ext1, ext2);
+ return BAD_VALUE;
+ }
+ return OK;
+}
+
+const nsecs_t EmulatedFakeCamera2::ControlThread::kControlCycleDelay =
+ 100 * MSEC;
+const nsecs_t EmulatedFakeCamera2::ControlThread::kMinAfDuration = 500 * MSEC;
+const nsecs_t EmulatedFakeCamera2::ControlThread::kMaxAfDuration = 900 * MSEC;
+const float EmulatedFakeCamera2::ControlThread::kAfSuccessRate = 0.9;
+// Once every 5 seconds
+const float EmulatedFakeCamera2::ControlThread::kContinuousAfStartRate =
+ kControlCycleDelay / 5.0 * SEC;
+const nsecs_t EmulatedFakeCamera2::ControlThread::kMinAeDuration = 500 * MSEC;
+const nsecs_t EmulatedFakeCamera2::ControlThread::kMaxAeDuration = 2 * SEC;
+const nsecs_t EmulatedFakeCamera2::ControlThread::kMinPrecaptureAeDuration =
+ 100 * MSEC;
+const nsecs_t EmulatedFakeCamera2::ControlThread::kMaxPrecaptureAeDuration =
+ 400 * MSEC;
+// Once every 3 seconds
+const float EmulatedFakeCamera2::ControlThread::kAeScanStartRate =
+ kControlCycleDelay / 3000000000.0;
+
+const nsecs_t EmulatedFakeCamera2::ControlThread::kNormalExposureTime =
+ 10 * MSEC;
+const nsecs_t EmulatedFakeCamera2::ControlThread::kExposureJump = 2 * MSEC;
+const nsecs_t EmulatedFakeCamera2::ControlThread::kMinExposureTime = 1 * MSEC;
+
+bool EmulatedFakeCamera2::ControlThread::threadLoop() {
+ bool afModeChange = false;
+ bool afTriggered = false;
+ bool afCancelled = false;
+ uint8_t afState;
+ uint8_t afMode;
+ int32_t afTriggerId;
+ bool precaptureTriggered = false;
+ uint8_t aeState;
+ uint8_t aeMode;
+ bool aeLock;
+ int32_t precaptureTriggerId;
+ nsecs_t nextSleep = kControlCycleDelay;
+
+ {
+ Mutex::Autolock lock(mInputMutex);
+ if (mStartAf) {
+ ALOGD("Starting AF trigger processing");
+ afTriggered = true;
+ mStartAf = false;
+ } else if (mCancelAf) {
+ ALOGD("Starting cancel AF trigger processing");
+ afCancelled = true;
+ mCancelAf = false;
+ }
+ afState = mAfState;
+ afMode = mAfMode;
+ afModeChange = mAfModeChange;
+ mAfModeChange = false;
+
+ afTriggerId = mAfTriggerId;
+
+ if (mStartPrecapture) {
+ ALOGD("Starting precapture trigger processing");
+ precaptureTriggered = true;
+ mStartPrecapture = false;
+ }
+ aeState = mAeState;
+ aeMode = mAeMode;
+ aeLock = mAeLock;
+ precaptureTriggerId = mPrecaptureTriggerId;
+ }
+
+ if (afCancelled || afModeChange) {
+ ALOGV("Resetting AF state due to cancel/mode change");
+ afState = ANDROID_CONTROL_AF_STATE_INACTIVE;
+ updateAfState(afState, afTriggerId);
+ mAfScanDuration = 0;
+ mLockAfterPassiveScan = false;
+ }
+
+ if (afTriggered) {
+ afState = processAfTrigger(afMode, afState);
+ }
+
+ afState = maybeStartAfScan(afMode, afState);
+ afState = updateAfScan(afMode, afState, &nextSleep);
+ updateAfState(afState, afTriggerId);
+
+ if (precaptureTriggered) {
+ aeState = processPrecaptureTrigger(aeMode, aeState);
+ }
+
+ aeState = maybeStartAeScan(aeMode, aeLock, aeState);
+ aeState = updateAeScan(aeMode, aeLock, aeState, &nextSleep);
+ updateAeState(aeState, precaptureTriggerId);
+
+ int ret;
+ timespec t;
+ t.tv_sec = 0;
+ t.tv_nsec = nextSleep;
+ do {
+ ret = nanosleep(&t, &t);
+ } while (ret != 0);
+
+ if (mAfScanDuration > 0) {
+ mAfScanDuration -= nextSleep;
+ }
+ if (mAeScanDuration > 0) {
+ mAeScanDuration -= nextSleep;
+ }
+
+ return true;
+}
+
+int EmulatedFakeCamera2::ControlThread::processAfTrigger(uint8_t afMode,
+ uint8_t afState) {
+ switch (afMode) {
+ case ANDROID_CONTROL_AF_MODE_OFF:
+ case ANDROID_CONTROL_AF_MODE_EDOF:
+ // Do nothing
+ break;
+ case ANDROID_CONTROL_AF_MODE_MACRO:
+ case ANDROID_CONTROL_AF_MODE_AUTO:
+ switch (afState) {
+ case ANDROID_CONTROL_AF_STATE_INACTIVE:
+ case ANDROID_CONTROL_AF_STATE_FOCUSED_LOCKED:
+ case ANDROID_CONTROL_AF_STATE_NOT_FOCUSED_LOCKED:
+ // Start new focusing cycle
+ mAfScanDuration =
+ ((double)rand() / RAND_MAX) * (kMaxAfDuration - kMinAfDuration) +
+ kMinAfDuration;
+ afState = ANDROID_CONTROL_AF_STATE_ACTIVE_SCAN;
+ ALOGV("%s: AF scan start, duration %" PRId64 " ms", __FUNCTION__,
+ mAfScanDuration / 1000000);
+ break;
+ case ANDROID_CONTROL_AF_STATE_ACTIVE_SCAN:
+ // Ignore new request, already scanning
+ break;
+ default:
+ ALOGE("Unexpected AF state in AUTO/MACRO AF mode: %d", afState);
+ }
+ break;
+ case ANDROID_CONTROL_AF_MODE_CONTINUOUS_PICTURE:
+ switch (afState) {
+ // Picture mode waits for passive scan to complete
+ case ANDROID_CONTROL_AF_STATE_PASSIVE_SCAN:
+ mLockAfterPassiveScan = true;
+ break;
+ case ANDROID_CONTROL_AF_STATE_INACTIVE:
+ afState = ANDROID_CONTROL_AF_STATE_NOT_FOCUSED_LOCKED;
+ break;
+ case ANDROID_CONTROL_AF_STATE_PASSIVE_FOCUSED:
+ afState = ANDROID_CONTROL_AF_STATE_FOCUSED_LOCKED;
+ break;
+ case ANDROID_CONTROL_AF_STATE_FOCUSED_LOCKED:
+ case ANDROID_CONTROL_AF_STATE_NOT_FOCUSED_LOCKED:
+ // Must cancel to get out of these states
+ break;
+ default:
+ ALOGE("Unexpected AF state in CONTINUOUS_PICTURE AF mode: %d",
+ afState);
+ }
+ break;
+ case ANDROID_CONTROL_AF_MODE_CONTINUOUS_VIDEO:
+ switch (afState) {
+ // Video mode does not wait for passive scan to complete
+ case ANDROID_CONTROL_AF_STATE_PASSIVE_SCAN:
+ case ANDROID_CONTROL_AF_STATE_INACTIVE:
+ afState = ANDROID_CONTROL_AF_STATE_NOT_FOCUSED_LOCKED;
+ break;
+ case ANDROID_CONTROL_AF_STATE_PASSIVE_FOCUSED:
+ afState = ANDROID_CONTROL_AF_STATE_FOCUSED_LOCKED;
+ break;
+ case ANDROID_CONTROL_AF_STATE_FOCUSED_LOCKED:
+ case ANDROID_CONTROL_AF_STATE_NOT_FOCUSED_LOCKED:
+ // Must cancel to get out of these states
+ break;
+ default:
+ ALOGE("Unexpected AF state in CONTINUOUS_VIDEO AF mode: %d", afState);
+ }
+ break;
+ default:
+ break;
+ }
+ return afState;
+}
+
+int EmulatedFakeCamera2::ControlThread::maybeStartAfScan(uint8_t afMode,
+ uint8_t afState) {
+ if ((afMode == ANDROID_CONTROL_AF_MODE_CONTINUOUS_VIDEO ||
+ afMode == ANDROID_CONTROL_AF_MODE_CONTINUOUS_PICTURE) &&
+ (afState == ANDROID_CONTROL_AF_STATE_INACTIVE ||
+ afState == ANDROID_CONTROL_AF_STATE_PASSIVE_FOCUSED)) {
+ bool startScan = ((double)rand() / RAND_MAX) < kContinuousAfStartRate;
+ if (startScan) {
+ // Start new passive focusing cycle
+ mAfScanDuration =
+ ((double)rand() / RAND_MAX) * (kMaxAfDuration - kMinAfDuration) +
+ kMinAfDuration;
+ afState = ANDROID_CONTROL_AF_STATE_PASSIVE_SCAN;
+ ALOGV("%s: AF passive scan start, duration %" PRId64 " ms", __FUNCTION__,
+ mAfScanDuration / 1000000);
+ }
+ }
+ return afState;
+}
+
+int EmulatedFakeCamera2::ControlThread::updateAfScan(uint8_t afMode,
+ uint8_t afState,
+ nsecs_t *maxSleep) {
+ if (!(afState == ANDROID_CONTROL_AF_STATE_ACTIVE_SCAN ||
+ afState == ANDROID_CONTROL_AF_STATE_PASSIVE_SCAN)) {
+ return afState;
+ }
+
+ if (mAfScanDuration <= 0) {
+ ALOGV("%s: AF scan done", __FUNCTION__);
+ switch (afMode) {
+ case ANDROID_CONTROL_AF_MODE_MACRO:
+ case ANDROID_CONTROL_AF_MODE_AUTO: {
+ bool success = ((double)rand() / RAND_MAX) < kAfSuccessRate;
+ if (success) {
+ afState = ANDROID_CONTROL_AF_STATE_FOCUSED_LOCKED;
+ } else {
+ afState = ANDROID_CONTROL_AF_STATE_NOT_FOCUSED_LOCKED;
+ }
+ break;
+ }
+ case ANDROID_CONTROL_AF_MODE_CONTINUOUS_PICTURE:
+ if (mLockAfterPassiveScan) {
+ afState = ANDROID_CONTROL_AF_STATE_FOCUSED_LOCKED;
+ mLockAfterPassiveScan = false;
+ } else {
+ afState = ANDROID_CONTROL_AF_STATE_PASSIVE_FOCUSED;
+ }
+ break;
+ case ANDROID_CONTROL_AF_MODE_CONTINUOUS_VIDEO:
+ afState = ANDROID_CONTROL_AF_STATE_PASSIVE_FOCUSED;
+ break;
+ default:
+ ALOGE("Unexpected AF mode in scan state");
+ }
+ } else {
+ if (mAfScanDuration <= *maxSleep) {
+ *maxSleep = mAfScanDuration;
+ }
+ }
+ return afState;
+}
+
+void EmulatedFakeCamera2::ControlThread::updateAfState(uint8_t newState,
+ int32_t triggerId) {
+ Mutex::Autolock lock(mInputMutex);
+ if (mAfState != newState) {
+ ALOGV("%s: Autofocus state now %d, id %d", __FUNCTION__, newState,
+ triggerId);
+ mAfState = newState;
+ mParent->sendNotification(CAMERA2_MSG_AUTOFOCUS, newState, triggerId, 0);
+ }
+}
+
+int EmulatedFakeCamera2::ControlThread::processPrecaptureTrigger(
+ uint8_t aeMode, uint8_t aeState) {
+ switch (aeMode) {
+ case ANDROID_CONTROL_AE_MODE_OFF:
+ // Don't do anything for these
+ return aeState;
+ case ANDROID_CONTROL_AE_MODE_ON:
+ case ANDROID_CONTROL_AE_MODE_ON_AUTO_FLASH:
+ case ANDROID_CONTROL_AE_MODE_ON_ALWAYS_FLASH:
+ case ANDROID_CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE:
+ // Trigger a precapture cycle
+ aeState = ANDROID_CONTROL_AE_STATE_PRECAPTURE;
+ mAeScanDuration =
+ ((double)rand() / RAND_MAX) *
+ (kMaxPrecaptureAeDuration - kMinPrecaptureAeDuration) +
+ kMinPrecaptureAeDuration;
+ ALOGD("%s: AE precapture scan start, duration %" PRId64 " ms",
+ __FUNCTION__, mAeScanDuration / 1000000);
+ }
+ return aeState;
+}
+
+int EmulatedFakeCamera2::ControlThread::maybeStartAeScan(uint8_t aeMode,
+ bool aeLocked,
+ uint8_t aeState) {
+ if (aeLocked) return aeState;
+ switch (aeMode) {
+ case ANDROID_CONTROL_AE_MODE_OFF:
+ break;
+ case ANDROID_CONTROL_AE_MODE_ON:
+ case ANDROID_CONTROL_AE_MODE_ON_AUTO_FLASH:
+ case ANDROID_CONTROL_AE_MODE_ON_ALWAYS_FLASH:
+ case ANDROID_CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE: {
+ if (aeState != ANDROID_CONTROL_AE_STATE_INACTIVE &&
+ aeState != ANDROID_CONTROL_AE_STATE_CONVERGED)
+ break;
+
+ bool startScan = ((double)rand() / RAND_MAX) < kAeScanStartRate;
+ if (startScan) {
+ mAeScanDuration =
+ ((double)rand() / RAND_MAX) * (kMaxAeDuration - kMinAeDuration) +
+ kMinAeDuration;
+ aeState = ANDROID_CONTROL_AE_STATE_SEARCHING;
+ ALOGV("%s: AE scan start, duration %" PRId64 " ms", __FUNCTION__,
+ mAeScanDuration / 1000000);
+ }
+ }
+ }
+
+ return aeState;
+}
+
+int EmulatedFakeCamera2::ControlThread::updateAeScan(uint8_t /*aeMode*/,
+ bool aeLock,
+ uint8_t aeState,
+ nsecs_t *maxSleep) {
+ if (aeLock && aeState != ANDROID_CONTROL_AE_STATE_PRECAPTURE) {
+ mAeScanDuration = 0;
+ aeState = ANDROID_CONTROL_AE_STATE_LOCKED;
+ } else if ((aeState == ANDROID_CONTROL_AE_STATE_SEARCHING) ||
+ (aeState == ANDROID_CONTROL_AE_STATE_PRECAPTURE)) {
+ if (mAeScanDuration <= 0) {
+ ALOGV("%s: AE scan done", __FUNCTION__);
+ aeState = aeLock ? ANDROID_CONTROL_AE_STATE_LOCKED
+ : ANDROID_CONTROL_AE_STATE_CONVERGED;
+
+ Mutex::Autolock lock(mInputMutex);
+ mExposureTime = kNormalExposureTime;
+ } else {
+ if (mAeScanDuration <= *maxSleep) {
+ *maxSleep = mAeScanDuration;
+ }
+
+ int64_t exposureDelta =
+ ((double)rand() / RAND_MAX) * 2 * kExposureJump - kExposureJump;
+ Mutex::Autolock lock(mInputMutex);
+ mExposureTime = mExposureTime + exposureDelta;
+ if (mExposureTime < kMinExposureTime) mExposureTime = kMinExposureTime;
+ }
+ }
+
+ return aeState;
+}
+
+void EmulatedFakeCamera2::ControlThread::updateAeState(uint8_t newState,
+ int32_t triggerId) {
+ Mutex::Autolock lock(mInputMutex);
+ if (mAeState != newState) {
+ ALOGV("%s: Autoexposure state now %d, id %d", __FUNCTION__, newState,
+ triggerId);
+ mAeState = newState;
+ mParent->sendNotification(CAMERA2_MSG_AUTOEXPOSURE, newState, triggerId, 0);
+ }
+}
+
+/** Private methods */
+
+status_t EmulatedFakeCamera2::constructStaticInfo(camera_metadata_t **info,
+ bool sizeRequest) const {
+ size_t entryCount = 0;
+ size_t dataCount = 0;
+ status_t ret;
+
+#define ADD_OR_SIZE(tag, data, count) \
+ if ((ret = addOrSize(*info, sizeRequest, &entryCount, &dataCount, tag, data, \
+ count)) != OK) \
+ return ret
+
+ // android.lens
+
+ // 5 cm min focus distance for back camera, infinity (fixed focus) for front
+ const float minFocusDistance = mFacingBack ? 1.0 / 0.05 : 0.0;
+ ADD_OR_SIZE(ANDROID_LENS_INFO_MINIMUM_FOCUS_DISTANCE, &minFocusDistance, 1);
+ // 5 m hyperfocal distance for back camera, infinity (fixed focus) for front
+ // const float hyperFocalDistance = mFacingBack ? 1.0 / 5.0 : 0.0;
+ ADD_OR_SIZE(ANDROID_LENS_INFO_HYPERFOCAL_DISTANCE, &minFocusDistance, 1);
+
+ static const float focalLength = 3.30f; // mm
+ ADD_OR_SIZE(ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS, &focalLength, 1);
+ static const float aperture = 2.8f;
+ ADD_OR_SIZE(ANDROID_LENS_INFO_AVAILABLE_APERTURES, &aperture, 1);
+ static const float filterDensity = 0;
+ ADD_OR_SIZE(ANDROID_LENS_INFO_AVAILABLE_FILTER_DENSITIES, &filterDensity, 1);
+ static const uint8_t availableOpticalStabilization =
+ ANDROID_LENS_OPTICAL_STABILIZATION_MODE_OFF;
+ ADD_OR_SIZE(ANDROID_LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION,
+ &availableOpticalStabilization, 1);
+
+ static const int32_t lensShadingMapSize[] = {1, 1};
+ ADD_OR_SIZE(ANDROID_LENS_INFO_SHADING_MAP_SIZE, lensShadingMapSize,
+ sizeof(lensShadingMapSize) / sizeof(int32_t));
+
+ int32_t lensFacing =
+ mFacingBack ? ANDROID_LENS_FACING_BACK : ANDROID_LENS_FACING_FRONT;
+ ADD_OR_SIZE(ANDROID_LENS_FACING, &lensFacing, 1);
+
+ // android.sensor
+
+ ADD_OR_SIZE(ANDROID_SENSOR_INFO_EXPOSURE_TIME_RANGE,
+ Sensor::kExposureTimeRange, 2);
+
+ ADD_OR_SIZE(ANDROID_SENSOR_INFO_MAX_FRAME_DURATION,
+ &Sensor::kFrameDurationRange[1], 1);
+
+ ADD_OR_SIZE(ANDROID_SENSOR_INFO_SENSITIVITY_RANGE, Sensor::kSensitivityRange,
+ sizeof(Sensor::kSensitivityRange) / sizeof(int32_t));
+
+ ADD_OR_SIZE(ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT,
+ &Sensor::kColorFilterArrangement, 1);
+
+ static const float sensorPhysicalSize[2] = {3.20f, 2.40f}; // mm
+ ADD_OR_SIZE(ANDROID_SENSOR_INFO_PHYSICAL_SIZE, sensorPhysicalSize, 2);
+
+ const int32_t pixelArray[] = {mSensorWidth, mSensorHeight};
+ ADD_OR_SIZE(ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE, pixelArray, 2);
+
+ ADD_OR_SIZE(ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE, pixelArray, 2);
+
+ ADD_OR_SIZE(ANDROID_SENSOR_INFO_WHITE_LEVEL, &Sensor::kMaxRawValue, 1);
+
+ static const int32_t blackLevelPattern[4] = {
+ static_cast<int32_t>(Sensor::kBlackLevel),
+ static_cast<int32_t>(Sensor::kBlackLevel),
+ static_cast<int32_t>(Sensor::kBlackLevel),
+ static_cast<int32_t>(Sensor::kBlackLevel)};
+ ADD_OR_SIZE(ANDROID_SENSOR_BLACK_LEVEL_PATTERN, blackLevelPattern,
+ sizeof(blackLevelPattern) / sizeof(int32_t));
+
+ // TODO: sensor color calibration fields
+
+ // android.flash
+ static const uint8_t flashAvailable = 0;
+ ADD_OR_SIZE(ANDROID_FLASH_INFO_AVAILABLE, &flashAvailable, 1);
+
+ static const int64_t flashChargeDuration = 0;
+ ADD_OR_SIZE(ANDROID_FLASH_INFO_CHARGE_DURATION, &flashChargeDuration, 1);
+
+ // android.tonemap
+
+ static const int32_t tonemapCurvePoints = 128;
+ ADD_OR_SIZE(ANDROID_TONEMAP_MAX_CURVE_POINTS, &tonemapCurvePoints, 1);
+
+ // android.scaler
+
+ ADD_OR_SIZE(ANDROID_SCALER_AVAILABLE_FORMATS, kAvailableFormats,
+ sizeof(kAvailableFormats) / sizeof(uint32_t));
+
+ ADD_OR_SIZE(ANDROID_SCALER_AVAILABLE_RAW_SIZES, &mAvailableRawSizes.front(),
+ mAvailableRawSizes.size());
+
+ ADD_OR_SIZE(ANDROID_SCALER_AVAILABLE_RAW_MIN_DURATIONS,
+ kAvailableRawMinDurations,
+ sizeof(kAvailableRawMinDurations) / sizeof(uint64_t));
+
+ ADD_OR_SIZE(ANDROID_SCALER_AVAILABLE_PROCESSED_SIZES,
+ &mAvailableProcessedSizes.front(),
+ mAvailableProcessedSizes.size());
+
+ ADD_OR_SIZE(ANDROID_SCALER_AVAILABLE_PROCESSED_MIN_DURATIONS,
+ kAvailableProcessedMinDurations,
+ sizeof(kAvailableProcessedMinDurations) / sizeof(uint64_t));
+
+ ADD_OR_SIZE(ANDROID_SCALER_AVAILABLE_JPEG_SIZES, &mAvailableJpegSizes.front(),
+ mAvailableJpegSizes.size());
+
+ ADD_OR_SIZE(ANDROID_SCALER_AVAILABLE_JPEG_MIN_DURATIONS,
+ kAvailableJpegMinDurations,
+ sizeof(kAvailableJpegMinDurations) / sizeof(uint64_t));
+
+ static const float maxZoom = 10;
+ ADD_OR_SIZE(ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM, &maxZoom, 1);
+
+ // android.jpeg
+
+ static const int32_t jpegThumbnailSizes[] = {0, 0, 160, 120, 320, 240};
+ ADD_OR_SIZE(ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES, jpegThumbnailSizes,
+ sizeof(jpegThumbnailSizes) / sizeof(int32_t));
+
+ static const int32_t jpegMaxSize = JpegCompressor::kMaxJpegSize;
+ ADD_OR_SIZE(ANDROID_JPEG_MAX_SIZE, &jpegMaxSize, 1);
+
+ // android.stats
+
+ static const uint8_t availableFaceDetectModes[] = {
+ ANDROID_STATISTICS_FACE_DETECT_MODE_OFF,
+ ANDROID_STATISTICS_FACE_DETECT_MODE_SIMPLE,
+ ANDROID_STATISTICS_FACE_DETECT_MODE_FULL};
+
+ ADD_OR_SIZE(ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES,
+ availableFaceDetectModes, sizeof(availableFaceDetectModes));
+
+ static const int32_t maxFaceCount = 8;
+ ADD_OR_SIZE(ANDROID_STATISTICS_INFO_MAX_FACE_COUNT, &maxFaceCount, 1);
+
+ static const int32_t histogramSize = 64;
+ ADD_OR_SIZE(ANDROID_STATISTICS_INFO_HISTOGRAM_BUCKET_COUNT, &histogramSize,
+ 1);
+
+ static const int32_t maxHistogramCount = 1000;
+ ADD_OR_SIZE(ANDROID_STATISTICS_INFO_MAX_HISTOGRAM_COUNT, &maxHistogramCount,
+ 1);
+
+ static const int32_t sharpnessMapSize[2] = {64, 64};
+ ADD_OR_SIZE(ANDROID_STATISTICS_INFO_SHARPNESS_MAP_SIZE, sharpnessMapSize,
+ sizeof(sharpnessMapSize) / sizeof(int32_t));
+
+ static const int32_t maxSharpnessMapValue = 1000;
+ ADD_OR_SIZE(ANDROID_STATISTICS_INFO_MAX_SHARPNESS_MAP_VALUE,
+ &maxSharpnessMapValue, 1);
+
+ // android.control
+
+ static const uint8_t availableSceneModes[] = {
+ ANDROID_CONTROL_SCENE_MODE_DISABLED
+ };
+ ADD_OR_SIZE(ANDROID_CONTROL_AVAILABLE_SCENE_MODES, availableSceneModes,
+ sizeof(availableSceneModes));
+
+ static const uint8_t availableEffects[] = {ANDROID_CONTROL_EFFECT_MODE_OFF};
+ ADD_OR_SIZE(ANDROID_CONTROL_AVAILABLE_EFFECTS, availableEffects,
+ sizeof(availableEffects));
+
+ static const int32_t max3aRegions[] = {/*AE*/ 0, /*AWB*/ 0, /*AF*/ 0};
+ ADD_OR_SIZE(ANDROID_CONTROL_MAX_REGIONS, max3aRegions,
+ sizeof(max3aRegions) / sizeof(max3aRegions[0]));
+
+ static const uint8_t availableAeModes[] = {ANDROID_CONTROL_AE_MODE_OFF,
+ ANDROID_CONTROL_AE_MODE_ON};
+ ADD_OR_SIZE(ANDROID_CONTROL_AE_AVAILABLE_MODES, availableAeModes,
+ sizeof(availableAeModes));
+
+ static const camera_metadata_rational exposureCompensationStep = {1, 3};
+ ADD_OR_SIZE(ANDROID_CONTROL_AE_COMPENSATION_STEP, &exposureCompensationStep,
+ 1);
+
+ int32_t exposureCompensationRange[] = {-9, 9};
+ ADD_OR_SIZE(ANDROID_CONTROL_AE_COMPENSATION_RANGE, exposureCompensationRange,
+ sizeof(exposureCompensationRange) / sizeof(int32_t));
+
+ static const int32_t availableTargetFpsRanges[] = {5, 30, 15, 30};
+ ADD_OR_SIZE(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,
+ availableTargetFpsRanges,
+ sizeof(availableTargetFpsRanges) / sizeof(int32_t));
+
+ static const uint8_t availableAntibandingModes[] = {
+ ANDROID_CONTROL_AE_ANTIBANDING_MODE_OFF,
+ ANDROID_CONTROL_AE_ANTIBANDING_MODE_AUTO};
+ ADD_OR_SIZE(ANDROID_CONTROL_AE_AVAILABLE_ANTIBANDING_MODES,
+ availableAntibandingModes, sizeof(availableAntibandingModes));
+
+ static const uint8_t availableAwbModes[] = {
+ ANDROID_CONTROL_AWB_MODE_OFF,
+ ANDROID_CONTROL_AWB_MODE_AUTO,
+ ANDROID_CONTROL_AWB_MODE_INCANDESCENT,
+ ANDROID_CONTROL_AWB_MODE_FLUORESCENT,
+ ANDROID_CONTROL_AWB_MODE_DAYLIGHT,
+ ANDROID_CONTROL_AWB_MODE_SHADE};
+ ADD_OR_SIZE(ANDROID_CONTROL_AWB_AVAILABLE_MODES, availableAwbModes,
+ sizeof(availableAwbModes));
+
+ static const uint8_t availableAfModesBack[] = {
+ ANDROID_CONTROL_AF_MODE_OFF, ANDROID_CONTROL_AF_MODE_AUTO,
+ ANDROID_CONTROL_AF_MODE_MACRO, ANDROID_CONTROL_AF_MODE_CONTINUOUS_VIDEO,
+ ANDROID_CONTROL_AF_MODE_CONTINUOUS_PICTURE};
+
+ static const uint8_t availableAfModesFront[] = {ANDROID_CONTROL_AF_MODE_OFF};
+
+ if (mFacingBack) {
+ ADD_OR_SIZE(ANDROID_CONTROL_AF_AVAILABLE_MODES, availableAfModesBack,
+ sizeof(availableAfModesBack));
+ } else {
+ ADD_OR_SIZE(ANDROID_CONTROL_AF_AVAILABLE_MODES, availableAfModesFront,
+ sizeof(availableAfModesFront));
+ }
+
+ static const uint8_t availableVstabModes[] = {
+ ANDROID_CONTROL_VIDEO_STABILIZATION_MODE_OFF};
+ ADD_OR_SIZE(ANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES,
+ availableVstabModes, sizeof(availableVstabModes));
+
+#undef ADD_OR_SIZE
+ /** Allocate metadata if sizing */
+ if (sizeRequest) {
+ ALOGV(
+ "Allocating %zu entries, %zu extra bytes for "
+ "static camera info",
+ entryCount, dataCount);
+ *info = allocate_camera_metadata(entryCount, dataCount);
+ if (*info == NULL) {
+ ALOGE(
+ "Unable to allocate camera static info"
+ "(%zu entries, %zu bytes extra data)",
+ entryCount, dataCount);
+ return NO_MEMORY;
+ }
+ }
+ return OK;
+}
+
+status_t EmulatedFakeCamera2::constructDefaultRequest(
+ int request_template, camera_metadata_t **request, bool sizeRequest) const {
+ size_t entryCount = 0;
+ size_t dataCount = 0;
+ status_t ret;
+
+#define ADD_OR_SIZE(tag, data, count) \
+ if ((ret = addOrSize(*request, sizeRequest, &entryCount, &dataCount, tag, \
+ data, count)) != OK) \
+ return ret
+
+ /** android.request */
+
+ static const uint8_t requestType = ANDROID_REQUEST_TYPE_CAPTURE;
+ ADD_OR_SIZE(ANDROID_REQUEST_TYPE, &requestType, 1);
+
+ static const uint8_t metadataMode = ANDROID_REQUEST_METADATA_MODE_FULL;
+ ADD_OR_SIZE(ANDROID_REQUEST_METADATA_MODE, &metadataMode, 1);
+
+ static const int32_t id = 0;
+ ADD_OR_SIZE(ANDROID_REQUEST_ID, &id, 1);
+
+ static const int32_t frameCount = 0;
+ ADD_OR_SIZE(ANDROID_REQUEST_FRAME_COUNT, &frameCount, 1);
+
+ // OUTPUT_STREAMS set by user
+ entryCount += 1;
+ dataCount += 5; // TODO: Should be maximum stream number
+
+ /** android.lens */
+
+ static const float focusDistance = 0;
+ ADD_OR_SIZE(ANDROID_LENS_FOCUS_DISTANCE, &focusDistance, 1);
+
+ static const float aperture = 2.8f;
+ ADD_OR_SIZE(ANDROID_LENS_APERTURE, &aperture, 1);
+
+ static const float focalLength = 5.0f;
+ ADD_OR_SIZE(ANDROID_LENS_FOCAL_LENGTH, &focalLength, 1);
+
+ static const float filterDensity = 0;
+ ADD_OR_SIZE(ANDROID_LENS_FILTER_DENSITY, &filterDensity, 1);
+
+ static const uint8_t opticalStabilizationMode =
+ ANDROID_LENS_OPTICAL_STABILIZATION_MODE_OFF;
+ ADD_OR_SIZE(ANDROID_LENS_OPTICAL_STABILIZATION_MODE,
+ &opticalStabilizationMode, 1);
+
+ // FOCUS_RANGE set only in frame
+
+ /** android.sensor */
+
+ static const int64_t exposureTime = 10 * MSEC;
+ ADD_OR_SIZE(ANDROID_SENSOR_EXPOSURE_TIME, &exposureTime, 1);
+
+ static const int64_t frameDuration = 33333333L; // 1/30 s
+ ADD_OR_SIZE(ANDROID_SENSOR_FRAME_DURATION, &frameDuration, 1);
+
+ static const int32_t sensitivity = 100;
+ ADD_OR_SIZE(ANDROID_SENSOR_SENSITIVITY, &sensitivity, 1);
+
+ // TIMESTAMP set only in frame
+
+ /** android.flash */
+
+ static const uint8_t flashMode = ANDROID_FLASH_MODE_OFF;
+ ADD_OR_SIZE(ANDROID_FLASH_MODE, &flashMode, 1);
+
+ static const uint8_t flashPower = 10;
+ ADD_OR_SIZE(ANDROID_FLASH_FIRING_POWER, &flashPower, 1);
+
+ static const int64_t firingTime = 0;
+ ADD_OR_SIZE(ANDROID_FLASH_FIRING_TIME, &firingTime, 1);
+
+ /** Processing block modes */
+ uint8_t hotPixelMode = 0;
+ uint8_t demosaicMode = 0;
+ uint8_t noiseMode = 0;
+ uint8_t shadingMode = 0;
+ uint8_t colorMode = 0;
+ uint8_t tonemapMode = 0;
+ uint8_t edgeMode = 0;
+ switch (request_template) {
+ case CAMERA2_TEMPLATE_STILL_CAPTURE:
+ // fall-through
+ case CAMERA2_TEMPLATE_VIDEO_SNAPSHOT:
+ // fall-through
+ case CAMERA2_TEMPLATE_ZERO_SHUTTER_LAG:
+ hotPixelMode = ANDROID_HOT_PIXEL_MODE_HIGH_QUALITY;
+ demosaicMode = ANDROID_DEMOSAIC_MODE_HIGH_QUALITY;
+ noiseMode = ANDROID_NOISE_REDUCTION_MODE_HIGH_QUALITY;
+ shadingMode = ANDROID_SHADING_MODE_HIGH_QUALITY;
+ colorMode = ANDROID_COLOR_CORRECTION_MODE_HIGH_QUALITY;
+ tonemapMode = ANDROID_TONEMAP_MODE_HIGH_QUALITY;
+ edgeMode = ANDROID_EDGE_MODE_HIGH_QUALITY;
+ break;
+ case CAMERA2_TEMPLATE_PREVIEW:
+ // fall-through
+ case CAMERA2_TEMPLATE_VIDEO_RECORD:
+ // fall-through
+ default:
+ hotPixelMode = ANDROID_HOT_PIXEL_MODE_FAST;
+ demosaicMode = ANDROID_DEMOSAIC_MODE_FAST;
+ noiseMode = ANDROID_NOISE_REDUCTION_MODE_FAST;
+ shadingMode = ANDROID_SHADING_MODE_FAST;
+ colorMode = ANDROID_COLOR_CORRECTION_MODE_FAST;
+ tonemapMode = ANDROID_TONEMAP_MODE_FAST;
+ edgeMode = ANDROID_EDGE_MODE_FAST;
+ break;
+ }
+ ADD_OR_SIZE(ANDROID_HOT_PIXEL_MODE, &hotPixelMode, 1);
+ ADD_OR_SIZE(ANDROID_DEMOSAIC_MODE, &demosaicMode, 1);
+ ADD_OR_SIZE(ANDROID_NOISE_REDUCTION_MODE, &noiseMode, 1);
+ ADD_OR_SIZE(ANDROID_SHADING_MODE, &shadingMode, 1);
+ ADD_OR_SIZE(ANDROID_COLOR_CORRECTION_MODE, &colorMode, 1);
+ ADD_OR_SIZE(ANDROID_TONEMAP_MODE, &tonemapMode, 1);
+ ADD_OR_SIZE(ANDROID_EDGE_MODE, &edgeMode, 1);
+
+ /** android.noise */
+ static const uint8_t noiseStrength = 5;
+ ADD_OR_SIZE(ANDROID_NOISE_REDUCTION_STRENGTH, &noiseStrength, 1);
+
+ /** android.color */
+ static const float colorTransform[9] = {1.0f, 0.f, 0.f, 0.f, 1.f,
+ 0.f, 0.f, 0.f, 1.f};
+ ADD_OR_SIZE(ANDROID_COLOR_CORRECTION_TRANSFORM, colorTransform, 9);
+
+ /** android.tonemap */
+ static const float tonemapCurve[4] = {0.f, 0.f, 1.f, 1.f};
+ ADD_OR_SIZE(ANDROID_TONEMAP_CURVE_RED, tonemapCurve, 4);
+ ADD_OR_SIZE(ANDROID_TONEMAP_CURVE_GREEN, tonemapCurve, 4);
+ ADD_OR_SIZE(ANDROID_TONEMAP_CURVE_BLUE, tonemapCurve, 4);
+
+ /** android.edge */
+ static const uint8_t edgeStrength = 5;
+ ADD_OR_SIZE(ANDROID_EDGE_STRENGTH, &edgeStrength, 1);
+
+ /** android.scaler */
+ static const int32_t cropRegion[3] = {0, 0,
+ static_cast<int32_t>(mSensorWidth)};
+ ADD_OR_SIZE(ANDROID_SCALER_CROP_REGION, cropRegion, 3);
+
+ /** android.jpeg */
+ static const int32_t jpegQuality = 80;
+ ADD_OR_SIZE(ANDROID_JPEG_QUALITY, &jpegQuality, 1);
+
+ static const int32_t thumbnailSize[2] = {640, 480};
+ ADD_OR_SIZE(ANDROID_JPEG_THUMBNAIL_SIZE, thumbnailSize, 2);
+
+ static const int32_t thumbnailQuality = 80;
+ ADD_OR_SIZE(ANDROID_JPEG_THUMBNAIL_QUALITY, &thumbnailQuality, 1);
+
+ static const double gpsCoordinates[2] = {0, 0};
+ ADD_OR_SIZE(ANDROID_JPEG_GPS_COORDINATES, gpsCoordinates, 2);
+
+ static const uint8_t gpsProcessingMethod[32] = "None";
+ ADD_OR_SIZE(ANDROID_JPEG_GPS_PROCESSING_METHOD, gpsProcessingMethod, 32);
+
+ static const int64_t gpsTimestamp = 0;
+ ADD_OR_SIZE(ANDROID_JPEG_GPS_TIMESTAMP, &gpsTimestamp, 1);
+
+ static const int32_t jpegOrientation = 0;
+ ADD_OR_SIZE(ANDROID_JPEG_ORIENTATION, &jpegOrientation, 1);
+
+ /** android.stats */
+
+ static const uint8_t faceDetectMode = ANDROID_STATISTICS_FACE_DETECT_MODE_OFF;
+ ADD_OR_SIZE(ANDROID_STATISTICS_FACE_DETECT_MODE, &faceDetectMode, 1);
+
+ static const uint8_t histogramMode = ANDROID_STATISTICS_HISTOGRAM_MODE_OFF;
+ ADD_OR_SIZE(ANDROID_STATISTICS_HISTOGRAM_MODE, &histogramMode, 1);
+
+ static const uint8_t sharpnessMapMode =
+ ANDROID_STATISTICS_SHARPNESS_MAP_MODE_OFF;
+ ADD_OR_SIZE(ANDROID_STATISTICS_SHARPNESS_MAP_MODE, &sharpnessMapMode, 1);
+
+ // faceRectangles, faceScores, faceLandmarks, faceIds, histogram,
+ // sharpnessMap only in frames
+
+ /** android.control */
+
+ uint8_t controlIntent = 0;
+ switch (request_template) {
+ case CAMERA2_TEMPLATE_PREVIEW:
+ controlIntent = ANDROID_CONTROL_CAPTURE_INTENT_PREVIEW;
+ break;
+ case CAMERA2_TEMPLATE_STILL_CAPTURE:
+ controlIntent = ANDROID_CONTROL_CAPTURE_INTENT_STILL_CAPTURE;
+ break;
+ case CAMERA2_TEMPLATE_VIDEO_RECORD:
+ controlIntent = ANDROID_CONTROL_CAPTURE_INTENT_VIDEO_RECORD;
+ break;
+ case CAMERA2_TEMPLATE_VIDEO_SNAPSHOT:
+ controlIntent = ANDROID_CONTROL_CAPTURE_INTENT_VIDEO_SNAPSHOT;
+ break;
+ case CAMERA2_TEMPLATE_ZERO_SHUTTER_LAG:
+ controlIntent = ANDROID_CONTROL_CAPTURE_INTENT_ZERO_SHUTTER_LAG;
+ break;
+ default:
+ controlIntent = ANDROID_CONTROL_CAPTURE_INTENT_CUSTOM;
+ break;
+ }
+ ADD_OR_SIZE(ANDROID_CONTROL_CAPTURE_INTENT, &controlIntent, 1);
+
+ static const uint8_t controlMode = ANDROID_CONTROL_MODE_AUTO;
+ ADD_OR_SIZE(ANDROID_CONTROL_MODE, &controlMode, 1);
+
+ static const uint8_t effectMode = ANDROID_CONTROL_EFFECT_MODE_OFF;
+ ADD_OR_SIZE(ANDROID_CONTROL_EFFECT_MODE, &effectMode, 1);
+
+ static const uint8_t sceneMode = ANDROID_CONTROL_SCENE_MODE_FACE_PRIORITY;
+ ADD_OR_SIZE(ANDROID_CONTROL_SCENE_MODE, &sceneMode, 1);
+
+ static const uint8_t aeMode = ANDROID_CONTROL_AE_MODE_ON_AUTO_FLASH;
+ ADD_OR_SIZE(ANDROID_CONTROL_AE_MODE, &aeMode, 1);
+
+ static const uint8_t aeLock = ANDROID_CONTROL_AE_LOCK_OFF;
+ ADD_OR_SIZE(ANDROID_CONTROL_AE_LOCK, &aeLock, 1);
+
+ static const int32_t controlRegions[5] = {
+ 0, 0, static_cast<int32_t>(mSensorWidth),
+ static_cast<int32_t>(mSensorHeight), 1000};
+ ADD_OR_SIZE(ANDROID_CONTROL_AE_REGIONS, controlRegions, 5);
+
+ static const int32_t aeExpCompensation = 0;
+ ADD_OR_SIZE(ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION, &aeExpCompensation, 1);
+
+ static const int32_t aeTargetFpsRange[2] = {10, 30};
+ ADD_OR_SIZE(ANDROID_CONTROL_AE_TARGET_FPS_RANGE, aeTargetFpsRange, 2);
+
+ static const uint8_t aeAntibandingMode =
+ ANDROID_CONTROL_AE_ANTIBANDING_MODE_AUTO;
+ ADD_OR_SIZE(ANDROID_CONTROL_AE_ANTIBANDING_MODE, &aeAntibandingMode, 1);
+
+ static const uint8_t awbMode = ANDROID_CONTROL_AWB_MODE_AUTO;
+ ADD_OR_SIZE(ANDROID_CONTROL_AWB_MODE, &awbMode, 1);
+
+ static const uint8_t awbLock = ANDROID_CONTROL_AWB_LOCK_OFF;
+ ADD_OR_SIZE(ANDROID_CONTROL_AWB_LOCK, &awbLock, 1);
+
+ ADD_OR_SIZE(ANDROID_CONTROL_AWB_REGIONS, controlRegions, 5);
+
+ uint8_t afMode = 0;
+ switch (request_template) {
+ case CAMERA2_TEMPLATE_PREVIEW:
+ afMode = ANDROID_CONTROL_AF_MODE_AUTO;
+ break;
+ case CAMERA2_TEMPLATE_STILL_CAPTURE:
+ afMode = ANDROID_CONTROL_AF_MODE_AUTO;
+ break;
+ case CAMERA2_TEMPLATE_VIDEO_RECORD:
+ afMode = ANDROID_CONTROL_AF_MODE_CONTINUOUS_VIDEO;
+ break;
+ case CAMERA2_TEMPLATE_VIDEO_SNAPSHOT:
+ afMode = ANDROID_CONTROL_AF_MODE_CONTINUOUS_VIDEO;
+ break;
+ case CAMERA2_TEMPLATE_ZERO_SHUTTER_LAG:
+ afMode = ANDROID_CONTROL_AF_MODE_CONTINUOUS_PICTURE;
+ break;
+ default:
+ afMode = ANDROID_CONTROL_AF_MODE_AUTO;
+ break;
+ }
+ ADD_OR_SIZE(ANDROID_CONTROL_AF_MODE, &afMode, 1);
+
+ ADD_OR_SIZE(ANDROID_CONTROL_AF_REGIONS, controlRegions, 5);
+
+ static const uint8_t vstabMode = ANDROID_CONTROL_VIDEO_STABILIZATION_MODE_OFF;
+ ADD_OR_SIZE(ANDROID_CONTROL_VIDEO_STABILIZATION_MODE, &vstabMode, 1);
+
+ // aeState, awbState, afState only in frame
+
+ /** Allocate metadata if sizing */
+ if (sizeRequest) {
+ ALOGV(
+ "Allocating %zu entries, %zu extra bytes for "
+ "request template type %d",
+ entryCount, dataCount, request_template);
+ *request = allocate_camera_metadata(entryCount, dataCount);
+ if (*request == NULL) {
+ ALOGE(
+ "Unable to allocate new request template type %d "
+ "(%zu entries, %zu bytes extra data)",
+ request_template, entryCount, dataCount);
+ return NO_MEMORY;
+ }
+ }
+ return OK;
+#undef ADD_OR_SIZE
+}
+
+status_t EmulatedFakeCamera2::addOrSize(camera_metadata_t *request,
+ bool sizeRequest, size_t *entryCount,
+ size_t *dataCount, uint32_t tag,
+ const void *entryData,
+ size_t entryDataCount) {
+ if (!sizeRequest) {
+ return add_camera_metadata_entry(request, tag, entryData, entryDataCount);
+ } else {
+ int type = get_camera_metadata_tag_type(tag);
+ if (type < 0) return BAD_VALUE;
+ (*entryCount)++;
+ (*dataCount) +=
+ calculate_camera_metadata_entry_data_size(type, entryDataCount);
+ return OK;
+ }
+}
+
+bool EmulatedFakeCamera2::isStreamInUse(uint32_t id) {
+ // Assumes mMutex is locked; otherwise new requests could enter
+ // configureThread while readoutThread is being checked
+
+ // Order of isStreamInUse calls matters
+ if (mConfigureThread->isStreamInUse(id) ||
+ mReadoutThread->isStreamInUse(id) || mJpegCompressor->isStreamInUse(id)) {
+ ALOGE("%s: Stream %d is in use in active requests!", __FUNCTION__, id);
+ return true;
+ }
+ return false;
+}
+
+bool EmulatedFakeCamera2::isReprocessStreamInUse(uint32_t /*id*/) {
+ // TODO: implement
+ return false;
+}
+
+const Stream &EmulatedFakeCamera2::getStreamInfo(uint32_t streamId) {
+ Mutex::Autolock lock(mMutex);
+
+ return mStreams.valueFor(streamId);
+}
+
+const ReprocessStream &EmulatedFakeCamera2::getReprocessStreamInfo(
+ uint32_t streamId) {
+ Mutex::Autolock lock(mMutex);
+
+ return mReprocessStreams.valueFor(streamId);
+}
+
+}; /* namespace android */
diff --git a/guest/hals/camera/EmulatedFakeCamera2.h b/guest/hals/camera/EmulatedFakeCamera2.h
new file mode 100644
index 000000000..b55d01261
--- /dev/null
+++ b/guest/hals/camera/EmulatedFakeCamera2.h
@@ -0,0 +1,421 @@
+/*
+ * Copyright (C) 2012 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 HW_EMULATOR_CAMERA_EMULATED_FAKE_CAMERA2_H
+#define HW_EMULATOR_CAMERA_EMULATED_FAKE_CAMERA2_H
+
+/*
+ * Contains declaration of a class EmulatedFakeCamera2 that encapsulates
+ * functionality of a fake camera that implements version 2 of the camera device
+ * interface.
+ */
+
+#include <vector>
+
+#include <utils/Condition.h>
+#include <utils/KeyedVector.h>
+#include <utils/String16.h>
+#include <utils/String8.h>
+#include "EmulatedCamera2.h"
+#include "fake-pipeline2/Base.h"
+#include "fake-pipeline2/JpegCompressor.h"
+#include "fake-pipeline2/Sensor.h"
+
+namespace android {
+
+/* Encapsulates functionality of an advanced fake camera. This camera contains
+ * a simple simulation of a scene, sensor, and image processing pipeline.
+ */
+class EmulatedFakeCamera2 : public EmulatedCamera2 {
+ public:
+ /* Constructs EmulatedFakeCamera instance. */
+ EmulatedFakeCamera2(int cameraId, bool facingBack,
+ struct hw_module_t *module);
+
+ /* Destructs EmulatedFakeCamera instance. */
+ ~EmulatedFakeCamera2();
+
+ /****************************************************************************
+ * EmulatedCamera2 virtual overrides.
+ ***************************************************************************/
+
+ public:
+ /* Initializes EmulatedFakeCamera2 instance. */
+ status_t Initialize(const cvd::CameraDefinition &props);
+
+ /****************************************************************************
+ * Camera Module API and generic hardware device API implementation
+ ***************************************************************************/
+ public:
+ virtual status_t connectCamera(hw_device_t **device);
+
+ virtual status_t plugCamera();
+ virtual status_t unplugCamera();
+ virtual camera_device_status_t getHotplugStatus();
+
+ virtual status_t closeCamera();
+
+ virtual status_t getCameraInfo(struct camera_info *info);
+
+ /****************************************************************************
+ * EmulatedCamera2 abstract API implementation.
+ ***************************************************************************/
+ protected:
+ /** Request input queue */
+
+ virtual int requestQueueNotify();
+
+ /** Count of requests in flight */
+ virtual int getInProgressCount();
+
+ /** Cancel all captures in flight */
+ // virtual int flushCapturesInProgress();
+
+ /** Construct default request */
+ virtual int constructDefaultRequest(int request_template,
+ camera_metadata_t **request);
+
+ virtual int allocateStream(uint32_t width, uint32_t height, int format,
+ const camera2_stream_ops_t *stream_ops,
+ uint32_t *stream_id, uint32_t *format_actual,
+ uint32_t *usage, uint32_t *max_buffers);
+
+ virtual int registerStreamBuffers(uint32_t stream_id, int num_buffers,
+ buffer_handle_t *buffers);
+
+ virtual int releaseStream(uint32_t stream_id);
+
+ // virtual int allocateReprocessStream(
+ // uint32_t width,
+ // uint32_t height,
+ // uint32_t format,
+ // const camera2_stream_ops_t *stream_ops,
+ // uint32_t *stream_id,
+ // uint32_t *format_actual,
+ // uint32_t *usage,
+ // uint32_t *max_buffers);
+
+ virtual int allocateReprocessStreamFromStream(
+ uint32_t output_stream_id, const camera2_stream_in_ops_t *stream_ops,
+ uint32_t *stream_id);
+
+ virtual int releaseReprocessStream(uint32_t stream_id);
+
+ virtual int triggerAction(uint32_t trigger_id, int32_t ext1, int32_t ext2);
+
+ /** Debug methods */
+
+ virtual int dump(int fd);
+
+ public:
+ /****************************************************************************
+ * Utility methods called by configure/readout threads and pipeline
+ ***************************************************************************/
+
+ // Get information about a given stream. Will lock mMutex
+ const Stream &getStreamInfo(uint32_t streamId);
+ const ReprocessStream &getReprocessStreamInfo(uint32_t streamId);
+
+ // Notifies rest of camera subsystem of serious error
+ void signalError();
+
+ private:
+ /****************************************************************************
+ * Utility methods
+ ***************************************************************************/
+ /** Construct static camera metadata, two-pass */
+ status_t constructStaticInfo(camera_metadata_t **info,
+ bool sizeRequest) const;
+
+ /** Two-pass implementation of constructDefaultRequest */
+ status_t constructDefaultRequest(int request_template,
+ camera_metadata_t **request,
+ bool sizeRequest) const;
+ /** Helper function for constructDefaultRequest */
+ static status_t addOrSize(camera_metadata_t *request, bool sizeRequest,
+ size_t *entryCount, size_t *dataCount, uint32_t tag,
+ const void *entry_data, size_t entry_count);
+
+ /** Determine if the stream id is listed in any currently-in-flight
+ * requests. Assumes mMutex is locked */
+ bool isStreamInUse(uint32_t streamId);
+
+ /** Determine if the reprocess stream id is listed in any
+ * currently-in-flight requests. Assumes mMutex is locked */
+ bool isReprocessStreamInUse(uint32_t streamId);
+
+ /****************************************************************************
+ * Pipeline controller threads
+ ***************************************************************************/
+
+ class ConfigureThread : public Thread {
+ public:
+ ConfigureThread(EmulatedFakeCamera2 *parent);
+ ~ConfigureThread();
+
+ status_t waitUntilRunning();
+ status_t newRequestAvailable();
+ status_t readyToRun();
+
+ bool isStreamInUse(uint32_t id);
+ int getInProgressCount();
+
+ private:
+ EmulatedFakeCamera2 *mParent;
+ static const nsecs_t kWaitPerLoop = 10000000L; // 10 ms
+
+ bool mRunning;
+ bool threadLoop();
+
+ bool setupCapture();
+ bool setupReprocess();
+
+ bool configureNextCapture();
+ bool configureNextReprocess();
+
+ bool getBuffers();
+
+ Mutex mInputMutex; // Protects mActive, mRequestCount
+ Condition mInputSignal;
+ bool mActive; // Whether we're waiting for input requests or actively
+ // working on them
+ size_t mRequestCount;
+
+ camera_metadata_t *mRequest;
+
+ Mutex mInternalsMutex; // Lock before accessing below members.
+ bool mWaitingForReadout;
+ bool mNextNeedsJpeg;
+ bool mNextIsCapture;
+ int32_t mNextFrameNumber;
+ int64_t mNextExposureTime;
+ int64_t mNextFrameDuration;
+ int32_t mNextSensitivity;
+ Buffers *mNextBuffers;
+ };
+
+ class ReadoutThread : public Thread, private JpegCompressor::JpegListener {
+ public:
+ ReadoutThread(EmulatedFakeCamera2 *parent);
+ ~ReadoutThread();
+
+ status_t readyToRun();
+
+ // Input
+ status_t waitUntilRunning();
+ bool waitForReady(nsecs_t timeout);
+ void setNextOperation(bool isCapture, camera_metadata_t *request,
+ Buffers *buffers);
+ bool isStreamInUse(uint32_t id);
+ int getInProgressCount();
+
+ private:
+ EmulatedFakeCamera2 *mParent;
+
+ bool mRunning;
+ bool threadLoop();
+
+ bool readyForNextCapture();
+ status_t collectStatisticsMetadata(camera_metadata_t *frame);
+
+ // Inputs
+ Mutex mInputMutex; // Protects mActive, mInFlightQueue, mRequestCount
+ Condition mInputSignal;
+ Condition mReadySignal;
+
+ bool mActive;
+
+ static const int kInFlightQueueSize = 4;
+ struct InFlightQueue {
+ bool isCapture;
+ camera_metadata_t *request;
+ Buffers *buffers;
+ } * mInFlightQueue;
+
+ size_t mInFlightHead;
+ size_t mInFlightTail;
+
+ size_t mRequestCount;
+
+ // Internals
+ Mutex mInternalsMutex;
+
+ bool mIsCapture;
+ camera_metadata_t *mRequest;
+ Buffers *mBuffers;
+
+ // Jpeg completion listeners
+ void onJpegDone(const StreamBuffer &jpegBuffer, bool success);
+ void onJpegInputDone(const StreamBuffer &inputBuffer);
+ nsecs_t mJpegTimestamp;
+ };
+
+ // 3A management thread (auto-exposure, focus, white balance)
+ class ControlThread : public Thread {
+ public:
+ ControlThread(EmulatedFakeCamera2 *parent);
+ ~ControlThread();
+
+ status_t readyToRun();
+
+ status_t waitUntilRunning();
+
+ // Interpret request's control parameters and override
+ // capture settings as needed
+ status_t processRequest(camera_metadata_t *request);
+
+ status_t triggerAction(uint32_t msgType, int32_t ext1, int32_t ext2);
+
+ private:
+ ControlThread(const ControlThread &t);
+ ControlThread &operator=(const ControlThread &t);
+
+ // Constants controlling fake 3A behavior
+ static const nsecs_t kControlCycleDelay;
+ static const nsecs_t kMinAfDuration;
+ static const nsecs_t kMaxAfDuration;
+ static const float kAfSuccessRate;
+ static const float kContinuousAfStartRate;
+
+ static const float kAeScanStartRate;
+ static const nsecs_t kMinAeDuration;
+ static const nsecs_t kMaxAeDuration;
+ static const nsecs_t kMinPrecaptureAeDuration;
+ static const nsecs_t kMaxPrecaptureAeDuration;
+
+ static const nsecs_t kNormalExposureTime;
+ static const nsecs_t kExposureJump;
+ static const nsecs_t kMinExposureTime;
+
+ EmulatedFakeCamera2 *mParent;
+
+ bool mRunning;
+ bool threadLoop();
+
+ Mutex mInputMutex; // Protects input methods
+ Condition mInputSignal;
+
+ // Trigger notifications
+ bool mStartAf;
+ bool mCancelAf;
+ bool mStartPrecapture;
+
+ // Latest state for 3A request fields
+ uint8_t mControlMode;
+
+ uint8_t mEffectMode;
+ uint8_t mSceneMode;
+
+ uint8_t mAfMode;
+ bool mAfModeChange;
+
+ uint8_t mAwbMode;
+ uint8_t mAeMode;
+
+ // Latest trigger IDs
+ int32_t mAfTriggerId;
+ int32_t mPrecaptureTriggerId;
+
+ // Current state for 3A algorithms
+ uint8_t mAfState;
+ uint8_t mAeState;
+ uint8_t mAwbState;
+ bool mAeLock;
+
+ // Current control parameters
+ nsecs_t mExposureTime;
+
+ // Private to threadLoop and its utility methods
+
+ nsecs_t mAfScanDuration;
+ nsecs_t mAeScanDuration;
+ bool mLockAfterPassiveScan;
+
+ // Utility methods for AF
+ int processAfTrigger(uint8_t afMode, uint8_t afState);
+ int maybeStartAfScan(uint8_t afMode, uint8_t afState);
+ int updateAfScan(uint8_t afMode, uint8_t afState, nsecs_t *maxSleep);
+ void updateAfState(uint8_t newState, int32_t triggerId);
+
+ // Utility methods for precapture trigger
+ int processPrecaptureTrigger(uint8_t aeMode, uint8_t aeState);
+ int maybeStartAeScan(uint8_t aeMode, bool aeLock, uint8_t aeState);
+ int updateAeScan(uint8_t aeMode, bool aeLock, uint8_t aeState,
+ nsecs_t *maxSleep);
+ void updateAeState(uint8_t newState, int32_t triggerId);
+ };
+
+ /****************************************************************************
+ * Static configuration information
+ ***************************************************************************/
+ private:
+ static const uint32_t kMaxRawStreamCount = 1;
+ static const uint32_t kMaxProcessedStreamCount = 3;
+ static const uint32_t kMaxJpegStreamCount = 1;
+ static const uint32_t kMaxReprocessStreamCount = 2;
+ static const uint32_t kMaxBufferCount = 4;
+ static const uint32_t kAvailableFormats[];
+ static const uint32_t kAvailableRawSizes[];
+ static const uint64_t kAvailableRawMinDurations[];
+ static const uint32_t kAvailableProcessedSizesBack[];
+ static const uint32_t kAvailableProcessedSizesFront[];
+ static const uint64_t kAvailableProcessedMinDurations[];
+ static const uint32_t kAvailableJpegSizesBack[];
+ static const uint32_t kAvailableJpegSizesFront[];
+ static const uint64_t kAvailableJpegMinDurations[];
+
+ /****************************************************************************
+ * Data members.
+ ***************************************************************************/
+
+ protected:
+ /* Facing back (true) or front (false) switch. */
+ bool mFacingBack;
+
+ private:
+ bool mIsConnected;
+
+ int32_t mSensorWidth, mSensorHeight;
+
+ /** Stream manipulation */
+ uint32_t mNextStreamId;
+ uint32_t mRawStreamCount;
+ uint32_t mProcessedStreamCount;
+ uint32_t mJpegStreamCount;
+
+ std::vector<uint32_t> mAvailableRawSizes;
+ std::vector<uint32_t> mAvailableProcessedSizes;
+ std::vector<uint32_t> mAvailableJpegSizes;
+
+ uint32_t mNextReprocessStreamId;
+ uint32_t mReprocessStreamCount;
+
+ KeyedVector<uint32_t, Stream> mStreams;
+ KeyedVector<uint32_t, ReprocessStream> mReprocessStreams;
+
+ /** Simulated hardware interfaces */
+ sp<Sensor> mSensor;
+ sp<JpegCompressor> mJpegCompressor;
+
+ /** Pipeline control threads */
+ sp<ConfigureThread> mConfigureThread;
+ sp<ReadoutThread> mReadoutThread;
+ sp<ControlThread> mControlThread;
+};
+
+}; /* namespace android */
+
+#endif /* HW_EMULATOR_CAMERA_EMULATED_FAKE_CAMERA2_H */
diff --git a/guest/hals/camera/EmulatedFakeCamera3.cpp b/guest/hals/camera/EmulatedFakeCamera3.cpp
new file mode 100644
index 000000000..f9d96283d
--- /dev/null
+++ b/guest/hals/camera/EmulatedFakeCamera3.cpp
@@ -0,0 +1,2661 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+/*
+ * Contains implementation of a class EmulatedFakeCamera3 that encapsulates
+ * functionality of an advanced fake camera.
+ */
+
+#include <cstdint>
+#include <inttypes.h>
+
+//#define LOG_NDEBUG 0
+//#define LOG_NNDEBUG 0
+#define LOG_TAG "EmulatedCamera_FakeCamera3"
+#include <cutils/properties.h>
+#include <utils/Log.h>
+
+#include <ui/Fence.h>
+#include "EmulatedCameraFactory.h"
+#include "EmulatedFakeCamera3.h"
+#include "GrallocModule.h"
+
+#include <cmath>
+#include "fake-pipeline2/JpegCompressor.h"
+#include "fake-pipeline2/Sensor.h"
+
+#include <vector>
+
+#if defined(LOG_NNDEBUG) && LOG_NNDEBUG == 0
+#define ALOGVV ALOGV
+#else
+#define ALOGVV(...) ((void)0)
+#endif
+
+namespace android {
+
+/**
+ * Constants for camera capabilities
+ */
+
+const int64_t USEC = 1000LL;
+const int64_t MSEC = USEC * 1000LL;
+// const int64_t SEC = MSEC * 1000LL;
+
+const int32_t EmulatedFakeCamera3::kAvailableFormats[] = {
+ HAL_PIXEL_FORMAT_RAW16, HAL_PIXEL_FORMAT_BLOB, HAL_PIXEL_FORMAT_RGBA_8888,
+ HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED,
+ // These are handled by YCbCr_420_888
+ // HAL_PIXEL_FORMAT_YV12,
+ // HAL_PIXEL_FORMAT_YCrCb_420_SP,
+ HAL_PIXEL_FORMAT_YCbCr_420_888, HAL_PIXEL_FORMAT_Y16};
+
+/**
+ * 3A constants
+ */
+
+// Default exposure and gain targets for different scenarios
+const nsecs_t EmulatedFakeCamera3::kNormalExposureTime = 10 * MSEC;
+const nsecs_t EmulatedFakeCamera3::kFacePriorityExposureTime = 30 * MSEC;
+const int EmulatedFakeCamera3::kNormalSensitivity = 100;
+const int EmulatedFakeCamera3::kFacePrioritySensitivity = 400;
+const float EmulatedFakeCamera3::kExposureTrackRate = 0.1;
+const int EmulatedFakeCamera3::kPrecaptureMinFrames = 10;
+const int EmulatedFakeCamera3::kStableAeMaxFrames = 100;
+const float EmulatedFakeCamera3::kExposureWanderMin = -2;
+const float EmulatedFakeCamera3::kExposureWanderMax = 1;
+
+/**
+ * Camera device lifecycle methods
+ */
+
+EmulatedFakeCamera3::EmulatedFakeCamera3(int cameraId, bool facingBack,
+ struct hw_module_t *module)
+ : EmulatedCamera3(cameraId, module), mFacingBack(facingBack) {
+ ALOGI("Constructing emulated fake camera 3: ID %d, facing %s", mCameraID,
+ facingBack ? "back" : "front");
+
+ for (size_t i = 0; i < CAMERA3_TEMPLATE_COUNT; i++) {
+ mDefaultTemplates[i] = NULL;
+ }
+}
+
+EmulatedFakeCamera3::~EmulatedFakeCamera3() {
+ for (size_t i = 0; i < CAMERA3_TEMPLATE_COUNT; i++) {
+ if (mDefaultTemplates[i] != NULL) {
+ free_camera_metadata(mDefaultTemplates[i]);
+ }
+ }
+}
+
+status_t EmulatedFakeCamera3::Initialize(const cvd::CameraDefinition &params) {
+ ALOGV("%s: E", __FUNCTION__);
+ status_t res;
+
+ if (mStatus != STATUS_ERROR) {
+ ALOGE("%s: Already initialized!", __FUNCTION__);
+ return INVALID_OPERATION;
+ }
+
+ res = getCameraCapabilities();
+ if (res != OK) {
+ ALOGE("%s: Unable to get camera capabilities: %s (%d)", __FUNCTION__,
+ strerror(-res), res);
+ return res;
+ }
+
+ res = constructStaticInfo(params);
+ if (res != OK) {
+ ALOGE("%s: Unable to allocate static info: %s (%d)", __FUNCTION__,
+ strerror(-res), res);
+ return res;
+ }
+
+ return EmulatedCamera3::Initialize(params);
+}
+
+status_t EmulatedFakeCamera3::connectCamera(hw_device_t **device) {
+ ALOGV("%s: E", __FUNCTION__);
+ Mutex::Autolock l(mLock);
+ status_t res;
+
+ if (mStatus != STATUS_CLOSED) {
+ ALOGE("%s: Can't connect in state %d", __FUNCTION__, mStatus);
+ return INVALID_OPERATION;
+ }
+
+ mSensor = new Sensor(mSensorWidth, mSensorHeight);
+ mSensor->setSensorListener(this);
+
+ res = mSensor->startUp();
+ if (res != NO_ERROR) return res;
+
+ mReadoutThread = new ReadoutThread(this);
+ mJpegCompressor = new JpegCompressor();
+
+ res = mReadoutThread->run("EmuCam3::readoutThread");
+ if (res != NO_ERROR) return res;
+
+ // Initialize fake 3A
+
+ mControlMode = ANDROID_CONTROL_MODE_AUTO;
+ mFacePriority = false;
+ mAeMode = ANDROID_CONTROL_AE_MODE_ON;
+ mAfMode = ANDROID_CONTROL_AF_MODE_AUTO;
+ mAwbMode = ANDROID_CONTROL_AWB_MODE_AUTO;
+ mAeState = ANDROID_CONTROL_AE_STATE_INACTIVE;
+ mAfState = ANDROID_CONTROL_AF_STATE_INACTIVE;
+ mAwbState = ANDROID_CONTROL_AWB_STATE_INACTIVE;
+ mAeCounter = 0;
+ mAeTargetExposureTime = kNormalExposureTime;
+ mAeCurrentExposureTime = kNormalExposureTime;
+ mAeCurrentSensitivity = kNormalSensitivity;
+
+ return EmulatedCamera3::connectCamera(device);
+}
+
+status_t EmulatedFakeCamera3::closeCamera() {
+ ALOGV("%s: E", __FUNCTION__);
+ status_t res;
+ {
+ Mutex::Autolock l(mLock);
+ if (mStatus == STATUS_CLOSED) return OK;
+
+ res = mSensor->shutDown();
+ if (res != NO_ERROR) {
+ ALOGE("%s: Unable to shut down sensor: %d", __FUNCTION__, res);
+ return res;
+ }
+ mSensor.clear();
+
+ mReadoutThread->requestExit();
+ }
+
+ mReadoutThread->join();
+
+ {
+ Mutex::Autolock l(mLock);
+ // Clear out private stream information
+ for (StreamIterator s = mStreams.begin(); s != mStreams.end(); s++) {
+ PrivateStreamInfo *privStream =
+ static_cast<PrivateStreamInfo *>((*s)->priv);
+ delete privStream;
+ (*s)->priv = NULL;
+ }
+ mStreams.clear();
+ mReadoutThread.clear();
+ }
+
+ return EmulatedCamera3::closeCamera();
+}
+
+status_t EmulatedFakeCamera3::getCameraInfo(struct camera_info *info) {
+ info->facing = mFacingBack ? CAMERA_FACING_BACK : CAMERA_FACING_FRONT;
+ info->orientation =
+ EmulatedCameraFactory::Instance().getFakeCameraOrientation();
+ info->resource_cost = 100;
+ info->conflicting_devices = NULL;
+ info->conflicting_devices_length = 0;
+ return EmulatedCamera3::getCameraInfo(info);
+}
+
+status_t EmulatedFakeCamera3::setTorchMode(bool enabled) {
+ if (!mFacingBack) {
+ ALOGE("%s: Front camera does not have flash unit", __FUNCTION__);
+ return INVALID_OPERATION;
+ }
+ EmulatedCameraFactory::Instance().onTorchModeStatusChanged(
+ mCameraID, enabled ? TORCH_MODE_STATUS_AVAILABLE_ON
+ : TORCH_MODE_STATUS_AVAILABLE_OFF);
+ return NO_ERROR;
+}
+
+/**
+ * Camera3 interface methods
+ */
+
+status_t EmulatedFakeCamera3::configureStreams(
+ camera3_stream_configuration *streamList) {
+ Mutex::Autolock l(mLock);
+ ALOGV("%s: %d streams", __FUNCTION__, streamList->num_streams);
+
+ if (mStatus != STATUS_OPEN && mStatus != STATUS_READY) {
+ ALOGE("%s: Cannot configure streams in state %d", __FUNCTION__, mStatus);
+ return NO_INIT;
+ }
+
+ /**
+ * Sanity-check input list.
+ */
+ if (streamList == NULL) {
+ ALOGE("%s: NULL stream configuration", __FUNCTION__);
+ return BAD_VALUE;
+ }
+
+ if (streamList->streams == NULL) {
+ ALOGE("%s: NULL stream list", __FUNCTION__);
+ return BAD_VALUE;
+ }
+
+ if (streamList->num_streams < 1) {
+ ALOGE("%s: Bad number of streams requested: %d", __FUNCTION__,
+ streamList->num_streams);
+ return BAD_VALUE;
+ }
+
+ camera3_stream_t *inputStream = NULL;
+ for (size_t i = 0; i < streamList->num_streams; i++) {
+ camera3_stream_t *newStream = streamList->streams[i];
+
+ if (newStream == NULL) {
+ ALOGE("%s: Stream index %zu was NULL", __FUNCTION__, i);
+ return BAD_VALUE;
+ }
+
+ ALOGV("%s: Stream %p (id %zu), type %d, usage 0x%x, format 0x%x",
+ __FUNCTION__, newStream, i, newStream->stream_type, newStream->usage,
+ newStream->format);
+
+ if (newStream->stream_type == CAMERA3_STREAM_INPUT ||
+ newStream->stream_type == CAMERA3_STREAM_BIDIRECTIONAL) {
+ if (inputStream != NULL) {
+ ALOGE("%s: Multiple input streams requested!", __FUNCTION__);
+ return BAD_VALUE;
+ }
+ inputStream = newStream;
+ }
+
+ bool validFormat = false;
+ for (size_t f = 0;
+ f < sizeof(kAvailableFormats) / sizeof(kAvailableFormats[0]); f++) {
+ if (newStream->format == kAvailableFormats[f]) {
+ validFormat = true;
+ break;
+ }
+ }
+ if (!validFormat) {
+ ALOGE("%s: Unsupported stream format 0x%x requested", __FUNCTION__,
+ newStream->format);
+ return BAD_VALUE;
+ }
+ }
+ mInputStream = inputStream;
+
+ /**
+ * Initially mark all existing streams as not alive
+ */
+ for (StreamIterator s = mStreams.begin(); s != mStreams.end(); ++s) {
+ PrivateStreamInfo *privStream =
+ static_cast<PrivateStreamInfo *>((*s)->priv);
+ privStream->alive = false;
+ }
+
+ /**
+ * Find new streams and mark still-alive ones
+ */
+ for (size_t i = 0; i < streamList->num_streams; i++) {
+ camera3_stream_t *newStream = streamList->streams[i];
+ if (newStream->priv == NULL) {
+ // New stream, construct info
+ PrivateStreamInfo *privStream = new PrivateStreamInfo();
+ privStream->alive = true;
+
+ newStream->max_buffers = kMaxBufferCount;
+ newStream->priv = privStream;
+ mStreams.push_back(newStream);
+ } else {
+ // Existing stream, mark as still alive.
+ PrivateStreamInfo *privStream =
+ static_cast<PrivateStreamInfo *>(newStream->priv);
+ privStream->alive = true;
+ }
+ // Always update usage and max buffers
+ newStream->max_buffers = kMaxBufferCount;
+ switch (newStream->stream_type) {
+ case CAMERA3_STREAM_OUTPUT:
+ newStream->usage = GRALLOC_USAGE_HW_CAMERA_WRITE;
+ break;
+ case CAMERA3_STREAM_INPUT:
+ newStream->usage = GRALLOC_USAGE_HW_CAMERA_READ;
+ break;
+ case CAMERA3_STREAM_BIDIRECTIONAL:
+ newStream->usage =
+ GRALLOC_USAGE_HW_CAMERA_READ | GRALLOC_USAGE_HW_CAMERA_WRITE;
+ break;
+ }
+ }
+
+ /**
+ * Reap the dead streams
+ */
+ for (StreamIterator s = mStreams.begin(); s != mStreams.end();) {
+ PrivateStreamInfo *privStream =
+ static_cast<PrivateStreamInfo *>((*s)->priv);
+ if (!privStream->alive) {
+ (*s)->priv = NULL;
+ delete privStream;
+ s = mStreams.erase(s);
+ } else {
+ ++s;
+ }
+ }
+
+ /**
+ * Can't reuse settings across configure call
+ */
+ mPrevSettings.clear();
+
+ return OK;
+}
+
+status_t EmulatedFakeCamera3::registerStreamBuffers(
+ const camera3_stream_buffer_set * /*bufferSet*/) {
+ ALOGV("%s: E", __FUNCTION__);
+ Mutex::Autolock l(mLock);
+
+ // Should not be called in HAL versions >= 3.2
+
+ ALOGE("%s: Should not be invoked on new HALs!", __FUNCTION__);
+ return NO_INIT;
+}
+
+const camera_metadata_t *EmulatedFakeCamera3::constructDefaultRequestSettings(
+ int type) {
+ ALOGV("%s: E", __FUNCTION__);
+ Mutex::Autolock l(mLock);
+
+ if (type < 0 || type >= CAMERA3_TEMPLATE_COUNT) {
+ ALOGE("%s: Unknown request settings template: %d", __FUNCTION__, type);
+ return NULL;
+ }
+
+ if (!hasCapability(BACKWARD_COMPATIBLE) && type != CAMERA3_TEMPLATE_PREVIEW) {
+ ALOGE("%s: Template %d not supported w/o BACKWARD_COMPATIBLE capability",
+ __FUNCTION__, type);
+ return NULL;
+ }
+
+ /**
+ * Cache is not just an optimization - pointer returned has to live at
+ * least as long as the camera device instance does.
+ */
+ if (mDefaultTemplates[type] != NULL) {
+ return mDefaultTemplates[type];
+ }
+
+ CameraMetadata settings;
+
+ /** android.request */
+
+ static const uint8_t metadataMode = ANDROID_REQUEST_METADATA_MODE_FULL;
+ settings.update(ANDROID_REQUEST_METADATA_MODE, &metadataMode, 1);
+
+ static const int32_t id = 0;
+ settings.update(ANDROID_REQUEST_ID, &id, 1);
+
+ static const int32_t frameCount = 0;
+ settings.update(ANDROID_REQUEST_FRAME_COUNT, &frameCount, 1);
+
+ /** android.lens */
+
+ static const float focalLength = 5.0f;
+ settings.update(ANDROID_LENS_FOCAL_LENGTH, &focalLength, 1);
+
+ if (hasCapability(BACKWARD_COMPATIBLE)) {
+ static const float focusDistance = 0;
+ settings.update(ANDROID_LENS_FOCUS_DISTANCE, &focusDistance, 1);
+
+ static const float aperture = 2.8f;
+ settings.update(ANDROID_LENS_APERTURE, &aperture, 1);
+
+ static const float filterDensity = 0;
+ settings.update(ANDROID_LENS_FILTER_DENSITY, &filterDensity, 1);
+
+ static const uint8_t opticalStabilizationMode =
+ ANDROID_LENS_OPTICAL_STABILIZATION_MODE_OFF;
+ settings.update(ANDROID_LENS_OPTICAL_STABILIZATION_MODE,
+ &opticalStabilizationMode, 1);
+
+ // FOCUS_RANGE set only in frame
+ }
+
+ /** android.sensor */
+
+ if (hasCapability(MANUAL_SENSOR)) {
+ static const int64_t exposureTime = 10 * MSEC;
+ settings.update(ANDROID_SENSOR_EXPOSURE_TIME, &exposureTime, 1);
+
+ static const int64_t frameDuration = 33333333L; // 1/30 s
+ settings.update(ANDROID_SENSOR_FRAME_DURATION, &frameDuration, 1);
+
+ static const int32_t sensitivity = 100;
+ settings.update(ANDROID_SENSOR_SENSITIVITY, &sensitivity, 1);
+ }
+
+ // TIMESTAMP set only in frame
+
+ /** android.flash */
+
+ if (hasCapability(BACKWARD_COMPATIBLE)) {
+ static const uint8_t flashMode = ANDROID_FLASH_MODE_OFF;
+ settings.update(ANDROID_FLASH_MODE, &flashMode, 1);
+
+ static const uint8_t flashPower = 10;
+ settings.update(ANDROID_FLASH_FIRING_POWER, &flashPower, 1);
+
+ static const int64_t firingTime = 0;
+ settings.update(ANDROID_FLASH_FIRING_TIME, &firingTime, 1);
+ }
+
+ /** Processing block modes */
+ if (hasCapability(MANUAL_POST_PROCESSING)) {
+ uint8_t hotPixelMode = 0;
+ uint8_t demosaicMode = 0;
+ uint8_t noiseMode = 0;
+ uint8_t shadingMode = 0;
+ uint8_t colorMode = 0;
+ uint8_t tonemapMode = 0;
+ uint8_t edgeMode = 0;
+ switch (type) {
+ case CAMERA3_TEMPLATE_STILL_CAPTURE:
+ // fall-through
+ case CAMERA3_TEMPLATE_VIDEO_SNAPSHOT:
+ // fall-through
+ case CAMERA3_TEMPLATE_ZERO_SHUTTER_LAG:
+ hotPixelMode = ANDROID_HOT_PIXEL_MODE_HIGH_QUALITY;
+ demosaicMode = ANDROID_DEMOSAIC_MODE_HIGH_QUALITY;
+ noiseMode = ANDROID_NOISE_REDUCTION_MODE_HIGH_QUALITY;
+ shadingMode = ANDROID_SHADING_MODE_HIGH_QUALITY;
+ colorMode = ANDROID_COLOR_CORRECTION_MODE_HIGH_QUALITY;
+ tonemapMode = ANDROID_TONEMAP_MODE_HIGH_QUALITY;
+ edgeMode = ANDROID_EDGE_MODE_HIGH_QUALITY;
+ break;
+ case CAMERA3_TEMPLATE_PREVIEW:
+ // fall-through
+ case CAMERA3_TEMPLATE_VIDEO_RECORD:
+ // fall-through
+ default:
+ hotPixelMode = ANDROID_HOT_PIXEL_MODE_FAST;
+ demosaicMode = ANDROID_DEMOSAIC_MODE_FAST;
+ noiseMode = ANDROID_NOISE_REDUCTION_MODE_FAST;
+ shadingMode = ANDROID_SHADING_MODE_FAST;
+ colorMode = ANDROID_COLOR_CORRECTION_MODE_FAST;
+ tonemapMode = ANDROID_TONEMAP_MODE_FAST;
+ edgeMode = ANDROID_EDGE_MODE_FAST;
+ break;
+ }
+ settings.update(ANDROID_HOT_PIXEL_MODE, &hotPixelMode, 1);
+ settings.update(ANDROID_DEMOSAIC_MODE, &demosaicMode, 1);
+ settings.update(ANDROID_NOISE_REDUCTION_MODE, &noiseMode, 1);
+ settings.update(ANDROID_SHADING_MODE, &shadingMode, 1);
+ settings.update(ANDROID_COLOR_CORRECTION_MODE, &colorMode, 1);
+ settings.update(ANDROID_TONEMAP_MODE, &tonemapMode, 1);
+ settings.update(ANDROID_EDGE_MODE, &edgeMode, 1);
+ }
+
+ /** android.colorCorrection */
+
+ if (hasCapability(MANUAL_POST_PROCESSING)) {
+ static const camera_metadata_rational colorTransform[9] = {
+ {1, 1}, {0, 1}, {0, 1}, {0, 1}, {1, 1}, {0, 1}, {0, 1}, {0, 1}, {1, 1}};
+ settings.update(ANDROID_COLOR_CORRECTION_TRANSFORM, colorTransform, 9);
+
+ static const float colorGains[4] = {1.0f, 1.0f, 1.0f, 1.0f};
+ settings.update(ANDROID_COLOR_CORRECTION_GAINS, colorGains, 4);
+ }
+
+ /** android.tonemap */
+
+ if (hasCapability(MANUAL_POST_PROCESSING)) {
+ static const float tonemapCurve[4] = {0.f, 0.f, 1.f, 1.f};
+ settings.update(ANDROID_TONEMAP_CURVE_RED, tonemapCurve, 4);
+ settings.update(ANDROID_TONEMAP_CURVE_GREEN, tonemapCurve, 4);
+ settings.update(ANDROID_TONEMAP_CURVE_BLUE, tonemapCurve, 4);
+ }
+
+ /** android.scaler */
+ if (hasCapability(BACKWARD_COMPATIBLE)) {
+ static const int32_t cropRegion[4] = {0, 0, mSensorWidth, mSensorHeight};
+ settings.update(ANDROID_SCALER_CROP_REGION, cropRegion, 4);
+ }
+
+ /** android.jpeg */
+ if (hasCapability(BACKWARD_COMPATIBLE)) {
+ static const uint8_t jpegQuality = 80;
+ settings.update(ANDROID_JPEG_QUALITY, &jpegQuality, 1);
+
+ static const int32_t thumbnailSize[2] = {640, 480};
+ settings.update(ANDROID_JPEG_THUMBNAIL_SIZE, thumbnailSize, 2);
+
+ static const uint8_t thumbnailQuality = 80;
+ settings.update(ANDROID_JPEG_THUMBNAIL_QUALITY, &thumbnailQuality, 1);
+
+ static const double gpsCoordinates[2] = {0, 0};
+ settings.update(ANDROID_JPEG_GPS_COORDINATES, gpsCoordinates, 2);
+
+ static const uint8_t gpsProcessingMethod[32] = "None";
+ settings.update(ANDROID_JPEG_GPS_PROCESSING_METHOD, gpsProcessingMethod,
+ 32);
+
+ static const int64_t gpsTimestamp = 0;
+ settings.update(ANDROID_JPEG_GPS_TIMESTAMP, &gpsTimestamp, 1);
+
+ static const int32_t jpegOrientation = 0;
+ settings.update(ANDROID_JPEG_ORIENTATION, &jpegOrientation, 1);
+ }
+
+ /** android.stats */
+
+ if (hasCapability(BACKWARD_COMPATIBLE)) {
+ static const uint8_t faceDetectMode =
+ ANDROID_STATISTICS_FACE_DETECT_MODE_OFF;
+ settings.update(ANDROID_STATISTICS_FACE_DETECT_MODE, &faceDetectMode, 1);
+
+ static const uint8_t hotPixelMapMode =
+ ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE_OFF;
+ settings.update(ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE, &hotPixelMapMode, 1);
+ }
+
+ // faceRectangles, faceScores, faceLandmarks, faceIds, histogram,
+ // sharpnessMap only in frames
+
+ /** android.control */
+
+ uint8_t controlIntent = 0;
+ switch (type) {
+ case CAMERA3_TEMPLATE_PREVIEW:
+ controlIntent = ANDROID_CONTROL_CAPTURE_INTENT_PREVIEW;
+ break;
+ case CAMERA3_TEMPLATE_STILL_CAPTURE:
+ controlIntent = ANDROID_CONTROL_CAPTURE_INTENT_STILL_CAPTURE;
+ break;
+ case CAMERA3_TEMPLATE_VIDEO_RECORD:
+ controlIntent = ANDROID_CONTROL_CAPTURE_INTENT_VIDEO_RECORD;
+ break;
+ case CAMERA3_TEMPLATE_VIDEO_SNAPSHOT:
+ controlIntent = ANDROID_CONTROL_CAPTURE_INTENT_VIDEO_SNAPSHOT;
+ break;
+ case CAMERA3_TEMPLATE_ZERO_SHUTTER_LAG:
+ controlIntent = ANDROID_CONTROL_CAPTURE_INTENT_ZERO_SHUTTER_LAG;
+ break;
+ case CAMERA3_TEMPLATE_MANUAL:
+ controlIntent = ANDROID_CONTROL_CAPTURE_INTENT_MANUAL;
+ break;
+ default:
+ controlIntent = ANDROID_CONTROL_CAPTURE_INTENT_CUSTOM;
+ break;
+ }
+ settings.update(ANDROID_CONTROL_CAPTURE_INTENT, &controlIntent, 1);
+
+ const uint8_t controlMode = (type == CAMERA3_TEMPLATE_MANUAL)
+ ? ANDROID_CONTROL_MODE_OFF
+ : ANDROID_CONTROL_MODE_AUTO;
+ settings.update(ANDROID_CONTROL_MODE, &controlMode, 1);
+
+ int32_t aeTargetFpsRange[2] = {5, 30};
+ if (type == CAMERA3_TEMPLATE_VIDEO_RECORD ||
+ type == CAMERA3_TEMPLATE_VIDEO_SNAPSHOT) {
+ aeTargetFpsRange[0] = 30;
+ }
+ settings.update(ANDROID_CONTROL_AE_TARGET_FPS_RANGE, aeTargetFpsRange, 2);
+
+ if (hasCapability(BACKWARD_COMPATIBLE)) {
+ static const uint8_t effectMode = ANDROID_CONTROL_EFFECT_MODE_OFF;
+ settings.update(ANDROID_CONTROL_EFFECT_MODE, &effectMode, 1);
+
+ static const uint8_t sceneMode = ANDROID_CONTROL_SCENE_MODE_FACE_PRIORITY;
+ settings.update(ANDROID_CONTROL_SCENE_MODE, &sceneMode, 1);
+
+ const uint8_t aeMode = (type == CAMERA3_TEMPLATE_MANUAL)
+ ? ANDROID_CONTROL_AE_MODE_OFF
+ : ANDROID_CONTROL_AE_MODE_ON;
+ settings.update(ANDROID_CONTROL_AE_MODE, &aeMode, 1);
+
+ static const uint8_t aeLock = ANDROID_CONTROL_AE_LOCK_OFF;
+ settings.update(ANDROID_CONTROL_AE_LOCK, &aeLock, 1);
+
+ static const int32_t controlRegions[5] = {0, 0, 0, 0, 0};
+ settings.update(ANDROID_CONTROL_AE_REGIONS, controlRegions, 5);
+
+ static const int32_t aeExpCompensation = 0;
+ settings.update(ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION,
+ &aeExpCompensation, 1);
+
+ static const uint8_t aeAntibandingMode =
+ ANDROID_CONTROL_AE_ANTIBANDING_MODE_AUTO;
+ settings.update(ANDROID_CONTROL_AE_ANTIBANDING_MODE, &aeAntibandingMode, 1);
+
+ static const uint8_t aePrecaptureTrigger =
+ ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_IDLE;
+ settings.update(ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER, &aePrecaptureTrigger,
+ 1);
+
+ const uint8_t awbMode = (type == CAMERA3_TEMPLATE_MANUAL)
+ ? ANDROID_CONTROL_AWB_MODE_OFF
+ : ANDROID_CONTROL_AWB_MODE_AUTO;
+ settings.update(ANDROID_CONTROL_AWB_MODE, &awbMode, 1);
+
+ static const uint8_t awbLock = ANDROID_CONTROL_AWB_LOCK_OFF;
+ settings.update(ANDROID_CONTROL_AWB_LOCK, &awbLock, 1);
+
+ uint8_t afMode = 0;
+
+ if (mFacingBack) {
+ switch (type) {
+ case CAMERA3_TEMPLATE_PREVIEW:
+ afMode = ANDROID_CONTROL_AF_MODE_CONTINUOUS_PICTURE;
+ break;
+ case CAMERA3_TEMPLATE_STILL_CAPTURE:
+ afMode = ANDROID_CONTROL_AF_MODE_CONTINUOUS_PICTURE;
+ break;
+ case CAMERA3_TEMPLATE_VIDEO_RECORD:
+ afMode = ANDROID_CONTROL_AF_MODE_CONTINUOUS_VIDEO;
+ break;
+ case CAMERA3_TEMPLATE_VIDEO_SNAPSHOT:
+ afMode = ANDROID_CONTROL_AF_MODE_CONTINUOUS_VIDEO;
+ break;
+ case CAMERA3_TEMPLATE_ZERO_SHUTTER_LAG:
+ afMode = ANDROID_CONTROL_AF_MODE_CONTINUOUS_PICTURE;
+ break;
+ case CAMERA3_TEMPLATE_MANUAL:
+ afMode = ANDROID_CONTROL_AF_MODE_OFF;
+ break;
+ default:
+ 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);
+
+ static const uint8_t afTrigger = ANDROID_CONTROL_AF_TRIGGER_IDLE;
+ settings.update(ANDROID_CONTROL_AF_TRIGGER, &afTrigger, 1);
+
+ static const uint8_t vstabMode =
+ ANDROID_CONTROL_VIDEO_STABILIZATION_MODE_OFF;
+ settings.update(ANDROID_CONTROL_VIDEO_STABILIZATION_MODE, &vstabMode, 1);
+
+ static const uint8_t blackLevelLock = ANDROID_BLACK_LEVEL_LOCK_OFF;
+ settings.update(ANDROID_BLACK_LEVEL_LOCK, &blackLevelLock, 1);
+
+ static const uint8_t lensShadingMapMode =
+ ANDROID_STATISTICS_LENS_SHADING_MAP_MODE_OFF;
+ settings.update(ANDROID_STATISTICS_LENS_SHADING_MAP_MODE,
+ &lensShadingMapMode, 1);
+
+ static const uint8_t aberrationMode =
+ ANDROID_COLOR_CORRECTION_ABERRATION_MODE_FAST;
+ settings.update(ANDROID_COLOR_CORRECTION_ABERRATION_MODE, &aberrationMode,
+ 1);
+
+ static const int32_t testPatternMode = ANDROID_SENSOR_TEST_PATTERN_MODE_OFF;
+ settings.update(ANDROID_SENSOR_TEST_PATTERN_MODE, &testPatternMode, 1);
+ }
+
+ mDefaultTemplates[type] = settings.release();
+
+ return mDefaultTemplates[type];
+}
+
+status_t EmulatedFakeCamera3::processCaptureRequest(
+ camera3_capture_request *request) {
+ Mutex::Autolock l(mLock);
+ status_t res;
+
+ /** Validation */
+
+ if (mStatus < STATUS_READY) {
+ ALOGE("%s: Can't submit capture requests in state %d", __FUNCTION__,
+ mStatus);
+ return INVALID_OPERATION;
+ }
+
+ if (request == NULL) {
+ ALOGE("%s: NULL request!", __FUNCTION__);
+ return BAD_VALUE;
+ }
+
+ uint32_t frameNumber = request->frame_number;
+
+ if (request->settings == NULL && mPrevSettings.isEmpty()) {
+ ALOGE(
+ "%s: Request %d: NULL settings for first request after"
+ "configureStreams()",
+ __FUNCTION__, frameNumber);
+ return BAD_VALUE;
+ }
+
+ if (request->input_buffer != NULL &&
+ request->input_buffer->stream != mInputStream) {
+ ALOGE("%s: Request %d: Input buffer not from input stream!", __FUNCTION__,
+ frameNumber);
+ ALOGV("%s: Bad stream %p, expected: %p", __FUNCTION__,
+ request->input_buffer->stream, mInputStream);
+ ALOGV("%s: Bad stream type %d, expected stream type %d", __FUNCTION__,
+ request->input_buffer->stream->stream_type,
+ mInputStream ? mInputStream->stream_type : -1);
+
+ return BAD_VALUE;
+ }
+
+ if (request->num_output_buffers < 1 || request->output_buffers == NULL) {
+ ALOGE("%s: Request %d: No output buffers provided!", __FUNCTION__,
+ frameNumber);
+ return BAD_VALUE;
+ }
+
+ // Validate all buffers, starting with input buffer if it's given
+
+ ssize_t idx;
+ const camera3_stream_buffer_t *b;
+ if (request->input_buffer != NULL) {
+ idx = -1;
+ b = request->input_buffer;
+ } else {
+ idx = 0;
+ b = request->output_buffers;
+ }
+ do {
+ PrivateStreamInfo *priv = static_cast<PrivateStreamInfo *>(b->stream->priv);
+ if (priv == NULL) {
+ ALOGE("%s: Request %d: Buffer %zu: Unconfigured stream!", __FUNCTION__,
+ frameNumber, idx);
+ return BAD_VALUE;
+ }
+ if (!priv->alive) {
+ ALOGE("%s: Request %d: Buffer %zu: Dead stream!", __FUNCTION__,
+ frameNumber, idx);
+ return BAD_VALUE;
+ }
+ if (b->status != CAMERA3_BUFFER_STATUS_OK) {
+ ALOGE("%s: Request %d: Buffer %zu: Status not OK!", __FUNCTION__,
+ frameNumber, idx);
+ return BAD_VALUE;
+ }
+ if (b->release_fence != -1) {
+ ALOGE("%s: Request %d: Buffer %zu: Has a release fence!", __FUNCTION__,
+ frameNumber, idx);
+ return BAD_VALUE;
+ }
+ if (b->buffer == NULL) {
+ ALOGE("%s: Request %d: Buffer %zu: NULL buffer handle!", __FUNCTION__,
+ frameNumber, idx);
+ return BAD_VALUE;
+ }
+ idx++;
+ b = &(request->output_buffers[idx]);
+ } while (idx < (ssize_t)request->num_output_buffers);
+
+ // TODO: Validate settings parameters
+
+ /**
+ * Start processing this request
+ */
+
+ mStatus = STATUS_ACTIVE;
+
+ CameraMetadata settings;
+
+ if (request->settings == NULL) {
+ settings.acquire(mPrevSettings);
+ } else {
+ settings = request->settings;
+ }
+
+ res = process3A(settings);
+ if (res != OK) {
+ return res;
+ }
+
+ // TODO: Handle reprocessing
+
+ /**
+ * Get ready for sensor config
+ */
+
+ nsecs_t exposureTime;
+ nsecs_t frameDuration;
+ uint32_t sensitivity;
+ bool needJpeg = false;
+ camera_metadata_entry_t entry;
+
+ entry = settings.find(ANDROID_SENSOR_EXPOSURE_TIME);
+ exposureTime =
+ (entry.count > 0) ? entry.data.i64[0] : Sensor::kExposureTimeRange[0];
+ entry = settings.find(ANDROID_SENSOR_FRAME_DURATION);
+ frameDuration =
+ (entry.count > 0) ? entry.data.i64[0] : Sensor::kFrameDurationRange[0];
+ entry = settings.find(ANDROID_SENSOR_SENSITIVITY);
+ sensitivity =
+ (entry.count > 0) ? entry.data.i32[0] : Sensor::kSensitivityRange[0];
+
+ if (exposureTime > frameDuration) {
+ frameDuration = exposureTime + Sensor::kMinVerticalBlank;
+ settings.update(ANDROID_SENSOR_FRAME_DURATION, &frameDuration, 1);
+ }
+
+ Buffers *sensorBuffers = new Buffers();
+ HalBufferVector *buffers = new HalBufferVector();
+
+ sensorBuffers->setCapacity(request->num_output_buffers);
+ buffers->setCapacity(request->num_output_buffers);
+
+ // Process all the buffers we got for output, constructing internal buffer
+ // structures for them, and lock them for writing.
+ for (size_t i = 0; i < request->num_output_buffers; i++) {
+ const camera3_stream_buffer &srcBuf = request->output_buffers[i];
+ StreamBuffer destBuf;
+ destBuf.streamId = kGenericStreamId;
+ destBuf.width = srcBuf.stream->width;
+ destBuf.height = srcBuf.stream->height;
+ // For GCE, IMPLEMENTATION_DEFINED is always RGBx_8888
+ destBuf.format =
+ (srcBuf.stream->format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED)
+ ? HAL_PIXEL_FORMAT_RGBA_8888
+ : srcBuf.stream->format;
+ destBuf.stride = srcBuf.stream->width;
+ destBuf.dataSpace = srcBuf.stream->data_space;
+ destBuf.buffer = srcBuf.buffer;
+
+ if (destBuf.format == HAL_PIXEL_FORMAT_BLOB) {
+ needJpeg = true;
+ }
+
+ // Wait on fence
+ sp<Fence> bufferAcquireFence = new Fence(srcBuf.acquire_fence);
+ res = bufferAcquireFence->wait(kFenceTimeoutMs);
+ if (res == TIMED_OUT) {
+ ALOGE("%s: Request %d: Buffer %zu: Fence timed out after %d ms",
+ __FUNCTION__, frameNumber, i, kFenceTimeoutMs);
+ }
+ if (res == OK) {
+ // Lock buffer for writing
+ if (srcBuf.stream->format == HAL_PIXEL_FORMAT_YCbCr_420_888) {
+ if (destBuf.format == HAL_PIXEL_FORMAT_YCbCr_420_888) {
+ android_ycbcr ycbcr = android_ycbcr();
+ res = GrallocModule::getInstance().lock_ycbcr(
+ *(destBuf.buffer), GRALLOC_USAGE_HW_CAMERA_WRITE, 0, 0,
+ destBuf.width, destBuf.height, &ycbcr);
+ // This is only valid because we know that emulator's
+ // YCbCr_420_888 is really contiguous NV21 under the hood
+ destBuf.img = static_cast<uint8_t *>(ycbcr.y);
+ } else {
+ ALOGE("Unexpected private format for flexible YUV: 0x%x",
+ destBuf.format);
+ res = INVALID_OPERATION;
+ }
+ } else {
+ res = GrallocModule::getInstance().lock(
+ *(destBuf.buffer), GRALLOC_USAGE_HW_CAMERA_WRITE, 0, 0,
+ destBuf.width, destBuf.height, (void **)&(destBuf.img));
+ }
+ if (res != OK) {
+ ALOGE("%s: Request %d: Buffer %zu: Unable to lock buffer", __FUNCTION__,
+ frameNumber, i);
+ }
+ }
+
+ if (res != OK) {
+ // Either waiting or locking failed. Unlock locked buffers and bail
+ // out.
+ for (size_t j = 0; j < i; j++) {
+ GrallocModule::getInstance().unlock(
+ *(request->output_buffers[i].buffer));
+ }
+ delete sensorBuffers;
+ delete buffers;
+ return NO_INIT;
+ }
+
+ sensorBuffers->push_back(destBuf);
+ buffers->push_back(srcBuf);
+ }
+
+ /**
+ * Wait for JPEG compressor to not be busy, if needed
+ */
+ if (needJpeg) {
+ bool ready = mJpegCompressor->waitForDone(kJpegTimeoutNs);
+ if (!ready) {
+ ALOGE("%s: Timeout waiting for JPEG compression to complete!",
+ __FUNCTION__);
+ return NO_INIT;
+ }
+ res = mJpegCompressor->reserve();
+ if (res != OK) {
+ ALOGE("%s: Error managing JPEG compressor resources, can't reserve it!",
+ __FUNCTION__);
+ return NO_INIT;
+ }
+ }
+
+ /**
+ * Wait until the in-flight queue has room
+ */
+ res = mReadoutThread->waitForReadout();
+ if (res != OK) {
+ ALOGE("%s: Timeout waiting for previous requests to complete!",
+ __FUNCTION__);
+ return NO_INIT;
+ }
+
+ /**
+ * Wait until sensor's ready. This waits for lengthy amounts of time with
+ * mLock held, but the interface spec is that no other calls may by done to
+ * the HAL by the framework while process_capture_request is happening.
+ */
+ int syncTimeoutCount = 0;
+ while (!mSensor->waitForVSync(kSyncWaitTimeout)) {
+ if (mStatus == STATUS_ERROR) {
+ return NO_INIT;
+ }
+ if (syncTimeoutCount == kMaxSyncTimeoutCount) {
+ ALOGE("%s: Request %d: Sensor sync timed out after %" PRId64 " ms",
+ __FUNCTION__, frameNumber,
+ kSyncWaitTimeout * kMaxSyncTimeoutCount / 1000000);
+ return NO_INIT;
+ }
+ syncTimeoutCount++;
+ }
+
+ /**
+ * Configure sensor and queue up the request to the readout thread
+ */
+ mSensor->setExposureTime(exposureTime);
+ mSensor->setFrameDuration(frameDuration);
+ mSensor->setSensitivity(sensitivity);
+ mSensor->setDestinationBuffers(sensorBuffers);
+ mSensor->setFrameNumber(request->frame_number);
+
+ ReadoutThread::Request r;
+ r.frameNumber = request->frame_number;
+ r.settings = settings;
+ r.sensorBuffers = sensorBuffers;
+ r.buffers = buffers;
+
+ mReadoutThread->queueCaptureRequest(r);
+ ALOGVV("%s: Queued frame %d", __FUNCTION__, request->frame_number);
+
+ // Cache the settings for next time
+ mPrevSettings.acquire(settings);
+
+ return OK;
+}
+
+status_t EmulatedFakeCamera3::flush() {
+ ALOGW("%s: Not implemented; ignored", __FUNCTION__);
+ return OK;
+}
+
+/** Debug methods */
+
+void EmulatedFakeCamera3::dump(int /*fd*/) {}
+
+/**
+ * Private methods
+ */
+
+status_t EmulatedFakeCamera3::getCameraCapabilities() {
+ const char *key =
+ mFacingBack ? "qemu.sf.back_camera_caps" : "qemu.sf.front_camera_caps";
+
+ /* Defined by 'qemu.sf.*_camera_caps' boot property: if the
+ * property doesn't exist, it is assumed to list FULL. */
+ char prop[PROPERTY_VALUE_MAX];
+ if (property_get(key, prop, NULL) > 0) {
+ char *saveptr = nullptr;
+ char *cap = strtok_r(prop, " ,", &saveptr);
+ while (cap != NULL) {
+ for (int i = 0; i < NUM_CAPABILITIES; i++) {
+ if (!strcasecmp(cap, sAvailableCapabilitiesStrings[i])) {
+ mCapabilities.add(static_cast<AvailableCapabilities>(i));
+ break;
+ }
+ }
+ cap = strtok_r(NULL, " ,", &saveptr);
+ }
+ if (mCapabilities.size() == 0) {
+ ALOGE("qemu.sf.back_camera_caps had no valid capabilities: %s", prop);
+ }
+ }
+ // Default to FULL_LEVEL plus RAW if nothing is defined
+ if (mCapabilities.size() == 0) {
+ mCapabilities.add(FULL_LEVEL);
+ mCapabilities.add(RAW);
+ }
+
+ // Add level-based caps
+ if (hasCapability(FULL_LEVEL)) {
+ mCapabilities.add(BURST_CAPTURE);
+ mCapabilities.add(READ_SENSOR_SETTINGS);
+ mCapabilities.add(MANUAL_SENSOR);
+ mCapabilities.add(MANUAL_POST_PROCESSING);
+ };
+
+ // Backwards-compatible is required for most other caps
+ // Not required for DEPTH_OUTPUT, though.
+ if (hasCapability(BURST_CAPTURE) || hasCapability(READ_SENSOR_SETTINGS) ||
+ hasCapability(RAW) || hasCapability(MANUAL_SENSOR) ||
+ hasCapability(MANUAL_POST_PROCESSING) ||
+ hasCapability(PRIVATE_REPROCESSING) || hasCapability(YUV_REPROCESSING) ||
+ hasCapability(CONSTRAINED_HIGH_SPEED_VIDEO)) {
+ mCapabilities.add(BACKWARD_COMPATIBLE);
+ }
+
+ ALOGI("Camera %d capabilities:", mCameraID);
+ for (size_t i = 0; i < mCapabilities.size(); i++) {
+ ALOGI(" %s", sAvailableCapabilitiesStrings[mCapabilities[i]]);
+ }
+
+ return OK;
+}
+
+bool EmulatedFakeCamera3::hasCapability(AvailableCapabilities cap) {
+ ssize_t idx = mCapabilities.indexOf(cap);
+ return idx >= 0;
+}
+
+status_t EmulatedFakeCamera3::constructStaticInfo(
+ const cvd::CameraDefinition &params) {
+ CameraMetadata info;
+ Vector<int32_t> availableCharacteristicsKeys;
+ status_t res;
+
+ int32_t width = 0, height = 0;
+
+ /* TODO(ender): this currently supports only maximum resolution. */
+ for (size_t index = 0; index < params.resolutions.size(); ++index) {
+ if (width <= params.resolutions[index].width &&
+ height <= params.resolutions[index].height) {
+ width = params.resolutions[index].width;
+ height = params.resolutions[index].height;
+ }
+ }
+
+ if (width < 640 || height < 480) {
+ width = 640;
+ height = 480;
+ }
+
+ mSensorWidth = width;
+ mSensorHeight = height;
+
+#define ADD_STATIC_ENTRY(name, varptr, count) \
+ availableCharacteristicsKeys.add(name); \
+ res = info.update(name, varptr, count); \
+ if (res != OK) return res
+
+ // android.sensor
+
+ if (hasCapability(MANUAL_SENSOR)) {
+ ADD_STATIC_ENTRY(ANDROID_SENSOR_INFO_EXPOSURE_TIME_RANGE,
+ Sensor::kExposureTimeRange, 2);
+
+ ADD_STATIC_ENTRY(ANDROID_SENSOR_INFO_MAX_FRAME_DURATION,
+ &Sensor::kFrameDurationRange[1], 1);
+
+ ADD_STATIC_ENTRY(ANDROID_SENSOR_INFO_SENSITIVITY_RANGE,
+ Sensor::kSensitivityRange,
+ sizeof(Sensor::kSensitivityRange) / sizeof(int32_t));
+
+ ADD_STATIC_ENTRY(ANDROID_SENSOR_MAX_ANALOG_SENSITIVITY,
+ &Sensor::kSensitivityRange[1], 1);
+ }
+
+ static const float sensorPhysicalSize[2] = {3.20f, 2.40f}; // mm
+ ADD_STATIC_ENTRY(ANDROID_SENSOR_INFO_PHYSICAL_SIZE, sensorPhysicalSize, 2);
+
+ const int32_t pixelArray[] = {mSensorWidth, mSensorHeight};
+ ADD_STATIC_ENTRY(ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE, pixelArray, 2);
+ const int32_t activeArray[] = {0, 0, mSensorWidth, mSensorHeight};
+ ADD_STATIC_ENTRY(ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE, activeArray, 4);
+
+ static const int32_t orientation = 90; // Aligned with 'long edge'
+ ADD_STATIC_ENTRY(ANDROID_SENSOR_ORIENTATION, &orientation, 1);
+
+ static const uint8_t timestampSource =
+ ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE_REALTIME;
+ ADD_STATIC_ENTRY(ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE, &timestampSource, 1);
+
+ if (hasCapability(RAW)) {
+ ADD_STATIC_ENTRY(ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT,
+ &Sensor::kColorFilterArrangement, 1);
+
+ ADD_STATIC_ENTRY(ANDROID_SENSOR_INFO_WHITE_LEVEL,
+ (int32_t *)&Sensor::kMaxRawValue, 1);
+
+ static const int32_t blackLevelPattern[4] = {
+ (int32_t)Sensor::kBlackLevel, (int32_t)Sensor::kBlackLevel,
+ (int32_t)Sensor::kBlackLevel, (int32_t)Sensor::kBlackLevel};
+ ADD_STATIC_ENTRY(ANDROID_SENSOR_BLACK_LEVEL_PATTERN, blackLevelPattern,
+ sizeof(blackLevelPattern) / sizeof(int32_t));
+ }
+
+ if (hasCapability(BACKWARD_COMPATIBLE)) {
+ static const int32_t availableTestPatternModes[] = {
+ ANDROID_SENSOR_TEST_PATTERN_MODE_OFF};
+ ADD_STATIC_ENTRY(ANDROID_SENSOR_AVAILABLE_TEST_PATTERN_MODES,
+ availableTestPatternModes,
+ sizeof(availableTestPatternModes) / sizeof(int32_t));
+ }
+
+ // android.lens
+
+ static const float focalLength = 3.30f; // mm
+ ADD_STATIC_ENTRY(ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS, &focalLength, 1);
+
+ if (hasCapability(BACKWARD_COMPATIBLE)) {
+ // 5 cm min focus distance for back camera, infinity (fixed focus) for front
+ 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 = mFacingBack ? 1.0 / 5.0 : 0.0;
+ ADD_STATIC_ENTRY(ANDROID_LENS_INFO_HYPERFOCAL_DISTANCE, &hyperFocalDistance,
+ 1);
+
+ static const float aperture = 2.8f;
+ ADD_STATIC_ENTRY(ANDROID_LENS_INFO_AVAILABLE_APERTURES, &aperture, 1);
+ static const float filterDensity = 0;
+ ADD_STATIC_ENTRY(ANDROID_LENS_INFO_AVAILABLE_FILTER_DENSITIES,
+ &filterDensity, 1);
+ static const uint8_t availableOpticalStabilization =
+ ANDROID_LENS_OPTICAL_STABILIZATION_MODE_OFF;
+ ADD_STATIC_ENTRY(ANDROID_LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION,
+ &availableOpticalStabilization, 1);
+
+ static const int32_t lensShadingMapSize[] = {1, 1};
+ ADD_STATIC_ENTRY(ANDROID_LENS_INFO_SHADING_MAP_SIZE, lensShadingMapSize,
+ sizeof(lensShadingMapSize) / sizeof(int32_t));
+
+ static const uint8_t lensFocusCalibration =
+ ANDROID_LENS_INFO_FOCUS_DISTANCE_CALIBRATION_APPROXIMATE;
+ ADD_STATIC_ENTRY(ANDROID_LENS_INFO_FOCUS_DISTANCE_CALIBRATION,
+ &lensFocusCalibration, 1);
+ }
+
+ if (hasCapability(DEPTH_OUTPUT)) {
+ // These could be included for non-DEPTH capability as well, but making this
+ // variable for testing coverage
+
+ // 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};
+
+ // 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],
+ qO[0] * qF[1] + qO[1] * qF[0] + qO[2] * qF[3] - qO[3] * qF[2],
+ qO[0] * qF[2] + qO[2] * qF[0] + qO[1] * qF[3] - qO[3] * qF[1],
+ qO[0] * qF[3] + qO[3] * qF[0] + qO[1] * qF[2] - qO[2] * qF[1]};
+
+ ADD_STATIC_ENTRY(ANDROID_LENS_POSE_ROTATION, lensPoseRotation,
+ sizeof(lensPoseRotation) / sizeof(float));
+
+ // Only one camera facing each way, so 0 translation needed to the center of
+ // the 'main' camera
+ static const float lensPoseTranslation[] = {0.f, 0.f, 0.f};
+
+ ADD_STATIC_ENTRY(ANDROID_LENS_POSE_TRANSLATION, lensPoseTranslation,
+ sizeof(lensPoseTranslation) / sizeof(float));
+
+ // Intrinsics are 'ideal' (f_x, f_y, c_x, c_y, s) match focal length and
+ // active array size
+ float f_x = focalLength * mSensorWidth / sensorPhysicalSize[0];
+ float f_y = focalLength * mSensorHeight / sensorPhysicalSize[1];
+ float c_x = mSensorWidth / 2.f;
+ float c_y = mSensorHeight / 2.f;
+ float s = 0.f;
+ const float lensIntrinsics[] = {f_x, f_y, c_x, c_y, s};
+
+ ADD_STATIC_ENTRY(ANDROID_LENS_INTRINSIC_CALIBRATION, lensIntrinsics,
+ sizeof(lensIntrinsics) / sizeof(float));
+
+ // No radial or tangential distortion
+
+ float lensRadialDistortion[] = {1.0f, 0.f, 0.f, 0.f, 0.f, 0.f};
+
+ ADD_STATIC_ENTRY(ANDROID_LENS_RADIAL_DISTORTION, lensRadialDistortion,
+ sizeof(lensRadialDistortion) / sizeof(float));
+ }
+
+ const uint8_t lensFacing =
+ mFacingBack ? ANDROID_LENS_FACING_BACK : ANDROID_LENS_FACING_FRONT;
+ ADD_STATIC_ENTRY(ANDROID_LENS_FACING, &lensFacing, 1);
+
+ // android.flash
+
+ const uint8_t flashAvailable = mFacingBack;
+ ADD_STATIC_ENTRY(ANDROID_FLASH_INFO_AVAILABLE, &flashAvailable, 1);
+
+ // android.tonemap
+
+ if (hasCapability(MANUAL_POST_PROCESSING)) {
+ static const int32_t tonemapCurvePoints = 128;
+ ADD_STATIC_ENTRY(ANDROID_TONEMAP_MAX_CURVE_POINTS, &tonemapCurvePoints, 1);
+
+ static const uint8_t availableToneMapModes[] = {
+ ANDROID_TONEMAP_MODE_CONTRAST_CURVE, ANDROID_TONEMAP_MODE_FAST,
+ ANDROID_TONEMAP_MODE_HIGH_QUALITY};
+ ADD_STATIC_ENTRY(ANDROID_TONEMAP_AVAILABLE_TONE_MAP_MODES,
+ availableToneMapModes, sizeof(availableToneMapModes));
+ }
+
+ // android.scaler
+
+ const std::vector<int32_t> availableStreamConfigurationsBasic = {
+ HAL_PIXEL_FORMAT_BLOB,
+ width,
+ height,
+ 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,
+ };
+
+ // 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 = {
+ HAL_PIXEL_FORMAT_RAW16,
+ width,
+ height,
+ ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT,
+ };
+
+ const std::vector<int32_t> availableStreamConfigurationsBurst = {
+ HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED,
+ width,
+ height,
+ ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT,
+ HAL_PIXEL_FORMAT_YCbCr_420_888,
+ width,
+ height,
+ ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT,
+ HAL_PIXEL_FORMAT_RGBA_8888,
+ width,
+ height,
+ ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT,
+ };
+
+ std::vector<int32_t> availableStreamConfigurations;
+
+ if (hasCapability(BACKWARD_COMPATIBLE)) {
+ 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(),
+ availableStreamConfigurationsRaw.begin(),
+ availableStreamConfigurationsRaw.end());
+ }
+ if (hasCapability(BURST_CAPTURE)) {
+ availableStreamConfigurations.insert(
+ availableStreamConfigurations.end(),
+ availableStreamConfigurationsBurst.begin(),
+ availableStreamConfigurationsBurst.end());
+ }
+
+ if (availableStreamConfigurations.size() > 0) {
+ ADD_STATIC_ENTRY(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
+ &availableStreamConfigurations[0],
+ availableStreamConfigurations.size());
+ }
+
+ const std::vector<int64_t> availableMinFrameDurationsBasic = {
+ HAL_PIXEL_FORMAT_BLOB,
+ width,
+ height,
+ 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],
+ };
+
+ // 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 = {
+ HAL_PIXEL_FORMAT_RAW16,
+ width,
+ height,
+ Sensor::kFrameDurationRange[0],
+ };
+
+ const std::vector<int64_t> availableMinFrameDurationsBurst = {
+ HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED,
+ width,
+ height,
+ Sensor::kFrameDurationRange[0],
+ HAL_PIXEL_FORMAT_YCbCr_420_888,
+ width,
+ height,
+ Sensor::kFrameDurationRange[0],
+ HAL_PIXEL_FORMAT_RGBA_8888,
+ width,
+ height,
+ Sensor::kFrameDurationRange[0],
+ };
+
+ std::vector<int64_t> availableMinFrameDurations;
+
+ if (hasCapability(BACKWARD_COMPATIBLE)) {
+ 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(),
+ availableMinFrameDurationsRaw.begin(),
+ availableMinFrameDurationsRaw.end());
+ }
+ if (hasCapability(BURST_CAPTURE)) {
+ availableMinFrameDurations.insert(availableMinFrameDurations.end(),
+ availableMinFrameDurationsBurst.begin(),
+ availableMinFrameDurationsBurst.end());
+ }
+
+ if (availableMinFrameDurations.size() > 0) {
+ ADD_STATIC_ENTRY(ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS,
+ &availableMinFrameDurations[0],
+ availableMinFrameDurations.size());
+ }
+
+ const std::vector<int64_t> availableStallDurationsBasic = {
+ HAL_PIXEL_FORMAT_BLOB,
+ width,
+ height,
+ 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,
+ };
+
+ // 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]};
+ 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};
+
+ std::vector<int64_t> availableStallDurations;
+
+ if (hasCapability(BACKWARD_COMPATIBLE)) {
+ 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(),
+ availableStallDurationsRaw.begin(),
+ availableStallDurationsRaw.end());
+ }
+ if (hasCapability(BURST_CAPTURE)) {
+ availableStallDurations.insert(availableStallDurations.end(),
+ availableStallDurationsBurst.begin(),
+ availableStallDurationsBurst.end());
+ }
+
+ if (availableStallDurations.size() > 0) {
+ ADD_STATIC_ENTRY(ANDROID_SCALER_AVAILABLE_STALL_DURATIONS,
+ &availableStallDurations[0],
+ availableStallDurations.size());
+ }
+
+ if (hasCapability(BACKWARD_COMPATIBLE)) {
+ static const uint8_t croppingType = ANDROID_SCALER_CROPPING_TYPE_FREEFORM;
+ ADD_STATIC_ENTRY(ANDROID_SCALER_CROPPING_TYPE, &croppingType, 1);
+
+ static const float maxZoom = 10;
+ ADD_STATIC_ENTRY(ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM, &maxZoom, 1);
+ }
+
+ // android.jpeg
+
+ if (hasCapability(BACKWARD_COMPATIBLE)) {
+ static const int32_t jpegThumbnailSizes[] = {0, 0, 160, 120, 320, 240};
+ ADD_STATIC_ENTRY(ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES, jpegThumbnailSizes,
+ sizeof(jpegThumbnailSizes) / sizeof(int32_t));
+
+ static const int32_t jpegMaxSize = JpegCompressor::kMaxJpegSize;
+ ADD_STATIC_ENTRY(ANDROID_JPEG_MAX_SIZE, &jpegMaxSize, 1);
+ }
+
+ // android.stats
+
+ if (hasCapability(BACKWARD_COMPATIBLE)) {
+ static const uint8_t availableFaceDetectModes[] = {
+ ANDROID_STATISTICS_FACE_DETECT_MODE_OFF,
+ ANDROID_STATISTICS_FACE_DETECT_MODE_SIMPLE,
+ ANDROID_STATISTICS_FACE_DETECT_MODE_FULL};
+ ADD_STATIC_ENTRY(ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES,
+ availableFaceDetectModes,
+ sizeof(availableFaceDetectModes));
+
+ static const int32_t maxFaceCount = 8;
+ ADD_STATIC_ENTRY(ANDROID_STATISTICS_INFO_MAX_FACE_COUNT, &maxFaceCount, 1);
+
+ static const uint8_t availableShadingMapModes[] = {
+ ANDROID_STATISTICS_LENS_SHADING_MAP_MODE_OFF};
+ ADD_STATIC_ENTRY(ANDROID_STATISTICS_INFO_AVAILABLE_LENS_SHADING_MAP_MODES,
+ availableShadingMapModes,
+ sizeof(availableShadingMapModes));
+ }
+
+ // android.sync
+
+ static const int32_t maxLatency =
+ hasCapability(FULL_LEVEL) ? ANDROID_SYNC_MAX_LATENCY_PER_FRAME_CONTROL
+ : 3;
+ ADD_STATIC_ENTRY(ANDROID_SYNC_MAX_LATENCY, &maxLatency, 1);
+
+ // android.control
+
+ if (hasCapability(BACKWARD_COMPATIBLE)) {
+ static const uint8_t availableControlModes[] = {
+ ANDROID_CONTROL_MODE_OFF, ANDROID_CONTROL_MODE_AUTO,
+ ANDROID_CONTROL_MODE_USE_SCENE_MODE};
+ ADD_STATIC_ENTRY(ANDROID_CONTROL_AVAILABLE_MODES, availableControlModes,
+ sizeof(availableControlModes));
+ } else {
+ static const uint8_t availableControlModes[] = {ANDROID_CONTROL_MODE_AUTO};
+ ADD_STATIC_ENTRY(ANDROID_CONTROL_AVAILABLE_MODES, availableControlModes,
+ sizeof(availableControlModes));
+ }
+
+ static const uint8_t availableSceneModes[] = {
+ static_cast<uint8_t>(hasCapability(BACKWARD_COMPATIBLE)
+ ? ANDROID_CONTROL_SCENE_MODE_FACE_PRIORITY
+ : ANDROID_CONTROL_SCENE_MODE_DISABLED)};
+ ADD_STATIC_ENTRY(ANDROID_CONTROL_AVAILABLE_SCENE_MODES, availableSceneModes,
+ sizeof(availableSceneModes));
+
+ if (hasCapability(BACKWARD_COMPATIBLE)) {
+ static const uint8_t availableEffects[] = {ANDROID_CONTROL_EFFECT_MODE_OFF};
+ ADD_STATIC_ENTRY(ANDROID_CONTROL_AVAILABLE_EFFECTS, availableEffects,
+ sizeof(availableEffects));
+ }
+
+ if (hasCapability(BACKWARD_COMPATIBLE)) {
+ static const int32_t max3aRegions[] = {/*AE*/ 1, /*AWB*/ 0, /*AF*/ 1};
+ ADD_STATIC_ENTRY(ANDROID_CONTROL_MAX_REGIONS, max3aRegions,
+ sizeof(max3aRegions) / sizeof(max3aRegions[0]));
+
+ static const uint8_t availableAeModes[] = {ANDROID_CONTROL_AE_MODE_OFF,
+ ANDROID_CONTROL_AE_MODE_ON};
+ ADD_STATIC_ENTRY(ANDROID_CONTROL_AE_AVAILABLE_MODES, availableAeModes,
+ sizeof(availableAeModes));
+
+ static const camera_metadata_rational exposureCompensationStep = {1, 3};
+ ADD_STATIC_ENTRY(ANDROID_CONTROL_AE_COMPENSATION_STEP,
+ &exposureCompensationStep, 1);
+
+ int32_t exposureCompensationRange[] = {-9, 9};
+ ADD_STATIC_ENTRY(ANDROID_CONTROL_AE_COMPENSATION_RANGE,
+ exposureCompensationRange,
+ sizeof(exposureCompensationRange) / sizeof(int32_t));
+ }
+
+ static const int32_t availableTargetFpsRanges[] = {5, 30, 15, 30,
+ 15, 15, 30, 30};
+ ADD_STATIC_ENTRY(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,
+ availableTargetFpsRanges,
+ sizeof(availableTargetFpsRanges) / sizeof(int32_t));
+
+ if (hasCapability(BACKWARD_COMPATIBLE)) {
+ static const uint8_t availableAntibandingModes[] = {
+ ANDROID_CONTROL_AE_ANTIBANDING_MODE_OFF,
+ ANDROID_CONTROL_AE_ANTIBANDING_MODE_AUTO};
+ ADD_STATIC_ENTRY(ANDROID_CONTROL_AE_AVAILABLE_ANTIBANDING_MODES,
+ availableAntibandingModes,
+ sizeof(availableAntibandingModes));
+ }
+
+ static const uint8_t aeLockAvailable =
+ hasCapability(BACKWARD_COMPATIBLE)
+ ? ANDROID_CONTROL_AE_LOCK_AVAILABLE_TRUE
+ : ANDROID_CONTROL_AE_LOCK_AVAILABLE_FALSE;
+
+ ADD_STATIC_ENTRY(ANDROID_CONTROL_AE_LOCK_AVAILABLE, &aeLockAvailable, 1);
+
+ if (hasCapability(BACKWARD_COMPATIBLE)) {
+ static const uint8_t availableAwbModes[] = {
+ ANDROID_CONTROL_AWB_MODE_OFF,
+ ANDROID_CONTROL_AWB_MODE_AUTO,
+ ANDROID_CONTROL_AWB_MODE_INCANDESCENT,
+ ANDROID_CONTROL_AWB_MODE_FLUORESCENT,
+ ANDROID_CONTROL_AWB_MODE_DAYLIGHT,
+ ANDROID_CONTROL_AWB_MODE_SHADE};
+ ADD_STATIC_ENTRY(ANDROID_CONTROL_AWB_AVAILABLE_MODES, availableAwbModes,
+ sizeof(availableAwbModes));
+ }
+
+ static const uint8_t awbLockAvailable =
+ hasCapability(BACKWARD_COMPATIBLE)
+ ? ANDROID_CONTROL_AWB_LOCK_AVAILABLE_TRUE
+ : ANDROID_CONTROL_AWB_LOCK_AVAILABLE_FALSE;
+
+ ADD_STATIC_ENTRY(ANDROID_CONTROL_AWB_LOCK_AVAILABLE, &awbLockAvailable, 1);
+
+ static const uint8_t availableAfModesBack[] = {
+ ANDROID_CONTROL_AF_MODE_OFF, ANDROID_CONTROL_AF_MODE_AUTO,
+ ANDROID_CONTROL_AF_MODE_MACRO, ANDROID_CONTROL_AF_MODE_CONTINUOUS_VIDEO,
+ ANDROID_CONTROL_AF_MODE_CONTINUOUS_PICTURE};
+
+ static const uint8_t availableAfModesFront[] = {ANDROID_CONTROL_AF_MODE_OFF};
+
+ if (mFacingBack && hasCapability(BACKWARD_COMPATIBLE)) {
+ ADD_STATIC_ENTRY(ANDROID_CONTROL_AF_AVAILABLE_MODES, availableAfModesBack,
+ sizeof(availableAfModesBack));
+ } else {
+ ADD_STATIC_ENTRY(ANDROID_CONTROL_AF_AVAILABLE_MODES, availableAfModesFront,
+ sizeof(availableAfModesFront));
+ }
+
+ static const uint8_t availableVstabModes[] = {
+ ANDROID_CONTROL_VIDEO_STABILIZATION_MODE_OFF};
+ ADD_STATIC_ENTRY(ANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES,
+ availableVstabModes, sizeof(availableVstabModes));
+
+ // android.colorCorrection
+
+ if (hasCapability(BACKWARD_COMPATIBLE)) {
+ static const uint8_t availableAberrationModes[] = {
+ ANDROID_COLOR_CORRECTION_ABERRATION_MODE_OFF,
+ ANDROID_COLOR_CORRECTION_ABERRATION_MODE_FAST,
+ ANDROID_COLOR_CORRECTION_ABERRATION_MODE_HIGH_QUALITY};
+ ADD_STATIC_ENTRY(ANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES,
+ availableAberrationModes,
+ sizeof(availableAberrationModes));
+ } else {
+ static const uint8_t availableAberrationModes[] = {
+ ANDROID_COLOR_CORRECTION_ABERRATION_MODE_OFF,
+ };
+ ADD_STATIC_ENTRY(ANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES,
+ availableAberrationModes,
+ sizeof(availableAberrationModes));
+ }
+ // android.edge
+
+ if (hasCapability(BACKWARD_COMPATIBLE)) {
+ static const uint8_t availableEdgeModes[] = {
+ ANDROID_EDGE_MODE_OFF, ANDROID_EDGE_MODE_FAST,
+ ANDROID_EDGE_MODE_HIGH_QUALITY};
+ ADD_STATIC_ENTRY(ANDROID_EDGE_AVAILABLE_EDGE_MODES, availableEdgeModes,
+ sizeof(availableEdgeModes));
+ } else {
+ static const uint8_t availableEdgeModes[] = {ANDROID_EDGE_MODE_OFF};
+ ADD_STATIC_ENTRY(ANDROID_EDGE_AVAILABLE_EDGE_MODES, availableEdgeModes,
+ sizeof(availableEdgeModes));
+ }
+
+ // android.info
+
+ static const uint8_t supportedHardwareLevel =
+ hasCapability(FULL_LEVEL) ? ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_FULL
+ : ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED;
+ ADD_STATIC_ENTRY(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL,
+ &supportedHardwareLevel,
+ /*count*/ 1);
+
+ // android.noiseReduction
+
+ if (hasCapability(BACKWARD_COMPATIBLE)) {
+ static const uint8_t availableNoiseReductionModes[] = {
+ ANDROID_NOISE_REDUCTION_MODE_OFF, ANDROID_NOISE_REDUCTION_MODE_FAST,
+ ANDROID_NOISE_REDUCTION_MODE_HIGH_QUALITY};
+ ADD_STATIC_ENTRY(ANDROID_NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES,
+ availableNoiseReductionModes,
+ sizeof(availableNoiseReductionModes));
+ } else {
+ static const uint8_t availableNoiseReductionModes[] = {
+ ANDROID_NOISE_REDUCTION_MODE_OFF,
+ };
+ ADD_STATIC_ENTRY(ANDROID_NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES,
+ availableNoiseReductionModes,
+ sizeof(availableNoiseReductionModes));
+ }
+
+ // android.depth
+
+ if (hasCapability(DEPTH_OUTPUT)) {
+ static const int32_t maxDepthSamples = 100;
+ ADD_STATIC_ENTRY(ANDROID_DEPTH_MAX_DEPTH_SAMPLES, &maxDepthSamples, 1);
+
+ static const int32_t availableDepthStreamConfigurations[] = {
+ HAL_PIXEL_FORMAT_Y16,
+ 160,
+ 120,
+ ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS_OUTPUT,
+ HAL_PIXEL_FORMAT_BLOB,
+ maxDepthSamples,
+ 1,
+ ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS_OUTPUT};
+ ADD_STATIC_ENTRY(
+ ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS,
+ availableDepthStreamConfigurations,
+ sizeof(availableDepthStreamConfigurations) / sizeof(int32_t));
+
+ static const int64_t availableDepthMinFrameDurations[] = {
+ HAL_PIXEL_FORMAT_Y16,
+ 160,
+ 120,
+ Sensor::kFrameDurationRange[0],
+ HAL_PIXEL_FORMAT_BLOB,
+ maxDepthSamples,
+ 1,
+ Sensor::kFrameDurationRange[0]};
+ ADD_STATIC_ENTRY(ANDROID_DEPTH_AVAILABLE_DEPTH_MIN_FRAME_DURATIONS,
+ availableDepthMinFrameDurations,
+ sizeof(availableDepthMinFrameDurations) / sizeof(int64_t));
+
+ static const int64_t availableDepthStallDurations[] = {
+ HAL_PIXEL_FORMAT_Y16,
+ 160,
+ 120,
+ Sensor::kFrameDurationRange[0],
+ HAL_PIXEL_FORMAT_BLOB,
+ maxDepthSamples,
+ 1,
+ Sensor::kFrameDurationRange[0]};
+ ADD_STATIC_ENTRY(ANDROID_DEPTH_AVAILABLE_DEPTH_STALL_DURATIONS,
+ availableDepthStallDurations,
+ sizeof(availableDepthStallDurations) / sizeof(int64_t));
+
+ uint8_t depthIsExclusive = ANDROID_DEPTH_DEPTH_IS_EXCLUSIVE_FALSE;
+ ADD_STATIC_ENTRY(ANDROID_DEPTH_DEPTH_IS_EXCLUSIVE, &depthIsExclusive, 1);
+ }
+
+ // android.shading
+
+ if (hasCapability(BACKWARD_COMPATIBLE)) {
+ static const uint8_t availableShadingModes[] = {
+ ANDROID_SHADING_MODE_OFF, ANDROID_SHADING_MODE_FAST,
+ ANDROID_SHADING_MODE_HIGH_QUALITY};
+ ADD_STATIC_ENTRY(ANDROID_SHADING_AVAILABLE_MODES, availableShadingModes,
+ sizeof(availableShadingModes));
+ } else {
+ static const uint8_t availableShadingModes[] = {ANDROID_SHADING_MODE_OFF};
+ ADD_STATIC_ENTRY(ANDROID_SHADING_AVAILABLE_MODES, availableShadingModes,
+ sizeof(availableShadingModes));
+ }
+
+ // android.request
+
+ static const int32_t maxNumOutputStreams[] = {
+ kMaxRawStreamCount, kMaxProcessedStreamCount, kMaxJpegStreamCount};
+ ADD_STATIC_ENTRY(ANDROID_REQUEST_MAX_NUM_OUTPUT_STREAMS, maxNumOutputStreams,
+ 3);
+
+ static const uint8_t maxPipelineDepth = kMaxBufferCount;
+ ADD_STATIC_ENTRY(ANDROID_REQUEST_PIPELINE_MAX_DEPTH, &maxPipelineDepth, 1);
+
+ static const int32_t partialResultCount = 1;
+ ADD_STATIC_ENTRY(ANDROID_REQUEST_PARTIAL_RESULT_COUNT, &partialResultCount,
+ /*count*/ 1);
+
+ SortedVector<uint8_t> caps;
+ for (size_t i = 0; i < mCapabilities.size(); i++) {
+ switch (mCapabilities[i]) {
+ case BACKWARD_COMPATIBLE:
+ caps.add(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE);
+ break;
+ case MANUAL_SENSOR:
+ caps.add(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR);
+ break;
+ case MANUAL_POST_PROCESSING:
+ caps.add(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING);
+ break;
+ case RAW:
+ caps.add(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_RAW);
+ break;
+ case PRIVATE_REPROCESSING:
+ caps.add(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_PRIVATE_REPROCESSING);
+ break;
+ case READ_SENSOR_SETTINGS:
+ caps.add(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_READ_SENSOR_SETTINGS);
+ break;
+ case BURST_CAPTURE:
+ caps.add(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE);
+ break;
+ case YUV_REPROCESSING:
+ caps.add(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING);
+ break;
+ case DEPTH_OUTPUT:
+ caps.add(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_DEPTH_OUTPUT);
+ break;
+ case CONSTRAINED_HIGH_SPEED_VIDEO:
+ caps.add(
+ ANDROID_REQUEST_AVAILABLE_CAPABILITIES_CONSTRAINED_HIGH_SPEED_VIDEO);
+ break;
+ default:
+ // Ignore LEVELs
+ break;
+ }
+ }
+ ADD_STATIC_ENTRY(ANDROID_REQUEST_AVAILABLE_CAPABILITIES, caps.array(),
+ caps.size());
+
+ // Scan a default request template for included request keys
+ Vector<int32_t> availableRequestKeys;
+ const camera_metadata_t *previewRequest =
+ constructDefaultRequestSettings(CAMERA3_TEMPLATE_PREVIEW);
+ for (size_t i = 0; i < get_camera_metadata_entry_count(previewRequest); i++) {
+ camera_metadata_ro_entry_t entry;
+ get_camera_metadata_ro_entry(previewRequest, i, &entry);
+ availableRequestKeys.add(entry.tag);
+ }
+ ADD_STATIC_ENTRY(ANDROID_REQUEST_AVAILABLE_REQUEST_KEYS,
+ availableRequestKeys.array(), availableRequestKeys.size());
+
+ // Add a few more result keys. Must be kept up to date with the various places
+ // that add these
+
+ Vector<int32_t> availableResultKeys(availableRequestKeys);
+ if (hasCapability(BACKWARD_COMPATIBLE)) {
+ availableResultKeys.add(ANDROID_CONTROL_AE_STATE);
+ availableResultKeys.add(ANDROID_CONTROL_AF_STATE);
+ availableResultKeys.add(ANDROID_CONTROL_AWB_STATE);
+ availableResultKeys.add(ANDROID_FLASH_STATE);
+ availableResultKeys.add(ANDROID_LENS_STATE);
+ availableResultKeys.add(ANDROID_LENS_FOCUS_RANGE);
+ availableResultKeys.add(ANDROID_SENSOR_ROLLING_SHUTTER_SKEW);
+ availableResultKeys.add(ANDROID_STATISTICS_SCENE_FLICKER);
+ }
+
+ if (hasCapability(DEPTH_OUTPUT)) {
+ availableResultKeys.add(ANDROID_LENS_POSE_ROTATION);
+ availableResultKeys.add(ANDROID_LENS_POSE_TRANSLATION);
+ availableResultKeys.add(ANDROID_LENS_INTRINSIC_CALIBRATION);
+ availableResultKeys.add(ANDROID_LENS_RADIAL_DISTORTION);
+ }
+
+ availableResultKeys.add(ANDROID_REQUEST_PIPELINE_DEPTH);
+ availableResultKeys.add(ANDROID_SENSOR_TIMESTAMP);
+
+ ADD_STATIC_ENTRY(ANDROID_REQUEST_AVAILABLE_RESULT_KEYS,
+ availableResultKeys.array(), availableResultKeys.size());
+
+ // Needs to be last, to collect all the keys set
+
+ availableCharacteristicsKeys.add(
+ ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS);
+ info.update(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS,
+ availableCharacteristicsKeys);
+
+ mCameraInfo = info.release();
+
+#undef ADD_STATIC_ENTRY
+ return OK;
+}
+
+status_t EmulatedFakeCamera3::process3A(CameraMetadata &settings) {
+ /**
+ * Extract top-level 3A controls
+ */
+ status_t res;
+
+ camera_metadata_entry e;
+
+ e = settings.find(ANDROID_CONTROL_MODE);
+ if (e.count == 0) {
+ ALOGE("%s: No control mode entry!", __FUNCTION__);
+ return BAD_VALUE;
+ }
+ uint8_t controlMode = e.data.u8[0];
+
+ if (controlMode == ANDROID_CONTROL_MODE_OFF) {
+ mAeMode = ANDROID_CONTROL_AE_MODE_OFF;
+ mAfMode = ANDROID_CONTROL_AF_MODE_OFF;
+ mAwbMode = ANDROID_CONTROL_AWB_MODE_OFF;
+ mAeState = ANDROID_CONTROL_AE_STATE_INACTIVE;
+ mAfState = ANDROID_CONTROL_AF_STATE_INACTIVE;
+ mAwbState = ANDROID_CONTROL_AWB_STATE_INACTIVE;
+ update3A(settings);
+ return OK;
+ } else if (controlMode == ANDROID_CONTROL_MODE_USE_SCENE_MODE) {
+ if (!hasCapability(BACKWARD_COMPATIBLE)) {
+ ALOGE("%s: Can't use scene mode when BACKWARD_COMPATIBLE not supported!",
+ __FUNCTION__);
+ return BAD_VALUE;
+ }
+
+ e = settings.find(ANDROID_CONTROL_SCENE_MODE);
+ if (e.count == 0) {
+ ALOGE("%s: No scene mode entry!", __FUNCTION__);
+ return BAD_VALUE;
+ }
+ uint8_t sceneMode = e.data.u8[0];
+
+ switch (sceneMode) {
+ case ANDROID_CONTROL_SCENE_MODE_FACE_PRIORITY:
+ mFacePriority = true;
+ break;
+ default:
+ ALOGE("%s: Emulator doesn't support scene mode %d", __FUNCTION__,
+ sceneMode);
+ return BAD_VALUE;
+ }
+ } else {
+ mFacePriority = false;
+ }
+
+ // controlMode == AUTO or sceneMode = FACE_PRIORITY
+ // Process individual 3A controls
+
+ res = doFakeAE(settings);
+ if (res != OK) return res;
+
+ res = doFakeAF(settings);
+ if (res != OK) return res;
+
+ res = doFakeAWB(settings);
+ if (res != OK) return res;
+
+ update3A(settings);
+ return OK;
+}
+
+status_t EmulatedFakeCamera3::doFakeAE(CameraMetadata &settings) {
+ camera_metadata_entry e;
+
+ e = settings.find(ANDROID_CONTROL_AE_MODE);
+ if (e.count == 0 && hasCapability(BACKWARD_COMPATIBLE)) {
+ ALOGE("%s: No AE mode entry!", __FUNCTION__);
+ return BAD_VALUE;
+ }
+ uint8_t aeMode =
+ (e.count > 0) ? e.data.u8[0] : (uint8_t)ANDROID_CONTROL_AE_MODE_ON;
+ mAeMode = aeMode;
+
+ switch (aeMode) {
+ case ANDROID_CONTROL_AE_MODE_OFF:
+ // AE is OFF
+ mAeState = ANDROID_CONTROL_AE_STATE_INACTIVE;
+ return OK;
+ case ANDROID_CONTROL_AE_MODE_ON:
+ // OK for AUTO modes
+ break;
+ default:
+ // Mostly silently ignore unsupported modes
+ ALOGV("%s: Emulator doesn't support AE mode %d, assuming ON",
+ __FUNCTION__, aeMode);
+ break;
+ }
+
+ e = settings.find(ANDROID_CONTROL_AE_LOCK);
+ bool aeLocked =
+ (e.count > 0) ? (e.data.u8[0] == ANDROID_CONTROL_AE_LOCK_ON) : false;
+
+ e = settings.find(ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER);
+ bool precaptureTrigger = false;
+ if (e.count != 0) {
+ precaptureTrigger =
+ (e.data.u8[0] == ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_START);
+ }
+
+ if (precaptureTrigger) {
+ ALOGV("%s: Pre capture trigger = %d", __FUNCTION__, precaptureTrigger);
+ } else if (e.count > 0) {
+ ALOGV("%s: Pre capture trigger was present? %zu", __FUNCTION__, e.count);
+ }
+
+ if (precaptureTrigger || mAeState == ANDROID_CONTROL_AE_STATE_PRECAPTURE) {
+ // Run precapture sequence
+ if (mAeState != ANDROID_CONTROL_AE_STATE_PRECAPTURE) {
+ mAeCounter = 0;
+ }
+
+ if (mFacePriority) {
+ mAeTargetExposureTime = kFacePriorityExposureTime;
+ } else {
+ mAeTargetExposureTime = kNormalExposureTime;
+ }
+
+ if (mAeCounter > kPrecaptureMinFrames &&
+ (mAeTargetExposureTime - mAeCurrentExposureTime) <
+ mAeTargetExposureTime / 10) {
+ // Done with precapture
+ mAeCounter = 0;
+ mAeState = aeLocked ? ANDROID_CONTROL_AE_STATE_LOCKED
+ : ANDROID_CONTROL_AE_STATE_CONVERGED;
+ } else {
+ // Converge some more
+ mAeCurrentExposureTime +=
+ (mAeTargetExposureTime - mAeCurrentExposureTime) * kExposureTrackRate;
+ mAeCounter++;
+ mAeState = ANDROID_CONTROL_AE_STATE_PRECAPTURE;
+ }
+
+ } else if (!aeLocked) {
+ // Run standard occasional AE scan
+ switch (mAeState) {
+ case ANDROID_CONTROL_AE_STATE_CONVERGED:
+ case ANDROID_CONTROL_AE_STATE_INACTIVE:
+ mAeCounter++;
+ if (mAeCounter > kStableAeMaxFrames) {
+ mAeTargetExposureTime =
+ mFacePriority ? kFacePriorityExposureTime : kNormalExposureTime;
+ float exposureStep = ((double)rand() / RAND_MAX) *
+ (kExposureWanderMax - kExposureWanderMin) +
+ kExposureWanderMin;
+ mAeTargetExposureTime *= std::pow(2, exposureStep);
+ mAeState = ANDROID_CONTROL_AE_STATE_SEARCHING;
+ }
+ break;
+ case ANDROID_CONTROL_AE_STATE_SEARCHING:
+ mAeCurrentExposureTime +=
+ (mAeTargetExposureTime - mAeCurrentExposureTime) *
+ kExposureTrackRate;
+ if (llabs(mAeTargetExposureTime - mAeCurrentExposureTime) <
+ mAeTargetExposureTime / 10) {
+ // Close enough
+ mAeState = ANDROID_CONTROL_AE_STATE_CONVERGED;
+ mAeCounter = 0;
+ }
+ break;
+ case ANDROID_CONTROL_AE_STATE_LOCKED:
+ mAeState = ANDROID_CONTROL_AE_STATE_CONVERGED;
+ mAeCounter = 0;
+ break;
+ default:
+ ALOGE("%s: Emulator in unexpected AE state %d", __FUNCTION__, mAeState);
+ return INVALID_OPERATION;
+ }
+ } else {
+ // AE is locked
+ mAeState = ANDROID_CONTROL_AE_STATE_LOCKED;
+ }
+
+ return OK;
+}
+
+status_t EmulatedFakeCamera3::doFakeAF(CameraMetadata &settings) {
+ camera_metadata_entry e;
+
+ e = settings.find(ANDROID_CONTROL_AF_MODE);
+ if (e.count == 0 && hasCapability(BACKWARD_COMPATIBLE)) {
+ ALOGE("%s: No AF mode entry!", __FUNCTION__);
+ return BAD_VALUE;
+ }
+ uint8_t afMode =
+ (e.count > 0) ? e.data.u8[0] : (uint8_t)ANDROID_CONTROL_AF_MODE_OFF;
+
+ e = settings.find(ANDROID_CONTROL_AF_TRIGGER);
+ typedef camera_metadata_enum_android_control_af_trigger af_trigger_t;
+ af_trigger_t afTrigger;
+ if (e.count != 0) {
+ afTrigger = static_cast<af_trigger_t>(e.data.u8[0]);
+
+ ALOGV("%s: AF trigger set to 0x%x", __FUNCTION__, afTrigger);
+ ALOGV("%s: AF mode is 0x%x", __FUNCTION__, afMode);
+ } else {
+ afTrigger = ANDROID_CONTROL_AF_TRIGGER_IDLE;
+ }
+
+ switch (afMode) {
+ case ANDROID_CONTROL_AF_MODE_OFF:
+ mAfState = ANDROID_CONTROL_AF_STATE_INACTIVE;
+ return OK;
+ case ANDROID_CONTROL_AF_MODE_AUTO:
+ case ANDROID_CONTROL_AF_MODE_MACRO:
+ case ANDROID_CONTROL_AF_MODE_CONTINUOUS_VIDEO:
+ case ANDROID_CONTROL_AF_MODE_CONTINUOUS_PICTURE:
+ if (!mFacingBack) {
+ ALOGE("%s: Front camera doesn't support AF mode %d", __FUNCTION__,
+ afMode);
+ return BAD_VALUE;
+ }
+ // OK, handle transitions lower on
+ break;
+ default:
+ ALOGE("%s: Emulator doesn't support AF mode %d", __FUNCTION__, afMode);
+ return BAD_VALUE;
+ }
+
+ bool afModeChanged = mAfMode != afMode;
+ mAfMode = afMode;
+
+ /**
+ * Simulate AF triggers. Transition at most 1 state per frame.
+ * - Focusing always succeeds (goes into locked, or PASSIVE_SCAN).
+ */
+
+ bool afTriggerStart = false;
+ bool afTriggerCancel = false;
+ switch (afTrigger) {
+ case ANDROID_CONTROL_AF_TRIGGER_IDLE:
+ break;
+ case ANDROID_CONTROL_AF_TRIGGER_START:
+ afTriggerStart = true;
+ break;
+ case ANDROID_CONTROL_AF_TRIGGER_CANCEL:
+ afTriggerCancel = true;
+ // Cancel trigger always transitions into INACTIVE
+ mAfState = ANDROID_CONTROL_AF_STATE_INACTIVE;
+
+ ALOGV("%s: AF State transition to STATE_INACTIVE", __FUNCTION__);
+
+ // Stay in 'inactive' until at least next frame
+ return OK;
+ default:
+ ALOGE("%s: Unknown af trigger value %d", __FUNCTION__, afTrigger);
+ return BAD_VALUE;
+ }
+
+ // If we get down here, we're either in an autofocus mode
+ // or in a continuous focus mode (and no other modes)
+
+ int oldAfState = mAfState;
+ switch (mAfState) {
+ case ANDROID_CONTROL_AF_STATE_INACTIVE:
+ if (afTriggerStart) {
+ switch (afMode) {
+ case ANDROID_CONTROL_AF_MODE_AUTO:
+ // fall-through
+ case ANDROID_CONTROL_AF_MODE_MACRO:
+ mAfState = ANDROID_CONTROL_AF_STATE_ACTIVE_SCAN;
+ break;
+ case ANDROID_CONTROL_AF_MODE_CONTINUOUS_VIDEO:
+ // fall-through
+ case ANDROID_CONTROL_AF_MODE_CONTINUOUS_PICTURE:
+ mAfState = ANDROID_CONTROL_AF_STATE_NOT_FOCUSED_LOCKED;
+ break;
+ }
+ } else {
+ // At least one frame stays in INACTIVE
+ if (!afModeChanged) {
+ switch (afMode) {
+ case ANDROID_CONTROL_AF_MODE_CONTINUOUS_VIDEO:
+ // fall-through
+ case ANDROID_CONTROL_AF_MODE_CONTINUOUS_PICTURE:
+ mAfState = ANDROID_CONTROL_AF_STATE_PASSIVE_SCAN;
+ break;
+ }
+ }
+ }
+ break;
+ case ANDROID_CONTROL_AF_STATE_PASSIVE_SCAN:
+ /**
+ * When the AF trigger is activated, the algorithm should finish
+ * its PASSIVE_SCAN if active, and then transition into AF_FOCUSED
+ * or AF_NOT_FOCUSED as appropriate
+ */
+ if (afTriggerStart) {
+ // Randomly transition to focused or not focused
+ if (rand() % 3) {
+ mAfState = ANDROID_CONTROL_AF_STATE_FOCUSED_LOCKED;
+ } else {
+ mAfState = ANDROID_CONTROL_AF_STATE_NOT_FOCUSED_LOCKED;
+ }
+ }
+ /**
+ * When the AF trigger is not involved, the AF algorithm should
+ * start in INACTIVE state, and then transition into PASSIVE_SCAN
+ * and PASSIVE_FOCUSED states
+ */
+ else if (!afTriggerCancel) {
+ // Randomly transition to passive focus
+ if (rand() % 3 == 0) {
+ mAfState = ANDROID_CONTROL_AF_STATE_PASSIVE_FOCUSED;
+ }
+ }
+
+ break;
+ case ANDROID_CONTROL_AF_STATE_PASSIVE_FOCUSED:
+ if (afTriggerStart) {
+ // Randomly transition to focused or not focused
+ if (rand() % 3) {
+ mAfState = ANDROID_CONTROL_AF_STATE_FOCUSED_LOCKED;
+ } else {
+ mAfState = ANDROID_CONTROL_AF_STATE_NOT_FOCUSED_LOCKED;
+ }
+ }
+ // TODO: initiate passive scan (PASSIVE_SCAN)
+ break;
+ case ANDROID_CONTROL_AF_STATE_ACTIVE_SCAN:
+ // Simulate AF sweep completing instantaneously
+
+ // Randomly transition to focused or not focused
+ if (rand() % 3) {
+ mAfState = ANDROID_CONTROL_AF_STATE_FOCUSED_LOCKED;
+ } else {
+ mAfState = ANDROID_CONTROL_AF_STATE_NOT_FOCUSED_LOCKED;
+ }
+ break;
+ case ANDROID_CONTROL_AF_STATE_FOCUSED_LOCKED:
+ if (afTriggerStart) {
+ switch (afMode) {
+ case ANDROID_CONTROL_AF_MODE_AUTO:
+ // fall-through
+ case ANDROID_CONTROL_AF_MODE_MACRO:
+ mAfState = ANDROID_CONTROL_AF_STATE_ACTIVE_SCAN;
+ break;
+ case ANDROID_CONTROL_AF_MODE_CONTINUOUS_VIDEO:
+ // fall-through
+ case ANDROID_CONTROL_AF_MODE_CONTINUOUS_PICTURE:
+ // continuous autofocus => trigger start has no effect
+ break;
+ }
+ }
+ break;
+ case ANDROID_CONTROL_AF_STATE_NOT_FOCUSED_LOCKED:
+ if (afTriggerStart) {
+ switch (afMode) {
+ case ANDROID_CONTROL_AF_MODE_AUTO:
+ // fall-through
+ case ANDROID_CONTROL_AF_MODE_MACRO:
+ mAfState = ANDROID_CONTROL_AF_STATE_ACTIVE_SCAN;
+ break;
+ case ANDROID_CONTROL_AF_MODE_CONTINUOUS_VIDEO:
+ // fall-through
+ case ANDROID_CONTROL_AF_MODE_CONTINUOUS_PICTURE:
+ // continuous autofocus => trigger start has no effect
+ break;
+ }
+ }
+ break;
+ default:
+ ALOGE("%s: Bad af state %d", __FUNCTION__, mAfState);
+ }
+
+ {
+ char afStateString[100] = {
+ 0,
+ };
+ camera_metadata_enum_snprint(ANDROID_CONTROL_AF_STATE, oldAfState,
+ afStateString, sizeof(afStateString));
+
+ char afNewStateString[100] = {
+ 0,
+ };
+ camera_metadata_enum_snprint(ANDROID_CONTROL_AF_STATE, mAfState,
+ afNewStateString, sizeof(afNewStateString));
+ ALOGVV("%s: AF state transitioned from %s to %s", __FUNCTION__,
+ afStateString, afNewStateString);
+ }
+
+ return OK;
+}
+
+status_t EmulatedFakeCamera3::doFakeAWB(CameraMetadata &settings) {
+ camera_metadata_entry e;
+
+ e = settings.find(ANDROID_CONTROL_AWB_MODE);
+ if (e.count == 0 && hasCapability(BACKWARD_COMPATIBLE)) {
+ ALOGE("%s: No AWB mode entry!", __FUNCTION__);
+ return BAD_VALUE;
+ }
+ uint8_t awbMode =
+ (e.count > 0) ? e.data.u8[0] : (uint8_t)ANDROID_CONTROL_AWB_MODE_AUTO;
+
+ // TODO: Add white balance simulation
+
+ e = settings.find(ANDROID_CONTROL_AWB_LOCK);
+ bool awbLocked =
+ (e.count > 0) ? (e.data.u8[0] == ANDROID_CONTROL_AWB_LOCK_ON) : false;
+
+ switch (awbMode) {
+ case ANDROID_CONTROL_AWB_MODE_OFF:
+ mAwbState = ANDROID_CONTROL_AWB_STATE_INACTIVE;
+ break;
+ case ANDROID_CONTROL_AWB_MODE_AUTO:
+ case ANDROID_CONTROL_AWB_MODE_INCANDESCENT:
+ case ANDROID_CONTROL_AWB_MODE_FLUORESCENT:
+ case ANDROID_CONTROL_AWB_MODE_DAYLIGHT:
+ case ANDROID_CONTROL_AWB_MODE_SHADE:
+ // Always magically right, or locked
+ mAwbState = awbLocked ? ANDROID_CONTROL_AWB_STATE_LOCKED
+ : ANDROID_CONTROL_AWB_STATE_CONVERGED;
+ break;
+ default:
+ ALOGE("%s: Emulator doesn't support AWB mode %d", __FUNCTION__, awbMode);
+ return BAD_VALUE;
+ }
+
+ return OK;
+}
+
+void EmulatedFakeCamera3::update3A(CameraMetadata &settings) {
+ if (mAeMode != ANDROID_CONTROL_AE_MODE_OFF) {
+ settings.update(ANDROID_SENSOR_EXPOSURE_TIME, &mAeCurrentExposureTime, 1);
+ settings.update(ANDROID_SENSOR_SENSITIVITY, &mAeCurrentSensitivity, 1);
+ }
+
+ settings.update(ANDROID_CONTROL_AE_STATE, &mAeState, 1);
+ settings.update(ANDROID_CONTROL_AF_STATE, &mAfState, 1);
+ settings.update(ANDROID_CONTROL_AWB_STATE, &mAwbState, 1);
+
+ uint8_t lensState;
+ switch (mAfState) {
+ case ANDROID_CONTROL_AF_STATE_PASSIVE_SCAN:
+ case ANDROID_CONTROL_AF_STATE_ACTIVE_SCAN:
+ lensState = ANDROID_LENS_STATE_MOVING;
+ break;
+ case ANDROID_CONTROL_AF_STATE_INACTIVE:
+ case ANDROID_CONTROL_AF_STATE_PASSIVE_FOCUSED:
+ case ANDROID_CONTROL_AF_STATE_FOCUSED_LOCKED:
+ case ANDROID_CONTROL_AF_STATE_NOT_FOCUSED_LOCKED:
+ case ANDROID_CONTROL_AF_STATE_PASSIVE_UNFOCUSED:
+ default:
+ lensState = ANDROID_LENS_STATE_STATIONARY;
+ break;
+ }
+ settings.update(ANDROID_LENS_STATE, &lensState, 1);
+}
+
+void EmulatedFakeCamera3::signalReadoutIdle() {
+ Mutex::Autolock l(mLock);
+ // Need to chek isIdle again because waiting on mLock may have allowed
+ // something to be placed in the in-flight queue.
+ if (mStatus == STATUS_ACTIVE && mReadoutThread->isIdle()) {
+ ALOGV("Now idle");
+ mStatus = STATUS_READY;
+ }
+}
+
+void EmulatedFakeCamera3::onSensorEvent(uint32_t frameNumber, Event e,
+ nsecs_t timestamp) {
+ switch (e) {
+ case Sensor::SensorListener::EXPOSURE_START: {
+ ALOGVV("%s: Frame %d: Sensor started exposure at %lld", __FUNCTION__,
+ frameNumber, timestamp);
+ // Trigger shutter notify to framework
+ camera3_notify_msg_t msg;
+ msg.type = CAMERA3_MSG_SHUTTER;
+ msg.message.shutter.frame_number = frameNumber;
+ msg.message.shutter.timestamp = timestamp;
+ sendNotify(&msg);
+ break;
+ }
+ default:
+ ALOGW("%s: Unexpected sensor event %d at %" PRId64, __FUNCTION__, e,
+ timestamp);
+ break;
+ }
+}
+
+EmulatedFakeCamera3::ReadoutThread::ReadoutThread(EmulatedFakeCamera3 *parent)
+ : mParent(parent), mJpegWaiting(false) {}
+
+EmulatedFakeCamera3::ReadoutThread::~ReadoutThread() {
+ for (List<Request>::iterator i = mInFlightQueue.begin();
+ i != mInFlightQueue.end(); i++) {
+ delete i->buffers;
+ delete i->sensorBuffers;
+ }
+}
+
+void EmulatedFakeCamera3::ReadoutThread::queueCaptureRequest(const Request &r) {
+ Mutex::Autolock l(mLock);
+
+ mInFlightQueue.push_back(r);
+ mInFlightSignal.signal();
+}
+
+bool EmulatedFakeCamera3::ReadoutThread::isIdle() {
+ Mutex::Autolock l(mLock);
+ return mInFlightQueue.empty() && !mThreadActive;
+}
+
+status_t EmulatedFakeCamera3::ReadoutThread::waitForReadout() {
+ status_t res;
+ Mutex::Autolock l(mLock);
+ int loopCount = 0;
+ while (mInFlightQueue.size() >= kMaxQueueSize) {
+ res = mInFlightSignal.waitRelative(mLock, kWaitPerLoop);
+ if (res != OK && res != TIMED_OUT) {
+ ALOGE("%s: Error waiting for in-flight queue to shrink", __FUNCTION__);
+ return INVALID_OPERATION;
+ }
+ if (loopCount == kMaxWaitLoops) {
+ ALOGE("%s: Timed out waiting for in-flight queue to shrink",
+ __FUNCTION__);
+ return TIMED_OUT;
+ }
+ loopCount++;
+ }
+ return OK;
+}
+
+bool EmulatedFakeCamera3::ReadoutThread::threadLoop() {
+ status_t res;
+
+ ALOGVV("%s: ReadoutThread waiting for request", __FUNCTION__);
+
+ // First wait for a request from the in-flight queue
+
+ if (mCurrentRequest.settings.isEmpty()) {
+ Mutex::Autolock l(mLock);
+ if (mInFlightQueue.empty()) {
+ res = mInFlightSignal.waitRelative(mLock, kWaitPerLoop);
+ if (res == TIMED_OUT) {
+ ALOGVV("%s: ReadoutThread: Timed out waiting for request",
+ __FUNCTION__);
+ return true;
+ } else if (res != NO_ERROR) {
+ ALOGE("%s: Error waiting for capture requests: %d", __FUNCTION__, res);
+ return false;
+ }
+ }
+ mCurrentRequest.frameNumber = mInFlightQueue.begin()->frameNumber;
+ mCurrentRequest.settings.acquire(mInFlightQueue.begin()->settings);
+ mCurrentRequest.buffers = mInFlightQueue.begin()->buffers;
+ mCurrentRequest.sensorBuffers = mInFlightQueue.begin()->sensorBuffers;
+ mInFlightQueue.erase(mInFlightQueue.begin());
+ mInFlightSignal.signal();
+ mThreadActive = true;
+ ALOGVV("%s: Beginning readout of frame %d", __FUNCTION__,
+ mCurrentRequest.frameNumber);
+ }
+
+ // Then wait for it to be delivered from the sensor
+ ALOGVV("%s: ReadoutThread: Wait for frame to be delivered from sensor",
+ __FUNCTION__);
+
+ nsecs_t captureTime;
+ bool gotFrame = mParent->mSensor->waitForNewFrame(kWaitPerLoop, &captureTime);
+ if (!gotFrame) {
+ ALOGVV("%s: ReadoutThread: Timed out waiting for sensor frame",
+ __FUNCTION__);
+ return true;
+ }
+
+ ALOGVV("Sensor done with readout for frame %d, captured at %lld ",
+ mCurrentRequest.frameNumber, captureTime);
+
+ // Check if we need to JPEG encode a buffer, and send it for async
+ // compression if so. Otherwise prepare the buffer for return.
+ bool needJpeg = false;
+ HalBufferVector::iterator buf = mCurrentRequest.buffers->begin();
+ while (buf != mCurrentRequest.buffers->end()) {
+ bool goodBuffer = true;
+ if (buf->stream->format == HAL_PIXEL_FORMAT_BLOB &&
+ buf->stream->data_space != HAL_DATASPACE_DEPTH) {
+ Mutex::Autolock jl(mJpegLock);
+ if (mJpegWaiting) {
+ // This shouldn't happen, because processCaptureRequest should
+ // be stalling until JPEG compressor is free.
+ ALOGE("%s: Already processing a JPEG!", __FUNCTION__);
+ goodBuffer = false;
+ }
+ if (goodBuffer) {
+ // Compressor takes ownership of sensorBuffers here
+ res = mParent->mJpegCompressor->start(mCurrentRequest.sensorBuffers,
+ this);
+ goodBuffer = (res == OK);
+ }
+ if (goodBuffer) {
+ needJpeg = true;
+
+ mJpegHalBuffer = *buf;
+ mJpegFrameNumber = mCurrentRequest.frameNumber;
+ mJpegWaiting = true;
+
+ mCurrentRequest.sensorBuffers = NULL;
+ buf = mCurrentRequest.buffers->erase(buf);
+
+ continue;
+ }
+ ALOGE("%s: Error compressing output buffer: %s (%d)", __FUNCTION__,
+ strerror(-res), res);
+ // fallthrough for cleanup
+ }
+ GrallocModule::getInstance().unlock(*(buf->buffer));
+
+ buf->status =
+ goodBuffer ? CAMERA3_BUFFER_STATUS_OK : CAMERA3_BUFFER_STATUS_ERROR;
+ buf->acquire_fence = -1;
+ buf->release_fence = -1;
+
+ ++buf;
+ } // end while
+
+ // Construct result for all completed buffers and results
+
+ camera3_capture_result result;
+
+ if (mParent->hasCapability(BACKWARD_COMPATIBLE)) {
+ static const uint8_t sceneFlicker = ANDROID_STATISTICS_SCENE_FLICKER_NONE;
+ mCurrentRequest.settings.update(ANDROID_STATISTICS_SCENE_FLICKER,
+ &sceneFlicker, 1);
+
+ static const uint8_t flashState = ANDROID_FLASH_STATE_UNAVAILABLE;
+ mCurrentRequest.settings.update(ANDROID_FLASH_STATE, &flashState, 1);
+
+ nsecs_t rollingShutterSkew = Sensor::kFrameDurationRange[0];
+ mCurrentRequest.settings.update(ANDROID_SENSOR_ROLLING_SHUTTER_SKEW,
+ &rollingShutterSkew, 1);
+
+ float focusRange[] = {1.0f / 5.0f, 0}; // 5 m to infinity in focus
+ mCurrentRequest.settings.update(ANDROID_LENS_FOCUS_RANGE, focusRange,
+ sizeof(focusRange) / sizeof(float));
+ }
+
+ if (mParent->hasCapability(DEPTH_OUTPUT)) {
+ camera_metadata_entry_t entry;
+
+ find_camera_metadata_entry(mParent->mCameraInfo,
+ ANDROID_LENS_POSE_TRANSLATION, &entry);
+ mCurrentRequest.settings.update(ANDROID_LENS_POSE_TRANSLATION, entry.data.f,
+ entry.count);
+
+ find_camera_metadata_entry(mParent->mCameraInfo, ANDROID_LENS_POSE_ROTATION,
+ &entry);
+ mCurrentRequest.settings.update(ANDROID_LENS_POSE_ROTATION, entry.data.f,
+ entry.count);
+
+ find_camera_metadata_entry(mParent->mCameraInfo,
+ ANDROID_LENS_INTRINSIC_CALIBRATION, &entry);
+ mCurrentRequest.settings.update(ANDROID_LENS_INTRINSIC_CALIBRATION,
+ entry.data.f, entry.count);
+
+ find_camera_metadata_entry(mParent->mCameraInfo,
+ ANDROID_LENS_RADIAL_DISTORTION, &entry);
+ mCurrentRequest.settings.update(ANDROID_LENS_RADIAL_DISTORTION,
+ entry.data.f, entry.count);
+ }
+
+ mCurrentRequest.settings.update(ANDROID_SENSOR_TIMESTAMP, &captureTime, 1);
+
+ // JPEGs take a stage longer
+ const uint8_t pipelineDepth =
+ needJpeg ? kMaxBufferCount : kMaxBufferCount - 1;
+ mCurrentRequest.settings.update(ANDROID_REQUEST_PIPELINE_DEPTH,
+ &pipelineDepth, 1);
+
+ result.frame_number = mCurrentRequest.frameNumber;
+ result.result = mCurrentRequest.settings.getAndLock();
+ result.num_output_buffers = mCurrentRequest.buffers->size();
+ result.output_buffers = mCurrentRequest.buffers->array();
+ result.input_buffer = nullptr;
+ result.partial_result = 1;
+
+ // Go idle if queue is empty, before sending result
+ bool signalIdle = false;
+ {
+ Mutex::Autolock l(mLock);
+ if (mInFlightQueue.empty()) {
+ mThreadActive = false;
+ signalIdle = true;
+ }
+ }
+ if (signalIdle) mParent->signalReadoutIdle();
+
+ // Send it off to the framework
+ ALOGVV("%s: ReadoutThread: Send result to framework", __FUNCTION__);
+ mParent->sendCaptureResult(&result);
+
+ // Clean up
+ mCurrentRequest.settings.unlock(result.result);
+
+ delete mCurrentRequest.buffers;
+ mCurrentRequest.buffers = NULL;
+ if (!needJpeg) {
+ delete mCurrentRequest.sensorBuffers;
+ mCurrentRequest.sensorBuffers = NULL;
+ }
+ mCurrentRequest.settings.clear();
+
+ return true;
+}
+
+void EmulatedFakeCamera3::ReadoutThread::onJpegDone(
+ const StreamBuffer &jpegBuffer, bool success) {
+ Mutex::Autolock jl(mJpegLock);
+
+ GrallocModule::getInstance().unlock(*(jpegBuffer.buffer));
+
+ mJpegHalBuffer.status =
+ success ? CAMERA3_BUFFER_STATUS_OK : CAMERA3_BUFFER_STATUS_ERROR;
+ mJpegHalBuffer.acquire_fence = -1;
+ mJpegHalBuffer.release_fence = -1;
+ mJpegWaiting = false;
+
+ camera3_capture_result result;
+
+ result.frame_number = mJpegFrameNumber;
+ result.result = NULL;
+ result.num_output_buffers = 1;
+ result.output_buffers = &mJpegHalBuffer;
+ result.input_buffer = nullptr;
+ result.partial_result = 0;
+
+ if (!success) {
+ ALOGE(
+ "%s: Compression failure, returning error state buffer to"
+ " framework",
+ __FUNCTION__);
+ } else {
+ ALOGV("%s: Compression complete, returning buffer to framework",
+ __FUNCTION__);
+ }
+
+ mParent->sendCaptureResult(&result);
+}
+
+void EmulatedFakeCamera3::ReadoutThread::onJpegInputDone(
+ const StreamBuffer & /*inputBuffer*/) {
+ // Should never get here, since the input buffer has to be returned
+ // by end of processCaptureRequest
+ ALOGE("%s: Unexpected input buffer from JPEG compressor!", __FUNCTION__);
+}
+
+}; // namespace android
diff --git a/guest/hals/camera/EmulatedFakeCamera3.h b/guest/hals/camera/EmulatedFakeCamera3.h
new file mode 100644
index 000000000..d67662aea
--- /dev/null
+++ b/guest/hals/camera/EmulatedFakeCamera3.h
@@ -0,0 +1,289 @@
+/*
+ * Copyright (C) 2013 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 HW_EMULATOR_CAMERA_EMULATED_FAKE_CAMERA3_H
+#define HW_EMULATOR_CAMERA_EMULATED_FAKE_CAMERA3_H
+
+/**
+ * Contains declaration of a class EmulatedCamera that encapsulates
+ * functionality of a fake camera that implements version 3 of the camera device
+ * interace.
+ */
+
+#include <CameraMetadata.h>
+using ::android::hardware::camera::common::V1_0::helper::CameraMetadata;
+
+#include <utils/List.h>
+#include <utils/Mutex.h>
+#include <utils/SortedVector.h>
+#include "EmulatedCamera3.h"
+#include "fake-pipeline2/Base.h"
+#include "fake-pipeline2/JpegCompressor.h"
+#include "fake-pipeline2/Sensor.h"
+
+namespace android {
+
+/**
+ * Encapsulates functionality for a v3 HAL camera which produces synthetic data.
+ *
+ * Note that EmulatedCameraFactory instantiates an object of this class just
+ * once, when EmulatedCameraFactory instance gets constructed. Connection to /
+ * disconnection from the actual camera device is handled by calls to
+ * connectDevice(), and closeCamera() methods of this class that are invoked in
+ * response to hw_module_methods_t::open, and camera_device::close callbacks.
+ */
+class EmulatedFakeCamera3 : public EmulatedCamera3,
+ private Sensor::SensorListener {
+ public:
+ EmulatedFakeCamera3(int cameraId, bool facingBack,
+ struct hw_module_t *module);
+
+ virtual ~EmulatedFakeCamera3();
+
+ /****************************************************************************
+ * EmulatedCamera3 virtual overrides
+ ***************************************************************************/
+
+ public:
+ virtual status_t Initialize(const cvd::CameraDefinition &params);
+
+ /****************************************************************************
+ * Camera module API and generic hardware device API implementation
+ ***************************************************************************/
+
+ public:
+ virtual status_t connectCamera(hw_device_t **device);
+
+ virtual status_t closeCamera();
+
+ virtual status_t getCameraInfo(struct camera_info *info);
+
+ virtual status_t setTorchMode(bool enabled);
+
+ /****************************************************************************
+ * EmulatedCamera3 abstract API implementation
+ ***************************************************************************/
+
+ protected:
+ virtual status_t configureStreams(camera3_stream_configuration *streamList);
+
+ virtual status_t registerStreamBuffers(
+ const camera3_stream_buffer_set *bufferSet);
+
+ virtual const camera_metadata_t *constructDefaultRequestSettings(int type);
+
+ virtual status_t processCaptureRequest(camera3_capture_request *request);
+
+ virtual status_t flush();
+
+ /** Debug methods */
+
+ virtual void dump(int fd);
+
+ private:
+ /**
+ * Get the requested capability set for this camera
+ */
+ status_t getCameraCapabilities();
+
+ bool hasCapability(AvailableCapabilities cap);
+
+ /**
+ * Build the static info metadata buffer for this device
+ */
+ status_t constructStaticInfo(const cvd::CameraDefinition &params);
+
+ /**
+ * Run the fake 3A algorithms as needed. May override/modify settings
+ * values.
+ */
+ status_t process3A(CameraMetadata &settings);
+
+ status_t doFakeAE(CameraMetadata &settings);
+ status_t doFakeAF(CameraMetadata &settings);
+ status_t doFakeAWB(CameraMetadata &settings);
+ void update3A(CameraMetadata &settings);
+
+ /** Signal from readout thread that it doesn't have anything to do */
+ void signalReadoutIdle();
+
+ /** Handle interrupt events from the sensor */
+ void onSensorEvent(uint32_t frameNumber, Event e, nsecs_t timestamp);
+
+ /****************************************************************************
+ * Static configuration information
+ ***************************************************************************/
+ private:
+ static const uint32_t kMaxRawStreamCount = 1;
+ static const uint32_t kMaxProcessedStreamCount = 3;
+ static const uint32_t kMaxJpegStreamCount = 1;
+ static const uint32_t kMaxReprocessStreamCount = 2;
+ static const uint32_t kMaxBufferCount = 4;
+ // We need a positive stream ID to distinguish external buffers from
+ // sensor-generated buffers which use a nonpositive ID. Otherwise, HAL3 has
+ // no concept of a stream id.
+ static const uint32_t kGenericStreamId = 1;
+ static const int32_t kAvailableFormats[];
+
+ static const int64_t kSyncWaitTimeout = 10000000; // 10 ms
+ static const int32_t kMaxSyncTimeoutCount = 1000; // 1000 kSyncWaitTimeouts
+ static const uint32_t kFenceTimeoutMs = 2000; // 2 s
+ static const nsecs_t kJpegTimeoutNs = 5000000000l; // 5 s
+
+ /****************************************************************************
+ * Data members.
+ ***************************************************************************/
+
+ /* HAL interface serialization lock. */
+ Mutex mLock;
+
+ /* Facing back (true) or front (false) switch. */
+ bool mFacingBack;
+ int32_t mSensorWidth;
+ int32_t mSensorHeight;
+
+ SortedVector<AvailableCapabilities> mCapabilities;
+
+ /**
+ * Cache for default templates. Once one is requested, the pointer must be
+ * valid at least until close() is called on the device
+ */
+ camera_metadata_t *mDefaultTemplates[CAMERA3_TEMPLATE_COUNT];
+
+ /**
+ * Private stream information, stored in camera3_stream_t->priv.
+ */
+ struct PrivateStreamInfo {
+ bool alive;
+ };
+
+ // Shortcut to the input stream
+ camera3_stream_t *mInputStream;
+
+ typedef List<camera3_stream_t *> StreamList;
+ typedef List<camera3_stream_t *>::iterator StreamIterator;
+ typedef Vector<camera3_stream_buffer> HalBufferVector;
+
+ // All streams, including input stream
+ StreamList mStreams;
+
+ // Cached settings from latest submitted request
+ CameraMetadata mPrevSettings;
+
+ /** Fake hardware interfaces */
+ sp<Sensor> mSensor;
+ sp<JpegCompressor> mJpegCompressor;
+ friend class JpegCompressor;
+
+ /** Processing thread for sending out results */
+
+ class ReadoutThread : public Thread, private JpegCompressor::JpegListener {
+ public:
+ ReadoutThread(EmulatedFakeCamera3 *parent);
+ ~ReadoutThread();
+
+ struct Request {
+ uint32_t frameNumber;
+ CameraMetadata settings;
+ HalBufferVector *buffers;
+ Buffers *sensorBuffers;
+ };
+
+ /**
+ * Interface to parent class
+ */
+
+ // Place request in the in-flight queue to wait for sensor capture
+ void queueCaptureRequest(const Request &r);
+
+ // Test if the readout thread is idle (no in-flight requests, not
+ // currently reading out anything
+ bool isIdle();
+
+ // Wait until isIdle is true
+ status_t waitForReadout();
+
+ private:
+ static const nsecs_t kWaitPerLoop = 10000000L; // 10 ms
+ static const nsecs_t kMaxWaitLoops = 1000;
+ static const size_t kMaxQueueSize = 2;
+
+ EmulatedFakeCamera3 *mParent;
+ Mutex mLock;
+
+ List<Request> mInFlightQueue;
+ Condition mInFlightSignal;
+ bool mThreadActive;
+
+ virtual bool threadLoop();
+
+ // Only accessed by threadLoop
+
+ Request mCurrentRequest;
+
+ // Jpeg completion callbacks
+
+ Mutex mJpegLock;
+ bool mJpegWaiting;
+ camera3_stream_buffer mJpegHalBuffer;
+ uint32_t mJpegFrameNumber;
+ virtual void onJpegDone(const StreamBuffer &jpegBuffer, bool success);
+ virtual void onJpegInputDone(const StreamBuffer &inputBuffer);
+ };
+
+ sp<ReadoutThread> mReadoutThread;
+
+ /** Fake 3A constants */
+
+ static const nsecs_t kNormalExposureTime;
+ static const nsecs_t kFacePriorityExposureTime;
+ static const int kNormalSensitivity;
+ static const int kFacePrioritySensitivity;
+ // Rate of converging AE to new target value, as fraction of difference
+ // between current and target value.
+ static const float kExposureTrackRate;
+ // Minimum duration for precapture state. May be longer if slow to converge
+ // to target exposure
+ static const int kPrecaptureMinFrames;
+ // How often to restart AE 'scanning'
+ static const int kStableAeMaxFrames;
+ // Maximum stop below 'normal' exposure time that we'll wander to while
+ // pretending to converge AE. In powers of 2. (-2 == 1/4 as bright)
+ static const float kExposureWanderMin;
+ // Maximum stop above 'normal' exposure time that we'll wander to while
+ // pretending to converge AE. In powers of 2. (2 == 4x as bright)
+ static const float kExposureWanderMax;
+
+ /** Fake 3A state */
+
+ uint8_t mControlMode;
+ bool mFacePriority;
+ uint8_t mAeState;
+ uint8_t mAfState;
+ uint8_t mAwbState;
+ uint8_t mAeMode;
+ uint8_t mAfMode;
+ uint8_t mAwbMode;
+
+ int mAeCounter;
+ nsecs_t mAeCurrentExposureTime;
+ nsecs_t mAeTargetExposureTime;
+ int mAeCurrentSensitivity;
+};
+
+} // namespace android
+
+#endif // HW_EMULATOR_CAMERA_EMULATED_CAMERA3_H
diff --git a/guest/hals/camera/EmulatedFakeCameraDevice.cpp b/guest/hals/camera/EmulatedFakeCameraDevice.cpp
new file mode 100644
index 000000000..a354e690d
--- /dev/null
+++ b/guest/hals/camera/EmulatedFakeCameraDevice.cpp
@@ -0,0 +1,427 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+/*
+ * Contains implementation of a class EmulatedFakeCameraDevice that encapsulates
+ * fake camera device.
+ */
+
+#define LOG_NDEBUG 0
+#define LOG_TAG "EmulatedCamera_FakeDevice"
+#include "EmulatedFakeCameraDevice.h"
+#include <log/log.h>
+#include "EmulatedFakeCamera.h"
+
+namespace android {
+
+EmulatedFakeCameraDevice::EmulatedFakeCameraDevice(
+ EmulatedFakeCamera* camera_hal)
+ : EmulatedCameraDevice(camera_hal),
+ mBlackYUV(kBlack32),
+ mWhiteYUV(kWhite32),
+ mRedYUV(kRed8),
+ mGreenYUV(kGreen8),
+ mBlueYUV(kBlue8),
+ mLastRedrawn(0),
+ mCheckX(0),
+ mCheckY(0),
+ mCcounter(0)
+#if EFCD_ROTATE_FRAME
+ ,
+ mLastRotatedAt(0),
+ mCurrentFrameType(0),
+ mCurrentColor(&mWhiteYUV)
+#endif // EFCD_ROTATE_FRAME
+{
+ // Makes the image with the original exposure compensation darker.
+ // So the effects of changing the exposure compensation can be seen.
+ mBlackYUV.Y = mBlackYUV.Y / 2;
+ mWhiteYUV.Y = mWhiteYUV.Y / 2;
+ mRedYUV.Y = mRedYUV.Y / 2;
+ mGreenYUV.Y = mGreenYUV.Y / 2;
+ mBlueYUV.Y = mBlueYUV.Y / 2;
+}
+
+EmulatedFakeCameraDevice::~EmulatedFakeCameraDevice() {}
+
+/****************************************************************************
+ * Emulated camera device abstract interface implementation.
+ ***************************************************************************/
+
+status_t EmulatedFakeCameraDevice::connectDevice() {
+ ALOGV("%s", __FUNCTION__);
+
+ Mutex::Autolock locker(&mObjectLock);
+ if (!isInitialized()) {
+ ALOGE("%s: Fake camera device is not initialized.", __FUNCTION__);
+ return EINVAL;
+ }
+ if (isConnected()) {
+ ALOGW("%s: Fake camera device is already connected.", __FUNCTION__);
+ return NO_ERROR;
+ }
+
+ /* There is no device to connect to. */
+ mState = ECDS_CONNECTED;
+
+ return NO_ERROR;
+}
+
+status_t EmulatedFakeCameraDevice::disconnectDevice() {
+ ALOGV("%s", __FUNCTION__);
+
+ Mutex::Autolock locker(&mObjectLock);
+ if (!isConnected()) {
+ ALOGW("%s: Fake camera device is already disconnected.", __FUNCTION__);
+ return NO_ERROR;
+ }
+ if (isStarted()) {
+ ALOGE("%s: Cannot disconnect from the started device.", __FUNCTION__);
+ return EINVAL;
+ }
+
+ /* There is no device to disconnect from. */
+ mState = ECDS_INITIALIZED;
+
+ return NO_ERROR;
+}
+
+status_t EmulatedFakeCameraDevice::startDevice(int width, int height,
+ uint32_t pix_fmt, int fps) {
+ ALOGV("%s", __FUNCTION__);
+
+ Mutex::Autolock locker(&mObjectLock);
+ if (!isConnected()) {
+ ALOGE("%s: Fake camera device is not connected.", __FUNCTION__);
+ return EINVAL;
+ }
+ if (isStarted()) {
+ ALOGE("%s: Fake camera device is already started.", __FUNCTION__);
+ return EINVAL;
+ }
+
+ /* Initialize the base class. */
+ const status_t res =
+ EmulatedCameraDevice::commonStartDevice(width, height, pix_fmt, fps);
+ if (res == NO_ERROR) {
+ /* Calculate U/V panes inside the framebuffer. */
+ switch (mPixelFormat) {
+ case V4L2_PIX_FMT_YVU420:
+ mFrameV = mCurrentFrame + mTotalPixels;
+ mFrameU = mFrameU + mTotalPixels / 4;
+ mUVStep = 1;
+ mUVTotalNum = mTotalPixels / 4;
+ break;
+
+ case V4L2_PIX_FMT_YUV420:
+ mFrameU = mCurrentFrame + mTotalPixels;
+ mFrameV = mFrameU + mTotalPixels / 4;
+ mUVStep = 1;
+ mUVTotalNum = mTotalPixels / 4;
+ break;
+
+ case V4L2_PIX_FMT_NV21:
+ /* Interleaved UV pane, V first. */
+ mFrameV = mCurrentFrame + mTotalPixels;
+ mFrameU = mFrameV + 1;
+ mUVStep = 2;
+ mUVTotalNum = mTotalPixels / 4;
+ break;
+
+ case V4L2_PIX_FMT_NV12:
+ /* Interleaved UV pane, U first. */
+ mFrameU = mCurrentFrame + mTotalPixels;
+ mFrameV = mFrameU + 1;
+ mUVStep = 2;
+ mUVTotalNum = mTotalPixels / 4;
+ break;
+
+ default:
+ ALOGE("%s: Unknown pixel format %.4s", __FUNCTION__,
+ reinterpret_cast<const char*>(&mPixelFormat));
+ return EINVAL;
+ }
+ /* Number of items in a single row inside U/V panes. */
+ mUVInRow = (width / 2) * mUVStep;
+ mState = ECDS_STARTED;
+ mCurFrameTimestamp = 0;
+ } else {
+ ALOGE("%s: commonStartDevice failed", __FUNCTION__);
+ }
+
+ return res;
+}
+
+status_t EmulatedFakeCameraDevice::stopDevice() {
+ ALOGV("%s", __FUNCTION__);
+
+ Mutex::Autolock locker(&mObjectLock);
+ if (!isStarted()) {
+ ALOGW("%s: Fake camera device is not started.", __FUNCTION__);
+ return NO_ERROR;
+ }
+
+ mFrameU = mFrameV = NULL;
+ EmulatedCameraDevice::commonStopDevice();
+ mState = ECDS_CONNECTED;
+
+ return NO_ERROR;
+}
+
+/****************************************************************************
+ * Worker thread management overrides.
+ ***************************************************************************/
+
+bool EmulatedFakeCameraDevice::inWorkerThread() {
+ /* Wait till FPS timeout expires, or thread exit message is received. */
+ WorkerThread::SelectRes res =
+ getWorkerThread()->Select(-1, 1000000 / (mTargetFps / 1000));
+ if (res == WorkerThread::EXIT_THREAD) {
+ ALOGV("%s: Worker thread has been terminated.", __FUNCTION__);
+ return false;
+ }
+
+ /* Lets see if we need to generate a new frame. */
+ if ((systemTime(SYSTEM_TIME_MONOTONIC) - mLastRedrawn) >= mRedrawAfter) {
+ /*
+ * Time to generate a new frame.
+ */
+
+#if EFCD_ROTATE_FRAME
+ const int frame_type = rotateFrame();
+ switch (frame_type) {
+ case 0:
+ drawCheckerboard();
+ break;
+ case 1:
+ drawStripes();
+ break;
+ case 2:
+ drawSolid(mCurrentColor);
+ break;
+ }
+#else
+ /* Draw the checker board. */
+ drawCheckerboard();
+
+#endif // EFCD_ROTATE_FRAME
+
+ // mCurFrameTimestamp = systemTime(SYSTEM_TIME_MONOTONIC);
+ mCurFrameTimestamp += (1000000000 / (mTargetFps / 1000));
+ /* Timestamp the current frame, and notify the camera HAL about new frame.
+ */
+ mLastRedrawn = systemTime(SYSTEM_TIME_MONOTONIC);
+ mCameraHAL->onNextFrameAvailable(mCurrentFrame, mCurFrameTimestamp, this);
+ }
+
+ return true;
+}
+
+/****************************************************************************
+ * Fake camera device private API
+ ***************************************************************************/
+
+void EmulatedFakeCameraDevice::drawCheckerboard() {
+ const int size = mFrameWidth / 10;
+ bool black = true;
+
+ if (size == 0) {
+ // When this happens, it happens at a very high rate,
+ // so don't log any messages and just return.
+ return;
+ }
+
+ if ((mCheckX / size) & 1) black = false;
+ if ((mCheckY / size) & 1) black = !black;
+
+ int county = mCheckY % size;
+ int checkxremainder = mCheckX % size;
+ uint8_t* Y = mCurrentFrame;
+ uint8_t* U_pos = mFrameU;
+ uint8_t* V_pos = mFrameV;
+ uint8_t* U = U_pos;
+ uint8_t* V = V_pos;
+
+ YUVPixel adjustedWhite = YUVPixel(mWhiteYUV);
+ changeWhiteBalance(adjustedWhite.Y, adjustedWhite.U, adjustedWhite.V);
+
+ for (int y = 0; y < mFrameHeight; y++) {
+ int countx = checkxremainder;
+ bool current = black;
+ for (int x = 0; x < mFrameWidth; x += 2) {
+ if (current) {
+ mBlackYUV.get(Y, U, V);
+ } else {
+ adjustedWhite.get(Y, U, V);
+ }
+ *Y = changeExposure(*Y);
+ Y[1] = *Y;
+ Y += 2;
+ U += mUVStep;
+ V += mUVStep;
+ countx += 2;
+ if (countx >= size) {
+ countx = 0;
+ current = !current;
+ }
+ }
+ if (y & 0x1) {
+ U_pos = U;
+ V_pos = V;
+ } else {
+ U = U_pos;
+ V = V_pos;
+ }
+ if (county++ >= size) {
+ county = 0;
+ black = !black;
+ }
+ }
+ mCheckX += 3;
+ mCheckY++;
+
+ /* Run the square. */
+ int sqx = ((mCcounter * 3) & 255);
+ if (sqx > 128) sqx = 255 - sqx;
+ int sqy = ((mCcounter * 5) & 255);
+ if (sqy > 128) sqy = 255 - sqy;
+ const int sqsize = mFrameWidth / 10;
+ drawSquare(sqx * sqsize / 32, sqy * sqsize / 32, (sqsize * 5) >> 1,
+ (mCcounter & 0x100) ? &mRedYUV : &mGreenYUV);
+ mCcounter++;
+}
+
+void EmulatedFakeCameraDevice::drawSquare(int x, int y, int size,
+ const YUVPixel* color) {
+ const int square_xstop = std::min(mFrameWidth, x + size);
+ const int square_ystop = std::min(mFrameHeight, y + size);
+ uint8_t* Y_pos = mCurrentFrame + y * mFrameWidth + x;
+
+ YUVPixel adjustedColor = *color;
+ changeWhiteBalance(adjustedColor.Y, adjustedColor.U, adjustedColor.V);
+
+ // Draw the square.
+ for (; y < square_ystop; y++) {
+ const int iUV = (y / 2) * mUVInRow + (x / 2) * mUVStep;
+ uint8_t* sqU = mFrameU + iUV;
+ uint8_t* sqV = mFrameV + iUV;
+ uint8_t* sqY = Y_pos;
+ for (int i = x; i < square_xstop; i += 2) {
+ adjustedColor.get(sqY, sqU, sqV);
+ *sqY = changeExposure(*sqY);
+ sqY[1] = *sqY;
+ sqY += 2;
+ sqU += mUVStep;
+ sqV += mUVStep;
+ }
+ Y_pos += mFrameWidth;
+ }
+}
+
+#if EFCD_ROTATE_FRAME
+
+void EmulatedFakeCameraDevice::drawSolid(YUVPixel* color) {
+ YUVPixel adjustedColor = *color;
+ changeWhiteBalance(adjustedColor.Y, adjustedColor.U, adjustedColor.V);
+
+ /* All Ys are the same. */
+ memset(mCurrentFrame, changeExposure(adjustedColor.Y), mTotalPixels);
+
+ /* Fill U, and V panes. */
+ uint8_t* U = mFrameU;
+ uint8_t* V = mFrameV;
+ for (int k = 0; k < mUVTotalNum; k++, U += mUVStep, V += mUVStep) {
+ *U = color->U;
+ *V = color->V;
+ }
+}
+
+void EmulatedFakeCameraDevice::drawStripes() {
+ /* Divide frame into 4 stripes. */
+ const int change_color_at = mFrameHeight / 4;
+ const int each_in_row = mUVInRow / mUVStep;
+ uint8_t* pY = mCurrentFrame;
+ for (int y = 0; y < mFrameHeight; y++, pY += mFrameWidth) {
+ /* Select the color. */
+ YUVPixel* color;
+ const int color_index = y / change_color_at;
+ if (color_index == 0) {
+ /* White stripe on top. */
+ color = &mWhiteYUV;
+ } else if (color_index == 1) {
+ /* Then the red stripe. */
+ color = &mRedYUV;
+ } else if (color_index == 2) {
+ /* Then the green stripe. */
+ color = &mGreenYUV;
+ } else {
+ /* And the blue stripe at the bottom. */
+ color = &mBlueYUV;
+ }
+ changeWhiteBalance(color->Y, color->U, color->V);
+
+ /* All Ys at the row are the same. */
+ memset(pY, changeExposure(color->Y), mFrameWidth);
+
+ /* Offset of the current row inside U/V panes. */
+ const int uv_off = (y / 2) * mUVInRow;
+ /* Fill U, and V panes. */
+ uint8_t* U = mFrameU + uv_off;
+ uint8_t* V = mFrameV + uv_off;
+ for (int k = 0; k < each_in_row; k++, U += mUVStep, V += mUVStep) {
+ *U = color->U;
+ *V = color->V;
+ }
+ }
+}
+
+int EmulatedFakeCameraDevice::rotateFrame() {
+ if ((systemTime(SYSTEM_TIME_MONOTONIC) - mLastRotatedAt) >= mRotateFreq) {
+ mLastRotatedAt = systemTime(SYSTEM_TIME_MONOTONIC);
+ mCurrentFrameType++;
+ if (mCurrentFrameType > 2) {
+ mCurrentFrameType = 0;
+ }
+ if (mCurrentFrameType == 2) {
+ ALOGD("********** Rotated to the SOLID COLOR frame **********");
+ /* Solid color: lets rotate color too. */
+ if (mCurrentColor == &mWhiteYUV) {
+ ALOGD("----- Painting a solid RED frame -----");
+ mCurrentColor = &mRedYUV;
+ } else if (mCurrentColor == &mRedYUV) {
+ ALOGD("----- Painting a solid GREEN frame -----");
+ mCurrentColor = &mGreenYUV;
+ } else if (mCurrentColor == &mGreenYUV) {
+ ALOGD("----- Painting a solid BLUE frame -----");
+ mCurrentColor = &mBlueYUV;
+ } else {
+ /* Back to white. */
+ ALOGD("----- Painting a solid WHITE frame -----");
+ mCurrentColor = &mWhiteYUV;
+ }
+ } else if (mCurrentFrameType == 0) {
+ ALOGD("********** Rotated to the CHECKERBOARD frame **********");
+ } else if (mCurrentFrameType == 1) {
+ ALOGD("********** Rotated to the STRIPED frame **********");
+ }
+ }
+
+ return mCurrentFrameType;
+}
+
+#endif // EFCD_ROTATE_FRAME
+
+}; /* namespace android */
diff --git a/guest/hals/camera/EmulatedFakeCameraDevice.h b/guest/hals/camera/EmulatedFakeCameraDevice.h
new file mode 100644
index 000000000..096d1bc5f
--- /dev/null
+++ b/guest/hals/camera/EmulatedFakeCameraDevice.h
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2011 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 HW_EMULATOR_CAMERA_EMULATED_FAKE_CAMERA_DEVICE_H
+#define HW_EMULATOR_CAMERA_EMULATED_FAKE_CAMERA_DEVICE_H
+
+/*
+ * Contains declaration of a class EmulatedFakeCameraDevice that encapsulates
+ * a fake camera device.
+ */
+
+#include "Converters.h"
+#include "EmulatedCameraDevice.h"
+
+/* This is used for debugging format / conversion issues. If EFCD_ROTATE_FRAME
+ * is set to 0, the frame content will be always the "checkerboard". Otherwise,
+ * if EFCD_ROTATE_FRAME is set to a non-zero value, the frame content will
+ * "rotate" from a "checkerboard" frame to a "white/red/green/blue stripes"
+ * frame, to a "white/red/green/blue" frame. Frame content rotation helps
+ * finding bugs in format conversions.
+ */
+#define EFCD_ROTATE_FRAME 0
+
+namespace android {
+
+class EmulatedFakeCamera;
+
+/* Encapsulates a fake camera device.
+ * Fake camera device emulates a camera device by providing frames containing
+ * a black and white checker board, moving diagonally towards the 0,0 corner.
+ * There is also a green, or red square that bounces inside the frame, changing
+ * its color when bouncing off the 0,0 corner.
+ */
+class EmulatedFakeCameraDevice : public EmulatedCameraDevice {
+ public:
+ /* Constructs EmulatedFakeCameraDevice instance. */
+ explicit EmulatedFakeCameraDevice(EmulatedFakeCamera* camera_hal);
+
+ /* Destructs EmulatedFakeCameraDevice instance. */
+ ~EmulatedFakeCameraDevice();
+
+ /***************************************************************************
+ * Emulated camera device abstract interface implementation.
+ * See declarations of these methods in EmulatedCameraDevice class for
+ * information on each of these methods.
+ **************************************************************************/
+
+ public:
+ /* Connects to the camera device.
+ * Since there is no real device to connect to, this method does nothing,
+ * but changes the state.
+ */
+ status_t connectDevice();
+
+ /* Disconnects from the camera device.
+ * Since there is no real device to disconnect from, this method does
+ * nothing, but changes the state.
+ */
+ status_t disconnectDevice();
+
+ /* Starts the camera device. */
+ status_t startDevice(int width, int height, uint32_t pix_fmt, int fps);
+
+ /* Stops the camera device. */
+ status_t stopDevice();
+
+ /* Gets current preview fame into provided buffer. */
+ status_t getPreviewFrame(void* /*buffer*/) { return OK; }
+
+ /***************************************************************************
+ * Worker thread management overrides.
+ * See declarations of these methods in EmulatedCameraDevice class for
+ * information on each of these methods.
+ **************************************************************************/
+
+ protected:
+ /* Implementation of the worker thread routine.
+ * This method simply sleeps for a period of time defined by the FPS property
+ * of the fake camera (simulating frame frequency), and then calls emulated
+ * camera's onNextFrameAvailable method.
+ */
+ bool inWorkerThread();
+
+ /****************************************************************************
+ * Fake camera device private API
+ ***************************************************************************/
+
+ private:
+ /* Draws a black and white checker board in the current frame buffer. */
+ void drawCheckerboard();
+
+ /* Draws a square of the given color in the current frame buffer.
+ * Param:
+ * x, y - Coordinates of the top left corner of the square in the buffer.
+ * size - Size of the square's side.
+ * color - Square's color.
+ */
+ void drawSquare(int x, int y, int size, const YUVPixel* color);
+
+#if EFCD_ROTATE_FRAME
+ void drawSolid(YUVPixel* color);
+ void drawStripes();
+ int rotateFrame();
+#endif // EFCD_ROTATE_FRAME
+
+ /****************************************************************************
+ * Fake camera device data members
+ ***************************************************************************/
+
+ private:
+ /*
+ * Pixel colors in YUV format used when drawing the checker board.
+ */
+
+ YUVPixel mBlackYUV;
+ YUVPixel mWhiteYUV;
+ YUVPixel mRedYUV;
+ YUVPixel mGreenYUV;
+ YUVPixel mBlueYUV;
+
+ /* Last time the frame has been redrawn. */
+ nsecs_t mLastRedrawn;
+
+ /*
+ * Precalculated values related to U/V panes.
+ */
+
+ /* U pane inside the framebuffer. */
+ uint8_t* mFrameU;
+
+ /* V pane inside the framebuffer. */
+ uint8_t* mFrameV;
+
+ /* Defines byte distance between adjacent U, and V values. */
+ int mUVStep;
+
+ /* Defines number of Us and Vs in a row inside the U/V panes.
+ * Note that if U/V panes are interleaved, this value reflects the total
+ * number of both, Us and Vs in a single row in the interleaved UV pane. */
+ int mUVInRow;
+
+ /* Total number of each, U, and V elements in the framebuffer. */
+ int mUVTotalNum;
+
+ /*
+ * Checkerboard drawing related stuff
+ */
+
+ int mCheckX;
+ int mCheckY;
+ int mCcounter;
+
+ /* Defines time (in nanoseconds) between redrawing the checker board.
+ * We will redraw the checker board every 15 milliseconds. */
+ static const nsecs_t mRedrawAfter = 15000000LL;
+
+#if EFCD_ROTATE_FRAME
+ /* Frame rotation frequency in nanosec (currently - 3 sec) */
+ static const nsecs_t mRotateFreq = 3000000000LL;
+
+ /* Last time the frame has rotated. */
+ nsecs_t mLastRotatedAt;
+
+ /* Type of the frame to display in the current rotation:
+ * 0 - Checkerboard.
+ * 1 - White/Red/Green/Blue horisontal stripes
+ * 2 - Solid color. */
+ int mCurrentFrameType;
+
+ /* Color to use to paint the solid color frame. Colors will rotate between
+ * white, red, gree, and blue each time rotation comes to the solid color
+ * frame. */
+ YUVPixel* mCurrentColor;
+#endif // EFCD_ROTATE_FRAME
+};
+
+}; /* namespace android */
+
+#endif /* HW_EMULATOR_CAMERA_EMULATED_FAKE_CAMERA_DEVICE_H */
diff --git a/guest/hals/camera/EmulatedQemuCamera.cpp b/guest/hals/camera/EmulatedQemuCamera.cpp
new file mode 100644
index 000000000..99c4797ee
--- /dev/null
+++ b/guest/hals/camera/EmulatedQemuCamera.cpp
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+/*
+ * Contains implementation of a class EmulatedQemuCamera that encapsulates
+ * functionality of an emulated camera connected to the host.
+ */
+
+#define LOG_NDEBUG 0
+#define LOG_TAG "EmulatedCamera_QemuCamera"
+#include "EmulatedQemuCamera.h"
+#include <log/log.h>
+#include "EmulatedCameraFactory.h"
+
+namespace android {
+
+EmulatedQemuCamera::EmulatedQemuCamera(int cameraId, struct hw_module_t* module)
+ : EmulatedCamera(cameraId, module), mQemuCameraDevice(this) {}
+
+EmulatedQemuCamera::~EmulatedQemuCamera() {}
+
+/****************************************************************************
+ * EmulatedCamera virtual overrides.
+ ***************************************************************************/
+
+status_t EmulatedQemuCamera::Initialize(const char* device_name,
+ const char* frame_dims,
+ const char* facing_dir) {
+ ALOGV("%s:\n Name=%s\n Facing '%s'\n Dimensions=%s", __FUNCTION__,
+ device_name, facing_dir, frame_dims);
+ /* Save dimensions. */
+ mFrameDims = frame_dims;
+
+ /* Initialize camera device. */
+ status_t res = mQemuCameraDevice.Initialize(device_name);
+ if (res != NO_ERROR) {
+ return res;
+ }
+
+ /* Initialize base class. */
+ res = EmulatedCamera::Initialize();
+ if (res != NO_ERROR) {
+ return res;
+ }
+
+ /*
+ * Set customizable parameters.
+ */
+
+ mParameters.set(EmulatedCamera::FACING_KEY, facing_dir);
+ mParameters.set(EmulatedCamera::ORIENTATION_KEY,
+ gEmulatedCameraFactory.getQemuCameraOrientation());
+ mParameters.set(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES, frame_dims);
+ mParameters.set(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES, frame_dims);
+
+ /*
+ * Use first dimension reported by the device to set current preview and
+ * picture sizes.
+ */
+
+ char first_dim[128];
+ /* Dimensions are separated with ',' */
+ const char* c = strchr(frame_dims, ',');
+ if (c == NULL) {
+ strncpy(first_dim, frame_dims, sizeof(first_dim));
+ first_dim[sizeof(first_dim) - 1] = '\0';
+ } else if (static_cast<size_t>(c - frame_dims) < sizeof(first_dim)) {
+ memcpy(first_dim, frame_dims, c - frame_dims);
+ first_dim[c - frame_dims] = '\0';
+ } else {
+ memcpy(first_dim, frame_dims, sizeof(first_dim));
+ first_dim[sizeof(first_dim) - 1] = '\0';
+ }
+
+ /* Width and height are separated with 'x' */
+ char* sep = strchr(first_dim, 'x');
+ if (sep == NULL) {
+ ALOGE("%s: Invalid first dimension format in %s", __FUNCTION__, frame_dims);
+ return EINVAL;
+ }
+
+ *sep = '\0';
+ const int x = atoi(first_dim);
+ const int y = atoi(sep + 1);
+ mParameters.setPreviewSize(x, y);
+ mParameters.setPictureSize(x, y);
+
+ ALOGV("%s: Qemu camera %s is initialized. Current frame is %dx%d",
+ __FUNCTION__, device_name, x, y);
+
+ return NO_ERROR;
+}
+
+EmulatedCameraDevice* EmulatedQemuCamera::getCameraDevice() {
+ return &mQemuCameraDevice;
+}
+
+}; /* namespace android */
diff --git a/guest/hals/camera/EmulatedQemuCamera.h b/guest/hals/camera/EmulatedQemuCamera.h
new file mode 100644
index 000000000..fe063bfb7
--- /dev/null
+++ b/guest/hals/camera/EmulatedQemuCamera.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2011 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 HW_EMULATOR_CAMERA_EMULATED_QEMU_CAMERA_H
+#define HW_EMULATOR_CAMERA_EMULATED_QEMU_CAMERA_H
+
+/*
+ * Contains declaration of a class EmulatedQemuCamera that encapsulates
+ * functionality of an emulated camera connected to the host.
+ */
+
+#include "EmulatedCamera.h"
+#include "EmulatedQemuCameraDevice.h"
+
+namespace android {
+
+/* Encapsulates functionality of an emulated camera connected to the host.
+ */
+class EmulatedQemuCamera : public EmulatedCamera {
+ public:
+ /* Constructs EmulatedQemuCamera instance. */
+ EmulatedQemuCamera(int cameraId, struct hw_module_t* module);
+
+ /* Destructs EmulatedQemuCamera instance. */
+ ~EmulatedQemuCamera();
+
+ /***************************************************************************
+ * EmulatedCamera virtual overrides.
+ **************************************************************************/
+
+ public:
+ /* Initializes EmulatedQemuCamera instance. */
+ status_t Initialize(const char* device_name, const char* frame_dims,
+ const char* facing_dir);
+
+ /***************************************************************************
+ * EmulatedCamera abstract API implementation.
+ **************************************************************************/
+
+ protected:
+ /* Gets emulated camera device ised by this instance of the emulated camera.
+ */
+ EmulatedCameraDevice* getCameraDevice();
+
+ /***************************************************************************
+ * Data memebers.
+ **************************************************************************/
+
+ protected:
+ /* Contained qemu camera device object. */
+ EmulatedQemuCameraDevice mQemuCameraDevice;
+
+ /* Supported frame dimensions reported by the camera device. */
+ String8 mFrameDims;
+};
+
+}; /* namespace android */
+
+#endif /* HW_EMULATOR_CAMERA_EMULATED_QEMU_CAMERA_H */
diff --git a/guest/hals/camera/EmulatedQemuCamera2.cpp b/guest/hals/camera/EmulatedQemuCamera2.cpp
new file mode 100644
index 000000000..cf894fd1a
--- /dev/null
+++ b/guest/hals/camera/EmulatedQemuCamera2.cpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+/*
+ * Contains implementation of a class EmulatedQemuCamera2 that encapsulates
+ * functionality of a host webcam with further processing to simulate the
+ * capabilities of a v2 camera device.
+ */
+
+#define LOG_NDEBUG 0
+#define LOG_TAG "EmulatedCamera_QemuCamera2"
+#include "EmulatedQemuCamera2.h"
+#include <log/log.h>
+#include <cutils/properties.h>
+#include "EmulatedCameraFactory.h"
+
+namespace android {
+
+EmulatedQemuCamera2::EmulatedQemuCamera2(int cameraId, bool facingBack,
+ struct hw_module_t* module)
+ : EmulatedCamera2(cameraId, module), mFacingBack(facingBack) {
+ ALOGD("Constructing emulated qemu camera 2 facing %s",
+ facingBack ? "back" : "front");
+}
+
+EmulatedQemuCamera2::~EmulatedQemuCamera2() {}
+
+/****************************************************************************
+ * Public API overrides
+ ***************************************************************************/
+
+status_t EmulatedQemuCamera2::Initialize() { return NO_ERROR; }
+
+}; /* namespace android */
diff --git a/guest/hals/camera/EmulatedQemuCamera2.h b/guest/hals/camera/EmulatedQemuCamera2.h
new file mode 100644
index 000000000..7697c0ee9
--- /dev/null
+++ b/guest/hals/camera/EmulatedQemuCamera2.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2012 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 HW_EMULATOR_CAMERA_EMULATED_QEMU_CAMERA2_H
+#define HW_EMULATOR_CAMERA_EMULATED_QEMU_CAMERA2_H
+
+/*
+ * Contains declaration of a class EmulatedQemuCamera2 that encapsulates
+ * functionality of a host webcam with added processing to implement version 2
+ * of the camera device interface.
+ */
+
+#include "EmulatedCamera2.h"
+
+namespace android {
+
+/* Encapsulates functionality of an advanced fake camera based on real host
+ * camera data.
+ */
+class EmulatedQemuCamera2 : public EmulatedCamera2 {
+ public:
+ /* Constructs EmulatedFakeCamera instance. */
+ EmulatedQemuCamera2(int cameraId, bool facingBack,
+ struct hw_module_t* module);
+
+ /* Destructs EmulatedFakeCamera instance. */
+ ~EmulatedQemuCamera2();
+
+ /****************************************************************************
+ * EmulatedCamera2 virtual overrides.
+ ***************************************************************************/
+
+ public:
+ /* Initializes EmulatedQemuCamera2 instance. */
+ status_t Initialize();
+
+ /****************************************************************************
+ * EmulatedCamera abstract API implementation.
+ ***************************************************************************/
+
+ protected:
+ /****************************************************************************
+ * Data memebers.
+ ***************************************************************************/
+
+ protected:
+ /* Facing back (true) or front (false) switch. */
+ bool mFacingBack;
+};
+
+}; /* namespace android */
+
+#endif /* HW_EMULATOR_CAMERA_EMULATED_QEMU_CAMERA2_H */
diff --git a/guest/hals/camera/EmulatedQemuCameraDevice.cpp b/guest/hals/camera/EmulatedQemuCameraDevice.cpp
new file mode 100644
index 000000000..61291e8c1
--- /dev/null
+++ b/guest/hals/camera/EmulatedQemuCameraDevice.cpp
@@ -0,0 +1,251 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+/*
+ * Contains implementation of a class EmulatedQemuCameraDevice that encapsulates
+ * an emulated camera device connected to the host.
+ */
+
+#define LOG_NDEBUG 0
+#define LOG_TAG "EmulatedCamera_QemuDevice"
+#include "EmulatedQemuCameraDevice.h"
+#include <log/log.h>
+#include "EmulatedQemuCamera.h"
+
+namespace android {
+
+EmulatedQemuCameraDevice::EmulatedQemuCameraDevice(
+ EmulatedQemuCamera* camera_hal)
+ : EmulatedCameraDevice(camera_hal), mQemuClient(), mPreviewFrame(NULL) {}
+
+EmulatedQemuCameraDevice::~EmulatedQemuCameraDevice() {
+ if (mPreviewFrame != NULL) {
+ delete[] mPreviewFrame;
+ }
+}
+
+/****************************************************************************
+ * Public API
+ ***************************************************************************/
+
+status_t EmulatedQemuCameraDevice::Initialize(const char* device_name) {
+ /* Connect to the service. */
+ char connect_str[256];
+ snprintf(connect_str, sizeof(connect_str), "name=%s", device_name);
+ status_t res = mQemuClient.connectClient(connect_str);
+ if (res != NO_ERROR) {
+ return res;
+ }
+
+ /* Initialize base class. */
+ res = EmulatedCameraDevice::Initialize();
+ if (res == NO_ERROR) {
+ ALOGV("%s: Connected to the emulated camera service '%s'", __FUNCTION__,
+ device_name);
+ mDeviceName = device_name;
+ } else {
+ mQemuClient.queryDisconnect();
+ }
+
+ return res;
+}
+
+/****************************************************************************
+ * Emulated camera device abstract interface implementation.
+ ***************************************************************************/
+
+status_t EmulatedQemuCameraDevice::connectDevice() {
+ ALOGV("%s", __FUNCTION__);
+
+ Mutex::Autolock locker(&mObjectLock);
+ if (!isInitialized()) {
+ ALOGE("%s: Qemu camera device is not initialized.", __FUNCTION__);
+ return EINVAL;
+ }
+ if (isConnected()) {
+ ALOGW("%s: Qemu camera device '%s' is already connected.", __FUNCTION__,
+ (const char*)mDeviceName);
+ return NO_ERROR;
+ }
+
+ /* Connect to the camera device via emulator. */
+ const status_t res = mQemuClient.queryConnect();
+ if (res == NO_ERROR) {
+ ALOGV("%s: Connected to device '%s'", __FUNCTION__,
+ (const char*)mDeviceName);
+ mState = ECDS_CONNECTED;
+ } else {
+ ALOGE("%s: Connection to device '%s' failed", __FUNCTION__,
+ (const char*)mDeviceName);
+ }
+
+ return res;
+}
+
+status_t EmulatedQemuCameraDevice::disconnectDevice() {
+ ALOGV("%s", __FUNCTION__);
+
+ Mutex::Autolock locker(&mObjectLock);
+ if (!isConnected()) {
+ ALOGW("%s: Qemu camera device '%s' is already disconnected.", __FUNCTION__,
+ (const char*)mDeviceName);
+ return NO_ERROR;
+ }
+ if (isStarted()) {
+ ALOGE("%s: Cannot disconnect from the started device '%s.", __FUNCTION__,
+ (const char*)mDeviceName);
+ return EINVAL;
+ }
+
+ /* Disconnect from the camera device via emulator. */
+ const status_t res = mQemuClient.queryDisconnect();
+ if (res == NO_ERROR) {
+ ALOGV("%s: Disonnected from device '%s'", __FUNCTION__,
+ (const char*)mDeviceName);
+ mState = ECDS_INITIALIZED;
+ } else {
+ ALOGE("%s: Disconnection from device '%s' failed", __FUNCTION__,
+ (const char*)mDeviceName);
+ }
+
+ return res;
+}
+
+status_t EmulatedQemuCameraDevice::startDevice(int width, int height,
+ uint32_t pix_fmt, int fps) {
+ ALOGV("%s", __FUNCTION__);
+
+ Mutex::Autolock locker(&mObjectLock);
+ if (!isConnected()) {
+ ALOGE("%s: Qemu camera device '%s' is not connected.", __FUNCTION__,
+ (const char*)mDeviceName);
+ return EINVAL;
+ }
+ if (isStarted()) {
+ ALOGW("%s: Qemu camera device '%s' is already started.", __FUNCTION__,
+ (const char*)mDeviceName);
+ return NO_ERROR;
+ }
+
+ status_t res =
+ EmulatedCameraDevice::commonStartDevice(width, height, pix_fmt, fps);
+ if (res != NO_ERROR) {
+ ALOGE("%s: commonStartDevice failed", __FUNCTION__);
+ return res;
+ }
+
+ /* Allocate preview frame buffer. */
+ /* TODO: Watch out for preview format changes! At this point we implement
+ * RGB32 only.*/
+ mPreviewFrame = new uint32_t[mTotalPixels];
+ if (mPreviewFrame == NULL) {
+ ALOGE("%s: Unable to allocate %d bytes for preview frame", __FUNCTION__,
+ mTotalPixels);
+ return ENOMEM;
+ }
+
+ /* Start the actual camera device. */
+ res = mQemuClient.queryStart(mPixelFormat, mFrameWidth, mFrameHeight);
+ if (res == NO_ERROR) {
+ ALOGV("%s: Qemu camera device '%s' is started for %.4s[%dx%d] frames",
+ __FUNCTION__, (const char*)mDeviceName,
+ reinterpret_cast<const char*>(&mPixelFormat), mFrameWidth,
+ mFrameHeight);
+ mState = ECDS_STARTED;
+ } else {
+ ALOGE("%s: Unable to start device '%s' for %.4s[%dx%d] frames",
+ __FUNCTION__, (const char*)mDeviceName,
+ reinterpret_cast<const char*>(&pix_fmt), width, height);
+ }
+
+ return res;
+}
+
+status_t EmulatedQemuCameraDevice::stopDevice() {
+ ALOGV("%s", __FUNCTION__);
+
+ Mutex::Autolock locker(&mObjectLock);
+ if (!isStarted()) {
+ ALOGW("%s: Qemu camera device '%s' is not started.", __FUNCTION__,
+ (const char*)mDeviceName);
+ return NO_ERROR;
+ }
+
+ /* Stop the actual camera device. */
+ status_t res = mQemuClient.queryStop();
+ if (res == NO_ERROR) {
+ if (mPreviewFrame == NULL) {
+ delete[] mPreviewFrame;
+ mPreviewFrame = NULL;
+ }
+ EmulatedCameraDevice::commonStopDevice();
+ mState = ECDS_CONNECTED;
+ ALOGV("%s: Qemu camera device '%s' is stopped", __FUNCTION__,
+ (const char*)mDeviceName);
+ } else {
+ ALOGE("%s: Unable to stop device '%s'", __FUNCTION__,
+ (const char*)mDeviceName);
+ }
+
+ return res;
+}
+
+/****************************************************************************
+ * EmulatedCameraDevice virtual overrides
+ ***************************************************************************/
+
+status_t EmulatedQemuCameraDevice::getCurrentPreviewFrame(void* buffer) {
+ ALOGW_IF(mPreviewFrame == NULL, "%s: No preview frame", __FUNCTION__);
+ if (mPreviewFrame != NULL) {
+ memcpy(buffer, mPreviewFrame, mTotalPixels * 4);
+ return 0;
+ } else {
+ return EmulatedCameraDevice::getCurrentPreviewFrame(buffer);
+ }
+}
+
+/****************************************************************************
+ * Worker thread management overrides.
+ ***************************************************************************/
+
+bool EmulatedQemuCameraDevice::inWorkerThread() {
+ /* Wait till FPS timeout expires, or thread exit message is received. */
+ WorkerThread::SelectRes res =
+ getWorkerThread()->Select(-1, 1000000 / mEmulatedFPS);
+ if (res == WorkerThread::EXIT_THREAD) {
+ ALOGV("%s: Worker thread has been terminated.", __FUNCTION__);
+ return false;
+ }
+
+ /* Query frames from the service. */
+ status_t query_res = mQemuClient.queryFrame(
+ mCurrentFrame, mPreviewFrame, mFrameBufferSize, mTotalPixels * 4,
+ mWhiteBalanceScale[0], mWhiteBalanceScale[1], mWhiteBalanceScale[2],
+ mExposureCompensation);
+ if (query_res == NO_ERROR) {
+ /* Timestamp the current frame, and notify the camera HAL. */
+ mCurFrameTimestamp = systemTime(SYSTEM_TIME_MONOTONIC);
+ mCameraHAL->onNextFrameAvailable(mCurrentFrame, mCurFrameTimestamp, this);
+ return true;
+ } else {
+ ALOGE("%s: Unable to get current video frame: %s", __FUNCTION__,
+ strerror(query_res));
+ mCameraHAL->onCameraDeviceError(CAMERA_ERROR_SERVER_DIED);
+ return false;
+ }
+}
+
+}; /* namespace android */
diff --git a/guest/hals/camera/EmulatedQemuCameraDevice.h b/guest/hals/camera/EmulatedQemuCameraDevice.h
new file mode 100644
index 000000000..2e4770b48
--- /dev/null
+++ b/guest/hals/camera/EmulatedQemuCameraDevice.h
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2011 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 HW_EMULATOR_CAMERA_EMULATED_QEMU_CAMERA_DEVICE_H
+#define HW_EMULATOR_CAMERA_EMULATED_QEMU_CAMERA_DEVICE_H
+
+/*
+ * Contains declaration of a class EmulatedQemuCameraDevice that encapsulates
+ * an emulated camera device connected to the host.
+ */
+
+#include "EmulatedCameraDevice.h"
+#include "QemuClient.h"
+
+namespace android {
+
+class EmulatedQemuCamera;
+
+/* Encapsulates an emulated camera device connected to the host.
+ */
+class EmulatedQemuCameraDevice : public EmulatedCameraDevice {
+ public:
+ /* Constructs EmulatedQemuCameraDevice instance. */
+ explicit EmulatedQemuCameraDevice(EmulatedQemuCamera* camera_hal);
+
+ /* Destructs EmulatedQemuCameraDevice instance. */
+ ~EmulatedQemuCameraDevice();
+
+ /***************************************************************************
+ * Public API
+ **************************************************************************/
+
+ public:
+ /* Initializes EmulatedQemuCameraDevice instance.
+ * Param:
+ * device_name - Name of the camera device connected to the host. The name
+ * that is used here must have been reported by the 'factory' camera
+ * service when it listed camera devices connected to the host.
+ * Return:
+ * NO_ERROR on success, or an appropriate error status.
+ */
+ status_t Initialize(const char* device_name);
+
+ /***************************************************************************
+ * Emulated camera device abstract interface implementation.
+ * See declarations of these methods in EmulatedCameraDevice class for
+ * information on each of these methods.
+ **************************************************************************/
+
+ public:
+ /* Connects to the camera device. */
+ status_t connectDevice();
+
+ /* Disconnects from the camera device. */
+ status_t disconnectDevice();
+
+ /* Starts capturing frames from the camera device. */
+ status_t startDevice(int width, int height, uint32_t pix_fmt, int fps);
+
+ /* Stops capturing frames from the camera device. */
+ status_t stopDevice();
+
+ /***************************************************************************
+ * EmulatedCameraDevice virtual overrides
+ * See declarations of these methods in EmulatedCameraDevice class for
+ * information on each of these methods.
+ **************************************************************************/
+
+ public:
+ /* Gets current preview fame into provided buffer.
+ * We override this method in order to provide preview frames cached in this
+ * object.
+ */
+ status_t getCurrentPreviewFrame(void* buffer);
+
+ /***************************************************************************
+ * Worker thread management overrides.
+ * See declarations of these methods in EmulatedCameraDevice class for
+ * information on each of these methods.
+ **************************************************************************/
+
+ protected:
+ /* Implementation of the worker thread routine. */
+ bool inWorkerThread();
+
+ /***************************************************************************
+ * Qemu camera device data members
+ **************************************************************************/
+
+ private:
+ /* Qemu client that is used to communicate with the 'emulated camera'
+ * service, created for this instance in the emulator. */
+ CameraQemuClient mQemuClient;
+
+ /* Name of the camera device connected to the host. */
+ String8 mDeviceName;
+
+ /* Current preview framebuffer. */
+ uint32_t* mPreviewFrame;
+
+ /* Emulated FPS (frames per second).
+ * We will emulate 50 FPS. */
+ static const int mEmulatedFPS = 50;
+};
+
+}; /* namespace android */
+
+#endif /* HW_EMULATOR_CAMERA_EMULATED_QEMU_CAMERA_DEVICE_H */
diff --git a/guest/hals/camera/Exif.cpp b/guest/hals/camera/Exif.cpp
new file mode 100644
index 000000000..e57bb8c25
--- /dev/null
+++ b/guest/hals/camera/Exif.cpp
@@ -0,0 +1,413 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_NDEBUG 0
+#define LOG_TAG "EmulatedCamera_Exif"
+#include <log/log.h>
+
+#include <inttypes.h>
+#include <math.h>
+#include <stdint.h>
+
+#include <CameraParameters.h>
+
+using ::android::hardware::camera::common::V1_0::helper::CameraParameters;
+using ::android::hardware::camera::common::V1_0::helper::Size;
+
+#include "Exif.h"
+
+#include <libexif/exif-data.h>
+#include <libexif/exif-entry.h>
+#include <libexif/exif-ifd.h>
+#include <libexif/exif-tag.h>
+
+#include <string>
+#include <vector>
+
+// For GPS timestamping we want to ensure we use a 64-bit time_t, 32-bit
+// platforms have time64_t but 64-bit platforms do not.
+#if defined(__LP64__)
+#include <time.h>
+using Timestamp = time_t;
+#define TIMESTAMP_TO_TM(timestamp, tm) gmtime_r(timestamp, tm)
+#else
+#include <time64.h>
+using Timestamp = time64_t;
+#define TIMESTAMP_TO_TM(timestamp, tm) gmtime64_r(timestamp, tm)
+#endif
+
+namespace android {
+
+// A prefix that is used for tags with the "undefined" format to indicate that
+// the contents are ASCII encoded. See the user comment section of the EXIF spec
+// for more details http://www.exif.org/Exif2-2.PDF
+static const unsigned char kAsciiPrefix[] = {
+ 0x41, 0x53, 0x43, 0x49, 0x49, 0x00, 0x00, 0x00 // "ASCII\0\0\0"
+};
+
+// Remove an existing EXIF entry from |exifData| if it exists. This is useful
+// when replacing existing data, it's easier to just remove the data and
+// re-allocate it than to adjust the amount of allocated data.
+static void removeExistingEntry(ExifData* exifData, ExifIfd ifd, int tag) {
+ ExifEntry* entry = exif_content_get_entry(exifData->ifd[ifd],
+ static_cast<ExifTag>(tag));
+ if (entry) {
+ exif_content_remove_entry(exifData->ifd[ifd], entry);
+ }
+}
+
+static ExifEntry* allocateEntry(int tag,
+ ExifFormat format,
+ unsigned int numComponents) {
+ ExifMem* mem = exif_mem_new_default();
+ ExifEntry* entry = exif_entry_new_mem(mem);
+
+ unsigned int size = numComponents * exif_format_get_size(format);
+ entry->data = reinterpret_cast<unsigned char*>(exif_mem_alloc(mem, size));
+ entry->size = size;
+ entry->tag = static_cast<ExifTag>(tag);
+ entry->components = numComponents;
+ entry->format = format;
+
+ exif_mem_unref(mem);
+ return entry;
+}
+
+// Create an entry and place it in |exifData|, the entry is initialized with an
+// array of floats from |values|
+template<size_t N>
+static bool createEntry(ExifData* exifData,
+ ExifIfd ifd,
+ int tag,
+ const float (&values)[N],
+ float denominator = 1000.0) {
+ removeExistingEntry(exifData, ifd, tag);
+ ExifByteOrder byteOrder = exif_data_get_byte_order(exifData);
+ ExifEntry* entry = allocateEntry(tag, EXIF_FORMAT_RATIONAL, N);
+ exif_content_add_entry(exifData->ifd[ifd], entry);
+ unsigned int rationalSize = exif_format_get_size(EXIF_FORMAT_RATIONAL);
+ for (size_t i = 0; i < N; ++i) {
+ ExifRational rational = {
+ static_cast<uint32_t>(values[i] * denominator),
+ static_cast<uint32_t>(denominator)
+ };
+
+ exif_set_rational(&entry->data[i * rationalSize], byteOrder, rational);
+ }
+
+ // Unref entry after changing owner to the ExifData struct
+ exif_entry_unref(entry);
+ return true;
+}
+
+// Create an entry with a single float |value| in it and place it in |exifData|
+static bool createEntry(ExifData* exifData,
+ ExifIfd ifd,
+ int tag,
+ const float value,
+ float denominator = 1000.0) {
+ float values[1] = { value };
+ // Recycling functions is good for the environment
+ return createEntry(exifData, ifd, tag, values, denominator);
+}
+
+// Create an entry and place it in |exifData|, the entry contains the raw data
+// pointed to by |data| of length |size|.
+static bool createEntry(ExifData* exifData,
+ ExifIfd ifd,
+ int tag,
+ const unsigned char* data,
+ size_t size,
+ ExifFormat format = EXIF_FORMAT_UNDEFINED) {
+ removeExistingEntry(exifData, ifd, tag);
+ ExifEntry* entry = allocateEntry(tag, format, size);
+ memcpy(entry->data, data, size);
+ exif_content_add_entry(exifData->ifd[ifd], entry);
+ // Unref entry after changing owner to the ExifData struct
+ exif_entry_unref(entry);
+ return true;
+}
+
+// Create an entry and place it in |exifData|, the entry is initialized with
+// the string provided in |value|
+static bool createEntry(ExifData* exifData,
+ ExifIfd ifd,
+ int tag,
+ const char* value) {
+ unsigned int length = strlen(value) + 1;
+ const unsigned char* data = reinterpret_cast<const unsigned char*>(value);
+ return createEntry(exifData, ifd, tag, data, length, EXIF_FORMAT_ASCII);
+}
+
+// Create an entry and place it in |exifData|, the entry is initialized with a
+// single byte in |value|
+static bool createEntry(ExifData* exifData,
+ ExifIfd ifd,
+ int tag,
+ uint8_t value) {
+ return createEntry(exifData, ifd, tag, &value, 1, EXIF_FORMAT_BYTE);
+}
+
+// Create an entry and place it in |exifData|, the entry is default initialized
+// by the exif library based on |tag|
+static bool createEntry(ExifData* exifData,
+ ExifIfd ifd,
+ int tag) {
+ removeExistingEntry(exifData, ifd, tag);
+ ExifEntry* entry = exif_entry_new();
+ exif_content_add_entry(exifData->ifd[ifd], entry);
+ exif_entry_initialize(entry, static_cast<ExifTag>(tag));
+ // Unref entry after changing owner to the ExifData struct
+ exif_entry_unref(entry);
+ return true;
+}
+
+// Create an entry with a single EXIF LONG (32-bit value) and place it in
+// |exifData|.
+static bool createEntry(ExifData* exifData,
+ ExifIfd ifd,
+ int tag,
+ int value) {
+ removeExistingEntry(exifData, ifd, tag);
+ ExifByteOrder byteOrder = exif_data_get_byte_order(exifData);
+ ExifEntry* entry = allocateEntry(tag, EXIF_FORMAT_LONG, 1);
+ exif_content_add_entry(exifData->ifd[ifd], entry);
+ exif_set_long(entry->data, byteOrder, value);
+
+ // Unref entry after changing owner to the ExifData struct
+ exif_entry_unref(entry);
+ return true;
+}
+
+static bool getCameraParam(const CameraParameters& parameters,
+ const char* parameterKey,
+ const char** outValue) {
+ const char* value = parameters.get(parameterKey);
+ if (value) {
+ *outValue = value;
+ return true;
+ }
+ return false;
+}
+
+static bool getCameraParam(const CameraParameters& parameters,
+ const char* parameterKey,
+ float* outValue) {
+ const char* value = parameters.get(parameterKey);
+ if (value) {
+ *outValue = parameters.getFloat(parameterKey);
+ return true;
+ }
+ return false;
+}
+
+static bool getCameraParam(const CameraParameters& parameters,
+ const char* parameterKey,
+ int64_t* outValue) {
+ const char* value = parameters.get(parameterKey);
+ if (value) {
+ char dummy = 0;
+ // Attempt to scan an extra character and then make sure it was not
+ // scanned by checking that the return value indicates only one item.
+ // This way we fail on any trailing characters
+ if (sscanf(value, "%" SCNd64 "%c", outValue, &dummy) == 1) {
+ return true;
+ }
+ }
+ return false;
+}
+
+// Convert a GPS coordinate represented as a decimal degree value to sexagesimal
+// GPS coordinates comprised of <degrees> <minutes>' <seconds>"
+static void convertGpsCoordinate(float degrees, float (*result)[3]) {
+ float absDegrees = fabs(degrees);
+ // First value is degrees without any decimal digits
+ (*result)[0] = floor(absDegrees);
+
+ // Subtract degrees so we only have the fraction left, then multiply by
+ // 60 to get the minutes
+ float minutes = (absDegrees - (*result)[0]) * 60.0f;
+ (*result)[1] = floor(minutes);
+
+ // Same thing for seconds but here we store seconds with the fraction
+ float seconds = (minutes - (*result)[1]) * 60.0f;
+ (*result)[2] = seconds;
+}
+
+// Convert a UNIX epoch timestamp to a timestamp comprised of three floats for
+// hour, minute and second, and a date part that is represented as a string.
+static bool convertTimestampToTimeAndDate(int64_t timestamp,
+ float (*timeValues)[3],
+ std::string* date) {
+ Timestamp time = timestamp;
+ struct tm utcTime;
+ if (TIMESTAMP_TO_TM(&time, &utcTime) == nullptr) {
+ ALOGE("Could not decompose timestamp into components");
+ return false;
+ }
+ (*timeValues)[0] = utcTime.tm_hour;
+ (*timeValues)[1] = utcTime.tm_min;
+ (*timeValues)[2] = utcTime.tm_sec;
+
+ char buffer[64] = {};
+ if (strftime(buffer, sizeof(buffer), "%Y:%m:%d", &utcTime) == 0) {
+ ALOGE("Could not construct date string from timestamp");
+ return false;
+ }
+ *date = buffer;
+ return true;
+}
+
+ExifData* createExifData(const CameraParameters& params) {
+ ExifData* exifData = exif_data_new();
+
+ exif_data_set_option(exifData, EXIF_DATA_OPTION_FOLLOW_SPECIFICATION);
+ exif_data_set_data_type(exifData, EXIF_DATA_TYPE_COMPRESSED);
+ exif_data_set_byte_order(exifData, EXIF_BYTE_ORDER_INTEL);
+
+ // Create mandatory exif fields and set their default values
+ exif_data_fix(exifData);
+
+ float triplet[3];
+ float floatValue = 0.0f;
+ const char* stringValue;
+ int64_t degrees;
+
+ // Datetime, creating and initializing a datetime tag will automatically
+ // set the current date and time in the tag so just do that.
+ createEntry(exifData, EXIF_IFD_0, EXIF_TAG_DATE_TIME);
+
+ // Make and model
+ createEntry(exifData, EXIF_IFD_0, EXIF_TAG_MAKE, "Emulator-Cuttlefish");
+ createEntry(exifData, EXIF_IFD_0, EXIF_TAG_MODEL, "Emulator-Cuttlefish");
+
+ // Picture size
+ int width = -1, height = -1;
+ params.getPictureSize(&width, &height);
+ if (width >= 0 && height >= 0) {
+ createEntry(exifData, EXIF_IFD_EXIF,
+ EXIF_TAG_PIXEL_X_DIMENSION, width);
+ createEntry(exifData, EXIF_IFD_EXIF,
+ EXIF_TAG_PIXEL_Y_DIMENSION, height);
+ }
+ // Orientation
+ if (getCameraParam(params,
+ CameraParameters::KEY_ROTATION,
+ &degrees)) {
+ // Exif orientation values, please refer to
+ // http://www.exif.org/Exif2-2.PDF, Section 4.6.4-A-Orientation
+ // Or these websites:
+ // http://sylvana.net/jpegcrop/exif_orientation.html
+ // http://www.impulseadventure.com/photo/exif-orientation.html
+ enum {
+ EXIF_ROTATE_CAMERA_CW0 = 1,
+ EXIF_ROTATE_CAMERA_CW90 = 6,
+ EXIF_ROTATE_CAMERA_CW180 = 3,
+ EXIF_ROTATE_CAMERA_CW270 = 8,
+ };
+ uint16_t exifOrien = 1;
+ switch (degrees) {
+ case 0:
+ exifOrien = EXIF_ROTATE_CAMERA_CW0;
+ break;
+ case 90:
+ exifOrien = EXIF_ROTATE_CAMERA_CW90;
+ break;
+ case 180:
+ exifOrien = EXIF_ROTATE_CAMERA_CW180;
+ break;
+ case 270:
+ exifOrien = EXIF_ROTATE_CAMERA_CW270;
+ break;
+ }
+ createEntry(exifData, EXIF_IFD_0, EXIF_TAG_ORIENTATION, exifOrien);
+ }
+ // Focal length
+ if (getCameraParam(params,
+ CameraParameters::KEY_FOCAL_LENGTH,
+ &floatValue)) {
+ createEntry(exifData, EXIF_IFD_EXIF, EXIF_TAG_FOCAL_LENGTH, floatValue);
+ }
+ // GPS latitude and reference, reference indicates sign, store unsigned
+ if (getCameraParam(params,
+ CameraParameters::KEY_GPS_LATITUDE,
+ &floatValue)) {
+ convertGpsCoordinate(floatValue, &triplet);
+ createEntry(exifData, EXIF_IFD_GPS, EXIF_TAG_GPS_LATITUDE, triplet);
+
+ const char* ref = floatValue < 0.0f ? "S" : "N";
+ createEntry(exifData, EXIF_IFD_GPS, EXIF_TAG_GPS_LATITUDE_REF, ref);
+ }
+ // GPS longitude and reference, reference indicates sign, store unsigned
+ if (getCameraParam(params,
+ CameraParameters::KEY_GPS_LONGITUDE,
+ &floatValue)) {
+ convertGpsCoordinate(floatValue, &triplet);
+ createEntry(exifData, EXIF_IFD_GPS, EXIF_TAG_GPS_LONGITUDE, triplet);
+
+ const char* ref = floatValue < 0.0f ? "W" : "E";
+ createEntry(exifData, EXIF_IFD_GPS, EXIF_TAG_GPS_LONGITUDE_REF, ref);
+ }
+ // GPS altitude and reference, reference indicates sign, store unsigned
+ if (getCameraParam(params,
+ CameraParameters::KEY_GPS_ALTITUDE,
+ &floatValue)) {
+ createEntry(exifData, EXIF_IFD_GPS, EXIF_TAG_GPS_ALTITUDE,
+ static_cast<float>(fabs(floatValue)));
+
+ // 1 indicated below sea level, 0 indicates above sea level
+ uint8_t ref = floatValue < 0.0f ? 1 : 0;
+ createEntry(exifData, EXIF_IFD_GPS, EXIF_TAG_GPS_ALTITUDE_REF, ref);
+ }
+ // GPS timestamp and datestamp
+ int64_t timestamp = 0;
+ if (getCameraParam(params,
+ CameraParameters::KEY_GPS_TIMESTAMP,
+ &timestamp)) {
+ std::string date;
+ if (convertTimestampToTimeAndDate(timestamp, &triplet, &date)) {
+ createEntry(exifData, EXIF_IFD_GPS, EXIF_TAG_GPS_TIME_STAMP,
+ triplet, 1.0f);
+ createEntry(exifData, EXIF_IFD_GPS, EXIF_TAG_GPS_DATE_STAMP,
+ date.c_str());
+ }
+ }
+
+ // GPS processing method
+ if (getCameraParam(params,
+ CameraParameters::KEY_GPS_PROCESSING_METHOD,
+ &stringValue)) {
+ std::vector<unsigned char> data;
+ // Because this is a tag with an undefined format it has to be prefixed
+ // with the encoding type. Insert an ASCII prefix first, then the
+ // actual string. Undefined tags do not have to be null terminated.
+ data.insert(data.end(),
+ std::begin(kAsciiPrefix),
+ std::end(kAsciiPrefix));
+ data.insert(data.end(), stringValue, stringValue + strlen(stringValue));
+ createEntry(exifData, EXIF_IFD_GPS, EXIF_TAG_GPS_PROCESSING_METHOD,
+ &data[0], data.size());
+ }
+
+ return exifData;
+}
+
+void freeExifData(ExifData* exifData) {
+ exif_data_free(exifData);
+}
+
+} // namespace android
+
diff --git a/guest/hals/camera/Exif.h b/guest/hals/camera/Exif.h
new file mode 100644
index 000000000..4ea06e164
--- /dev/null
+++ b/guest/hals/camera/Exif.h
@@ -0,0 +1,41 @@
+
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CUTTLEFISH_CAMERA_EXIF_H
+#define CUTTLEFISH_CAMERA_EXIF_H
+
+#include <CameraParameters.h>
+
+using ::android::hardware::camera::common::V1_0::helper::CameraParameters;
+
+struct _ExifData;
+typedef struct _ExifData ExifData;
+
+namespace android {
+
+/* Create an EXIF data structure based on camera parameters. This includes
+ * things like GPS information that has been set by the camera client.
+ */
+ExifData* createExifData(const CameraParameters& parameters);
+
+/* Free EXIF data created in the createExifData call */
+void freeExifData(ExifData* exifData);
+
+} // namespace android
+
+#endif // CUTTLEFISH_CAMERA_EXIF_H
+
diff --git a/guest/hals/camera/GrallocModule.h b/guest/hals/camera/GrallocModule.h
new file mode 100644
index 000000000..2033e8d5b
--- /dev/null
+++ b/guest/hals/camera/GrallocModule.h
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+#ifndef GUEST_HALS_CAMERA_GRALLOCMODULE_H_
+#define GUEST_HALS_CAMERA_GRALLOCMODULE_H_
+
+#include <hardware/gralloc.h>
+
+class GrallocModule {
+ public:
+ static GrallocModule &getInstance() {
+ static GrallocModule instance;
+ return instance;
+ }
+
+ int lock(buffer_handle_t handle, int usage, int l, int t, int w, int h,
+ void **vaddr) {
+ return mModule->lock(mModule, handle, usage, l, t, w, h, vaddr);
+ }
+
+#ifdef GRALLOC_MODULE_API_VERSION_0_2
+ int lock_ycbcr(buffer_handle_t handle, int usage, int l, int t, int w, int h,
+ struct android_ycbcr *ycbcr) {
+ return mModule->lock_ycbcr(mModule, handle, usage, l, t, w, h, ycbcr);
+ }
+#endif
+
+ int unlock(buffer_handle_t handle) {
+ return mModule->unlock(mModule, handle);
+ }
+
+ private:
+ GrallocModule() {
+ const hw_module_t *module = NULL;
+ int ret = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
+ if (ret) {
+ ALOGE("%s: Failed to get gralloc module: %d", __FUNCTION__, ret);
+ }
+ mModule = reinterpret_cast<const gralloc_module_t *>(module);
+ }
+ const gralloc_module_t *mModule;
+};
+
+#endif // GUEST_HALS_CAMERA_GRALLOCMODULE_H_
diff --git a/guest/hals/camera/JpegCompressor.cpp b/guest/hals/camera/JpegCompressor.cpp
new file mode 100644
index 000000000..99164c9cd
--- /dev/null
+++ b/guest/hals/camera/JpegCompressor.cpp
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+/*
+ * Contains implementation of a class NV21JpegCompressor that encapsulates a
+ * converter between NV21, and JPEG formats.
+ */
+
+#define LOG_NDEBUG 0
+#define LOG_TAG "EmulatedCamera_JPEG"
+#include "JpegCompressor.h"
+#include <assert.h>
+#include <log/log.h>
+#include <dlfcn.h>
+
+namespace android {
+
+void* NV21JpegCompressor::mDl = NULL;
+
+static void* getSymbol(void* dl, const char* signature) {
+ void* res = dlsym(dl, signature);
+ assert(res != NULL);
+
+ return res;
+}
+
+typedef void (*InitFunc)(JpegStub* stub);
+typedef void (*CleanupFunc)(JpegStub* stub);
+typedef int (*CompressFunc)(JpegStub* stub, const void* image, int width,
+ int height, int quality, ExifData* exifData);
+typedef void (*GetCompressedImageFunc)(JpegStub* stub, void* buff);
+typedef size_t (*GetCompressedSizeFunc)(JpegStub* stub);
+
+NV21JpegCompressor::NV21JpegCompressor() {
+ if (mDl == NULL) {
+ mDl = dlopen("/vendor/lib/hw/camera.cutf.jpeg.so", RTLD_NOW);
+ }
+ if (mDl == NULL) {
+ mDl = dlopen("/system/lib/hw/camera.cutf.jpeg.so", RTLD_NOW);
+ }
+ assert(mDl != NULL);
+
+ InitFunc f = (InitFunc)getSymbol(mDl, "JpegStub_init");
+ (*f)(&mStub);
+}
+
+NV21JpegCompressor::~NV21JpegCompressor() {
+ CleanupFunc f = (CleanupFunc)getSymbol(mDl, "JpegStub_cleanup");
+ (*f)(&mStub);
+}
+
+/****************************************************************************
+ * Public API
+ ***************************************************************************/
+
+status_t NV21JpegCompressor::compressRawImage(const void* image,
+ ExifData* exifData,
+ int quality,
+ int width,
+ int height) {
+ mStrides[0] = width;
+ mStrides[1] = width;
+ CompressFunc f = (CompressFunc)getSymbol(mDl, "JpegStub_compress");
+ return (status_t)(*f)(&mStub, image, width, height, quality, exifData);
+}
+
+size_t NV21JpegCompressor::getCompressedSize() {
+ GetCompressedSizeFunc f =
+ (GetCompressedSizeFunc)getSymbol(mDl, "JpegStub_getCompressedSize");
+ return (*f)(&mStub);
+}
+
+void NV21JpegCompressor::getCompressedImage(void* buff) {
+ GetCompressedImageFunc f =
+ (GetCompressedImageFunc)getSymbol(mDl, "JpegStub_getCompressedImage");
+ (*f)(&mStub, buff);
+}
+
+}; /* namespace android */
diff --git a/guest/hals/camera/JpegCompressor.h b/guest/hals/camera/JpegCompressor.h
new file mode 100644
index 000000000..6d93c4613
--- /dev/null
+++ b/guest/hals/camera/JpegCompressor.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2011 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 HW_EMULATOR_CAMERA_JPEG_COMPRESSOR_H
+#define HW_EMULATOR_CAMERA_JPEG_COMPRESSOR_H
+
+/*
+ * Contains declaration of a class NV21JpegCompressor that encapsulates a
+ * converter between YV21, and JPEG formats.
+ */
+
+#include <utils/threads.h>
+#include "JpegStub.h"
+
+namespace android {
+
+/* Encapsulates a converter between YV12, and JPEG formats.
+ */
+class NV21JpegCompressor {
+ public:
+ /* Constructs JpegCompressor instance. */
+ NV21JpegCompressor();
+ /* Destructs JpegCompressor instance. */
+ ~NV21JpegCompressor();
+
+ /****************************************************************************
+ * Public API
+ ***************************************************************************/
+
+ public:
+ /* Compresses raw NV21 image into a JPEG.
+ * The compressed image will be saved in mStream member of this class. Use
+ * getCompressedSize method to obtain buffer size of the compressed image,
+ * and getCompressedImage to copy out the compressed image.
+ * Param:
+ * image - Raw NV21 image.
+ * metadata - Image metadata (dimensions, location etc).
+ * quality - JPEG quality.
+ * Return:
+ * NO_ERROR on success, or an appropriate error status.
+ *
+ */
+ status_t compressRawImage(const void* image, ExifData* exifData,
+ int quality, int width, int height);
+
+ /* Get size of the compressed JPEG buffer.
+ * This method must be called only after a successful completion of
+ * compressRawImage call.
+ * Return:
+ * Size of the compressed JPEG buffer.
+ */
+ size_t getCompressedSize();
+
+ /* Copies out compressed JPEG buffer.
+ * This method must be called only after a successful completion of
+ * compressRawImage call.
+ * Param:
+ * buff - Buffer where to copy the JPEG. Must be large enough to contain the
+ * entire image.
+ */
+ void getCompressedImage(void* buff);
+
+ /****************************************************************************
+ * Class data
+ ***************************************************************************/
+
+ protected:
+ /* Strides for Y (the first element), and UV (the second one) panes. */
+ int mStrides[2];
+
+ private:
+ // library handle to dlopen
+ static void* mDl;
+ JpegStub mStub;
+};
+
+}; /* namespace android */
+
+#endif /* HW_EMULATOR_CAMERA_JPEG_COMPRESSOR_H */
diff --git a/guest/hals/camera/JpegStub.cpp b/guest/hals/camera/JpegStub.cpp
new file mode 100644
index 000000000..3e02de066
--- /dev/null
+++ b/guest/hals/camera/JpegStub.cpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2013 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 "JpegStub.h"
+
+#define LOG_NDEBUG 0
+#define LOG_TAG "EmulatedCamera_JPEGStub"
+#include <errno.h>
+#include <log/log.h>
+#include <stdlib.h>
+
+#include "Compressor.h"
+
+extern "C" void JpegStub_init(JpegStub* stub) {
+ stub->mCompressor = static_cast<void*>(new Compressor());
+}
+
+extern "C" void JpegStub_cleanup(JpegStub* stub) {
+ delete reinterpret_cast<Compressor*>(stub->mCompressor);
+ stub->mCompressor = nullptr;
+}
+
+extern "C" int JpegStub_compress(JpegStub* stub,
+ const void* buffer,
+ int width,
+ int height,
+ int quality,
+ ExifData* exifData)
+{
+ Compressor* compressor = reinterpret_cast<Compressor*>(stub->mCompressor);
+
+ if (compressor->compress(reinterpret_cast<const unsigned char*>(buffer),
+ width, height, quality, exifData)) {
+ ALOGV("%s: Compressed JPEG: %d[%dx%d] -> %zu bytes",
+ __FUNCTION__, (width * height * 12) / 8,
+ width, height, compressor->getCompressedData().size());
+ return 0;
+ }
+ ALOGE("%s: JPEG compression failed", __FUNCTION__);
+ return errno ? errno : EINVAL;
+}
+
+extern "C" void JpegStub_getCompressedImage(JpegStub* stub, void* buff) {
+ Compressor* compressor = reinterpret_cast<Compressor*>(stub->mCompressor);
+
+ const std::vector<unsigned char>& data = compressor->getCompressedData();
+ memcpy(buff, &data[0], data.size());
+}
+
+extern "C" size_t JpegStub_getCompressedSize(JpegStub* stub) {
+ Compressor* compressor = reinterpret_cast<Compressor*>(stub->mCompressor);
+
+ return compressor->getCompressedData().size();
+}
diff --git a/guest/hals/camera/JpegStub.h b/guest/hals/camera/JpegStub.h
new file mode 100644
index 000000000..2e6218208
--- /dev/null
+++ b/guest/hals/camera/JpegStub.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2013 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 JPEGSTUB_H_
+#define JPEGSTUB_H_
+
+#include <stddef.h>
+
+struct _ExifData;
+typedef _ExifData ExifData;
+
+extern "C" {
+
+struct JpegStub {
+ void* mCompressor;
+};
+
+void JpegStub_init(JpegStub* stub);
+void JpegStub_cleanup(JpegStub* stub);
+int JpegStub_compress(JpegStub* stub,
+ const void* image,
+ int width,
+ int height,
+ int quality,
+ ExifData* exifData);
+void JpegStub_getCompressedImage(JpegStub* stub, void* buff);
+size_t JpegStub_getCompressedSize(JpegStub* stub);
+
+};
+#endif // JPEGSTUB_H_
diff --git a/guest/hals/camera/PreviewWindow.cpp b/guest/hals/camera/PreviewWindow.cpp
new file mode 100644
index 000000000..e49843521
--- /dev/null
+++ b/guest/hals/camera/PreviewWindow.cpp
@@ -0,0 +1,204 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+/*
+ * Contains implementation of a class PreviewWindow that encapsulates
+ * functionality of a preview window set via set_preview_window camera HAL API.
+ */
+
+#define LOG_NDEBUG 0
+#define LOG_TAG "EmulatedCamera_Preview"
+#include "PreviewWindow.h"
+#include <log/log.h>
+#include <hardware/camera.h>
+#include "EmulatedCameraDevice.h"
+#include "GrallocModule.h"
+
+namespace android {
+
+PreviewWindow::PreviewWindow()
+ : mPreviewWindow(NULL),
+ mLastPreviewed(0),
+ mPreviewFrameWidth(0),
+ mPreviewFrameHeight(0),
+ mPreviewEnabled(false) {}
+
+PreviewWindow::~PreviewWindow() {}
+
+/****************************************************************************
+ * Camera API
+ ***************************************************************************/
+
+status_t PreviewWindow::setPreviewWindow(struct preview_stream_ops* window,
+ int preview_fps) {
+ ALOGV("%s: current: %p -> new: %p", __FUNCTION__, mPreviewWindow, window);
+
+ status_t res = NO_ERROR;
+ Mutex::Autolock locker(&mObjectLock);
+
+ /* Reset preview info. */
+ mPreviewFrameWidth = mPreviewFrameHeight = 0;
+ mPreviewAfter = 0;
+ mLastPreviewed = 0;
+
+ if (window != NULL) {
+ /* The CPU will write each frame to the preview window buffer.
+ * Note that we delay setting preview window buffer geometry until
+ * frames start to come in. */
+ res = window->set_usage(window, GRALLOC_USAGE_SW_WRITE_OFTEN);
+ if (res == NO_ERROR) {
+ /* Set preview frequency. */
+ mPreviewAfter = 1000000 / preview_fps;
+ } else {
+ window = NULL;
+ res = -res; // set_usage returns a negative errno.
+ ALOGE("%s: Error setting preview window usage %d -> %s", __FUNCTION__,
+ res, strerror(res));
+ }
+ }
+ mPreviewWindow = window;
+
+ return res;
+}
+
+status_t PreviewWindow::startPreview() {
+ ALOGV("%s", __FUNCTION__);
+
+ Mutex::Autolock locker(&mObjectLock);
+ mPreviewEnabled = true;
+
+ return NO_ERROR;
+}
+
+void PreviewWindow::stopPreview() {
+ ALOGV("%s", __FUNCTION__);
+
+ Mutex::Autolock locker(&mObjectLock);
+ mPreviewEnabled = false;
+}
+
+/****************************************************************************
+ * Public API
+ ***************************************************************************/
+
+void PreviewWindow::onNextFrameAvailable(const void* /*frame*/,
+ nsecs_t timestamp,
+ EmulatedCameraDevice* camera_dev) {
+ int res;
+ Mutex::Autolock locker(&mObjectLock);
+
+ if (!isPreviewEnabled() || mPreviewWindow == NULL || !isPreviewTime()) {
+ return;
+ }
+
+ /* Make sure that preview window dimensions are OK with the camera device */
+ if (adjustPreviewDimensions(camera_dev)) {
+ /* Need to set / adjust buffer geometry for the preview window.
+ * Note that in the emulator preview window uses only RGB for pixel
+ * formats. */
+ ALOGV("%s: Adjusting preview windows %p geometry to %dx%d", __FUNCTION__,
+ mPreviewWindow, mPreviewFrameWidth, mPreviewFrameHeight);
+ res = mPreviewWindow->set_buffers_geometry(
+ mPreviewWindow, mPreviewFrameWidth, mPreviewFrameHeight,
+ HAL_PIXEL_FORMAT_RGBA_8888);
+ if (res != NO_ERROR) {
+ ALOGE("%s: Error in set_buffers_geometry %d -> %s", __FUNCTION__, -res,
+ strerror(-res));
+ return;
+ }
+ }
+
+ /*
+ * Push new frame to the preview window.
+ */
+
+ /* Dequeue preview window buffer for the frame. */
+ buffer_handle_t* buffer = NULL;
+ int stride = 0;
+ res = mPreviewWindow->dequeue_buffer(mPreviewWindow, &buffer, &stride);
+ if (res != NO_ERROR || buffer == NULL) {
+ ALOGE("%s: Unable to dequeue preview window buffer: %d -> %s", __FUNCTION__,
+ -res, strerror(-res));
+ return;
+ }
+
+ /* Let the preview window to lock the buffer. */
+ res = mPreviewWindow->lock_buffer(mPreviewWindow, buffer);
+ if (res != NO_ERROR) {
+ ALOGE("%s: Unable to lock preview window buffer: %d -> %s", __FUNCTION__,
+ -res, strerror(-res));
+ mPreviewWindow->cancel_buffer(mPreviewWindow, buffer);
+ return;
+ }
+
+ /* Now let the graphics framework to lock the buffer, and provide
+ * us with the framebuffer data address. */
+ void* img = NULL;
+ res = GrallocModule::getInstance().lock(*buffer, GRALLOC_USAGE_SW_WRITE_OFTEN,
+ 0, 0, mPreviewFrameWidth,
+ mPreviewFrameHeight, &img);
+ if (res != NO_ERROR) {
+ ALOGE("%s: gralloc.lock failure: %d -> %s", __FUNCTION__, res,
+ strerror(res));
+ mPreviewWindow->cancel_buffer(mPreviewWindow, buffer);
+ return;
+ }
+
+ /* Frames come in in YV12/NV12/NV21 format. Since preview window doesn't
+ * supports those formats, we need to obtain the frame in RGB565. */
+ res = camera_dev->getCurrentPreviewFrame(img);
+ if (res == NO_ERROR) {
+ /* Show it. */
+ mPreviewWindow->set_timestamp(mPreviewWindow, timestamp);
+ mPreviewWindow->enqueue_buffer(mPreviewWindow, buffer);
+ } else {
+ ALOGE("%s: Unable to obtain preview frame: %d", __FUNCTION__, res);
+ mPreviewWindow->cancel_buffer(mPreviewWindow, buffer);
+ }
+ GrallocModule::getInstance().unlock(*buffer);
+}
+
+/***************************************************************************
+ * Private API
+ **************************************************************************/
+
+bool PreviewWindow::adjustPreviewDimensions(EmulatedCameraDevice* camera_dev) {
+ /* Match the cached frame dimensions against the actual ones. */
+ if (mPreviewFrameWidth == camera_dev->getFrameWidth() &&
+ mPreviewFrameHeight == camera_dev->getFrameHeight()) {
+ /* They match. */
+ return false;
+ }
+
+ /* They don't match: adjust the cache. */
+ mPreviewFrameWidth = camera_dev->getFrameWidth();
+ mPreviewFrameHeight = camera_dev->getFrameHeight();
+
+ return true;
+}
+
+bool PreviewWindow::isPreviewTime() {
+ timeval cur_time;
+ gettimeofday(&cur_time, NULL);
+ const uint64_t cur_mks = cur_time.tv_sec * 1000000LL + cur_time.tv_usec;
+ if ((cur_mks - mLastPreviewed) >= mPreviewAfter) {
+ mLastPreviewed = cur_mks;
+ return true;
+ }
+ return false;
+}
+
+}; /* namespace android */
diff --git a/guest/hals/camera/PreviewWindow.h b/guest/hals/camera/PreviewWindow.h
new file mode 100644
index 000000000..0041c5549
--- /dev/null
+++ b/guest/hals/camera/PreviewWindow.h
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2011 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 HW_EMULATOR_CAMERA_PREVIEW_WINDOW_H
+#define HW_EMULATOR_CAMERA_PREVIEW_WINDOW_H
+
+#include <hardware/camera.h>
+#include <utils/Errors.h>
+#include <utils/Mutex.h>
+#include <utils/Timers.h>
+
+/*
+ * Contains declaration of a class PreviewWindow that encapsulates functionality
+ * of a preview window set via set_preview_window camera HAL API.
+ */
+
+namespace android {
+
+class EmulatedCameraDevice;
+
+/* Encapsulates functionality of a preview window set via set_preview_window
+ * camera HAL API.
+ *
+ * Objects of this class are contained in EmulatedCamera objects, and handle
+ * relevant camera API callbacks.
+ */
+class PreviewWindow {
+ public:
+ /* Constructs PreviewWindow instance. */
+ PreviewWindow();
+
+ /* Destructs PreviewWindow instance. */
+ ~PreviewWindow();
+
+ /***************************************************************************
+ * Camera API
+ **************************************************************************/
+
+ public:
+ /* Actual handler for camera_device_ops_t::set_preview_window callback.
+ * This method is called by the containing emulated camera object when it is
+ * handing the camera_device_ops_t::set_preview_window callback.
+ * Param:
+ * window - Preview window to set. This parameter might be NULL, which
+ * indicates preview window reset.
+ * preview_fps - Preview's frame frequency. This parameter determins when
+ * a frame received via onNextFrameAvailable call will be pushed to
+ * the preview window. If 'window' parameter passed to this method is
+ * NULL, this parameter is ignored.
+ * Return:
+ * NO_ERROR on success, or an appropriate error status.
+ */
+ status_t setPreviewWindow(struct preview_stream_ops* window, int preview_fps);
+
+ /* Starts the preview.
+ * This method is called by the containing emulated camera object when it is
+ * handing the camera_device_ops_t::start_preview callback.
+ */
+ status_t startPreview();
+
+ /* Stops the preview.
+ * This method is called by the containing emulated camera object when it is
+ * handing the camera_device_ops_t::start_preview callback.
+ */
+ void stopPreview();
+
+ /* Checks if preview is enabled. */
+ inline bool isPreviewEnabled() { return mPreviewEnabled; }
+
+ /****************************************************************************
+ * Public API
+ ***************************************************************************/
+
+ public:
+ /* Next frame is available in the camera device.
+ * This is a notification callback that is invoked by the camera device when
+ * a new frame is available.
+ * Note that most likely this method is called in context of a worker thread
+ * that camera device has created for frame capturing.
+ * Param:
+ * frame - Captured frame, or NULL if camera device didn't pull the frame
+ * yet. If NULL is passed in this parameter use GetCurrentFrame method
+ * of the camera device class to obtain the next frame. Also note that
+ * the size of the frame that is passed here (as well as the frame
+ * returned from the GetCurrentFrame method) is defined by the current
+ * frame settings (width + height + pixel format) for the camera device.
+ * timestamp - Frame's timestamp.
+ * camera_dev - Camera device instance that delivered the frame.
+ */
+ void onNextFrameAvailable(const void* frame, nsecs_t timestamp,
+ EmulatedCameraDevice* camera_dev);
+
+ /***************************************************************************
+ * Private API
+ **************************************************************************/
+
+ protected:
+ /* Adjusts cached dimensions of the preview window frame according to the
+ * frame dimensions used by the camera device.
+ *
+ * When preview is started, it's not known (hard to define) what are going
+ * to be the dimensions of the frames that are going to be displayed. Plus,
+ * it might be possible, that such dimensions can be changed on the fly. So,
+ * in order to be always in sync with frame dimensions, this method is
+ * called for each frame passed to onNextFrameAvailable method, in order to
+ * properly adjust frame dimensions, used by the preview window.
+ * Note that this method must be called while object is locked.
+ * Param:
+ * camera_dev - Camera device, prpviding frames displayed in the preview
+ * window.
+ * Return:
+ * true if cached dimensions have been adjusted, or false if cached
+ * dimensions match device's frame dimensions.
+ */
+ bool adjustPreviewDimensions(EmulatedCameraDevice* camera_dev);
+
+ /* Checks if it's the time to push new frame to the preview window.
+ * Note that this method must be called while object is locked. */
+ bool isPreviewTime();
+
+ /***************************************************************************
+ * Data members
+ **************************************************************************/
+
+ protected:
+ /* Locks this instance for data changes. */
+ Mutex mObjectLock;
+
+ /* Preview window instance. */
+ preview_stream_ops* mPreviewWindow;
+
+ /* Timestamp (abs. microseconds) when last frame has been pushed to the
+ * preview window. */
+ uint64_t mLastPreviewed;
+
+ /* Preview frequency in microseconds. */
+ uint32_t mPreviewAfter;
+
+ /*
+ * Cached preview window frame dimensions.
+ */
+
+ int mPreviewFrameWidth;
+ int mPreviewFrameHeight;
+
+ /* Preview status. */
+ bool mPreviewEnabled;
+};
+
+}; /* namespace android */
+
+#endif /* HW_EMULATOR_CAMERA_PREVIEW_WINDOW_H */
diff --git a/guest/hals/camera/QemuClient.cpp b/guest/hals/camera/QemuClient.cpp
new file mode 100644
index 000000000..eb8970242
--- /dev/null
+++ b/guest/hals/camera/QemuClient.cpp
@@ -0,0 +1,516 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+/*
+ * Contains implementation of classes that encapsulate connection to camera
+ * services in the emulator via qemu pipe.
+ */
+
+#define LOG_NDEBUG 0
+#define LOG_TAG "EmulatedCamera_QemuClient"
+#include "QemuClient.h"
+#include <log/log.h>
+#include "EmulatedCamera.h"
+
+#define LOG_QUERIES 0
+#if LOG_QUERIES
+#define LOGQ(...) ALOGD(__VA_ARGS__)
+#else
+#define LOGQ(...) (void(0))
+
+#endif // LOG_QUERIES
+namespace android {
+
+/****************************************************************************
+ * Qemu query
+ ***************************************************************************/
+
+QemuQuery::QemuQuery()
+ : mQuery(mQueryPrealloc),
+ mQueryDeliveryStatus(NO_ERROR),
+ mReplyBuffer(NULL),
+ mReplyData(NULL),
+ mReplySize(0),
+ mReplyDataSize(0),
+ mReplyStatus(0) {
+ *mQuery = '\0';
+}
+
+QemuQuery::QemuQuery(const char* query_string)
+ : mQuery(mQueryPrealloc),
+ mQueryDeliveryStatus(NO_ERROR),
+ mReplyBuffer(NULL),
+ mReplyData(NULL),
+ mReplySize(0),
+ mReplyDataSize(0),
+ mReplyStatus(0) {
+ mQueryDeliveryStatus = QemuQuery::createQuery(query_string, NULL);
+}
+
+QemuQuery::QemuQuery(const char* query_name, const char* query_param)
+ : mQuery(mQueryPrealloc),
+ mQueryDeliveryStatus(NO_ERROR),
+ mReplyBuffer(NULL),
+ mReplyData(NULL),
+ mReplySize(0),
+ mReplyDataSize(0),
+ mReplyStatus(0) {
+ mQueryDeliveryStatus = QemuQuery::createQuery(query_name, query_param);
+}
+
+QemuQuery::~QemuQuery() { QemuQuery::resetQuery(); }
+
+status_t QemuQuery::createQuery(const char* name, const char* param) {
+ /* Reset from the previous use. */
+ resetQuery();
+
+ /* Query name cannot be NULL or an empty string. */
+ if (name == NULL || *name == '\0') {
+ ALOGE("%s: NULL or an empty string is passed as query name.", __FUNCTION__);
+ mQueryDeliveryStatus = EINVAL;
+ return EINVAL;
+ }
+
+ const size_t name_len = strlen(name);
+ const size_t param_len = (param != NULL) ? strlen(param) : 0;
+ const size_t required = strlen(name) + (param_len ? (param_len + 2) : 1);
+
+ if (required > sizeof(mQueryPrealloc)) {
+ /* Preallocated buffer was too small. Allocate a bigger query buffer. */
+ mQuery = new char[required];
+ if (mQuery == NULL) {
+ ALOGE("%s: Unable to allocate %zu bytes for query buffer", __FUNCTION__,
+ required);
+ mQueryDeliveryStatus = ENOMEM;
+ return ENOMEM;
+ }
+ }
+
+ /* At this point mQuery buffer is big enough for the query. */
+ if (param_len) {
+ sprintf(mQuery, "%s %s", name, param);
+ } else {
+ memcpy(mQuery, name, name_len + 1);
+ }
+
+ return NO_ERROR;
+}
+
+status_t QemuQuery::completeQuery(status_t status) {
+ /* Save query completion status. */
+ mQueryDeliveryStatus = status;
+ if (mQueryDeliveryStatus != NO_ERROR) {
+ return mQueryDeliveryStatus;
+ }
+
+ /* Make sure reply buffer contains at least 'ok', or 'ko'.
+ * Note that 'ok', or 'ko' prefixes are always 3 characters long: in case
+ * there are more data in the reply, that data will be separated from
+ * 'ok'/'ko' with a ':'. If there is no more data in the reply, the prefix
+ * will be
+ * zero-terminated, and the terminator will be inculded in the reply. */
+ if (mReplyBuffer == NULL || mReplySize < 3) {
+ ALOGE("%s: Invalid reply to the query", __FUNCTION__);
+ mQueryDeliveryStatus = EINVAL;
+ return EINVAL;
+ }
+
+ /* Lets see the reply status. */
+ if (!memcmp(mReplyBuffer, "ok", 2)) {
+ mReplyStatus = 1;
+ } else if (!memcmp(mReplyBuffer, "ko", 2)) {
+ mReplyStatus = 0;
+ } else {
+ ALOGE("%s: Invalid query reply: '%s'", __FUNCTION__, mReplyBuffer);
+ mQueryDeliveryStatus = EINVAL;
+ return EINVAL;
+ }
+
+ /* Lets see if there are reply data that follow. */
+ if (mReplySize > 3) {
+ /* There are extra data. Make sure they are separated from the status
+ * with a ':' */
+ if (mReplyBuffer[2] != ':') {
+ ALOGE("%s: Invalid query reply: '%s'", __FUNCTION__, mReplyBuffer);
+ mQueryDeliveryStatus = EINVAL;
+ return EINVAL;
+ }
+ mReplyData = mReplyBuffer + 3;
+ mReplyDataSize = mReplySize - 3;
+ } else {
+ /* Make sure reply buffer containing just 'ok'/'ko' ends with
+ * zero-terminator. */
+ if (mReplyBuffer[2] != '\0') {
+ ALOGE("%s: Invalid query reply: '%s'", __FUNCTION__, mReplyBuffer);
+ mQueryDeliveryStatus = EINVAL;
+ return EINVAL;
+ }
+ }
+
+ return NO_ERROR;
+}
+
+void QemuQuery::resetQuery() {
+ if (mQuery != NULL && mQuery != mQueryPrealloc) {
+ delete[] mQuery;
+ }
+ mQuery = mQueryPrealloc;
+ mQueryDeliveryStatus = NO_ERROR;
+ if (mReplyBuffer != NULL) {
+ free(mReplyBuffer);
+ mReplyBuffer = NULL;
+ }
+ mReplyData = NULL;
+ mReplySize = mReplyDataSize = 0;
+ mReplyStatus = 0;
+}
+
+/****************************************************************************
+ * Qemu client base
+ ***************************************************************************/
+
+/* Camera service name. */
+const char QemuClient::mCameraServiceName[] = "camera";
+
+QemuClient::QemuClient() : mPipeFD(-1) {}
+
+QemuClient::~QemuClient() {
+ if (mPipeFD >= 0) {
+ close(mPipeFD);
+ }
+}
+
+/****************************************************************************
+ * Qemu client API
+ ***************************************************************************/
+
+status_t QemuClient::connectClient(const char* param) {
+ ALOGV("%s: '%s'", __FUNCTION__, param ? param : "");
+
+ /* Make sure that client is not connected already. */
+ if (mPipeFD >= 0) {
+ ALOGE("%s: Qemu client is already connected", __FUNCTION__);
+ return EINVAL;
+ }
+
+ /* Select one of the two: 'factory', or 'emulated camera' service */
+ if (param == NULL || *param == '\0') {
+ /* No parameters: connect to the factory service. */
+ char pipe_name[512];
+ snprintf(pipe_name, sizeof(pipe_name), "qemud:%s", mCameraServiceName);
+ mPipeFD = qemu_pipe_open(pipe_name);
+ } else {
+ /* One extra char ':' that separates service name and parameters + six
+ * characters for 'qemud:'. This is required by qemu pipe protocol. */
+ char* connection_str =
+ new char[strlen(mCameraServiceName) + strlen(param) + 8];
+ sprintf(connection_str, "qemud:%s:%s", mCameraServiceName, param);
+
+ mPipeFD = qemu_pipe_open(connection_str);
+ delete[] connection_str;
+ }
+ if (mPipeFD < 0) {
+ ALOGE("%s: Unable to connect to the camera service '%s': %s", __FUNCTION__,
+ param ? param : "Factory", strerror(errno));
+ return errno ? errno : EINVAL;
+ }
+
+ return NO_ERROR;
+}
+
+void QemuClient::disconnectClient() {
+ ALOGV("%s", __FUNCTION__);
+
+ if (mPipeFD >= 0) {
+ close(mPipeFD);
+ mPipeFD = -1;
+ }
+}
+
+status_t QemuClient::sendMessage(const void* data, size_t data_size) {
+ if (mPipeFD < 0) {
+ ALOGE("%s: Qemu client is not connected", __FUNCTION__);
+ return EINVAL;
+ }
+
+ /* Note that we don't use here qemud_client_send, since with qemu pipes we
+ * don't need to provide payload size prior to payload when we're writing to
+ * the pipe. So, we can use simple write, and qemu pipe will take care of the
+ * rest, calling the receiving end with the number of bytes transferred. */
+ const size_t written = qemud_fd_write(mPipeFD, data, data_size);
+ if (written == data_size) {
+ return NO_ERROR;
+ } else {
+ ALOGE("%s: Error sending data via qemu pipe: '%s'", __FUNCTION__,
+ strerror(errno));
+ return errno ? errno : EIO;
+ }
+}
+
+status_t QemuClient::receiveMessage(void** data, size_t* data_size) {
+ *data = NULL;
+ *data_size = 0;
+
+ if (mPipeFD < 0) {
+ ALOGE("%s: Qemu client is not connected", __FUNCTION__);
+ return EINVAL;
+ }
+
+ /* The way the service replies to a query, it sends payload size first, and
+ * then it sends the payload itself. Note that payload size is sent as a
+ * string, containing 8 characters representing a hexadecimal payload size
+ * value. Note also, that the string doesn't contain zero-terminator. */
+ size_t payload_size;
+ char payload_size_str[9];
+ int rd_res = qemud_fd_read(mPipeFD, payload_size_str, 8);
+ if (rd_res != 8) {
+ ALOGE("%s: Unable to obtain payload size: %s", __FUNCTION__,
+ strerror(errno));
+ return errno ? errno : EIO;
+ }
+
+ /* Convert payload size. */
+ errno = 0;
+ payload_size_str[8] = '\0';
+ payload_size = strtol(payload_size_str, NULL, 16);
+ if (errno) {
+ ALOGE("%s: Invalid payload size '%s'", __FUNCTION__, payload_size_str);
+ return EIO;
+ }
+
+ /* Allocate payload data buffer, and read the payload there. */
+ *data = malloc(payload_size);
+ if (*data == NULL) {
+ ALOGE("%s: Unable to allocate %zu bytes payload buffer", __FUNCTION__,
+ payload_size);
+ return ENOMEM;
+ }
+ rd_res = qemud_fd_read(mPipeFD, *data, payload_size);
+ if (static_cast<size_t>(rd_res) == payload_size) {
+ *data_size = payload_size;
+ return NO_ERROR;
+ } else {
+ ALOGE("%s: Read size %d doesnt match expected payload size %zu: %s",
+ __FUNCTION__, rd_res, payload_size, strerror(errno));
+ free(*data);
+ *data = NULL;
+ return errno ? errno : EIO;
+ }
+}
+
+status_t QemuClient::doQuery(QemuQuery* query) {
+ /* Make sure that query has been successfuly constructed. */
+ if (query->mQueryDeliveryStatus != NO_ERROR) {
+ ALOGE("%s: Query is invalid", __FUNCTION__);
+ return query->mQueryDeliveryStatus;
+ }
+
+ LOGQ("Send query '%s'", query->mQuery);
+
+ /* Send the query. */
+ status_t res = sendMessage(query->mQuery, strlen(query->mQuery) + 1);
+ if (res == NO_ERROR) {
+ /* Read the response. */
+ res = receiveMessage(reinterpret_cast<void**>(&query->mReplyBuffer),
+ &query->mReplySize);
+ if (res == NO_ERROR) {
+ LOGQ("Response to query '%s': Status = '%.2s', %d bytes in response",
+ query->mQuery, query->mReplyBuffer, query->mReplySize);
+ } else {
+ ALOGE("%s Response to query '%s' has failed: %s", __FUNCTION__,
+ query->mQuery, strerror(res));
+ }
+ } else {
+ ALOGE("%s: Send query '%s' failed: %s", __FUNCTION__, query->mQuery,
+ strerror(res));
+ }
+
+ /* Complete the query, and return its completion handling status. */
+ const status_t res1 = query->completeQuery(res);
+ ALOGE_IF(res1 != NO_ERROR && res1 != res,
+ "%s: Error %d in query '%s' completion", __FUNCTION__, res1,
+ query->mQuery);
+ return res1;
+}
+
+/****************************************************************************
+ * Qemu client for the 'factory' service.
+ ***************************************************************************/
+
+/*
+ * Factory service queries.
+ */
+
+/* Queries list of cameras connected to the host. */
+const char FactoryQemuClient::mQueryList[] = "list";
+
+FactoryQemuClient::FactoryQemuClient() : QemuClient() {}
+
+FactoryQemuClient::~FactoryQemuClient() {}
+
+status_t FactoryQemuClient::listCameras(char** list) {
+ ALOGV("%s", __FUNCTION__);
+
+ QemuQuery query(mQueryList);
+ if (doQuery(&query) || !query.isQuerySucceeded()) {
+ ALOGE("%s: List cameras query failed: %s", __FUNCTION__,
+ query.mReplyData ? query.mReplyData : "No error message");
+ return query.getCompletionStatus();
+ }
+
+ /* Make sure there is a list returned. */
+ if (query.mReplyDataSize == 0) {
+ ALOGE("%s: No camera list is returned.", __FUNCTION__);
+ return EINVAL;
+ }
+
+ /* Copy the list over. */
+ *list = (char*)malloc(query.mReplyDataSize);
+ if (*list != NULL) {
+ memcpy(*list, query.mReplyData, query.mReplyDataSize);
+ ALOGD("Emulated camera list: %s", *list);
+ return NO_ERROR;
+ } else {
+ ALOGE("%s: Unable to allocate %zu bytes", __FUNCTION__,
+ query.mReplyDataSize);
+ return ENOMEM;
+ }
+}
+
+/****************************************************************************
+ * Qemu client for an 'emulated camera' service.
+ ***************************************************************************/
+
+/*
+ * Emulated camera queries
+ */
+
+/* Connect to the camera device. */
+const char CameraQemuClient::mQueryConnect[] = "connect";
+/* Disconect from the camera device. */
+const char CameraQemuClient::mQueryDisconnect[] = "disconnect";
+/* Start capturing video from the camera device. */
+const char CameraQemuClient::mQueryStart[] = "start";
+/* Stop capturing video from the camera device. */
+const char CameraQemuClient::mQueryStop[] = "stop";
+/* Get next video frame from the camera device. */
+const char CameraQemuClient::mQueryFrame[] = "frame";
+
+CameraQemuClient::CameraQemuClient() : QemuClient() {}
+
+CameraQemuClient::~CameraQemuClient() {}
+
+status_t CameraQemuClient::queryConnect() {
+ ALOGV("%s", __FUNCTION__);
+
+ QemuQuery query(mQueryConnect);
+ doQuery(&query);
+ const status_t res = query.getCompletionStatus();
+ ALOGE_IF(res != NO_ERROR, "%s: Query failed: %s", __FUNCTION__,
+ query.mReplyData ? query.mReplyData : "No error message");
+ return res;
+}
+
+status_t CameraQemuClient::queryDisconnect() {
+ ALOGV("%s", __FUNCTION__);
+
+ QemuQuery query(mQueryDisconnect);
+ doQuery(&query);
+ const status_t res = query.getCompletionStatus();
+ ALOGE_IF(res != NO_ERROR, "%s: Query failed: %s", __FUNCTION__,
+ query.mReplyData ? query.mReplyData : "No error message");
+ return res;
+}
+
+status_t CameraQemuClient::queryStart(uint32_t pixel_format, int width,
+ int height) {
+ ALOGV("%s", __FUNCTION__);
+
+ char query_str[256];
+ snprintf(query_str, sizeof(query_str), "%s dim=%dx%d pix=%d", mQueryStart,
+ width, height, pixel_format);
+ QemuQuery query(query_str);
+ doQuery(&query);
+ const status_t res = query.getCompletionStatus();
+ ALOGE_IF(res != NO_ERROR, "%s: Query failed: %s", __FUNCTION__,
+ query.mReplyData ? query.mReplyData : "No error message");
+ return res;
+}
+
+status_t CameraQemuClient::queryStop() {
+ ALOGV("%s", __FUNCTION__);
+
+ QemuQuery query(mQueryStop);
+ doQuery(&query);
+ const status_t res = query.getCompletionStatus();
+ ALOGE_IF(res != NO_ERROR, "%s: Query failed: %s", __FUNCTION__,
+ query.mReplyData ? query.mReplyData : "No error message");
+ return res;
+}
+
+status_t CameraQemuClient::queryFrame(void* vframe, void* pframe,
+ size_t vframe_size, size_t pframe_size,
+ float r_scale, float g_scale,
+ float b_scale, float exposure_comp) {
+ ALOGV("%s", __FUNCTION__);
+
+ char query_str[256];
+ snprintf(query_str, sizeof(query_str),
+ "%s video=%zu preview=%zu whiteb=%g,%g,%g expcomp=%g", mQueryFrame,
+ (vframe && vframe_size) ? vframe_size : 0,
+ (pframe && pframe_size) ? pframe_size : 0, r_scale, g_scale, b_scale,
+ exposure_comp);
+ QemuQuery query(query_str);
+ doQuery(&query);
+ const status_t res = query.getCompletionStatus();
+ if (res != NO_ERROR) {
+ ALOGE("%s: Query failed: %s", __FUNCTION__,
+ query.mReplyData ? query.mReplyData : "No error message");
+ return res;
+ }
+
+ /* Copy requested frames. */
+ size_t cur_offset = 0;
+ const uint8_t* frame = reinterpret_cast<const uint8_t*>(query.mReplyData);
+ /* Video frame is always first. */
+ if (vframe != NULL && vframe_size != 0) {
+ /* Make sure that video frame is in. */
+ if ((query.mReplyDataSize - cur_offset) >= vframe_size) {
+ memcpy(vframe, frame, vframe_size);
+ cur_offset += vframe_size;
+ } else {
+ ALOGE("%s: Reply %zu bytes is to small to contain %zu bytes video frame",
+ __FUNCTION__, query.mReplyDataSize - cur_offset, vframe_size);
+ return EINVAL;
+ }
+ }
+ if (pframe != NULL && pframe_size != 0) {
+ /* Make sure that preview frame is in. */
+ if ((query.mReplyDataSize - cur_offset) >= pframe_size) {
+ memcpy(pframe, frame + cur_offset, pframe_size);
+ cur_offset += pframe_size;
+ } else {
+ ALOGE(
+ "%s: Reply %zu bytes is to small to contain %zu bytes preview frame",
+ __FUNCTION__, query.mReplyDataSize - cur_offset, pframe_size);
+ return EINVAL;
+ }
+ }
+
+ return NO_ERROR;
+}
+
+}; /* namespace android */
diff --git a/guest/hals/camera/QemuClient.h b/guest/hals/camera/QemuClient.h
new file mode 100644
index 000000000..290ab41c7
--- /dev/null
+++ b/guest/hals/camera/QemuClient.h
@@ -0,0 +1,433 @@
+/*
+ * Copyright (C) 2011 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 HW_EMULATOR_CAMERA_QEMU_CLIENT_H
+#define HW_EMULATOR_CAMERA_QEMU_CLIENT_H
+
+/*
+ * Contains declaration of classes that encapsulate connection to camera
+ * services in the emulator via qemu pipe.
+ */
+
+#include <hardware/qemud.h>
+
+namespace android {
+
+/****************************************************************************
+ * Qemu query
+ ***************************************************************************/
+
+/* Encapsulates a query to the emulator.
+ * Guest exchanges data with the emulator via queries sent over the qemu pipe.
+ * The queries as well as replies to the queries are all strings (except for the
+ * 'frame' query where reply is a framebuffer).
+ * Each query is formatted as such:
+ *
+ * "<query name>[ <parameters>]",
+ *
+ * where <query name> is a string representing query name, and <parameters> are
+ * optional parameters for the query. If parameters are present, they must be
+ * separated from the query name with a single space, and they must be formatted
+ * as such:
+ *
+ * "<name1>=<value1> <name2>=<value2> ... <nameN>=<valueN>"
+ *
+ * I.e.:
+ * - Every parameter must have a name, and a value.
+ * - Name and value must be separated with '='.
+ * - No spaces are allowed around '=' separating name and value.
+ * - Parameters must be separated with a single space character.
+ * - No '=' character is allowed in name and in value.
+ *
+ * There are certain restrictions on strings used in the query:
+ * - Spaces are allowed only as separators.
+ * - '=' are allowed only to divide parameter names from parameter values.
+ *
+ * Emulator replies to each query in two chunks:
+ * - 8 bytes encoding the payload size as a string containing hexadecimal
+ * representation of the payload size value. This is done in order to simplify
+ * dealing with different endianness on the host, and on the guest.
+ * - Payload, whose size is defined by the first chunk.
+ *
+ * Every payload always begins with two characters, encoding the result of the
+ * query:
+ * - 'ok' Encoding the success
+ * - 'ko' Encoding a failure.
+ * After that payload may have optional data. If payload has more data following
+ * the query result, there is a ':' character separating them. If payload
+ * carries only the result, it always ends with a zero-terminator. So, payload
+ * 'ok'/'ko' prefix is always 3 bytes long: it either includes a
+ * zero-terminator, if there is no data, or a ':' separator.
+ */
+class QemuQuery {
+ public:
+ /* Constructs an uninitialized QemuQuery instance. */
+ QemuQuery();
+
+ /* Constructs and initializes QemuQuery instance for a query.
+ * Param:
+ * query_string - Query string. This constructor can also be used to
+ * construct a query that doesn't have parameters. In this case query
+ * name can be passed as a parameter here.
+ */
+ explicit QemuQuery(const char* query_string);
+
+ /* Constructs and initializes QemuQuery instance for a query with parameters.
+ * Param:
+ * query_name - Query name.
+ * query_param - Query parameters. Can be NULL.
+ */
+ QemuQuery(const char* query_name, const char* query_param);
+
+ /* Destructs QemuQuery instance. */
+ ~QemuQuery();
+
+ /****************************************************************************
+ * Public API
+ ***************************************************************************/
+
+ /* Creates new query.
+ * Note: this method will reset this instance prior to creating a new query
+ * in order to discard possible "leftovers" from the previous query.
+ * Param:
+ * query_name - Query name.
+ * query_param - Query parameters. Can be NULL.
+ * Return:
+ * NO_ERROR on success, or an appropriate error status.
+ */
+ status_t createQuery(const char* name, const char* param);
+
+ /* Completes the query after a reply from the emulator.
+ * This method will parse the reply buffer, and calculate the final query
+ * status, which depends not only on the transport success / failure, but
+ * also on 'ok' / 'ko' in the reply buffer.
+ * Param:
+ * status - Query delivery status. This status doesn't necessarily reflects
+ * the final query status (which is defined by 'ok'/'ko' prefix in the
+ * reply buffer). This status simply states whether or not the query has
+ * been sent, and a reply has been received successfuly. However, if
+ * this status indicates a failure, it means that the entire query has
+ * failed.
+ * Return:
+ * NO_ERROR on success, or an appropriate error status on failure. Note that
+ * status returned here just signals whether or not the method has succeeded.
+ * Use isQuerySucceeded() / getCompletionStatus() methods of this class to
+ * check the final query status.
+ */
+ status_t completeQuery(status_t status);
+
+ /* Resets the query from a previous use. */
+ void resetQuery();
+
+ /* Checks if query has succeeded.
+ * Note that this method must be called after completeQuery() method of this
+ * class has been executed.
+ */
+ inline bool isQuerySucceeded() const {
+ return mQueryDeliveryStatus == NO_ERROR && mReplyStatus != 0;
+ }
+
+ /* Gets final completion status of the query.
+ * Note that this method must be called after completeQuery() method of this
+ * class has been executed.
+ * Return:
+ * NO_ERROR if query has succeeded, or an appropriate error status on query
+ * failure.
+ */
+ inline status_t getCompletionStatus() const {
+ if (mQueryDeliveryStatus == NO_ERROR) {
+ if (mReplyStatus) {
+ return NO_ERROR;
+ } else {
+ return EINVAL;
+ }
+ } else {
+ return mQueryDeliveryStatus;
+ }
+ }
+
+ /****************************************************************************
+ * Public data memebers
+ ***************************************************************************/
+
+ public:
+ /* Query string. */
+ char* mQuery;
+ /* Query delivery status. */
+ status_t mQueryDeliveryStatus;
+ /* Reply buffer */
+ char* mReplyBuffer;
+ /* Reply data (past 'ok'/'ko'). If NULL, there were no data in reply. */
+ char* mReplyData;
+ /* Reply buffer size. */
+ size_t mReplySize;
+ /* Reply data size. */
+ size_t mReplyDataSize;
+ /* Reply status: 1 - ok, 0 - ko. */
+ int mReplyStatus;
+
+ /****************************************************************************
+ * Private data memebers
+ ***************************************************************************/
+
+ protected:
+ /* Preallocated buffer for small queries. */
+ char mQueryPrealloc[256];
+};
+
+/****************************************************************************
+ * Qemu client base
+ ***************************************************************************/
+
+/* Encapsulates a connection to the 'camera' service in the emulator via qemu
+ * pipe.
+ */
+class QemuClient {
+ public:
+ /* Constructs QemuClient instance. */
+ QemuClient();
+
+ /* Destructs QemuClient instance. */
+ virtual ~QemuClient();
+
+ /****************************************************************************
+ * Qemu client API
+ ***************************************************************************/
+
+ public:
+ /* Connects to the 'camera' service in the emulator via qemu pipe.
+ * Param:
+ * param - Parameters to pass to the camera service. There are two types of
+ * camera services implemented by the emulator. The first one is a
+ * 'camera factory' type of service that provides list of cameras
+ * connected to the host. Another one is an 'emulated camera' type of
+ * service that provides interface to a camera connected to the host. At
+ * the connection time emulator makes distinction between the two by
+ * looking at connection parameters: no parameters means connection to
+ * the 'factory' service, while connection with parameters means
+ * connection to an 'emulated camera' service, where camera is identified
+ * by one of the connection parameters. So, passing NULL, or an empty
+ * string to this method will establish a connection with the 'factory'
+ * service, while not empty string passed here will establish connection
+ * with an 'emulated camera' service. Parameters defining the emulated
+ * camera must be formatted as such:
+ *
+ * "name=<device name> [inp_channel=<input channel #>]",
+ *
+ * where 'device name' is a required parameter defining name of the
+ * camera device, and 'input channel' is an optional parameter (positive
+ * integer), defining the input channel to use on the camera device.
+ * Note that device name passed here must have been previously obtained
+ * from the factory service using 'list' query.
+ * Return:
+ * NO_ERROR on success, or an appropriate error status.
+ */
+ virtual status_t connectClient(const char* param);
+
+ /* Disconnects from the service. */
+ virtual void disconnectClient();
+
+ /* Sends data to the service.
+ * Param:
+ * data, data_size - Data to send.
+ * Return:
+ * NO_ERROR on success, or an appropriate error status on failure.
+ */
+ virtual status_t sendMessage(const void* data, size_t data_size);
+
+ /* Receives data from the service.
+ * This method assumes that data to receive will come in two chunks: 8
+ * characters encoding the payload size in hexadecimal string, followed by
+ * the paylod (if any).
+ * This method will allocate data buffer where to receive the response.
+ * Param:
+ * data - Upon success contains address of the allocated data buffer with
+ * the data received from the service. The caller is responsible for
+ * freeing allocated data buffer.
+ * data_size - Upon success contains size of the data received from the
+ * service.
+ * Return:
+ * NO_ERROR on success, or an appropriate error status on failure.
+ */
+ virtual status_t receiveMessage(void** data, size_t* data_size);
+
+ /* Sends a query, and receives a response from the service.
+ * Param:
+ * query - Query to send to the service. When this method returns, the query
+ * is completed, and all its relevant data members are properly initialized.
+ * Return:
+ * NO_ERROR on success, or an appropriate error status on failure. Note that
+ * status returned here is not the final query status. Use
+ * isQuerySucceeded(), or getCompletionStatus() method on the query object to
+ * see if it has succeeded. However, if this method returns a failure, it
+ * means that the query has failed, and there is no guarantee that its data
+ * members are properly initialized (except for the 'mQueryDeliveryStatus',
+ * which is always in the proper state).
+ */
+ virtual status_t doQuery(QemuQuery* query);
+
+ /****************************************************************************
+ * Data members
+ ***************************************************************************/
+
+ protected:
+ /* Qemu pipe handle. */
+ int mPipeFD;
+
+ private:
+ /* Camera service name. */
+ static const char mCameraServiceName[];
+};
+
+/****************************************************************************
+ * Qemu client for the 'factory' service.
+ ***************************************************************************/
+
+/* Encapsulates QemuClient for the 'factory' service. */
+class FactoryQemuClient : public QemuClient {
+ public:
+ /* Constructs FactoryQemuClient instance. */
+ FactoryQemuClient();
+
+ /* Destructs FactoryQemuClient instance. */
+ ~FactoryQemuClient();
+
+ /****************************************************************************
+ * Public API
+ ***************************************************************************/
+
+ public:
+ /* Lists camera devices connected to the host.
+ * Param:
+ * list - Upon success contains a list of cameras connected to the host. The
+ * list returned here is represented as a string, containing multiple
+ * lines separated with '\n', where each line represents a camera. Each
+ * camera line is formatted as such:
+ *
+ * "name=<device name> channel=<num> pix=<num>
+ * framedims=<dimensions>\n"
+ *
+ * Where:
+ * - 'name' is the name of the camera device attached to the host. This
+ * name must be used for subsequent connection to the 'emulated camera'
+ * service for that camera.
+ * - 'channel' - input channel number (positive int) to use to
+ * communicate with the camera.
+ * - 'pix' - pixel format (a "fourcc" uint), chosen for the video frames
+ * by the camera service.
+ * - 'framedims' contains a list of frame dimensions supported by the
+ * camera for the chosen pixel format. Each etry in the list is in form
+ * '<width>x<height>', where 'width' and 'height' are numeric values
+ * for width and height of a supported frame dimension. Entries in
+ * this list are separated with ',' with no spaces between the entries.
+ * Return:
+ * NO_ERROR on success, or an appropriate error status on failure.
+ */
+ status_t listCameras(char** list);
+
+ /****************************************************************************
+ * Names of the queries available for the emulated camera factory.
+ ***************************************************************************/
+
+ private:
+ /* List cameras connected to the host. */
+ static const char mQueryList[];
+};
+
+/****************************************************************************
+ * Qemu client for an 'emulated camera' service.
+ ***************************************************************************/
+
+/* Encapsulates QemuClient for an 'emulated camera' service.
+ */
+class CameraQemuClient : public QemuClient {
+ public:
+ /* Constructs CameraQemuClient instance. */
+ CameraQemuClient();
+
+ /* Destructs CameraQemuClient instance. */
+ ~CameraQemuClient();
+
+ /****************************************************************************
+ * Public API
+ ***************************************************************************/
+
+ public:
+ /* Queries camera connection.
+ * Return:
+ * NO_ERROR on success, or an appropriate error status on failure.
+ */
+ status_t queryConnect();
+
+ /* Queries camera disconnection.
+ * Return:
+ * NO_ERROR on success, or an appropriate error status on failure.
+ */
+ status_t queryDisconnect();
+
+ /* Queries camera to start capturing video.
+ * Param:
+ * pixel_format - Pixel format that is used by the client to push video
+ * frames to the camera framework.
+ * width, height - Frame dimensions, requested by the framework.
+ * Return:
+ * NO_ERROR on success, or an appropriate error status on failure.
+ */
+ status_t queryStart(uint32_t pixel_format, int width, int height);
+
+ /* Queries camera to stop capturing video.
+ * Return:
+ * NO_ERROR on success, or an appropriate error status on failure.
+ */
+ status_t queryStop();
+
+ /* Queries camera for the next video frame.
+ * Param:
+ * vframe, vframe_size - Define buffer, allocated to receive a video frame.
+ * Any of these parameters can be 0, indicating that the caller is
+ * interested only in preview frame.
+ * pframe, pframe_size - Define buffer, allocated to receive a preview frame.
+ * Any of these parameters can be 0, indicating that the caller is
+ * interested only in video frame.
+ * r_scale, g_scale, b_scale - White balance scale.
+ * exposure_comp - Expsoure compensation.
+ * Return:
+ * NO_ERROR on success, or an appropriate error status on failure.
+ */
+ status_t queryFrame(void* vframe, void* pframe, size_t vframe_size,
+ size_t pframe_size, float r_scale, float g_scale,
+ float b_scale, float exposure_comp);
+
+ /****************************************************************************
+ * Names of the queries available for the emulated camera.
+ ***************************************************************************/
+
+ private:
+ /* Connect to the camera. */
+ static const char mQueryConnect[];
+ /* Disconnect from the camera. */
+ static const char mQueryDisconnect[];
+ /* Start video capturing. */
+ static const char mQueryStart[];
+ /* Stop video capturing. */
+ static const char mQueryStop[];
+ /* Query frame(s). */
+ static const char mQueryFrame[];
+};
+
+}; /* namespace android */
+
+#endif /* HW_EMULATOR_CAMERA_QEMU_CLIENT_H */
diff --git a/guest/hals/camera/Thumbnail.cpp b/guest/hals/camera/Thumbnail.cpp
new file mode 100644
index 000000000..e8f8126e2
--- /dev/null
+++ b/guest/hals/camera/Thumbnail.cpp
@@ -0,0 +1,170 @@
+/*
+* Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Thumbnail.h"
+
+#define LOG_NDEBUG 0
+#define LOG_TAG "EmulatedCamera_Thumbnail"
+#include <log/log.h>
+#include <libexif/exif-data.h>
+#include <libyuv.h>
+
+#include "JpegCompressor.h"
+
+#include <vector>
+
+/*
+ * 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 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 {
+
+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;
+ 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);
+
+ // The downscaled U and V planes will also be linear instead of interleaved,
+ // allocate space for them here
+ const size_t destUVPlaneSize = (thumbnailWidth * thumbnailHeight) / 4;
+ std::vector<unsigned char> destPlanes(destUVPlaneSize * 2);
+ unsigned char* yDestPlane = &(*thumbnail)[0];
+ 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
+ int result = libyuv::I420Scale(ySourcePlane, sourceWidth,
+ uSourcePlane, sourceWidth / 2,
+ vSourcePlane, sourceWidth / 2,
+ sourceWidth, sourceHeight,
+ yDestPlane, thumbnailWidth,
+ uDestPlane, thumbnailWidth / 2,
+ vDestPlane, thumbnailWidth / 2,
+ thumbnailWidth, thumbnailHeight,
+ libyuv::kFilterBilinear);
+ if (result != 0) {
+ ALOGE("Unable to create thumbnail, downscaling failed with error: %d",
+ result);
+ 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;
+}
+
+bool createThumbnail(const unsigned char* sourceImage,
+ int sourceWidth, int sourceHeight,
+ int thumbWidth, int thumbHeight, int quality,
+ ExifData* exifData) {
+ if (thumbWidth <= 0 || thumbHeight <= 0) {
+ ALOGE("%s: Invalid thumbnail width=%d or height=%d, must be > 0",
+ __FUNCTION__, thumbWidth, thumbHeight);
+ return false;
+ }
+
+ // First downscale the source image into a thumbnail-sized raw image
+ std::vector<unsigned char> rawThumbnail;
+ if (!createRawThumbnail(sourceImage, sourceWidth, sourceHeight,
+ thumbWidth, thumbHeight, &rawThumbnail)) {
+ // The thumbnail function will log an appropriate error if needed
+ return false;
+ }
+
+ // And then compress it into JPEG format without any EXIF data
+ NV21JpegCompressor compressor;
+ status_t result = compressor.compressRawImage(&rawThumbnail[0],
+ nullptr /* EXIF */,
+ quality, thumbWidth, thumbHeight);
+ if (result != NO_ERROR) {
+ ALOGE("%s: Unable to compress thumbnail", __FUNCTION__);
+ return false;
+ }
+
+ // And finally put it in the EXIF data. This transfers ownership of the
+ // malloc'd memory to the EXIF data structure. As long as the EXIF data
+ // structure is free'd using the EXIF library this memory will be free'd.
+ exifData->size = compressor.getCompressedSize();
+ exifData->data = reinterpret_cast<unsigned char*>(malloc(exifData->size));
+ if (exifData->data == nullptr) {
+ ALOGE("%s: Unable to allocate %u bytes of memory for thumbnail",
+ __FUNCTION__, exifData->size);
+ exifData->size = 0;
+ return false;
+ }
+ compressor.getCompressedImage(exifData->data);
+ return true;
+}
+
+} // namespace android
+
diff --git a/guest/hals/camera/Thumbnail.h b/guest/hals/camera/Thumbnail.h
new file mode 100644
index 000000000..b27636c1d
--- /dev/null
+++ b/guest/hals/camera/Thumbnail.h
@@ -0,0 +1,37 @@
+/*
+* Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef GOLDFISH_CAMERA_THUMBNAIL_H
+#define GOLDFISH_CAMERA_THUMBNAIL_H
+
+struct _ExifData;
+typedef struct _ExifData ExifData;
+
+namespace android {
+
+/* Create a thumbnail from NV21 source data in |sourceImage| with the given
+ * dimensions. The resulting thumbnail is JPEG compressed and a pointer and size
+ * is placed in |exifData| which takes ownership of the allocated memory.
+ */
+bool createThumbnail(const unsigned char* sourceImage,
+ int sourceWidth, int sourceHeight,
+ int thumbnailWidth, int thumbnailHeight, int quality,
+ ExifData* exifData);
+
+} // namespace android
+
+#endif // GOLDFISH_CAMERA_THUMBNAIL_H
+
diff --git a/guest/hals/camera/VSoCEmulatedCameraHotplugThread.cpp b/guest/hals/camera/VSoCEmulatedCameraHotplugThread.cpp
new file mode 100644
index 000000000..2378dc072
--- /dev/null
+++ b/guest/hals/camera/VSoCEmulatedCameraHotplugThread.cpp
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#define LOG_NDEBUG 0
+#define LOG_TAG "EmulatedCamera_HotplugThread"
+#include <log/log.h>
+
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "EmulatedCameraFactory.h"
+#include "EmulatedCameraHotplugThread.h"
+
+#define SubscriberInfo EmulatedCameraHotplugThread::SubscriberInfo
+
+namespace android {
+
+EmulatedCameraHotplugThread::EmulatedCameraHotplugThread(
+ size_t /*totalCameraCount*/)
+ : Thread(/*canCallJava*/ false) {}
+
+EmulatedCameraHotplugThread::~EmulatedCameraHotplugThread() {}
+
+status_t EmulatedCameraHotplugThread::requestExitAndWait() {
+ ALOGE("%s: Not implemented. Use requestExit + join instead", __FUNCTION__);
+ return INVALID_OPERATION;
+}
+
+void EmulatedCameraHotplugThread::requestExit() {
+ ALOGV("%s: Requesting thread exit", __FUNCTION__);
+ mRunning = false;
+}
+
+status_t EmulatedCameraHotplugThread::readyToRun() { return OK; }
+
+bool EmulatedCameraHotplugThread::threadLoop() {
+ // Thread is irrelevant right now; hoplug is not supported.
+ return false;
+}
+
+String8 EmulatedCameraHotplugThread::getFilePath(int /*cameraId*/) const {
+ return String8();
+}
+
+bool EmulatedCameraHotplugThread::createFileIfNotExists(
+ int /*cameraId*/) const {
+ return true;
+}
+
+int EmulatedCameraHotplugThread::getCameraId(String8 /*filePath*/) const {
+ // Not used anywhere.
+ return NAME_NOT_FOUND;
+}
+
+int EmulatedCameraHotplugThread::getCameraId(int /*wd*/) const {
+ // Not used anywhere.
+ return NAME_NOT_FOUND;
+}
+
+SubscriberInfo* EmulatedCameraHotplugThread::getSubscriberInfo(
+ int /*cameraId*/) {
+ // Not used anywhere.
+ return NULL;
+}
+
+bool EmulatedCameraHotplugThread::addWatch(int /*cameraId*/) { return true; }
+
+bool EmulatedCameraHotplugThread::removeWatch(int /*cameraId*/) { return true; }
+
+int EmulatedCameraHotplugThread::readFile(String8 /*filePath*/) const {
+ return 1;
+}
+
+} // namespace android
diff --git a/guest/hals/camera/fake-pipeline2/Base.h b/guest/hals/camera/fake-pipeline2/Base.h
new file mode 100644
index 000000000..3cd1e1535
--- /dev/null
+++ b/guest/hals/camera/fake-pipeline2/Base.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+/**
+ * This file includes various basic structures that are needed by multiple parts
+ * of the fake camera 2 implementation.
+ */
+
+#ifndef HW_EMULATOR_CAMERA2_BASE_H
+#define HW_EMULATOR_CAMERA2_BASE_H
+
+#include <hardware/camera2.h>
+#include <utils/Vector.h>
+
+namespace android {
+
+/* Internal structure for passing buffers across threads */
+struct StreamBuffer {
+ // Positive numbers are output streams
+ // Negative numbers are input reprocess streams
+ // Zero is an auxillary buffer
+ int streamId;
+ uint32_t width, height;
+ uint32_t format;
+ uint32_t dataSpace;
+ uint32_t stride;
+ buffer_handle_t *buffer;
+ uint8_t *img;
+};
+typedef Vector<StreamBuffer> Buffers;
+
+struct Stream {
+ const camera2_stream_ops_t *ops;
+ uint32_t width, height;
+ int32_t format;
+ uint32_t stride;
+};
+
+struct ReprocessStream {
+ const camera2_stream_in_ops_t *ops;
+ uint32_t width, height;
+ int32_t format;
+ uint32_t stride;
+ // -1 if the reprocessing stream is independent
+ int32_t sourceStreamId;
+};
+
+} // namespace android
+
+#endif
diff --git a/guest/hals/camera/fake-pipeline2/JpegCompressor.cpp b/guest/hals/camera/fake-pipeline2/JpegCompressor.cpp
new file mode 100644
index 000000000..22c5d3ae3
--- /dev/null
+++ b/guest/hals/camera/fake-pipeline2/JpegCompressor.cpp
@@ -0,0 +1,286 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "EmulatedCamera2_JpegCompressor"
+
+#include <utils/Log.h>
+
+#include "../EmulatedFakeCamera2.h"
+#include "../EmulatedFakeCamera3.h"
+#include "JpegCompressor.h"
+
+namespace android {
+
+JpegCompressor::JpegCompressor()
+ : Thread(false),
+ mIsBusy(false),
+ mSynchronous(false),
+ mBuffers(NULL),
+ mListener(NULL),
+ mFoundAux(false) {}
+
+JpegCompressor::~JpegCompressor() { Mutex::Autolock lock(mMutex); }
+
+status_t JpegCompressor::reserve() {
+ Mutex::Autolock busyLock(mBusyMutex);
+ if (mIsBusy) {
+ ALOGE("%s: Already processing a buffer!", __FUNCTION__);
+ return INVALID_OPERATION;
+ }
+ mIsBusy = true;
+ return OK;
+}
+
+status_t JpegCompressor::start(Buffers *buffers, JpegListener *listener) {
+ if (listener == NULL) {
+ ALOGE("%s: NULL listener not allowed!", __FUNCTION__);
+ return BAD_VALUE;
+ }
+ ALOGV("%s: Starting JPEG compression thread", __FUNCTION__);
+ Mutex::Autolock lock(mMutex);
+ {
+ Mutex::Autolock busyLock(mBusyMutex);
+
+ if (!mIsBusy) {
+ ALOGE("Called start without reserve() first!");
+ return INVALID_OPERATION;
+ }
+ mSynchronous = false;
+ mBuffers = buffers;
+ mListener = listener;
+ }
+
+ status_t res;
+ res = run("EmulatedFakeCamera2::JpegCompressor");
+ if (res != OK) {
+ ALOGE("%s: Unable to start up compression thread: %s (%d)", __FUNCTION__,
+ strerror(-res), res);
+ delete mBuffers;
+ }
+ return res;
+}
+
+status_t JpegCompressor::compressSynchronous(Buffers *buffers) {
+ status_t res;
+
+ Mutex::Autolock lock(mMutex);
+ {
+ Mutex::Autolock busyLock(mBusyMutex);
+
+ if (mIsBusy) {
+ ALOGE("%s: Already processing a buffer!", __FUNCTION__);
+ return INVALID_OPERATION;
+ }
+
+ mIsBusy = true;
+ mSynchronous = true;
+ mBuffers = buffers;
+ }
+
+ res = compress();
+
+ cleanUp();
+
+ return res;
+}
+
+status_t JpegCompressor::cancel() {
+ requestExitAndWait();
+ return OK;
+}
+
+status_t JpegCompressor::readyToRun() { return OK; }
+
+bool JpegCompressor::threadLoop() {
+ status_t res;
+ ALOGV("%s: Starting compression thread", __FUNCTION__);
+
+ res = compress();
+
+ mListener->onJpegDone(mJpegBuffer, res == OK);
+
+ cleanUp();
+
+ return false;
+}
+
+status_t JpegCompressor::compress() {
+ // Find source and target buffers. Assumes only one buffer matches
+ // each condition!
+ ALOGV("%s: Compressing start", __FUNCTION__);
+ for (size_t i = 0; i < mBuffers->size(); i++) {
+ const StreamBuffer &b = (*mBuffers)[i];
+ if (b.format == HAL_PIXEL_FORMAT_BLOB) {
+ mJpegBuffer = b;
+ mFoundJpeg = true;
+ } else if (b.streamId <= 0) {
+ mAuxBuffer = b;
+ mFoundAux = true;
+ }
+ if (mFoundJpeg && mFoundAux) break;
+ }
+ if (!mFoundJpeg || !mFoundAux) {
+ ALOGE("%s: Unable to find buffers for JPEG source/destination",
+ __FUNCTION__);
+ return BAD_VALUE;
+ }
+
+ // Set up error management
+
+ mJpegErrorInfo = NULL;
+ JpegError error;
+ error.parent = this;
+
+ mCInfo.err = jpeg_std_error(&error);
+ mCInfo.err->error_exit = jpegErrorHandler;
+
+ jpeg_create_compress(&mCInfo);
+ if (checkError("Error initializing compression")) return NO_INIT;
+
+ // Route compressed data straight to output stream buffer
+
+ JpegDestination jpegDestMgr;
+ jpegDestMgr.parent = this;
+ jpegDestMgr.init_destination = jpegInitDestination;
+ jpegDestMgr.empty_output_buffer = jpegEmptyOutputBuffer;
+ jpegDestMgr.term_destination = jpegTermDestination;
+
+ mCInfo.dest = &jpegDestMgr;
+
+ // Set up compression parameters
+
+ mCInfo.image_width = mAuxBuffer.width;
+ mCInfo.image_height = mAuxBuffer.height;
+ mCInfo.input_components = 3;
+ mCInfo.in_color_space = JCS_RGB;
+
+ jpeg_set_defaults(&mCInfo);
+ if (checkError("Error configuring defaults")) return NO_INIT;
+
+ // Do compression
+
+ jpeg_start_compress(&mCInfo, TRUE);
+ if (checkError("Error starting compression")) return NO_INIT;
+
+ size_t rowStride = mAuxBuffer.stride * 3;
+ const size_t kChunkSize = 32;
+ while (mCInfo.next_scanline < mCInfo.image_height) {
+ JSAMPROW chunk[kChunkSize];
+ for (size_t i = 0; i < kChunkSize; i++) {
+ chunk[i] =
+ (JSAMPROW)(mAuxBuffer.img + (i + mCInfo.next_scanline) * rowStride);
+ }
+ jpeg_write_scanlines(&mCInfo, chunk, kChunkSize);
+ if (checkError("Error while compressing")) return NO_INIT;
+ if (exitPending()) {
+ ALOGV("%s: Cancel called, exiting early", __FUNCTION__);
+ return TIMED_OUT;
+ }
+ }
+
+ jpeg_finish_compress(&mCInfo);
+ if (checkError("Error while finishing compression")) return NO_INIT;
+
+ // All done
+ ALOGV("%s: Compressing done", __FUNCTION__);
+
+ return OK;
+}
+
+bool JpegCompressor::isBusy() {
+ Mutex::Autolock busyLock(mBusyMutex);
+ return mIsBusy;
+}
+
+bool JpegCompressor::isStreamInUse(uint32_t id) {
+ Mutex::Autolock lock(mBusyMutex);
+
+ if (mBuffers && mIsBusy) {
+ for (size_t i = 0; i < mBuffers->size(); i++) {
+ if ((*mBuffers)[i].streamId == (int)id) return true;
+ }
+ }
+ return false;
+}
+
+bool JpegCompressor::waitForDone(nsecs_t timeout) {
+ Mutex::Autolock lock(mBusyMutex);
+ while (mIsBusy) {
+ status_t res = mDone.waitRelative(mBusyMutex, timeout);
+ if (res != OK) return false;
+ }
+ return true;
+}
+
+bool JpegCompressor::checkError(const char *msg) {
+ if (mJpegErrorInfo) {
+ char errBuffer[JMSG_LENGTH_MAX];
+ mJpegErrorInfo->err->format_message(mJpegErrorInfo, errBuffer);
+ ALOGE("%s: %s: %s", __FUNCTION__, msg, errBuffer);
+ mJpegErrorInfo = NULL;
+ return true;
+ }
+ return false;
+}
+
+void JpegCompressor::cleanUp() {
+ jpeg_destroy_compress(&mCInfo);
+ Mutex::Autolock lock(mBusyMutex);
+
+ if (mFoundAux) {
+ if (mAuxBuffer.streamId == 0) {
+ delete[] mAuxBuffer.img;
+ } else if (!mSynchronous) {
+ mListener->onJpegInputDone(mAuxBuffer);
+ }
+ }
+ if (!mSynchronous) {
+ delete mBuffers;
+ }
+
+ mBuffers = NULL;
+
+ mIsBusy = false;
+ mDone.signal();
+}
+
+void JpegCompressor::jpegErrorHandler(j_common_ptr cinfo) {
+ JpegError *error = static_cast<JpegError *>(cinfo->err);
+ error->parent->mJpegErrorInfo = cinfo;
+}
+
+void JpegCompressor::jpegInitDestination(j_compress_ptr cinfo) {
+ JpegDestination *dest = static_cast<JpegDestination *>(cinfo->dest);
+ ALOGV("%s: Setting destination to %p, size %zu", __FUNCTION__,
+ dest->parent->mJpegBuffer.img, kMaxJpegSize);
+ dest->next_output_byte = (JOCTET *)(dest->parent->mJpegBuffer.img);
+ dest->free_in_buffer = kMaxJpegSize;
+}
+
+boolean JpegCompressor::jpegEmptyOutputBuffer(j_compress_ptr /*cinfo*/) {
+ ALOGE("%s: JPEG destination buffer overflow!", __FUNCTION__);
+ return true;
+}
+
+void JpegCompressor::jpegTermDestination(j_compress_ptr cinfo) {
+ ALOGV("%s: Done writing JPEG data. %zu bytes left in buffer", __FUNCTION__,
+ cinfo->dest->free_in_buffer);
+}
+
+JpegCompressor::JpegListener::~JpegListener() {}
+
+} // namespace android
diff --git a/guest/hals/camera/fake-pipeline2/JpegCompressor.h b/guest/hals/camera/fake-pipeline2/JpegCompressor.h
new file mode 100644
index 000000000..bdbc77220
--- /dev/null
+++ b/guest/hals/camera/fake-pipeline2/JpegCompressor.h
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+/**
+ * This class simulates a hardware JPEG compressor. It receives image buffers
+ * in RGBA_8888 format, processes them in a worker thread, and then pushes them
+ * out to their destination stream.
+ */
+
+#ifndef HW_EMULATOR_CAMERA2_JPEG_H
+#define HW_EMULATOR_CAMERA2_JPEG_H
+
+#include "utils/Mutex.h"
+#include "utils/Thread.h"
+#include "utils/Timers.h"
+
+#include "Base.h"
+
+#include <stdio.h>
+
+extern "C" {
+#include <jpeglib.h>
+}
+
+namespace android {
+
+class JpegCompressor : private Thread, public virtual RefBase {
+ public:
+ JpegCompressor();
+ ~JpegCompressor();
+
+ struct JpegListener {
+ // Called when JPEG compression has finished, or encountered an error
+ virtual void onJpegDone(const StreamBuffer &jpegBuffer, bool success) = 0;
+ // Called when the input buffer for JPEG is not needed any more,
+ // if the buffer came from the framework.
+ virtual void onJpegInputDone(const StreamBuffer &inputBuffer) = 0;
+ virtual ~JpegListener();
+ };
+
+ // Start compressing COMPRESSED format buffers; JpegCompressor takes
+ // ownership of the Buffers vector.
+ // Reserve() must be called first.
+ status_t start(Buffers *buffers, JpegListener *listener);
+
+ // Compress and block until buffer is complete.
+ status_t compressSynchronous(Buffers *buffers);
+
+ status_t cancel();
+
+ bool isBusy();
+ bool isStreamInUse(uint32_t id);
+
+ bool waitForDone(nsecs_t timeout);
+
+ // Reserve the compressor for a later start() call.
+ status_t reserve();
+
+ // TODO: Measure this
+ static const size_t kMaxJpegSize = 300000;
+
+ private:
+ Mutex mBusyMutex;
+ bool mIsBusy;
+ Condition mDone;
+ bool mSynchronous;
+
+ Mutex mMutex;
+
+ Buffers *mBuffers;
+ JpegListener *mListener;
+
+ StreamBuffer mJpegBuffer, mAuxBuffer;
+ bool mFoundJpeg, mFoundAux;
+
+ jpeg_compress_struct mCInfo;
+
+ struct JpegError : public jpeg_error_mgr {
+ JpegCompressor *parent;
+ };
+ j_common_ptr mJpegErrorInfo;
+
+ struct JpegDestination : public jpeg_destination_mgr {
+ JpegCompressor *parent;
+ };
+
+ static void jpegErrorHandler(j_common_ptr cinfo);
+
+ static void jpegInitDestination(j_compress_ptr cinfo);
+ static boolean jpegEmptyOutputBuffer(j_compress_ptr cinfo);
+ static void jpegTermDestination(j_compress_ptr cinfo);
+
+ bool checkError(const char *msg);
+ status_t compress();
+
+ void cleanUp();
+
+ /**
+ * Inherited Thread virtual overrides
+ */
+ private:
+ virtual status_t readyToRun();
+ virtual bool threadLoop();
+};
+
+} // namespace android
+
+#endif
diff --git a/guest/hals/camera/fake-pipeline2/Scene.cpp b/guest/hals/camera/fake-pipeline2/Scene.cpp
new file mode 100644
index 000000000..c70dc4c8d
--- /dev/null
+++ b/guest/hals/camera/fake-pipeline2/Scene.cpp
@@ -0,0 +1,436 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "EmulatedCamera_Scene"
+#include "Scene.h"
+#include <stdlib.h>
+#include <utils/Log.h>
+#include <cmath>
+
+// TODO: This should probably be done host-side in OpenGL for speed and better
+// quality
+
+namespace android {
+
+// Define single-letter shortcuts for scene definition, for directly indexing
+// mCurrentColors
+#define G (Scene::GRASS * Scene::NUM_CHANNELS)
+#define S (Scene::GRASS_SHADOW * Scene::NUM_CHANNELS)
+#define H (Scene::HILL * Scene::NUM_CHANNELS)
+#define W (Scene::WALL * Scene::NUM_CHANNELS)
+#define R (Scene::ROOF * Scene::NUM_CHANNELS)
+#define D (Scene::DOOR * Scene::NUM_CHANNELS)
+#define C (Scene::CHIMNEY * Scene::NUM_CHANNELS)
+#define I (Scene::WINDOW * Scene::NUM_CHANNELS)
+#define U (Scene::SUN * Scene::NUM_CHANNELS)
+#define K (Scene::SKY * Scene::NUM_CHANNELS)
+#define M (Scene::MOON * Scene::NUM_CHANNELS)
+
+const int Scene::kSceneWidth = 20;
+const int Scene::kSceneHeight = 20;
+
+const uint8_t Scene::kScene[Scene::kSceneWidth * Scene::kSceneHeight] = {
+ // 5 10 15 20
+ K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K,
+ K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K,
+ K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K,
+ K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K,
+ K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, // 5
+ K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K, K,
+ K, K, K, K, K, K, K, K, H, H, H, H, H, H, H, H, H, H, H, H,
+ K, K, K, K, K, K, K, K, H, H, H, H, H, H, H, C, C, H, H, H,
+ K, K, K, K, K, K, H, H, H, H, H, H, H, H, H, C, C, H, H, H,
+ H, K, K, K, K, K, H, R, R, R, R, R, R, R, R, R, R, R, R, H, // 10
+ H, K, K, K, K, H, H, R, R, R, R, R, R, R, R, R, R, R, R, H,
+ H, H, H, K, K, H, H, R, R, R, R, R, R, R, R, R, R, R, R, H,
+ H, H, H, K, K, H, H, H, W, W, W, W, W, W, W, W, W, W, H, H,
+ S, S, S, G, G, S, S, S, W, W, W, W, W, W, W, W, W, W, S, S,
+ S, G, G, G, G, S, S, S, W, I, I, W, D, D, W, I, I, W, S, S, // 15
+ G, G, G, G, G, G, S, S, W, I, I, W, D, D, W, I, I, W, S, S,
+ G, G, G, G, G, G, G, G, W, W, W, W, D, D, W, W, W, W, G, G,
+ G, G, G, G, G, G, G, G, W, W, W, W, D, D, W, W, W, W, G, G,
+ G, G, G, G, G, G, G, G, S, S, S, S, S, S, S, S, S, S, G, G,
+ G, G, G, G, G, G, G, G, S, S, S, S, S, S, S, S, S, S, G, G, // 20
+ // 5 10 15 20
+};
+
+#undef G
+#undef S
+#undef H
+#undef W
+#undef R
+#undef D
+#undef C
+#undef I
+#undef U
+#undef K
+#undef M
+
+Scene::Scene(int sensorWidthPx, int sensorHeightPx, float sensorSensitivity)
+ : mSensorWidth(sensorWidthPx),
+ mSensorHeight(sensorHeightPx),
+ mHour(12),
+ mExposureDuration(0.033f),
+ mSensorSensitivity(sensorSensitivity) {
+ // Map scene to sensor pixels
+ if (mSensorWidth > mSensorHeight) {
+ mMapDiv = (mSensorWidth / (kSceneWidth + 1)) + 1;
+ } else {
+ mMapDiv = (mSensorHeight / (kSceneHeight + 1)) + 1;
+ }
+ mOffsetX = (kSceneWidth * mMapDiv - mSensorWidth) / 2;
+ mOffsetY = (kSceneHeight * mMapDiv - mSensorHeight) / 2;
+
+ // Assume that sensor filters are sRGB primaries to start
+ mFilterR[0] = 3.2406f;
+ mFilterR[1] = -1.5372f;
+ mFilterR[2] = -0.4986f;
+ mFilterGr[0] = -0.9689f;
+ mFilterGr[1] = 1.8758f;
+ mFilterGr[2] = 0.0415f;
+ mFilterGb[0] = -0.9689f;
+ mFilterGb[1] = 1.8758f;
+ mFilterGb[2] = 0.0415f;
+ mFilterB[0] = 0.0557f;
+ mFilterB[1] = -0.2040f;
+ mFilterB[2] = 1.0570f;
+}
+
+Scene::~Scene() {}
+
+void Scene::setColorFilterXYZ(float rX, float rY, float rZ, float grX,
+ float grY, float grZ, float gbX, float gbY,
+ float gbZ, float bX, float bY, float bZ) {
+ mFilterR[0] = rX;
+ mFilterR[1] = rY;
+ mFilterR[2] = rZ;
+ mFilterGr[0] = grX;
+ mFilterGr[1] = grY;
+ mFilterGr[2] = grZ;
+ mFilterGb[0] = gbX;
+ mFilterGb[1] = gbY;
+ mFilterGb[2] = gbZ;
+ mFilterB[0] = bX;
+ mFilterB[1] = bY;
+ mFilterB[2] = bZ;
+}
+
+void Scene::setHour(int hour) {
+ ALOGV("Hour set to: %d", hour);
+ mHour = hour % 24;
+}
+
+int Scene::getHour() { return mHour; }
+
+void Scene::setExposureDuration(float seconds) { mExposureDuration = seconds; }
+
+void Scene::calculateScene(nsecs_t time) {
+ // Calculate time fractions for interpolation
+ int timeIdx = mHour / kTimeStep;
+ int nextTimeIdx = (timeIdx + 1) % (24 / kTimeStep);
+ const nsecs_t kOneHourInNsec = 1e9 * 60 * 60;
+ nsecs_t timeSinceIdx = (mHour - timeIdx * kTimeStep) * kOneHourInNsec + time;
+ float timeFrac = timeSinceIdx / (float)(kOneHourInNsec * kTimeStep);
+
+ // Determine overall sunlight levels
+ float sunLux =
+ kSunlight[timeIdx] * (1 - timeFrac) + kSunlight[nextTimeIdx] * timeFrac;
+ ALOGV("Sun lux: %f", sunLux);
+
+ float sunShadeLux = sunLux * (kDaylightShadeIllum / kDirectSunIllum);
+
+ // Determine sun/shade illumination chromaticity
+ float currentSunXY[2];
+ float currentShadeXY[2];
+
+ const float *prevSunXY, *nextSunXY;
+ const float *prevShadeXY, *nextShadeXY;
+ if (kSunlight[timeIdx] == kSunsetIllum ||
+ kSunlight[timeIdx] == kTwilightIllum) {
+ prevSunXY = kSunsetXY;
+ prevShadeXY = kSunsetXY;
+ } else {
+ prevSunXY = kDirectSunlightXY;
+ prevShadeXY = kDaylightXY;
+ }
+ if (kSunlight[nextTimeIdx] == kSunsetIllum ||
+ kSunlight[nextTimeIdx] == kTwilightIllum) {
+ nextSunXY = kSunsetXY;
+ nextShadeXY = kSunsetXY;
+ } else {
+ nextSunXY = kDirectSunlightXY;
+ nextShadeXY = kDaylightXY;
+ }
+ currentSunXY[0] = prevSunXY[0] * (1 - timeFrac) + nextSunXY[0] * timeFrac;
+ currentSunXY[1] = prevSunXY[1] * (1 - timeFrac) + nextSunXY[1] * timeFrac;
+
+ currentShadeXY[0] =
+ prevShadeXY[0] * (1 - timeFrac) + nextShadeXY[0] * timeFrac;
+ currentShadeXY[1] =
+ prevShadeXY[1] * (1 - timeFrac) + nextShadeXY[1] * timeFrac;
+
+ ALOGV("Sun XY: %f, %f, Shade XY: %f, %f", currentSunXY[0], currentSunXY[1],
+ currentShadeXY[0], currentShadeXY[1]);
+
+ // Converting for xyY to XYZ:
+ // X = Y / y * x
+ // Y = Y
+ // Z = Y / y * (1 - x - y);
+ float sunXYZ[3] = {
+ sunLux / currentSunXY[1] * currentSunXY[0], sunLux,
+ sunLux / currentSunXY[1] * (1 - currentSunXY[0] - currentSunXY[1])};
+ float sunShadeXYZ[3] = {sunShadeLux / currentShadeXY[1] * currentShadeXY[0],
+ sunShadeLux,
+ sunShadeLux / currentShadeXY[1] *
+ (1 - currentShadeXY[0] - currentShadeXY[1])};
+ ALOGV("Sun XYZ: %f, %f, %f", sunXYZ[0], sunXYZ[1], sunXYZ[2]);
+ ALOGV("Sun shade XYZ: %f, %f, %f", sunShadeXYZ[0], sunShadeXYZ[1],
+ sunShadeXYZ[2]);
+
+ // Determine moonlight levels
+ float moonLux =
+ kMoonlight[timeIdx] * (1 - timeFrac) + kMoonlight[nextTimeIdx] * timeFrac;
+ float moonShadeLux = moonLux * (kDaylightShadeIllum / kDirectSunIllum);
+
+ float moonXYZ[3] = {
+ moonLux / kMoonlightXY[1] * kMoonlightXY[0], moonLux,
+ moonLux / kMoonlightXY[1] * (1 - kMoonlightXY[0] - kMoonlightXY[1])};
+ float moonShadeXYZ[3] = {
+ moonShadeLux / kMoonlightXY[1] * kMoonlightXY[0], moonShadeLux,
+ moonShadeLux / kMoonlightXY[1] * (1 - kMoonlightXY[0] - kMoonlightXY[1])};
+
+ // Determine starlight level
+ const float kClearNightXYZ[3] = {
+ kClearNightIllum / kMoonlightXY[1] * kMoonlightXY[0], kClearNightIllum,
+ kClearNightIllum / kMoonlightXY[1] *
+ (1 - kMoonlightXY[0] - kMoonlightXY[1])};
+
+ // Calculate direct and shaded light
+ float directIllumXYZ[3] = {
+ sunXYZ[0] + moonXYZ[0] + kClearNightXYZ[0],
+ sunXYZ[1] + moonXYZ[1] + kClearNightXYZ[1],
+ sunXYZ[2] + moonXYZ[2] + kClearNightXYZ[2],
+ };
+
+ float shadeIllumXYZ[3] = {kClearNightXYZ[0], kClearNightXYZ[1],
+ kClearNightXYZ[2]};
+
+ shadeIllumXYZ[0] += (mHour < kSunOverhead) ? sunXYZ[0] : sunShadeXYZ[0];
+ shadeIllumXYZ[1] += (mHour < kSunOverhead) ? sunXYZ[1] : sunShadeXYZ[1];
+ shadeIllumXYZ[2] += (mHour < kSunOverhead) ? sunXYZ[2] : sunShadeXYZ[2];
+
+ // Moon up period covers 23->0 transition, shift for simplicity
+ int adjHour = (mHour + 12) % 24;
+ int adjMoonOverhead = (kMoonOverhead + 12) % 24;
+ shadeIllumXYZ[0] +=
+ (adjHour < adjMoonOverhead) ? moonXYZ[0] : moonShadeXYZ[0];
+ shadeIllumXYZ[1] +=
+ (adjHour < adjMoonOverhead) ? moonXYZ[1] : moonShadeXYZ[1];
+ shadeIllumXYZ[2] +=
+ (adjHour < adjMoonOverhead) ? moonXYZ[2] : moonShadeXYZ[2];
+
+ ALOGV("Direct XYZ: %f, %f, %f", directIllumXYZ[0], directIllumXYZ[1],
+ directIllumXYZ[2]);
+ ALOGV("Shade XYZ: %f, %f, %f", shadeIllumXYZ[0], shadeIllumXYZ[1],
+ shadeIllumXYZ[2]);
+
+ for (int i = 0; i < NUM_MATERIALS; i++) {
+ // Converting for xyY to XYZ:
+ // X = Y / y * x
+ // Y = Y
+ // Z = Y / y * (1 - x - y);
+ float matXYZ[3] = {
+ kMaterials_xyY[i][2] / kMaterials_xyY[i][1] * kMaterials_xyY[i][0],
+ kMaterials_xyY[i][2],
+ kMaterials_xyY[i][2] / kMaterials_xyY[i][1] *
+ (1 - kMaterials_xyY[i][0] - kMaterials_xyY[i][1])};
+
+ if (kMaterialsFlags[i] == 0 || kMaterialsFlags[i] & kSky) {
+ matXYZ[0] *= directIllumXYZ[0];
+ matXYZ[1] *= directIllumXYZ[1];
+ matXYZ[2] *= directIllumXYZ[2];
+ } else if (kMaterialsFlags[i] & kShadowed) {
+ matXYZ[0] *= shadeIllumXYZ[0];
+ matXYZ[1] *= shadeIllumXYZ[1];
+ matXYZ[2] *= shadeIllumXYZ[2];
+ } // else if (kMaterialsFlags[i] * kSelfLit), do nothing
+
+ ALOGV("Mat %d XYZ: %f, %f, %f", i, matXYZ[0], matXYZ[1], matXYZ[2]);
+ float luxToElectrons =
+ mSensorSensitivity * mExposureDuration / (kAperture * kAperture);
+ mCurrentColors[i * NUM_CHANNELS + 0] =
+ (mFilterR[0] * matXYZ[0] + mFilterR[1] * matXYZ[1] +
+ mFilterR[2] * matXYZ[2]) *
+ luxToElectrons;
+ mCurrentColors[i * NUM_CHANNELS + 1] =
+ (mFilterGr[0] * matXYZ[0] + mFilterGr[1] * matXYZ[1] +
+ mFilterGr[2] * matXYZ[2]) *
+ luxToElectrons;
+ mCurrentColors[i * NUM_CHANNELS + 2] =
+ (mFilterGb[0] * matXYZ[0] + mFilterGb[1] * matXYZ[1] +
+ mFilterGb[2] * matXYZ[2]) *
+ luxToElectrons;
+ mCurrentColors[i * NUM_CHANNELS + 3] =
+ (mFilterB[0] * matXYZ[0] + mFilterB[1] * matXYZ[1] +
+ mFilterB[2] * matXYZ[2]) *
+ luxToElectrons;
+
+ ALOGV("Color %d RGGB: %d, %d, %d, %d", i,
+ mCurrentColors[i * NUM_CHANNELS + 0],
+ mCurrentColors[i * NUM_CHANNELS + 1],
+ mCurrentColors[i * NUM_CHANNELS + 2],
+ mCurrentColors[i * NUM_CHANNELS + 3]);
+ }
+ // Shake viewpoint; horizontal and vertical sinusoids at roughly
+ // human handshake frequencies
+ mHandshakeX = (kFreq1Magnitude * std::sin(kHorizShakeFreq1 * timeSinceIdx) +
+ kFreq2Magnitude * std::sin(kHorizShakeFreq2 * timeSinceIdx)) *
+ mMapDiv * kShakeFraction;
+
+ mHandshakeY = (kFreq1Magnitude * std::sin(kVertShakeFreq1 * timeSinceIdx) +
+ kFreq2Magnitude * std::sin(kVertShakeFreq2 * timeSinceIdx)) *
+ mMapDiv * kShakeFraction;
+
+ // Set starting pixel
+ 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 * 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.03; // As a fraction of a scene tile
+
+// RGB->YUV, Jpeg standard
+const float Scene::kRgb2Yuv[12] = {
+ 0.299f, 0.587f, 0.114f, 0.f, -0.16874f, -0.33126f,
+ 0.5f, -128.f, 0.5f, -0.41869f, -0.08131f, -128.f,
+};
+
+// Aperture of imaging lens
+const float Scene::kAperture = 2.8;
+
+// Sun illumination levels through the day
+const float Scene::kSunlight[24 / kTimeStep] = {0, // 00:00
+ 0,
+ 0,
+ kTwilightIllum, // 06:00
+ kDirectSunIllum,
+ kDirectSunIllum,
+ kDirectSunIllum, // 12:00
+ kDirectSunIllum,
+ kDirectSunIllum,
+ kSunsetIllum, // 18:00
+ kTwilightIllum,
+ 0};
+
+// Moon illumination levels through the day
+const float Scene::kMoonlight[24 / kTimeStep] = {kFullMoonIllum, // 00:00
+ kFullMoonIllum,
+ 0,
+ 0, // 06:00
+ 0,
+ 0,
+ 0, // 12:00
+ 0,
+ 0,
+ 0, // 18:00
+ 0,
+ kFullMoonIllum};
+
+const int Scene::kSunOverhead = 12;
+const int Scene::kMoonOverhead = 0;
+
+// Used for sun illumination levels
+const float Scene::kDirectSunIllum = 100000;
+const float Scene::kSunsetIllum = 400;
+const float Scene::kTwilightIllum = 4;
+// Used for moon illumination levels
+const float Scene::kFullMoonIllum = 1;
+// Other illumination levels
+const float Scene::kDaylightShadeIllum = 20000;
+const float Scene::kClearNightIllum = 2e-3;
+const float Scene::kStarIllum = 2e-6;
+const float Scene::kLivingRoomIllum = 50;
+
+const float Scene::kIncandescentXY[2] = {0.44757f, 0.40745f};
+const float Scene::kDirectSunlightXY[2] = {0.34842f, 0.35161f};
+const float Scene::kDaylightXY[2] = {0.31271f, 0.32902f};
+const float Scene::kNoonSkyXY[2] = {0.346f, 0.359f};
+const float Scene::kMoonlightXY[2] = {0.34842f, 0.35161f};
+const float Scene::kSunsetXY[2] = {0.527f, 0.413f};
+
+const uint8_t Scene::kSelfLit = 0x01;
+const uint8_t Scene::kShadowed = 0x02;
+const uint8_t Scene::kSky = 0x04;
+
+// For non-self-lit materials, the Y component is normalized with 1=full
+// reflectance; for self-lit materials, it's the constant illuminance in lux.
+const float Scene::kMaterials_xyY[Scene::NUM_MATERIALS][3] = {
+ {0.3688f, 0.4501f, .1329f}, // GRASS
+ {0.3688f, 0.4501f, .1329f}, // GRASS_SHADOW
+ {0.3986f, 0.5002f, .4440f}, // HILL
+ {0.3262f, 0.5040f, .2297f}, // WALL
+ {0.4336f, 0.3787f, .1029f}, // ROOF
+ {0.3316f, 0.2544f, .0639f}, // DOOR
+ {0.3425f, 0.3577f, .0887f}, // CHIMNEY
+ {kIncandescentXY[0], kIncandescentXY[1], kLivingRoomIllum}, // WINDOW
+ {kDirectSunlightXY[0], kDirectSunlightXY[1], kDirectSunIllum}, // SUN
+ {kNoonSkyXY[0], kNoonSkyXY[1],
+ kDaylightShadeIllum / kDirectSunIllum}, // SKY
+ {kMoonlightXY[0], kMoonlightXY[1], kFullMoonIllum} // MOON
+};
+
+const uint8_t Scene::kMaterialsFlags[Scene::NUM_MATERIALS] = {
+ 0, kShadowed, kShadowed, kShadowed, kShadowed, kShadowed,
+ kShadowed, kSelfLit, kSelfLit, kSky, kSelfLit,
+};
+
+} // namespace android
diff --git a/guest/hals/camera/fake-pipeline2/Scene.h b/guest/hals/camera/fake-pipeline2/Scene.h
new file mode 100644
index 000000000..5e86861e5
--- /dev/null
+++ b/guest/hals/camera/fake-pipeline2/Scene.h
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+/**
+ * The Scene class implements a simple physical simulation of a scene, using the
+ * CIE 1931 colorspace to represent light in physical units (lux).
+ *
+ * It's fairly approximate, but does provide a scene with realistic widely
+ * variable illumination levels and colors over time.
+ *
+ */
+
+#ifndef HW_EMULATOR_CAMERA2_SCENE_H
+#define HW_EMULATOR_CAMERA2_SCENE_H
+
+#include "utils/Timers.h"
+
+namespace android {
+
+class Scene {
+ public:
+ Scene(int sensorWidthPx, int sensorHeightPx, float sensorSensitivity);
+ ~Scene();
+
+ // Set the filter coefficients for the red, green, and blue filters on the
+ // sensor. Used as an optimization to pre-calculate various illuminance
+ // values. Two different green filters can be provided, to account for
+ // possible cross-talk on a Bayer sensor. Must be called before
+ // calculateScene.
+ void setColorFilterXYZ(float rX, float rY, float rZ, float grX, float grY,
+ float grZ, float gbX, float gbY, float gbZ, float bX,
+ float bY, float bZ);
+
+ // Set time of day (24-hour clock). This controls the general light levels
+ // in the scene. Must be called before calculateScene
+ void setHour(int hour);
+ // Get current hour
+ int getHour();
+
+ // Set the duration of exposure for determining luminous exposure.
+ // Must be called before calculateScene
+ void setExposureDuration(float seconds);
+
+ // Calculate scene information for current hour and the time offset since
+ // the hour. Must be called at least once before calling getLuminousExposure.
+ // Resets pixel readout location to 0,0
+ void calculateScene(nsecs_t time);
+
+ // Set sensor pixel readout location.
+ 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.
+ const uint32_t* getPixelElectrons();
+
+ enum ColorChannels { R = 0, Gr, Gb, B, Y, Cb, Cr, NUM_CHANNELS };
+
+ private:
+ // Sensor color filtering coefficients in XYZ
+ float mFilterR[3];
+ float mFilterGr[3];
+ float mFilterGb[3];
+ float mFilterB[3];
+
+ int mOffsetX, mOffsetY;
+ int mMapDiv;
+
+ int mHandshakeX, mHandshakeY;
+
+ int mSensorWidth;
+ int mSensorHeight;
+ int mCurrentX;
+ int mCurrentY;
+ int mSubX;
+ int mSubY;
+ int mSceneX;
+ int mSceneY;
+ int mSceneIdx;
+ uint32_t* mCurrentSceneMaterial;
+
+ int mHour;
+ float mExposureDuration;
+ float mSensorSensitivity;
+
+ enum Materials {
+ GRASS = 0,
+ GRASS_SHADOW,
+ HILL,
+ WALL,
+ ROOF,
+ DOOR,
+ CHIMNEY,
+ WINDOW,
+ SUN,
+ SKY,
+ MOON,
+ NUM_MATERIALS
+ };
+
+ uint32_t mCurrentColors[NUM_MATERIALS * NUM_CHANNELS];
+
+ /**
+ * Constants for scene definition. These are various degrees of approximate.
+ */
+
+ // Fake handshake parameters. Two shake frequencies per axis, plus magnitude
+ // as a fraction of a scene tile, and relative magnitudes for the frequencies
+ static const float kHorizShakeFreq1;
+ static const float kHorizShakeFreq2;
+ static const float kVertShakeFreq1;
+ static const float kVertShakeFreq2;
+ static const float kFreq1Magnitude;
+ static const float kFreq2Magnitude;
+
+ static const float kShakeFraction;
+
+ // RGB->YUV conversion
+ static const float kRgb2Yuv[12];
+
+ // Aperture of imaging lens
+ static const float kAperture;
+
+ // Sun, moon illuminance levels in 2-hour increments. These don't match any
+ // real day anywhere.
+ static const uint32_t kTimeStep = 2;
+ static const float kSunlight[];
+ static const float kMoonlight[];
+ static const int kSunOverhead;
+ static const int kMoonOverhead;
+
+ // Illumination levels for various conditions, in lux
+ static const float kDirectSunIllum;
+ static const float kDaylightShadeIllum;
+ static const float kSunsetIllum;
+ static const float kTwilightIllum;
+ static const float kFullMoonIllum;
+ static const float kClearNightIllum;
+ static const float kStarIllum;
+ static const float kLivingRoomIllum;
+
+ // Chromaticity of various illumination sources
+ static const float kIncandescentXY[2];
+ static const float kDirectSunlightXY[2];
+ static const float kDaylightXY[2];
+ static const float kNoonSkyXY[2];
+ static const float kMoonlightXY[2];
+ static const float kSunsetXY[2];
+
+ static const uint8_t kSelfLit;
+ static const uint8_t kShadowed;
+ static const uint8_t kSky;
+
+ static const float kMaterials_xyY[NUM_MATERIALS][3];
+ static const uint8_t kMaterialsFlags[NUM_MATERIALS];
+
+ static const int kSceneWidth;
+ static const int kSceneHeight;
+ static const uint8_t kScene[];
+};
+
+} // namespace android
+
+#endif // HW_EMULATOR_CAMERA2_SCENE_H
diff --git a/guest/hals/camera/fake-pipeline2/Sensor.cpp b/guest/hals/camera/fake-pipeline2/Sensor.cpp
new file mode 100644
index 000000000..f39bbbdd2
--- /dev/null
+++ b/guest/hals/camera/fake-pipeline2/Sensor.cpp
@@ -0,0 +1,591 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+//#define LOG_NNDEBUG 0
+#define LOG_TAG "EmulatedCamera2_Sensor"
+
+#ifdef LOG_NNDEBUG
+#define ALOGVV(...) ALOGV(__VA_ARGS__)
+#else
+#define ALOGVV(...) ((void)0)
+#endif
+
+#include <utils/Log.h>
+
+#include <cmath>
+#include <cstdlib>
+#include "../EmulatedFakeCamera2.h"
+#include "Sensor.h"
+#include "system/camera_metadata.h"
+
+namespace android {
+
+// const nsecs_t Sensor::kExposureTimeRange[2] =
+// {1000L, 30000000000L} ; // 1 us - 30 sec
+// const nsecs_t Sensor::kFrameDurationRange[2] =
+// {33331760L, 30000000000L}; // ~1/30 s - 30 sec
+const nsecs_t Sensor::kExposureTimeRange[2] = {1000L,
+ 300000000L}; // 1 us - 0.3 sec
+const nsecs_t Sensor::kFrameDurationRange[2] = {
+ 33331760L, 300000000L}; // ~1/30 s - 0.3 sec
+
+const nsecs_t Sensor::kMinVerticalBlank = 10000L;
+
+const uint8_t Sensor::kColorFilterArrangement =
+ ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_RGGB;
+
+// Output image data characteristics
+const uint32_t Sensor::kMaxRawValue = 4000;
+const uint32_t Sensor::kBlackLevel = 1000;
+
+// Sensor sensitivity
+const float Sensor::kSaturationVoltage = 0.520f;
+const uint32_t Sensor::kSaturationElectrons = 2000;
+const float Sensor::kVoltsPerLuxSecond = 0.100f;
+
+const float Sensor::kElectronsPerLuxSecond = Sensor::kSaturationElectrons /
+ Sensor::kSaturationVoltage *
+ Sensor::kVoltsPerLuxSecond;
+
+const float Sensor::kBaseGainFactor =
+ (float)Sensor::kMaxRawValue / Sensor::kSaturationElectrons;
+
+const float Sensor::kReadNoiseStddevBeforeGain = 1.177; // in electrons
+const float Sensor::kReadNoiseStddevAfterGain = 2.100; // in digital counts
+const float Sensor::kReadNoiseVarBeforeGain =
+ Sensor::kReadNoiseStddevBeforeGain * Sensor::kReadNoiseStddevBeforeGain;
+const float Sensor::kReadNoiseVarAfterGain =
+ Sensor::kReadNoiseStddevAfterGain * Sensor::kReadNoiseStddevAfterGain;
+
+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
+// square root. Accurate to within +-3.6%
+float sqrtf_approx(float r) {
+ // Modifier is based on IEEE floating-point representation; the
+ // manipulations boil down to finding approximate log2, dividing by two, and
+ // then inverting the log2. A bias is added to make the relative error
+ // symmetric about the real answer.
+ const int32_t modifier = 0x1FBB4000;
+
+ int32_t r_i = *(int32_t *)(&r);
+ r_i = (r_i >> 1) + modifier;
+
+ return *(float *)(&r_i);
+}
+
+Sensor::Sensor(uint32_t width, uint32_t height)
+ : Thread(false),
+ mResolution{width, height},
+ mActiveArray{0, 0, width, height},
+ mRowReadoutTime(kFrameDurationRange[0] / height),
+ mGotVSync(false),
+ mExposureTime(kFrameDurationRange[0] - kMinVerticalBlank),
+ mFrameDuration(kFrameDurationRange[0]),
+ mGainFactor(kDefaultSensitivity),
+ mNextBuffers(NULL),
+ mFrameNumber(0),
+ mCapturedBuffers(NULL),
+ mListener(NULL),
+ mScene(width, height, kElectronsPerLuxSecond) {
+ ALOGV("Sensor created with pixel array %d x %d", width, height);
+}
+
+Sensor::~Sensor() { shutDown(); }
+
+status_t Sensor::startUp() {
+ ALOGV("%s: E", __FUNCTION__);
+
+ int res;
+ mCapturedBuffers = NULL;
+ res = run("EmulatedFakeCamera2::Sensor", ANDROID_PRIORITY_URGENT_DISPLAY);
+
+ if (res != OK) {
+ ALOGE("Unable to start up sensor capture thread: %d", res);
+ }
+ return res;
+}
+
+status_t Sensor::shutDown() {
+ ALOGV("%s: E", __FUNCTION__);
+
+ int res;
+ res = requestExitAndWait();
+ if (res != OK) {
+ ALOGE("Unable to shut down sensor capture thread: %d", res);
+ }
+ return res;
+}
+
+Scene &Sensor::getScene() { return mScene; }
+
+void Sensor::setExposureTime(uint64_t ns) {
+ Mutex::Autolock lock(mControlMutex);
+ ALOGVV("Exposure set to %f", ns / 1000000.f);
+ mExposureTime = ns;
+}
+
+void Sensor::setFrameDuration(uint64_t ns) {
+ Mutex::Autolock lock(mControlMutex);
+ ALOGVV("Frame duration set to %f", ns / 1000000.f);
+ mFrameDuration = ns;
+}
+
+void Sensor::setSensitivity(uint32_t gain) {
+ Mutex::Autolock lock(mControlMutex);
+ ALOGVV("Gain set to %d", gain);
+ mGainFactor = gain;
+}
+
+void Sensor::setDestinationBuffers(Buffers *buffers) {
+ Mutex::Autolock lock(mControlMutex);
+ mNextBuffers = buffers;
+}
+
+void Sensor::setFrameNumber(uint32_t frameNumber) {
+ Mutex::Autolock lock(mControlMutex);
+ mFrameNumber = frameNumber;
+}
+
+bool Sensor::waitForVSync(nsecs_t reltime) {
+ int res;
+ Mutex::Autolock lock(mControlMutex);
+
+ mGotVSync = false;
+ res = mVSync.waitRelative(mControlMutex, reltime);
+ if (res != OK && res != TIMED_OUT) {
+ ALOGE("%s: Error waiting for VSync signal: %d", __FUNCTION__, res);
+ return false;
+ }
+ return mGotVSync;
+}
+
+bool Sensor::waitForNewFrame(nsecs_t reltime, nsecs_t *captureTime) {
+ Mutex::Autolock lock(mReadoutMutex);
+
+ if (mCapturedBuffers == NULL) {
+ int res;
+ res = mReadoutAvailable.waitRelative(mReadoutMutex, reltime);
+ if (res == TIMED_OUT) {
+ return false;
+ } else if (res != OK || mCapturedBuffers == NULL) {
+ ALOGE("Error waiting for sensor readout signal: %d", res);
+ return false;
+ }
+ }
+ mReadoutComplete.signal();
+
+ *captureTime = mCaptureTime;
+ mCapturedBuffers = NULL;
+ return true;
+}
+
+Sensor::SensorListener::~SensorListener() {}
+
+void Sensor::setSensorListener(SensorListener *listener) {
+ Mutex::Autolock lock(mControlMutex);
+ mListener = listener;
+}
+
+status_t Sensor::readyToRun() {
+ ALOGV("Starting up sensor thread");
+ mStartupTime = systemTime();
+ mNextCaptureTime = 0;
+ mNextCapturedBuffers = NULL;
+ return OK;
+}
+
+bool Sensor::threadLoop() {
+ /**
+ * Sensor capture operation main loop.
+ *
+ * Stages are out-of-order relative to a single frame's processing, but
+ * in-order in time.
+ */
+
+ /**
+ * Stage 1: Read in latest control parameters
+ */
+ uint64_t exposureDuration;
+ uint64_t frameDuration;
+ uint32_t gain;
+ Buffers *nextBuffers;
+ uint32_t frameNumber;
+ SensorListener *listener = NULL;
+ {
+ Mutex::Autolock lock(mControlMutex);
+ exposureDuration = mExposureTime;
+ frameDuration = mFrameDuration;
+ gain = mGainFactor;
+ nextBuffers = mNextBuffers;
+ frameNumber = mFrameNumber;
+ listener = mListener;
+ // Don't reuse a buffer set
+ mNextBuffers = NULL;
+
+ // Signal VSync for start of readout
+ ALOGVV("Sensor VSync");
+ mGotVSync = true;
+ mVSync.signal();
+ }
+
+ /**
+ * Stage 3: Read out latest captured image
+ */
+
+ Buffers *capturedBuffers = NULL;
+ nsecs_t captureTime = 0;
+
+ nsecs_t startRealTime = systemTime();
+ // Stagefright cares about system time for timestamps, so base simulated
+ // time on that.
+ nsecs_t simulatedTime = startRealTime;
+ nsecs_t frameEndRealTime = startRealTime + frameDuration;
+
+ if (mNextCapturedBuffers != NULL) {
+ ALOGVV("Sensor starting readout");
+ // Pretend we're doing readout now; will signal once enough time has elapsed
+ capturedBuffers = mNextCapturedBuffers;
+ captureTime = mNextCaptureTime;
+ }
+ simulatedTime += mRowReadoutTime + kMinVerticalBlank;
+
+ // TODO: Move this signal to another thread to simulate readout
+ // time properly
+ if (capturedBuffers != NULL) {
+ ALOGVV("Sensor readout complete");
+ Mutex::Autolock lock(mReadoutMutex);
+ if (mCapturedBuffers != NULL) {
+ ALOGV("Waiting for readout thread to catch up!");
+ mReadoutComplete.wait(mReadoutMutex);
+ }
+
+ mCapturedBuffers = capturedBuffers;
+ mCaptureTime = captureTime;
+ mReadoutAvailable.signal();
+ capturedBuffers = NULL;
+ }
+
+ /**
+ * Stage 2: Capture new image
+ */
+ mNextCaptureTime = simulatedTime;
+ mNextCapturedBuffers = nextBuffers;
+
+ if (mNextCapturedBuffers != NULL) {
+ if (listener != NULL) {
+ listener->onSensorEvent(frameNumber, SensorListener::EXPOSURE_START,
+ mNextCaptureTime);
+ }
+ ALOGVV("Starting next capture: Exposure: %f ms, gain: %d",
+ (float)exposureDuration / 1e6, gain);
+ mScene.setExposureDuration((float)exposureDuration / 1e9);
+ mScene.calculateScene(mNextCaptureTime);
+
+ // Might be adding more buffers, so size isn't constant
+ for (size_t i = 0; i < mNextCapturedBuffers->size(); i++) {
+ const StreamBuffer &b = (*mNextCapturedBuffers)[i];
+ ALOGVV(
+ "Sensor capturing buffer %d: stream %d,"
+ " %d x %d, format %x, stride %d, buf %p, img %p",
+ i, b.streamId, b.width, b.height, b.format, b.stride, b.buffer,
+ b.img);
+ switch (b.format) {
+ case HAL_PIXEL_FORMAT_RAW16:
+ captureRaw(b.img, gain, b.stride);
+ break;
+ case HAL_PIXEL_FORMAT_RGB_888:
+ captureRGB(b.img, gain, b.stride);
+ break;
+ case HAL_PIXEL_FORMAT_RGBA_8888:
+ captureRGBA(b.img, gain, b.stride);
+ break;
+ case HAL_PIXEL_FORMAT_BLOB:
+#if defined HAL_DATASPACE_DEPTH
+ if (b.dataSpace != HAL_DATASPACE_DEPTH) {
+#endif
+ // Add auxillary buffer of the right size
+ // Assumes only one BLOB (JPEG) buffer in
+ // mNextCapturedBuffers
+ StreamBuffer bAux;
+ bAux.streamId = 0;
+ bAux.width = b.width;
+ bAux.height = b.height;
+ bAux.format = HAL_PIXEL_FORMAT_RGB_888;
+ bAux.stride = b.width;
+ bAux.buffer = NULL;
+ // TODO: Reuse these
+ bAux.img = new uint8_t[b.width * b.height * 3];
+ mNextCapturedBuffers->push_back(bAux);
+#if defined HAL_DATASPACE_DEPTH
+ } else {
+ captureDepthCloud(b.img);
+ }
+#endif
+ break;
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+ case HAL_PIXEL_FORMAT_YCbCr_420_888:
+ captureNV21(b.img, gain, b.stride);
+ break;
+ case HAL_PIXEL_FORMAT_YV12:
+ // TODO:
+ ALOGE("%s: Format %x is TODO", __FUNCTION__, b.format);
+ break;
+ case HAL_PIXEL_FORMAT_Y16:
+ captureDepth(b.img, gain, b.stride);
+ break;
+ default:
+ ALOGE("%s: Unknown format %x, no output", __FUNCTION__, b.format);
+ break;
+ }
+ }
+ }
+
+ ALOGVV("Sensor vertical blanking interval");
+ nsecs_t workDoneRealTime = systemTime();
+ const nsecs_t timeAccuracy = 2e6; // 2 ms of imprecision is ok
+ if (workDoneRealTime < frameEndRealTime - timeAccuracy) {
+ timespec t;
+ t.tv_sec = (frameEndRealTime - workDoneRealTime) / 1000000000L;
+ t.tv_nsec = (frameEndRealTime - workDoneRealTime) % 1000000000L;
+
+ int ret;
+ do {
+ ret = nanosleep(&t, &t);
+ } while (ret != 0);
+ }
+ nsecs_t endRealTime __unused = systemTime();
+ ALOGVV("Frame cycle took %d ms, target %d ms",
+ (int)((endRealTime - startRealTime) / 1000000),
+ (int)(frameDuration / 1000000));
+ return true;
+};
+
+void Sensor::captureRaw(uint8_t *img, uint32_t gain, uint32_t stride) {
+ float totalGain = gain / 100.0 * kBaseGainFactor;
+ float noiseVarGain = totalGain * totalGain;
+ float readNoiseVar =
+ kReadNoiseVarBeforeGain * noiseVarGain + kReadNoiseVarAfterGain;
+
+ int bayerSelect[4] = {Scene::R, Scene::Gr, Scene::Gb, Scene::B}; // RGGB
+ mScene.setReadoutPixel(0, 0);
+ for (unsigned int y = 0; y < mResolution[1]; y++) {
+ int *bayerRow = bayerSelect + (y & 0x1) * 2;
+ uint16_t *px = (uint16_t *)img + y * stride;
+ for (unsigned int x = 0; x < mResolution[0]; x++) {
+ uint32_t electronCount;
+ electronCount = mScene.getPixelElectrons()[bayerRow[x & 0x1]];
+
+ // TODO: Better pixel saturation curve?
+ electronCount = (electronCount < kSaturationElectrons)
+ ? electronCount
+ : kSaturationElectrons;
+
+ // TODO: Better A/D saturation curve?
+ uint16_t rawCount = electronCount * totalGain;
+ rawCount = (rawCount < kMaxRawValue) ? rawCount : kMaxRawValue;
+
+ // Calculate noise value
+ // TODO: Use more-correct Gaussian instead of uniform noise
+ float photonNoiseVar = electronCount * noiseVarGain;
+ float noiseStddev = sqrtf_approx(readNoiseVar + photonNoiseVar);
+ // Scaled to roughly match gaussian/uniform noise stddev
+ float noiseSample = std::rand() * (2.5 / (1.0 + RAND_MAX)) - 1.25;
+
+ rawCount += kBlackLevel;
+ rawCount += noiseStddev * noiseSample;
+
+ *px++ = rawCount;
+ }
+ // TODO: Handle this better
+ // simulatedTime += mRowReadoutTime;
+ }
+ ALOGVV("Raw sensor image captured");
+}
+
+void Sensor::captureRGBA(uint8_t *img, uint32_t gain, uint32_t stride) {
+ float totalGain = gain / 100.0 * kBaseGainFactor;
+ // In fixed-point math, calculate total scaling from electrons to 8bpp
+ int scale64x = 64 * totalGain * 255 / kMaxRawValue;
+ uint32_t inc = ceil((float)mResolution[0] / stride);
+
+ for (unsigned int y = 0, outY = 0; y < mResolution[1]; y += inc, outY++) {
+ uint8_t *px = img + outY * stride * 4;
+ mScene.setReadoutPixel(0, y);
+ for (unsigned int x = 0; x < mResolution[0]; x += inc) {
+ uint32_t rCount, gCount, bCount;
+ // TODO: Perfect demosaicing is a cheat
+ const uint32_t *pixel = mScene.getPixelElectrons();
+ rCount = pixel[Scene::R] * scale64x;
+ gCount = pixel[Scene::Gr] * scale64x;
+ bCount = pixel[Scene::B] * scale64x;
+
+ *px++ = rCount < 255 * 64 ? rCount / 64 : 255;
+ *px++ = gCount < 255 * 64 ? gCount / 64 : 255;
+ *px++ = bCount < 255 * 64 ? bCount / 64 : 255;
+ *px++ = 255;
+ for (unsigned int j = 1; j < inc; j++) mScene.getPixelElectrons();
+ }
+ // TODO: Handle this better
+ // simulatedTime += mRowReadoutTime;
+ }
+ ALOGVV("RGBA sensor image captured");
+}
+
+void Sensor::captureRGB(uint8_t *img, uint32_t gain, uint32_t stride) {
+ float totalGain = gain / 100.0 * kBaseGainFactor;
+ // In fixed-point math, calculate total scaling from electrons to 8bpp
+ int scale64x = 64 * totalGain * 255 / kMaxRawValue;
+ uint32_t inc = ceil((float)mResolution[0] / stride);
+
+ for (unsigned int y = 0, outY = 0; y < mResolution[1]; y += inc, outY++) {
+ mScene.setReadoutPixel(0, y);
+ uint8_t *px = img + outY * stride * 3;
+ for (unsigned int x = 0; x < mResolution[0]; x += inc) {
+ uint32_t rCount, gCount, bCount;
+ // TODO: Perfect demosaicing is a cheat
+ const uint32_t *pixel = mScene.getPixelElectrons();
+ rCount = pixel[Scene::R] * scale64x;
+ gCount = pixel[Scene::Gr] * scale64x;
+ bCount = pixel[Scene::B] * scale64x;
+
+ *px++ = rCount < 255 * 64 ? rCount / 64 : 255;
+ *px++ = gCount < 255 * 64 ? gCount / 64 : 255;
+ *px++ = bCount < 255 * 64 ? bCount / 64 : 255;
+ for (unsigned int j = 1; j < inc; j++) mScene.getPixelElectrons();
+ }
+ // TODO: Handle this better
+ // simulatedTime += mRowReadoutTime;
+ }
+ ALOGVV("RGB sensor image captured");
+}
+
+void Sensor::captureNV21(uint8_t *img, uint32_t gain, uint32_t stride) {
+ 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
+ const int scale64x = 64 * totalGain * 255 / kMaxRawValue;
+ // In fixed-point math, saturation point of sensor after gain
+ const int saturationPoint = 64 * 255;
+ // 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
+ 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
+
+ // inc = how many pixels to skip while reading every next pixel
+ // horizontally.
+ uint32_t inc = ceil((float)mResolution[0] / stride);
+ // outH = projected vertical resolution based on stride.
+ uint32_t outH = mResolution[1] / inc;
+ for (unsigned int y = 0, outY = 0; y < mResolution[1]; y += inc, outY++) {
+ uint8_t *pxY = img + outY * stride;
+ uint8_t *pxVU = img + (outH + outY / 2) * stride;
+ mScene.setReadoutPixel(0, y);
+ for (unsigned int outX = 0; outX < stride; outX++) {
+ int32_t rCount, gCount, bCount;
+ // TODO: Perfect demosaicing is a cheat
+ const uint32_t *pixel = mScene.getPixelElectrons();
+ rCount = pixel[Scene::R] * scale64x;
+ rCount = rCount < saturationPoint ? rCount : saturationPoint;
+ gCount = pixel[Scene::Gr] * scale64x;
+ gCount = gCount < saturationPoint ? gCount : saturationPoint;
+ bCount = pixel[Scene::B] * scale64x;
+ bCount = bCount < saturationPoint ? bCount : saturationPoint;
+
+ *pxY++ = (rgbToY[0] * rCount + rgbToY[1] * gCount + rgbToY[2] * bCount) /
+ scaleOutSq;
+ if (outY % 2 == 0 && outX % 2 == 0) {
+ *pxVU++ = (rgbToCb[0] * rCount + rgbToCb[1] * gCount +
+ rgbToCb[2] * bCount + rgbToCb[3]) /
+ scaleOutSq;
+ *pxVU++ = (rgbToCr[0] * rCount + rgbToCr[1] * gCount +
+ rgbToCr[2] * bCount + rgbToCr[3]) /
+ scaleOutSq;
+ }
+
+ // Skip unprocessed pixels from sensor.
+ for (unsigned int j = 1; j < inc; j++) mScene.getPixelElectrons();
+ }
+ }
+ ALOGVV("NV21 sensor image captured");
+}
+
+void Sensor::captureDepth(uint8_t *img, uint32_t gain, uint32_t stride) {
+ float totalGain = gain / 100.0 * kBaseGainFactor;
+ // In fixed-point math, calculate scaling factor to 13bpp millimeters
+ int scale64x = 64 * totalGain * 8191 / kMaxRawValue;
+ uint32_t inc = ceil((float)mResolution[0] / stride);
+
+ for (unsigned int y = 0, outY = 0; y < mResolution[1]; y += inc, outY++) {
+ mScene.setReadoutPixel(0, y);
+ uint16_t *px = ((uint16_t *)img) + outY * stride;
+ for (unsigned int x = 0; x < mResolution[0]; x += inc) {
+ uint32_t depthCount;
+ // TODO: Make up real depth scene instead of using green channel
+ // as depth
+ const uint32_t *pixel = mScene.getPixelElectrons();
+ depthCount = pixel[Scene::Gr] * scale64x;
+
+ *px++ = depthCount < 8191 * 64 ? depthCount / 64 : 0;
+ for (unsigned int j = 1; j < inc; j++) mScene.getPixelElectrons();
+ }
+ // TODO: Handle this better
+ // simulatedTime += mRowReadoutTime;
+ }
+ ALOGVV("Depth sensor image captured");
+}
+
+void Sensor::captureDepthCloud(uint8_t * /*img*/) {
+#if defined HAL_DATASPACE_DEPTH
+ android_depth_points *cloud = reinterpret_cast<android_depth_points *>(img);
+
+ cloud->num_points = 16;
+
+ // TODO: Create point cloud values that match RGB scene
+ const int FLOATS_PER_POINT = 4;
+ const float JITTER_STDDEV = 0.1f;
+ for (size_t y = 0, i = 0; y < 4; y++) {
+ for (size_t x = 0; x < 4; x++, i++) {
+ float randSampleX = std::rand() * (2.5f / (1.0f + RAND_MAX)) - 1.25f;
+ randSampleX *= JITTER_STDDEV;
+
+ float randSampleY = std::rand() * (2.5f / (1.0f + RAND_MAX)) - 1.25f;
+ randSampleY *= JITTER_STDDEV;
+
+ float randSampleZ = std::rand() * (2.5f / (1.0f + RAND_MAX)) - 1.25f;
+ randSampleZ *= JITTER_STDDEV;
+
+ cloud->xyzc_points[i * FLOATS_PER_POINT + 0] = x - 1.5f + randSampleX;
+ cloud->xyzc_points[i * FLOATS_PER_POINT + 1] = y - 1.5f + randSampleY;
+ cloud->xyzc_points[i * FLOATS_PER_POINT + 2] = 3.f + randSampleZ;
+ cloud->xyzc_points[i * FLOATS_PER_POINT + 3] = 0.8f;
+ }
+ }
+
+ ALOGVV("Depth point cloud captured");
+#endif
+}
+
+} // namespace android
diff --git a/guest/hals/camera/fake-pipeline2/Sensor.h b/guest/hals/camera/fake-pipeline2/Sensor.h
new file mode 100644
index 000000000..326af2976
--- /dev/null
+++ b/guest/hals/camera/fake-pipeline2/Sensor.h
@@ -0,0 +1,244 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+/**
+ * This class is a simple simulation of a typical CMOS cellphone imager chip,
+ * which outputs 12-bit Bayer-mosaic raw images.
+ *
+ * Unlike most real image sensors, this one's native color space is linear sRGB.
+ *
+ * The sensor is abstracted as operating as a pipeline 3 stages deep;
+ * conceptually, each frame to be captured goes through these three stages. The
+ * processing step for the sensor is marked off by vertical sync signals, which
+ * indicate the start of readout of the oldest frame. The interval between
+ * processing steps depends on the frame duration of the frame currently being
+ * captured. The stages are 1) configure, 2) capture, and 3) readout. During
+ * configuration, the sensor's registers for settings such as exposure time,
+ * frame duration, and gain are set for the next frame to be captured. In stage
+ * 2, the image data for the frame is actually captured by the sensor. Finally,
+ * in stage 3, the just-captured data is read out and sent to the rest of the
+ * system.
+ *
+ * The sensor is assumed to be rolling-shutter, so low-numbered rows of the
+ * sensor are exposed earlier in time than larger-numbered rows, with the time
+ * offset between each row being equal to the row readout time.
+ *
+ * The characteristics of this sensor don't correspond to any actual sensor,
+ * but are not far off typical sensors.
+ *
+ * Example timing diagram, with three frames:
+ * Frame 0-1: Frame duration 50 ms, exposure time 20 ms.
+ * Frame 2: Frame duration 75 ms, exposure time 65 ms.
+ * Legend:
+ * C = update sensor registers for frame
+ * v = row in reset (vertical blanking interval)
+ * E = row capturing image data
+ * R = row being read out
+ * | = vertical sync signal
+ *time(ms)| 0 55 105 155 230 270
+ * Frame 0| :configure : capture : readout : : :
+ * Row # | ..|CCCC______|_________|_________| : :
+ * 0 | :\ \vvvvvEEEER \ : :
+ * 500 | : \ \vvvvvEEEER \ : :
+ * 1000 | : \ \vvvvvEEEER \ : :
+ * 1500 | : \ \vvvvvEEEER \ : :
+ * 2000 | : \__________\vvvvvEEEER_________\ : :
+ * Frame 1| : configure capture readout : :
+ * Row # | : |CCCC_____|_________|______________| :
+ * 0 | : :\ \vvvvvEEEER \ :
+ * 500 | : : \ \vvvvvEEEER \ :
+ * 1000 | : : \ \vvvvvEEEER \ :
+ * 1500 | : : \ \vvvvvEEEER \ :
+ * 2000 | : : \_________\vvvvvEEEER______________\ :
+ * Frame 2| : : configure capture readout:
+ * Row # | : : |CCCC_____|______________|_______|...
+ * 0 | : : :\ \vEEEEEEEEEEEEER \
+ * 500 | : : : \ \vEEEEEEEEEEEEER \
+ * 1000 | : : : \ \vEEEEEEEEEEEEER \
+ * 1500 | : : : \ \vEEEEEEEEEEEEER \
+ * 2000 | : : : \_________\vEEEEEEEEEEEEER_______\
+ */
+
+#ifndef HW_EMULATOR_CAMERA2_SENSOR_H
+#define HW_EMULATOR_CAMERA2_SENSOR_H
+
+#include "utils/Mutex.h"
+#include "utils/Thread.h"
+#include "utils/Timers.h"
+
+#include "Base.h"
+#include "Scene.h"
+
+namespace android {
+
+class EmulatedFakeCamera2;
+
+class Sensor : private Thread, public virtual RefBase {
+ public:
+ // width: Width of pixel array
+ // height: Height of pixel array
+ Sensor(uint32_t width, uint32_t height);
+ ~Sensor();
+
+ /*
+ * Power control
+ */
+
+ status_t startUp();
+ status_t shutDown();
+
+ /*
+ * Access to scene
+ */
+ Scene &getScene();
+
+ /*
+ * Controls that can be updated every frame
+ */
+
+ void setExposureTime(uint64_t ns);
+ void setFrameDuration(uint64_t ns);
+ void setSensitivity(uint32_t gain);
+ // Buffer must be at least stride*height*2 bytes in size
+ void setDestinationBuffers(Buffers *buffers);
+ // To simplify tracking sensor's current frame
+ void setFrameNumber(uint32_t frameNumber);
+
+ /*
+ * Controls that cause reconfiguration delay
+ */
+
+ void setBinning(int horizontalFactor, int verticalFactor);
+
+ /*
+ * Synchronizing with sensor operation (vertical sync)
+ */
+
+ // Wait until the sensor outputs its next vertical sync signal, meaning it
+ // is starting readout of its latest frame of data. Returns true if vertical
+ // sync is signaled, false if the wait timed out.
+ bool waitForVSync(nsecs_t reltime);
+
+ // Wait until a new frame has been read out, and then return the time
+ // capture started. May return immediately if a new frame has been pushed
+ // since the last wait for a new frame. Returns true if new frame is
+ // returned, false if timed out.
+ bool waitForNewFrame(nsecs_t reltime, nsecs_t *captureTime);
+
+ /*
+ * Interrupt event servicing from the sensor. Only triggers for sensor
+ * cycles that have valid buffers to write to.
+ */
+ struct SensorListener {
+ enum Event {
+ EXPOSURE_START, // Start of exposure
+ };
+
+ virtual void onSensorEvent(uint32_t frameNumber, Event e,
+ nsecs_t timestamp) = 0;
+ virtual ~SensorListener();
+ };
+
+ void setSensorListener(SensorListener *listener);
+
+ /**
+ * Static sensor characteristics
+ */
+ const uint32_t mResolution[2];
+ const uint32_t mActiveArray[4];
+
+ static const nsecs_t kExposureTimeRange[2];
+ static const nsecs_t kFrameDurationRange[2];
+ static const nsecs_t kMinVerticalBlank;
+
+ static const uint8_t kColorFilterArrangement;
+
+ // Output image data characteristics
+ static const uint32_t kMaxRawValue;
+ static const uint32_t kBlackLevel;
+ // Sensor sensitivity, approximate
+
+ static const float kSaturationVoltage;
+ static const uint32_t kSaturationElectrons;
+ static const float kVoltsPerLuxSecond;
+ static const float kElectronsPerLuxSecond;
+
+ static const float kBaseGainFactor;
+
+ static const float kReadNoiseStddevBeforeGain; // In electrons
+ static const float kReadNoiseStddevAfterGain; // In raw digital units
+ static const float kReadNoiseVarBeforeGain;
+ static const float kReadNoiseVarAfterGain;
+
+ // While each row has to read out, reset, and then expose, the (reset +
+ // expose) sequence can be overlapped by other row readouts, so the final
+ // minimum frame duration is purely a function of row readout time, at least
+ // if there's a reasonable number of rows.
+ const nsecs_t mRowReadoutTime;
+
+ static const int32_t kSensitivityRange[2];
+ static const uint32_t kDefaultSensitivity;
+
+ private:
+ Mutex mControlMutex; // Lock before accessing control parameters
+ // Start of control parameters
+ Condition mVSync;
+ bool mGotVSync;
+ uint64_t mExposureTime;
+ uint64_t mFrameDuration;
+ uint32_t mGainFactor;
+ Buffers *mNextBuffers;
+ uint32_t mFrameNumber;
+
+ // End of control parameters
+
+ Mutex mReadoutMutex; // Lock before accessing readout variables
+ // Start of readout variables
+ Condition mReadoutAvailable;
+ Condition mReadoutComplete;
+ Buffers *mCapturedBuffers;
+ nsecs_t mCaptureTime;
+ SensorListener *mListener;
+ // End of readout variables
+
+ // Time of sensor startup, used for simulation zero-time point
+ nsecs_t mStartupTime;
+
+ /**
+ * Inherited Thread virtual overrides, and members only used by the
+ * processing thread
+ */
+ private:
+ virtual status_t readyToRun();
+
+ virtual bool threadLoop();
+
+ nsecs_t mNextCaptureTime;
+ Buffers *mNextCapturedBuffers;
+
+ Scene mScene;
+
+ void captureRaw(uint8_t *img, uint32_t gain, uint32_t stride);
+ void captureRGBA(uint8_t *img, uint32_t gain, uint32_t stride);
+ void captureRGB(uint8_t *img, uint32_t gain, uint32_t stride);
+ void captureNV21(uint8_t *img, uint32_t gain, uint32_t stride);
+ void captureDepth(uint8_t *img, uint32_t gain, uint32_t stride);
+ void captureDepthCloud(uint8_t *img);
+};
+
+} // namespace android
+
+#endif // HW_EMULATOR_CAMERA2_SENSOR_H
diff --git a/guest/hals/gatekeeper/OWNERS b/guest/hals/gatekeeper/OWNERS
deleted file mode 100644
index f3bae3964..000000000
--- a/guest/hals/gatekeeper/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-include platform/system/gatekeeper:/OWNERS
diff --git a/guest/hals/gatekeeper/remote/Android.bp b/guest/hals/gatekeeper/remote/Android.bp
deleted file mode 100644
index d20ad9f82..000000000
--- a/guest/hals/gatekeeper/remote/Android.bp
+++ /dev/null
@@ -1,55 +0,0 @@
-// 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.
-
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-cc_binary {
- name: "android.hardware.gatekeeper@1.0-service.remote",
- defaults: ["cuttlefish_guest_only", "hidl_defaults"],
- vendor: true,
- relative_install_path: "hw",
- init_rc: ["android.hardware.gatekeeper@1.0-service.remote.rc"],
-
- srcs: [
- "remote_gatekeeper.cpp",
- "service.cpp",
- ],
-
- cflags: [
- "-fvisibility=hidden",
- "-Wall",
- "-Werror",
- ],
-
- static_libs: [
- "libgflags",
- ],
-
- shared_libs: [
- "android.hardware.gatekeeper@1.0",
- "libbase",
- "libcuttlefish_fs",
- "libcuttlefish_security",
- "libhidlbase",
- "libgatekeeper",
- "libutils",
- "liblog",
- "libcutils",
- "libtrusty",
- ],
-
- vintf_fragments: ["android.hardware.gatekeeper@1.0-service.remote.xml"],
-}
diff --git a/guest/hals/gatekeeper/remote/android.hardware.gatekeeper@1.0-service.remote.rc b/guest/hals/gatekeeper/remote/android.hardware.gatekeeper@1.0-service.remote.rc
deleted file mode 100644
index 45bf26846..000000000
--- a/guest/hals/gatekeeper/remote/android.hardware.gatekeeper@1.0-service.remote.rc
+++ /dev/null
@@ -1,4 +0,0 @@
-service vendor.gatekeeper-1-0 /vendor/bin/hw/android.hardware.gatekeeper@1.0-service.remote
- class hal
- user system
- group system
diff --git a/guest/hals/gatekeeper/remote/android.hardware.gatekeeper@1.0-service.remote.xml b/guest/hals/gatekeeper/remote/android.hardware.gatekeeper@1.0-service.remote.xml
deleted file mode 100644
index 19714a83b..000000000
--- a/guest/hals/gatekeeper/remote/android.hardware.gatekeeper@1.0-service.remote.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<manifest version="1.0" type="device">
- <hal format="hidl">
- <name>android.hardware.gatekeeper</name>
- <transport>hwbinder</transport>
- <version>1.0</version>
- <interface>
- <name>IGatekeeper</name>
- <instance>default</instance>
- </interface>
- </hal>
-</manifest>
diff --git a/guest/hals/gatekeeper/remote/remote_gatekeeper.cpp b/guest/hals/gatekeeper/remote/remote_gatekeeper.cpp
deleted file mode 100644
index 5cca87914..000000000
--- a/guest/hals/gatekeeper/remote/remote_gatekeeper.cpp
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * 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.
- */
-
-#define LOG_TAG "RemoteGateKeeper"
-
-#include "remote_gatekeeper.h"
-
-#include <limits>
-
-#include <android-base/logging.h>
-
-using ::android::hardware::hidl_vec;
-using ::android::hardware::Return;
-using ::android::hardware::gatekeeper::V1_0::GatekeeperStatusCode;
-using ::gatekeeper::EnrollRequest;
-using ::gatekeeper::EnrollResponse;
-using ::gatekeeper::ERROR_INVALID;
-using ::gatekeeper::ERROR_MEMORY_ALLOCATION_FAILED;
-using ::gatekeeper::ERROR_NONE;
-using ::gatekeeper::ERROR_RETRY;
-using ::gatekeeper::SizedBuffer;
-using ::gatekeeper::VerifyRequest;
-using ::gatekeeper::VerifyResponse;
-
-namespace gatekeeper {
-
-RemoteGateKeeperDevice::RemoteGateKeeperDevice(cuttlefish::GatekeeperChannel* channel)
- : gatekeeper_channel_(channel), error_(0) {
-}
-
-RemoteGateKeeperDevice::~RemoteGateKeeperDevice() {
-}
-
-SizedBuffer hidl_vec2sized_buffer(const hidl_vec<uint8_t>& vec) {
- if (vec.size() == 0 || vec.size() > std::numeric_limits<uint32_t>::max()) return {};
- auto unused = new uint8_t[vec.size()];
- std::copy(vec.begin(), vec.end(), unused);
- return {unused, static_cast<uint32_t>(vec.size())};
-}
-
-Return<void> RemoteGateKeeperDevice::enroll(uint32_t uid,
- const hidl_vec<uint8_t>& currentPasswordHandle,
- const hidl_vec<uint8_t>& currentPassword,
- const hidl_vec<uint8_t>& desiredPassword,
- enroll_cb _hidl_cb) {
- if (error_ != 0) {
- LOG(ERROR) << "Gatekeeper in invalid state";
- _hidl_cb({GatekeeperStatusCode::ERROR_GENERAL_FAILURE, 0, {}});
- return {};
- }
-
- if (desiredPassword.size() == 0) {
- LOG(ERROR) << "Desired password size is 0";
- _hidl_cb({GatekeeperStatusCode::ERROR_GENERAL_FAILURE, 0, {}});
- return {};
- }
-
- EnrollRequest request(uid, hidl_vec2sized_buffer(currentPasswordHandle),
- hidl_vec2sized_buffer(desiredPassword),
- hidl_vec2sized_buffer(currentPassword));
- EnrollResponse response;
- auto error = Send(request, &response);
- if (error != ERROR_NONE) {
- LOG(ERROR) << "Enroll request gave error: " << error;
- _hidl_cb({GatekeeperStatusCode::ERROR_GENERAL_FAILURE, 0, {}});
- } else if (response.error == ERROR_RETRY) {
- LOG(ERROR) << "Enroll response has a retry error";
- _hidl_cb({GatekeeperStatusCode::ERROR_RETRY_TIMEOUT, response.retry_timeout, {}});
- } else if (response.error != ERROR_NONE) {
- LOG(ERROR) << "Enroll response has an error: " << response.error;
- _hidl_cb({GatekeeperStatusCode::ERROR_GENERAL_FAILURE, 0, {}});
- } else {
- hidl_vec<uint8_t> new_handle(response.enrolled_password_handle.Data<uint8_t>(),
- response.enrolled_password_handle.Data<uint8_t>() +
- response.enrolled_password_handle.size());
- _hidl_cb({GatekeeperStatusCode::STATUS_OK, response.retry_timeout, new_handle});
- }
- return {};
-}
-
-Return<void> RemoteGateKeeperDevice::verify(
- uint32_t uid, uint64_t challenge,
- const ::android::hardware::hidl_vec<uint8_t>& enrolledPasswordHandle,
- const ::android::hardware::hidl_vec<uint8_t>& providedPassword, verify_cb _hidl_cb) {
- if (error_ != 0) {
- LOG(ERROR) << "Gatekeeper in invalid state";
- _hidl_cb({GatekeeperStatusCode::ERROR_GENERAL_FAILURE, 0, {}});
- return {};
- }
-
- if (enrolledPasswordHandle.size() == 0) {
- LOG(ERROR) << "Enrolled password size is 0";
- _hidl_cb({GatekeeperStatusCode::ERROR_GENERAL_FAILURE, 0, {}});
- return {};
- }
-
- VerifyRequest request(uid, challenge, hidl_vec2sized_buffer(enrolledPasswordHandle),
- hidl_vec2sized_buffer(providedPassword));
- VerifyResponse response;
-
- auto error = Send(request, &response);
- if (error != ERROR_NONE) {
- LOG(ERROR) << "Verify request gave error: " << error;
- _hidl_cb({GatekeeperStatusCode::ERROR_GENERAL_FAILURE, 0, {}});
- } else if (response.error == ERROR_RETRY) {
- LOG(ERROR) << "Verify request response gave retry error";
- _hidl_cb({GatekeeperStatusCode::ERROR_RETRY_TIMEOUT, response.retry_timeout, {}});
- } else if (response.error != ERROR_NONE) {
- LOG(ERROR) << "Verify request response gave error: " << response.error;
- _hidl_cb({GatekeeperStatusCode::ERROR_GENERAL_FAILURE, 0, {}});
- } else {
- hidl_vec<uint8_t> auth_token(
- response.auth_token.Data<uint8_t>(),
- response.auth_token.Data<uint8_t>() + response.auth_token.size());
-
- _hidl_cb({response.request_reenroll ? GatekeeperStatusCode::STATUS_REENROLL
- : GatekeeperStatusCode::STATUS_OK,
- response.retry_timeout, auth_token});
- }
- return {};
-}
-
-Return<void> RemoteGateKeeperDevice::deleteUser(uint32_t /*uid*/, deleteUser_cb _hidl_cb) {
- LOG(ERROR) << "deleteUser is unimplemented";
- _hidl_cb({GatekeeperStatusCode::ERROR_NOT_IMPLEMENTED, 0, {}});
- return {};
-}
-
-Return<void> RemoteGateKeeperDevice::deleteAllUsers(deleteAllUsers_cb _hidl_cb) {
- LOG(ERROR) << "deleteAllUsers is unimplemented";
- _hidl_cb({GatekeeperStatusCode::ERROR_NOT_IMPLEMENTED, 0, {}});
- return {};
-}
-
-gatekeeper_error_t RemoteGateKeeperDevice::Send(uint32_t command, const GateKeeperMessage& request,
- GateKeeperMessage *response) {
- if (!gatekeeper_channel_->SendRequest(command, request)) {
- LOG(ERROR) << "Failed to send request";
- return ERROR_UNKNOWN;
- }
- auto remote_response = gatekeeper_channel_->ReceiveMessage();
- if (!remote_response) {
- LOG(ERROR) << "Failed to receive response";
- return ERROR_UNKNOWN;
- }
- const uint8_t* buffer = remote_response->payload;
- const uint8_t* buffer_end = remote_response->payload + remote_response->payload_size;
- auto rc = response->Deserialize(buffer, buffer_end);
- if (rc != ERROR_NONE) {
- LOG(ERROR) << "Failed to deserialize keymaster response: " << command;
- return ERROR_UNKNOWN;
- }
- return rc;
-}
-
-};
diff --git a/guest/hals/gatekeeper/remote/remote_gatekeeper.h b/guest/hals/gatekeeper/remote/remote_gatekeeper.h
deleted file mode 100644
index 557505229..000000000
--- a/guest/hals/gatekeeper/remote/remote_gatekeeper.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef TRUSTY_GATEKEEPER_H
-#define TRUSTY_GATEKEEPER_H
-
-#include <memory>
-
-#include <android/hardware/gatekeeper/1.0/IGatekeeper.h>
-#include <hidl/Status.h>
-#include <gatekeeper/gatekeeper_messages.h>
-
-#include "common/libs/security/gatekeeper_channel.h"
-
-namespace gatekeeper {
-
-class RemoteGateKeeperDevice : public ::android::hardware::gatekeeper::V1_0::IGatekeeper {
- public:
- explicit RemoteGateKeeperDevice(cuttlefish::GatekeeperChannel* gatekeeper_channel);
- ~RemoteGateKeeperDevice();
- /**
- * 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.
- */
- ::android::hardware::Return<void> enroll(
- uint32_t uid, const ::android::hardware::hidl_vec<uint8_t>& currentPasswordHandle,
- const ::android::hardware::hidl_vec<uint8_t>& currentPassword,
- const ::android::hardware::hidl_vec<uint8_t>& desiredPassword,
- enroll_cb _hidl_cb) override;
-
- /**
- * 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
- */
- ::android::hardware::Return<void> verify(
- uint32_t uid, uint64_t challenge,
- const ::android::hardware::hidl_vec<uint8_t>& enrolledPasswordHandle,
- const ::android::hardware::hidl_vec<uint8_t>& providedPassword,
- verify_cb _hidl_cb) override;
-
- ::android::hardware::Return<void> deleteUser(uint32_t uid, deleteUser_cb _hidl_cb) override;
-
- ::android::hardware::Return<void> deleteAllUsers(deleteAllUsers_cb _hidl_cb) override;
-
- private:
- cuttlefish::GatekeeperChannel* gatekeeper_channel_;
-
- gatekeeper_error_t Send(uint32_t command, const GateKeeperMessage& request,
- GateKeeperMessage* response);
-
- gatekeeper_error_t Send(const EnrollRequest& request, EnrollResponse *response) {
- return Send(ENROLL, request, response);
- }
-
- gatekeeper_error_t Send(const VerifyRequest& request, VerifyResponse *response) {
- return Send(VERIFY, request, response);
- }
-
- int error_;
-};
-
-} // namespace gatekeeper
-
-#endif
diff --git a/guest/hals/gatekeeper/remote/service.cpp b/guest/hals/gatekeeper/remote/service.cpp
deleted file mode 100644
index 9a230f521..000000000
--- a/guest/hals/gatekeeper/remote/service.cpp
+++ /dev/null
@@ -1,61 +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.
- */
-#define LOG_TAG "android.hardware.gatekeeper@1.0-service.remote"
-
-#include <android-base/logging.h>
-#include <android/hardware/gatekeeper/1.0/IGatekeeper.h>
-#include <cutils/properties.h>
-#include <gflags/gflags.h>
-
-#include <hidl/LegacySupport.h>
-
-#include "common/libs/fs/shared_fd.h"
-#include "common/libs/security/gatekeeper_channel.h"
-#include "guest/hals/gatekeeper/remote/remote_gatekeeper.h"
-
-// Generated HIDL files
-using android::hardware::gatekeeper::V1_0::IGatekeeper;
-using gatekeeper::RemoteGateKeeperDevice;
-
-const char device[] = "/dev/hvc4";
-
-int main(int argc, char** argv) {
- ::android::base::InitLogging(argv, ::android::base::KernelLogger);
- gflags::ParseCommandLineFlags(&argc, &argv, true);
- ::android::hardware::configureRpcThreadpool(1, true /* willJoinThreadpool */);
-
- auto fd = cuttlefish::SharedFD::Open(device, O_RDWR);
- if (!fd->IsOpen()) {
- LOG(FATAL) << "Could not connect to gatekeeper: " << fd->StrError();
- }
-
- if (fd->SetTerminalRaw() < 0) {
- LOG(FATAL) << "Could not make " << device << " a raw terminal: "
- << fd->StrError();
- }
-
- cuttlefish::GatekeeperChannel gatekeeperChannel(fd, fd);
-
- android::sp<RemoteGateKeeperDevice> gatekeeper(
- new RemoteGateKeeperDevice(&gatekeeperChannel));
- auto status = gatekeeper->registerAsService();
- if (status != android::OK) {
- LOG(FATAL) << "Could not register service for Gatekeeper 1.0 (remote) (" << status << ")";
- }
-
- android::hardware::joinRpcThreadpool();
- return -1; // Should never get here.
-}
diff --git a/guest/hals/rild/Android.bp b/guest/hals/gps/Android.bp
index 9a7ad010a..22c5998b8 100644
--- a/guest/hals/rild/Android.bp
+++ b/guest/hals/gps/Android.bp
@@ -1,4 +1,4 @@
-// Copyright (C) 2020 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.
@@ -12,33 +12,23 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-cc_binary {
- name: "libcuttlefish-rild",
- vendor: true,
- cflags: [
- "-DRIL_SHLIB",
- "-Wall",
- "-Werror",
- "-Wextra",
- ],
+// HAL module implemenation, not prelinked and stored in
+// hw/<LIGHTS_HARDWARE_MODULE_ID>.<ro.hardware>.so
+cc_library_shared {
+ name: "gps.cutf",
+ relative_install_path: "hw",
srcs: [
- "rild_cuttlefish.c",
- ],
- include_dirs: [
- "device/google/cuttlefish",
- "hardware/ril/include",
+ "gps_vsoc.cpp",
+ "gps_thread.cpp",
],
shared_libs: [
- "libcutils",
- "libdl",
"liblog",
- "libril-modem-lib",
+ "libcutils",
],
- init_rc: ["rild_cuttlefish.rc"],
- relative_install_path: "hw",
- overrides: ["rild"],
+ header_libs: ["libhardware_headers"],
+ cflags: [
+ "-Wno-missing-field-initializers",
+ "-DLOG_TAG=\"VSoCGPS\"",
+ ],
+ defaults: ["cuttlefish_guest_only"],
}
diff --git a/guest/hals/gps/gps_thread.cpp b/guest/hals/gps/gps_thread.cpp
new file mode 100644
index 000000000..cea830cb8
--- /dev/null
+++ b/guest/hals/gps/gps_thread.cpp
@@ -0,0 +1,200 @@
+/*
+ * 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 "guest/hals/gps/gps_thread.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <math.h>
+#include <pthread.h>
+#include <sys/epoll.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <log/log.h>
+#include <cutils/sockets.h>
+#include <hardware/gps.h>
+
+// Calls an callback function to pass received and parsed GPS data to Android.
+static void reader_call_callback(GpsDataReader* r) {
+ if (!r) {
+ ALOGW("%s: called with r=NULL", __FUNCTION__);
+ return;
+ }
+ if (!r->callback) {
+ ALOGW("%s: no callback registered; keeping the data to send later",
+ __FUNCTION__);
+ return;
+ }
+ if (!r->fix.flags) {
+ ALOGW("%s: no GPS fix", __FUNCTION__);
+ return;
+ }
+ // Always uses current time converted to UTC time in milliseconds.
+ time_t secs = time(NULL); // seconds from 01/01/1970.
+ r->fix.timestamp = (long long)secs * 1000;
+
+#if GPS_DEBUG
+ D("* Parsed GPS Data");
+ if (r->fix.flags & GPS_LOCATION_HAS_LAT_LONG) {
+ D(" - latitude = %g", r->fix.latitude);
+ D(" - longitude = %g", r->fix.longitude);
+ }
+ if (r->fix.flags & GPS_LOCATION_HAS_ALTITUDE)
+ D(" - altitude = %g", r->fix.altitude);
+ if (r->fix.flags & GPS_LOCATION_HAS_SPEED) D(" - speed = %g", r->fix.speed);
+ if (r->fix.flags & GPS_LOCATION_HAS_BEARING)
+ D(" - bearing = %g", r->fix.bearing);
+ if (r->fix.flags & GPS_LOCATION_HAS_ACCURACY)
+ D(" - accuracy = %g", r->fix.accuracy);
+ long long utc_secs = r->fix.timestamp / 1000;
+ struct tm utc;
+ gmtime_r((time_t*)&utc_secs, &utc);
+ D(" - time = %s", asctime(&utc));
+#endif
+
+ D("Sending fix to callback %p", r->callback);
+ r->callback(&r->fix);
+}
+
+// Parses data received so far and calls reader_call_callback().
+static void reader_parse_message(GpsDataReader* r) {
+ D("Received: '%s'", r->buffer);
+
+ int num_read = sscanf(r->buffer, "%lf,%lf,%lf,%f,%f,%f", &r->fix.longitude,
+ &r->fix.latitude, &r->fix.altitude, &r->fix.bearing,
+ &r->fix.speed, &r->fix.accuracy);
+ if (num_read != 6) {
+ ALOGE("Couldn't find 6 values from the received message %s.", r->buffer);
+ return;
+ }
+ r->fix.flags = DEFAULT_GPS_LOCATION_FLAG;
+ reader_call_callback(r);
+}
+
+// Accepts a newly received string & calls reader_parse_message if '\n' is seen.
+static void reader_accept_string(GpsDataReader* r, char* const str,
+ const int len) {
+ int index;
+ for (index = 0; index < len; index++) {
+ if (r->index >= (int)sizeof(r->buffer) - 1) {
+ if (str[index] == '\n') {
+ ALOGW("Message longer than buffer; new byte (%d) skipped.", str[index]);
+ r->index = 0;
+ }
+ } else {
+ r->buffer[r->index++] = str[index];
+ if (str[index] == '\n') {
+ r->buffer[r->index] = '\0';
+ reader_parse_message(r);
+ r->index = 0;
+ }
+ }
+ }
+}
+
+// GPS state threads which communicates with control and data sockets.
+void gps_state_thread(void* arg) {
+ GpsState* state = (GpsState*)arg;
+ GpsDataReader reader;
+ int epoll_fd = epoll_create(2);
+ int started = -1;
+ int gps_fd = state->fd;
+ int control_fd = state->control[1];
+
+ memset(&reader, 0, sizeof(reader));
+ reader.fix.size = sizeof(reader.fix);
+
+ epoll_register(epoll_fd, control_fd);
+ epoll_register(epoll_fd, gps_fd);
+
+ while (1) {
+ struct epoll_event events[2];
+ int nevents, event_index;
+
+ nevents = epoll_wait(epoll_fd, events, 2, 500);
+ D("Thread received %d events", nevents);
+ if (nevents < 0) {
+ if (errno != EINTR)
+ ALOGE("epoll_wait() unexpected error: %s", strerror(errno));
+ continue;
+ } else if (nevents == 0) {
+ if (started == 1) {
+ reader_call_callback(&reader);
+ }
+ continue;
+ }
+
+ for (event_index = 0; event_index < nevents; event_index++) {
+ if ((events[event_index].events & (EPOLLERR | EPOLLHUP)) != 0) {
+ ALOGE("EPOLLERR or EPOLLHUP after epoll_wait() !?");
+ goto Exit;
+ }
+
+ if ((events[event_index].events & EPOLLIN) != 0) {
+ int fd = events[event_index].data.fd;
+ if (fd == control_fd) {
+ unsigned char cmd = 255;
+ int ret;
+ do {
+ ret = read(fd, &cmd, 1);
+ } while (ret < 0 && errno == EINTR);
+
+ if (cmd == CMD_STOP || cmd == CMD_QUIT) {
+ if (started == 1) {
+ D("Thread stopping");
+ started = 0;
+ reader.callback = NULL;
+ }
+ if (cmd == CMD_QUIT) {
+ D("Thread quitting");
+ goto Exit;
+ }
+ } else if (cmd == CMD_START) {
+ if (started != 1) {
+ reader.callback = state->callbacks.location_cb;
+ D("Thread starting callback=%p", reader.callback);
+ reader_call_callback(&reader);
+ started = 1;
+ }
+ } else {
+ ALOGE("unknown control command %d", cmd);
+ }
+ } else if (fd == gps_fd) {
+ char buff[256];
+ int ret;
+ for (;;) {
+ ret = read(fd, buff, sizeof(buff));
+ if (ret < 0) {
+ if (errno == EINTR) continue;
+ if (errno != EWOULDBLOCK)
+ ALOGE("error while reading from gps daemon socket: %s:",
+ strerror(errno));
+ break;
+ }
+ D("Thread received %d bytes: %.*s", ret, ret, buff);
+ reader_accept_string(&reader, buff, ret);
+ }
+ } else {
+ ALOGE("epoll_wait() returned unknown fd %d.", fd);
+ }
+ }
+ }
+ }
+
+Exit:
+ epoll_deregister(epoll_fd, control_fd);
+ epoll_deregister(epoll_fd, gps_fd);
+}
diff --git a/guest/hals/gps/gps_thread.h b/guest/hals/gps/gps_thread.h
new file mode 100644
index 000000000..7cd3c9eab
--- /dev/null
+++ b/guest/hals/gps/gps_thread.h
@@ -0,0 +1,79 @@
+/*
+ * 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 <errno.h>
+#include <fcntl.h>
+#include <sys/epoll.h>
+
+#include <hardware/gps.h>
+
+#define GPS_DEBUG 0
+#define GPS_DATA_BUFFER_MAX_SIZE 256
+
+#define DEFAULT_GPS_LOCATION_FLAG \
+ (GPS_LOCATION_HAS_LAT_LONG | GPS_LOCATION_HAS_ALTITUDE | \
+ GPS_LOCATION_HAS_BEARING | GPS_LOCATION_HAS_SPEED | \
+ GPS_LOCATION_HAS_ACCURACY)
+
+#if GPS_DEBUG
+#define D(...) ALOGD(__VA_ARGS__)
+#else
+#define D(...) ((void)0)
+#endif
+
+// Control commands to GPS thread
+enum { CMD_QUIT = 0, CMD_START = 1, CMD_STOP = 2 };
+
+// GPS HAL's state
+typedef struct {
+ int init;
+ int fd;
+ int control[2];
+ pthread_t thread;
+ GpsCallbacks callbacks;
+} GpsState;
+
+typedef struct {
+ GpsLocation fix;
+ gps_location_callback callback;
+ char buffer[GPS_DATA_BUFFER_MAX_SIZE + 1];
+ int index;
+} GpsDataReader;
+
+void gps_state_thread(void* arg);
+
+static inline int epoll_register(int epoll_fd, int fd) {
+ fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);
+
+ struct epoll_event ev;
+ ev.events = EPOLLIN;
+ ev.data.fd = fd;
+
+ int ret;
+ do {
+ ret = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &ev);
+ } while (ret < 0 && errno == EINTR);
+ return ret;
+}
+
+static inline int epoll_deregister(int epoll_fd, int fd) {
+ int ret;
+ do {
+ ret = epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fd, NULL);
+ } while (ret < 0 && errno == EINTR);
+ return ret;
+}
diff --git a/guest/hals/gps/gps_vsoc.cpp b/guest/hals/gps/gps_vsoc.cpp
new file mode 100644
index 000000000..94bfce4f5
--- /dev/null
+++ b/guest/hals/gps/gps_vsoc.cpp
@@ -0,0 +1,258 @@
+/*
+ * 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.
+ */
+
+/* This implements a GPS hardware HAL library for cuttlefish.
+ * A produced shared library is placed in /system/lib/hw/gps.gce.so, and
+ * loaded by hardware/libhardware/hardware.c code which is called from
+ * android_location_GpsLocationProvider.cpp
+ */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <inttypes.h>
+
+#include <log/log.h>
+#include <cutils/sockets.h>
+#include <hardware/gps.h>
+
+#include "guest/hals/gps/gps_thread.h"
+
+static GpsState _gps_state;
+
+// Cleans up GpsState data structure.
+static void gps_state_cleanup(GpsState* s) {
+ char cmd = CMD_QUIT;
+
+ write(s->control[0], &cmd, 1);
+ if (s->thread > 0) {
+ pthread_join(s->thread, NULL);
+ }
+
+ close(s->control[0]);
+ close(s->control[1]);
+ close(s->fd);
+
+ s->thread = 0;
+ s->control[0] = -1;
+ s->control[1] = -1;
+ s->fd = -1;
+ s->init = 0;
+}
+
+static int gce_gps_init(GpsCallbacks* callbacks) {
+ D("%s: called", __FUNCTION__);
+ // Stop if the framework does not fulfill its interface contract.
+ // We don't want to return an error and continue to ensure that we
+ // catch framework breaks ASAP and to give a tombstone to track down the
+ // offending code.
+ LOG_ALWAYS_FATAL_IF(!callbacks->location_cb);
+ LOG_ALWAYS_FATAL_IF(!callbacks->status_cb);
+ LOG_ALWAYS_FATAL_IF(!callbacks->sv_status_cb);
+ LOG_ALWAYS_FATAL_IF(!callbacks->nmea_cb);
+ LOG_ALWAYS_FATAL_IF(!callbacks->set_capabilities_cb);
+ LOG_ALWAYS_FATAL_IF(!callbacks->acquire_wakelock_cb);
+ LOG_ALWAYS_FATAL_IF(!callbacks->release_wakelock_cb);
+ LOG_ALWAYS_FATAL_IF(!callbacks->create_thread_cb);
+ LOG_ALWAYS_FATAL_IF(!callbacks->request_utc_time_cb);
+ if (!_gps_state.init) {
+ _gps_state.init = 1;
+ _gps_state.control[0] = -1;
+ _gps_state.control[1] = -1;
+ _gps_state.thread = 0;
+
+ _gps_state.fd = socket_local_client(
+ "gps_broadcasts", ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
+ if (_gps_state.fd < 0) {
+ ALOGE("no GPS emulation detected.");
+ goto Fail;
+ }
+ D("GPS HAL will receive data from remoter via gps_broadcasts channel.");
+
+ if (socketpair(AF_LOCAL, SOCK_STREAM, 0, _gps_state.control) < 0) {
+ ALOGE("could not create thread control socket pair: %s", strerror(errno));
+ goto Fail;
+ }
+
+ _gps_state.callbacks = *callbacks;
+ ALOGE("Starting thread callback=%p", callbacks->location_cb);
+ _gps_state.thread = callbacks->create_thread_cb(
+ "gps_state_thread", gps_state_thread, &_gps_state);
+ if (!_gps_state.thread) {
+ ALOGE("could not create GPS thread: %s", strerror(errno));
+ goto Fail;
+ }
+ }
+
+ if (_gps_state.fd < 0) return -1;
+ return 0;
+
+Fail:
+ gps_state_cleanup(&_gps_state);
+ return -1;
+}
+
+static void gce_gps_cleanup() {
+ D("%s: called", __FUNCTION__);
+ if (_gps_state.init) gps_state_cleanup(&_gps_state);
+}
+
+static int gce_gps_start() {
+ if (!_gps_state.init) {
+ ALOGE("%s: called with uninitialized gps_state!", __FUNCTION__);
+ return -1;
+ }
+
+ char cmd = CMD_START;
+ int ret;
+ do {
+ ret = write(_gps_state.control[0], &cmd, 1);
+ } while (ret < 0 && errno == EINTR);
+
+ if (ret != 1) {
+ D("%s: could not send CMD_START command: ret=%d: %s", __FUNCTION__, ret,
+ strerror(errno));
+ return -1;
+ }
+
+ return 0;
+}
+
+static int gce_gps_stop() {
+ D("%s: called", __FUNCTION__);
+ if (!_gps_state.init) {
+ ALOGE("%s: called with uninitialized gps_state!", __FUNCTION__);
+ return -1;
+ }
+
+ char cmd = CMD_STOP;
+ int ret;
+
+ do {
+ ret = write(_gps_state.control[0], &cmd, 1);
+ } while (ret < 0 && errno == EINTR);
+
+ if (ret != 1) {
+ ALOGE("%s: could not send CMD_STOP command: ret=%d: %s", __FUNCTION__, ret,
+ strerror(errno));
+ return -1;
+ }
+ return 0;
+}
+
+static int gce_gps_inject_time(GpsUtcTime /*time*/, int64_t /*time_ref*/,
+ int /*uncertainty*/) {
+ D("%s: called", __FUNCTION__);
+ if (!_gps_state.init) {
+ ALOGE("%s: called with uninitialized gps_state!", __FUNCTION__);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int gce_gps_inject_location(double /*latitude*/, double /*longitude*/,
+ float /*accuracy*/) {
+ D("%s: called", __FUNCTION__);
+ if (!_gps_state.init) {
+ ALOGE("%s: called with uninitialized gps_state!", __FUNCTION__);
+ return -1;
+ }
+
+ return 0;
+}
+
+static void gce_gps_delete_aiding_data(GpsAidingData /*flags*/) {
+ D("%s: called", __FUNCTION__);
+ if (!_gps_state.init) {
+ ALOGE("%s: called with uninitialized gps_state!", __FUNCTION__);
+ return;
+ }
+}
+
+static int gce_gps_set_position_mode(GpsPositionMode mode,
+ GpsPositionRecurrence recurrence,
+ uint32_t min_interval,
+ uint32_t preferred_accuracy,
+ uint32_t preferred_time) {
+ D("%s: called", __FUNCTION__);
+ if (!_gps_state.init) {
+ ALOGE("%s: called with uninitialized gps_state!", __FUNCTION__);
+ return -1;
+ }
+ ALOGE("%s(mode=%d, recurrence=%d, min_interval=%" PRIu32
+ ", "
+ "preferred_accuracy=%" PRIu32 ", preferred_time=%" PRIu32
+ ") unimplemented",
+ __FUNCTION__, mode, recurrence, min_interval, preferred_accuracy,
+ preferred_time);
+ return 0;
+}
+
+static const void* gce_gps_get_extension(const char* name) {
+ D("%s: called", __FUNCTION__);
+ // It is normal for this to be called before init.
+ ALOGE("%s(%s): called but not implemented.", __FUNCTION__,
+ name ? name : "NULL");
+ return NULL;
+}
+
+static const GpsInterface gceGpsInterface = {
+ sizeof(GpsInterface),
+ gce_gps_init,
+ gce_gps_start,
+ gce_gps_stop,
+ gce_gps_cleanup,
+ gce_gps_inject_time,
+ gce_gps_inject_location,
+ gce_gps_delete_aiding_data,
+ gce_gps_set_position_mode,
+ gce_gps_get_extension,
+};
+
+const GpsInterface* gps_get_gps_interface(struct gps_device_t* /*dev*/) {
+ return &gceGpsInterface;
+}
+
+static int open_gps(const struct hw_module_t* module, char const* /*name*/,
+ struct hw_device_t** device) {
+ struct gps_device_t* dev =
+ (struct gps_device_t*)malloc(sizeof(struct gps_device_t));
+ LOG_FATAL_IF(!dev, "%s: malloc returned NULL.", __FUNCTION__);
+ memset(dev, 0, sizeof(*dev));
+
+ dev->common.tag = HARDWARE_DEVICE_TAG;
+ dev->common.version = 0;
+ dev->common.module = (struct hw_module_t*)module;
+ dev->get_gps_interface = gps_get_gps_interface;
+
+ *device = (struct hw_device_t*)dev;
+ return 0;
+}
+
+static struct hw_module_methods_t gps_module_methods = {
+ .open = open_gps};
+
+struct hw_module_t HAL_MODULE_INFO_SYM = {
+ .tag = HARDWARE_MODULE_TAG,
+ .version_major = 1,
+ .version_minor = 0,
+ .id = GPS_HARDWARE_MODULE_ID,
+ .name = "GCE GPS Module",
+ .author = "The Android Open Source Project",
+ .methods = & gps_module_methods,
+};
diff --git a/guest/hals/gralloc/legacy/Android.mk b/guest/hals/gralloc/legacy/Android.mk
new file mode 100644
index 000000000..257605efa
--- /dev/null
+++ b/guest/hals/gralloc/legacy/Android.mk
@@ -0,0 +1,57 @@
+# Copyright (C) 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Temporary, should be removed once vsoc hals are in usable state
+
+LOCAL_PATH := $(call my-dir)
+
+VSOC_GRALLOC_COMMON_SRC_FILES := \
+ gralloc.cpp \
+ mapper.cpp \
+ region_registry.cpp
+
+VSOC_GRALLOC_COMMON_CFLAGS:= \
+ -DLOG_TAG=\"gralloc_vsoc_legacy\" \
+ -Wno-missing-field-initializers \
+ -Wall -Werror \
+ $(VSOC_VERSION_CFLAGS)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := gralloc.cutf_ashmem
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := $(VSOC_GRALLOC_COMMON_SRC_FILES)
+
+LOCAL_CFLAGS := $(VSOC_GRALLOC_COMMON_CFLAGS)
+LOCAL_C_INCLUDES := \
+ device/google/cuttlefish
+
+LOCAL_HEADER_LIBRARIES := \
+ libhardware_headers
+
+LOCAL_SHARED_LIBRARIES := \
+ libbase \
+ liblog \
+ libutils \
+ libcutils
+
+LOCAL_VENDOR_MODULE := true
+
+# See b/67109557
+ifeq (true, $(TARGET_TRANSLATE_2ND_ARCH))
+LOCAL_MULTILIB := first
+endif
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/guest/hals/gralloc/legacy/gralloc.cpp b/guest/hals/gralloc/legacy/gralloc.cpp
new file mode 100644
index 000000000..28e71eb93
--- /dev/null
+++ b/guest/hals/gralloc/legacy/gralloc.cpp
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <atomic>
+#include <limits.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+
+#include <cutils/ashmem.h>
+#include <log/log.h>
+#include <cutils/atomic.h>
+#include <utils/String8.h>
+
+#include <hardware/hardware.h>
+#include <hardware/gralloc.h>
+
+#include "gralloc_vsoc_priv.h"
+#include "region_registry.h"
+
+using vsoc::screen::ScreenRegionView;
+
+/*****************************************************************************/
+
+static inline size_t roundUpToPageSize(size_t x) {
+ return (x + (PAGE_SIZE-1)) & ~(PAGE_SIZE-1);
+}
+
+static int gralloc_alloc_buffer(
+ alloc_device_t* /*dev*/, int format, int w, int h,
+ buffer_handle_t* pHandle, int* pStrideInPixels) {
+ int err = 0;
+ int fd = -1;
+ static std::atomic<int> sequence;
+
+ int bytes_per_pixel = formatToBytesPerPixel(format);
+ int bytes_per_line;
+ int stride_in_pixels;
+ int size = 0;
+ // SwiftShader can't handle RGB_888, so fail fast and hard if we try to create
+ // a gralloc buffer in this format.
+ ALOG_ASSERT(format != HAL_PIXEL_FORMAT_RGB_888);
+ if (format == HAL_PIXEL_FORMAT_YV12) {
+ bytes_per_line = ScreenRegionView::align(bytes_per_pixel * w);
+ } else {
+ bytes_per_line = ScreenRegionView::align(bytes_per_pixel * w);
+ }
+ size = roundUpToPageSize(size + formatToBytesPerFrame(format, w, h));
+ size += PAGE_SIZE;
+ fd = ashmem_create_region(
+ android::String8::format(
+ "gralloc-%d.%d", getpid(), sequence++).string(),
+ size);
+ if (fd < 0) {
+ ALOGE("couldn't create ashmem (%s)", strerror(-errno));
+ err = -errno;
+ }
+
+ if (err == 0) {
+ stride_in_pixels = bytes_per_line / bytes_per_pixel;
+ private_handle_t* hnd =
+ new private_handle_t(fd, size, format, w, h, stride_in_pixels, 0);
+ void* base = reference_region(__FUNCTION__, hnd);
+ if (base) {
+ *pHandle = hnd;
+ *pStrideInPixels = stride_in_pixels;
+ } else {
+ err = -EIO;
+ }
+ }
+
+ ALOGE_IF(err, "gralloc failed err=%s", strerror(-err));
+
+ return err;
+}
+
+/*****************************************************************************/
+
+static int gralloc_alloc(alloc_device_t* dev, int w, int h, int format,
+ int /*usage*/, buffer_handle_t* pHandle,
+ int* pStrideInPixels) {
+ if (!pHandle || !pStrideInPixels)
+ return -EINVAL;
+
+ int err = gralloc_alloc_buffer(dev, format, w, h, pHandle, pStrideInPixels);
+
+ if (err < 0) {
+ return err;
+ }
+ return 0;
+}
+
+static int gralloc_free(alloc_device_t* /*dev*/, buffer_handle_t handle) {
+ if (private_handle_t::validate(handle) < 0) {
+ return -EINVAL;
+ }
+
+ private_handle_t const* hnd = reinterpret_cast<private_handle_t const*>(
+ handle);
+ int retval = unreference_region(__FUNCTION__, hnd);
+
+ close(hnd->fd);
+ delete hnd;
+ return retval;
+}
+
+/*****************************************************************************/
+
+static int gralloc_close(struct hw_device_t *dev) {
+ priv_alloc_device_t* ctx = reinterpret_cast<priv_alloc_device_t*>(dev);
+ if (ctx) {
+ /* TODO: keep a list of all buffer_handle_t created, and free them
+ * all here.
+ */
+ free(ctx);
+ }
+ return 0;
+}
+
+static int gralloc_device_open(
+ const hw_module_t* module, const char* name, hw_device_t** device) {
+ int status = -EINVAL;
+ if (!strcmp(name, GRALLOC_HARDWARE_GPU0)) {
+ priv_alloc_device_t *dev;
+ dev = (priv_alloc_device_t*) malloc(sizeof(*dev));
+ LOG_FATAL_IF(!dev, "%s: malloc returned NULL.", __FUNCTION__);
+
+ /* initialize our state here */
+ memset(dev, 0, sizeof(*dev));
+
+ /* initialize the procs */
+ dev->device.common.tag = HARDWARE_DEVICE_TAG;
+ dev->device.common.version = 0;
+ dev->device.common.module = const_cast<hw_module_t*>(module);
+ dev->device.common.close = gralloc_close;
+
+ dev->device.alloc = gralloc_alloc;
+ dev->device.free = gralloc_free;
+
+ *device = &dev->device.common;
+ status = 0;
+ } else {
+ ALOGE("Need to create framebuffer, but it is unsupported");
+ }
+ return status;
+}
+
+/*****************************************************************************/
+
+static struct hw_module_methods_t gralloc_module_methods = {
+ .open = gralloc_device_open
+};
+
+struct private_module_t HAL_MODULE_INFO_SYM = {
+ .base = {
+ .common = {
+ .tag = HARDWARE_MODULE_TAG,
+#ifdef GRALLOC_MODULE_API_VERSION_0_2
+ .version_major = GRALLOC_MODULE_API_VERSION_0_2,
+#else
+ .version_major = 1,
+#endif
+ .version_minor = 0,
+ .id = GRALLOC_HARDWARE_MODULE_ID,
+ .name = "VSOC X86 Graphics Memory Allocator Module",
+ .author = "The Android Open Source Project",
+ .methods = &gralloc_module_methods,
+ .dso = NULL,
+ .reserved = {0},
+ },
+ .registerBuffer = gralloc_register_buffer,
+ .unregisterBuffer = gralloc_unregister_buffer,
+ .lock = gralloc_lock,
+ .unlock = gralloc_unlock,
+#ifdef GRALLOC_MODULE_API_VERSION_0_2
+ .perform = NULL,
+ .lock_ycbcr = gralloc_lock_ycbcr,
+#endif
+ .getTransportSize = gralloc_get_transport_size,
+ .validateBufferSize = gralloc_validate_buffer_size,
+ },
+};
diff --git a/guest/hals/gralloc/legacy/gralloc_vsoc_priv.h b/guest/hals/gralloc/legacy/gralloc_vsoc_priv.h
new file mode 100644
index 000000000..390c6545c
--- /dev/null
+++ b/guest/hals/gralloc/legacy/gralloc_vsoc_priv.h
@@ -0,0 +1,340 @@
+#pragma once
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <stdint.h>
+#include <limits.h>
+#include <string.h>
+#include <sys/cdefs.h>
+#include <sys/mman.h>
+#include <hardware/gralloc.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <cutils/native_handle.h>
+#include <log/log.h>
+
+#include <linux/fb.h>
+
+#ifndef GRALLOC_MODULE_API_VERSION_0_2
+// This structure will be defined in later releases of Android. Declare it
+// here to allow us to structure the code well.
+struct android_ycbcr {
+ void* y;
+ void* cb;
+ void* cr;
+ size_t ystride;
+ size_t cstride;
+ size_t chroma_step;
+ uint32_t reserved[8];
+};
+#endif
+
+namespace vsoc {
+namespace screen {
+
+struct ScreenRegionView {
+ static int align(int input) {
+ auto constexpr alignment = 16;
+ return (input + alignment - 1) & -alignment;
+ }
+ static constexpr int kSwiftShaderPadding = 4;
+};
+
+}
+}
+
+/*****************************************************************************/
+
+struct private_handle_t;
+
+struct private_module_t {
+ gralloc_module_t base;
+};
+
+/*****************************************************************************/
+
+struct priv_alloc_device_t {
+ alloc_device_t device;
+};
+
+/*****************************************************************************/
+
+struct private_handle_t : public native_handle {
+ // file-descriptors
+ int fd;
+ // ints
+ int magic;
+ int flags;
+ int format;
+ int x_res;
+ int y_res;
+ int stride_in_pixels;
+ // Use to indicate which frame we're using.
+ int frame_offset;
+ int total_size;
+ int lock_level;
+
+ static inline int sNumInts() {
+ return (((sizeof(private_handle_t) - sizeof(native_handle_t))/sizeof(int)) - sNumFds);
+ }
+ static const int sNumFds = 1;
+ static const int sMagic = 0x3141592;
+
+ private_handle_t(int fd, int size, int format, int x_res, int y_res,
+ int stride_in_pixels, int flags, int frame_offset = 0)
+ : fd(fd),
+ magic(sMagic),
+ flags(flags),
+ format(format),
+ x_res(x_res),
+ y_res(y_res),
+ stride_in_pixels(stride_in_pixels),
+ frame_offset(frame_offset),
+ total_size(size),
+ lock_level(0) {
+ version = sizeof(native_handle);
+ numInts = sNumInts();
+ numFds = sNumFds;
+ }
+
+ ~private_handle_t() {
+ magic = 0;
+ }
+
+ static int validate(const native_handle* h) {
+ const private_handle_t* hnd = (const private_handle_t*)h;
+ if (!h) {
+ ALOGE("invalid gralloc handle (at %p): NULL pointer", h);
+ return -EINVAL;
+ }
+ if (h->version != sizeof(native_handle)) {
+ ALOGE(
+ "invalid gralloc handle (at %p): Wrong version(observed: %d, "
+ "expected: %zu)",
+ h,
+ h->version,
+ sizeof(native_handle));
+ return -EINVAL;
+ }
+ if (h->numInts != sNumInts()) {
+ ALOGE(
+ "invalid gralloc handle (at %p): Wrong number of ints(observed: %d, "
+ "expected: %d)",
+ h,
+ h->numInts,
+ sNumInts());
+ return -EINVAL;
+ }
+ if (h->numFds != sNumFds) {
+ ALOGE(
+ "invalid gralloc handle (at %p): Wrong number of file "
+ "descriptors(observed: %d, expected: %d)",
+ h,
+ h->numFds,
+ sNumFds);
+ return -EINVAL;
+ }
+ if (hnd->magic != sMagic) {
+ ALOGE(
+ "invalid gralloc handle (at %p): Wrong magic number(observed: %d, "
+ "expected: %d)",
+ h,
+ hnd->magic,
+ sMagic);
+ return -EINVAL;
+ }
+ return 0;
+ }
+};
+
+
+static inline int formatToBytesPerPixel(int format) {
+ switch (format) {
+ case HAL_PIXEL_FORMAT_RGBA_FP16:
+ return 8;
+ case HAL_PIXEL_FORMAT_RGBA_8888:
+ case HAL_PIXEL_FORMAT_RGBX_8888:
+ case HAL_PIXEL_FORMAT_BGRA_8888:
+ // The camera 3.0 implementation assumes that IMPLEMENTATION_DEFINED
+ // means HAL_PIXEL_FORMAT_RGBA_8888
+ case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
+ return 4;
+ case HAL_PIXEL_FORMAT_RGB_888:
+ return 3;
+ case HAL_PIXEL_FORMAT_RGB_565:
+ case HAL_PIXEL_FORMAT_YV12:
+#ifdef GRALLOC_MODULE_API_VERSION_0_2
+ case HAL_PIXEL_FORMAT_YCbCr_420_888:
+#endif
+ return 2;
+ case HAL_PIXEL_FORMAT_BLOB:
+ return 1;
+ default:
+ ALOGE("%s: unknown format=%d", __FUNCTION__, format);
+ return 8;
+ }
+}
+
+inline const char* pixel_format_to_string(int format) {
+ switch (format) {
+ // Formats that are universal across versions
+ case HAL_PIXEL_FORMAT_RGBA_8888:
+ return "RGBA_8888";
+ case HAL_PIXEL_FORMAT_RGBX_8888:
+ return "RGBX_8888";
+ case HAL_PIXEL_FORMAT_BGRA_8888:
+ return "BGRA_8888";
+ case HAL_PIXEL_FORMAT_RGB_888:
+ return "RGB_888";
+ case HAL_PIXEL_FORMAT_RGB_565:
+ return "RGB_565";
+ case HAL_PIXEL_FORMAT_YV12:
+ return "YV12";
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+ return "YCrCb_420_SP";
+ case HAL_PIXEL_FORMAT_YCbCr_422_SP:
+ return "YCbCr_422_SP";
+ case HAL_PIXEL_FORMAT_YCbCr_422_I:
+ return "YCbCr_422_I";
+
+ // First supported on JBMR1 (API 17)
+ case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
+ return "IMPLEMENTATION_DEFINED";
+ case HAL_PIXEL_FORMAT_BLOB:
+ return "BLOB";
+ // First supported on JBMR2 (API 18)
+ case HAL_PIXEL_FORMAT_YCbCr_420_888:
+ return "YCbCr_420_888";
+ case HAL_PIXEL_FORMAT_Y8:
+ return "Y8";
+ case HAL_PIXEL_FORMAT_Y16:
+ return "Y16";
+ // Support was added in L (API 21)
+ case HAL_PIXEL_FORMAT_RAW_OPAQUE:
+ return "RAW_OPAQUE";
+ // This is an alias for RAW_SENSOR in L and replaces it in M.
+ case HAL_PIXEL_FORMAT_RAW16:
+ return "RAW16";
+ case HAL_PIXEL_FORMAT_RAW10:
+ return "RAW10";
+ case HAL_PIXEL_FORMAT_YCbCr_444_888:
+ return "YCbCr_444_888";
+ case HAL_PIXEL_FORMAT_YCbCr_422_888:
+ return "YCbCr_422_888";
+ case HAL_PIXEL_FORMAT_RAW12:
+ return "RAW12";
+ case HAL_PIXEL_FORMAT_FLEX_RGBA_8888:
+ return "FLEX_RGBA_8888";
+ case HAL_PIXEL_FORMAT_FLEX_RGB_888:
+ return "FLEX_RGB_888";
+ case HAL_PIXEL_FORMAT_RGBA_FP16:
+ return "RGBA_FP16";
+ }
+ return "UNKNOWN";
+}
+
+
+static inline void formatToYcbcr(
+ int format, int width, int height, void* base_v, android_ycbcr* out) {
+ char* it = static_cast<char*>(base_v);
+ // Clear reserved fields;
+ memset(out, 0, sizeof(*out));
+ switch (format) {
+ case HAL_PIXEL_FORMAT_YV12:
+#ifdef GRALLOC_MODULE_API_VERSION_0_2
+ case HAL_PIXEL_FORMAT_YCbCr_420_888:
+#endif
+ out->ystride = vsoc::screen::ScreenRegionView::align(width);
+ out->cstride =
+ vsoc::screen::ScreenRegionView::align(out->ystride / 2);
+ out->chroma_step = 1;
+ out->y = it;
+ it += out->ystride * height;
+ out->cr = it;
+ it += out->cstride * height / 2;
+ out->cb = it;
+ break;
+ default:
+ ALOGE("%s: can't deal with format=0x%x (%s)",
+ __FUNCTION__, format, pixel_format_to_string(format));
+ }
+}
+
+static inline int formatToBytesPerFrame(int format, int w, int h) {
+ int bytes_per_pixel = formatToBytesPerPixel(format);
+ int w16, h16;
+ int y_size, c_size;
+
+ switch (format) {
+ // BLOB is used to allocate buffers for JPEG formatted data. Bytes per pixel
+ // is 1, the desired buffer size is in w, and h should be 1. We refrain from
+ // adding additional padding, although the caller is likely to round
+ // up to a page size.
+ case HAL_PIXEL_FORMAT_BLOB:
+ return bytes_per_pixel * w * h;
+ case HAL_PIXEL_FORMAT_YV12:
+#ifdef GRALLOC_MODULE_API_VERSION_0_2
+ case HAL_PIXEL_FORMAT_YCbCr_420_888:
+#endif
+ android_ycbcr strides;
+ formatToYcbcr(format, w, h, NULL, &strides);
+ y_size = strides.ystride * h;
+ c_size = strides.cstride * h / 2;
+ return (y_size + 2 * c_size +
+ vsoc::screen::ScreenRegionView::kSwiftShaderPadding);
+ /*case HAL_PIXEL_FORMAT_RGBA_8888:
+ case HAL_PIXEL_FORMAT_RGBX_8888:
+ case HAL_PIXEL_FORMAT_BGRA_8888:
+ case HAL_PIXEL_FORMAT_RGB_888:
+ case HAL_PIXEL_FORMAT_RGB_565:*/
+ default:
+ w16 = vsoc::screen::ScreenRegionView::align(w);
+ h16 = vsoc::screen::ScreenRegionView::align(h);
+ return bytes_per_pixel * w16 * h16 +
+ vsoc::screen::ScreenRegionView::kSwiftShaderPadding;
+ }
+}
+
+int gralloc_lock(
+ gralloc_module_t const* module,
+ buffer_handle_t handle, int usage,
+ int l, int t, int w, int h,
+ void** vaddr);
+
+int gralloc_unlock(
+ gralloc_module_t const* module, buffer_handle_t handle);
+
+int gralloc_register_buffer(
+ gralloc_module_t const* module, buffer_handle_t handle);
+
+int gralloc_unregister_buffer(
+ gralloc_module_t const* module, buffer_handle_t handle);
+
+int gralloc_lock_ycbcr(
+ struct gralloc_module_t const* module,
+ buffer_handle_t handle, int usage,
+ int l, int t, int w, int h,
+ struct android_ycbcr *ycbcr);
+
+int32_t gralloc_get_transport_size(
+ struct gralloc_module_t const* module, buffer_handle_t handle,
+ uint32_t *outNumFds, uint32_t *outNumInts);
+
+int32_t gralloc_validate_buffer_size(
+ struct gralloc_module_t const* device, buffer_handle_t handle,
+ uint32_t w, uint32_t h, int32_t format, int usage,
+ uint32_t stride);
diff --git a/guest/hals/gralloc/legacy/mapper.cpp b/guest/hals/gralloc/legacy/mapper.cpp
new file mode 100644
index 000000000..eb0facc35
--- /dev/null
+++ b/guest/hals/gralloc/legacy/mapper.cpp
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <limits.h>
+#include <errno.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <cutils/hashmap.h>
+#include <log/log.h>
+#include <cutils/atomic.h>
+
+#include <hardware/hardware.h>
+#include <hardware/gralloc.h>
+#include <system/graphics.h>
+
+#include "gralloc_vsoc_priv.h"
+#include "region_registry.h"
+
+#define DEBUG_REFERENCES 1
+#define DEBUG_MAX_LOCK_LEVEL 20
+
+/*****************************************************************************/
+
+int gralloc_register_buffer(gralloc_module_t const* /*module*/,
+ buffer_handle_t handle) {
+ if (private_handle_t::validate(handle) < 0) {
+ return -EINVAL;
+ }
+
+ private_handle_t* hnd = (private_handle_t*)handle;
+ if (reference_region(__FUNCTION__, hnd)) {
+ return 0;
+ } else {
+ return -EIO;
+ }
+}
+
+int gralloc_unregister_buffer(gralloc_module_t const* /*module*/,
+ buffer_handle_t handle) {
+ if (private_handle_t::validate(handle) < 0) {
+ return -EINVAL;
+ }
+ private_handle_t* hnd = (private_handle_t*)handle;
+ return unreference_region("gralloc_unregister_buffer", hnd);
+}
+
+int gralloc_lock(
+ gralloc_module_t const* /*module*/, buffer_handle_t handle, int /*usage*/,
+ int /*l*/, int /*t*/, int /*w*/, int /*h*/,
+ void** vaddr) {
+ if (private_handle_t::validate(handle) < 0) {
+ return -EINVAL;
+ }
+ if (!vaddr) {
+ return -EINVAL;
+ }
+ private_handle_t* hnd = (private_handle_t*)handle;
+#if DEBUG_REFERENCES
+ if (hnd->lock_level > DEBUG_MAX_LOCK_LEVEL) {
+ LOG_FATAL("%s: unbalanced lock detected. lock level = %d",
+ __FUNCTION__, hnd->lock_level);
+ }
+ ++hnd->lock_level;
+#endif
+ void* base = reference_region("gralloc_lock", hnd);
+ *vaddr = reinterpret_cast<unsigned char*>(base)
+ + hnd->frame_offset;
+ return 0;
+}
+
+int gralloc_unlock(
+ gralloc_module_t const* /*module*/, buffer_handle_t handle) {
+ if (private_handle_t::validate(handle) < 0) {
+ return -EINVAL;
+ }
+ private_handle_t* hnd = (private_handle_t*) handle;
+#if DEBUG_REFERENCES
+ if (hnd->lock_level <= 0) {
+ LOG_FATAL("%s unbalanced unlock detected. lock level = %d",
+ __FUNCTION__, hnd->lock_level);
+ }
+ --hnd->lock_level;
+#endif
+ unreference_region("gralloc_unlock", hnd);
+ return 0;
+}
+
+int gralloc_lock_ycbcr(
+ gralloc_module_t const* /*module*/, buffer_handle_t handle, int /*usage*/,
+ int /*l*/, int /*t*/, int /*w*/, int /*h*/,
+ struct android_ycbcr* ycbcr) {
+ if (private_handle_t::validate(handle) < 0) {
+ return -EINVAL;
+ }
+ private_handle_t* hnd = (private_handle_t*)handle;
+#if DEBUG_REFERENCES
+ if (hnd->lock_level > DEBUG_MAX_LOCK_LEVEL) {
+ LOG_FATAL("%s: unbalanced lock detected. lock level = %d",
+ __FUNCTION__, hnd->lock_level);
+ }
+ ++hnd->lock_level;
+#endif
+ void* base = reference_region("gralloc_lock_ycbcr", hnd);
+ formatToYcbcr(hnd->format, hnd->x_res, hnd->y_res, base, ycbcr);
+ return 0;
+}
+
+int32_t gralloc_get_transport_size(struct gralloc_module_t const* /*module*/,
+ buffer_handle_t handle,
+ uint32_t *outNumFds,
+ uint32_t *outNumInts) {
+ if (private_handle_t::validate(handle) < 0) {
+ return 2; // GRALLOC1_ERROR_BAD_HANDLE
+ }
+ private_handle_t* hnd = (private_handle_t*)handle;
+ *outNumFds = hnd->numFds;
+ *outNumInts = hnd->numInts;
+ return 0;
+}
+
+int32_t gralloc_validate_buffer_size(struct gralloc_module_t const* /*device*/,
+ buffer_handle_t handle,
+ uint32_t w,
+ uint32_t h,
+ int32_t format,
+ int /*usage*/,
+ uint32_t stride) {
+ if (private_handle_t::validate(handle) < 0) {
+ return 2; // GRALLOC1_ERROR_BAD_HANDLE
+ }
+ private_handle_t* hnd = (private_handle_t*)handle;
+ if (format != hnd->format ||
+ w > hnd->x_res ||
+ h > hnd->y_res ||
+ stride > hnd->stride_in_pixels) {
+ return 3; // GRALLOC1_ERROR_BAD_VALUE
+ }
+ return 0;
+}
diff --git a/guest/hals/gralloc/legacy/region_registry.cpp b/guest/hals/gralloc/legacy/region_registry.cpp
new file mode 100644
index 000000000..9829d461e
--- /dev/null
+++ b/guest/hals/gralloc/legacy/region_registry.cpp
@@ -0,0 +1,249 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "VSoCGrallocRegionRegistry"
+// Ensure verbose messages appear even on release builds
+#define LOG_NDEBUG 0
+
+#include <limits.h>
+#include <errno.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <cutils/hashmap.h>
+#include <log/log.h>
+#include <cutils/atomic.h>
+
+#include <linux/ashmem.h>
+
+#include <hardware/hardware.h>
+#include <hardware/gralloc.h>
+#include <system/graphics.h>
+
+#include "gralloc_vsoc_priv.h"
+
+#include <deque>
+#include <map>
+#include <mutex>
+
+static const bool g_log_maps = false;
+static const bool g_log_refs = false;
+
+struct GrallocRegion {
+ void* base_;
+ int num_references_;
+
+ GrallocRegion() : base_(0), num_references_(0) { }
+ // Copy constructors are ok.
+};
+
+
+static const char* get_buffer_name(
+ const private_handle_t* hnd, char output[ASHMEM_NAME_LEN]) {
+ output[0] = '\0';
+ if (!hnd) {
+ ALOGE("Attempted to log gralloc name hnd=NULL");
+ return output;
+ }
+ if (hnd->fd == -1) {
+ ALOGE("Attempted to log gralloc name hnd=%p with fd == -1", hnd);
+ return output;
+ }
+ int rval = ioctl(hnd->fd, ASHMEM_GET_NAME, output);
+ if (rval == -1) {
+ output[0] = '\0';
+ }
+ return output;
+}
+
+
+static int str_hash(void* str) {
+ return hashmapHash(str, strlen(reinterpret_cast<const char*>(str)));
+}
+
+
+static bool str_equal(void* a, void* b) {
+ return strcmp(
+ reinterpret_cast<const char*>(a),
+ reinterpret_cast<const char*>(b)) == 0;
+}
+
+
+static Hashmap* get_regions() {
+ static Hashmap* regionMap = hashmapCreate(19, str_hash, str_equal);
+ return regionMap;
+}
+
+
+static GrallocRegion* lock_region_for_handle(
+ const private_handle_t* hnd, char region_name[ASHMEM_NAME_LEN]) {
+ region_name[0] = '\0';
+ get_buffer_name(hnd, region_name);
+ Hashmap* hash = get_regions();
+ hashmapLock(hash);
+ GrallocRegion* region = reinterpret_cast<GrallocRegion*>(
+ hashmapGet(hash, region_name));
+ if (!region) {
+ region = new GrallocRegion;
+ hashmapPut(hash, strdup(region_name), region);
+ }
+ return region;
+}
+
+
+/* The current implementation uses only a single lock for all regions.
+ * This method takes a region to simplfy the refactoring if we go to
+ * finer-grained locks.
+ */
+static inline void unlock_region(GrallocRegion* ) {
+ hashmapUnlock(get_regions());
+}
+
+
+/*
+ * surface_flinger can drop its last reference to a gralloc buffer (from the
+ * gralloc HAL's point of view) even though it also has work in flight to the
+ * GPU for that target. This causes segfaults in the swiftshader code.
+ *
+ * We create a compromise solution. On unmap we release the pages by mmaping
+ * anonymous memory over the range, but we don't release the address space.
+ * Instead we mark the address space for recycling into a new gralloc buffer.
+ * This means that the shaders can still write, that the writes won't land in
+ * the gralloc buffer, and the gralloc buffer memory can be released.
+ *
+ * When we're preparing to mmap a new gralloc buffer we see if we can recycle
+ * address space from a prior gralloc buffer.
+ *
+ * The protects the application layer from stray memory writes and pointer
+ * references to freed memory. It does mean that bad pixel data can land in
+ * a buffer in the case of a fast map-unmap-map sequence. However, that
+ * could also happen on a physical GPU.
+ *
+ * The alternative to this would be to create an elaborate reference counting
+ * mechanism below both gralloc and SwiftShader. However, we want to keep the
+ * SwiftShader code clean, so that seems undesirable.
+ *
+ * This problem also comes up for physical GPUs b/62267886. Background fo rthis
+ * solution is in b/118777601
+ */
+
+static std::map<size_t, std::deque<void*>> g_recycled_addrs;
+std::mutex g_recycled_addrs_mutex;
+
+
+
+static void* recycle_mmap(void *addr, size_t length, int prot, int flags,
+ int fd, off_t offset) {
+ if (!addr) {
+ std::lock_guard<std::mutex> guard(g_recycled_addrs_mutex);
+ auto it = g_recycled_addrs.find(length);
+ if (it != g_recycled_addrs.end()) {
+ if (it->second.size()) {
+ addr = it->second.front();
+ flags |= MAP_FIXED;
+ it->second.pop_front();
+ }
+ }
+ }
+ return mmap(addr, length, prot, flags, fd, offset);
+}
+
+
+static int recycle_munmap(void *addr, size_t length) {
+ // Do this first so we don't hold the mutex during the syscall
+ if (addr != mmap(addr, length, PROT_READ|PROT_WRITE,
+ MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, -1, 0)) {
+ // Be conservative. Don't recycle here.
+ return -1;
+ }
+ std::lock_guard<std::mutex> guard(g_recycled_addrs_mutex);
+ g_recycled_addrs[length].push_back(addr);
+ return 0;
+}
+
+
+void* reference_region(const char* op, const private_handle_t* hnd) {
+ char name_buf[ASHMEM_NAME_LEN];
+ GrallocRegion* region = lock_region_for_handle(hnd, name_buf);
+ if (!region->base_) {
+ void* mappedAddress = recycle_mmap(
+ 0, hnd->total_size, PROT_READ|PROT_WRITE, MAP_SHARED, hnd->fd, 0);
+ if (mappedAddress == MAP_FAILED) {
+ ALOGE("Could not mmap %s", strerror(errno));
+ unlock_region(region);
+ return NULL;
+ }
+ // Set up the guard pages. The last page is always a guard
+ uintptr_t base = uintptr_t(mappedAddress);
+ uintptr_t addr = base + hnd->total_size - PAGE_SIZE;
+ if (mprotect((void*)addr, PAGE_SIZE, PROT_NONE) == -1) {
+ ALOGE("mprotect base=%p, pg=%p failed (%s)", (void*)base, (void*)addr,
+ strerror(errno));
+ }
+ region->base_ = mappedAddress;
+ ALOGV_IF(g_log_maps, "Mapped %s hnd=%p fd=%d base=%p format=%s(0x%x) "
+ "width=%d height=%d stride_in_pixels=%d total_size=%d",
+ name_buf, hnd, hnd->fd, region->base_,
+ pixel_format_to_string(hnd->format), hnd->format,
+ hnd->x_res, hnd->y_res, hnd->stride_in_pixels, hnd->total_size);
+ }
+
+ void* rval = region->base_;
+ ++region->num_references_;
+ ALOGV_IF(g_log_refs, "Referencing name=%s op=%s addr=%p new numRefs=%d",
+ name_buf, op, region->base_, region->num_references_);
+ unlock_region(region);
+ return rval;
+}
+
+
+int unreference_region(const char* op, const private_handle_t* hnd) {
+ char name_buf[ASHMEM_NAME_LEN];
+
+ GrallocRegion* region = lock_region_for_handle(hnd, name_buf);
+ if (!region->base_) {
+ ALOGE("Unmapping region with no map hnd=%p", hnd);
+ unlock_region(region);
+ return -1;
+ }
+ if (region->num_references_ < 1) {
+ ALOGE(
+ "unmap with hnd=%p, numReferences=%d", hnd, region->num_references_);
+ unlock_region(region);
+ return -1;
+ }
+ --region->num_references_;
+ if (!region->num_references_) {
+ ALOGV_IF(g_log_maps, "Unmapped %s hnd=%p fd=%d base=%p", name_buf, hnd,
+ hnd->fd, region->base_);
+ if (recycle_munmap(region->base_, hnd->total_size) < 0) {
+ ALOGE("Could not unmap %s", strerror(errno));
+ }
+ region->base_ = 0;
+ }
+ ALOGV_IF(g_log_refs, "Unreferencing name=%s op=%s addr=%p new numRefs=%d",
+ name_buf, op, region->base_, region->num_references_);
+ unlock_region(region);
+ return 0;
+}
diff --git a/guest/libs/wpa_supplicant_8_lib/driver_cmd_nl80211.h b/guest/hals/gralloc/legacy/region_registry.h
index 0970a63bb..210ba9a29 100644
--- a/guest/libs/wpa_supplicant_8_lib/driver_cmd_nl80211.h
+++ b/guest/hals/gralloc/legacy/region_registry.h
@@ -14,27 +14,17 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-#include <linux/if_ether.h>
-#include <memory.h>
-#include <stdbool.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "common.h"
-#include "linux_ioctl.h"
-#include "wpa_supplicant_i.h"
+struct private_handle_t;
-#define VSOC_WPA_SUPPLICANT_DEBUG 0
-
-#if VSOC_WPA_SUPPLICANT_DEBUG
-#define D(...) ALOGD(__VA_ARGS__)
-#else
-#define D(...) ((void)0)
-#endif
+/**
+ * Map the memory associated with hnd->fd or, if already mapped, increment
+ * its reference count.
+ */
+void* reference_region(
+ const char* op, const private_handle_t* hnd);
-typedef struct android_wifi_priv_cmd {
- char* buf;
- int used_len;
- int total_len;
-} android_wifi_priv_cmd;
+/**
+ * Decrement the reference count associated with hnd->fd, unmapping its
+ * memory iff the reference count reaches 0.
+ */
+int unreference_region(const char* op, const private_handle_t* hnd);
diff --git a/guest/hals/health/Android.bp b/guest/hals/health/Android.bp
index 81d19a3a5..3f2142576 100644
--- a/guest/hals/health/Android.bp
+++ b/guest/hals/health/Android.bp
@@ -13,10 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
cc_library_shared {
name: "android.hardware.health@2.1-impl-cuttlefish",
stem: "android.hardware.health@2.0-impl-2.1-cuttlefish",
diff --git a/guest/hals/health/storage/Android.bp b/guest/hals/health/storage/Android.bp
index dc57d0f50..74b36ad70 100644
--- a/guest/hals/health/storage/Android.bp
+++ b/guest/hals/health/storage/Android.bp
@@ -14,19 +14,12 @@
* limitations under the License.
*/
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
cc_binary {
- name: "android.hardware.health.storage-service.cuttlefish",
+ name: "android.hardware.health.storage@1.0-service.cuttlefish",
vendor: true,
defaults: ["hidl_defaults", "cuttlefish_health_storage"],
relative_install_path: "hw",
- init_rc: ["android.hardware.health.storage-service.cuttlefish.rc"],
- vintf_fragments: [
- "manifest_android.hardware.health.storage.cuttlefish.xml",
- ],
+ init_rc: ["android.hardware.health.storage@1.0-service.cuttlefish.rc"],
srcs: [
"Storage.cpp",
"service.cpp",
@@ -38,9 +31,9 @@ cc_binary {
],
shared_libs: [
- "android.hardware.health.storage-V1-ndk_platform",
+ "android.hardware.health.storage@1.0",
"libbase",
- "libbinder_ndk",
+ "libhidlbase",
"libutils",
],
}
diff --git a/guest/hals/health/storage/Storage.cpp b/guest/hals/health/storage/Storage.cpp
index afaf947c2..6b7671a28 100644
--- a/guest/hals/health/storage/Storage.cpp
+++ b/guest/hals/health/storage/Storage.cpp
@@ -18,20 +18,29 @@
#include <android-base/logging.h>
-namespace aidl::android::hardware::health::storage {
+namespace android {
+namespace hardware {
+namespace health {
+namespace storage {
+namespace V1_0 {
+namespace implementation {
-ndk::ScopedAStatus
-Storage::garbageCollect(int64_t /*timeout_seconds*/,
- const std::shared_ptr<IGarbageCollectCallback> &cb) {
- LOG(INFO) << "IStorage::garbageCollect() is called. Nothing to do.";
- if (cb != nullptr) {
- auto ret = cb->onFinish(Result::SUCCESS);
- if (!ret.isOk()) {
- LOG(WARNING) << "Cannot return result to callback: "
- << ret.getDescription();
+Return<void> Storage::garbageCollect(uint64_t /*timeoutSeconds*/,
+ const sp<IGarbageCollectCallback>& cb) {
+ LOG(INFO) << "IStorage::garbageCollect() is called. Nothing to do.";
+ if (cb != nullptr) {
+ auto ret = cb->onFinish(Result::SUCCESS);
+ if (!ret.isOk()) {
+ LOG(WARNING) << "Cannot return result to callback: " << ret.description();
+ }
}
- }
- return ndk::ScopedAStatus::ok();
+ return Void();
}
-} // namespace aidl::android::hardware::health::storage
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace storage
+} // namespace health
+} // namespace hardware
+} // namespace android
diff --git a/guest/hals/health/storage/Storage.h b/guest/hals/health/storage/Storage.h
index 39496232e..08ff3f273 100644
--- a/guest/hals/health/storage/Storage.h
+++ b/guest/hals/health/storage/Storage.h
@@ -14,16 +14,35 @@
* limitations under the License.
*/
-#pragma once
+#ifndef ANDROID_HARDWARE_HEALTH_FILESYSTEM_V1_0_FILESYSTEM_H
+#define ANDROID_HARDWARE_HEALTH_FILESYSTEM_V1_0_FILESYSTEM_H
-#include <aidl/android/hardware/health/storage/BnStorage.h>
+#include <android/hardware/health/storage/1.0/IStorage.h>
+#include <hidl/Status.h>
-namespace aidl::android::hardware::health::storage {
+namespace android {
+namespace hardware {
+namespace health {
+namespace storage {
+namespace V1_0 {
+namespace implementation {
-class Storage : public BnStorage {
- ndk::ScopedAStatus
- garbageCollect(int64_t timeout_seconds,
- const std::shared_ptr<IGarbageCollectCallback> &cb) override;
+using ::android::sp;
+using ::android::hardware::hidl_handle;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+
+struct Storage : public IStorage {
+ Return<void> garbageCollect(uint64_t timeoutSeconds,
+ const sp<IGarbageCollectCallback>& cb) override;
};
-} // namespace aidl::android::hardware::health::storage
+} // namespace implementation
+} // namespace V1_0
+} // namespace storage
+} // namespace health
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_HEALTH_FILESYSTEM_V1_0_FILESYSTEM_H
diff --git a/guest/hals/health/storage/android.hardware.health.storage-service.cuttlefish.rc b/guest/hals/health/storage/android.hardware.health.storage@1.0-service.cuttlefish.rc
index a94d265b7..44eccf33f 100644
--- a/guest/hals/health/storage/android.hardware.health.storage-service.cuttlefish.rc
+++ b/guest/hals/health/storage/android.hardware.health.storage@1.0-service.cuttlefish.rc
@@ -14,8 +14,8 @@
# limitations under the License.
#
-service vendor.health-storage-default /vendor/bin/hw/android.hardware.health.storage-service.cuttlefish
- interface aidl android.hardware.health.storage.IStorage/default
+service vendor.health-storage-hal-1-0 /vendor/bin/hw/android.hardware.health.storage@1.0-service.cuttlefish
+ interface android.hardware.health.storage@1.0::IStorage default
oneshot
disabled
class hal
diff --git a/guest/hals/health/storage/manifest_android.hardware.health.storage.cuttlefish.xml b/guest/hals/health/storage/manifest_android.hardware.health.storage@1.0.cuttlefish.xml
index d044e8aab..62b23e049 100644
--- a/guest/hals/health/storage/manifest_android.hardware.health.storage.cuttlefish.xml
+++ b/guest/hals/health/storage/manifest_android.hardware.health.storage@1.0.cuttlefish.xml
@@ -14,9 +14,13 @@
limitations under the License.
-->
<manifest version="1.0" type="device">
- <hal format="aidl">
+ <hal>
<name>android.hardware.health.storage</name>
- <version>1</version>
- <fqname>IStorage/default</fqname>
+ <transport>hwbinder</transport>
+ <version>1.0</version>
+ <interface>
+ <name>IStorage</name>
+ <instance>default</instance>
+ </interface>
</hal>
</manifest>
diff --git a/guest/hals/health/storage/service.cpp b/guest/hals/health/storage/service.cpp
index 87adf3eef..39ff08b18 100644
--- a/guest/hals/health/storage/service.cpp
+++ b/guest/hals/health/storage/service.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * 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.
@@ -14,24 +14,31 @@
* limitations under the License.
*/
-#include <android-base/logging.h>
-#include <android/binder_manager.h>
-#include <android/binder_process.h>
-
+#include <hidl/HidlLazyUtils.h>
+#include <hidl/HidlTransportSupport.h>
#include "Storage.h"
-using aidl::android::hardware::health::storage::Storage;
-using std::string_literals::operator""s;
+using android::OK;
+using android::sp;
+using android::status_t;
+using android::UNKNOWN_ERROR;
+using android::hardware::configureRpcThreadpool;
+using android::hardware::joinRpcThreadpool;
+using android::hardware::LazyServiceRegistrar;
+using android::hardware::health::storage::V1_0::IStorage;
+using android::hardware::health::storage::V1_0::implementation::Storage;
int main() {
- ABinderProcess_setThreadPoolMaxThreadCount(0);
+ configureRpcThreadpool(1, true);
+
+ sp<IStorage> service = new Storage();
+ auto serviceRegistrar = LazyServiceRegistrar::getInstance();
+ status_t result = serviceRegistrar.registerService(service);
- // make a default storage service
- auto storage = ndk::SharedRefBase::make<Storage>();
- const std::string name = Storage::descriptor + "/default"s;
- CHECK_EQ(STATUS_OK, AServiceManager_registerLazyService(
- storage->asBinder().get(), name.c_str()));
+ if (result != OK) {
+ return result;
+ }
- ABinderProcess_joinThreadPool();
- return EXIT_FAILURE; // should not reach
+ joinRpcThreadpool();
+ return UNKNOWN_ERROR;
}
diff --git a/host/libs/audio_connector/Android.bp b/guest/hals/hwcomposer/common/Android.bp
index c26fecb55..fa023f1d8 100644
--- a/host/libs/audio_connector/Android.bp
+++ b/guest/hals/hwcomposer/common/Android.bp
@@ -1,5 +1,4 @@
-//
-// Copyright (C) 2020 The Android Open Source Project
+// 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.
@@ -13,26 +12,37 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
cc_library_static {
- name: "libcuttlefish_audio_connector",
+ name: "hwcomposer_common",
+ defaults: ["cuttlefish_guest_only"],
+ vendor: true,
srcs: [
- "buffers.cpp",
- "commands.cpp",
- "server.cpp",
+ "base_composer.cpp",
+ "cpu_composer.cpp",
+ "drm_utils.cpp",
+ "geometry_utils.cpp",
+ "gralloc_utils.cpp",
+ "hwcomposer.cpp",
+ "screen_view.cpp",
+ "stats_keeper.cpp",
],
+ static_libs: [
+ "libyuv_static",
+ ],
+ header_libs: ["libhardware_headers"],
shared_libs: [
- "libcuttlefish_fs",
+ "android.hardware.graphics.mapper@4.0",
"libbase",
- "libjsoncpp",
- "liblog",
- ],
- static_libs: [
- "libcuttlefish_host_config",
+ "libcutils",
"libcuttlefish_utils",
+ "libcuttlefish_fs",
+ "libdrm",
+ "libgralloctypes",
+ "libhidlbase",
+ "libjpeg",
+ "liblog",
+ "libsync",
+ "libutils",
],
- defaults: ["cuttlefish_host"],
}
diff --git a/guest/hals/hwcomposer/common/base_composer.cpp b/guest/hals/hwcomposer/common/base_composer.cpp
new file mode 100644
index 000000000..cd3ac65a4
--- /dev/null
+++ b/guest/hals/hwcomposer/common/base_composer.cpp
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "guest/hals/hwcomposer/common/base_composer.h"
+
+#include <string.h>
+
+#include <cutils/properties.h>
+#include <log/log.h>
+
+namespace cvd {
+
+BaseComposer::BaseComposer(std::unique_ptr<ScreenView> screen_view)
+ : screen_view_(std::move(screen_view)), gralloc_() {}
+
+void BaseComposer::Dump(char* buff __unused, int buff_len __unused) {}
+
+int BaseComposer::PostFrameBufferTarget(buffer_handle_t buffer_handle) {
+ auto buffer_id = screen_view_->NextBuffer();
+ void* frame_buffer = screen_view_->GetBuffer(buffer_id);
+
+ auto imported_buffer_opt = gralloc_.Import(buffer_handle);
+ if (!imported_buffer_opt) {
+ ALOGE("Failed to Import() framebuffer for post.");
+ return -1;
+ }
+ GrallocBuffer& imported_buffer = *imported_buffer_opt;
+
+ auto buffer_opt = imported_buffer.Lock();
+ if (!buffer_opt) {
+ ALOGE("Failed to Lock() framebuffer for post.");
+ return -1;
+ }
+
+ void* buffer = *buffer_opt;
+ memcpy(frame_buffer, buffer, screen_view_->buffer_size());
+
+ imported_buffer.Unlock();
+
+ screen_view_->Broadcast(buffer_id);
+ return 0;
+} // namespace cvd
+
+bool BaseComposer::IsValidLayer(const hwc_layer_1_t& layer) {
+ auto buffer_opt = gralloc_.Import(layer.handle);
+ if (!buffer_opt) {
+ ALOGE("Failed to import and validate layer buffer handle.");
+ return false;
+ }
+ GrallocBuffer& buffer = *buffer_opt;
+
+ auto buffer_width_opt = buffer.GetWidth();
+ if (!buffer_width_opt) {
+ ALOGE("Failed to get layer buffer width.");
+ return false;
+ }
+ uint32_t buffer_width = *buffer_width_opt;
+
+ auto buffer_height_opt = buffer.GetHeight();
+ if (!buffer_height_opt) {
+ ALOGE("Failed to get layer buffer height.");
+ return false;
+ }
+ uint32_t buffer_height = *buffer_height_opt;
+
+ if (layer.sourceCrop.left < 0 || layer.sourceCrop.top < 0 ||
+ layer.sourceCrop.right > buffer_width ||
+ layer.sourceCrop.bottom > buffer_height) {
+ ALOGE(
+ "%s: Invalid sourceCrop for buffer handle: sourceCrop = [left = %d, "
+ "right = %d, top = %d, bottom = %d], handle = [width = %d, height = "
+ "%d]",
+ __FUNCTION__, layer.sourceCrop.left, layer.sourceCrop.right,
+ layer.sourceCrop.top, layer.sourceCrop.bottom, buffer_width,
+ buffer_height);
+ return false;
+ }
+ return true;
+}
+
+int BaseComposer::PrepareLayers(size_t num_layers, hwc_layer_1_t* layers) {
+ // find unsupported overlays
+ for (size_t i = 0; i < num_layers; i++) {
+ if (IS_TARGET_FRAMEBUFFER(layers[i].compositionType)) {
+ continue;
+ }
+ layers[i].compositionType = HWC_FRAMEBUFFER;
+ }
+ return 0;
+}
+
+int BaseComposer::SetLayers(size_t num_layers, hwc_layer_1_t* layers) {
+ for (size_t idx = 0; idx < num_layers; idx++) {
+ if (IS_TARGET_FRAMEBUFFER(layers[idx].compositionType)) {
+ return PostFrameBufferTarget(layers[idx].handle);
+ }
+ }
+ return -1;
+}
+
+} // namespace cvd
diff --git a/guest/hals/hwcomposer/common/base_composer.h b/guest/hals/hwcomposer/common/base_composer.h
new file mode 100644
index 000000000..c1ffbfe73
--- /dev/null
+++ b/guest/hals/hwcomposer/common/base_composer.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <memory>
+
+#include "guest/hals/hwcomposer/common/gralloc_utils.h"
+#include "guest/hals/hwcomposer/common/hwcomposer.h"
+#include "guest/hals/hwcomposer/common/screen_view.h"
+
+namespace cvd {
+
+class BaseComposer {
+ public:
+ BaseComposer(std::unique_ptr<ScreenView> screen_view);
+ virtual ~BaseComposer() = default;
+
+ virtual bool IsValidLayer(const hwc_layer_1_t& layer);
+ // Sets the composition type of each layer and returns the number of layers
+ // to be composited by the hwcomposer.
+ virtual int PrepareLayers(size_t num_layers, hwc_layer_1_t* layers);
+ // Returns 0 if successful.
+ virtual int SetLayers(size_t num_layers, hwc_layer_1_t* layers);
+ virtual void Dump(char* buff, int buff_len);
+
+ int32_t x_res() { return screen_view_->x_res(); }
+ int32_t y_res() { return screen_view_->y_res(); }
+ int32_t dpi() { return screen_view_->dpi(); }
+ int32_t refresh_rate() { return screen_view_->refresh_rate(); }
+
+ protected:
+ std::unique_ptr<ScreenView> screen_view_;
+ Gralloc gralloc_;
+
+ private:
+ // Returns buffer offset or negative on error.
+ int PostFrameBufferTarget(buffer_handle_t handle);
+};
+} // namespace cvd
diff --git a/guest/hals/hwcomposer/common/cpu_composer.cpp b/guest/hals/hwcomposer/common/cpu_composer.cpp
new file mode 100644
index 000000000..966aabfc3
--- /dev/null
+++ b/guest/hals/hwcomposer/common/cpu_composer.cpp
@@ -0,0 +1,697 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "guest/hals/hwcomposer/common/cpu_composer.h"
+
+#include <algorithm>
+#include <cstdlib>
+#include <utility>
+#include <vector>
+
+#include <drm_fourcc.h>
+#include <hardware/hwcomposer.h>
+#include <hardware/hwcomposer_defs.h>
+#include <libyuv.h>
+#include <log/log.h>
+
+#include "common/libs/utils/size_utils.h"
+#include "guest/hals/hwcomposer/common/drm_utils.h"
+#include "guest/hals/hwcomposer/common/geometry_utils.h"
+
+namespace cvd {
+
+namespace {
+
+bool LayerNeedsScaling(const hwc_layer_1_t& layer) {
+ int from_w = layer.sourceCrop.right - layer.sourceCrop.left;
+ int from_h = layer.sourceCrop.bottom - layer.sourceCrop.top;
+ int to_w = layer.displayFrame.right - layer.displayFrame.left;
+ int to_h = layer.displayFrame.bottom - layer.displayFrame.top;
+
+ bool not_rot_scale = from_w != to_w || from_h != to_h;
+ bool rot_scale = from_w != to_h || from_h != to_w;
+
+ bool needs_rot = layer.transform & HAL_TRANSFORM_ROT_90;
+
+ return needs_rot ? rot_scale : not_rot_scale;
+}
+
+bool LayerNeedsBlending(const hwc_layer_1_t& layer) {
+ return layer.blending != HWC_BLENDING_NONE;
+}
+
+bool LayerNeedsAttenuation(const hwc_layer_1_t& layer) {
+ return layer.blending == HWC_BLENDING_COVERAGE;
+}
+
+struct BufferSpec;
+typedef int (*ConverterFunction)(const BufferSpec& src, const BufferSpec& dst,
+ bool v_flip);
+int DoCopy(const BufferSpec& src, const BufferSpec& dst, bool v_flip);
+int ConvertFromYV12(const BufferSpec& src, const BufferSpec& dst, bool v_flip);
+
+ConverterFunction GetConverterForDrmFormat(uint32_t drm_format) {
+ switch (drm_format) {
+ case DRM_FORMAT_ABGR8888:
+ case DRM_FORMAT_XBGR8888:
+ return &DoCopy;
+ case DRM_FORMAT_YVU420:
+ return &ConvertFromYV12;
+ }
+ ALOGW("Unsupported format: %d(%s), returning null converter",
+ drm_format, GetDrmFormatString(drm_format));
+ return nullptr;
+}
+
+bool IsDrmFormatSupported(uint32_t drm_format) {
+ return GetConverterForDrmFormat(drm_format) != nullptr;
+}
+
+/*******************************************************************************
+Libyuv's convert functions only allow the combination of any rotation (multiple
+of 90 degrees) and a vertical flip, but not horizontal flips.
+Surfaceflinger's transformations are expressed in terms of a vertical flip, a
+horizontal flip and/or a single 90 degrees clockwise rotation (see
+NATIVE_WINDOW_TRANSFORM_HINT documentation on system/window.h for more insight).
+The following code allows to turn a horizontal flip into a 180 degrees rotation
+and a vertical flip.
+*******************************************************************************/
+libyuv::RotationMode GetRotationFromTransform(uint32_t transform) {
+ uint32_t rotation =
+ (transform & HAL_TRANSFORM_ROT_90) ? 1 : 0; // 1 * ROT90 bit
+ rotation += (transform & HAL_TRANSFORM_FLIP_H) ? 2 : 0; // 2 * VFLIP bit
+ return static_cast<libyuv::RotationMode>(90 * rotation);
+}
+
+bool GetVFlipFromTransform(uint32_t transform) {
+ // vertical flip xor horizontal flip
+ return ((transform & HAL_TRANSFORM_FLIP_V) >> 1) ^
+ (transform & HAL_TRANSFORM_FLIP_H);
+}
+
+struct BufferSpec {
+ uint8_t* buffer;
+ std::optional<android_ycbcr> buffer_ycbcr;
+ int width;
+ int height;
+ int crop_x;
+ int crop_y;
+ int crop_width;
+ int crop_height;
+ uint32_t drm_format;
+ int stride_bytes;
+ int sample_bytes;
+
+ BufferSpec(uint8_t* buffer,
+ std::optional<android_ycbcr> buffer_ycbcr,
+ int width,
+ int height,
+ int crop_x,
+ int crop_y,
+ int crop_width,
+ int crop_height,
+ uint32_t drm_format,
+ int stride_bytes,
+ int sample_bytes)
+ : buffer(buffer),
+ buffer_ycbcr(buffer_ycbcr),
+ width(width),
+ height(height),
+ crop_x(crop_x),
+ crop_y(crop_y),
+ crop_width(crop_width),
+ crop_height(crop_height),
+ drm_format(drm_format),
+ stride_bytes(stride_bytes),
+ sample_bytes(sample_bytes) {}
+
+ BufferSpec(uint8_t* buffer,
+ int width,
+ int height,
+ int stride_bytes)
+ : BufferSpec(buffer,
+ /*buffer_ycbcr=*/std::nullopt,
+ width,
+ height,
+ /*crop_x=*/0,
+ /*crop_y=*/0,
+ /*crop_width=*/width,
+ /*crop_height=*/height,
+ /*drm_format=*/DRM_FORMAT_ABGR8888,
+ stride_bytes,
+ /*sample_bytes=*/4) {}
+
+};
+
+int ConvertFromYV12(const BufferSpec& src, const BufferSpec& dst, bool v_flip) {
+ // The following calculation of plane offsets and alignments are based on
+ // swiftshader's Sampler::setTextureLevel() implementation
+ // (Renderer/Sampler.cpp:225)
+
+ auto& src_buffer_ycbcr_opt = src.buffer_ycbcr;
+ if (!src_buffer_ycbcr_opt) {
+ ALOGE("%s called on non ycbcr buffer", __FUNCTION__);
+ return -1;
+ }
+ auto& src_buffer_ycbcr = *src_buffer_ycbcr_opt;
+
+ // The libyuv::I420ToARGB() function is for tri-planar.
+ if (src_buffer_ycbcr.chroma_step != 1) {
+ ALOGE("%s called with bad chroma step", __FUNCTION__);
+ return -1;
+ }
+
+ uint8_t* src_y = reinterpret_cast<uint8_t*>(src_buffer_ycbcr.y);
+ int stride_y = src_buffer_ycbcr.ystride;
+ uint8_t* src_u = reinterpret_cast<uint8_t*>(src_buffer_ycbcr.cb);
+ int stride_u = src_buffer_ycbcr.cstride;
+ uint8_t* src_v = reinterpret_cast<uint8_t*>(src_buffer_ycbcr.cr);
+ int stride_v = src_buffer_ycbcr.cstride;
+
+ // Adjust for crop
+ src_y += src.crop_y * stride_y + src.crop_x;
+ src_v += (src.crop_y / 2) * stride_v + (src.crop_x / 2);
+ src_u += (src.crop_y / 2) * stride_u + (src.crop_x / 2);
+ uint8_t* dst_buffer = dst.buffer + dst.crop_y * dst.stride_bytes +
+ dst.crop_x * dst.sample_bytes;
+
+ // YV12 is the same as I420, with the U and V planes swapped
+ return libyuv::I420ToARGB(src_y, stride_y,
+ src_v, stride_v,
+ src_u, stride_u,
+ dst_buffer, dst.stride_bytes,
+ dst.crop_width,
+ v_flip ? -dst.crop_height : dst.crop_height);
+}
+
+int DoConversion(const BufferSpec& src, const BufferSpec& dst, bool v_flip) {
+ return (*GetConverterForDrmFormat(src.drm_format))(src, dst, v_flip);
+}
+
+int DoCopy(const BufferSpec& src, const BufferSpec& dst, bool v_flip) {
+ // Point to the upper left corner of the crop rectangle
+ uint8_t* src_buffer = src.buffer + src.crop_y * src.stride_bytes +
+ src.crop_x * src.sample_bytes;
+ uint8_t* dst_buffer = dst.buffer + dst.crop_y * dst.stride_bytes +
+ dst.crop_x * dst.sample_bytes;
+ int width = src.crop_width;
+ int height = src.crop_height;
+
+ if (v_flip) {
+ height = -height;
+ }
+
+ // HAL formats are named based on the order of the pixel componets on the
+ // byte stream, while libyuv formats are named based on the order of those
+ // pixel components in an integer written from left to right. So
+ // libyuv::FOURCC_ARGB is equivalent to HAL_PIXEL_FORMAT_BGRA_8888.
+ auto ret = libyuv::ARGBCopy(src_buffer, src.stride_bytes,
+ dst_buffer, dst.stride_bytes,
+ width, height);
+ return ret;
+}
+
+int DoRotation(const BufferSpec& src, const BufferSpec& dst,
+ libyuv::RotationMode rotation, bool v_flip) {
+ // Point to the upper left corner of the crop rectangles
+ uint8_t* src_buffer = src.buffer + src.crop_y * src.stride_bytes +
+ src.crop_x * src.sample_bytes;
+ uint8_t* dst_buffer = dst.buffer + dst.crop_y * dst.stride_bytes +
+ dst.crop_x * dst.sample_bytes;
+ int width = src.crop_width;
+ int height = src.crop_height;
+
+ if (v_flip) {
+ height = -height;
+ }
+
+ return libyuv::ARGBRotate(src_buffer, src.stride_bytes,
+ dst_buffer, dst.stride_bytes,
+ width, height, rotation);
+}
+
+int DoScaling(const BufferSpec& src, const BufferSpec& dst, bool v_flip) {
+ // Point to the upper left corner of the crop rectangles
+ uint8_t* src_buffer = src.buffer + src.crop_y * src.stride_bytes +
+ src.crop_x * src.sample_bytes;
+ uint8_t* dst_buffer = dst.buffer + dst.crop_y * dst.stride_bytes +
+ dst.crop_x * dst.sample_bytes;
+ int src_width = src.crop_width;
+ int src_height = src.crop_height;
+ int dst_width = dst.crop_width;
+ int dst_height = dst.crop_height;
+
+ if (v_flip) {
+ src_height = -src_height;
+ }
+
+ return libyuv::ARGBScale(src_buffer, src.stride_bytes, src_width, src_height,
+ dst_buffer, dst.stride_bytes, dst_width, dst_height,
+ libyuv::kFilterBilinear);
+}
+
+int DoAttenuation(const BufferSpec& src, const BufferSpec& dst, bool v_flip) {
+ // Point to the upper left corner of the crop rectangles
+ uint8_t* src_buffer = src.buffer + src.crop_y * src.stride_bytes +
+ src.crop_x * src.sample_bytes;
+ uint8_t* dst_buffer = dst.buffer + dst.crop_y * dst.stride_bytes +
+ dst.crop_x * dst.sample_bytes;
+ int width = dst.crop_width;
+ int height = dst.crop_height;
+
+ if (v_flip) {
+ height = -height;
+ }
+
+ return libyuv::ARGBAttenuate(src_buffer, src.stride_bytes,
+ dst_buffer, dst.stride_bytes,
+ width, height);
+}
+
+int DoBlending(const BufferSpec& src, const BufferSpec& dst, bool v_flip) {
+ // Point to the upper left corner of the crop rectangles
+ uint8_t* src_buffer = src.buffer + src.crop_y * src.stride_bytes +
+ src.crop_x * src.sample_bytes;
+ uint8_t* dst_buffer = dst.buffer + dst.crop_y * dst.stride_bytes +
+ dst.crop_x * dst.sample_bytes;
+ int width = dst.crop_width;
+ int height = dst.crop_height;
+
+ if (v_flip) {
+ height = -height;
+ }
+
+ // libyuv's ARGB format is hwcomposer's BGRA format, since blending only cares
+ // for the position of alpha in the pixel and not the position of the colors
+ // this function is perfectly usable.
+ return libyuv::ARGBBlend(src_buffer, src.stride_bytes,
+ dst_buffer, dst.stride_bytes,
+ dst_buffer, dst.stride_bytes,
+ width, height);
+}
+
+std::optional<BufferSpec> GetBufferSpec(GrallocBuffer& buffer,
+ const hwc_rect_t& buffer_crop) {
+ auto buffer_format_opt = buffer.GetDrmFormat();
+ if (!buffer_format_opt) {
+ ALOGE("Failed to get gralloc buffer format.");
+ return std::nullopt;
+ }
+ uint32_t buffer_format = *buffer_format_opt;
+
+ auto buffer_width_opt = buffer.GetWidth();
+ if (!buffer_width_opt) {
+ ALOGE("Failed to get gralloc buffer width.");
+ return std::nullopt;
+ }
+ uint32_t buffer_width = *buffer_width_opt;
+
+ auto buffer_height_opt = buffer.GetHeight();
+ if (!buffer_height_opt) {
+ ALOGE("Failed to get gralloc buffer height.");
+ return std::nullopt;
+ }
+ uint32_t buffer_height = *buffer_height_opt;
+
+ uint8_t* buffer_data = nullptr;
+ uint32_t buffer_stride_bytes = 0;
+ std::optional<android_ycbcr> buffer_ycbcr_data;
+
+ if (buffer_format == DRM_FORMAT_NV12 ||
+ buffer_format == DRM_FORMAT_NV21 ||
+ buffer_format == DRM_FORMAT_YVU420) {
+ buffer_ycbcr_data = buffer.LockYCbCr();
+ if (!buffer_ycbcr_data) {
+ ALOGE("%s failed to lock gralloc buffer.", __FUNCTION__);
+ return std::nullopt;
+ }
+ } else {
+ auto buffer_data_opt = buffer.Lock();
+ if (!buffer_data_opt) {
+ ALOGE("%s failed to lock gralloc buffer.", __FUNCTION__);
+ return std::nullopt;
+ }
+ buffer_data = reinterpret_cast<uint8_t*>(*buffer_data_opt);
+
+ auto buffer_stride_bytes_opt = buffer.GetMonoPlanarStrideBytes();
+ if (!buffer_stride_bytes_opt) {
+ ALOGE("%s failed to get plane stride.", __FUNCTION__);
+ return std::nullopt;
+ }
+ buffer_stride_bytes = *buffer_stride_bytes_opt;
+ }
+
+ return BufferSpec(
+ buffer_data,
+ buffer_ycbcr_data,
+ buffer_width,
+ buffer_height,
+ buffer_crop.left,
+ buffer_crop.top,
+ buffer_crop.right - buffer_crop.left,
+ buffer_crop.bottom - buffer_crop.top,
+ buffer_format,
+ buffer_stride_bytes,
+ GetDrmFormatBytesPerPixel(buffer_format));
+}
+
+} // namespace
+
+bool CpuComposer::CanCompositeLayer(const hwc_layer_1_t& layer) {
+ buffer_handle_t buffer_handle = layer.handle;
+ if (buffer_handle == nullptr) {
+ ALOGW("%s received a layer with a null handle", __FUNCTION__);
+ return false;
+ }
+
+ auto buffer_opt = gralloc_.Import(buffer_handle);
+ if (!buffer_opt) {
+ ALOGE("Failed to import layer buffer.");
+ return false;
+ }
+ GrallocBuffer& buffer = *buffer_opt;
+
+ auto buffer_format_opt = buffer.GetDrmFormat();
+ if (!buffer_format_opt) {
+ ALOGE("Failed to get layer buffer format.");
+ return false;
+ }
+ uint32_t buffer_format = *buffer_format_opt;
+
+ if (!IsDrmFormatSupported(buffer_format)) {
+ ALOGD("Unsupported pixel format: 0x%x, doing software composition instead",
+ buffer_format);
+ return false;
+ }
+ return true;
+}
+
+void CpuComposer::CompositeLayer(hwc_layer_1_t* src_layer, int buffer_idx) {
+ libyuv::RotationMode rotation =
+ GetRotationFromTransform(src_layer->transform);
+
+ auto src_imported_buffer_opt = gralloc_.Import(src_layer->handle);
+ if (!src_imported_buffer_opt) {
+ ALOGE("Failed to import layer buffer.");
+ return;
+ }
+ GrallocBuffer& src_imported_buffer = *src_imported_buffer_opt;
+
+ auto src_layer_spec_opt = GetBufferSpec(src_imported_buffer, src_layer->sourceCrop);
+ if (!src_layer_spec_opt) {
+ return;
+ }
+ BufferSpec src_layer_spec = *src_layer_spec_opt;
+
+ // TODO(jemoreira): Remove the hardcoded fomat.
+ bool needs_conversion = src_layer_spec.drm_format != DRM_FORMAT_XBGR8888;
+ bool needs_scaling = LayerNeedsScaling(*src_layer);
+ bool needs_rotation = rotation != libyuv::kRotate0;
+ bool needs_transpose = needs_rotation && rotation != libyuv::kRotate180;
+ bool needs_vflip = GetVFlipFromTransform(src_layer->transform);
+ bool needs_attenuation = LayerNeedsAttenuation(*src_layer);
+ bool needs_blending = LayerNeedsBlending(*src_layer);
+ bool needs_copy = !(needs_conversion || needs_scaling || needs_rotation ||
+ needs_vflip || needs_attenuation || needs_blending);
+
+ uint8_t* dst_buffer =
+ reinterpret_cast<uint8_t*>(screen_view_->GetBuffer(buffer_idx));
+
+ BufferSpec dst_layer_spec(
+ dst_buffer,
+ /*buffer_ycbcr=*/std::nullopt,
+ screen_view_->x_res(),
+ screen_view_->y_res(),
+ src_layer->displayFrame.left,
+ src_layer->displayFrame.top,
+ src_layer->displayFrame.right - src_layer->displayFrame.left,
+ src_layer->displayFrame.bottom - src_layer->displayFrame.top,
+ DRM_FORMAT_XBGR8888,
+ screen_view_->line_length(),
+ 4);
+
+ // Add the destination layer to the bottom of the buffer stack
+ std::vector<BufferSpec> dest_buffer_stack(1, dst_layer_spec);
+
+ // If more than operation is to be performed, a temporary buffer is needed for
+ // each additional operation
+
+ // N operations need N destination buffers, the destination layer (the
+ // framebuffer) is one of them, so only N-1 temporary buffers are needed.
+ // Vertical flip is not taken into account because it can be done together
+ // with any other operation.
+ int needed_tmp_buffers = (needs_conversion ? 1 : 0) +
+ (needs_scaling ? 1 : 0) + (needs_rotation ? 1 : 0) +
+ (needs_attenuation ? 1 : 0) +
+ (needs_blending ? 1 : 0) + (needs_copy ? 1 : 0) - 1;
+
+ int tmp_buffer_width =
+ src_layer->displayFrame.right - src_layer->displayFrame.left;
+ int tmp_buffer_height =
+ src_layer->displayFrame.bottom - src_layer->displayFrame.top;
+ int tmp_buffer_stride_bytes =
+ cvd::AlignToPowerOf2(tmp_buffer_width * screen_view_->bytes_per_pixel(), 4);
+
+ for (int i = 0; i < needed_tmp_buffers; i++) {
+ BufferSpec tmp_buffer_spec(
+ RotateTmpBuffer(i),
+ tmp_buffer_width,
+ tmp_buffer_height,
+ tmp_buffer_stride_bytes);
+ dest_buffer_stack.push_back(tmp_buffer_spec);
+ }
+
+ // Conversion and scaling should always be the first operations, so that every
+ // other operation works on equally sized frames (garanteed to fit in the tmp
+ // buffers)
+
+ // TODO(jemoreira): We are converting to ARGB as the first step under the
+ // assumption that scaling ARGB is faster than scaling I420 (the most common).
+ // This should be confirmed with testing.
+ if (needs_conversion) {
+ BufferSpec& dst_buffer_spec = dest_buffer_stack.back();
+ if (needs_scaling || needs_transpose) {
+ // If a rotation or a scaling operation are needed the dimensions at the
+ // top of the buffer stack are wrong (wrong sizes for scaling, swapped
+ // width and height for 90 and 270 rotations).
+ // Make width and height match the crop sizes on the source
+ int src_width = src_layer_spec.crop_width;
+ int src_height = src_layer_spec.crop_height;
+ int dst_stride_bytes =
+ cvd::AlignToPowerOf2(src_width * screen_view_->bytes_per_pixel(), 4);
+ size_t needed_size = dst_stride_bytes * src_height;
+ dst_buffer_spec.width = src_width;
+ dst_buffer_spec.height = src_height;
+ // Adjust the stride accordingly
+ dst_buffer_spec.stride_bytes = dst_stride_bytes;
+ // Crop sizes also need to be adjusted
+ dst_buffer_spec.crop_width = src_width;
+ dst_buffer_spec.crop_height = src_height;
+ // crop_x and y are fine at 0, format is already set to match destination
+
+ // In case of a scale, the source frame may be bigger than the default tmp
+ // buffer size
+ if (needed_size > tmp_buffer_.size() / kNumTmpBufferPieces) {
+ dst_buffer_spec.buffer = GetSpecialTmpBuffer(needed_size);
+ }
+ }
+
+ int retval = DoConversion(src_layer_spec, dst_buffer_spec, needs_vflip);
+ if (retval) {
+ ALOGE("Got error code %d from DoConversion function", retval);
+ }
+ needs_vflip = false;
+ src_layer_spec = dst_buffer_spec;
+ dest_buffer_stack.pop_back();
+ }
+
+ if (needs_scaling) {
+ BufferSpec& dst_buffer_spec = dest_buffer_stack.back();
+ if (needs_transpose) {
+ // If a rotation is needed, the temporary buffer has the correct size but
+ // needs to be transposed and have its stride updated accordingly. The
+ // crop sizes also needs to be transposed, but not the x and y since they
+ // are both zero in a temporary buffer (and it is a temporary buffer
+ // because a rotation will be performed next).
+ std::swap(dst_buffer_spec.width, dst_buffer_spec.height);
+ std::swap(dst_buffer_spec.crop_width, dst_buffer_spec.crop_height);
+ // TODO (jemoreira): Aligment (To align here may cause the needed size to
+ // be bigger than the buffer, so care should be taken)
+ dst_buffer_spec.stride_bytes =
+ dst_buffer_spec.width * screen_view_->bytes_per_pixel();
+ }
+ int retval = DoScaling(src_layer_spec, dst_buffer_spec, needs_vflip);
+ needs_vflip = false;
+ if (retval) {
+ ALOGE("Got error code %d from DoScaling function", retval);
+ }
+ src_layer_spec = dst_buffer_spec;
+ dest_buffer_stack.pop_back();
+ }
+
+ if (needs_rotation) {
+ int retval = DoRotation(src_layer_spec, dest_buffer_stack.back(), rotation,
+ needs_vflip);
+ needs_vflip = false;
+ if (retval) {
+ ALOGE("Got error code %d from DoTransform function", retval);
+ }
+ src_layer_spec = dest_buffer_stack.back();
+ dest_buffer_stack.pop_back();
+ }
+
+ if (needs_attenuation) {
+ int retval = DoAttenuation(src_layer_spec, dest_buffer_stack.back(),
+ needs_vflip);
+ needs_vflip = false;
+ if (retval) {
+ ALOGE("Got error code %d from DoBlending function", retval);
+ }
+ src_layer_spec = dest_buffer_stack.back();
+ dest_buffer_stack.pop_back();
+ }
+
+ if (needs_copy) {
+ int retval = DoCopy(src_layer_spec, dest_buffer_stack.back(), needs_vflip);
+ needs_vflip = false;
+ if (retval) {
+ ALOGE("Got error code %d from DoBlending function", retval);
+ }
+ src_layer_spec = dest_buffer_stack.back();
+ dest_buffer_stack.pop_back();
+ }
+
+ // Blending (if needed) should always be the last operation, so that it reads
+ // and writes in the destination layer and not some temporary buffer.
+ if (needs_blending) {
+ int retval = DoBlending(src_layer_spec, dest_buffer_stack.back(),
+ needs_vflip);
+ needs_vflip = false;
+ if (retval) {
+ ALOGE("Got error code %d from DoBlending function", retval);
+ }
+ // Don't need to assign destination to source in the last one
+ dest_buffer_stack.pop_back();
+ }
+
+ src_imported_buffer.Unlock();
+}
+
+/* static */ const int CpuComposer::kNumTmpBufferPieces = 2;
+
+CpuComposer::CpuComposer(std::unique_ptr<ScreenView> screen_view)
+ : BaseComposer(std::move(screen_view)),
+ tmp_buffer_(kNumTmpBufferPieces * screen_view_->buffer_size()) {}
+
+int CpuComposer::PrepareLayers(size_t num_layers, hwc_layer_1_t* layers) {
+ int composited_layers_count = 0;
+
+ // Loop over layers in inverse order of z-index
+ for (size_t layer_index = num_layers; layer_index > 0;) {
+ // Decrement here to be able to compare unsigned integer with 0 in the
+ // loop condition
+ --layer_index;
+ if (IS_TARGET_FRAMEBUFFER(layers[layer_index].compositionType)) {
+ continue;
+ }
+ if (layers[layer_index].flags & HWC_SKIP_LAYER) {
+ continue;
+ }
+ if (layers[layer_index].compositionType == HWC_BACKGROUND) {
+ layers[layer_index].compositionType = HWC_FRAMEBUFFER;
+ continue;
+ }
+ layers[layer_index].compositionType = HWC_OVERLAY;
+ // Hwcomposer cannot draw below software-composed layers, so we need
+ // to mark those HWC_FRAMEBUFFER as well.
+ for (size_t top_idx = layer_index + 1; top_idx < num_layers; ++top_idx) {
+ // layers marked as skip are in a state that makes them unreliable to
+ // read, so it's best to assume they cover the whole screen
+ if (layers[top_idx].flags & HWC_SKIP_LAYER ||
+ (layers[top_idx].compositionType == HWC_FRAMEBUFFER &&
+ LayersOverlap(layers[layer_index], layers[top_idx]))) {
+ layers[layer_index].compositionType = HWC_FRAMEBUFFER;
+ break;
+ }
+ }
+ if (layers[layer_index].compositionType == HWC_OVERLAY &&
+ !CanCompositeLayer(layers[layer_index])) {
+ layers[layer_index].compositionType = HWC_FRAMEBUFFER;
+ }
+ if (layers[layer_index].compositionType == HWC_OVERLAY) {
+ ++composited_layers_count;
+ }
+ }
+ return composited_layers_count;
+}
+
+int CpuComposer::SetLayers(size_t num_layers, hwc_layer_1_t* layers) {
+ int targetFbs = 0;
+ int buffer_idx = screen_view_->NextBuffer();
+
+ // The framebuffer target layer should be composed if at least one layers was
+ // marked HWC_FRAMEBUFFER or if it's the only layer in the composition
+ // (unlikely)
+ bool fb_target = true;
+ for (size_t idx = 0; idx < num_layers; idx++) {
+ if (layers[idx].compositionType == HWC_FRAMEBUFFER) {
+ // At least one was found
+ fb_target = true;
+ break;
+ }
+ if (layers[idx].compositionType == HWC_OVERLAY) {
+ // Not the only layer in the composition
+ fb_target = false;
+ }
+ }
+
+ // When the framebuffer target needs to be composed, it has to go first.
+ if (fb_target) {
+ for (size_t idx = 0; idx < num_layers; idx++) {
+ if (IS_TARGET_FRAMEBUFFER(layers[idx].compositionType)) {
+ CompositeLayer(&layers[idx], buffer_idx);
+ break;
+ }
+ }
+ }
+
+ for (size_t idx = 0; idx < num_layers; idx++) {
+ if (IS_TARGET_FRAMEBUFFER(layers[idx].compositionType)) {
+ ++targetFbs;
+ }
+ if (layers[idx].compositionType == HWC_OVERLAY &&
+ !(layers[idx].flags & HWC_SKIP_LAYER)) {
+ CompositeLayer(&layers[idx], buffer_idx);
+ }
+ }
+ if (targetFbs != 1) {
+ ALOGW("Saw %zu layers, posted=%d", num_layers, targetFbs);
+ }
+ screen_view_->Broadcast(buffer_idx);
+ return 0;
+}
+
+uint8_t* CpuComposer::RotateTmpBuffer(unsigned int order) {
+ return &tmp_buffer_[(order % kNumTmpBufferPieces) * tmp_buffer_.size() /
+ kNumTmpBufferPieces];
+}
+
+uint8_t* CpuComposer::GetSpecialTmpBuffer(size_t needed_size) {
+ special_tmp_buffer_.resize(needed_size);
+ return &special_tmp_buffer_[0];
+}
+
+} // namespace cvd
diff --git a/guest/hals/hwcomposer/common/cpu_composer.h b/guest/hals/hwcomposer/common/cpu_composer.h
new file mode 100644
index 000000000..f331e2d5a
--- /dev/null
+++ b/guest/hals/hwcomposer/common/cpu_composer.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <vector>
+
+#include <hardware/gralloc.h>
+
+#include "guest/hals/hwcomposer/common/base_composer.h"
+#include "guest/hals/hwcomposer/common/hwcomposer.h"
+
+namespace cvd {
+
+class CpuComposer : public BaseComposer {
+ public:
+ CpuComposer(std::unique_ptr<ScreenView> screen_view);
+ virtual ~CpuComposer() = default;
+
+ // override
+ int PrepareLayers(size_t num_layers, hwc_layer_1_t* layers) override;
+ // override
+ int SetLayers(size_t num_layers, hwc_layer_1_t* layers) override;
+
+ protected:
+ static const int kNumTmpBufferPieces;
+ uint8_t* RotateTmpBuffer(unsigned int order);
+ uint8_t* GetSpecialTmpBuffer(size_t needed_size);
+ bool CanCompositeLayer(const hwc_layer_1_t& layer);
+ void CompositeLayer(hwc_layer_1_t* src_layer, int32_t fb_offset);
+ std::vector<uint8_t> tmp_buffer_;
+ std::vector<uint8_t> special_tmp_buffer_;
+};
+
+} // namespace cvd
diff --git a/guest/hals/hwcomposer/common/drm_utils.cpp b/guest/hals/hwcomposer/common/drm_utils.cpp
new file mode 100644
index 000000000..d4c864ed6
--- /dev/null
+++ b/guest/hals/hwcomposer/common/drm_utils.cpp
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2020 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 "guest/hals/hwcomposer/common/drm_utils.h"
+
+#include <drm_fourcc.h>
+#include <log/log.h>
+#include <system/graphics.h>
+
+namespace cvd {
+
+const char* GetDrmFormatString(uint32_t drm_format) {
+ switch (drm_format) {
+ case DRM_FORMAT_ABGR1555:
+ return "DRM_FORMAT_ABGR1555";
+ case DRM_FORMAT_ABGR2101010:
+ return "DRM_FORMAT_ABGR2101010";
+ case DRM_FORMAT_ABGR4444:
+ return "DRM_FORMAT_ABGR4444";
+ case DRM_FORMAT_ABGR8888:
+ return "DRM_FORMAT_ABGR8888";
+ case DRM_FORMAT_ARGB1555:
+ return "DRM_FORMAT_ARGB1555";
+ case DRM_FORMAT_ARGB2101010:
+ return "DRM_FORMAT_ARGB2101010";
+ case DRM_FORMAT_ARGB4444:
+ return "DRM_FORMAT_ARGB4444";
+ case DRM_FORMAT_ARGB8888:
+ return "DRM_FORMAT_ARGB8888";
+ case DRM_FORMAT_AYUV:
+ return "DRM_FORMAT_AYUV";
+ case DRM_FORMAT_BGR233:
+ return "DRM_FORMAT_BGR233";
+ case DRM_FORMAT_BGR565:
+ return "DRM_FORMAT_BGR565";
+ case DRM_FORMAT_BGR888:
+ return "DRM_FORMAT_BGR888";
+ case DRM_FORMAT_BGRA1010102:
+ return "DRM_FORMAT_BGRA1010102";
+ case DRM_FORMAT_BGRA4444:
+ return "DRM_FORMAT_BGRA4444";
+ case DRM_FORMAT_BGRA5551:
+ return "DRM_FORMAT_BGRA5551";
+ case DRM_FORMAT_BGRA8888:
+ return "DRM_FORMAT_BGRA8888";
+ case DRM_FORMAT_BGRX1010102:
+ return "DRM_FORMAT_BGRX1010102";
+ case DRM_FORMAT_BGRX4444:
+ return "DRM_FORMAT_BGRX4444";
+ case DRM_FORMAT_BGRX5551:
+ return "DRM_FORMAT_BGRX5551";
+ case DRM_FORMAT_BGRX8888:
+ return "DRM_FORMAT_BGRX8888";
+ case DRM_FORMAT_C8:
+ return "DRM_FORMAT_C8";
+ case DRM_FORMAT_GR88:
+ return "DRM_FORMAT_GR88";
+ case DRM_FORMAT_NV12:
+ return "DRM_FORMAT_NV12";
+ case DRM_FORMAT_NV21:
+ return "DRM_FORMAT_NV21";
+ case DRM_FORMAT_R8:
+ return "DRM_FORMAT_R8";
+ case DRM_FORMAT_RG88:
+ return "DRM_FORMAT_RG88";
+ case DRM_FORMAT_RGB332:
+ return "DRM_FORMAT_RGB332";
+ case DRM_FORMAT_RGB565:
+ return "DRM_FORMAT_RGB565";
+ case DRM_FORMAT_RGB888:
+ return "DRM_FORMAT_RGB888";
+ case DRM_FORMAT_RGBA1010102:
+ return "DRM_FORMAT_RGBA1010102";
+ case DRM_FORMAT_RGBA4444:
+ return "DRM_FORMAT_RGBA4444";
+ case DRM_FORMAT_RGBA5551:
+ return "DRM_FORMAT_RGBA5551";
+ case DRM_FORMAT_RGBA8888:
+ return "DRM_FORMAT_RGBA8888";
+ case DRM_FORMAT_RGBX1010102:
+ return "DRM_FORMAT_RGBX1010102";
+ case DRM_FORMAT_RGBX4444:
+ return "DRM_FORMAT_RGBX4444";
+ case DRM_FORMAT_RGBX5551:
+ return "DRM_FORMAT_RGBX5551";
+ case DRM_FORMAT_RGBX8888:
+ return "DRM_FORMAT_RGBX8888";
+ case DRM_FORMAT_UYVY:
+ return "DRM_FORMAT_UYVY";
+ case DRM_FORMAT_VYUY:
+ return "DRM_FORMAT_VYUY";
+ case DRM_FORMAT_XBGR1555:
+ return "DRM_FORMAT_XBGR1555";
+ case DRM_FORMAT_XBGR2101010:
+ return "DRM_FORMAT_XBGR2101010";
+ case DRM_FORMAT_XBGR4444:
+ return "DRM_FORMAT_XBGR4444";
+ case DRM_FORMAT_XBGR8888:
+ return "DRM_FORMAT_XBGR8888";
+ case DRM_FORMAT_XRGB1555:
+ return "DRM_FORMAT_XRGB1555";
+ case DRM_FORMAT_XRGB2101010:
+ return "DRM_FORMAT_XRGB2101010";
+ case DRM_FORMAT_XRGB4444:
+ return "DRM_FORMAT_XRGB4444";
+ case DRM_FORMAT_XRGB8888:
+ return "DRM_FORMAT_XRGB8888";
+ case DRM_FORMAT_YUYV:
+ return "DRM_FORMAT_YUYV";
+ case DRM_FORMAT_YVU420:
+ return "DRM_FORMAT_YVU420";
+ case DRM_FORMAT_YVYU:
+ return "DRM_FORMAT_YVYU";
+ }
+ return "Unknown";
+}
+
+int GetDrmFormatBytesPerPixel(uint32_t drm_format) {
+ switch (drm_format) {
+ case DRM_FORMAT_ABGR8888:
+ case DRM_FORMAT_ARGB8888:
+ case DRM_FORMAT_XBGR8888:
+ return 4;
+ case DRM_FORMAT_BGR888:
+ return 3;
+ case DRM_FORMAT_RGB565:
+ case DRM_FORMAT_YVU420:
+#ifdef GRALLOC_MODULE_API_VERSION_0_2
+ case DRM_FORMAT_FLEX_YCbCr_420_888:
+#endif
+ return 2;
+ case DRM_FORMAT_R8:
+ return 1;
+ }
+ ALOGE("%s: format size unknown %d(%s)", __FUNCTION__, drm_format,
+ GetDrmFormatString(drm_format));
+ return 8;
+}
+
+int GetDrmFormatFromHalFormat(int hal_format) {
+ switch (hal_format) {
+ case HAL_PIXEL_FORMAT_RGBA_FP16:
+ return DRM_FORMAT_ABGR16161616F;
+ case HAL_PIXEL_FORMAT_RGBA_8888:
+ return DRM_FORMAT_ABGR8888;
+ case HAL_PIXEL_FORMAT_RGBX_8888:
+ return DRM_FORMAT_XBGR8888;
+ case HAL_PIXEL_FORMAT_BGRA_8888:
+ return DRM_FORMAT_ARGB8888;
+ case HAL_PIXEL_FORMAT_RGB_888:
+ return DRM_FORMAT_BGR888;
+ case HAL_PIXEL_FORMAT_RGB_565:
+ return DRM_FORMAT_BGR565;
+ case HAL_PIXEL_FORMAT_YV12:
+ return DRM_FORMAT_YVU420;
+ case HAL_PIXEL_FORMAT_YCbCr_420_888:
+ return DRM_FORMAT_YVU420;
+ case HAL_PIXEL_FORMAT_BLOB:
+ return DRM_FORMAT_R8;
+ default:
+ break;
+ }
+ ALOGE("%s unhandled hal format: %d", __FUNCTION__, hal_format);
+ return 0;
+}
+
+} // namespace cvd
diff --git a/host/commands/metrics/metrics_defs.h b/guest/hals/hwcomposer/common/drm_utils.h
index f36b3a0b8..15f788d8a 100644
--- a/host/commands/metrics/metrics_defs.h
+++ b/guest/hals/hwcomposer/common/drm_utils.h
@@ -15,12 +15,14 @@
*/
#pragma once
-namespace cuttlefish {
+#include <cstdlib>
-enum MetricsExitCodes : int {
- kSuccess=0,
- kMetricsError=1,
- kInvalidHostConfiguration=2,
-};
+namespace cvd {
-} // namespace cuttlefish
+const char* GetDrmFormatString(uint32_t drm_format);
+
+int GetDrmFormatBytesPerPixel(uint32_t drm_format);
+
+int GetDrmFormatFromHalFormat(int hal_format);
+
+} // namespace cvd
diff --git a/guest/hals/hwcomposer/common/geometry_utils.cpp b/guest/hals/hwcomposer/common/geometry_utils.cpp
new file mode 100644
index 000000000..ade2d787a
--- /dev/null
+++ b/guest/hals/hwcomposer/common/geometry_utils.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "guest/hals/hwcomposer/common/geometry_utils.h"
+
+#include <algorithm>
+#include <utility>
+
+namespace cvd {
+
+bool LayersOverlap(const hwc_layer_1_t& layer1, const hwc_layer_1_t& layer2) {
+ int left1 = layer1.displayFrame.left;
+ int right1 = layer1.displayFrame.right;
+ int top1 = layer1.displayFrame.top;
+ int bottom1 = layer1.displayFrame.bottom;
+
+ int left2 = layer2.displayFrame.left;
+ int right2 = layer2.displayFrame.right;
+ int top2 = layer2.displayFrame.top;
+ int bottom2 = layer2.displayFrame.bottom;
+
+ bool overlap_x = left1 < right2 && left2 < right1;
+ bool overlap_y = top1 < bottom2 && top2 < bottom1;
+
+ return overlap_x && overlap_y;
+}
+
+} // namespace cvd
diff --git a/host/commands/secure_env/tpm_commands.h b/guest/hals/hwcomposer/common/geometry_utils.h
index ee758445d..5563fa7df 100644
--- a/host/commands/secure_env/tpm_commands.h
+++ b/guest/hals/hwcomposer/common/geometry_utils.h
@@ -1,5 +1,6 @@
+#pragma once
/*
- * Copyright (C) 2020 The Android Open Source Project
+ * Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,9 +15,10 @@
* limitations under the License.
*/
-#pragma once
+#include "guest/hals/hwcomposer/common/hwcomposer.h"
+
+namespace cvd {
-#include <cstddef>
-#include <string>
+bool LayersOverlap(const hwc_layer_1_t& layer1, const hwc_layer_1_t& layer2);
-std::string TpmCommandName(std::uint32_t command_num);
+} // namespace cvd
diff --git a/guest/hals/hwcomposer/common/gralloc_utils.cpp b/guest/hals/hwcomposer/common/gralloc_utils.cpp
new file mode 100644
index 000000000..bb2350f21
--- /dev/null
+++ b/guest/hals/hwcomposer/common/gralloc_utils.cpp
@@ -0,0 +1,529 @@
+/*
+ * Copyright (C) 2020 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 "guest/hals/hwcomposer/common/gralloc_utils.h"
+
+#include <aidl/android/hardware/graphics/common/PlaneLayoutComponent.h>
+#include <aidl/android/hardware/graphics/common/PlaneLayoutComponentType.h>
+#include <drm_fourcc.h>
+#include <gralloctypes/Gralloc4.h>
+#include <hidl/ServiceManagement.h>
+#include <log/log.h>
+
+// TODO(b/146515640): remove this.
+#include "guest/hals/gralloc/legacy/gralloc_vsoc_priv.h"
+#include "guest/hals/hwcomposer/common/drm_utils.h"
+
+using aidl::android::hardware::graphics::common::PlaneLayout;
+using aidl::android::hardware::graphics::common::PlaneLayoutComponent;
+using aidl::android::hardware::graphics::common::PlaneLayoutComponentType;
+using android::hardware::graphics::common::V1_2::BufferUsage;
+using android::hardware::graphics::mapper::V4_0::Error;
+using android::hardware::graphics::mapper::V4_0::IMapper;
+using android::hardware::hidl_handle;
+using android::hardware::hidl_vec;
+using MetadataType =
+ android::hardware::graphics::mapper::V4_0::IMapper::MetadataType;
+
+// TODO(b/146515640): remove this.
+using cuttlefish_gralloc0_buffer_handle_t = private_handle_t;
+
+namespace cvd {
+
+Gralloc::Gralloc() {
+ android::hardware::preloadPassthroughService<IMapper>();
+
+ gralloc4_ = IMapper::getService();
+ if (gralloc4_ != nullptr) {
+ ALOGE("%s using Gralloc4.", __FUNCTION__);
+ return;
+ }
+ ALOGE("%s Gralloc4 not available.", __FUNCTION__);
+
+
+ hw_get_module(GRALLOC_HARDWARE_MODULE_ID,
+ reinterpret_cast<const hw_module_t**>(&gralloc0_));
+ if (gralloc0_ != nullptr) {
+ ALOGE("%s using Gralloc0.", __FUNCTION__);
+ return;
+ }
+ ALOGE("%s Gralloc0 not available.", __FUNCTION__);
+
+ ALOGE("%s No Grallocs available!", __FUNCTION__);
+}
+
+Error Gralloc::GetMetadata(buffer_handle_t buffer, MetadataType type,
+ hidl_vec<uint8_t>* metadata) {
+ if (gralloc4_ == nullptr) {
+ ALOGE("%s Gralloc4 not available.", __FUNCTION__);
+ return Error::NO_RESOURCES;
+ }
+
+ if (metadata == nullptr) {
+ return Error::BAD_VALUE;
+ }
+
+ Error error = Error::NONE;
+
+ auto native_handle = const_cast<native_handle_t*>(buffer);
+
+ auto ret = gralloc4_->get(native_handle, type,
+ [&](const auto& get_error, const auto& get_metadata) {
+ error = get_error;
+ *metadata = get_metadata;
+ });
+
+ if (!ret.isOk()) {
+ error = Error::NO_RESOURCES;
+ }
+
+ if (error != Error::NONE) {
+ ALOGE("%s failed to get metadata %s", __FUNCTION__, type.name.c_str());
+ }
+ return error;
+}
+
+std::optional<uint32_t> Gralloc::GetWidth(buffer_handle_t buffer) {
+ if (gralloc4_ != nullptr) {
+ hidl_vec<uint8_t> encoded_width;
+
+ Error error = GetMetadata(buffer, android::gralloc4::MetadataType_Width,
+ &encoded_width);
+ if (error != Error::NONE) {
+ return std::nullopt;
+ }
+
+ uint64_t width = 0;
+ android::gralloc4::decodeWidth(encoded_width, &width);
+ return static_cast<uint32_t>(width);
+ }
+ if (gralloc0_ != nullptr) {
+ const cuttlefish_gralloc0_buffer_handle_t* gralloc0_buffer =
+ reinterpret_cast<const cuttlefish_gralloc0_buffer_handle_t*>(buffer);
+
+ return gralloc0_buffer->x_res;
+ }
+ return std::nullopt;
+}
+
+std::optional<uint32_t> Gralloc::GetHeight(buffer_handle_t buffer) {
+ if (gralloc4_ != nullptr) {
+ hidl_vec<uint8_t> encoded_height;
+
+ Error error = GetMetadata(buffer, android::gralloc4::MetadataType_Height,
+ &encoded_height);
+ if (error != Error::NONE) {
+ return std::nullopt;
+ }
+
+ uint64_t height = 0;
+ android::gralloc4::decodeHeight(encoded_height, &height);
+ return static_cast<uint32_t>(height);
+ }
+ if (gralloc0_ != nullptr) {
+ const cuttlefish_gralloc0_buffer_handle_t* gralloc0_buffer =
+ reinterpret_cast<const cuttlefish_gralloc0_buffer_handle_t*>(buffer);
+
+ return gralloc0_buffer->y_res;
+ }
+ return std::nullopt;
+}
+
+std::optional<uint32_t> Gralloc::GetDrmFormat(buffer_handle_t buffer) {
+ if (gralloc4_ != nullptr) {
+ hidl_vec<uint8_t> encoded_format;
+
+ Error error = GetMetadata(buffer,
+ android::gralloc4::MetadataType_PixelFormatFourCC,
+ &encoded_format);
+ if (error != Error::NONE) {
+ return std::nullopt;
+ }
+
+ uint32_t format = 0;
+ android::gralloc4::decodePixelFormatFourCC(encoded_format, &format);
+ return static_cast<uint32_t>(format);
+ }
+ if (gralloc0_ != nullptr) {
+ const cuttlefish_gralloc0_buffer_handle_t* gralloc0_buffer =
+ reinterpret_cast<const cuttlefish_gralloc0_buffer_handle_t*>(buffer);
+
+ return GetDrmFormatFromHalFormat(gralloc0_buffer->format);
+ }
+ return std::nullopt;
+}
+
+std::optional<std::vector<PlaneLayout>> Gralloc::GetPlaneLayouts(
+ buffer_handle_t buffer) {
+ if (gralloc4_ != nullptr) {
+ hidl_vec<uint8_t> encoded_layouts;
+
+ Error error = GetMetadata(buffer,
+ android::gralloc4::MetadataType_PlaneLayouts,
+ &encoded_layouts);
+ if (error != Error::NONE) {
+ return std::nullopt;
+ }
+
+ std::vector<PlaneLayout> plane_layouts;
+ android::gralloc4::decodePlaneLayouts(encoded_layouts, &plane_layouts);
+ return plane_layouts;
+ }
+ return std::nullopt;
+}
+
+std::optional<uint32_t> Gralloc::GetMonoPlanarStrideBytes(
+ buffer_handle_t buffer) {
+ if (gralloc4_ != nullptr) {
+ auto plane_layouts_opt = GetPlaneLayouts(buffer);
+ if (!plane_layouts_opt) {
+ return std::nullopt;
+ }
+
+ std::vector<PlaneLayout>& plane_layouts = *plane_layouts_opt;
+ if (plane_layouts.size() != 1) {
+ return std::nullopt;
+ }
+
+ return static_cast<uint32_t>(plane_layouts[0].strideInBytes);
+ }
+ if (gralloc0_ != nullptr) {
+ const cuttlefish_gralloc0_buffer_handle_t* gralloc0_buffer =
+ reinterpret_cast<const cuttlefish_gralloc0_buffer_handle_t*>(buffer);
+
+ int bytes_per_pixel = formatToBytesPerPixel(gralloc0_buffer->format);
+ return gralloc0_buffer->stride_in_pixels * bytes_per_pixel;
+ }
+ return std::nullopt;
+}
+
+std::optional<GrallocBuffer> Gralloc::Import(buffer_handle_t buffer) {
+ if (gralloc4_ != nullptr) {
+ buffer_handle_t imported_buffer;
+
+ Error error;
+ auto ret = gralloc4_->importBuffer(buffer,
+ [&](const auto& err, const auto& buf) {
+ error = err;
+ if (err == Error::NONE) {
+ imported_buffer =
+ static_cast<buffer_handle_t>(buf);
+ }
+ });
+
+ if (!ret.isOk() || error != Error::NONE) {
+ ALOGE("%s failed to import buffer", __FUNCTION__);
+ return std::nullopt;
+ }
+ return GrallocBuffer(this, imported_buffer);
+ }
+ if (gralloc0_ != nullptr) {
+ return GrallocBuffer(this, buffer);
+ }
+ return std::nullopt;
+}
+
+void Gralloc::Release(buffer_handle_t buffer) {
+ if (gralloc4_ != nullptr) {
+ auto native_buffer = const_cast<native_handle_t*>(buffer);
+ auto ret = gralloc4_->freeBuffer(native_buffer);
+
+ if (!ret.isOk()) {
+ ALOGE("%s failed to release buffer", __FUNCTION__);
+ }
+ return;
+ }
+ if (gralloc0_) {
+ // no-opt
+ }
+}
+
+std::optional<void*> Gralloc::Lock(buffer_handle_t buffer) {
+ if (gralloc4_ != nullptr) {
+ auto native_buffer = const_cast<native_handle_t*>(buffer);
+
+ const auto buffer_usage = static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN);
+
+ auto width_opt = GetWidth(buffer);
+ if (!width_opt) {
+ return std::nullopt;
+ }
+
+ auto height_opt = GetHeight(buffer);
+ if (!height_opt) {
+ return std::nullopt;
+ }
+
+ IMapper::Rect buffer_region;
+ buffer_region.left = 0;
+ buffer_region.top = 0;
+ buffer_region.width = *width_opt;
+ buffer_region.height = *height_opt;
+
+ // Empty fence, lock immedietly.
+ hidl_handle fence;
+
+ Error error = Error::NONE;
+ void* data = nullptr;
+
+ auto ret = gralloc4_->lock(native_buffer, buffer_usage, buffer_region,
+ fence,
+ [&](const auto& lock_error,
+ const auto& lock_data) {
+ error = lock_error;
+ if (lock_error == Error::NONE) {
+ data = lock_data;
+ }
+ });
+
+ if (!ret.isOk()) {
+ error = Error::NO_RESOURCES;
+ }
+
+ if (error != Error::NONE) {
+ ALOGE("%s failed to lock buffer", __FUNCTION__);
+ return std::nullopt;
+ }
+
+ return data;
+ }
+ if (gralloc0_ != nullptr) {
+ const cuttlefish_gralloc0_buffer_handle_t* gralloc0_buffer =
+ reinterpret_cast<const cuttlefish_gralloc0_buffer_handle_t*>(buffer);
+
+ void* data = nullptr;
+ int ret = gralloc0_->lock(gralloc0_,
+ gralloc0_buffer,
+ GRALLOC_USAGE_SW_READ_OFTEN,
+ 0,
+ 0,
+ gralloc0_buffer->x_res,
+ gralloc0_buffer->y_res,
+ &data);
+
+ if (ret) {
+ ALOGE("%s failed to lock buffer", __FUNCTION__);
+ return std::nullopt;
+ }
+ return data;
+ }
+ return std::nullopt;
+}
+
+std::optional<android_ycbcr> Gralloc::LockYCbCr(buffer_handle_t buffer) {
+ auto format_opt = GetDrmFormat(buffer);
+ if (!format_opt) {
+ ALOGE("%s failed to check format of buffer", __FUNCTION__);
+ return std::nullopt;
+ }
+
+ if (*format_opt != DRM_FORMAT_NV12 &&
+ *format_opt != DRM_FORMAT_NV21 &&
+ *format_opt != DRM_FORMAT_YVU420) {
+ ALOGE("%s called on non-ycbcr buffer", __FUNCTION__);
+ return std::nullopt;
+ }
+
+ if (gralloc4_ != nullptr) {
+ auto lock_opt = Lock(buffer);
+ if (!lock_opt) {
+ ALOGE("%s failed to lock buffer", __FUNCTION__);
+ return std::nullopt;
+ }
+
+ auto plane_layouts_opt = GetPlaneLayouts(buffer);
+ if (!plane_layouts_opt) {
+ ALOGE("%s failed to get plane layouts", __FUNCTION__);
+ return std::nullopt;
+ }
+
+ android_ycbcr buffer_ycbcr;
+ buffer_ycbcr.y = nullptr;
+ buffer_ycbcr.cb = nullptr;
+ buffer_ycbcr.cr = nullptr;
+ buffer_ycbcr.ystride = 0;
+ buffer_ycbcr.cstride = 0;
+ buffer_ycbcr.chroma_step = 0;
+
+ for (const auto& plane_layout : *plane_layouts_opt) {
+ for (const auto& plane_layout_component : plane_layout.components) {
+ const auto& type = plane_layout_component.type;
+
+ if (!android::gralloc4::isStandardPlaneLayoutComponentType(type)) {
+ continue;
+ }
+
+ auto* component_data =
+ reinterpret_cast<uint8_t*>(*lock_opt) +
+ plane_layout.offsetInBytes +
+ plane_layout_component.offsetInBits / 8;
+
+ switch (static_cast<PlaneLayoutComponentType>(type.value)) {
+ case PlaneLayoutComponentType::Y:
+ buffer_ycbcr.y = component_data;
+ buffer_ycbcr.ystride = plane_layout.strideInBytes;
+ break;
+ case PlaneLayoutComponentType::CB:
+ buffer_ycbcr.cb = component_data;
+ buffer_ycbcr.cstride = plane_layout.strideInBytes;
+ buffer_ycbcr.chroma_step = plane_layout.sampleIncrementInBits / 8;
+ break;
+ case PlaneLayoutComponentType::CR:
+ buffer_ycbcr.cr = component_data;
+ buffer_ycbcr.cstride = plane_layout.strideInBytes;
+ buffer_ycbcr.chroma_step = plane_layout.sampleIncrementInBits / 8;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ return buffer_ycbcr;
+ }
+ if (gralloc0_ != nullptr) {
+ auto lock_opt = Lock(buffer);
+ if (!lock_opt) {
+ ALOGE("%s failed to lock buffer", __FUNCTION__);
+ return std::nullopt;
+ }
+ void* data = *lock_opt;
+
+ const cuttlefish_gralloc0_buffer_handle_t* gralloc0_buffer =
+ reinterpret_cast<const cuttlefish_gralloc0_buffer_handle_t*>(buffer);
+
+ android_ycbcr buffer_ycbcr;
+ formatToYcbcr(gralloc0_buffer->format,
+ gralloc0_buffer->x_res,
+ gralloc0_buffer->y_res,
+ data,
+ &buffer_ycbcr);
+ return buffer_ycbcr;
+ }
+ return std::nullopt;
+}
+
+void Gralloc::Unlock(buffer_handle_t buffer) {
+ if (gralloc4_ != nullptr) {
+ auto native_handle = const_cast<native_handle_t*>(buffer);
+
+ Error error = Error::NONE;
+ auto ret = gralloc4_->unlock(native_handle,
+ [&](const auto& unlock_error, const auto&) {
+ error = unlock_error;
+ });
+
+ if (!ret.isOk()) {
+ error = Error::NO_RESOURCES;
+ }
+
+ if (error != Error::NONE) {
+ ALOGE("%s failed to unlock buffer", __FUNCTION__);
+ }
+ return;
+ }
+ if (gralloc0_ != nullptr) {
+ const cuttlefish_gralloc0_buffer_handle_t* gralloc0_buffer =
+ reinterpret_cast<const cuttlefish_gralloc0_buffer_handle_t*>(buffer);
+
+ gralloc0_->unlock(gralloc0_, gralloc0_buffer);
+ return;
+ }
+}
+
+
+GrallocBuffer::GrallocBuffer(Gralloc* gralloc, buffer_handle_t buffer) :
+ gralloc_(gralloc), buffer_(buffer) {}
+
+GrallocBuffer::~GrallocBuffer() { Release(); }
+
+GrallocBuffer::GrallocBuffer(GrallocBuffer&& rhs) {
+ *this = std::move(rhs);
+}
+
+GrallocBuffer& GrallocBuffer::operator=(GrallocBuffer&& rhs) {
+ gralloc_ = rhs.gralloc_;
+ buffer_ = rhs.buffer_;
+ rhs.gralloc_ = nullptr;
+ rhs.buffer_ = nullptr;
+ return *this;
+}
+
+void GrallocBuffer::Release() {
+ if (gralloc_ && buffer_) {
+ gralloc_->Release(buffer_);
+ gralloc_ = nullptr;
+ buffer_ = nullptr;
+ }
+}
+
+std::optional<void*> GrallocBuffer::Lock() {
+ if (gralloc_ && buffer_) {
+ return gralloc_->Lock(buffer_);
+ }
+ return std::nullopt;
+}
+
+ std::optional<android_ycbcr> GrallocBuffer::LockYCbCr() {
+ if (gralloc_ && buffer_) {
+ return gralloc_->LockYCbCr(buffer_);
+ }
+ return std::nullopt;
+ }
+
+void GrallocBuffer::Unlock() {
+ if (gralloc_ && buffer_) {
+ gralloc_->Unlock(buffer_);
+ }
+}
+
+std::optional<uint32_t> GrallocBuffer::GetWidth() {
+ if (gralloc_ && buffer_) {
+ return gralloc_->GetWidth(buffer_);
+ }
+ return std::nullopt;
+}
+
+std::optional<uint32_t> GrallocBuffer::GetHeight() {
+ if (gralloc_ && buffer_) {
+ return gralloc_->GetHeight(buffer_);
+ }
+ return std::nullopt;
+}
+
+std::optional<uint32_t> GrallocBuffer::GetDrmFormat() {
+ if (gralloc_ && buffer_) {
+ return gralloc_->GetDrmFormat(buffer_);
+ }
+ return std::nullopt;
+}
+
+std::optional<std::vector<PlaneLayout>>
+GrallocBuffer::GetPlaneLayouts() {
+ if (gralloc_ && buffer_) {
+ return gralloc_->GetPlaneLayouts(buffer_);
+ }
+ return std::nullopt;
+}
+
+std::optional<uint32_t> GrallocBuffer::GetMonoPlanarStrideBytes() {
+ if (gralloc_ && buffer_) {
+ return gralloc_->GetMonoPlanarStrideBytes(buffer_);
+ }
+ return std::nullopt;
+}
+
+} // namespace cvd \ No newline at end of file
diff --git a/guest/hals/hwcomposer/common/gralloc_utils.h b/guest/hals/hwcomposer/common/gralloc_utils.h
new file mode 100644
index 000000000..370f2bb3b
--- /dev/null
+++ b/guest/hals/hwcomposer/common/gralloc_utils.h
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2020 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 <memory>
+#include <optional>
+#include <vector>
+
+#include <aidl/android/hardware/graphics/common/PlaneLayout.h>
+#include <android/hardware/graphics/mapper/4.0/IMapper.h>
+#include <hardware/gralloc.h>
+#include <system/graphics.h>
+#include <utils/StrongPointer.h>
+
+namespace cvd {
+
+class Gralloc;
+
+// A gralloc 4.0 buffer that has been imported in the current process and
+// that will be released upon destruction. Users must ensure that the Gralloc
+// instance that this buffer is created with out lives this buffer.
+class GrallocBuffer {
+ public:
+ GrallocBuffer(Gralloc* gralloc, buffer_handle_t buffer);
+ virtual ~GrallocBuffer();
+
+ GrallocBuffer(const GrallocBuffer& rhs) = delete;
+ GrallocBuffer& operator=(const GrallocBuffer& rhs) = delete;
+
+ GrallocBuffer(GrallocBuffer&& rhs);
+ GrallocBuffer& operator=(GrallocBuffer&& rhs);
+
+ // Locks the buffer for reading and returns the mapped address if successful.
+ // Fails and returns nullopt if the underlying buffer is a YCbCr buffer.
+ std::optional<void*> Lock();
+
+ // Locks the buffer for reading and returns the mapped addresses and strides
+ // of each plane if successful. Fails and returns nullopt if the underlying
+ // buffer is not a YCbCr buffer.
+ std::optional<android_ycbcr> LockYCbCr();
+
+ // Unlocks the buffer from reading.
+ void Unlock();
+
+ std::optional<uint32_t> GetWidth();
+ std::optional<uint32_t> GetHeight();
+ std::optional<uint32_t> GetDrmFormat();
+
+ // Returns the stride of the buffer if it is a single plane buffer or fails
+ // and returns nullopt if the buffer is for a multi plane buffer.
+ std::optional<uint32_t> GetMonoPlanarStrideBytes();
+
+ private:
+ std::optional<
+ std::vector<aidl::android::hardware::graphics::common::PlaneLayout>>
+ GetPlaneLayouts();
+
+ void Release();
+
+ Gralloc* gralloc_ = nullptr;
+ buffer_handle_t buffer_ = nullptr;
+};
+
+class Gralloc {
+ public:
+ Gralloc();
+ virtual ~Gralloc() = default;
+
+ // Imports the given buffer handle into the current process and returns an
+ // imported buffer which can be used for reading. Users must ensure that the
+ // Gralloc instance outlives any GrallocBuffers.
+ std::optional<GrallocBuffer> Import(buffer_handle_t buffer);
+
+ private:
+ // The below functions are made avaialble only to GrallocBuffer so that
+ // users only call gralloc functions on *imported* buffers.
+ friend class GrallocBuffer;
+
+ // See GrallocBuffer::Release.
+ void Release(buffer_handle_t buffer);
+
+ // See GrallocBuffer::Lock.
+ std::optional<void*> Lock(buffer_handle_t buffer);
+
+ // See GrallocBuffer::LockYCbCr.
+ std::optional<android_ycbcr> LockYCbCr(buffer_handle_t buffer);
+
+ // See GrallocBuffer::Unlock.
+ void Unlock(buffer_handle_t buffer);
+
+ // See GrallocBuffer::GetWidth.
+ std::optional<uint32_t> GetWidth(buffer_handle_t buffer);
+
+ // See GrallocBuffer::GetHeight.
+ std::optional<uint32_t> GetHeight(buffer_handle_t buffer);
+
+ // See GrallocBuffer::GetDrmFormat.
+ std::optional<uint32_t> GetDrmFormat(buffer_handle_t buffer);
+
+ // See GrallocBuffer::GetPlaneLayouts.
+ std::optional<
+ std::vector<aidl::android::hardware::graphics::common::PlaneLayout>>
+ GetPlaneLayouts(buffer_handle_t buffer);
+
+ // Returns the stride of the buffer if it is a single plane buffer or fails
+ // and returns nullopt if the buffer is for a multi plane buffer.
+ std::optional<uint32_t> GetMonoPlanarStrideBytes(buffer_handle_t);
+
+ // See GrallocBuffer::GetMetadata.
+ android::hardware::graphics::mapper::V4_0::Error GetMetadata(
+ buffer_handle_t buffer,
+ android::hardware::graphics::mapper::V4_0::IMapper::MetadataType type,
+ android::hardware::hidl_vec<uint8_t>* metadata);
+
+ const gralloc_module_t* gralloc0_ = nullptr;
+
+ android::sp<android::hardware::graphics::mapper::V4_0::IMapper> gralloc4_;
+};
+
+} // namespace cvd \ No newline at end of file
diff --git a/guest/hals/hwcomposer/common/hwcomposer.cpp b/guest/hals/hwcomposer/common/hwcomposer.cpp
new file mode 100644
index 000000000..4b512025e
--- /dev/null
+++ b/guest/hals/hwcomposer/common/hwcomposer.cpp
@@ -0,0 +1,574 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Versions of hwcomposer we implement:
+// JB: 0.3
+// JB-MR1 to N : 1.1
+// N-MR1 to ... : We report 1.1 but SurfaceFlinger has the option to use an
+// adapter to treat our 1.1 hwcomposer as a 2.0. If SF stops using that adapter
+// to support 1.1 implementations it can be copied into cuttlefish from
+// frameworks/native/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.*
+
+#define LOG_TAG "hwc.cf_x86"
+#define HWC_REMOVE_DEPRECATED_VERSIONS 1
+
+#include "guest/hals/hwcomposer/common/hwcomposer.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <math.h>
+#include <poll.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sync/sync.h>
+#include <sys/resource.h>
+#include <sys/time.h>
+
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include <cutils/compiler.h>
+#include <cutils/properties.h>
+#include <hardware/gralloc.h>
+#include <hardware/hardware.h>
+#include <hardware/hwcomposer.h>
+#include <hardware/hwcomposer_defs.h>
+#include <log/log.h>
+#include <utils/String8.h>
+#include <utils/Vector.h>
+
+#include "guest/hals/hwcomposer/common/base_composer.h"
+#include "guest/hals/hwcomposer/common/cpu_composer.h"
+#include "guest/hals/hwcomposer/common/geometry_utils.h"
+#include "guest/hals/hwcomposer/common/hwcomposer.h"
+
+#ifdef USE_OLD_HWCOMPOSER
+typedef cvd::BaseComposer ComposerType;
+#else
+typedef cvd::CpuComposer ComposerType;
+#endif
+
+struct hwc_composer_device_data_t {
+ const hwc_procs_t* procs;
+ pthread_t vsync_thread;
+ int64_t vsync_base_timestamp;
+ int32_t vsync_period_ns;
+};
+
+struct cvd_hwc_composer_device_1_t {
+ hwc_composer_device_1_t base;
+ hwc_composer_device_data_t vsync_data;
+ cvd::BaseComposer* composer;
+};
+
+struct external_display_config_t {
+ uint64_t physicalId;
+ uint32_t width;
+ uint32_t height;
+ uint32_t dpi;
+ uint32_t flags;
+};
+
+namespace {
+
+void* hwc_vsync_thread(void* data) {
+ struct hwc_composer_device_data_t* pdev =
+ (struct hwc_composer_device_data_t*)data;
+ setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY);
+
+ int64_t base_timestamp = pdev->vsync_base_timestamp;
+ int64_t last_logged = base_timestamp / 1e9;
+ int sent = 0;
+ int last_sent = 0;
+ static const int log_interval = 60;
+ void (*vsync_proc)(const struct hwc_procs*, int, int64_t) = nullptr;
+ bool log_no_procs = true, log_no_vsync = true;
+ while (true) {
+ struct timespec rt;
+ if (clock_gettime(CLOCK_MONOTONIC, &rt) == -1) {
+ LOG_ALWAYS_FATAL("%s:%d error in vsync thread clock_gettime: %s",
+ __FILE__, __LINE__, strerror(errno));
+ }
+
+ int64_t timestamp = int64_t(rt.tv_sec) * 1e9 + rt.tv_nsec;
+ // Given now's timestamp calculate the time of the next timestamp.
+ timestamp += pdev->vsync_period_ns -
+ (timestamp - base_timestamp) % pdev->vsync_period_ns;
+
+ rt.tv_sec = timestamp / 1e9;
+ rt.tv_nsec = timestamp % static_cast<int32_t>(1e9);
+ int err = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &rt, NULL);
+ if (err == -1) {
+ ALOGE("error in vsync thread: %s", strerror(errno));
+ if (errno == EINTR) {
+ continue;
+ }
+ }
+
+ // The vsync thread is started on device open, it may run before the
+ // registerProcs callback has a chance to be called, so we need to make sure
+ // procs is not NULL before dereferencing it.
+ if (pdev && pdev->procs) {
+ vsync_proc = pdev->procs->vsync;
+ } else if (log_no_procs) {
+ log_no_procs = false;
+ ALOGI("procs is not set yet, unable to deliver vsync event");
+ }
+ if (vsync_proc) {
+ vsync_proc(const_cast<hwc_procs_t*>(pdev->procs), 0, timestamp);
+ ++sent;
+ } else if (log_no_vsync) {
+ log_no_vsync = false;
+ ALOGE("vsync callback is null (but procs was already set)");
+ }
+ if (rt.tv_sec - last_logged > log_interval) {
+ ALOGI("Sent %d syncs in %ds", sent - last_sent, log_interval);
+ last_logged = rt.tv_sec;
+ last_sent = sent;
+ }
+ }
+
+ return NULL;
+}
+
+std::string CompositionString(int type) {
+ switch (type) {
+ case HWC_FRAMEBUFFER:
+ return "Framebuffer";
+ case HWC_OVERLAY:
+ return "Overlay";
+ case HWC_BACKGROUND:
+ return "Background";
+ case HWC_FRAMEBUFFER_TARGET:
+ return "FramebufferTarget";
+ case HWC_SIDEBAND:
+ return "Sideband";
+ case HWC_CURSOR_OVERLAY:
+ return "CursorOverlay";
+ default:
+ return std::string("Unknown (") + std::to_string(type) + ")";
+ }
+}
+
+void LogLayers(int num_layers, hwc_layer_1_t* layers, int invalid) {
+ ALOGE("Layers:");
+ for (int idx = 0; idx < num_layers; ++idx) {
+ std::string log_line;
+ if (idx == invalid) {
+ log_line = "Invalid layer: ";
+ }
+ log_line +=
+ "Composition Type: " + CompositionString(layers[idx].compositionType);
+ ALOGE("%s", log_line.c_str());
+ }
+}
+
+// Ensures that the layer does not include any inconsistencies
+bool IsValidLayer(hwc_composer_device_1_t* dev, const hwc_layer_1_t& layer) {
+ if (layer.flags & HWC_SKIP_LAYER) {
+ // A layer we are asked to skip validate should not be marked as skip
+ ALOGE("%s: Layer is marked as skip", __FUNCTION__);
+ return false;
+ }
+ // Check displayFrame
+ if (layer.displayFrame.left > layer.displayFrame.right ||
+ layer.displayFrame.top > layer.displayFrame.bottom) {
+ ALOGE(
+ "%s: Malformed rectangle (displayFrame): [left = %d, right = %d, top = "
+ "%d, bottom = %d]",
+ __FUNCTION__, layer.displayFrame.left, layer.displayFrame.right,
+ layer.displayFrame.top, layer.displayFrame.bottom);
+ return false;
+ }
+ // Check sourceCrop
+ if (layer.sourceCrop.left > layer.sourceCrop.right ||
+ layer.sourceCrop.top > layer.sourceCrop.bottom) {
+ ALOGE(
+ "%s: Malformed rectangle (sourceCrop): [left = %d, right = %d, top = "
+ "%d, bottom = %d]",
+ __FUNCTION__, layer.sourceCrop.left, layer.sourceCrop.right,
+ layer.sourceCrop.top, layer.sourceCrop.bottom);
+ return false;
+ }
+
+ auto* cvd_hwc_dev = reinterpret_cast<cvd_hwc_composer_device_1_t*>(dev);
+ return cvd_hwc_dev->composer->IsValidLayer(layer);
+}
+
+bool IsValidComposition(hwc_composer_device_1_t* dev, int num_layers,
+ hwc_layer_1_t* layers, bool on_set) {
+ if (num_layers == 0) {
+ ALOGE("Composition requested with 0 layers");
+ return false;
+ }
+ // Sometimes the hwcomposer receives a prepare and set calls with no other
+ // layer than the FRAMEBUFFER_TARGET with a null handler. We treat this case
+ // independently as a valid composition, but issue a warning about it.
+ if (num_layers == 1 && layers[0].compositionType == HWC_FRAMEBUFFER_TARGET &&
+ layers[0].handle == NULL) {
+ ALOGW("Received request for empty composition, treating as valid noop");
+ return true;
+ }
+ // The FRAMEBUFFER_TARGET layer needs to be sane only if
+ // there is at least one layer marked HWC_FRAMEBUFFER or if there is no layer
+ // marked HWC_OVERLAY (i.e some layers where composed with OpenGL, no layer
+ // marked overlay or framebuffer means that surfaceflinger decided to go for
+ // OpenGL without asking the hwcomposer first)
+ bool check_fb_target = true;
+ for (int idx = 0; idx < num_layers; ++idx) {
+ if (layers[idx].compositionType == HWC_FRAMEBUFFER) {
+ // There is at least one, so it needs to be checked.
+ // It may have been set to false before, so ensure it's set to true.
+ check_fb_target = true;
+ break;
+ }
+ if (layers[idx].compositionType == HWC_OVERLAY) {
+ // At least one overlay, we may not need to.
+ check_fb_target = false;
+ }
+ }
+
+ for (int idx = 0; idx < num_layers; ++idx) {
+ switch (layers[idx].compositionType) {
+ case HWC_FRAMEBUFFER_TARGET:
+ // In the call to prepare() the framebuffer target does not have a valid
+ // buffer_handle, so we don't validate it yet.
+ if (on_set && check_fb_target && !IsValidLayer(dev, layers[idx])) {
+ ALOGE("%s: Invalid layer found", __FUNCTION__);
+ LogLayers(num_layers, layers, idx);
+ return false;
+ }
+ break;
+ case HWC_OVERLAY:
+ if (!(layers[idx].flags & HWC_SKIP_LAYER) &&
+ !IsValidLayer(dev, layers[idx])) {
+ ALOGE("%s: Invalid layer found", __FUNCTION__);
+ LogLayers(num_layers, layers, idx);
+ return false;
+ }
+ break;
+ }
+ }
+ return true;
+}
+
+// Note predefined "hwservicemanager." is used to avoid adding new selinux rules
+#define EXTERANL_DISPLAY_PROP "hwservicemanager.external.displays"
+
+// return 0 for successful
+// return < 0 if failed
+int GetExternalDisplayConfigs(std::vector<struct external_display_config_t>* configs) {
+ // this guest property, hwservicemanager.external.displays,
+ // specifies multi-display info, with comma (,) as separator
+ // each display has the following info:
+ // physicalId,width,height,dpi,flags
+ // several displays can be provided, e.g., following has 2 displays:
+ // setprop hwservicemanager.external.displays 1,1200,800,120,0,2,1200,800,120,0
+ std::vector<uint64_t> values;
+ char displays_value[PROPERTY_VALUE_MAX] = "";
+ property_get(EXTERANL_DISPLAY_PROP, displays_value, "");
+ bool valid = displays_value[0] != '\0';
+ if (valid) {
+ char *p = displays_value;
+ while (*p) {
+ if (!isdigit(*p) && *p != ',' && *p != ' ') {
+ valid = false;
+ break;
+ }
+ p++;
+ }
+ }
+ if (!valid) {
+ // no external displays are specified
+ ALOGE("%s: Invalid syntax for the value of system prop: %s, value: %s",
+ __FUNCTION__, EXTERANL_DISPLAY_PROP, displays_value);
+ return 0;
+ }
+ // parse all int values to a vector
+ std::istringstream stream(displays_value);
+ for (uint64_t id; stream >> id;) {
+ values.push_back(id);
+ if (stream.peek() == ',')
+ stream.ignore();
+ }
+ // each display has 5 values
+ if ((values.size() % 5) != 0) {
+ ALOGE("%s: Invalid value for system property: %s", __FUNCTION__, EXTERANL_DISPLAY_PROP);
+ return -1;
+ }
+ while (!values.empty()) {
+ struct external_display_config_t config;
+ config.physicalId = values[0];
+ config.width = values[1];
+ config.height = values[2];
+ config.dpi = values[3];
+ config.flags = values[4];
+ values.erase(values.begin(), values.begin() + 5);
+ configs->push_back(config);
+ }
+ return 0;
+}
+
+} // namespace
+
+static int cvd_hwc_prepare(hwc_composer_device_1_t* dev, size_t numDisplays,
+ hwc_display_contents_1_t** displays) {
+ if (!numDisplays || !displays) return 0;
+
+ for (int disp = 0; disp < numDisplays; ++disp) {
+ hwc_display_contents_1_t* list = displays[disp];
+
+ if (!list) return 0;
+ if (!IsValidComposition(dev, list->numHwLayers, &list->hwLayers[0], false)) {
+ LOG_ALWAYS_FATAL("%s: Invalid composition requested", __FUNCTION__);
+ return -1;
+ }
+ reinterpret_cast<cvd_hwc_composer_device_1_t*>(dev)->composer->PrepareLayers(
+ list->numHwLayers, &list->hwLayers[0]);
+ }
+ return 0;
+}
+
+static int cvd_hwc_set(hwc_composer_device_1_t* dev, size_t numDisplays,
+ hwc_display_contents_1_t** displays) {
+ if (!numDisplays || !displays) return 0;
+
+ int retval = -1;
+ for (int disp = 0; disp < numDisplays; ++disp) {
+ hwc_display_contents_1_t* contents = displays[disp];
+ if (!contents) return 0;
+
+ hwc_layer_1_t* layers = &contents->hwLayers[0];
+ if (contents->numHwLayers == 1 &&
+ layers[0].compositionType == HWC_FRAMEBUFFER_TARGET) {
+ ALOGW("Received request for empty composition, treating as valid noop");
+ return 0;
+ }
+ if (!IsValidComposition(dev, contents->numHwLayers, layers, true)) {
+ LOG_ALWAYS_FATAL("%s: Invalid composition requested", __FUNCTION__);
+ return -1;
+ }
+ retval =
+ reinterpret_cast<cvd_hwc_composer_device_1_t*>(dev)->composer->SetLayers(
+ contents->numHwLayers, layers);
+ if (retval != 0) break;
+
+ int closedFds = 0;
+ for (size_t index = 0; index < contents->numHwLayers; ++index) {
+ if (layers[index].acquireFenceFd != -1) {
+ close(layers[index].acquireFenceFd);
+ layers[index].acquireFenceFd = -1;
+ ++closedFds;
+ }
+ }
+ if (closedFds) {
+ ALOGI("Saw %zu layers, closed=%d", contents->numHwLayers, closedFds);
+ }
+
+ // TODO(ghartman): This should be set before returning. On the next set it
+ // should be signalled when we load the new frame.
+ contents->retireFenceFd = -1;
+ }
+
+ return retval;
+}
+
+static void cvd_hwc_register_procs(hwc_composer_device_1_t* dev,
+ const hwc_procs_t* procs) {
+ struct cvd_hwc_composer_device_1_t* pdev =
+ (struct cvd_hwc_composer_device_1_t*)dev;
+ pdev->vsync_data.procs = procs;
+ if (procs) {
+ std::vector<struct external_display_config_t> configs;
+ int res = GetExternalDisplayConfigs(&configs);
+ if (res == 0 && !configs.empty()) {
+ // configs will be used in the future
+ procs->hotplug(procs, HWC_DISPLAY_EXTERNAL, 1);
+ }
+ }
+}
+
+static int cvd_hwc_query(hwc_composer_device_1_t* dev, int what, int* value) {
+ struct cvd_hwc_composer_device_1_t* pdev =
+ (struct cvd_hwc_composer_device_1_t*)dev;
+
+ switch (what) {
+ case HWC_BACKGROUND_LAYER_SUPPORTED:
+ // we support the background layer
+ value[0] = 0;
+ break;
+ case HWC_VSYNC_PERIOD:
+ value[0] = pdev->vsync_data.vsync_period_ns;
+ break;
+ default:
+ // unsupported query
+ ALOGE("%s badness unsupported query what=%d", __FUNCTION__, what);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int cvd_hwc_event_control(hwc_composer_device_1_t* /*dev*/, int /*dpy*/,
+ int event, int /*enabled*/) {
+ if (event == HWC_EVENT_VSYNC) {
+ return 0;
+ }
+ return -EINVAL;
+}
+
+static int cvd_hwc_blank(hwc_composer_device_1_t* /*dev*/, int disp, int /*blank*/) {
+ if (!IS_PRIMARY_DISPLAY(disp) && !IS_EXTERNAL_DISPLAY(disp)) return -EINVAL;
+ return 0;
+}
+
+static void cvd_hwc_dump(hwc_composer_device_1_t* dev, char* buff, int buff_len) {
+ reinterpret_cast<cvd_hwc_composer_device_1_t*>(dev)->composer->Dump(buff,
+ buff_len);
+}
+
+static int cvd_hwc_get_display_configs(hwc_composer_device_1_t* /*dev*/, int disp,
+ uint32_t* configs, size_t* numConfigs) {
+ if (*numConfigs == 0) return 0;
+
+ if (IS_PRIMARY_DISPLAY(disp) || IS_EXTERNAL_DISPLAY(disp)) {
+ configs[0] = 0;
+ *numConfigs = 1;
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static int32_t cvd_hwc_attribute(struct cvd_hwc_composer_device_1_t* pdev,
+ const uint32_t attribute) {
+ switch (attribute) {
+ case HWC_DISPLAY_VSYNC_PERIOD:
+ return pdev->vsync_data.vsync_period_ns;
+ case HWC_DISPLAY_WIDTH:
+ return pdev->composer->x_res();
+ case HWC_DISPLAY_HEIGHT:
+ return pdev->composer->y_res();
+ case HWC_DISPLAY_DPI_X:
+ ALOGI("Reporting DPI_X of %d", pdev->composer->dpi());
+ // The number of pixels per thousand inches
+ return pdev->composer->dpi() * 1000;
+ case HWC_DISPLAY_DPI_Y:
+ ALOGI("Reporting DPI_Y of %d", pdev->composer->dpi());
+ // The number of pixels per thousand inches
+ return pdev->composer->dpi() * 1000;
+ default:
+ ALOGE("unknown display attribute %u", attribute);
+ return -EINVAL;
+ }
+}
+
+static int cvd_hwc_get_display_attributes(hwc_composer_device_1_t* dev, int disp,
+ uint32_t config __unused,
+ const uint32_t* attributes,
+ int32_t* values) {
+ struct cvd_hwc_composer_device_1_t* pdev =
+ (struct cvd_hwc_composer_device_1_t*)dev;
+ if (!IS_PRIMARY_DISPLAY(disp) && !IS_EXTERNAL_DISPLAY(disp)) {
+ ALOGE("unknown display type %u", disp);
+ return -EINVAL;
+ }
+
+ for (int i = 0; attributes[i] != HWC_DISPLAY_NO_ATTRIBUTE; i++) {
+ values[i] = cvd_hwc_attribute(pdev, attributes[i]);
+ }
+
+ return 0;
+}
+
+static int cvd_hwc_close(hw_device_t* device) {
+ struct cvd_hwc_composer_device_1_t* dev =
+ (struct cvd_hwc_composer_device_1_t*)device;
+ ALOGE("cvd_hwc_close");
+ pthread_kill(dev->vsync_data.vsync_thread, SIGTERM);
+ pthread_join(dev->vsync_data.vsync_thread, NULL);
+ delete dev->composer;
+ delete dev;
+ return 0;
+}
+
+namespace cvd {
+
+int cvd_hwc_open(std::unique_ptr<ScreenView> screen_view,
+ const struct hw_module_t* module, const char* name,
+ struct hw_device_t** device) {
+ ALOGI("%s", __FUNCTION__);
+ if (strcmp(name, HWC_HARDWARE_COMPOSER)) {
+ ALOGE("%s called with bad name %s", __FUNCTION__, name);
+ return -EINVAL;
+ }
+
+ cvd_hwc_composer_device_1_t* dev = new cvd_hwc_composer_device_1_t();
+ if (!dev) {
+ ALOGE("%s failed to allocate dev", __FUNCTION__);
+ return -ENOMEM;
+ }
+
+ struct timespec rt;
+ if (clock_gettime(CLOCK_MONOTONIC, &rt) == -1) {
+ ALOGE("%s:%d error in vsync thread clock_gettime: %s", __FILE__, __LINE__,
+ strerror(errno));
+ }
+ dev->vsync_data.vsync_base_timestamp = int64_t(rt.tv_sec) * 1e9 + rt.tv_nsec;
+ dev->vsync_data.vsync_period_ns = 1e9 / screen_view->refresh_rate();
+
+ dev->base.common.tag = HARDWARE_DEVICE_TAG;
+ dev->base.common.version = HWC_DEVICE_API_VERSION_1_1;
+ dev->base.common.module = const_cast<hw_module_t*>(module);
+ dev->base.common.close = cvd_hwc_close;
+
+ dev->base.prepare = cvd_hwc_prepare;
+ dev->base.set = cvd_hwc_set;
+ dev->base.query = cvd_hwc_query;
+ dev->base.registerProcs = cvd_hwc_register_procs;
+ dev->base.dump = cvd_hwc_dump;
+ dev->base.blank = cvd_hwc_blank;
+ dev->base.eventControl = cvd_hwc_event_control;
+ dev->base.getDisplayConfigs = cvd_hwc_get_display_configs;
+ dev->base.getDisplayAttributes = cvd_hwc_get_display_attributes;
+#ifdef GATHER_STATS
+ dev->composer = new cvd::StatsKeepingComposer<ComposerType>(
+ dev->vsync_data.vsync_base_timestamp, std::move(screen_view));
+#else
+ dev->composer = new ComposerType(std::move(screen_view));
+#endif
+
+ if (!dev->composer) {
+ ALOGE("Failed to instantiate the composer object");
+ delete dev;
+ return -1;
+ }
+ int ret = pthread_create(&dev->vsync_data.vsync_thread, NULL,
+ hwc_vsync_thread, &dev->vsync_data);
+ if (ret) {
+ ALOGE("failed to start vsync thread: %s", strerror(ret));
+ ret = -ret;
+ delete dev->composer;
+ delete dev;
+ } else {
+ *device = &dev->base.common;
+ }
+
+ return ret;
+}
+
+} // namespace cvd
diff --git a/guest/hals/hwcomposer/common/hwcomposer.h b/guest/hals/hwcomposer/common/hwcomposer.h
new file mode 100644
index 000000000..60a786c9d
--- /dev/null
+++ b/guest/hals/hwcomposer/common/hwcomposer.h
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+#pragma once
+
+#include <memory>
+
+#include <hardware/hwcomposer.h>
+#include <hardware/hwcomposer_defs.h>
+
+#include "guest/hals/hwcomposer/common/screen_view.h"
+
+#define IS_TARGET_FRAMEBUFFER(x) ((x) == HWC_FRAMEBUFFER_TARGET)
+#define IS_PRIMARY_DISPLAY(x) ((x) == HWC_DISPLAY_PRIMARY)
+#define IS_EXTERNAL_DISPLAY(x) ((x) == HWC_DISPLAY_EXTERNAL)
+
+namespace cvd {
+int cvd_hwc_open(std::unique_ptr<ScreenView> screen_view,
+ const struct hw_module_t* module, const char* name,
+ struct hw_device_t** device);
+} // namespace cvd
diff --git a/guest/hals/hwcomposer/common/screen_view.cpp b/guest/hals/hwcomposer/common/screen_view.cpp
new file mode 100644
index 000000000..48f9fa6bd
--- /dev/null
+++ b/guest/hals/hwcomposer/common/screen_view.cpp
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+#include "guest/hals/hwcomposer/common/screen_view.h"
+
+#include "common/libs/utils/size_utils.h"
+
+namespace cvd {
+
+int ScreenView::NextBuffer() {
+ int num_buffers = this->num_buffers();
+ last_buffer_ = num_buffers > 0 ? (last_buffer_ + 1) % num_buffers : -1;
+ return last_buffer_;
+}
+
+size_t ScreenView::buffer_size() const {
+ return line_length() * y_res() + 4 /* swiftshader padding */;
+}
+
+size_t ScreenView::line_length() const {
+ return cvd::AlignToPowerOf2(x_res() * bytes_per_pixel(), 4);
+}
+
+int ScreenView::bytes_per_pixel() const { return 4; }
+} // namespace cvd
diff --git a/guest/hals/hwcomposer/common/screen_view.h b/guest/hals/hwcomposer/common/screen_view.h
new file mode 100644
index 000000000..b985f8ffb
--- /dev/null
+++ b/guest/hals/hwcomposer/common/screen_view.h
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <stdint.h>
+#include <sys/time.h>
+
+namespace cvd {
+
+struct CompositionStats {
+ uint32_t num_prepare_calls;
+ uint16_t num_layers;
+ uint16_t num_hwcomposited_layers;
+ timespec last_vsync;
+ timespec prepare_start;
+ timespec prepare_end;
+ timespec set_start;
+ timespec set_end;
+};
+
+class ScreenView {
+ public:
+ ScreenView() = default;
+ ScreenView(const ScreenView&) = delete;
+ virtual ~ScreenView() = default;
+
+ ScreenView& operator=(const ScreenView&) = delete;
+
+ virtual void Broadcast(int buffer_id,
+ const CompositionStats* stats = nullptr) = 0;
+ virtual int NextBuffer();
+ virtual void* GetBuffer(int buffer_id) = 0;
+
+ virtual int32_t x_res() const = 0;
+ virtual int32_t y_res() const = 0;
+ virtual int32_t dpi() const = 0;
+ virtual int32_t refresh_rate() const = 0;
+
+ size_t buffer_size() const;
+ size_t line_length() const;
+ int bytes_per_pixel() const;
+
+ virtual int num_buffers() const = 0;
+
+ private:
+ int last_buffer_ = 0;
+};
+} // namespace cvd \ No newline at end of file
diff --git a/guest/hals/hwcomposer/common/stats_keeper.cpp b/guest/hals/hwcomposer/common/stats_keeper.cpp
new file mode 100644
index 000000000..9e0d0d2f8
--- /dev/null
+++ b/guest/hals/hwcomposer/common/stats_keeper.cpp
@@ -0,0 +1,260 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "guest/hals/hwcomposer/common/stats_keeper.h"
+
+#include <inttypes.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <algorithm>
+#include <mutex>
+#include <utility>
+#include <vector>
+
+#include <log/log.h>
+
+#include "guest/hals/hwcomposer/common/geometry_utils.h"
+
+using cvd::time::Microseconds;
+using cvd::time::MonotonicTimePoint;
+using cvd::time::Nanoseconds;
+using cvd::time::Seconds;
+using cvd::time::TimeDifference;
+
+namespace cvd {
+
+namespace {
+
+// These functions assume that there is at least one suitable element inside
+// the multiset.
+template <class T>
+void MultisetDeleteOne(std::multiset<T>* mset, const T& key) {
+ mset->erase(mset->find(key));
+}
+template <class T>
+const T& MultisetMin(const std::multiset<T>& mset) {
+ return *mset.begin();
+}
+template <class T>
+const T& MultisetMax(const std::multiset<T>& mset) {
+ return *mset.rbegin();
+}
+
+void TimeDifferenceToTimeSpec(const TimeDifference& td, timespec* ts) {
+ ts->tv_sec = td.seconds();
+ ts->tv_nsec = td.subseconds_in_ns();
+}
+
+} // namespace
+
+void StatsKeeper::GetLastCompositionStats(CompositionStats* stats_p) {
+ if (stats_p) {
+ TimeDifferenceToTimeSpec(last_composition_stats_.prepare_start.SinceEpoch(),
+ &stats_p->prepare_start);
+ TimeDifferenceToTimeSpec(last_composition_stats_.prepare_end.SinceEpoch(),
+ &stats_p->prepare_end);
+ TimeDifferenceToTimeSpec(last_composition_stats_.set_start.SinceEpoch(),
+ &stats_p->set_start);
+ TimeDifferenceToTimeSpec(last_composition_stats_.set_end.SinceEpoch(),
+ &stats_p->set_end);
+ TimeDifferenceToTimeSpec(last_composition_stats_.last_vsync.SinceEpoch(),
+ &stats_p->last_vsync);
+
+ stats_p->num_prepare_calls = last_composition_stats_.num_prepare_calls;
+ stats_p->num_layers = last_composition_stats_.num_layers;
+ stats_p->num_hwcomposited_layers = last_composition_stats_.num_hwc_layers;
+ }
+}
+
+StatsKeeper::StatsKeeper(TimeDifference timespan, int64_t vsync_base,
+ int32_t vsync_period)
+ : period_length_(timespan, 1),
+ vsync_base_(vsync_base),
+ vsync_period_(vsync_period),
+ num_layers_(0),
+ num_hwcomposited_layers_(0),
+ num_prepare_calls_(0),
+ num_set_calls_(0),
+ prepare_call_total_time_(0),
+ set_call_total_time_(0),
+ total_layers_area(0),
+ total_invisible_area(0) {
+ last_composition_stats_.num_prepare_calls = 0;
+}
+
+StatsKeeper::~StatsKeeper() {}
+
+void StatsKeeper::RecordPrepareStart(int num_layers) {
+ last_composition_stats_.num_layers = num_layers;
+ last_composition_stats_.num_prepare_calls++;
+ num_prepare_calls_++;
+ last_composition_stats_.prepare_start = MonotonicTimePoint::Now();
+ // Calculate the (expected) time of last VSYNC event. We can only make a guess
+ // about it because the vsync thread could run late or surfaceflinger could
+ // run late and call prepare from a previous vsync cycle.
+ int64_t last_vsync =
+ Nanoseconds(last_composition_stats_.set_start.SinceEpoch()).count();
+ last_vsync -= (last_vsync - vsync_base_) % vsync_period_;
+ last_composition_stats_.last_vsync =
+ MonotonicTimePoint() + Nanoseconds(last_vsync);
+}
+
+void StatsKeeper::RecordPrepareEnd(int num_hwcomposited_layers) {
+ last_composition_stats_.prepare_end = MonotonicTimePoint::Now();
+ last_composition_stats_.num_hwc_layers = num_hwcomposited_layers;
+}
+
+void StatsKeeper::RecordSetStart() {
+ last_composition_stats_.set_start = MonotonicTimePoint::Now();
+}
+
+void StatsKeeper::RecordSetEnd() {
+ last_composition_stats_.set_end = MonotonicTimePoint::Now();
+ std::lock_guard lock(mutex_);
+ num_set_calls_++;
+ while (!raw_composition_data_.empty() &&
+ period_length_ < last_composition_stats_.set_end -
+ raw_composition_data_.front().time_point()) {
+ const CompositionData& front = raw_composition_data_.front();
+
+ num_prepare_calls_ -= front.num_prepare_calls();
+ --num_set_calls_;
+ num_layers_ -= front.num_layers();
+ num_hwcomposited_layers_ -= front.num_hwcomposited_layers();
+ prepare_call_total_time_ =
+ Nanoseconds(prepare_call_total_time_ - front.prepare_time());
+ set_call_total_time_ =
+ Nanoseconds(set_call_total_time_ - front.set_calls_time());
+
+ MultisetDeleteOne(&prepare_calls_per_set_calls_, front.num_prepare_calls());
+ MultisetDeleteOne(&layers_per_compositions_, front.num_layers());
+ MultisetDeleteOne(&prepare_call_times_, front.prepare_time());
+ MultisetDeleteOne(&set_call_times_, front.set_calls_time());
+ if (front.num_hwcomposited_layers() != 0) {
+ MultisetDeleteOne(
+ &set_call_times_per_hwcomposited_layer_ns_,
+ front.set_calls_time().count() / front.num_hwcomposited_layers());
+ }
+
+ raw_composition_data_.pop_front();
+ }
+ Nanoseconds last_prepare_call_time_(last_composition_stats_.prepare_end -
+ last_composition_stats_.prepare_start);
+ Nanoseconds last_set_call_total_time_(last_composition_stats_.set_end -
+ last_composition_stats_.set_start);
+ raw_composition_data_.push_back(
+ CompositionData(last_composition_stats_.set_end,
+ last_composition_stats_.num_prepare_calls,
+ last_composition_stats_.num_layers,
+ last_composition_stats_.num_hwc_layers,
+ last_prepare_call_time_, last_set_call_total_time_));
+
+ // There may be several calls to prepare before a call to set, but the only
+ // valid call is the last one, so we need to compute these here:
+ num_layers_ += last_composition_stats_.num_layers;
+ num_hwcomposited_layers_ += last_composition_stats_.num_hwc_layers;
+ prepare_call_total_time_ =
+ Nanoseconds(prepare_call_total_time_ + last_prepare_call_time_);
+ set_call_total_time_ =
+ Nanoseconds(set_call_total_time_ + last_set_call_total_time_);
+ prepare_calls_per_set_calls_.insert(
+ last_composition_stats_.num_prepare_calls);
+ layers_per_compositions_.insert(last_composition_stats_.num_layers);
+ prepare_call_times_.insert(last_prepare_call_time_);
+ set_call_times_.insert(last_set_call_total_time_);
+ if (last_composition_stats_.num_hwc_layers != 0) {
+ set_call_times_per_hwcomposited_layer_ns_.insert(
+ last_set_call_total_time_.count() /
+ last_composition_stats_.num_hwc_layers);
+ }
+
+ // Reset the counter
+ last_composition_stats_.num_prepare_calls = 0;
+}
+
+void StatsKeeper::SynchronizedDump(char* buffer, int buffer_size) const {
+ std::lock_guard lock(mutex_);
+ int chars_written = 0;
+// Make sure there is enough space to write the next line
+#define bprintf(...) \
+ (chars_written += (chars_written < buffer_size) \
+ ? (snprintf(&buffer[chars_written], \
+ buffer_size - chars_written, __VA_ARGS__)) \
+ : 0)
+
+ bprintf("HWComposer stats from the %" PRId64
+ " seconds just before the last call to "
+ "set() (which happended %" PRId64 " seconds ago):\n",
+ Seconds(period_length_).count(),
+ Seconds(MonotonicTimePoint::Now() - last_composition_stats_.set_end)
+ .count());
+ bprintf(" Layer count: %d\n", num_layers_);
+
+ if (num_layers_ == 0 || num_prepare_calls_ == 0 || num_set_calls_ == 0) {
+ return;
+ }
+
+ bprintf(" Layers composited by hwcomposer: %d (%d%%)\n",
+ num_hwcomposited_layers_,
+ 100 * num_hwcomposited_layers_ / num_layers_);
+ bprintf(" Number of calls to prepare(): %d\n", num_prepare_calls_);
+ bprintf(" Number of calls to set(): %d\n", num_set_calls_);
+ if (num_set_calls_ > 0) {
+ bprintf(
+ " Maximum number of calls to prepare() before a single call to set(): "
+ "%d\n",
+ MultisetMax(prepare_calls_per_set_calls_));
+ }
+ bprintf(" Time spent on prepare() (in microseconds):\n max: %" PRId64
+ "\n "
+ "average: %" PRId64 "\n min: %" PRId64 "\n total: %" PRId64
+ "\n",
+ Microseconds(MultisetMax(prepare_call_times_)).count(),
+ Microseconds(prepare_call_total_time_).count() / num_prepare_calls_,
+ Microseconds(MultisetMin(prepare_call_times_)).count(),
+ Microseconds(prepare_call_total_time_).count());
+ bprintf(" Time spent on set() (in microseconds):\n max: %" PRId64
+ "\n average: "
+ "%" PRId64 "\n min: %" PRId64 "\n total: %" PRId64 "\n",
+ Microseconds(MultisetMax(set_call_times_)).count(),
+ Microseconds(set_call_total_time_).count() / num_set_calls_,
+ Microseconds(MultisetMin(set_call_times_)).count(),
+ Microseconds(set_call_total_time_).count());
+ if (num_hwcomposited_layers_ > 0) {
+ bprintf(
+ " Per layer compostition time:\n max: %" PRId64
+ "\n average: %" PRId64
+ "\n "
+ "min: %" PRId64 "\n",
+ Microseconds(MultisetMax(set_call_times_per_hwcomposited_layer_ns_))
+ .count(),
+ Microseconds(set_call_total_time_).count() / num_hwcomposited_layers_,
+ Microseconds(MultisetMin(set_call_times_per_hwcomposited_layer_ns_))
+ .count());
+ }
+ bprintf("Statistics from last 100 compositions:\n");
+ bprintf(" Total area: %" PRId64 " square pixels\n", total_layers_area);
+ if (total_layers_area != 0) {
+ bprintf(
+ " Total invisible area: %" PRId64 " square pixels, %" PRId64 "%%\n",
+ total_invisible_area, 100 * total_invisible_area / total_layers_area);
+ }
+#undef bprintf
+}
+
+} // namespace cvd
diff --git a/guest/hals/hwcomposer/common/stats_keeper.h b/guest/hals/hwcomposer/common/stats_keeper.h
new file mode 100644
index 000000000..3a123f709
--- /dev/null
+++ b/guest/hals/hwcomposer/common/stats_keeper.h
@@ -0,0 +1,224 @@
+#pragma once
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <deque>
+#include <mutex>
+#include <set>
+
+#include <android-base/thread_annotations.h>
+
+#include "common/libs/time/monotonic_time.h"
+
+#include "guest/hals/hwcomposer/common/base_composer.h"
+#include "guest/hals/hwcomposer/common/hwcomposer.h"
+
+namespace cvd {
+
+class CompositionData {
+ public:
+ CompositionData(cvd::time::MonotonicTimePoint time_point, int num_prepares,
+ int num_layers, int num_hwcomposited_layers,
+ cvd::time::Nanoseconds prepare_time,
+ cvd::time::Nanoseconds set_calls_time)
+ : time_point_(time_point),
+ num_prepare_calls_(num_prepares),
+ num_layers_(num_layers),
+ num_hwcomposited_layers_(num_hwcomposited_layers),
+ prepare_time_(prepare_time),
+ set_calls_time_(set_calls_time) {}
+
+ cvd::time::MonotonicTimePoint time_point() const { return time_point_; }
+
+ int num_prepare_calls() const { return num_prepare_calls_; }
+
+ int num_layers() const { return num_layers_; }
+
+ int num_hwcomposited_layers() const { return num_hwcomposited_layers_; }
+
+ cvd::time::Nanoseconds prepare_time() const { return prepare_time_; }
+
+ cvd::time::Nanoseconds set_calls_time() const { return set_calls_time_; }
+
+ private:
+ cvd::time::MonotonicTimePoint time_point_;
+ int num_prepare_calls_;
+ int num_layers_;
+ int num_hwcomposited_layers_;
+ cvd::time::Nanoseconds prepare_time_;
+ cvd::time::Nanoseconds set_calls_time_;
+};
+
+struct HWCCompositionStats {
+ cvd::time::MonotonicTimePoint prepare_start;
+ cvd::time::MonotonicTimePoint prepare_end;
+ cvd::time::MonotonicTimePoint set_start;
+ cvd::time::MonotonicTimePoint set_end;
+ cvd::time::MonotonicTimePoint last_vsync;
+ // There may be more than one call to prepare, the timestamps are with regards
+ // to the last one (the one that precedes the set call)
+ int num_prepare_calls;
+ int num_layers;
+ // The number of layers composed by the hwcomposer
+ int num_hwc_layers;
+};
+
+class StatsKeeper {
+ public:
+ // The timespan parameter indicates for how long we keep stats about the past
+ // compositions.
+ StatsKeeper(cvd::time::TimeDifference timespan, int64_t vsync_base,
+ int32_t vsync_period);
+ StatsKeeper();
+ ~StatsKeeper();
+
+ // Record the time at which a call to prepare was made, takes the number of
+ // layers received (excluding the framebuffer) as a parameter.
+ void RecordPrepareStart(int num_layers);
+ // Record the time at which a call to prepare (was about to) returned, takes
+ // the number of layers marked for hardware composition as a parameter.
+ void RecordPrepareEnd(int num_hwcomposited_layers);
+ void RecordSetStart();
+ void RecordSetEnd() EXCLUDES(mutex_);
+
+ void GetLastCompositionStats(CompositionStats* stats_p);
+
+ // Calls to this function are synchronized with calls to 'RecordSetEnd' with a
+ // mutex. The other Record* functions do not need such synchronization because
+ // they access last_* variables only, which are not read by 'Dump'.
+ void SynchronizedDump(char* buffer, int buffer_size) const EXCLUDES(mutex_);
+
+ private:
+ cvd::time::TimeDifference period_length_;
+
+ // Base and period of the VSYNC signal, allows to accurately calculate the
+ // time of the last vsync broadcast.
+ int64_t vsync_base_;
+ int32_t vsync_period_;
+ // Data collected about ongoing composition. These variables are not accessed
+ // from Dump(), so they don't need to be guarded by a mutex.
+ HWCCompositionStats last_composition_stats_;
+
+ // Aggregated performance data collected from past compositions. These
+ // variables are modified when a composition is completed and when old
+ // compositions need to be discarded in RecordSetEnd(), and is accessed from
+ // Dump(). Non-aggregated data is kept in the raw_composition_data_ deque to
+ // be able to discard old values from the aggregated data.
+ int num_layers_ GUARDED_BY(mutex_);
+ int num_hwcomposited_layers_ GUARDED_BY(mutex_);
+ int num_prepare_calls_ GUARDED_BY(mutex_);
+ int num_set_calls_ GUARDED_BY(mutex_);
+ cvd::time::Nanoseconds prepare_call_total_time_ GUARDED_BY(mutex_);
+ cvd::time::Nanoseconds set_call_total_time_ GUARDED_BY(mutex_);
+ // These are kept in multisets to be able to calculate mins and maxs of
+ // changing sets of (not necessarily different) values.
+ std::multiset<int> prepare_calls_per_set_calls_ GUARDED_BY(mutex_);
+ std::multiset<int> layers_per_compositions_ GUARDED_BY(mutex_);
+ std::multiset<cvd::time::Nanoseconds> prepare_call_times_ GUARDED_BY(mutex_);
+ std::multiset<cvd::time::Nanoseconds> set_call_times_ GUARDED_BY(mutex_);
+ std::multiset<int64_t> set_call_times_per_hwcomposited_layer_ns_
+ GUARDED_BY(mutex_);
+
+ // Time-ordered list of compositions, used to update the global aggregated
+ // performance data when old compositions fall out of the period of interest.
+ std::deque<CompositionData> raw_composition_data_ GUARDED_BY(mutex_);
+
+ // TODO(jemoreira): Add min/max/average composition times per layer area units
+
+ std::deque<std::pair<int64_t, int64_t> > composition_areas GUARDED_BY(mutex_);
+ int64_t total_layers_area GUARDED_BY(mutex_);
+ int64_t total_invisible_area GUARDED_BY(mutex_);
+
+ // Controls access to data from past compositions.
+ mutable std::mutex mutex_;
+};
+
+class WrappedScreenView : public ScreenView {
+ public:
+ WrappedScreenView(std::unique_ptr<ScreenView> screen_view,
+ std::function<void(CompositionStats*)> stats_getter)
+ : screen_view_(std::move(screen_view)), stats_getter_(stats_getter) {}
+ virtual ~WrappedScreenView() = default;
+
+ void Broadcast(int buffer_id, const CompositionStats*) override {
+ // The composer object in stats_keeper produces null stats, use the ones
+ // provided by the stats_keeper instead.
+ CompositionStats stats;
+ stats_getter_(&stats);
+ return screen_view_->Broadcast(buffer_id, &stats);
+ }
+
+ void* GetBuffer(int buffer_id) override {
+ return screen_view_->GetBuffer(buffer_id);
+ }
+
+ int32_t x_res() const override { return screen_view_->x_res(); }
+
+ int32_t y_res() const override { return screen_view_->y_res(); }
+
+ int32_t dpi() const override { return screen_view_->dpi(); }
+
+ int32_t refresh_rate() const override { return screen_view_->refresh_rate(); }
+
+ int num_buffers() const override { return screen_view_->num_buffers(); }
+
+ private:
+ std::unique_ptr<ScreenView> screen_view_;
+ std::function<void(CompositionStats*)> stats_getter_;
+};
+
+template <class Composer>
+class StatsKeepingComposer : public BaseComposer {
+ public:
+ // Keep stats from the last 10 seconds.
+ StatsKeepingComposer(int64_t vsync_base_timestamp,
+ std::unique_ptr<ScreenView> screen_view)
+ : composer_(std::unique_ptr<ScreenView>(
+ new WrappedScreenView(std::move(screen_view),
+ [this](CompositionStats* stats) {
+ FinalizeStatsAndGet(stats);
+ }))),
+ stats_keeper_(cvd::time::TimeDifference(cvd::time::Seconds(10), 1),
+ vsync_base_timestamp, 1e9 / composer_.refresh_rate()) {}
+ virtual ~StatsKeepingComposer() = default;
+
+ int PrepareLayers(size_t num_layers, hwc_layer_1_t* layers) override {
+ stats_keeper_.RecordPrepareStart(num_layers);
+ int num_hwc_layers = composer_.PrepareLayers(num_layers, layers);
+ stats_keeper_.RecordPrepareEnd(num_hwc_layers);
+ return num_hwc_layers;
+ }
+
+ int SetLayers(size_t num_layers, hwc_layer_1_t* layers) override {
+ stats_keeper_.RecordSetStart();
+ return composer_.SetLayers(num_layers, layers);
+ }
+
+ void Dump(char* buff, int buff_len) override {
+ stats_keeper_.SynchronizedDump(buff, buff_len);
+ }
+
+ void FinalizeStatsAndGet(CompositionStats* stats) {
+ stats_keeper_.RecordSetEnd();
+ stats_keeper_.GetLastCompositionStats(stats);
+ }
+
+ private:
+ Composer composer_;
+ StatsKeeper stats_keeper_;
+};
+
+} // namespace cvd
diff --git a/guest/hals/hwcomposer/cutf_cvm/Android.bp b/guest/hals/hwcomposer/cutf_cvm/Android.bp
new file mode 100644
index 000000000..d62207728
--- /dev/null
+++ b/guest/hals/hwcomposer/cutf_cvm/Android.bp
@@ -0,0 +1,100 @@
+// 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_library_shared {
+ name: "hwcomposer.cutf_cvm_ashmem",
+ relative_install_path: "hw",
+ defaults: ["cuttlefish_guest_only"],
+ vendor: true,
+ srcs: [
+ "hwcomposer.cpp",
+ "vsocket_screen_view.cpp",
+ ],
+ include_dirs: [
+ "device/google/cuttlefish",
+ ],
+ export_include_dirs: ["."],
+ static_libs: [
+ "hwcomposer_common",
+ "libyuv_static",
+ ],
+ shared_libs: [
+ "android.hardware.graphics.mapper@4.0",
+ "libbase",
+ "libcutils",
+ "libcuttlefish_device_config",
+ "libcuttlefish_utils",
+ "libcuttlefish_fs",
+ "libdrm",
+ "libgralloctypes",
+ "libhardware",
+ "libhidlbase",
+ "libjpeg",
+ "liblog",
+ "libsync",
+ "libutils",
+ ],
+}
+
+cc_library_shared {
+ name: "hwcomposer.cutf_hwc2",
+ relative_install_path: "hw",
+ defaults: ["cuttlefish_guest_only"],
+ vendor: true,
+
+ clang: true,
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+ cppflags: [
+ "-Wextra",
+ "-Wunused",
+ "-Wunreachable-code",
+
+ // Disabling warning specific to hwc2on1adapter code
+ "-Wno-sign-compare",
+ ],
+
+ srcs: [
+ "HWC2.cpp",
+ "MiniFence.cpp",
+ "vsocket_screen_view.cpp",
+ ],
+
+ include_dirs: [
+ "device/google/cuttlefish",
+ ],
+
+ export_include_dirs: ["."],
+
+ static_libs: [
+ "hwcomposer_common",
+ "libyuv_static",
+ ],
+
+ shared_libs: [
+ "android.hardware.graphics.mapper@4.0",
+ "libcutils",
+ "libcuttlefish_device_config",
+ "libcuttlefish_utils",
+ "libcuttlefish_fs",
+ "libgralloctypes",
+ "libhardware",
+ "libhidlbase",
+ "liblog",
+ "libutils",
+ ],
+}
diff --git a/guest/hals/hwcomposer/cutf_cvm/HWC2.cpp b/guest/hals/hwcomposer/cutf_cvm/HWC2.cpp
new file mode 100644
index 000000000..e366b2f2b
--- /dev/null
+++ b/guest/hals/hwcomposer/cutf_cvm/HWC2.cpp
@@ -0,0 +1,2845 @@
+/*
+ * 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 "HWC2.h"
+
+//#define LOG_NDEBUG 0
+
+#undef LOG_TAG
+#define LOG_TAG "CfHWC2"
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+
+#include <inttypes.h>
+
+#include <chrono>
+#include <cstdlib>
+#include <sstream>
+
+#include <hardware/hwcomposer.h>
+#include <log/log.h>
+#include <utils/Trace.h>
+
+#include "guest/hals/hwcomposer/common/hwcomposer.h"
+#include "guest/hals/hwcomposer/cutf_cvm/vsocket_screen_view.h"
+
+using namespace std::chrono_literals;
+
+static uint8_t getMinorVersion(struct hwc_composer_device_1* device)
+{
+ auto version = device->common.version & HARDWARE_API_VERSION_2_MAJ_MIN_MASK;
+ return (version >> 16) & 0xF;
+}
+
+template <typename PFN, typename T>
+static hwc2_function_pointer_t asFP(T function)
+{
+ static_assert(std::is_same<PFN, T>::value, "Incompatible function pointer");
+ return reinterpret_cast<hwc2_function_pointer_t>(function);
+}
+
+using namespace HWC2;
+
+static constexpr Attribute ColorMode = static_cast<Attribute>(6);
+
+namespace android {
+
+class CfHWC2::Callbacks : public hwc_procs_t {
+ public:
+ explicit Callbacks(CfHWC2& adapter) : mAdapter(adapter) {
+ invalidate = &invalidateHook;
+ vsync = &vsyncHook;
+ hotplug = &hotplugHook;
+ }
+
+ static void invalidateHook(const hwc_procs_t* procs) {
+ auto callbacks = static_cast<const Callbacks*>(procs);
+ callbacks->mAdapter.hwc1Invalidate();
+ }
+
+ static void vsyncHook(const hwc_procs_t* procs, int display,
+ int64_t timestamp) {
+ auto callbacks = static_cast<const Callbacks*>(procs);
+ callbacks->mAdapter.hwc1Vsync(display, timestamp);
+ }
+
+ static void hotplugHook(const hwc_procs_t* procs, int display,
+ int connected) {
+ auto callbacks = static_cast<const Callbacks*>(procs);
+ callbacks->mAdapter.hwc1Hotplug(display, connected);
+ }
+
+ private:
+ CfHWC2& mAdapter;
+};
+
+static int closeHook(hw_device_t* /*device*/)
+{
+ // Do nothing, since the real work is done in the class destructor, but we
+ // need to provide a valid function pointer for hwc2_close to call
+ return 0;
+}
+
+CfHWC2::CfHWC2(hwc_composer_device_1_t* hwc1Device)
+ : mDumpString(),
+ mHwc1Device(hwc1Device),
+ mHwc1MinorVersion(getMinorVersion(hwc1Device)),
+ mHwc1SupportsVirtualDisplays(false),
+ mHwc1SupportsBackgroundColor(false),
+ mHwc1Callbacks(std::make_unique<Callbacks>(*this)),
+ mCapabilities(),
+ mLayers(),
+ mHwc1VirtualDisplay(),
+ mStateMutex(),
+ mCallbacks(),
+ mHasPendingInvalidate(false),
+ mPendingVsyncs(),
+ mPendingHotplugs(),
+ mDisplays(),
+ mHwc1DisplayMap()
+{
+ common.tag = HARDWARE_DEVICE_TAG;
+ common.version = HWC_DEVICE_API_VERSION_2_0;
+ common.close = closeHook;
+ getCapabilities = getCapabilitiesHook;
+ getFunction = getFunctionHook;
+ populateCapabilities();
+ populatePrimary();
+ mHwc1Device->registerProcs(mHwc1Device,
+ static_cast<const hwc_procs_t*>(mHwc1Callbacks.get()));
+}
+
+CfHWC2::~CfHWC2() {
+ hwc_close_1(mHwc1Device);
+}
+
+void CfHWC2::doGetCapabilities(uint32_t* outCount,
+ int32_t* outCapabilities) {
+ if (outCapabilities == nullptr) {
+ *outCount = mCapabilities.size();
+ return;
+ }
+
+ auto capabilityIter = mCapabilities.cbegin();
+ for (size_t written = 0; written < *outCount; ++written) {
+ if (capabilityIter == mCapabilities.cend()) {
+ return;
+ }
+ outCapabilities[written] = static_cast<int32_t>(*capabilityIter);
+ ++capabilityIter;
+ }
+}
+
+hwc2_function_pointer_t CfHWC2::doGetFunction(
+ FunctionDescriptor descriptor) {
+ switch (descriptor) {
+ // Device functions
+ case FunctionDescriptor::CreateVirtualDisplay:
+ return asFP<HWC2_PFN_CREATE_VIRTUAL_DISPLAY>(
+ createVirtualDisplayHook);
+ case FunctionDescriptor::DestroyVirtualDisplay:
+ return asFP<HWC2_PFN_DESTROY_VIRTUAL_DISPLAY>(
+ destroyVirtualDisplayHook);
+ case FunctionDescriptor::Dump:
+ return asFP<HWC2_PFN_DUMP>(dumpHook);
+ case FunctionDescriptor::GetMaxVirtualDisplayCount:
+ return asFP<HWC2_PFN_GET_MAX_VIRTUAL_DISPLAY_COUNT>(
+ getMaxVirtualDisplayCountHook);
+ case FunctionDescriptor::RegisterCallback:
+ return asFP<HWC2_PFN_REGISTER_CALLBACK>(registerCallbackHook);
+
+ // Display functions
+ case FunctionDescriptor::AcceptDisplayChanges:
+ return asFP<HWC2_PFN_ACCEPT_DISPLAY_CHANGES>(
+ displayHook<decltype(&Display::acceptChanges),
+ &Display::acceptChanges>);
+ case FunctionDescriptor::CreateLayer:
+ return asFP<HWC2_PFN_CREATE_LAYER>(
+ displayHook<decltype(&Display::createLayer),
+ &Display::createLayer, hwc2_layer_t*>);
+ case FunctionDescriptor::DestroyLayer:
+ return asFP<HWC2_PFN_DESTROY_LAYER>(
+ displayHook<decltype(&Display::destroyLayer),
+ &Display::destroyLayer, hwc2_layer_t>);
+ case FunctionDescriptor::GetActiveConfig:
+ return asFP<HWC2_PFN_GET_ACTIVE_CONFIG>(
+ displayHook<decltype(&Display::getActiveConfig),
+ &Display::getActiveConfig, hwc2_config_t*>);
+ case FunctionDescriptor::GetChangedCompositionTypes:
+ return asFP<HWC2_PFN_GET_CHANGED_COMPOSITION_TYPES>(
+ displayHook<decltype(&Display::getChangedCompositionTypes),
+ &Display::getChangedCompositionTypes, uint32_t*,
+ hwc2_layer_t*, int32_t*>);
+ case FunctionDescriptor::GetColorModes:
+ return asFP<HWC2_PFN_GET_COLOR_MODES>(
+ displayHook<decltype(&Display::getColorModes),
+ &Display::getColorModes, uint32_t*, int32_t*>);
+ case FunctionDescriptor::GetDisplayAttribute:
+ return asFP<HWC2_PFN_GET_DISPLAY_ATTRIBUTE>(
+ getDisplayAttributeHook);
+ case FunctionDescriptor::GetDisplayConfigs:
+ return asFP<HWC2_PFN_GET_DISPLAY_CONFIGS>(
+ displayHook<decltype(&Display::getConfigs),
+ &Display::getConfigs, uint32_t*, hwc2_config_t*>);
+ case FunctionDescriptor::GetDisplayName:
+ return asFP<HWC2_PFN_GET_DISPLAY_NAME>(
+ displayHook<decltype(&Display::getName),
+ &Display::getName, uint32_t*, char*>);
+ case FunctionDescriptor::GetDisplayRequests:
+ return asFP<HWC2_PFN_GET_DISPLAY_REQUESTS>(
+ displayHook<decltype(&Display::getRequests),
+ &Display::getRequests, int32_t*, uint32_t*, hwc2_layer_t*,
+ int32_t*>);
+ case FunctionDescriptor::GetDisplayType:
+ return asFP<HWC2_PFN_GET_DISPLAY_TYPE>(
+ displayHook<decltype(&Display::getType),
+ &Display::getType, int32_t*>);
+ case FunctionDescriptor::GetDozeSupport:
+ return asFP<HWC2_PFN_GET_DOZE_SUPPORT>(
+ displayHook<decltype(&Display::getDozeSupport),
+ &Display::getDozeSupport, int32_t*>);
+ case FunctionDescriptor::GetHdrCapabilities:
+ return asFP<HWC2_PFN_GET_HDR_CAPABILITIES>(
+ displayHook<decltype(&Display::getHdrCapabilities),
+ &Display::getHdrCapabilities, uint32_t*, int32_t*, float*,
+ float*, float*>);
+ case FunctionDescriptor::GetReleaseFences:
+ return asFP<HWC2_PFN_GET_RELEASE_FENCES>(
+ displayHook<decltype(&Display::getReleaseFences),
+ &Display::getReleaseFences, uint32_t*, hwc2_layer_t*,
+ int32_t*>);
+ case FunctionDescriptor::PresentDisplay:
+ return asFP<HWC2_PFN_PRESENT_DISPLAY>(
+ displayHook<decltype(&Display::present),
+ &Display::present, int32_t*>);
+ case FunctionDescriptor::SetActiveConfig:
+ return asFP<HWC2_PFN_SET_ACTIVE_CONFIG>(
+ displayHook<decltype(&Display::setActiveConfig),
+ &Display::setActiveConfig, hwc2_config_t>);
+ case FunctionDescriptor::SetClientTarget:
+ return asFP<HWC2_PFN_SET_CLIENT_TARGET>(
+ displayHook<decltype(&Display::setClientTarget),
+ &Display::setClientTarget, buffer_handle_t, int32_t,
+ int32_t, hwc_region_t>);
+ case FunctionDescriptor::SetColorMode:
+ return asFP<HWC2_PFN_SET_COLOR_MODE>(setColorModeHook);
+ case FunctionDescriptor::SetColorTransform:
+ return asFP<HWC2_PFN_SET_COLOR_TRANSFORM>(setColorTransformHook);
+ case FunctionDescriptor::SetOutputBuffer:
+ return asFP<HWC2_PFN_SET_OUTPUT_BUFFER>(
+ displayHook<decltype(&Display::setOutputBuffer),
+ &Display::setOutputBuffer, buffer_handle_t, int32_t>);
+ case FunctionDescriptor::SetPowerMode:
+ return asFP<HWC2_PFN_SET_POWER_MODE>(setPowerModeHook);
+ case FunctionDescriptor::SetVsyncEnabled:
+ return asFP<HWC2_PFN_SET_VSYNC_ENABLED>(setVsyncEnabledHook);
+ case FunctionDescriptor::ValidateDisplay:
+ return asFP<HWC2_PFN_VALIDATE_DISPLAY>(
+ displayHook<decltype(&Display::validate),
+ &Display::validate, uint32_t*, uint32_t*>);
+ case FunctionDescriptor::GetClientTargetSupport:
+ return asFP<HWC2_PFN_GET_CLIENT_TARGET_SUPPORT>(
+ displayHook<decltype(&Display::getClientTargetSupport),
+ &Display::getClientTargetSupport, uint32_t, uint32_t,
+ int32_t, int32_t>);
+
+ // 2.3 required functions
+ case FunctionDescriptor::GetDisplayIdentificationData:
+ return asFP<HWC2_PFN_GET_DISPLAY_IDENTIFICATION_DATA>(
+ displayHook<decltype(&Display::getDisplayIdentificationData),
+ &Display::getDisplayIdentificationData, uint8_t*, uint32_t*, uint8_t*>);
+ case FunctionDescriptor::GetDisplayCapabilities:
+ return asFP<HWC2_PFN_GET_DISPLAY_CAPABILITIES>(
+ displayHook<decltype(&Display::getDisplayCapabilities),
+ &Display::getDisplayCapabilities, uint32_t*, uint32_t*>);
+ case FunctionDescriptor::GetDisplayBrightnessSupport:
+ return asFP<HWC2_PFN_GET_DISPLAY_BRIGHTNESS_SUPPORT>(
+ displayHook<decltype(&Display::getDisplayBrightnessSupport),
+ &Display::getDisplayBrightnessSupport, bool*>);
+ case FunctionDescriptor::SetDisplayBrightness:
+ return asFP<HWC2_PFN_SET_DISPLAY_BRIGHTNESS>(
+ displayHook<decltype(&Display::setDisplayBrightness),
+ &Display::setDisplayBrightness, float>);
+
+ // Layer functions
+ case FunctionDescriptor::SetCursorPosition:
+ return asFP<HWC2_PFN_SET_CURSOR_POSITION>(
+ layerHook<decltype(&Layer::setCursorPosition),
+ &Layer::setCursorPosition, int32_t, int32_t>);
+ case FunctionDescriptor::SetLayerBuffer:
+ return asFP<HWC2_PFN_SET_LAYER_BUFFER>(
+ layerHook<decltype(&Layer::setBuffer), &Layer::setBuffer,
+ buffer_handle_t, int32_t>);
+ case FunctionDescriptor::SetLayerSurfaceDamage:
+ return asFP<HWC2_PFN_SET_LAYER_SURFACE_DAMAGE>(
+ layerHook<decltype(&Layer::setSurfaceDamage),
+ &Layer::setSurfaceDamage, hwc_region_t>);
+
+ // Layer state functions
+ case FunctionDescriptor::SetLayerBlendMode:
+ return asFP<HWC2_PFN_SET_LAYER_BLEND_MODE>(
+ setLayerBlendModeHook);
+ case FunctionDescriptor::SetLayerColor:
+ return asFP<HWC2_PFN_SET_LAYER_COLOR>(
+ layerHook<decltype(&Layer::setColor), &Layer::setColor,
+ hwc_color_t>);
+ case FunctionDescriptor::SetLayerCompositionType:
+ return asFP<HWC2_PFN_SET_LAYER_COMPOSITION_TYPE>(
+ setLayerCompositionTypeHook);
+ case FunctionDescriptor::SetLayerDataspace:
+ return asFP<HWC2_PFN_SET_LAYER_DATASPACE>(setLayerDataspaceHook);
+ case FunctionDescriptor::SetLayerDisplayFrame:
+ return asFP<HWC2_PFN_SET_LAYER_DISPLAY_FRAME>(
+ layerHook<decltype(&Layer::setDisplayFrame),
+ &Layer::setDisplayFrame, hwc_rect_t>);
+ case FunctionDescriptor::SetLayerPlaneAlpha:
+ return asFP<HWC2_PFN_SET_LAYER_PLANE_ALPHA>(
+ layerHook<decltype(&Layer::setPlaneAlpha),
+ &Layer::setPlaneAlpha, float>);
+ case FunctionDescriptor::SetLayerSidebandStream:
+ return asFP<HWC2_PFN_SET_LAYER_SIDEBAND_STREAM>(
+ layerHook<decltype(&Layer::setSidebandStream),
+ &Layer::setSidebandStream, const native_handle_t*>);
+ case FunctionDescriptor::SetLayerSourceCrop:
+ return asFP<HWC2_PFN_SET_LAYER_SOURCE_CROP>(
+ layerHook<decltype(&Layer::setSourceCrop),
+ &Layer::setSourceCrop, hwc_frect_t>);
+ case FunctionDescriptor::SetLayerTransform:
+ return asFP<HWC2_PFN_SET_LAYER_TRANSFORM>(setLayerTransformHook);
+ case FunctionDescriptor::SetLayerVisibleRegion:
+ return asFP<HWC2_PFN_SET_LAYER_VISIBLE_REGION>(
+ layerHook<decltype(&Layer::setVisibleRegion),
+ &Layer::setVisibleRegion, hwc_region_t>);
+ case FunctionDescriptor::SetLayerZOrder:
+ return asFP<HWC2_PFN_SET_LAYER_Z_ORDER>(setLayerZOrderHook);
+
+ default:
+ ALOGE("doGetFunction: Unknown function descriptor: %d (%s)",
+ static_cast<int32_t>(descriptor),
+ to_string(descriptor).c_str());
+ return nullptr;
+ }
+}
+
+// Device functions
+
+Error CfHWC2::createVirtualDisplay(uint32_t width,
+ uint32_t height, hwc2_display_t* outDisplay) {
+ std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex);
+
+ if (mHwc1VirtualDisplay) {
+ // We have already allocated our only HWC1 virtual display
+ ALOGE("createVirtualDisplay: HWC1 virtual display already allocated");
+ return Error::NoResources;
+ }
+
+ mHwc1VirtualDisplay = std::make_shared<CfHWC2::Display>(*this,
+ HWC2::DisplayType::Virtual);
+ mHwc1VirtualDisplay->populateConfigs(width, height);
+ const auto displayId = mHwc1VirtualDisplay->getId();
+ mHwc1DisplayMap[HWC_DISPLAY_VIRTUAL] = displayId;
+ mHwc1VirtualDisplay->setHwc1Id(HWC_DISPLAY_VIRTUAL);
+ mDisplays.emplace(displayId, mHwc1VirtualDisplay);
+ *outDisplay = displayId;
+
+ return Error::None;
+}
+
+Error CfHWC2::destroyVirtualDisplay(hwc2_display_t displayId) {
+ std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex);
+
+ if (!mHwc1VirtualDisplay || (mHwc1VirtualDisplay->getId() != displayId)) {
+ return Error::BadDisplay;
+ }
+
+ mHwc1VirtualDisplay.reset();
+ mHwc1DisplayMap.erase(HWC_DISPLAY_VIRTUAL);
+ mDisplays.erase(displayId);
+
+ return Error::None;
+}
+
+void CfHWC2::dump(uint32_t* outSize, char* outBuffer) {
+ if (outBuffer != nullptr) {
+ auto copiedBytes = mDumpString.copy(outBuffer, *outSize);
+ *outSize = static_cast<uint32_t>(copiedBytes);
+ return;
+ }
+
+ std::stringstream output;
+
+ output << "-- CfHWC2 --\n";
+
+ output << "Adapting to a HWC 1." << static_cast<int>(mHwc1MinorVersion) <<
+ " device\n";
+
+ // Attempt to acquire the lock for 1 second, but proceed without the lock
+ // after that, so we can still get some information if we're deadlocked
+ std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex,
+ std::defer_lock);
+ lock.try_lock_for(1s);
+
+ if (mCapabilities.empty()) {
+ output << "Capabilities: None\n";
+ } else {
+ output << "Capabilities:\n";
+ for (auto capability : mCapabilities) {
+ output << " " << to_string(capability) << '\n';
+ }
+ }
+
+ output << "Displays:\n";
+ for (const auto& element : mDisplays) {
+ const auto& display = element.second;
+ output << display->dump();
+ }
+ output << '\n';
+
+ // Release the lock before calling into HWC1, and since we no longer require
+ // mutual exclusion to access mCapabilities or mDisplays
+ lock.unlock();
+
+ if (mHwc1Device->dump) {
+ output << "HWC1 dump:\n";
+ std::vector<char> hwc1Dump(4096);
+ // Call with size - 1 to preserve a null character at the end
+ mHwc1Device->dump(mHwc1Device, hwc1Dump.data(),
+ static_cast<int>(hwc1Dump.size() - 1));
+ output << hwc1Dump.data();
+ }
+
+ mDumpString = output.str();
+ *outSize = static_cast<uint32_t>(mDumpString.size());
+}
+
+uint32_t CfHWC2::getMaxVirtualDisplayCount() {
+ return mHwc1SupportsVirtualDisplays ? 1 : 0;
+}
+
+static bool isValid(Callback descriptor) {
+ switch (descriptor) {
+ case Callback::Hotplug: // Fall-through
+ case Callback::Refresh: // Fall-through
+ case Callback::Vsync: return true;
+ default: return false;
+ }
+}
+
+Error CfHWC2::registerCallback(Callback descriptor,
+ hwc2_callback_data_t callbackData, hwc2_function_pointer_t pointer) {
+ if (!isValid(descriptor)) {
+ return Error::BadParameter;
+ }
+
+ ALOGV("registerCallback(%s, %p, %p)", to_string(descriptor).c_str(),
+ callbackData, pointer);
+
+ std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex);
+
+ if (pointer != nullptr) {
+ mCallbacks[descriptor] = {callbackData, pointer};
+ } else {
+ ALOGI("unregisterCallback(%s)", to_string(descriptor).c_str());
+ mCallbacks.erase(descriptor);
+ return Error::None;
+ }
+
+ bool hasPendingInvalidate = false;
+ std::vector<hwc2_display_t> displayIds;
+ std::vector<std::pair<hwc2_display_t, int64_t>> pendingVsyncs;
+ std::vector<std::pair<hwc2_display_t, int>> pendingHotplugs;
+
+ if (descriptor == Callback::Refresh) {
+ hasPendingInvalidate = mHasPendingInvalidate;
+ if (hasPendingInvalidate) {
+ for (auto& displayPair : mDisplays) {
+ displayIds.emplace_back(displayPair.first);
+ }
+ }
+ mHasPendingInvalidate = false;
+ } else if (descriptor == Callback::Vsync) {
+ for (auto pending : mPendingVsyncs) {
+ auto hwc1DisplayId = pending.first;
+ if (mHwc1DisplayMap.count(hwc1DisplayId) == 0) {
+ ALOGE("hwc1Vsync: Couldn't find display for HWC1 id %d",
+ hwc1DisplayId);
+ continue;
+ }
+ auto displayId = mHwc1DisplayMap[hwc1DisplayId];
+ auto timestamp = pending.second;
+ pendingVsyncs.emplace_back(displayId, timestamp);
+ }
+ mPendingVsyncs.clear();
+ } else if (descriptor == Callback::Hotplug) {
+ // Hotplug the primary display
+ pendingHotplugs.emplace_back(mHwc1DisplayMap[HWC_DISPLAY_PRIMARY],
+ static_cast<int32_t>(Connection::Connected));
+
+ for (auto pending : mPendingHotplugs) {
+ auto hwc1DisplayId = pending.first;
+ if (mHwc1DisplayMap.count(hwc1DisplayId) == 0) {
+ ALOGE("hwc1Hotplug: Couldn't find display for HWC1 id %d",
+ hwc1DisplayId);
+ continue;
+ }
+ auto displayId = mHwc1DisplayMap[hwc1DisplayId];
+ auto connected = pending.second;
+ pendingHotplugs.emplace_back(displayId, connected);
+ }
+ }
+
+ // Call pending callbacks without the state lock held
+ lock.unlock();
+
+ if (hasPendingInvalidate) {
+ auto refresh = reinterpret_cast<HWC2_PFN_REFRESH>(pointer);
+ for (auto displayId : displayIds) {
+ refresh(callbackData, displayId);
+ }
+ }
+ if (!pendingVsyncs.empty()) {
+ auto vsync = reinterpret_cast<HWC2_PFN_VSYNC>(pointer);
+ for (auto& pendingVsync : pendingVsyncs) {
+ vsync(callbackData, pendingVsync.first, pendingVsync.second);
+ }
+ }
+ if (!pendingHotplugs.empty()) {
+ auto hotplug = reinterpret_cast<HWC2_PFN_HOTPLUG>(pointer);
+ for (auto& pendingHotplug : pendingHotplugs) {
+ hotplug(callbackData, pendingHotplug.first, pendingHotplug.second);
+ }
+ }
+ return Error::None;
+}
+
+// Display functions
+
+std::atomic<hwc2_display_t> CfHWC2::Display::sNextId(1);
+
+CfHWC2::Display::Display(CfHWC2& device, HWC2::DisplayType type)
+ : mId(sNextId++),
+ mDevice(device),
+ mStateMutex(),
+ mHwc1RequestedContents(nullptr),
+ mRetireFence(),
+ mChanges(),
+ mHwc1Id(-1),
+ mConfigs(),
+ mActiveConfig(nullptr),
+ mActiveColorMode(static_cast<android_color_mode_t>(-1)),
+ mName(),
+ mType(type),
+ mPowerMode(PowerMode::Off),
+ mVsyncEnabled(Vsync::Invalid),
+ mClientTarget(),
+ mOutputBuffer(),
+ mHasColorTransform(false),
+ mLayers(),
+ mHwc1LayerMap(),
+ mNumAvailableRects(0),
+ mNextAvailableRect(nullptr),
+ mGeometryChanged(false)
+ {}
+
+Error CfHWC2::Display::acceptChanges() {
+ std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+ if (!mChanges) {
+ ALOGV("[%" PRIu64 "] acceptChanges failed, not validated", mId);
+ return Error::NotValidated;
+ }
+
+ ALOGV("[%" PRIu64 "] acceptChanges", mId);
+
+ for (auto& change : mChanges->getTypeChanges()) {
+ auto layerId = change.first;
+ auto type = change.second;
+ if (mDevice.mLayers.count(layerId) == 0) {
+ // This should never happen but somehow does.
+ ALOGW("Cannot accept change for unknown layer (%" PRIu64 ")",
+ layerId);
+ continue;
+ }
+ auto layer = mDevice.mLayers[layerId];
+ layer->setCompositionType(type);
+ }
+
+ mChanges->clearTypeChanges();
+
+ return Error::None;
+}
+
+Error CfHWC2::Display::createLayer(hwc2_layer_t* outLayerId) {
+ std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+ auto layer = *mLayers.emplace(std::make_shared<Layer>(*this));
+ mDevice.mLayers.emplace(std::make_pair(layer->getId(), layer));
+ *outLayerId = layer->getId();
+ ALOGV("[%" PRIu64 "] created layer %" PRIu64, mId, *outLayerId);
+ markGeometryChanged();
+ return Error::None;
+}
+
+Error CfHWC2::Display::destroyLayer(hwc2_layer_t layerId) {
+ std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+ const auto mapLayer = mDevice.mLayers.find(layerId);
+ if (mapLayer == mDevice.mLayers.end()) {
+ ALOGV("[%" PRIu64 "] destroyLayer(%" PRIu64 ") failed: no such layer",
+ mId, layerId);
+ return Error::BadLayer;
+ }
+ const auto layer = mapLayer->second;
+ mDevice.mLayers.erase(mapLayer);
+ const auto zRange = mLayers.equal_range(layer);
+ for (auto current = zRange.first; current != zRange.second; ++current) {
+ if (**current == *layer) {
+ current = mLayers.erase(current);
+ break;
+ }
+ }
+ ALOGV("[%" PRIu64 "] destroyed layer %" PRIu64, mId, layerId);
+ markGeometryChanged();
+ return Error::None;
+}
+
+Error CfHWC2::Display::getActiveConfig(hwc2_config_t* outConfig) {
+ std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+ if (!mActiveConfig) {
+ ALOGV("[%" PRIu64 "] getActiveConfig --> %s", mId,
+ to_string(Error::BadConfig).c_str());
+ return Error::BadConfig;
+ }
+ auto configId = mActiveConfig->getId();
+ ALOGV("[%" PRIu64 "] getActiveConfig --> %u", mId, configId);
+ *outConfig = configId;
+ return Error::None;
+}
+
+Error CfHWC2::Display::getAttribute(hwc2_config_t configId,
+ Attribute attribute, int32_t* outValue) {
+ std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+ if (configId > mConfigs.size() || !mConfigs[configId]->isOnDisplay(*this)) {
+ ALOGV("[%" PRIu64 "] getAttribute failed: bad config (%u)", mId,
+ configId);
+ return Error::BadConfig;
+ }
+ *outValue = mConfigs[configId]->getAttribute(attribute);
+ ALOGV("[%" PRIu64 "] getAttribute(%u, %s) --> %d", mId, configId,
+ to_string(attribute).c_str(), *outValue);
+ return Error::None;
+}
+
+Error CfHWC2::Display::getChangedCompositionTypes(
+ uint32_t* outNumElements, hwc2_layer_t* outLayers, int32_t* outTypes) {
+ std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+ if (!mChanges) {
+ ALOGE("[%" PRIu64 "] getChangedCompositionTypes failed: not validated",
+ mId);
+ return Error::NotValidated;
+ }
+
+ if ((outLayers == nullptr) || (outTypes == nullptr)) {
+ *outNumElements = mChanges->getTypeChanges().size();
+ return Error::None;
+ }
+
+ uint32_t numWritten = 0;
+ for (const auto& element : mChanges->getTypeChanges()) {
+ if (numWritten == *outNumElements) {
+ break;
+ }
+ auto layerId = element.first;
+ auto intType = static_cast<int32_t>(element.second);
+ ALOGV("Adding %" PRIu64 " %s", layerId,
+ to_string(element.second).c_str());
+ outLayers[numWritten] = layerId;
+ outTypes[numWritten] = intType;
+ ++numWritten;
+ }
+ *outNumElements = numWritten;
+
+ return Error::None;
+}
+
+Error CfHWC2::Display::getColorModes(uint32_t* outNumModes,
+ int32_t* outModes) {
+ std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+ if (!outModes) {
+ *outNumModes = mColorModes.size();
+ return Error::None;
+ }
+ uint32_t numModes = std::min(*outNumModes,
+ static_cast<uint32_t>(mColorModes.size()));
+ std::copy_n(mColorModes.cbegin(), numModes, outModes);
+ *outNumModes = numModes;
+ return Error::None;
+}
+
+Error CfHWC2::Display::getConfigs(uint32_t* outNumConfigs,
+ hwc2_config_t* outConfigs) {
+ std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+ if (!outConfigs) {
+ *outNumConfigs = mConfigs.size();
+ return Error::None;
+ }
+ uint32_t numWritten = 0;
+ for (const auto& config : mConfigs) {
+ if (numWritten == *outNumConfigs) {
+ break;
+ }
+ outConfigs[numWritten] = config->getId();
+ ++numWritten;
+ }
+ *outNumConfigs = numWritten;
+ return Error::None;
+}
+
+Error CfHWC2::Display::getDozeSupport(int32_t* outSupport) {
+ std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+ if (mDevice.mHwc1MinorVersion < 4 || mHwc1Id != 0) {
+ *outSupport = 0;
+ } else {
+ *outSupport = 1;
+ }
+ return Error::None;
+}
+
+Error CfHWC2::Display::getHdrCapabilities(uint32_t* outNumTypes,
+ int32_t* /*outTypes*/, float* /*outMaxLuminance*/,
+ float* /*outMaxAverageLuminance*/, float* /*outMinLuminance*/) {
+ // This isn't supported on HWC1, so per the HWC2 header, return numTypes = 0
+ *outNumTypes = 0;
+ return Error::None;
+}
+
+Error CfHWC2::Display::getName(uint32_t* outSize, char* outName) {
+ std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+ if (!outName) {
+ *outSize = mName.size();
+ return Error::None;
+ }
+ auto numCopied = mName.copy(outName, *outSize);
+ *outSize = numCopied;
+ return Error::None;
+}
+
+Error CfHWC2::Display::getReleaseFences(uint32_t* outNumElements,
+ hwc2_layer_t* outLayers, int32_t* outFences) {
+ std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+ uint32_t numWritten = 0;
+ bool outputsNonNull = (outLayers != nullptr) && (outFences != nullptr);
+ for (const auto& layer : mLayers) {
+ if (outputsNonNull && (numWritten == *outNumElements)) {
+ break;
+ }
+
+ auto releaseFence = layer->getReleaseFence();
+ if (releaseFence != MiniFence::NO_FENCE) {
+ if (outputsNonNull) {
+ outLayers[numWritten] = layer->getId();
+ outFences[numWritten] = releaseFence->dup();
+ }
+ ++numWritten;
+ }
+ }
+ *outNumElements = numWritten;
+
+ return Error::None;
+}
+
+Error CfHWC2::Display::getRequests(int32_t* outDisplayRequests,
+ uint32_t* outNumElements, hwc2_layer_t* outLayers,
+ int32_t* outLayerRequests) {
+ std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+ if (!mChanges) {
+ return Error::NotValidated;
+ }
+
+ if (outLayers == nullptr || outLayerRequests == nullptr) {
+ *outNumElements = mChanges->getNumLayerRequests();
+ return Error::None;
+ }
+
+ // Display requests (HWC2::DisplayRequest) are not supported by hwc1:
+ // A hwc1 has always zero requests for the client.
+ *outDisplayRequests = 0;
+
+ uint32_t numWritten = 0;
+ for (const auto& request : mChanges->getLayerRequests()) {
+ if (numWritten == *outNumElements) {
+ break;
+ }
+ outLayers[numWritten] = request.first;
+ outLayerRequests[numWritten] = static_cast<int32_t>(request.second);
+ ++numWritten;
+ }
+
+ return Error::None;
+}
+
+Error CfHWC2::Display::getType(int32_t* outType) {
+ std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+ *outType = static_cast<int32_t>(mType);
+ return Error::None;
+}
+
+Error CfHWC2::Display::present(int32_t* outRetireFence) {
+ std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+ if (mChanges) {
+ Error error = mDevice.setAllDisplays();
+ if (error != Error::None) {
+ ALOGE("[%" PRIu64 "] present: setAllDisplaysFailed (%s)", mId,
+ to_string(error).c_str());
+ return error;
+ }
+ }
+
+ *outRetireFence = mRetireFence.get()->dup();
+ ALOGV("[%" PRIu64 "] present returning retire fence %d", mId,
+ *outRetireFence);
+
+ return Error::None;
+}
+
+Error CfHWC2::Display::setActiveConfig(hwc2_config_t configId) {
+ std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+ auto config = getConfig(configId);
+ if (!config) {
+ return Error::BadConfig;
+ }
+ if (config == mActiveConfig) {
+ return Error::None;
+ }
+
+ if (mDevice.mHwc1MinorVersion >= 4) {
+ uint32_t hwc1Id = 0;
+ auto error = config->getHwc1IdForColorMode(mActiveColorMode, &hwc1Id);
+ if (error != Error::None) {
+ return error;
+ }
+
+ int intError = mDevice.mHwc1Device->setActiveConfig(mDevice.mHwc1Device,
+ mHwc1Id, static_cast<int>(hwc1Id));
+ if (intError != 0) {
+ ALOGE("setActiveConfig: Failed to set active config on HWC1 (%d)",
+ intError);
+ return Error::BadConfig;
+ }
+ mActiveConfig = config;
+ }
+
+ return Error::None;
+}
+
+Error CfHWC2::Display::setClientTarget(buffer_handle_t target,
+ int32_t acquireFence, int32_t /*dataspace*/, hwc_region_t /*damage*/) {
+ std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+ ALOGV("[%" PRIu64 "] setClientTarget(%p, %d)", mId, target, acquireFence);
+ mClientTarget.setBuffer(target);
+ mClientTarget.setFence(acquireFence);
+ // dataspace and damage can't be used by HWC1, so ignore them
+ return Error::None;
+}
+
+Error CfHWC2::Display::setColorMode(android_color_mode_t mode) {
+ std::unique_lock<std::recursive_mutex> lock (mStateMutex);
+
+ ALOGV("[%" PRIu64 "] setColorMode(%d)", mId, mode);
+
+ if (mode == mActiveColorMode) {
+ return Error::None;
+ }
+ if (mColorModes.count(mode) == 0) {
+ ALOGE("[%" PRIu64 "] Mode %d not found in mColorModes", mId, mode);
+ return Error::Unsupported;
+ }
+
+ if (mDevice.mHwc1MinorVersion >= 4) {
+ uint32_t hwc1Config = 0;
+ auto error = mActiveConfig->getHwc1IdForColorMode(mode, &hwc1Config);
+ if (error != Error::None) {
+ return error;
+ }
+
+ ALOGV("[%" PRIu64 "] Setting HWC1 config %u", mId, hwc1Config);
+ int intError =
+ mDevice.mHwc1Device->setActiveConfig(mDevice.mHwc1Device, mHwc1Id, hwc1Config);
+ if (intError != 0) {
+ ALOGE("[%" PRIu64 "] Failed to set HWC1 config (%d)", mId, intError);
+ return Error::Unsupported;
+ }
+ }
+
+ mActiveColorMode = mode;
+ return Error::None;
+}
+
+Error CfHWC2::Display::setColorTransform(android_color_transform_t hint) {
+ std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+ ALOGV("%" PRIu64 "] setColorTransform(%d)", mId,
+ static_cast<int32_t>(hint));
+ mHasColorTransform = (hint != HAL_COLOR_TRANSFORM_IDENTITY);
+ return Error::None;
+}
+
+Error CfHWC2::Display::setOutputBuffer(buffer_handle_t buffer,
+ int32_t releaseFence) {
+ std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+ ALOGV("[%" PRIu64 "] setOutputBuffer(%p, %d)", mId, buffer, releaseFence);
+ mOutputBuffer.setBuffer(buffer);
+ mOutputBuffer.setFence(releaseFence);
+ return Error::None;
+}
+
+static bool isValid(PowerMode mode) {
+ switch (mode) {
+ case PowerMode::Off: // Fall-through
+ case PowerMode::DozeSuspend: // Fall-through
+ case PowerMode::Doze: // Fall-through
+ case PowerMode::On: return true;
+ }
+}
+
+static int getHwc1PowerMode(PowerMode mode) {
+ switch (mode) {
+ case PowerMode::Off: return HWC_POWER_MODE_OFF;
+ case PowerMode::DozeSuspend: return HWC_POWER_MODE_DOZE_SUSPEND;
+ case PowerMode::Doze: return HWC_POWER_MODE_DOZE;
+ case PowerMode::On: return HWC_POWER_MODE_NORMAL;
+ }
+}
+
+Error CfHWC2::Display::setPowerMode(PowerMode mode) {
+ if (!isValid(mode)) {
+ return Error::BadParameter;
+ }
+ if (mode == mPowerMode) {
+ return Error::None;
+ }
+
+ std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+ int error = 0;
+ if (mDevice.mHwc1MinorVersion < 4) {
+ error = mDevice.mHwc1Device->blank(mDevice.mHwc1Device, mHwc1Id,
+ mode == PowerMode::Off);
+ } else {
+ error = mDevice.mHwc1Device->setPowerMode(mDevice.mHwc1Device,
+ mHwc1Id, getHwc1PowerMode(mode));
+ }
+ ALOGE_IF(error != 0, "setPowerMode: Failed to set power mode on HWC1 (%d)",
+ error);
+
+ ALOGV("[%" PRIu64 "] setPowerMode(%s)", mId, to_string(mode).c_str());
+ mPowerMode = mode;
+ return Error::None;
+}
+
+static bool isValid(Vsync enable) {
+ switch (enable) {
+ case Vsync::Enable: // Fall-through
+ case Vsync::Disable: return true;
+ case Vsync::Invalid: return false;
+ }
+}
+
+Error CfHWC2::Display::setVsyncEnabled(Vsync enable) {
+ if (!isValid(enable)) {
+ return Error::BadParameter;
+ }
+ if (enable == mVsyncEnabled) {
+ return Error::None;
+ }
+
+ std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+ int error = mDevice.mHwc1Device->eventControl(mDevice.mHwc1Device,
+ mHwc1Id, HWC_EVENT_VSYNC, enable == Vsync::Enable);
+ ALOGE_IF(error != 0, "setVsyncEnabled: Failed to set vsync on HWC1 (%d)",
+ error);
+
+ mVsyncEnabled = enable;
+ return Error::None;
+}
+
+Error CfHWC2::Display::validate(uint32_t* outNumTypes,
+ uint32_t* outNumRequests) {
+ std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+ if (!mChanges) {
+ if (!mDevice.prepareAllDisplays()) {
+ return Error::BadDisplay;
+ }
+ } else {
+ ALOGE("Validate was called more than once!");
+ }
+
+ *outNumTypes = mChanges->getNumTypes();
+ *outNumRequests = mChanges->getNumLayerRequests();
+ ALOGV("[%" PRIu64 "] validate --> %u types, %u requests", mId, *outNumTypes,
+ *outNumRequests);
+ for (auto request : mChanges->getTypeChanges()) {
+ ALOGV("Layer %" PRIu64 " --> %s", request.first,
+ to_string(request.second).c_str());
+ }
+ return *outNumTypes > 0 ? Error::HasChanges : Error::None;
+}
+
+Error CfHWC2::Display::updateLayerZ(hwc2_layer_t layerId, uint32_t z) {
+ std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+ const auto mapLayer = mDevice.mLayers.find(layerId);
+ if (mapLayer == mDevice.mLayers.end()) {
+ ALOGE("[%" PRIu64 "] updateLayerZ failed to find layer", mId);
+ return Error::BadLayer;
+ }
+
+ const auto layer = mapLayer->second;
+ const auto zRange = mLayers.equal_range(layer);
+ bool layerOnDisplay = false;
+ for (auto current = zRange.first; current != zRange.second; ++current) {
+ if (**current == *layer) {
+ if ((*current)->getZ() == z) {
+ // Don't change anything if the Z hasn't changed
+ return Error::None;
+ }
+ current = mLayers.erase(current);
+ layerOnDisplay = true;
+ break;
+ }
+ }
+
+ if (!layerOnDisplay) {
+ ALOGE("[%" PRIu64 "] updateLayerZ failed to find layer on display",
+ mId);
+ return Error::BadLayer;
+ }
+
+ layer->setZ(z);
+ mLayers.emplace(std::move(layer));
+ markGeometryChanged();
+
+ return Error::None;
+}
+
+Error CfHWC2::Display::getClientTargetSupport(uint32_t width, uint32_t height,
+ int32_t format, int32_t dataspace){
+ if (mActiveConfig == nullptr) {
+ return Error::Unsupported;
+ }
+
+ if (width == mActiveConfig->getAttribute(Attribute::Width) &&
+ height == mActiveConfig->getAttribute(Attribute::Height) &&
+ format == HAL_PIXEL_FORMAT_RGBA_8888 &&
+ dataspace == HAL_DATASPACE_UNKNOWN) {
+ return Error::None;
+ }
+
+ return Error::Unsupported;
+}
+
+// thess EDIDs are carefully generated according to the EDID spec version 1.3, more info
+// can be found from the following file:
+// frameworks/native/services/surfaceflinger/DisplayHardware/DisplayIdentification.cpp
+// approved pnp ids can be found here: https://uefi.org/pnp_id_list
+// pnp id: GGL, name: EMU_display_0, last byte is checksum
+// display id is local:8141603649153536
+static const uint8_t sEDID0[] = {
+ 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x1c, 0xec, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x1b, 0x10, 0x01, 0x03, 0x80, 0x50, 0x2d, 0x78, 0x0a, 0x0d, 0xc9, 0xa0, 0x57, 0x47, 0x98, 0x27,
+ 0x12, 0x48, 0x4c, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x3a, 0x80, 0x18, 0x71, 0x38, 0x2d, 0x40, 0x58, 0x2c,
+ 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
+ 0x00, 0x45, 0x4d, 0x55, 0x5f, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x30, 0x00, 0x4b
+};
+
+// pnp id: GGL, name: EMU_display_1
+// display id is local:8140900251843329
+static const uint8_t sEDID1[] = {
+ 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x1c, 0xec, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x1b, 0x10, 0x01, 0x03, 0x80, 0x50, 0x2d, 0x78, 0x0a, 0x0d, 0xc9, 0xa0, 0x57, 0x47, 0x98, 0x27,
+ 0x12, 0x48, 0x4c, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x3a, 0x80, 0x18, 0x71, 0x38, 0x2d, 0x40, 0x58, 0x2c,
+ 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
+ 0x00, 0x45, 0x4d, 0x55, 0x5f, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x31, 0x00, 0x3b
+};
+
+// pnp id: GGL, name: EMU_display_2
+// display id is local:8140940453066754
+static const uint8_t sEDID2[] = {
+ 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x1c, 0xec, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x1b, 0x10, 0x01, 0x03, 0x80, 0x50, 0x2d, 0x78, 0x0a, 0x0d, 0xc9, 0xa0, 0x57, 0x47, 0x98, 0x27,
+ 0x12, 0x48, 0x4c, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x3a, 0x80, 0x18, 0x71, 0x38, 0x2d, 0x40, 0x58, 0x2c,
+ 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
+ 0x00, 0x45, 0x4d, 0x55, 0x5f, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x32, 0x00, 0x49
+};
+
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
+
+Error CfHWC2::Display::getDisplayIdentificationData(uint8_t* outPort,
+ uint32_t* outDataSize, uint8_t* outData) {
+ ALOGV("%s DisplayId %u", __FUNCTION__, (uint32_t)mId);
+ if (outPort == nullptr || outDataSize == nullptr)
+ return Error::BadParameter;
+
+ uint32_t len = std::min(*outDataSize, (uint32_t)ARRAY_SIZE(sEDID0));
+ if (outData != nullptr && len < (uint32_t)ARRAY_SIZE(sEDID0)) {
+ ALOGW("%s DisplayId %u, small buffer size: %u is specified",
+ __FUNCTION__, (uint32_t)mId, len);
+ }
+ *outDataSize = ARRAY_SIZE(sEDID0);
+ switch (mId) {
+ case 0:
+ *outPort = 0;
+ if (outData)
+ memcpy(outData, sEDID0, len);
+ break;
+
+ case 1:
+ *outPort = 1;
+ if (outData)
+ memcpy(outData, sEDID1, len);
+ break;
+
+ case 2:
+ *outPort = 2;
+ if (outData)
+ memcpy(outData, sEDID2, len);
+ break;
+
+ default:
+ *outPort = (uint8_t)mId;
+ if (outData) {
+ memcpy(outData, sEDID2, len);
+ uint32_t size = ARRAY_SIZE(sEDID0);
+ // change the name to EMU_display_<mID>
+ // note the 3rd char from back is the number, _0, _1, _2, etc.
+ if (len >= size - 2)
+ outData[size-3] = '0' + (uint8_t)mId;
+ if (len >= size) {
+ // update the last byte, which is checksum byte
+ uint8_t checksum = -(uint8_t)std::accumulate(
+ outData, outData + size - 1, static_cast<uint8_t>(0));
+ outData[size - 1] = checksum;
+ }
+ }
+ break;
+ }
+
+ return Error::None;
+}
+
+Error CfHWC2::Display::getDisplayCapabilities(uint32_t* outNumCapabilities,
+ uint32_t* outCapabilities) {
+ ALOGV("%s DisplayId %u", __FUNCTION__, (uint32_t)mId);
+ if (outNumCapabilities == nullptr) {
+ return Error::None;
+ }
+
+ bool brightness_support = true;
+ bool doze_support = true;
+
+ uint32_t count = 1 + static_cast<uint32_t>(doze_support) + (brightness_support ? 1 : 0);
+ int index = 0;
+ if (outCapabilities != nullptr && (*outNumCapabilities >= count)) {
+ outCapabilities[index++] = HWC2_DISPLAY_CAPABILITY_SKIP_CLIENT_COLOR_TRANSFORM;
+ if (doze_support) {
+ outCapabilities[index++] = HWC2_DISPLAY_CAPABILITY_DOZE;
+ }
+ if (brightness_support) {
+ outCapabilities[index++] = HWC2_DISPLAY_CAPABILITY_BRIGHTNESS;
+ }
+ }
+
+ *outNumCapabilities = count;
+ return Error::None;
+}
+
+Error CfHWC2::Display::getDisplayBrightnessSupport(bool *out_support) {
+ *out_support = false;
+ return Error::None;
+}
+
+Error CfHWC2::Display::setDisplayBrightness(float brightness) {
+ ALOGW("TODO: setDisplayBrightness() is not implemented yet: brightness=%f", brightness);
+ return Error::None;
+}
+
+static constexpr uint32_t ATTRIBUTES_WITH_COLOR[] = {
+ HWC_DISPLAY_VSYNC_PERIOD,
+ HWC_DISPLAY_WIDTH,
+ HWC_DISPLAY_HEIGHT,
+ HWC_DISPLAY_DPI_X,
+ HWC_DISPLAY_DPI_Y,
+ HWC_DISPLAY_COLOR_TRANSFORM,
+ HWC_DISPLAY_NO_ATTRIBUTE,
+};
+
+static constexpr uint32_t ATTRIBUTES_WITHOUT_COLOR[] = {
+ HWC_DISPLAY_VSYNC_PERIOD,
+ HWC_DISPLAY_WIDTH,
+ HWC_DISPLAY_HEIGHT,
+ HWC_DISPLAY_DPI_X,
+ HWC_DISPLAY_DPI_Y,
+ HWC_DISPLAY_NO_ATTRIBUTE,
+};
+
+static constexpr size_t NUM_ATTRIBUTES_WITH_COLOR =
+ sizeof(ATTRIBUTES_WITH_COLOR) / sizeof(uint32_t);
+static_assert(sizeof(ATTRIBUTES_WITH_COLOR) > sizeof(ATTRIBUTES_WITHOUT_COLOR),
+ "Attribute tables have unexpected sizes");
+
+static constexpr uint32_t ATTRIBUTE_MAP_WITH_COLOR[] = {
+ 6, // HWC_DISPLAY_NO_ATTRIBUTE = 0
+ 0, // HWC_DISPLAY_VSYNC_PERIOD = 1,
+ 1, // HWC_DISPLAY_WIDTH = 2,
+ 2, // HWC_DISPLAY_HEIGHT = 3,
+ 3, // HWC_DISPLAY_DPI_X = 4,
+ 4, // HWC_DISPLAY_DPI_Y = 5,
+ 5, // HWC_DISPLAY_COLOR_TRANSFORM = 6,
+};
+
+static constexpr uint32_t ATTRIBUTE_MAP_WITHOUT_COLOR[] = {
+ 5, // HWC_DISPLAY_NO_ATTRIBUTE = 0
+ 0, // HWC_DISPLAY_VSYNC_PERIOD = 1,
+ 1, // HWC_DISPLAY_WIDTH = 2,
+ 2, // HWC_DISPLAY_HEIGHT = 3,
+ 3, // HWC_DISPLAY_DPI_X = 4,
+ 4, // HWC_DISPLAY_DPI_Y = 5,
+};
+
+template <uint32_t attribute>
+static constexpr bool attributesMatch()
+{
+ bool match = (attribute ==
+ ATTRIBUTES_WITH_COLOR[ATTRIBUTE_MAP_WITH_COLOR[attribute]]);
+ if (attribute == HWC_DISPLAY_COLOR_TRANSFORM) {
+ return match;
+ }
+
+ return match && (attribute ==
+ ATTRIBUTES_WITHOUT_COLOR[ATTRIBUTE_MAP_WITHOUT_COLOR[attribute]]);
+}
+static_assert(attributesMatch<HWC_DISPLAY_VSYNC_PERIOD>(),
+ "Tables out of sync");
+static_assert(attributesMatch<HWC_DISPLAY_WIDTH>(), "Tables out of sync");
+static_assert(attributesMatch<HWC_DISPLAY_HEIGHT>(), "Tables out of sync");
+static_assert(attributesMatch<HWC_DISPLAY_DPI_X>(), "Tables out of sync");
+static_assert(attributesMatch<HWC_DISPLAY_DPI_Y>(), "Tables out of sync");
+static_assert(attributesMatch<HWC_DISPLAY_COLOR_TRANSFORM>(),
+ "Tables out of sync");
+
+void CfHWC2::Display::populateConfigs() {
+ std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+ ALOGV("[%" PRIu64 "] populateConfigs", mId);
+
+ if (mHwc1Id == -1) {
+ ALOGE("populateConfigs: HWC1 ID not set");
+ return;
+ }
+
+ const size_t MAX_NUM_CONFIGS = 128;
+ uint32_t configs[MAX_NUM_CONFIGS] = {};
+ size_t numConfigs = MAX_NUM_CONFIGS;
+ mDevice.mHwc1Device->getDisplayConfigs(mDevice.mHwc1Device, mHwc1Id,
+ configs, &numConfigs);
+
+ for (size_t c = 0; c < numConfigs; ++c) {
+ uint32_t hwc1ConfigId = configs[c];
+ auto newConfig = std::make_shared<Config>(*this);
+
+ int32_t values[NUM_ATTRIBUTES_WITH_COLOR] = {};
+ bool hasColor = true;
+ auto result = mDevice.mHwc1Device->getDisplayAttributes(
+ mDevice.mHwc1Device, mHwc1Id, hwc1ConfigId,
+ ATTRIBUTES_WITH_COLOR, values);
+ if (result != 0) {
+ mDevice.mHwc1Device->getDisplayAttributes(mDevice.mHwc1Device,
+ mHwc1Id, hwc1ConfigId, ATTRIBUTES_WITHOUT_COLOR, values);
+ hasColor = false;
+ }
+
+ auto attributeMap = hasColor ?
+ ATTRIBUTE_MAP_WITH_COLOR : ATTRIBUTE_MAP_WITHOUT_COLOR;
+
+ newConfig->setAttribute(Attribute::VsyncPeriod,
+ values[attributeMap[HWC_DISPLAY_VSYNC_PERIOD]]);
+ newConfig->setAttribute(Attribute::Width,
+ values[attributeMap[HWC_DISPLAY_WIDTH]]);
+ newConfig->setAttribute(Attribute::Height,
+ values[attributeMap[HWC_DISPLAY_HEIGHT]]);
+ newConfig->setAttribute(Attribute::DpiX,
+ values[attributeMap[HWC_DISPLAY_DPI_X]]);
+ newConfig->setAttribute(Attribute::DpiY,
+ values[attributeMap[HWC_DISPLAY_DPI_Y]]);
+ if (hasColor) {
+ // In HWC1, color modes are referred to as color transforms. To avoid confusion with
+ // the HWC2 concept of color transforms, we internally refer to them as color modes for
+ // both HWC1 and 2.
+ newConfig->setAttribute(ColorMode,
+ values[attributeMap[HWC_DISPLAY_COLOR_TRANSFORM]]);
+ }
+
+ // We can only do this after attempting to read the color mode
+ newConfig->setHwc1Id(hwc1ConfigId);
+
+ for (auto& existingConfig : mConfigs) {
+ if (existingConfig->merge(*newConfig)) {
+ ALOGV("Merged config %d with existing config %u: %s",
+ hwc1ConfigId, existingConfig->getId(),
+ existingConfig->toString().c_str());
+ newConfig.reset();
+ break;
+ }
+ }
+
+ // If it wasn't merged with any existing config, add it to the end
+ if (newConfig) {
+ newConfig->setId(static_cast<hwc2_config_t>(mConfigs.size()));
+ ALOGV("Found new config %u: %s", newConfig->getId(),
+ newConfig->toString().c_str());
+ mConfigs.emplace_back(std::move(newConfig));
+ }
+ }
+
+ initializeActiveConfig();
+ populateColorModes();
+}
+
+void CfHWC2::Display::populateConfigs(uint32_t width, uint32_t height) {
+ std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+ mConfigs.emplace_back(std::make_shared<Config>(*this));
+ auto& config = mConfigs[0];
+
+ config->setAttribute(Attribute::Width, static_cast<int32_t>(width));
+ config->setAttribute(Attribute::Height, static_cast<int32_t>(height));
+ config->setHwc1Id(0);
+ config->setId(0);
+ mActiveConfig = config;
+}
+
+bool CfHWC2::Display::prepare() {
+ std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+ // Only prepare display contents for displays HWC1 knows about
+ if (mHwc1Id == -1) {
+ return true;
+ }
+
+ // It doesn't make sense to prepare a display for which there is no active
+ // config, so return early
+ if (!mActiveConfig) {
+ ALOGE("[%" PRIu64 "] Attempted to prepare, but no config active", mId);
+ return false;
+ }
+
+ allocateRequestedContents();
+ assignHwc1LayerIds();
+
+ mHwc1RequestedContents->retireFenceFd = -1;
+ mHwc1RequestedContents->flags = 0;
+ if (mGeometryChanged) {
+ mHwc1RequestedContents->flags |= HWC_GEOMETRY_CHANGED;
+ }
+ mHwc1RequestedContents->outbuf = mOutputBuffer.getBuffer();
+ mHwc1RequestedContents->outbufAcquireFenceFd = mOutputBuffer.getFence();
+
+ // +1 is for framebuffer target layer.
+ mHwc1RequestedContents->numHwLayers = mLayers.size() + 1;
+ for (auto& layer : mLayers) {
+ auto& hwc1Layer = mHwc1RequestedContents->hwLayers[layer->getHwc1Id()];
+ hwc1Layer.releaseFenceFd = -1;
+ hwc1Layer.acquireFenceFd = -1;
+ ALOGV("Applying states for layer %" PRIu64 " ", layer->getId());
+ layer->applyState(hwc1Layer);
+ }
+
+ prepareFramebufferTarget();
+
+ resetGeometryMarker();
+
+ return true;
+}
+
+void CfHWC2::Display::generateChanges() {
+ std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+ mChanges.reset(new Changes);
+
+ size_t numLayers = mHwc1RequestedContents->numHwLayers;
+ for (size_t hwc1Id = 0; hwc1Id < numLayers; ++hwc1Id) {
+ const auto& receivedLayer = mHwc1RequestedContents->hwLayers[hwc1Id];
+ if (mHwc1LayerMap.count(hwc1Id) == 0) {
+ ALOGE_IF(receivedLayer.compositionType != HWC_FRAMEBUFFER_TARGET,
+ "generateChanges: HWC1 layer %zd doesn't have a"
+ " matching HWC2 layer, and isn't the framebuffer target",
+ hwc1Id);
+ continue;
+ }
+
+ Layer& layer = *mHwc1LayerMap[hwc1Id];
+ updateTypeChanges(receivedLayer, layer);
+ updateLayerRequests(receivedLayer, layer);
+ }
+}
+
+bool CfHWC2::Display::hasChanges() const {
+ std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+ return mChanges != nullptr;
+}
+
+Error CfHWC2::Display::set(hwc_display_contents_1& hwcContents) {
+ std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+ if (!mChanges || (mChanges->getNumTypes() > 0)) {
+ ALOGE("[%" PRIu64 "] set failed: not validated", mId);
+ return Error::NotValidated;
+ }
+
+ // Set up the client/framebuffer target
+ auto numLayers = hwcContents.numHwLayers;
+
+ // Close acquire fences on FRAMEBUFFER layers, since they will not be used
+ // by HWC
+ for (size_t l = 0; l < numLayers - 1; ++l) {
+ auto& layer = hwcContents.hwLayers[l];
+ if (layer.compositionType == HWC_FRAMEBUFFER) {
+ ALOGV("Closing fence %d for layer %zd", layer.acquireFenceFd, l);
+ close(layer.acquireFenceFd);
+ layer.acquireFenceFd = -1;
+ }
+ }
+
+ auto& clientTargetLayer = hwcContents.hwLayers[numLayers - 1];
+ if (clientTargetLayer.compositionType == HWC_FRAMEBUFFER_TARGET) {
+ clientTargetLayer.handle = mClientTarget.getBuffer();
+ clientTargetLayer.acquireFenceFd = mClientTarget.getFence();
+ } else {
+ ALOGE("[%" PRIu64 "] set: last HWC layer wasn't FRAMEBUFFER_TARGET",
+ mId);
+ }
+
+ mChanges.reset();
+
+ return Error::None;
+}
+
+void CfHWC2::Display::addRetireFence(int fenceFd) {
+ std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+ mRetireFence.add(fenceFd);
+}
+
+void CfHWC2::Display::addReleaseFences(
+ const hwc_display_contents_1_t& hwcContents) {
+ std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+ size_t numLayers = hwcContents.numHwLayers;
+ for (size_t hwc1Id = 0; hwc1Id < numLayers; ++hwc1Id) {
+ const auto& receivedLayer = hwcContents.hwLayers[hwc1Id];
+ if (mHwc1LayerMap.count(hwc1Id) == 0) {
+ if (receivedLayer.compositionType != HWC_FRAMEBUFFER_TARGET) {
+ ALOGE("addReleaseFences: HWC1 layer %zd doesn't have a"
+ " matching HWC2 layer, and isn't the framebuffer"
+ " target", hwc1Id);
+ }
+ // Close the framebuffer target release fence since we will use the
+ // display retire fence instead
+ if (receivedLayer.releaseFenceFd != -1) {
+ close(receivedLayer.releaseFenceFd);
+ }
+ continue;
+ }
+
+ Layer& layer = *mHwc1LayerMap[hwc1Id];
+ ALOGV("Adding release fence %d to layer %" PRIu64,
+ receivedLayer.releaseFenceFd, layer.getId());
+ layer.addReleaseFence(receivedLayer.releaseFenceFd);
+ }
+}
+
+bool CfHWC2::Display::hasColorTransform() const {
+ std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+ return mHasColorTransform;
+}
+
+static std::string hwc1CompositionString(int32_t type) {
+ switch (type) {
+ case HWC_FRAMEBUFFER: return "Framebuffer";
+ case HWC_OVERLAY: return "Overlay";
+ case HWC_BACKGROUND: return "Background";
+ case HWC_FRAMEBUFFER_TARGET: return "FramebufferTarget";
+ case HWC_SIDEBAND: return "Sideband";
+ case HWC_CURSOR_OVERLAY: return "CursorOverlay";
+ default:
+ return std::string("Unknown (") + std::to_string(type) + ")";
+ }
+}
+
+static std::string hwc1TransformString(int32_t transform) {
+ switch (transform) {
+ case 0: return "None";
+ case HWC_TRANSFORM_FLIP_H: return "FlipH";
+ case HWC_TRANSFORM_FLIP_V: return "FlipV";
+ case HWC_TRANSFORM_ROT_90: return "Rotate90";
+ case HWC_TRANSFORM_ROT_180: return "Rotate180";
+ case HWC_TRANSFORM_ROT_270: return "Rotate270";
+ case HWC_TRANSFORM_FLIP_H_ROT_90: return "FlipHRotate90";
+ case HWC_TRANSFORM_FLIP_V_ROT_90: return "FlipVRotate90";
+ default:
+ return std::string("Unknown (") + std::to_string(transform) + ")";
+ }
+}
+
+static std::string hwc1BlendModeString(int32_t mode) {
+ switch (mode) {
+ case HWC_BLENDING_NONE: return "None";
+ case HWC_BLENDING_PREMULT: return "Premultiplied";
+ case HWC_BLENDING_COVERAGE: return "Coverage";
+ default:
+ return std::string("Unknown (") + std::to_string(mode) + ")";
+ }
+}
+
+static std::string rectString(hwc_rect_t rect) {
+ std::stringstream output;
+ output << "[" << rect.left << ", " << rect.top << ", ";
+ output << rect.right << ", " << rect.bottom << "]";
+ return output.str();
+}
+
+static std::string approximateFloatString(float f) {
+ if (static_cast<float>(static_cast<int32_t>(f)) == f) {
+ return std::to_string(static_cast<int32_t>(f));
+ }
+ int32_t truncated = static_cast<int32_t>(f * 10);
+ bool approximate = (static_cast<float>(truncated) != f * 10);
+ const size_t BUFFER_SIZE = 32;
+ char buffer[BUFFER_SIZE] = {};
+ auto bytesWritten = snprintf(buffer, BUFFER_SIZE,
+ "%s%.1f", approximate ? "~" : "", f);
+ return std::string(buffer, bytesWritten);
+}
+
+static std::string frectString(hwc_frect_t frect) {
+ std::stringstream output;
+ output << "[" << approximateFloatString(frect.left) << ", ";
+ output << approximateFloatString(frect.top) << ", ";
+ output << approximateFloatString(frect.right) << ", ";
+ output << approximateFloatString(frect.bottom) << "]";
+ return output.str();
+}
+
+static std::string colorString(hwc_color_t color) {
+ std::stringstream output;
+ output << "RGBA [";
+ output << static_cast<int32_t>(color.r) << ", ";
+ output << static_cast<int32_t>(color.g) << ", ";
+ output << static_cast<int32_t>(color.b) << ", ";
+ output << static_cast<int32_t>(color.a) << "]";
+ return output.str();
+}
+
+static std::string alphaString(float f) {
+ const size_t BUFFER_SIZE = 8;
+ char buffer[BUFFER_SIZE] = {};
+ auto bytesWritten = snprintf(buffer, BUFFER_SIZE, "%.3f", f);
+ return std::string(buffer, bytesWritten);
+}
+
+static std::string to_string(const hwc_layer_1_t& hwcLayer,
+ int32_t hwc1MinorVersion) {
+ const char* fill = " ";
+
+ std::stringstream output;
+
+ output << " Composition: " <<
+ hwc1CompositionString(hwcLayer.compositionType);
+
+ if (hwcLayer.compositionType == HWC_BACKGROUND) {
+ output << " Color: " << colorString(hwcLayer.backgroundColor) << '\n';
+ } else if (hwcLayer.compositionType == HWC_SIDEBAND) {
+ output << " Stream: " << hwcLayer.sidebandStream << '\n';
+ } else {
+ output << " Buffer: " << hwcLayer.handle << "/" <<
+ hwcLayer.acquireFenceFd << '\n';
+ }
+
+ output << fill << "Display frame: " << rectString(hwcLayer.displayFrame) <<
+ '\n';
+
+ output << fill << "Source crop: ";
+ if (hwc1MinorVersion >= 3) {
+ output << frectString(hwcLayer.sourceCropf) << '\n';
+ } else {
+ output << rectString(hwcLayer.sourceCropi) << '\n';
+ }
+
+ output << fill << "Transform: " << hwc1TransformString(hwcLayer.transform);
+ output << " Blend mode: " << hwc1BlendModeString(hwcLayer.blending);
+ if (hwcLayer.planeAlpha != 0xFF) {
+ output << " Alpha: " << alphaString(hwcLayer.planeAlpha / 255.0f);
+ }
+ output << '\n';
+
+ if (hwcLayer.hints != 0) {
+ output << fill << "Hints:";
+ if ((hwcLayer.hints & HWC_HINT_TRIPLE_BUFFER) != 0) {
+ output << " TripleBuffer";
+ }
+ if ((hwcLayer.hints & HWC_HINT_CLEAR_FB) != 0) {
+ output << " ClearFB";
+ }
+ output << '\n';
+ }
+
+ if (hwcLayer.flags != 0) {
+ output << fill << "Flags:";
+ if ((hwcLayer.flags & HWC_SKIP_LAYER) != 0) {
+ output << " SkipLayer";
+ }
+ if ((hwcLayer.flags & HWC_IS_CURSOR_LAYER) != 0) {
+ output << " IsCursorLayer";
+ }
+ output << '\n';
+ }
+
+ return output.str();
+}
+
+static std::string to_string(const hwc_display_contents_1_t& hwcContents,
+ int32_t hwc1MinorVersion) {
+ const char* fill = " ";
+
+ std::stringstream output;
+ output << fill << "Geometry changed: " <<
+ ((hwcContents.flags & HWC_GEOMETRY_CHANGED) != 0 ? "Y\n" : "N\n");
+
+ output << fill << hwcContents.numHwLayers << " Layer" <<
+ ((hwcContents.numHwLayers == 1) ? "\n" : "s\n");
+ for (size_t layer = 0; layer < hwcContents.numHwLayers; ++layer) {
+ output << fill << " Layer " << layer;
+ output << to_string(hwcContents.hwLayers[layer], hwc1MinorVersion);
+ }
+
+ if (hwcContents.outbuf != nullptr) {
+ output << fill << "Output buffer: " << hwcContents.outbuf << "/" <<
+ hwcContents.outbufAcquireFenceFd << '\n';
+ }
+
+ return output.str();
+}
+
+std::string CfHWC2::Display::dump() const {
+ std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+ std::stringstream output;
+
+ output << " Display " << mId << ": ";
+ output << to_string(mType) << " ";
+ output << "HWC1 ID: " << mHwc1Id << " ";
+ output << "Power mode: " << to_string(mPowerMode) << " ";
+ output << "Vsync: " << to_string(mVsyncEnabled) << '\n';
+
+ output << " Color modes [active]:";
+ for (const auto& mode : mColorModes) {
+ if (mode == mActiveColorMode) {
+ output << " [" << mode << ']';
+ } else {
+ output << " " << mode;
+ }
+ }
+ output << '\n';
+
+ output << " " << mConfigs.size() << " Config" <<
+ (mConfigs.size() == 1 ? "" : "s") << " (* active)\n";
+ for (const auto& config : mConfigs) {
+ output << (config == mActiveConfig ? " * " : " ");
+ output << config->toString(true) << '\n';
+ }
+
+ output << " " << mLayers.size() << " Layer" <<
+ (mLayers.size() == 1 ? "" : "s") << '\n';
+ for (const auto& layer : mLayers) {
+ output << layer->dump();
+ }
+
+ output << " Client target: " << mClientTarget.getBuffer() << '\n';
+
+ if (mOutputBuffer.getBuffer() != nullptr) {
+ output << " Output buffer: " << mOutputBuffer.getBuffer() << '\n';
+ }
+
+ if (mHwc1RequestedContents) {
+ output << " Last requested HWC1 state\n";
+ output << to_string(*mHwc1RequestedContents, mDevice.mHwc1MinorVersion);
+ }
+
+ return output.str();
+}
+
+hwc_rect_t* CfHWC2::Display::GetRects(size_t numRects) {
+ if (numRects == 0) {
+ return nullptr;
+ }
+
+ if (numRects > mNumAvailableRects) {
+ // This should NEVER happen since we calculated how many rects the
+ // display would need.
+ ALOGE("Rect allocation failure! SF is likely to crash soon!");
+ return nullptr;
+
+ }
+ hwc_rect_t* rects = mNextAvailableRect;
+ mNextAvailableRect += numRects;
+ mNumAvailableRects -= numRects;
+ return rects;
+}
+
+hwc_display_contents_1* CfHWC2::Display::getDisplayContents() {
+ return mHwc1RequestedContents.get();
+}
+
+void CfHWC2::Display::Config::setAttribute(HWC2::Attribute attribute,
+ int32_t value) {
+ mAttributes[attribute] = value;
+}
+
+int32_t CfHWC2::Display::Config::getAttribute(Attribute attribute) const {
+ if (mAttributes.count(attribute) == 0) {
+ return -1;
+ }
+ return mAttributes.at(attribute);
+}
+
+void CfHWC2::Display::Config::setHwc1Id(uint32_t id) {
+ android_color_mode_t colorMode = static_cast<android_color_mode_t>(getAttribute(ColorMode));
+ mHwc1Ids.emplace(colorMode, id);
+}
+
+bool CfHWC2::Display::Config::hasHwc1Id(uint32_t id) const {
+ for (const auto& idPair : mHwc1Ids) {
+ if (id == idPair.second) {
+ return true;
+ }
+ }
+ return false;
+}
+
+Error CfHWC2::Display::Config::getColorModeForHwc1Id(
+ uint32_t id, android_color_mode_t* outMode) const {
+ for (const auto& idPair : mHwc1Ids) {
+ if (id == idPair.second) {
+ *outMode = idPair.first;
+ return Error::None;
+ }
+ }
+ ALOGE("Unable to find color mode for HWC ID %" PRIu32 " on config %u", id, mId);
+ return Error::BadParameter;
+}
+
+Error CfHWC2::Display::Config::getHwc1IdForColorMode(android_color_mode_t mode,
+ uint32_t* outId) const {
+ for (const auto& idPair : mHwc1Ids) {
+ if (mode == idPair.first) {
+ *outId = idPair.second;
+ return Error::None;
+ }
+ }
+ ALOGE("Unable to find HWC1 ID for color mode %d on config %u", mode, mId);
+ return Error::BadParameter;
+}
+
+bool CfHWC2::Display::Config::merge(const Config& other) {
+ auto attributes = {HWC2::Attribute::Width, HWC2::Attribute::Height,
+ HWC2::Attribute::VsyncPeriod, HWC2::Attribute::DpiX,
+ HWC2::Attribute::DpiY};
+ for (auto attribute : attributes) {
+ if (getAttribute(attribute) != other.getAttribute(attribute)) {
+ return false;
+ }
+ }
+ android_color_mode_t otherColorMode =
+ static_cast<android_color_mode_t>(other.getAttribute(ColorMode));
+ if (mHwc1Ids.count(otherColorMode) != 0) {
+ ALOGE("Attempted to merge two configs (%u and %u) which appear to be "
+ "identical", mHwc1Ids.at(otherColorMode),
+ other.mHwc1Ids.at(otherColorMode));
+ return false;
+ }
+ mHwc1Ids.emplace(otherColorMode,
+ other.mHwc1Ids.at(otherColorMode));
+ return true;
+}
+
+std::set<android_color_mode_t> CfHWC2::Display::Config::getColorModes() const {
+ std::set<android_color_mode_t> colorModes;
+ for (const auto& idPair : mHwc1Ids) {
+ colorModes.emplace(idPair.first);
+ }
+ return colorModes;
+}
+
+std::string CfHWC2::Display::Config::toString(bool splitLine) const {
+ std::string output;
+
+ const size_t BUFFER_SIZE = 100;
+ char buffer[BUFFER_SIZE] = {};
+ auto writtenBytes = snprintf(buffer, BUFFER_SIZE,
+ "%u x %u", mAttributes.at(HWC2::Attribute::Width),
+ mAttributes.at(HWC2::Attribute::Height));
+ output.append(buffer, writtenBytes);
+
+ if (mAttributes.count(HWC2::Attribute::VsyncPeriod) != 0) {
+ std::memset(buffer, 0, BUFFER_SIZE);
+ writtenBytes = snprintf(buffer, BUFFER_SIZE, " @ %.1f Hz",
+ 1e9 / mAttributes.at(HWC2::Attribute::VsyncPeriod));
+ output.append(buffer, writtenBytes);
+ }
+
+ if (mAttributes.count(HWC2::Attribute::DpiX) != 0 &&
+ mAttributes.at(HWC2::Attribute::DpiX) != -1) {
+ std::memset(buffer, 0, BUFFER_SIZE);
+ writtenBytes =
+ snprintf(buffer, BUFFER_SIZE, ", DPI: %.1f x %.1f",
+ static_cast<float>(mAttributes.at(HWC2::Attribute::DpiX)) / 1000.0f,
+ static_cast<float>(mAttributes.at(HWC2::Attribute::DpiY)) / 1000.0f);
+ output.append(buffer, writtenBytes);
+ }
+
+ std::memset(buffer, 0, BUFFER_SIZE);
+ if (splitLine) {
+ writtenBytes = snprintf(buffer, BUFFER_SIZE,
+ "\n HWC1 ID/Color transform:");
+ } else {
+ writtenBytes = snprintf(buffer, BUFFER_SIZE,
+ ", HWC1 ID/Color transform:");
+ }
+ output.append(buffer, writtenBytes);
+
+
+ for (const auto& id : mHwc1Ids) {
+ android_color_mode_t colorMode = id.first;
+ uint32_t hwc1Id = id.second;
+ std::memset(buffer, 0, BUFFER_SIZE);
+ if (colorMode == mDisplay.mActiveColorMode) {
+ writtenBytes = snprintf(buffer, BUFFER_SIZE, " [%u/%d]", hwc1Id,
+ colorMode);
+ } else {
+ writtenBytes = snprintf(buffer, BUFFER_SIZE, " %u/%d", hwc1Id,
+ colorMode);
+ }
+ output.append(buffer, writtenBytes);
+ }
+
+ return output;
+}
+
+std::shared_ptr<const CfHWC2::Display::Config>
+ CfHWC2::Display::getConfig(hwc2_config_t configId) const {
+ if (configId > mConfigs.size() || !mConfigs[configId]->isOnDisplay(*this)) {
+ return nullptr;
+ }
+ return mConfigs[configId];
+}
+
+void CfHWC2::Display::populateColorModes() {
+ mColorModes = mConfigs[0]->getColorModes();
+ for (const auto& config : mConfigs) {
+ std::set<android_color_mode_t> intersection;
+ auto configModes = config->getColorModes();
+ std::set_intersection(mColorModes.cbegin(), mColorModes.cend(),
+ configModes.cbegin(), configModes.cend(),
+ std::inserter(intersection, intersection.begin()));
+ std::swap(intersection, mColorModes);
+ }
+}
+
+void CfHWC2::Display::initializeActiveConfig() {
+ if (mDevice.mHwc1Device->getActiveConfig == nullptr) {
+ ALOGV("getActiveConfig is null, choosing config 0");
+ mActiveConfig = mConfigs[0];
+ mActiveColorMode = HAL_COLOR_MODE_NATIVE;
+ return;
+ }
+
+ auto activeConfig = mDevice.mHwc1Device->getActiveConfig(
+ mDevice.mHwc1Device, mHwc1Id);
+
+ // Some devices startup without an activeConfig:
+ // We need to set one ourselves.
+ if (activeConfig == HWC_ERROR) {
+ ALOGV("There is no active configuration: Picking the first one: 0.");
+ const int defaultIndex = 0;
+ mDevice.mHwc1Device->setActiveConfig(mDevice.mHwc1Device, mHwc1Id, defaultIndex);
+ activeConfig = defaultIndex;
+ }
+
+ for (const auto& config : mConfigs) {
+ if (config->hasHwc1Id(activeConfig)) {
+ ALOGE("Setting active config to %d for HWC1 config %u", config->getId(), activeConfig);
+ mActiveConfig = config;
+ if (config->getColorModeForHwc1Id(activeConfig, &mActiveColorMode) != Error::None) {
+ // This should never happen since we checked for the config's presence before
+ // setting it as active.
+ ALOGE("Unable to find color mode for active HWC1 config %d", config->getId());
+ mActiveColorMode = HAL_COLOR_MODE_NATIVE;
+ }
+ break;
+ }
+ }
+ if (!mActiveConfig) {
+ ALOGV("Unable to find active HWC1 config %u, defaulting to "
+ "config 0", activeConfig);
+ mActiveConfig = mConfigs[0];
+ mActiveColorMode = HAL_COLOR_MODE_NATIVE;
+ }
+
+
+
+
+}
+
+void CfHWC2::Display::allocateRequestedContents() {
+ // What needs to be allocated:
+ // 1 hwc_display_contents_1_t
+ // 1 hwc_layer_1_t for each layer
+ // 1 hwc_rect_t for each layer's surfaceDamage
+ // 1 hwc_rect_t for each layer's visibleRegion
+ // 1 hwc_layer_1_t for the framebuffer
+ // 1 hwc_rect_t for the framebuffer's visibleRegion
+
+ // Count # of surfaceDamage
+ size_t numSurfaceDamages = 0;
+ for (const auto& layer : mLayers) {
+ numSurfaceDamages += layer->getNumSurfaceDamages();
+ }
+
+ // Count # of visibleRegions (start at 1 for mandatory framebuffer target
+ // region)
+ size_t numVisibleRegion = 1;
+ for (const auto& layer : mLayers) {
+ numVisibleRegion += layer->getNumVisibleRegions();
+ }
+
+ size_t numRects = numVisibleRegion + numSurfaceDamages;
+ auto numLayers = mLayers.size() + 1;
+ size_t size = sizeof(hwc_display_contents_1_t) +
+ sizeof(hwc_layer_1_t) * numLayers +
+ sizeof(hwc_rect_t) * numRects;
+ auto contents = static_cast<hwc_display_contents_1_t*>(std::calloc(size, 1));
+ mHwc1RequestedContents.reset(contents);
+ mNextAvailableRect = reinterpret_cast<hwc_rect_t*>(&contents->hwLayers[numLayers]);
+ mNumAvailableRects = numRects;
+}
+
+void CfHWC2::Display::assignHwc1LayerIds() {
+ mHwc1LayerMap.clear();
+ size_t nextHwc1Id = 0;
+ for (auto& layer : mLayers) {
+ mHwc1LayerMap[nextHwc1Id] = layer;
+ layer->setHwc1Id(nextHwc1Id++);
+ }
+}
+
+void CfHWC2::Display::updateTypeChanges(const hwc_layer_1_t& hwc1Layer,
+ const Layer& layer) {
+ auto layerId = layer.getId();
+ switch (hwc1Layer.compositionType) {
+ case HWC_FRAMEBUFFER:
+ if (layer.getCompositionType() != Composition::Client) {
+ mChanges->addTypeChange(layerId, Composition::Client);
+ }
+ break;
+ case HWC_OVERLAY:
+ if (layer.getCompositionType() != Composition::Device) {
+ mChanges->addTypeChange(layerId, Composition::Device);
+ }
+ break;
+ case HWC_BACKGROUND:
+ ALOGE_IF(layer.getCompositionType() != Composition::SolidColor,
+ "updateTypeChanges: HWC1 requested BACKGROUND, but HWC2"
+ " wasn't expecting SolidColor");
+ break;
+ case HWC_FRAMEBUFFER_TARGET:
+ // Do nothing, since it shouldn't be modified by HWC1
+ break;
+ case HWC_SIDEBAND:
+ ALOGE_IF(layer.getCompositionType() != Composition::Sideband,
+ "updateTypeChanges: HWC1 requested SIDEBAND, but HWC2"
+ " wasn't expecting Sideband");
+ break;
+ case HWC_CURSOR_OVERLAY:
+ ALOGE_IF(layer.getCompositionType() != Composition::Cursor,
+ "updateTypeChanges: HWC1 requested CURSOR_OVERLAY, but"
+ " HWC2 wasn't expecting Cursor");
+ break;
+ }
+}
+
+void CfHWC2::Display::updateLayerRequests(
+ const hwc_layer_1_t& hwc1Layer, const Layer& layer) {
+ if ((hwc1Layer.hints & HWC_HINT_CLEAR_FB) != 0) {
+ mChanges->addLayerRequest(layer.getId(),
+ LayerRequest::ClearClientTarget);
+ }
+}
+
+void CfHWC2::Display::prepareFramebufferTarget() {
+ // We check that mActiveConfig is valid in Display::prepare
+ int32_t width = mActiveConfig->getAttribute(Attribute::Width);
+ int32_t height = mActiveConfig->getAttribute(Attribute::Height);
+
+ auto& hwc1Target = mHwc1RequestedContents->hwLayers[mLayers.size()];
+ hwc1Target.compositionType = HWC_FRAMEBUFFER_TARGET;
+ hwc1Target.releaseFenceFd = -1;
+ hwc1Target.hints = 0;
+ hwc1Target.flags = 0;
+ hwc1Target.transform = 0;
+ hwc1Target.blending = HWC_BLENDING_PREMULT;
+ if (mDevice.getHwc1MinorVersion() < 3) {
+ hwc1Target.sourceCropi = {0, 0, width, height};
+ } else {
+ hwc1Target.sourceCropf = {0.0f, 0.0f, static_cast<float>(width),
+ static_cast<float>(height)};
+ }
+ hwc1Target.displayFrame = {0, 0, width, height};
+ hwc1Target.planeAlpha = 255;
+
+ hwc1Target.visibleRegionScreen.numRects = 1;
+ hwc_rect_t* rects = GetRects(1);
+ rects[0].left = 0;
+ rects[0].top = 0;
+ rects[0].right = width;
+ rects[0].bottom = height;
+ hwc1Target.visibleRegionScreen.rects = rects;
+
+ // We will set this to the correct value in set
+ hwc1Target.acquireFenceFd = -1;
+}
+
+// Layer functions
+
+std::atomic<hwc2_layer_t> CfHWC2::Layer::sNextId(1);
+
+CfHWC2::Layer::Layer(Display& display)
+ : mId(sNextId++),
+ mDisplay(display),
+ mBuffer(),
+ mSurfaceDamage(),
+ mBlendMode(BlendMode::None),
+ mColor({0, 0, 0, 0}),
+ mCompositionType(Composition::Invalid),
+ mDisplayFrame({0, 0, -1, -1}),
+ mPlaneAlpha(0.0f),
+ mSidebandStream(nullptr),
+ mSourceCrop({0.0f, 0.0f, -1.0f, -1.0f}),
+ mTransform(Transform::None),
+ mVisibleRegion(),
+ mZ(0),
+ mReleaseFence(),
+ mHwc1Id(0),
+ mHasUnsupportedPlaneAlpha(false) {}
+
+bool CfHWC2::SortLayersByZ::operator()(const std::shared_ptr<Layer>& lhs,
+ const std::shared_ptr<Layer>& rhs) const {
+ return lhs->getZ() < rhs->getZ();
+}
+
+Error CfHWC2::Layer::setBuffer(buffer_handle_t buffer,
+ int32_t acquireFence) {
+ ALOGV("Setting acquireFence to %d for layer %" PRIu64, acquireFence, mId);
+ mBuffer.setBuffer(buffer);
+ mBuffer.setFence(acquireFence);
+ return Error::None;
+}
+
+Error CfHWC2::Layer::setCursorPosition(int32_t x, int32_t y) {
+ if (mCompositionType != Composition::Cursor) {
+ return Error::BadLayer;
+ }
+
+ if (mDisplay.hasChanges()) {
+ return Error::NotValidated;
+ }
+
+ auto displayId = mDisplay.getHwc1Id();
+ auto hwc1Device = mDisplay.getDevice().getHwc1Device();
+ hwc1Device->setCursorPositionAsync(hwc1Device, displayId, x, y);
+ return Error::None;
+}
+
+Error CfHWC2::Layer::setSurfaceDamage(hwc_region_t damage) {
+ // HWC1 supports surface damage starting only with version 1.5.
+ if (mDisplay.getDevice().mHwc1MinorVersion < 5) {
+ return Error::None;
+ }
+ mSurfaceDamage.resize(damage.numRects);
+ std::copy_n(damage.rects, damage.numRects, mSurfaceDamage.begin());
+ return Error::None;
+}
+
+// Layer state functions
+
+Error CfHWC2::Layer::setBlendMode(BlendMode mode) {
+ mBlendMode = mode;
+ mDisplay.markGeometryChanged();
+ return Error::None;
+}
+
+Error CfHWC2::Layer::setColor(hwc_color_t color) {
+ mColor = color;
+ mDisplay.markGeometryChanged();
+ return Error::None;
+}
+
+Error CfHWC2::Layer::setCompositionType(Composition type) {
+ mCompositionType = type;
+ mDisplay.markGeometryChanged();
+ return Error::None;
+}
+
+Error CfHWC2::Layer::setDataspace(android_dataspace_t) {
+ return Error::None;
+}
+
+Error CfHWC2::Layer::setDisplayFrame(hwc_rect_t frame) {
+ mDisplayFrame = frame;
+ mDisplay.markGeometryChanged();
+ return Error::None;
+}
+
+Error CfHWC2::Layer::setPlaneAlpha(float alpha) {
+ mPlaneAlpha = alpha;
+ mDisplay.markGeometryChanged();
+ return Error::None;
+}
+
+Error CfHWC2::Layer::setSidebandStream(const native_handle_t* stream) {
+ mSidebandStream = stream;
+ mDisplay.markGeometryChanged();
+ return Error::None;
+}
+
+Error CfHWC2::Layer::setSourceCrop(hwc_frect_t crop) {
+ mSourceCrop = crop;
+ mDisplay.markGeometryChanged();
+ return Error::None;
+}
+
+Error CfHWC2::Layer::setTransform(Transform transform) {
+ mTransform = transform;
+ mDisplay.markGeometryChanged();
+ return Error::None;
+}
+
+static bool compareRects(const hwc_rect_t& rect1, const hwc_rect_t& rect2) {
+ return rect1.left == rect2.left &&
+ rect1.right == rect2.right &&
+ rect1.top == rect2.top &&
+ rect1.bottom == rect2.bottom;
+}
+
+Error CfHWC2::Layer::setVisibleRegion(hwc_region_t visible) {
+ if ((getNumVisibleRegions() != visible.numRects) ||
+ !std::equal(mVisibleRegion.begin(), mVisibleRegion.end(), visible.rects,
+ compareRects)) {
+ mVisibleRegion.resize(visible.numRects);
+ std::copy_n(visible.rects, visible.numRects, mVisibleRegion.begin());
+ mDisplay.markGeometryChanged();
+ }
+ return Error::None;
+}
+
+Error CfHWC2::Layer::setZ(uint32_t z) {
+ mZ = z;
+ return Error::None;
+}
+
+void CfHWC2::Layer::addReleaseFence(int fenceFd) {
+ ALOGV("addReleaseFence %d to layer %" PRIu64, fenceFd, mId);
+ mReleaseFence.add(fenceFd);
+}
+
+const sp<MiniFence>& CfHWC2::Layer::getReleaseFence() const {
+ return mReleaseFence.get();
+}
+
+void CfHWC2::Layer::applyState(hwc_layer_1_t& hwc1Layer) {
+ applyCommonState(hwc1Layer);
+ applyCompositionType(hwc1Layer);
+ switch (mCompositionType) {
+ case Composition::SolidColor : applySolidColorState(hwc1Layer); break;
+ case Composition::Sideband : applySidebandState(hwc1Layer); break;
+ default: applyBufferState(hwc1Layer); break;
+ }
+}
+
+static std::string regionStrings(const std::vector<hwc_rect_t>& visibleRegion,
+ const std::vector<hwc_rect_t>& surfaceDamage) {
+ std::string regions;
+ regions += " Visible Region";
+ regions.resize(40, ' ');
+ regions += "Surface Damage\n";
+
+ size_t numPrinted = 0;
+ size_t maxSize = std::max(visibleRegion.size(), surfaceDamage.size());
+ while (numPrinted < maxSize) {
+ std::string line(" ");
+ if (visibleRegion.empty() && numPrinted == 0) {
+ line += "None";
+ } else if (numPrinted < visibleRegion.size()) {
+ line += rectString(visibleRegion[numPrinted]);
+ }
+ line.resize(40, ' ');
+ if (surfaceDamage.empty() && numPrinted == 0) {
+ line += "None";
+ } else if (numPrinted < surfaceDamage.size()) {
+ line += rectString(surfaceDamage[numPrinted]);
+ }
+ line += '\n';
+ regions += line;
+ ++numPrinted;
+ }
+ return regions;
+}
+
+std::string CfHWC2::Layer::dump() const {
+ std::stringstream output;
+ const char* fill = " ";
+
+ output << fill << to_string(mCompositionType);
+ output << " Layer HWC2/1: " << mId << "/" << mHwc1Id << " ";
+ output << "Z: " << mZ;
+ if (mCompositionType == HWC2::Composition::SolidColor) {
+ output << " " << colorString(mColor);
+ } else if (mCompositionType == HWC2::Composition::Sideband) {
+ output << " Handle: " << mSidebandStream << '\n';
+ } else {
+ output << " Buffer: " << mBuffer.getBuffer() << '\n';
+ output << fill << " Display frame [LTRB]: " <<
+ rectString(mDisplayFrame) << '\n';
+ output << fill << " Source crop: " <<
+ frectString(mSourceCrop) << '\n';
+ output << fill << " Transform: " << to_string(mTransform);
+ output << " Blend mode: " << to_string(mBlendMode);
+ if (mPlaneAlpha != 1.0f) {
+ output << " Alpha: " <<
+ alphaString(mPlaneAlpha) << '\n';
+ } else {
+ output << '\n';
+ }
+ output << regionStrings(mVisibleRegion, mSurfaceDamage);
+ }
+ return output.str();
+}
+
+static int getHwc1Blending(HWC2::BlendMode blendMode) {
+ switch (blendMode) {
+ case BlendMode::Coverage: return HWC_BLENDING_COVERAGE;
+ case BlendMode::Premultiplied: return HWC_BLENDING_PREMULT;
+ default: return HWC_BLENDING_NONE;
+ }
+}
+
+void CfHWC2::Layer::applyCommonState(hwc_layer_1_t& hwc1Layer) {
+ auto minorVersion = mDisplay.getDevice().getHwc1MinorVersion();
+ hwc1Layer.blending = getHwc1Blending(mBlendMode);
+ hwc1Layer.displayFrame = mDisplayFrame;
+
+ auto pendingAlpha = mPlaneAlpha;
+ if (minorVersion < 2) {
+ mHasUnsupportedPlaneAlpha = pendingAlpha < 1.0f;
+ } else {
+ hwc1Layer.planeAlpha =
+ static_cast<uint8_t>(255.0f * pendingAlpha + 0.5f);
+ }
+
+ if (minorVersion < 3) {
+ auto pending = mSourceCrop;
+ hwc1Layer.sourceCropi.left =
+ static_cast<int32_t>(std::ceil(pending.left));
+ hwc1Layer.sourceCropi.top =
+ static_cast<int32_t>(std::ceil(pending.top));
+ hwc1Layer.sourceCropi.right =
+ static_cast<int32_t>(std::floor(pending.right));
+ hwc1Layer.sourceCropi.bottom =
+ static_cast<int32_t>(std::floor(pending.bottom));
+ } else {
+ hwc1Layer.sourceCropf = mSourceCrop;
+ }
+
+ hwc1Layer.transform = static_cast<uint32_t>(mTransform);
+
+ auto& hwc1VisibleRegion = hwc1Layer.visibleRegionScreen;
+ hwc1VisibleRegion.numRects = mVisibleRegion.size();
+ hwc_rect_t* rects = mDisplay.GetRects(hwc1VisibleRegion.numRects);
+ hwc1VisibleRegion.rects = rects;
+ for (size_t i = 0; i < mVisibleRegion.size(); i++) {
+ rects[i] = mVisibleRegion[i];
+ }
+}
+
+void CfHWC2::Layer::applySolidColorState(hwc_layer_1_t& hwc1Layer) {
+ // If the device does not support background color it is likely to make
+ // assumption regarding backgroundColor and handle (both fields occupy
+ // the same location in hwc_layer_1_t union).
+ // To not confuse these devices we don't set background color and we
+ // make sure handle is a null pointer.
+ if (hasUnsupportedBackgroundColor()) {
+ hwc1Layer.handle = nullptr;
+ } else {
+ hwc1Layer.backgroundColor = mColor;
+ }
+}
+
+void CfHWC2::Layer::applySidebandState(hwc_layer_1_t& hwc1Layer) {
+ hwc1Layer.sidebandStream = mSidebandStream;
+}
+
+void CfHWC2::Layer::applyBufferState(hwc_layer_1_t& hwc1Layer) {
+ hwc1Layer.handle = mBuffer.getBuffer();
+ hwc1Layer.acquireFenceFd = mBuffer.getFence();
+}
+
+void CfHWC2::Layer::applyCompositionType(hwc_layer_1_t& hwc1Layer) {
+ // HWC1 never supports color transforms or dataspaces and only sometimes
+ // supports plane alpha (depending on the version). These require us to drop
+ // some or all layers to client composition.
+ if (mHasUnsupportedPlaneAlpha || mDisplay.hasColorTransform() ||
+ hasUnsupportedBackgroundColor()) {
+ hwc1Layer.compositionType = HWC_FRAMEBUFFER;
+ hwc1Layer.flags = HWC_SKIP_LAYER;
+ return;
+ }
+
+ hwc1Layer.flags = 0;
+ switch (mCompositionType) {
+ case Composition::Client:
+ hwc1Layer.compositionType = HWC_FRAMEBUFFER;
+ hwc1Layer.flags |= HWC_SKIP_LAYER;
+ break;
+ case Composition::Device:
+ hwc1Layer.compositionType = HWC_FRAMEBUFFER;
+ break;
+ case Composition::SolidColor:
+ // In theory the following line should work, but since the HWC1
+ // version of SurfaceFlinger never used HWC_BACKGROUND, HWC1
+ // devices may not work correctly. To be on the safe side, we
+ // fall back to client composition.
+ //
+ // hwc1Layer.compositionType = HWC_BACKGROUND;
+ hwc1Layer.compositionType = HWC_FRAMEBUFFER;
+ hwc1Layer.flags |= HWC_SKIP_LAYER;
+ break;
+ case Composition::Cursor:
+ hwc1Layer.compositionType = HWC_FRAMEBUFFER;
+ if (mDisplay.getDevice().getHwc1MinorVersion() >= 4) {
+ hwc1Layer.hints |= HWC_IS_CURSOR_LAYER;
+ }
+ break;
+ case Composition::Sideband:
+ if (mDisplay.getDevice().getHwc1MinorVersion() < 4) {
+ hwc1Layer.compositionType = HWC_SIDEBAND;
+ } else {
+ hwc1Layer.compositionType = HWC_FRAMEBUFFER;
+ hwc1Layer.flags |= HWC_SKIP_LAYER;
+ }
+ break;
+ default:
+ hwc1Layer.compositionType = HWC_FRAMEBUFFER;
+ hwc1Layer.flags |= HWC_SKIP_LAYER;
+ break;
+ }
+ ALOGV("Layer %" PRIu64 " %s set to %d", mId,
+ to_string(mCompositionType).c_str(),
+ hwc1Layer.compositionType);
+ ALOGV_IF(hwc1Layer.flags & HWC_SKIP_LAYER, " and skipping");
+}
+
+// Adapter helpers
+
+void CfHWC2::populateCapabilities() {
+ if (mHwc1MinorVersion >= 3U) {
+ int supportedTypes = 0;
+ auto result = mHwc1Device->query(mHwc1Device,
+ HWC_DISPLAY_TYPES_SUPPORTED, &supportedTypes);
+ if ((result == 0) && ((supportedTypes & HWC_DISPLAY_VIRTUAL_BIT) != 0)) {
+ ALOGI("Found support for HWC virtual displays");
+ mHwc1SupportsVirtualDisplays = true;
+ }
+ }
+ if (mHwc1MinorVersion >= 4U) {
+ mCapabilities.insert(Capability::SidebandStream);
+ }
+
+ // Check for HWC background color layer support.
+ if (mHwc1MinorVersion >= 1U) {
+ int backgroundColorSupported = 0;
+ auto result = mHwc1Device->query(mHwc1Device,
+ HWC_BACKGROUND_LAYER_SUPPORTED,
+ &backgroundColorSupported);
+ if ((result == 0) && (backgroundColorSupported == 1)) {
+ ALOGV("Found support for HWC background color");
+ mHwc1SupportsBackgroundColor = true;
+ }
+ }
+
+ // Some devices might have HWC1 retire fences that accurately emulate
+ // HWC2 present fences when they are deferred, but it's not very reliable.
+ // To be safe, we indicate PresentFenceIsNotReliable for all HWC1 devices.
+ //mCapabilities.insert(Capability::PresentFenceIsNotReliable);
+}
+
+CfHWC2::Display* CfHWC2::getDisplay(hwc2_display_t id) {
+ std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex);
+
+ auto display = mDisplays.find(id);
+ if (display == mDisplays.end()) {
+ return nullptr;
+ }
+
+ return display->second.get();
+}
+
+std::tuple<CfHWC2::Layer*, Error> CfHWC2::getLayer(
+ hwc2_display_t displayId, hwc2_layer_t layerId) {
+ auto display = getDisplay(displayId);
+ if (!display) {
+ return std::make_tuple(static_cast<Layer*>(nullptr), Error::BadDisplay);
+ }
+
+ auto layerEntry = mLayers.find(layerId);
+ if (layerEntry == mLayers.end()) {
+ return std::make_tuple(static_cast<Layer*>(nullptr), Error::BadLayer);
+ }
+
+ auto layer = layerEntry->second;
+ if (layer->getDisplay().getId() != displayId) {
+ return std::make_tuple(static_cast<Layer*>(nullptr), Error::BadLayer);
+ }
+ return std::make_tuple(layer.get(), Error::None);
+}
+
+void CfHWC2::populatePrimary() {
+ std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex);
+
+ auto display = std::make_shared<Display>(*this, HWC2::DisplayType::Physical);
+ mHwc1DisplayMap[HWC_DISPLAY_PRIMARY] = display->getId();
+ display->setHwc1Id(HWC_DISPLAY_PRIMARY);
+ display->populateConfigs();
+ mDisplays.emplace(display->getId(), std::move(display));
+}
+
+bool CfHWC2::prepareAllDisplays() {
+ ATRACE_CALL();
+
+ std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex);
+
+ for (const auto& displayPair : mDisplays) {
+ auto& display = displayPair.second;
+ if (!display->prepare()) {
+ return false;
+ }
+ }
+
+ if (mHwc1DisplayMap.count(HWC_DISPLAY_PRIMARY) == 0) {
+ ALOGE("prepareAllDisplays: Unable to find primary HWC1 display");
+ return false;
+ }
+
+ // Build an array of hwc_display_contents_1 to call prepare() on HWC1.
+ mHwc1Contents.clear();
+
+ // Always push the primary display
+ auto primaryDisplayId = mHwc1DisplayMap[HWC_DISPLAY_PRIMARY];
+ auto& primaryDisplay = mDisplays[primaryDisplayId];
+ mHwc1Contents.push_back(primaryDisplay->getDisplayContents());
+
+ // Push the external display, if present
+ if (mHwc1DisplayMap.count(HWC_DISPLAY_EXTERNAL) != 0) {
+ auto externalDisplayId = mHwc1DisplayMap[HWC_DISPLAY_EXTERNAL];
+ auto& externalDisplay = mDisplays[externalDisplayId];
+ mHwc1Contents.push_back(externalDisplay->getDisplayContents());
+ } else {
+ // Even if an external display isn't present, we still need to send
+ // at least two displays down to HWC1
+ mHwc1Contents.push_back(nullptr);
+ }
+
+ // Push the hardware virtual display, if supported and present
+ if (mHwc1MinorVersion >= 3) {
+ if (mHwc1DisplayMap.count(HWC_DISPLAY_VIRTUAL) != 0) {
+ auto virtualDisplayId = mHwc1DisplayMap[HWC_DISPLAY_VIRTUAL];
+ auto& virtualDisplay = mDisplays[virtualDisplayId];
+ mHwc1Contents.push_back(virtualDisplay->getDisplayContents());
+ } else {
+ mHwc1Contents.push_back(nullptr);
+ }
+ }
+
+ for (auto& displayContents : mHwc1Contents) {
+ if (!displayContents) {
+ continue;
+ }
+
+ ALOGV("Display %zd layers:", mHwc1Contents.size() - 1);
+ for (size_t l = 0; l < displayContents->numHwLayers; ++l) {
+ auto& layer = displayContents->hwLayers[l];
+ ALOGV(" %zd: %d", l, layer.compositionType);
+ }
+ }
+
+ ALOGV("Calling HWC1 prepare");
+ {
+ ATRACE_NAME("HWC1 prepare");
+ mHwc1Device->prepare(mHwc1Device, mHwc1Contents.size(),
+ mHwc1Contents.data());
+ }
+
+ for (size_t c = 0; c < mHwc1Contents.size(); ++c) {
+ auto& contents = mHwc1Contents[c];
+ if (!contents) {
+ continue;
+ }
+ ALOGV("Display %zd layers:", c);
+ for (size_t l = 0; l < contents->numHwLayers; ++l) {
+ ALOGV(" %zd: %d", l, contents->hwLayers[l].compositionType);
+ }
+ }
+
+ // Return the received contents to their respective displays
+ for (size_t hwc1Id = 0; hwc1Id < mHwc1Contents.size(); ++hwc1Id) {
+ if (mHwc1Contents[hwc1Id] == nullptr) {
+ continue;
+ }
+
+ auto displayId = mHwc1DisplayMap[hwc1Id];
+ auto& display = mDisplays[displayId];
+ display->generateChanges();
+ }
+
+ return true;
+}
+
+void dumpHWC1Message(hwc_composer_device_1* device, size_t numDisplays,
+ hwc_display_contents_1_t** displays) {
+ ALOGV("*****************************");
+ size_t displayId = 0;
+ while (displayId < numDisplays) {
+ hwc_display_contents_1_t* display = displays[displayId];
+
+ ALOGV("hwc_display_contents_1_t[%zu] @0x%p", displayId, display);
+ if (display == nullptr) {
+ displayId++;
+ continue;
+ }
+ ALOGV(" retirefd:0x%08x", display->retireFenceFd);
+ ALOGV(" outbuf :0x%p", display->outbuf);
+ ALOGV(" outbuffd:0x%08x", display->outbufAcquireFenceFd);
+ ALOGV(" flags :0x%08x", display->flags);
+ for(size_t layerId=0 ; layerId < display->numHwLayers ; layerId++) {
+ hwc_layer_1_t& layer = display->hwLayers[layerId];
+ ALOGV(" Layer[%zu]:", layerId);
+ ALOGV(" composition : 0x%08x", layer.compositionType);
+ ALOGV(" hints : 0x%08x", layer.hints);
+ ALOGV(" flags : 0x%08x", layer.flags);
+ ALOGV(" handle : 0x%p", layer.handle);
+ ALOGV(" transform : 0x%08x", layer.transform);
+ ALOGV(" blending : 0x%08x", layer.blending);
+ ALOGV(" sourceCropf : %f, %f, %f, %f",
+ layer.sourceCropf.left,
+ layer.sourceCropf.top,
+ layer.sourceCropf.right,
+ layer.sourceCropf.bottom);
+ ALOGV(" displayFrame : %d, %d, %d, %d",
+ layer.displayFrame.left,
+ layer.displayFrame.left,
+ layer.displayFrame.left,
+ layer.displayFrame.left);
+ hwc_region_t& visReg = layer.visibleRegionScreen;
+ ALOGV(" visibleRegionScreen: #0x%08zx[@0x%p]",
+ visReg.numRects,
+ visReg.rects);
+ for (size_t visRegId=0; visRegId < visReg.numRects ; visRegId++) {
+ if (layer.visibleRegionScreen.rects == nullptr) {
+ ALOGV(" null");
+ } else {
+ ALOGV(" visibleRegionScreen[%zu] %d, %d, %d, %d",
+ visRegId,
+ visReg.rects[visRegId].left,
+ visReg.rects[visRegId].top,
+ visReg.rects[visRegId].right,
+ visReg.rects[visRegId].bottom);
+ }
+ }
+ ALOGV(" acquireFenceFd : 0x%08x", layer.acquireFenceFd);
+ ALOGV(" releaseFenceFd : 0x%08x", layer.releaseFenceFd);
+ ALOGV(" planeAlpha : 0x%08x", layer.planeAlpha);
+ if (getMinorVersion(device) < 5)
+ continue;
+ ALOGV(" surfaceDamage : #0x%08zx[@0x%p]",
+ layer.surfaceDamage.numRects,
+ layer.surfaceDamage.rects);
+ for (size_t sdId=0; sdId < layer.surfaceDamage.numRects ; sdId++) {
+ if (layer.surfaceDamage.rects == nullptr) {
+ ALOGV(" null");
+ } else {
+ ALOGV(" surfaceDamage[%zu] %d, %d, %d, %d",
+ sdId,
+ layer.surfaceDamage.rects[sdId].left,
+ layer.surfaceDamage.rects[sdId].top,
+ layer.surfaceDamage.rects[sdId].right,
+ layer.surfaceDamage.rects[sdId].bottom);
+ }
+ }
+ }
+ displayId++;
+ }
+ ALOGV("-----------------------------");
+}
+
+Error CfHWC2::setAllDisplays() {
+ ATRACE_CALL();
+
+ std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex);
+
+ // Make sure we're ready to validate
+ for (size_t hwc1Id = 0; hwc1Id < mHwc1Contents.size(); ++hwc1Id) {
+ if (mHwc1Contents[hwc1Id] == nullptr) {
+ continue;
+ }
+
+ auto displayId = mHwc1DisplayMap[hwc1Id];
+ auto& display = mDisplays[displayId];
+ Error error = display->set(*mHwc1Contents[hwc1Id]);
+ if (error != Error::None) {
+ ALOGE("setAllDisplays: Failed to set display %zd: %s", hwc1Id,
+ to_string(error).c_str());
+ return error;
+ }
+ }
+
+ ALOGV("Calling HWC1 set");
+ {
+ ATRACE_NAME("HWC1 set");
+ //dumpHWC1Message(mHwc1Device, mHwc1Contents.size(), mHwc1Contents.data());
+ mHwc1Device->set(mHwc1Device, mHwc1Contents.size(),
+ mHwc1Contents.data());
+ }
+
+ // Add retire and release fences
+ for (size_t hwc1Id = 0; hwc1Id < mHwc1Contents.size(); ++hwc1Id) {
+ if (mHwc1Contents[hwc1Id] == nullptr) {
+ continue;
+ }
+
+ auto displayId = mHwc1DisplayMap[hwc1Id];
+ auto& display = mDisplays[displayId];
+ auto retireFenceFd = mHwc1Contents[hwc1Id]->retireFenceFd;
+ ALOGV("setAllDisplays: Adding retire fence %d to display %zd",
+ retireFenceFd, hwc1Id);
+ display->addRetireFence(mHwc1Contents[hwc1Id]->retireFenceFd);
+ display->addReleaseFences(*mHwc1Contents[hwc1Id]);
+ }
+
+ return Error::None;
+}
+
+void CfHWC2::hwc1Invalidate() {
+ ALOGV("Received hwc1Invalidate");
+
+ std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex);
+
+ // If the HWC2-side callback hasn't been registered yet, buffer this until
+ // it is registered.
+ if (mCallbacks.count(Callback::Refresh) == 0) {
+ mHasPendingInvalidate = true;
+ return;
+ }
+
+ const auto& callbackInfo = mCallbacks[Callback::Refresh];
+ std::vector<hwc2_display_t> displays;
+ for (const auto& displayPair : mDisplays) {
+ displays.emplace_back(displayPair.first);
+ }
+
+ // Call back without the state lock held.
+ lock.unlock();
+
+ auto refresh = reinterpret_cast<HWC2_PFN_REFRESH>(callbackInfo.pointer);
+ for (auto display : displays) {
+ refresh(callbackInfo.data, display);
+ }
+}
+
+void CfHWC2::hwc1Vsync(int hwc1DisplayId, int64_t timestamp) {
+ ALOGV("Received hwc1Vsync(%d, %" PRId64 ")", hwc1DisplayId, timestamp);
+
+ std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex);
+
+ // If the HWC2-side callback hasn't been registered yet, buffer this until
+ // it is registered.
+ if (mCallbacks.count(Callback::Vsync) == 0) {
+ mPendingVsyncs.emplace_back(hwc1DisplayId, timestamp);
+ return;
+ }
+
+ if (mHwc1DisplayMap.count(hwc1DisplayId) == 0) {
+ ALOGE("hwc1Vsync: Couldn't find display for HWC1 id %d", hwc1DisplayId);
+ return;
+ }
+
+ const auto& callbackInfo = mCallbacks[Callback::Vsync];
+ auto displayId = mHwc1DisplayMap[hwc1DisplayId];
+
+ // Call back without the state lock held.
+ lock.unlock();
+
+ auto vsync = reinterpret_cast<HWC2_PFN_VSYNC>(callbackInfo.pointer);
+ vsync(callbackInfo.data, displayId, timestamp);
+}
+
+void CfHWC2::hwc1Hotplug(int hwc1DisplayId, int connected) {
+ ALOGV("Received hwc1Hotplug(%d, %d)", hwc1DisplayId, connected);
+
+ if (hwc1DisplayId != HWC_DISPLAY_EXTERNAL) {
+ ALOGE("hwc1Hotplug: Received hotplug for non-external display");
+ return;
+ }
+
+ std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex);
+
+ hwc2_display_t displayId = UINT64_MAX;
+ if (mHwc1DisplayMap.count(hwc1DisplayId) == 0) {
+ if (connected == 0) {
+ ALOGW("hwc1Hotplug: Received disconnect for unconnected display");
+ return;
+ }
+
+ // Create a new display on connect
+ auto display = std::make_shared<CfHWC2::Display>(*this,
+ HWC2::DisplayType::Physical);
+ display->setHwc1Id(HWC_DISPLAY_EXTERNAL);
+ display->populateConfigs();
+ displayId = display->getId();
+ mHwc1DisplayMap[HWC_DISPLAY_EXTERNAL] = displayId;
+ mDisplays.emplace(displayId, std::move(display));
+ } else {
+ if (connected != 0) {
+ ALOGW("hwc1Hotplug: Received connect for previously connected "
+ "display");
+ return;
+ }
+
+ // Disconnect an existing display
+ displayId = mHwc1DisplayMap[hwc1DisplayId];
+ mHwc1DisplayMap.erase(HWC_DISPLAY_EXTERNAL);
+ mDisplays.erase(displayId);
+ }
+
+ // If the HWC2-side callback hasn't been registered yet, buffer this until
+ // it is registered
+ if (mCallbacks.count(Callback::Hotplug) == 0) {
+ mPendingHotplugs.emplace_back(hwc1DisplayId, connected);
+ return;
+ }
+
+ const auto& callbackInfo = mCallbacks[Callback::Hotplug];
+
+ // Call back without the state lock held
+ lock.unlock();
+
+ auto hotplug = reinterpret_cast<HWC2_PFN_HOTPLUG>(callbackInfo.pointer);
+ auto hwc2Connected = (connected == 0) ?
+ HWC2::Connection::Disconnected : HWC2::Connection::Connected;
+ hotplug(callbackInfo.data, displayId, static_cast<int32_t>(hwc2Connected));
+}
+
+static int hwc2DevOpen(const struct hw_module_t *module, const char *name,
+ struct hw_device_t **dev) {
+ ALOGV("%s()", __FUNCTION__);
+ if (strcmp(name, HWC_HARDWARE_COMPOSER)) {
+ ALOGE("Invalid module name- %s", name);
+ return -EINVAL;
+ }
+
+ std::unique_ptr<cvd::ScreenView> screen_view(new cvd::VsocketScreenView());
+ if (!screen_view) {
+ ALOGE("Failed to instantiate screen view");
+ return -1;
+ }
+
+ hw_device_t* device;
+ int error = cvd::cvd_hwc_open(std::move(screen_view), module, name, &device);
+ if (error) {
+ ALOGE("failed to open hwcomposer device: %s", strerror(-error));
+ return -1;
+ }
+
+ int major = (device->version >> 24) & 0xf;
+ ALOGV("%s(): major=%d", __FUNCTION__, major);
+ if (major < 2) {
+ CfHWC2* hwc2 = new CfHWC2(std::move(reinterpret_cast<hwc_composer_device_1*>(device)));
+ hwc2->common.module = const_cast<hw_module_t *>(module);
+ *dev = &hwc2->common;
+ } else {
+ *dev = device;
+ }
+
+ return 0;
+}
+
+} // namespace android
+
+static struct hw_module_methods_t hwc2_module_methods = {
+ .open = android::hwc2DevOpen
+};
+
+hw_module_t HAL_MODULE_INFO_SYM = {
+ .tag = HARDWARE_MODULE_TAG,
+ .version_major = 2,
+ .version_minor = 0,
+ .id = HWC_HARDWARE_MODULE_ID,
+ .name = "CuttleFish HWC2 module",
+ .author = "Google",
+ .methods = &hwc2_module_methods,
+ .dso = NULL,
+ .reserved = {0},
+};
diff --git a/guest/hals/hwcomposer/cutf_cvm/HWC2.h b/guest/hals/hwcomposer/cutf_cvm/HWC2.h
new file mode 100644
index 000000000..7739b25ed
--- /dev/null
+++ b/guest/hals/hwcomposer/cutf_cvm/HWC2.h
@@ -0,0 +1,743 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_SF_HWC2_ON_1_ADAPTER_H
+#define ANDROID_SF_HWC2_ON_1_ADAPTER_H
+
+#define HWC2_INCLUDE_STRINGIFICATION
+#define HWC2_USE_CPP11
+#include <hardware/hwcomposer2.h>
+#undef HWC2_INCLUDE_STRINGIFICATION
+#undef HWC2_USE_CPP11
+
+#include "MiniFence.h"
+
+#include <atomic>
+#include <map>
+#include <mutex>
+#include <numeric>
+#include <queue>
+#include <set>
+#include <unordered_map>
+#include <unordered_set>
+#include <vector>
+
+struct hwc_composer_device_1;
+struct hwc_display_contents_1;
+struct hwc_layer_1;
+
+namespace android {
+
+class CfHWC2 : public hwc2_device_t
+{
+public:
+ explicit CfHWC2(struct hwc_composer_device_1* hwc1Device);
+ ~CfHWC2();
+
+ struct hwc_composer_device_1* getHwc1Device() const { return mHwc1Device; }
+ uint8_t getHwc1MinorVersion() const { return mHwc1MinorVersion; }
+
+private:
+ static inline CfHWC2* getAdapter(hwc2_device_t* device) {
+ return static_cast<CfHWC2*>(device);
+ }
+
+ // getCapabilities
+
+ void doGetCapabilities(uint32_t* outCount,
+ int32_t* /*hwc2_capability_t*/ outCapabilities);
+ static void getCapabilitiesHook(hwc2_device_t* device, uint32_t* outCount,
+ int32_t* /*hwc2_capability_t*/ outCapabilities) {
+ getAdapter(device)->doGetCapabilities(outCount, outCapabilities);
+ }
+
+ bool supportsBackgroundColor() {
+ return mHwc1SupportsBackgroundColor;
+ }
+
+ // getFunction
+
+ hwc2_function_pointer_t doGetFunction(HWC2::FunctionDescriptor descriptor);
+ static hwc2_function_pointer_t getFunctionHook(hwc2_device_t* device,
+ int32_t intDesc) {
+ auto descriptor = static_cast<HWC2::FunctionDescriptor>(intDesc);
+ return getAdapter(device)->doGetFunction(descriptor);
+ }
+
+ // Device functions
+
+ HWC2::Error createVirtualDisplay(uint32_t width, uint32_t height,
+ hwc2_display_t* outDisplay);
+ static int32_t createVirtualDisplayHook(hwc2_device_t* device,
+ uint32_t width, uint32_t height, int32_t* /*format*/,
+ hwc2_display_t* outDisplay) {
+ // HWC1 implementations cannot override the buffer format requested by
+ // the consumer
+ auto error = getAdapter(device)->createVirtualDisplay(width, height,
+ outDisplay);
+ return static_cast<int32_t>(error);
+ }
+
+ HWC2::Error destroyVirtualDisplay(hwc2_display_t display);
+ static int32_t destroyVirtualDisplayHook(hwc2_device_t* device,
+ hwc2_display_t display) {
+ auto error = getAdapter(device)->destroyVirtualDisplay(display);
+ return static_cast<int32_t>(error);
+ }
+
+ std::string mDumpString;
+ void dump(uint32_t* outSize, char* outBuffer);
+ static void dumpHook(hwc2_device_t* device, uint32_t* outSize,
+ char* outBuffer) {
+ getAdapter(device)->dump(outSize, outBuffer);
+ }
+
+ uint32_t getMaxVirtualDisplayCount();
+ static uint32_t getMaxVirtualDisplayCountHook(hwc2_device_t* device) {
+ return getAdapter(device)->getMaxVirtualDisplayCount();
+ }
+
+ HWC2::Error registerCallback(HWC2::Callback descriptor,
+ hwc2_callback_data_t callbackData, hwc2_function_pointer_t pointer);
+ static int32_t registerCallbackHook(hwc2_device_t* device,
+ int32_t intDesc, hwc2_callback_data_t callbackData,
+ hwc2_function_pointer_t pointer) {
+ auto descriptor = static_cast<HWC2::Callback>(intDesc);
+ auto error = getAdapter(device)->registerCallback(descriptor,
+ callbackData, pointer);
+ return static_cast<int32_t>(error);
+ }
+
+ // Display functions
+
+ class Layer;
+
+ class SortLayersByZ {
+ public:
+ bool operator()(const std::shared_ptr<Layer>& lhs,
+ const std::shared_ptr<Layer>& rhs) const;
+ };
+
+ // The semantics of the fences returned by the device differ between
+ // hwc1.set() and hwc2.present(). Read hwcomposer.h and hwcomposer2.h
+ // for more information.
+ //
+ // Release fences in hwc1 are obtained on set() for a frame n and signaled
+ // when the layer buffer is not needed for read operations anymore
+ // (typically on frame n+1). In HWC2, release fences are obtained with a
+ // special call after present() for frame n. These fences signal
+ // on frame n: More specifically, the fence for a given buffer provided in
+ // frame n will signal when the prior buffer is no longer required.
+ //
+ // A retire fence (HWC1) is signaled when a composition is replaced
+ // on the panel whereas a present fence (HWC2) is signaled when a
+ // composition starts to be displayed on a panel.
+ //
+ // The HWC2to1Adapter emulates the new fence semantics for a frame
+ // n by returning the fence from frame n-1. For frame 0, the adapter
+ // returns NO_FENCE.
+ class DeferredFence {
+ public:
+ DeferredFence()
+ : mFences({MiniFence::NO_FENCE, MiniFence::NO_FENCE}) {}
+
+ void add(int32_t fenceFd) {
+ mFences.emplace(new MiniFence(fenceFd));
+ mFences.pop();
+ }
+
+ const sp<MiniFence>& get() const {
+ return mFences.front();
+ }
+
+ private:
+ // There are always two fences in this queue.
+ std::queue<sp<MiniFence>> mFences;
+ };
+
+ class FencedBuffer {
+ public:
+ FencedBuffer() : mBuffer(nullptr), mFence(MiniFence::NO_FENCE) {}
+
+ void setBuffer(buffer_handle_t buffer) { mBuffer = buffer; }
+ void setFence(int fenceFd) { mFence = new MiniFence(fenceFd); }
+
+ buffer_handle_t getBuffer() const { return mBuffer; }
+ int getFence() const { return mFence->dup(); }
+
+ private:
+ buffer_handle_t mBuffer;
+ sp<MiniFence> mFence;
+ };
+
+ class Display {
+ public:
+ Display(CfHWC2& device, HWC2::DisplayType type);
+
+ hwc2_display_t getId() const { return mId; }
+ CfHWC2& getDevice() const { return mDevice; }
+
+ // Does not require locking because it is set before adding the
+ // Displays to the Adapter's list of displays
+ void setHwc1Id(int32_t id) { mHwc1Id = id; }
+ int32_t getHwc1Id() const { return mHwc1Id; }
+
+ // HWC2 Display functions
+ HWC2::Error acceptChanges();
+ HWC2::Error createLayer(hwc2_layer_t* outLayerId);
+ HWC2::Error destroyLayer(hwc2_layer_t layerId);
+ HWC2::Error getActiveConfig(hwc2_config_t* outConfigId);
+ HWC2::Error getAttribute(hwc2_config_t configId,
+ HWC2::Attribute attribute, int32_t* outValue);
+ HWC2::Error getChangedCompositionTypes(uint32_t* outNumElements,
+ hwc2_layer_t* outLayers, int32_t* outTypes);
+ HWC2::Error getColorModes(uint32_t* outNumModes, int32_t* outModes);
+ HWC2::Error getConfigs(uint32_t* outNumConfigs,
+ hwc2_config_t* outConfigIds);
+ HWC2::Error getDozeSupport(int32_t* outSupport);
+ HWC2::Error getHdrCapabilities(uint32_t* outNumTypes,
+ int32_t* outTypes, float* outMaxLuminance,
+ float* outMaxAverageLuminance, float* outMinLuminance);
+ HWC2::Error getName(uint32_t* outSize, char* outName);
+ HWC2::Error getReleaseFences(uint32_t* outNumElements,
+ hwc2_layer_t* outLayers, int32_t* outFences);
+ HWC2::Error getRequests(int32_t* outDisplayRequests,
+ uint32_t* outNumElements, hwc2_layer_t* outLayers,
+ int32_t* outLayerRequests);
+ HWC2::Error getType(int32_t* outType);
+
+ // Since HWC1 "presents" (called "set" in HWC1) all Displays
+ // at once, the first call to any Display::present will trigger
+ // present() on all Displays in the Device. Subsequent calls without
+ // first calling validate() are noop (except for duping/returning
+ // the retire fence).
+ HWC2::Error present(int32_t* outRetireFence);
+
+ HWC2::Error setActiveConfig(hwc2_config_t configId);
+ HWC2::Error setClientTarget(buffer_handle_t target,
+ int32_t acquireFence, int32_t dataspace,
+ hwc_region_t damage);
+ HWC2::Error setColorMode(android_color_mode_t mode);
+ HWC2::Error setColorTransform(android_color_transform_t hint);
+ HWC2::Error setOutputBuffer(buffer_handle_t buffer,
+ int32_t releaseFence);
+ HWC2::Error setPowerMode(HWC2::PowerMode mode);
+ HWC2::Error setVsyncEnabled(HWC2::Vsync enabled);
+
+ // Since HWC1 "validates" (called "prepare" in HWC1) all Displays
+ // at once, the first call to any Display::validate() will trigger
+ // validate() on all other Displays in the Device.
+ HWC2::Error validate(uint32_t* outNumTypes,
+ uint32_t* outNumRequests);
+
+ HWC2::Error updateLayerZ(hwc2_layer_t layerId, uint32_t z);
+
+ HWC2::Error getClientTargetSupport(uint32_t width, uint32_t height,
+ int32_t format, int32_t dataspace);
+
+ // 2.3 required functions
+ HWC2::Error getDisplayIdentificationData(uint8_t* outPort,
+ uint32_t* outDataSize, uint8_t* outData);
+ HWC2::Error getDisplayCapabilities(uint32_t* outNumCapabilities,
+ uint32_t* outCapabilities);
+ HWC2::Error getDisplayBrightnessSupport(bool *out_support);
+ HWC2::Error setDisplayBrightness(float brightness);
+
+ // Read configs from HWC1 device
+ void populateConfigs();
+
+ // Set configs for a virtual display
+ void populateConfigs(uint32_t width, uint32_t height);
+
+ bool prepare();
+
+ // Called after hwc.prepare() with responses from the device.
+ void generateChanges();
+
+ bool hasChanges() const;
+ HWC2::Error set(hwc_display_contents_1& hwcContents);
+ void addRetireFence(int fenceFd);
+ void addReleaseFences(const hwc_display_contents_1& hwcContents);
+
+ bool hasColorTransform() const;
+
+ std::string dump() const;
+
+ // Return a rect from the pool allocated during validate()
+ hwc_rect_t* GetRects(size_t numRects);
+
+ hwc_display_contents_1* getDisplayContents();
+
+ void markGeometryChanged() { mGeometryChanged = true; }
+ void resetGeometryMarker() { mGeometryChanged = false;}
+ private:
+ class Config {
+ public:
+ Config(Display& display)
+ : mDisplay(display),
+ mId(0),
+ mAttributes() {}
+
+ bool isOnDisplay(const Display& display) const {
+ return display.getId() == mDisplay.getId();
+ }
+
+ void setAttribute(HWC2::Attribute attribute, int32_t value);
+ int32_t getAttribute(HWC2::Attribute attribute) const;
+
+ void setHwc1Id(uint32_t id);
+ bool hasHwc1Id(uint32_t id) const;
+ HWC2::Error getColorModeForHwc1Id(uint32_t id,
+ android_color_mode_t *outMode) const;
+ HWC2::Error getHwc1IdForColorMode(android_color_mode_t mode,
+ uint32_t* outId) const;
+
+ void setId(hwc2_config_t id) { mId = id; }
+ hwc2_config_t getId() const { return mId; }
+
+ // Attempts to merge two configs that differ only in color
+ // mode. Returns whether the merge was successful
+ bool merge(const Config& other);
+
+ std::set<android_color_mode_t> getColorModes() const;
+
+ // splitLine divides the output into two lines suitable for
+ // dumpsys SurfaceFlinger
+ std::string toString(bool splitLine = false) const;
+
+ private:
+ Display& mDisplay;
+ hwc2_config_t mId;
+ std::unordered_map<HWC2::Attribute, int32_t> mAttributes;
+
+ // Maps from color transform to HWC1 config ID
+ std::unordered_map<android_color_mode_t, uint32_t> mHwc1Ids;
+ };
+
+ // Stores changes requested from the device upon calling prepare().
+ // Handles change request to:
+ // - Layer composition type.
+ // - Layer hints.
+ class Changes {
+ public:
+ uint32_t getNumTypes() const {
+ return static_cast<uint32_t>(mTypeChanges.size());
+ }
+
+ uint32_t getNumLayerRequests() const {
+ return static_cast<uint32_t>(mLayerRequests.size());
+ }
+
+ const std::unordered_map<hwc2_layer_t, HWC2::Composition>&
+ getTypeChanges() const {
+ return mTypeChanges;
+ }
+
+ const std::unordered_map<hwc2_layer_t, HWC2::LayerRequest>&
+ getLayerRequests() const {
+ return mLayerRequests;
+ }
+
+ void addTypeChange(hwc2_layer_t layerId,
+ HWC2::Composition type) {
+ mTypeChanges.insert({layerId, type});
+ }
+
+ void clearTypeChanges() { mTypeChanges.clear(); }
+
+ void addLayerRequest(hwc2_layer_t layerId,
+ HWC2::LayerRequest request) {
+ mLayerRequests.insert({layerId, request});
+ }
+
+ private:
+ std::unordered_map<hwc2_layer_t, HWC2::Composition>
+ mTypeChanges;
+ std::unordered_map<hwc2_layer_t, HWC2::LayerRequest>
+ mLayerRequests;
+ };
+
+ std::shared_ptr<const Config>
+ getConfig(hwc2_config_t configId) const;
+
+ void populateColorModes();
+ void initializeActiveConfig();
+
+ // Creates a bi-directional mapping between index in HWC1
+ // prepare/set array and Layer object. Stores mapping in
+ // mHwc1LayerMap and also updates Layer's attribute mHwc1Id.
+ void assignHwc1LayerIds();
+
+ // Called after a response to prepare() has been received:
+ // Ingest composition type changes requested by the device.
+ void updateTypeChanges(const struct hwc_layer_1& hwc1Layer,
+ const Layer& layer);
+
+ // Called after a response to prepare() has been received:
+ // Ingest layer hint changes requested by the device.
+ void updateLayerRequests(const struct hwc_layer_1& hwc1Layer,
+ const Layer& layer);
+
+ // Set all fields in HWC1 comm array for layer containing the
+ // HWC_FRAMEBUFFER_TARGET (always the last layer).
+ void prepareFramebufferTarget();
+
+ // Display ID generator.
+ static std::atomic<hwc2_display_t> sNextId;
+ const hwc2_display_t mId;
+
+
+ CfHWC2& mDevice;
+
+ // The state of this display should only be modified from
+ // SurfaceFlinger's main loop, with the exception of when dump is
+ // called. To prevent a bad state from crashing us during a dump
+ // call, all public calls into Display must acquire this mutex.
+ //
+ // It is recursive because we don't want to deadlock in validate
+ // (or present) when we call CfHWC2::prepareAllDisplays
+ // (or setAllDisplays), which calls back into Display functions
+ // which require locking.
+ mutable std::recursive_mutex mStateMutex;
+
+ // Allocate RAM able to store all layers and rects used for
+ // communication with HWC1. Place allocated RAM in variable
+ // mHwc1RequestedContents.
+ void allocateRequestedContents();
+
+ // Array of structs exchanged between client and hwc1 device.
+ // Sent to device upon calling prepare().
+ std::unique_ptr<hwc_display_contents_1> mHwc1RequestedContents;
+ private:
+ DeferredFence mRetireFence;
+
+ // Will only be non-null after the Display has been validated and
+ // before it has been presented
+ std::unique_ptr<Changes> mChanges;
+
+ int32_t mHwc1Id;
+
+ std::vector<std::shared_ptr<Config>> mConfigs;
+ std::shared_ptr<const Config> mActiveConfig;
+ std::set<android_color_mode_t> mColorModes;
+ android_color_mode_t mActiveColorMode;
+ std::string mName;
+ HWC2::DisplayType mType;
+ HWC2::PowerMode mPowerMode;
+ HWC2::Vsync mVsyncEnabled;
+
+ // Used to populate HWC1 HWC_FRAMEBUFFER_TARGET layer
+ FencedBuffer mClientTarget;
+
+
+ FencedBuffer mOutputBuffer;
+
+ bool mHasColorTransform;
+
+ // All layers this Display is aware of.
+ std::multiset<std::shared_ptr<Layer>, SortLayersByZ> mLayers;
+
+ // Mapping between layer index in array of hwc_display_contents_1*
+ // passed to HWC1 during validate/set and Layer object.
+ std::unordered_map<size_t, std::shared_ptr<Layer>> mHwc1LayerMap;
+
+ // All communication with HWC1 via prepare/set is done with one
+ // alloc. This pointer is pointing to a pool of hwc_rect_t.
+ size_t mNumAvailableRects;
+ hwc_rect_t* mNextAvailableRect;
+
+ // True if any of the Layers contained in this Display have been
+ // updated with anything other than a buffer since last call to
+ // Display::set()
+ bool mGeometryChanged;
+ };
+
+ // Utility template calling a Display object method directly based on the
+ // hwc2_display_t displayId parameter.
+ template <typename ...Args>
+ static int32_t callDisplayFunction(hwc2_device_t* device,
+ hwc2_display_t displayId, HWC2::Error (Display::*member)(Args...),
+ Args... args) {
+ auto display = getAdapter(device)->getDisplay(displayId);
+ if (!display) {
+ return static_cast<int32_t>(HWC2::Error::BadDisplay);
+ }
+ auto error = ((*display).*member)(std::forward<Args>(args)...);
+ return static_cast<int32_t>(error);
+ }
+
+ template <typename MF, MF memFunc, typename ...Args>
+ static int32_t displayHook(hwc2_device_t* device, hwc2_display_t displayId,
+ Args... args) {
+ return CfHWC2::callDisplayFunction(device, displayId, memFunc,
+ std::forward<Args>(args)...);
+ }
+
+ static int32_t getDisplayAttributeHook(hwc2_device_t* device,
+ hwc2_display_t display, hwc2_config_t config,
+ int32_t intAttribute, int32_t* outValue) {
+ auto attribute = static_cast<HWC2::Attribute>(intAttribute);
+ return callDisplayFunction(device, display, &Display::getAttribute,
+ config, attribute, outValue);
+ }
+
+ static int32_t setColorTransformHook(hwc2_device_t* device,
+ hwc2_display_t display, const float* /*matrix*/,
+ int32_t /*android_color_transform_t*/ intHint) {
+ // We intentionally throw away the matrix, because if the hint is
+ // anything other than IDENTITY, we have to fall back to client
+ // composition anyway
+ auto hint = static_cast<android_color_transform_t>(intHint);
+ return callDisplayFunction(device, display, &Display::setColorTransform,
+ hint);
+ }
+
+ static int32_t setColorModeHook(hwc2_device_t* device,
+ hwc2_display_t display, int32_t /*android_color_mode_t*/ intMode) {
+ auto mode = static_cast<android_color_mode_t>(intMode);
+ return callDisplayFunction(device, display, &Display::setColorMode,
+ mode);
+ }
+
+ static int32_t setPowerModeHook(hwc2_device_t* device,
+ hwc2_display_t display, int32_t intMode) {
+ auto mode = static_cast<HWC2::PowerMode>(intMode);
+ return callDisplayFunction(device, display, &Display::setPowerMode,
+ mode);
+ }
+
+ static int32_t setVsyncEnabledHook(hwc2_device_t* device,
+ hwc2_display_t display, int32_t intEnabled) {
+ auto enabled = static_cast<HWC2::Vsync>(intEnabled);
+ return callDisplayFunction(device, display, &Display::setVsyncEnabled,
+ enabled);
+ }
+
+ class Layer {
+ public:
+ explicit Layer(Display& display);
+
+ bool operator==(const Layer& other) { return mId == other.mId; }
+ bool operator!=(const Layer& other) { return !(*this == other); }
+
+ hwc2_layer_t getId() const { return mId; }
+ Display& getDisplay() const { return mDisplay; }
+
+ // HWC2 Layer functions
+ HWC2::Error setBuffer(buffer_handle_t buffer, int32_t acquireFence);
+ HWC2::Error setCursorPosition(int32_t x, int32_t y);
+ HWC2::Error setSurfaceDamage(hwc_region_t damage);
+
+ // HWC2 Layer state functions
+ HWC2::Error setBlendMode(HWC2::BlendMode mode);
+ HWC2::Error setColor(hwc_color_t color);
+ HWC2::Error setCompositionType(HWC2::Composition type);
+ HWC2::Error setDataspace(android_dataspace_t dataspace);
+ HWC2::Error setDisplayFrame(hwc_rect_t frame);
+ HWC2::Error setPlaneAlpha(float alpha);
+ HWC2::Error setSidebandStream(const native_handle_t* stream);
+ HWC2::Error setSourceCrop(hwc_frect_t crop);
+ HWC2::Error setTransform(HWC2::Transform transform);
+ HWC2::Error setVisibleRegion(hwc_region_t visible);
+ HWC2::Error setZ(uint32_t z);
+
+ HWC2::Composition getCompositionType() const {
+ return mCompositionType;
+ }
+ uint32_t getZ() const { return mZ; }
+
+ void addReleaseFence(int fenceFd);
+ const sp<MiniFence>& getReleaseFence() const;
+
+ void setHwc1Id(size_t id) { mHwc1Id = id; }
+ size_t getHwc1Id() const { return mHwc1Id; }
+
+ // Write state to HWC1 communication struct.
+ void applyState(struct hwc_layer_1& hwc1Layer);
+
+ std::string dump() const;
+
+ std::size_t getNumVisibleRegions() { return mVisibleRegion.size(); }
+
+ std::size_t getNumSurfaceDamages() { return mSurfaceDamage.size(); }
+
+ // True if a layer cannot be properly rendered by the device due
+ // to usage of SolidColor (a.k.a BackgroundColor in HWC1).
+ bool hasUnsupportedBackgroundColor() {
+ return (mCompositionType == HWC2::Composition::SolidColor &&
+ !mDisplay.getDevice().supportsBackgroundColor());
+ }
+ private:
+ void applyCommonState(struct hwc_layer_1& hwc1Layer);
+ void applySolidColorState(struct hwc_layer_1& hwc1Layer);
+ void applySidebandState(struct hwc_layer_1& hwc1Layer);
+ void applyBufferState(struct hwc_layer_1& hwc1Layer);
+ void applyCompositionType(struct hwc_layer_1& hwc1Layer);
+
+ static std::atomic<hwc2_layer_t> sNextId;
+ const hwc2_layer_t mId;
+ Display& mDisplay;
+
+ FencedBuffer mBuffer;
+ std::vector<hwc_rect_t> mSurfaceDamage;
+
+ HWC2::BlendMode mBlendMode;
+ hwc_color_t mColor;
+ HWC2::Composition mCompositionType;
+ hwc_rect_t mDisplayFrame;
+ float mPlaneAlpha;
+ const native_handle_t* mSidebandStream;
+ hwc_frect_t mSourceCrop;
+ HWC2::Transform mTransform;
+ std::vector<hwc_rect_t> mVisibleRegion;
+
+ uint32_t mZ;
+
+ DeferredFence mReleaseFence;
+
+ size_t mHwc1Id;
+ bool mHasUnsupportedPlaneAlpha;
+ };
+
+ // Utility tempate calling a Layer object method based on ID parameters:
+ // hwc2_display_t displayId
+ // and
+ // hwc2_layer_t layerId
+ template <typename ...Args>
+ static int32_t callLayerFunction(hwc2_device_t* device,
+ hwc2_display_t displayId, hwc2_layer_t layerId,
+ HWC2::Error (Layer::*member)(Args...), Args... args) {
+ auto result = getAdapter(device)->getLayer(displayId, layerId);
+ auto error = std::get<HWC2::Error>(result);
+ if (error == HWC2::Error::None) {
+ auto layer = std::get<Layer*>(result);
+ error = ((*layer).*member)(std::forward<Args>(args)...);
+ }
+ return static_cast<int32_t>(error);
+ }
+
+ template <typename MF, MF memFunc, typename ...Args>
+ static int32_t layerHook(hwc2_device_t* device, hwc2_display_t displayId,
+ hwc2_layer_t layerId, Args... args) {
+ return CfHWC2::callLayerFunction(device, displayId, layerId,
+ memFunc, std::forward<Args>(args)...);
+ }
+
+ // Layer state functions
+
+ static int32_t setLayerBlendModeHook(hwc2_device_t* device,
+ hwc2_display_t display, hwc2_layer_t layer, int32_t intMode) {
+ auto mode = static_cast<HWC2::BlendMode>(intMode);
+ return callLayerFunction(device, display, layer,
+ &Layer::setBlendMode, mode);
+ }
+
+ static int32_t setLayerCompositionTypeHook(hwc2_device_t* device,
+ hwc2_display_t display, hwc2_layer_t layer, int32_t intType) {
+ auto type = static_cast<HWC2::Composition>(intType);
+ return callLayerFunction(device, display, layer,
+ &Layer::setCompositionType, type);
+ }
+
+ static int32_t setLayerDataspaceHook(hwc2_device_t* device,
+ hwc2_display_t display, hwc2_layer_t layer, int32_t intDataspace) {
+ auto dataspace = static_cast<android_dataspace_t>(intDataspace);
+ return callLayerFunction(device, display, layer, &Layer::setDataspace,
+ dataspace);
+ }
+
+ static int32_t setLayerTransformHook(hwc2_device_t* device,
+ hwc2_display_t display, hwc2_layer_t layer, int32_t intTransform) {
+ auto transform = static_cast<HWC2::Transform>(intTransform);
+ return callLayerFunction(device, display, layer, &Layer::setTransform,
+ transform);
+ }
+
+ static int32_t setLayerZOrderHook(hwc2_device_t* device,
+ hwc2_display_t display, hwc2_layer_t layer, uint32_t z) {
+ return callDisplayFunction(device, display, &Display::updateLayerZ,
+ layer, z);
+ }
+
+ // Adapter internals
+
+ void populateCapabilities();
+ Display* getDisplay(hwc2_display_t id);
+ std::tuple<Layer*, HWC2::Error> getLayer(hwc2_display_t displayId,
+ hwc2_layer_t layerId);
+ void populatePrimary();
+
+ bool prepareAllDisplays();
+ std::vector<struct hwc_display_contents_1*> mHwc1Contents;
+ HWC2::Error setAllDisplays();
+
+ // Callbacks
+ void hwc1Invalidate();
+ void hwc1Vsync(int hwc1DisplayId, int64_t timestamp);
+ void hwc1Hotplug(int hwc1DisplayId, int connected);
+
+ // These are set in the constructor and before any asynchronous events are
+ // possible
+
+ struct hwc_composer_device_1* const mHwc1Device;
+ const uint8_t mHwc1MinorVersion;
+ bool mHwc1SupportsVirtualDisplays;
+ bool mHwc1SupportsBackgroundColor;
+
+ class Callbacks;
+ const std::unique_ptr<Callbacks> mHwc1Callbacks;
+
+ std::unordered_set<HWC2::Capability> mCapabilities;
+
+ // These are only accessed from the main SurfaceFlinger thread (not from
+ // callbacks or dump
+
+ std::map<hwc2_layer_t, std::shared_ptr<Layer>> mLayers;
+
+ // A HWC1 supports only one virtual display.
+ std::shared_ptr<Display> mHwc1VirtualDisplay;
+
+ // These are potentially accessed from multiple threads, and are protected
+ // by this mutex. This needs to be recursive, since the HWC1 implementation
+ // can call back into the invalidate callback on the same thread that is
+ // calling prepare.
+ std::recursive_timed_mutex mStateMutex;
+
+ struct CallbackInfo {
+ hwc2_callback_data_t data;
+ hwc2_function_pointer_t pointer;
+ };
+ std::unordered_map<HWC2::Callback, CallbackInfo> mCallbacks;
+ bool mHasPendingInvalidate;
+
+ // There is a small gap between the time the HWC1 module is started and
+ // when the callbacks for vsync and hotplugs are registered by the
+ // CfHWC2. To prevent losing events they are stored in these arrays
+ // and fed to the callback as soon as possible.
+ std::vector<std::pair<int, int64_t>> mPendingVsyncs;
+ std::vector<std::pair<int, int>> mPendingHotplugs;
+
+ // Mapping between HWC1 display id and Display objects.
+ std::map<hwc2_display_t, std::shared_ptr<Display>> mDisplays;
+
+ // Map HWC1 display type (HWC_DISPLAY_PRIMARY, HWC_DISPLAY_EXTERNAL,
+ // HWC_DISPLAY_VIRTUAL) to Display IDs generated by CfHWC2 objects.
+ std::unordered_map<int, hwc2_display_t> mHwc1DisplayMap;
+};
+
+} // namespace android
+
+#endif
diff --git a/host/libs/config/kernel_args.h b/guest/hals/hwcomposer/cutf_cvm/MiniFence.cpp
index 59b9e8e77..ecfb0635c 100644
--- a/host/libs/config/kernel_args.h
+++ b/guest/hals/hwcomposer/cutf_cvm/MiniFence.cpp
@@ -14,16 +14,29 @@
* limitations under the License.
*/
-#pragma once
+#include "MiniFence.h"
-#include <string>
-#include <vector>
+#include <unistd.h>
-#include "host/libs/config/cuttlefish_config.h"
+namespace android {
-namespace cuttlefish {
+const sp<MiniFence> MiniFence::NO_FENCE = sp<MiniFence>(new MiniFence);
-std::vector<std::string> KernelCommandLineFromConfig(
- const CuttlefishConfig& config);
+MiniFence::MiniFence() :
+ mFenceFd(-1) {
+}
-} // namespace cuttlefish
+MiniFence::MiniFence(int fenceFd) :
+ mFenceFd(fenceFd) {
+}
+
+MiniFence::~MiniFence() {
+ if (mFenceFd != -1) {
+ close(mFenceFd);
+ }
+}
+
+int MiniFence::dup() const {
+ return ::dup(mFenceFd);
+}
+}
diff --git a/guest/hals/hwcomposer/cutf_cvm/MiniFence.h b/guest/hals/hwcomposer/cutf_cvm/MiniFence.h
new file mode 100644
index 000000000..34fbdd8b0
--- /dev/null
+++ b/guest/hals/hwcomposer/cutf_cvm/MiniFence.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2020 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 MINIFENCE_H
+#define MINIFENCE_H
+
+#include <utils/RefBase.h>
+
+namespace android {
+
+/* MiniFence is a minimal re-implementation of Fence from libui. It exists to
+ * avoid linking the HWC2on1Adapter to libui and satisfy Treble requirements.
+ */
+class MiniFence : public LightRefBase<MiniFence> {
+public:
+ static const sp<MiniFence> NO_FENCE;
+
+ // Construct a new MiniFence object with an invalid file descriptor.
+ MiniFence();
+
+ // Construct a new MiniFence object to manage a given fence file descriptor.
+ // When the new MiniFence object is destructed the file descriptor will be
+ // closed.
+ explicit MiniFence(int fenceFd);
+
+ // Not copyable or movable.
+ MiniFence(const MiniFence& rhs) = delete;
+ MiniFence& operator=(const MiniFence& rhs) = delete;
+ MiniFence(MiniFence&& rhs) = delete;
+ MiniFence& operator=(MiniFence&& rhs) = delete;
+
+ // Return a duplicate of the fence file descriptor. The caller is
+ // responsible for closing the returned file descriptor. On error, -1 will
+ // be returned and errno will indicate the problem.
+ int dup() const;
+
+private:
+ // Only allow instantiation using ref counting.
+ friend class LightRefBase<MiniFence>;
+ ~MiniFence();
+
+ int mFenceFd;
+
+};
+}
+#endif //MINIFENCE_H
diff --git a/guest/hals/hwcomposer/cutf_cvm/hwcomposer.cpp b/guest/hals/hwcomposer/cutf_cvm/hwcomposer.cpp
new file mode 100644
index 000000000..976a68c6e
--- /dev/null
+++ b/guest/hals/hwcomposer/cutf_cvm/hwcomposer.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "hwc.cutf_cvm"
+
+#include <cutils/properties.h>
+#include <hardware/hardware.h>
+#include <hardware/hwcomposer.h>
+#include <hardware/hwcomposer_defs.h>
+#include <log/log.h>
+
+#include "guest/hals/hwcomposer/common/hwcomposer.h"
+
+#include "guest/hals/hwcomposer/cutf_cvm/vsocket_screen_view.h"
+
+static int hwc_open(const struct hw_module_t* module, const char* name,
+ struct hw_device_t** device) {
+ std::unique_ptr<cvd::ScreenView> screen_view(new cvd::VsocketScreenView());
+ if (!screen_view) {
+ ALOGE("Failed to instantiate screen view");
+ return -1;
+ }
+
+ return cvd::cvd_hwc_open(std::move(screen_view), module, name, device);
+}
+
+static struct hw_module_methods_t hwc_module_methods = {
+ hwc_open,
+};
+
+hwc_module_t HAL_MODULE_INFO_SYM = {{HARDWARE_MODULE_TAG,
+ HWC_MODULE_API_VERSION_0_1,
+ HARDWARE_HAL_API_VERSION,
+ HWC_HARDWARE_MODULE_ID,
+ "VSOCKET hwcomposer module",
+ "Google",
+ &hwc_module_methods,
+ NULL,
+ {0}}};
diff --git a/guest/hals/hwcomposer/cutf_cvm/vsocket_screen_view.cpp b/guest/hals/hwcomposer/cutf_cvm/vsocket_screen_view.cpp
new file mode 100644
index 000000000..16185b5d0
--- /dev/null
+++ b/guest/hals/hwcomposer/cutf_cvm/vsocket_screen_view.cpp
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "vsock_hwc"
+
+#include "guest/hals/hwcomposer/cutf_cvm/vsocket_screen_view.h"
+
+#include <cutils/properties.h>
+#include <log/log.h>
+
+#include "common/libs/device_config/device_config.h"
+
+namespace cvd {
+
+VsocketScreenView::VsocketScreenView()
+ : broadcast_thread_([this]() { BroadcastLoop(); }) {
+ GetScreenParameters();
+ // inner_buffer needs to be initialized after the final values of the screen
+ // parameters are set (either from the config server or default).
+ inner_buffer_ = std::vector<char>(buffer_size() * 8);
+}
+
+VsocketScreenView::~VsocketScreenView() {
+ running_ = false;
+ broadcast_thread_.join();
+}
+
+void VsocketScreenView::GetScreenParameters() {
+ auto device_config = cvd::DeviceConfig::Get();
+ if (!device_config) {
+ ALOGI(
+ "Failed to obtain device configuration from server, running in "
+ "headless mode");
+ // It is impossible to ensure host and guest agree on the screen parameters
+ // if these could not be read from the host configuration server. It's best
+ // to not attempt to send frames in this case.
+ running_ = false;
+ // Do a phony Broadcast to ensure the broadcaster thread exits.
+ Broadcast(-1);
+ return;
+ }
+ x_res_ = device_config->screen_x_res();
+ y_res_ = device_config->screen_y_res();
+ dpi_ = device_config->screen_dpi();
+ refresh_rate_ = device_config->screen_refresh_rate();
+ ALOGI("Received screen parameters: res=%dx%d, dpi=%d, freq=%d", x_res_,
+ y_res_, dpi_, refresh_rate_);
+}
+
+bool VsocketScreenView::ConnectToScreenServer() {
+ auto vsock_frames_port = property_get_int64("ro.boot.vsock_frames_port", -1);
+ if (vsock_frames_port <= 0) {
+ ALOGI("No screen server configured, operating on headless mode");
+ return false;
+ }
+
+ screen_server_ = cvd::SharedFD::VsockClient(
+ 2, static_cast<unsigned int>(vsock_frames_port), SOCK_STREAM);
+ if (!screen_server_->IsOpen()) {
+ ALOGE("Unable to connect to screen server: %s", screen_server_->StrError());
+ return false;
+ }
+
+ return true;
+}
+
+void VsocketScreenView::BroadcastLoop() {
+ auto connected = ConnectToScreenServer();
+ if (!connected) {
+ ALOGE(
+ "Broadcaster thread exiting due to no connection to screen server. "
+ "Compositions will occur, but frames won't be sent anywhere");
+ return;
+ }
+ int current_seq = 0;
+ int current_offset;
+ ALOGI("Broadcaster thread loop starting");
+ while (true) {
+ {
+ std::unique_lock<std::mutex> lock(mutex_);
+ while (running_ && current_seq == current_seq_) {
+ cond_var_.wait(lock);
+ }
+ if (!running_) {
+ ALOGI("Broadcaster thread exiting");
+ return;
+ }
+ current_offset = current_offset_;
+ current_seq = current_seq_;
+ }
+ int32_t size = buffer_size();
+ screen_server_->Write(&size, sizeof(size));
+ auto buff = static_cast<char*>(GetBuffer(current_offset));
+ while (size > 0) {
+ auto written = screen_server_->Write(buff, size);
+ if (written == -1) {
+ ALOGE("Broadcaster thread failed to write frame: %s", strerror(errno));
+ break;
+ }
+ size -= written;
+ buff += written;
+ }
+ }
+}
+
+void VsocketScreenView::Broadcast(int offset, const CompositionStats*) {
+ std::lock_guard<std::mutex> lock(mutex_);
+ current_offset_ = offset;
+ current_seq_++;
+ cond_var_.notify_all();
+}
+
+void* VsocketScreenView::GetBuffer(int buffer_id) {
+ return &inner_buffer_[buffer_size() * buffer_id];
+}
+
+int32_t VsocketScreenView::x_res() const { return x_res_; }
+int32_t VsocketScreenView::y_res() const { return y_res_; }
+int32_t VsocketScreenView::dpi() const { return dpi_; }
+int32_t VsocketScreenView::refresh_rate() const { return refresh_rate_; }
+
+int VsocketScreenView::num_buffers() const {
+ return inner_buffer_.size() / buffer_size();
+}
+
+} // namespace cvd
diff --git a/guest/hals/hwcomposer/cutf_cvm/vsocket_screen_view.h b/guest/hals/hwcomposer/cutf_cvm/vsocket_screen_view.h
new file mode 100644
index 000000000..0d6d90af6
--- /dev/null
+++ b/guest/hals/hwcomposer/cutf_cvm/vsocket_screen_view.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <condition_variable>
+#include <functional>
+#include <mutex>
+#include <thread>
+#include <vector>
+
+#include "common/libs/fs/shared_fd.h"
+#include "guest/hals/hwcomposer/common/screen_view.h"
+
+namespace cvd {
+
+class VsocketScreenView : public ScreenView {
+ public:
+ VsocketScreenView();
+ virtual ~VsocketScreenView();
+
+ void Broadcast(int buffer_id,
+ const CompositionStats* stats = nullptr) override;
+ void* GetBuffer(int fb_index) override;
+
+ int32_t x_res() const override;
+ int32_t y_res() const override;
+ int32_t dpi() const override;
+ int32_t refresh_rate() const override;
+
+ int num_buffers() const override;
+
+ private:
+ bool ConnectToScreenServer();
+ void GetScreenParameters();
+ void BroadcastLoop();
+
+ std::vector<char> inner_buffer_;
+ cvd::SharedFD screen_server_;
+ std::thread broadcast_thread_;
+ int current_offset_ = 0;
+ int current_seq_ = 0;
+ std::mutex mutex_;
+ std::condition_variable cond_var_;
+ bool running_ = true;
+ int32_t x_res_{720};
+ int32_t y_res_{1280};
+ int32_t dpi_{160};
+ int32_t refresh_rate_{60};
+};
+
+} // namespace cvd
diff --git a/guest/hals/keymaster/OWNERS b/guest/hals/keymaster/OWNERS
deleted file mode 100644
index fb015cbb1..000000000
--- a/guest/hals/keymaster/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-include platform/system/keymaster:/OWNERS
diff --git a/guest/hals/keymaster/remote/Android.bp b/guest/hals/keymaster/remote/Android.bp
deleted file mode 100644
index 805a803fb..000000000
--- a/guest/hals/keymaster/remote/Android.bp
+++ /dev/null
@@ -1,53 +0,0 @@
-//
-// Copyright (C) 2020 The Android Open-Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-cc_binary {
- name: "android.hardware.keymaster@4.1-service.remote",
- defaults: ["hidl_defaults", "cuttlefish_guest_only"],
- relative_install_path: "hw",
- vendor: true,
- init_rc: ["android.hardware.keymaster@4.1-service.remote.rc"],
- srcs: [
- "service4.cpp",
- "remote_keymaster4_device.cpp",
- "remote_keymaster.cpp",
- ],
-
- static_libs: [
- "libgflags",
- ],
-
- shared_libs: [
- "android.hardware.keymaster@4.1",
- "libbase",
- "libcutils",
- "libcuttlefish_fs",
- "libcuttlefish_security",
- "libdl",
- "libhardware",
- "libhidlbase",
- "libkeymaster4",
- "libkeymaster_messages",
- "liblog",
- "libtrusty",
- "libutils",
- ],
-
- vintf_fragments: ["android.hardware.keymaster@4.1-service.remote.xml"],
-}
diff --git a/guest/hals/keymaster/remote/android.hardware.keymaster@4.1-service.remote.rc b/guest/hals/keymaster/remote/android.hardware.keymaster@4.1-service.remote.rc
deleted file mode 100644
index d8ef4e164..000000000
--- a/guest/hals/keymaster/remote/android.hardware.keymaster@4.1-service.remote.rc
+++ /dev/null
@@ -1,6 +0,0 @@
-service vendor.keymaster-4-1 /vendor/bin/hw/android.hardware.keymaster@4.1-service.remote
- interface android.hardware.keymaster@4.0::IKeymasterDevice default
- interface android.hardware.keymaster@4.1::IKeymasterDevice default
- class early_hal
- user system
- group system drmrpc
diff --git a/guest/hals/keymaster/remote/android.hardware.keymaster@4.1-service.remote.xml b/guest/hals/keymaster/remote/android.hardware.keymaster@4.1-service.remote.xml
deleted file mode 100644
index af27c1ea5..000000000
--- a/guest/hals/keymaster/remote/android.hardware.keymaster@4.1-service.remote.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<manifest version="1.0" type="device">
- <hal format="hidl">
- <name>android.hardware.keymaster</name>
- <transport>hwbinder</transport>
- <fqname>@4.1::IKeymasterDevice/default</fqname>
- </hal>
-</manifest>
diff --git a/guest/hals/keymaster/remote/remote_keymaster.cpp b/guest/hals/keymaster/remote/remote_keymaster.cpp
deleted file mode 100644
index daf595622..000000000
--- a/guest/hals/keymaster/remote/remote_keymaster.cpp
+++ /dev/null
@@ -1,218 +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 "remote_keymaster.h"
-
-#include <android-base/logging.h>
-#include <keymaster/android_keymaster_messages.h>
-#include <keymaster/keymaster_configuration.h>
-
-namespace keymaster {
-
-RemoteKeymaster::RemoteKeymaster(cuttlefish::KeymasterChannel* channel)
- : channel_(channel) {}
-
-RemoteKeymaster::~RemoteKeymaster() {
-}
-
-void RemoteKeymaster::ForwardCommand(AndroidKeymasterCommand command, const Serializable& req,
- KeymasterResponse* rsp) {
- if (!channel_->SendRequest(command, req)) {
- LOG(ERROR) << "Failed to send keymaster message: " << command;
- rsp->error = KM_ERROR_UNKNOWN_ERROR;
- return;
- }
- auto response = channel_->ReceiveMessage();
- if (!response) {
- LOG(ERROR) << "Failed to receive keymaster response: " << command;
- rsp->error = KM_ERROR_UNKNOWN_ERROR;
- return;
- }
- const uint8_t* buffer = response->payload;
- const uint8_t* buffer_end = response->payload + response->payload_size;
- if (!rsp->Deserialize(&buffer, buffer_end)) {
- LOG(ERROR) << "Failed to deserialize keymaster response: " << command;
- rsp->error = KM_ERROR_UNKNOWN_ERROR;
- return;
- }
-}
-
-bool RemoteKeymaster::Initialize() {
- // We don't need to bother with GetVersion, because CF HAL and remote sides are always compiled
- // together, so will never disagree about message versions.
- ConfigureRequest req(message_version());
- req.os_version = GetOsVersion();
- req.os_patchlevel = GetOsPatchlevel();
-
- ConfigureResponse rsp(message_version());
- Configure(req, &rsp);
-
- if (rsp.error != KM_ERROR_OK) {
- LOG(ERROR) << "Failed to configure keymaster: " << rsp.error;
- return false;
- }
-
- return true;
-}
-
-void RemoteKeymaster::GetVersion(const GetVersionRequest& request, GetVersionResponse* response) {
- ForwardCommand(GET_VERSION, request, response);
-}
-
-void RemoteKeymaster::SupportedAlgorithms(const SupportedAlgorithmsRequest& request,
- SupportedAlgorithmsResponse* response) {
- ForwardCommand(GET_SUPPORTED_ALGORITHMS, request, response);
-}
-
-void RemoteKeymaster::SupportedBlockModes(const SupportedBlockModesRequest& request,
- SupportedBlockModesResponse* response) {
- ForwardCommand(GET_SUPPORTED_BLOCK_MODES, request, response);
-}
-
-void RemoteKeymaster::SupportedPaddingModes(const SupportedPaddingModesRequest& request,
- SupportedPaddingModesResponse* response) {
- ForwardCommand(GET_SUPPORTED_PADDING_MODES, request, response);
-}
-
-void RemoteKeymaster::SupportedDigests(const SupportedDigestsRequest& request,
- SupportedDigestsResponse* response) {
- ForwardCommand(GET_SUPPORTED_DIGESTS, request, response);
-}
-
-void RemoteKeymaster::SupportedImportFormats(const SupportedImportFormatsRequest& request,
- SupportedImportFormatsResponse* response) {
- ForwardCommand(GET_SUPPORTED_IMPORT_FORMATS, request, response);
-}
-
-void RemoteKeymaster::SupportedExportFormats(const SupportedExportFormatsRequest& request,
- SupportedExportFormatsResponse* response) {
- ForwardCommand(GET_SUPPORTED_EXPORT_FORMATS, request, response);
-}
-
-void RemoteKeymaster::AddRngEntropy(const AddEntropyRequest& request,
- AddEntropyResponse* response) {
- ForwardCommand(ADD_RNG_ENTROPY, request, response);
-}
-
-void RemoteKeymaster::Configure(const ConfigureRequest& request, ConfigureResponse* response) {
- ForwardCommand(CONFIGURE, request, response);
-}
-
-void RemoteKeymaster::GenerateKey(const GenerateKeyRequest& request,
- GenerateKeyResponse* response) {
- GenerateKeyRequest datedRequest(request.message_version);
- datedRequest.key_description = request.key_description;
-
- if (!request.key_description.Contains(TAG_CREATION_DATETIME)) {
- datedRequest.key_description.push_back(TAG_CREATION_DATETIME, java_time(time(NULL)));
- }
-
- ForwardCommand(GENERATE_KEY, datedRequest, response);
-}
-
-void RemoteKeymaster::GetKeyCharacteristics(const GetKeyCharacteristicsRequest& request,
- GetKeyCharacteristicsResponse* response) {
- ForwardCommand(GET_KEY_CHARACTERISTICS, request, response);
-}
-
-void RemoteKeymaster::ImportKey(const ImportKeyRequest& request, ImportKeyResponse* response) {
- ForwardCommand(IMPORT_KEY, request, response);
-}
-
-void RemoteKeymaster::ImportWrappedKey(const ImportWrappedKeyRequest& request,
- ImportWrappedKeyResponse* response) {
- ForwardCommand(IMPORT_WRAPPED_KEY, request, response);
-}
-
-void RemoteKeymaster::ExportKey(const ExportKeyRequest& request, ExportKeyResponse* response) {
- ForwardCommand(EXPORT_KEY, request, response);
-}
-
-void RemoteKeymaster::AttestKey(const AttestKeyRequest& request, AttestKeyResponse* response) {
- ForwardCommand(ATTEST_KEY, request, response);
-}
-
-void RemoteKeymaster::UpgradeKey(const UpgradeKeyRequest& request, UpgradeKeyResponse* response) {
- ForwardCommand(UPGRADE_KEY, request, response);
-}
-
-void RemoteKeymaster::DeleteKey(const DeleteKeyRequest& request, DeleteKeyResponse* response) {
- ForwardCommand(DELETE_KEY, request, response);
-}
-
-void RemoteKeymaster::DeleteAllKeys(const DeleteAllKeysRequest& request,
- DeleteAllKeysResponse* response) {
- ForwardCommand(DELETE_ALL_KEYS, request, response);
-}
-
-void RemoteKeymaster::BeginOperation(const BeginOperationRequest& request,
- BeginOperationResponse* response) {
- ForwardCommand(BEGIN_OPERATION, request, response);
-}
-
-void RemoteKeymaster::UpdateOperation(const UpdateOperationRequest& request,
- UpdateOperationResponse* response) {
- ForwardCommand(UPDATE_OPERATION, request, response);
-}
-
-void RemoteKeymaster::FinishOperation(const FinishOperationRequest& request,
- FinishOperationResponse* response) {
- ForwardCommand(FINISH_OPERATION, request, response);
-}
-
-void RemoteKeymaster::AbortOperation(const AbortOperationRequest& request,
- AbortOperationResponse* response) {
- ForwardCommand(ABORT_OPERATION, request, response);
-}
-
-GetHmacSharingParametersResponse RemoteKeymaster::GetHmacSharingParameters() {
- // Unused empty buffer to allow ForwardCommand to have something to serialize
- Buffer request;
- GetHmacSharingParametersResponse response(message_version());
- ForwardCommand(GET_HMAC_SHARING_PARAMETERS, request, &response);
- return response;
-}
-
-ComputeSharedHmacResponse RemoteKeymaster::ComputeSharedHmac(
- const ComputeSharedHmacRequest& request) {
- ComputeSharedHmacResponse response(message_version());
- ForwardCommand(COMPUTE_SHARED_HMAC, request, &response);
- return response;
-}
-
-VerifyAuthorizationResponse RemoteKeymaster::VerifyAuthorization(
- const VerifyAuthorizationRequest& request) {
- VerifyAuthorizationResponse response(message_version());
- ForwardCommand(VERIFY_AUTHORIZATION, request, &response);
- return response;
-}
-
-DeviceLockedResponse RemoteKeymaster::DeviceLocked(
- const DeviceLockedRequest& request) {
- DeviceLockedResponse response(message_version());
- ForwardCommand(DEVICE_LOCKED, request, &response);
- return response;
-}
-
-EarlyBootEndedResponse RemoteKeymaster::EarlyBootEnded() {
- // Unused empty buffer to allow ForwardCommand to have something to serialize
- Buffer request;
- EarlyBootEndedResponse response(message_version());
- ForwardCommand(EARLY_BOOT_ENDED, request, &response);
- return response;
-}
-
-} // namespace keymaster
diff --git a/guest/hals/keymaster/remote/remote_keymaster.h b/guest/hals/keymaster/remote/remote_keymaster.h
deleted file mode 100644
index 13c428f4e..000000000
--- a/guest/hals/keymaster/remote/remote_keymaster.h
+++ /dev/null
@@ -1,79 +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.
- */
-
-#ifndef REMOTE_KEYMASTER_H_
-#define REMOTE_KEYMASTER_H_
-
-#include <keymaster/android_keymaster_messages.h>
-
-#include "common/libs/security/keymaster_channel.h"
-
-namespace keymaster {
-
-class RemoteKeymaster {
- private:
- cuttlefish::KeymasterChannel* channel_;
-
- void ForwardCommand(
- AndroidKeymasterCommand command, const Serializable& req, KeymasterResponse* rsp);
- public:
- RemoteKeymaster(cuttlefish::KeymasterChannel*);
- ~RemoteKeymaster();
- bool Initialize();
- void GetVersion(const GetVersionRequest& request, GetVersionResponse* response);
- void SupportedAlgorithms(const SupportedAlgorithmsRequest& request,
- SupportedAlgorithmsResponse* response);
- void SupportedBlockModes(const SupportedBlockModesRequest& request,
- SupportedBlockModesResponse* response);
- void SupportedPaddingModes(const SupportedPaddingModesRequest& request,
- SupportedPaddingModesResponse* response);
- void SupportedDigests(const SupportedDigestsRequest& request,
- SupportedDigestsResponse* response);
- void SupportedImportFormats(const SupportedImportFormatsRequest& request,
- SupportedImportFormatsResponse* response);
- void SupportedExportFormats(const SupportedExportFormatsRequest& request,
- SupportedExportFormatsResponse* response);
- void AddRngEntropy(const AddEntropyRequest& request, AddEntropyResponse* response);
- void Configure(const ConfigureRequest& request, ConfigureResponse* response);
- void GenerateKey(const GenerateKeyRequest& request, GenerateKeyResponse* response);
- void GetKeyCharacteristics(const GetKeyCharacteristicsRequest& request,
- GetKeyCharacteristicsResponse* response);
- void ImportKey(const ImportKeyRequest& request, ImportKeyResponse* response);
- void ImportWrappedKey(const ImportWrappedKeyRequest& request,
- ImportWrappedKeyResponse* response);
- void ExportKey(const ExportKeyRequest& request, ExportKeyResponse* response);
- void AttestKey(const AttestKeyRequest& request, AttestKeyResponse* response);
- void UpgradeKey(const UpgradeKeyRequest& request, UpgradeKeyResponse* response);
- void DeleteKey(const DeleteKeyRequest& request, DeleteKeyResponse* response);
- void DeleteAllKeys(const DeleteAllKeysRequest& request, DeleteAllKeysResponse* response);
- void BeginOperation(const BeginOperationRequest& request, BeginOperationResponse* response);
- void UpdateOperation(const UpdateOperationRequest& request, UpdateOperationResponse* response);
- void FinishOperation(const FinishOperationRequest& request, FinishOperationResponse* response);
- void AbortOperation(const AbortOperationRequest& request, AbortOperationResponse* response);
- GetHmacSharingParametersResponse GetHmacSharingParameters();
- ComputeSharedHmacResponse ComputeSharedHmac(const ComputeSharedHmacRequest& request);
- VerifyAuthorizationResponse VerifyAuthorization(const VerifyAuthorizationRequest& request);
- DeviceLockedResponse DeviceLocked(const DeviceLockedRequest& request);
- EarlyBootEndedResponse EarlyBootEnded();
-
- // CF HAL and remote sides are always compiled together, so will never disagree about message
- // versions.
- uint32_t message_version() { return kDefaultMessageVersion; }
-};
-
-} // namespace keymaster
-
-#endif // REMOTE_KEYMASTER_H_
diff --git a/guest/hals/keymaster/remote/remote_keymaster4_device.cpp b/guest/hals/keymaster/remote/remote_keymaster4_device.cpp
deleted file mode 100644
index b82aa8378..000000000
--- a/guest/hals/keymaster/remote/remote_keymaster4_device.cpp
+++ /dev/null
@@ -1,631 +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.
- */
-
-#define LOG_TAG "android.hardware.keymaster@4.0-impl.remote"
-
-#include "remote_keymaster4_device.h"
-
-#include <android/hardware/keymaster/3.0/IKeymasterDevice.h>
-#include <authorization_set.h>
-#include <cutils/log.h>
-#include <keymaster/android_keymaster_messages.h>
-
-using ::keymaster::AbortOperationRequest;
-using ::keymaster::AbortOperationResponse;
-using ::keymaster::AddEntropyRequest;
-using ::keymaster::AddEntropyResponse;
-using ::keymaster::AttestKeyRequest;
-using ::keymaster::AttestKeyResponse;
-using ::keymaster::AuthorizationSet;
-using ::keymaster::BeginOperationRequest;
-using ::keymaster::BeginOperationResponse;
-using ::keymaster::ExportKeyRequest;
-using ::keymaster::ExportKeyResponse;
-using ::keymaster::FinishOperationRequest;
-using ::keymaster::FinishOperationResponse;
-using ::keymaster::GenerateKeyRequest;
-using ::keymaster::GenerateKeyResponse;
-using ::keymaster::GetKeyCharacteristicsRequest;
-using ::keymaster::GetKeyCharacteristicsResponse;
-using ::keymaster::ImportKeyRequest;
-using ::keymaster::ImportKeyResponse;
-using ::keymaster::UpdateOperationRequest;
-using ::keymaster::UpdateOperationResponse;
-using ::keymaster::ng::Tag;
-
-typedef ::android::hardware::keymaster::V3_0::Tag Tag3;
-using ::android::hardware::keymaster::V4_0::Constants;
-
-namespace keymaster {
-namespace V4_1 {
-namespace {
-
-inline keymaster_tag_t legacy_enum_conversion(const Tag value) {
- return keymaster_tag_t(value);
-}
-inline Tag legacy_enum_conversion(const keymaster_tag_t value) {
- return Tag(value);
-}
-inline keymaster_purpose_t legacy_enum_conversion(const KeyPurpose value) {
- return keymaster_purpose_t(value);
-}
-inline keymaster_key_format_t legacy_enum_conversion(const KeyFormat value) {
- return keymaster_key_format_t(value);
-}
-
-inline SecurityLevel legacy_enum_conversion(const keymaster_security_level_t value) {
- return static_cast<SecurityLevel>(value);
-}
-
-inline hw_authenticator_type_t legacy_enum_conversion(const HardwareAuthenticatorType value) {
- return static_cast<hw_authenticator_type_t>(value);
-}
-
-inline ErrorCode legacy_enum_conversion(const keymaster_error_t value) {
- return ErrorCode(value);
-}
-
-inline keymaster_tag_type_t typeFromTag(const keymaster_tag_t tag) {
- return keymaster_tag_get_type(tag);
-}
-
-/*
- * injectAuthToken translates a KM4 authToken into a legacy AUTH_TOKEN tag
- *
- * Currently, system/keymaster's reference implementation only accepts this
- * method for passing an auth token, so until that changes we need to
- * translate to the old format.
- */
-inline hidl_vec<KeyParameter> injectAuthToken(const hidl_vec<KeyParameter>& keyParamsBase,
- const HardwareAuthToken& authToken) {
- std::vector<KeyParameter> keyParams(keyParamsBase);
- const size_t mac_len = static_cast<size_t>(Constants::AUTH_TOKEN_MAC_LENGTH);
- /*
- * mac.size() == 0 indicates no token provided, so we should not copy.
- * mac.size() != mac_len means it is incompatible with the old
- * hw_auth_token_t structure. This is forbidden by spec, but to be safe
- * we only copy if mac.size() == mac_len, e.g. there is an authToken
- * with a hw_auth_token_t compatible MAC.
- */
- if (authToken.mac.size() == mac_len) {
- KeyParameter p;
- p.tag = static_cast<Tag>(Tag3::AUTH_TOKEN);
- p.blob.resize(sizeof(hw_auth_token_t));
-
- hw_auth_token_t* auth_token = reinterpret_cast<hw_auth_token_t*>(p.blob.data());
- auth_token->version = 0;
- auth_token->challenge = authToken.challenge;
- auth_token->user_id = authToken.userId;
- auth_token->authenticator_id = authToken.authenticatorId;
- auth_token->authenticator_type =
- htobe32(static_cast<uint32_t>(authToken.authenticatorType));
- auth_token->timestamp = htobe64(authToken.timestamp);
- static_assert(mac_len == sizeof(auth_token->hmac));
- memcpy(auth_token->hmac, authToken.mac.data(), mac_len);
- keyParams.push_back(p);
- }
-
- return hidl_vec<KeyParameter>(std::move(keyParams));
-}
-
-class KmParamSet : public keymaster_key_param_set_t {
- public:
- KmParamSet(const hidl_vec<KeyParameter>& keyParams) {
- params = new keymaster_key_param_t[keyParams.size()];
- length = keyParams.size();
- for (size_t i = 0; i < keyParams.size(); ++i) {
- auto tag = legacy_enum_conversion(keyParams[i].tag);
- switch (typeFromTag(tag)) {
- case KM_ENUM:
- case KM_ENUM_REP:
- params[i] = keymaster_param_enum(tag, keyParams[i].f.integer);
- break;
- case KM_UINT:
- case KM_UINT_REP:
- params[i] = keymaster_param_int(tag, keyParams[i].f.integer);
- break;
- case KM_ULONG:
- case KM_ULONG_REP:
- params[i] = keymaster_param_long(tag, keyParams[i].f.longInteger);
- break;
- case KM_DATE:
- params[i] = keymaster_param_date(tag, keyParams[i].f.dateTime);
- break;
- case KM_BOOL:
- if (keyParams[i].f.boolValue)
- params[i] = keymaster_param_bool(tag);
- else
- params[i].tag = KM_TAG_INVALID;
- break;
- case KM_BIGNUM:
- case KM_BYTES:
- params[i] = keymaster_param_blob(tag, &keyParams[i].blob[0],
- keyParams[i].blob.size());
- break;
- case KM_INVALID:
- default:
- params[i].tag = KM_TAG_INVALID;
- /* just skip */
- break;
- }
- }
- }
- KmParamSet(KmParamSet&& other) noexcept
- : keymaster_key_param_set_t{other.params, other.length} {
- other.length = 0;
- other.params = nullptr;
- }
- KmParamSet(const KmParamSet&) = delete;
- ~KmParamSet() { delete[] params; }
-};
-
-inline hidl_vec<uint8_t> kmBlob2hidlVec(const keymaster_key_blob_t& blob) {
- hidl_vec<uint8_t> result;
- result.setToExternal(const_cast<unsigned char*>(blob.key_material), blob.key_material_size);
- return result;
-}
-
-inline hidl_vec<uint8_t> kmBlob2hidlVec(const keymaster_blob_t& blob) {
- hidl_vec<uint8_t> result;
- result.setToExternal(const_cast<unsigned char*>(blob.data), blob.data_length);
- return result;
-}
-
-inline hidl_vec<uint8_t> kmBuffer2hidlVec(const ::keymaster::Buffer& buf) {
- hidl_vec<uint8_t> result;
- result.setToExternal(const_cast<unsigned char*>(buf.peek_read()), buf.available_read());
- return result;
-}
-
-inline static hidl_vec<hidl_vec<uint8_t>> kmCertChain2Hidl(
- const keymaster_cert_chain_t& cert_chain) {
- hidl_vec<hidl_vec<uint8_t>> result;
- if (!cert_chain.entry_count || !cert_chain.entries) return result;
-
- result.resize(cert_chain.entry_count);
- for (size_t i = 0; i < cert_chain.entry_count; ++i) {
- result[i] = kmBlob2hidlVec(cert_chain.entries[i]);
- }
-
- return result;
-}
-
-static inline hidl_vec<KeyParameter> kmParamSet2Hidl(const keymaster_key_param_set_t& set) {
- hidl_vec<KeyParameter> result;
- if (set.length == 0 || set.params == nullptr) return result;
-
- result.resize(set.length);
- keymaster_key_param_t* params = set.params;
- for (size_t i = 0; i < set.length; ++i) {
- auto tag = params[i].tag;
- result[i].tag = legacy_enum_conversion(tag);
- switch (typeFromTag(tag)) {
- case KM_ENUM:
- case KM_ENUM_REP:
- result[i].f.integer = params[i].enumerated;
- break;
- case KM_UINT:
- case KM_UINT_REP:
- result[i].f.integer = params[i].integer;
- break;
- case KM_ULONG:
- case KM_ULONG_REP:
- result[i].f.longInteger = params[i].long_integer;
- break;
- case KM_DATE:
- result[i].f.dateTime = params[i].date_time;
- break;
- case KM_BOOL:
- result[i].f.boolValue = params[i].boolean;
- break;
- case KM_BIGNUM:
- case KM_BYTES:
- result[i].blob.setToExternal(const_cast<unsigned char*>(params[i].blob.data),
- params[i].blob.data_length);
- break;
- case KM_INVALID:
- default:
- params[i].tag = KM_TAG_INVALID;
- /* just skip */
- break;
- }
- }
- return result;
-}
-
-void addClientAndAppData(const hidl_vec<uint8_t>& clientId, const hidl_vec<uint8_t>& appData,
- ::keymaster::AuthorizationSet* params) {
- params->Clear();
- if (clientId.size()) {
- params->push_back(::keymaster::TAG_APPLICATION_ID, clientId.data(), clientId.size());
- }
- if (appData.size()) {
- params->push_back(::keymaster::TAG_APPLICATION_DATA, appData.data(), appData.size());
- }
-}
-
-} // anonymous namespace
-
-RemoteKeymaster4Device::RemoteKeymaster4Device(RemoteKeymaster* impl) : impl_(impl) {}
-
-RemoteKeymaster4Device::~RemoteKeymaster4Device() {}
-
-Return<void> RemoteKeymaster4Device::getHardwareInfo(getHardwareInfo_cb _hidl_cb) {
- _hidl_cb(SecurityLevel::TRUSTED_ENVIRONMENT, "RemoteKeymaster", "Google");
- return Void();
-}
-
-Return<void> RemoteKeymaster4Device::getHmacSharingParameters(
- getHmacSharingParameters_cb _hidl_cb) {
- const GetHmacSharingParametersResponse response = impl_->GetHmacSharingParameters();
- // response.params is not the same as the HIDL structure, we need to convert it
- HmacSharingParameters params;
- params.seed.setToExternal(const_cast<uint8_t*>(response.params.seed.data),
- response.params.seed.data_length);
- static_assert(sizeof(response.params.nonce) == params.nonce.size(), "Nonce sizes don't match");
- memcpy(params.nonce.data(), response.params.nonce, params.nonce.size());
- _hidl_cb(legacy_enum_conversion(response.error), params);
- return Void();
-}
-
-Return<void> RemoteKeymaster4Device::computeSharedHmac(
- const hidl_vec<HmacSharingParameters>& params, computeSharedHmac_cb _hidl_cb) {
- ComputeSharedHmacRequest request(impl_->message_version());
- request.params_array.params_array = new keymaster::HmacSharingParameters[params.size()];
- request.params_array.num_params = params.size();
- for (size_t i = 0; i < params.size(); ++i) {
- request.params_array.params_array[i].seed = {params[i].seed.data(), params[i].seed.size()};
- static_assert(sizeof(request.params_array.params_array[i].nonce) ==
- decltype(params[i].nonce)::size(),
- "Nonce sizes don't match");
- memcpy(request.params_array.params_array[i].nonce, params[i].nonce.data(),
- params[i].nonce.size());
- }
-
- auto response = impl_->ComputeSharedHmac(request);
- hidl_vec<uint8_t> sharing_check;
- if (response.error == KM_ERROR_OK) {
- sharing_check = kmBlob2hidlVec(response.sharing_check);
- }
-
- _hidl_cb(legacy_enum_conversion(response.error), sharing_check);
- return Void();
-}
-
-Return<void> RemoteKeymaster4Device::verifyAuthorization(
- uint64_t challenge, const hidl_vec<KeyParameter>& parametersToVerify,
- const HardwareAuthToken& authToken, verifyAuthorization_cb _hidl_cb) {
- VerifyAuthorizationRequest request(impl_->message_version());
- request.challenge = challenge;
- request.parameters_to_verify.Reinitialize(KmParamSet(parametersToVerify));
- request.auth_token.challenge = authToken.challenge;
- request.auth_token.user_id = authToken.userId;
- request.auth_token.authenticator_id = authToken.authenticatorId;
- request.auth_token.authenticator_type = legacy_enum_conversion(authToken.authenticatorType);
- request.auth_token.timestamp = authToken.timestamp;
- KeymasterBlob mac(authToken.mac.data(), authToken.mac.size());
- request.auth_token.mac = mac;
-
- auto response = impl_->VerifyAuthorization(request);
-
- ::android::hardware::keymaster::V4_0::VerificationToken token;
- token.challenge = response.token.challenge;
- token.timestamp = response.token.timestamp;
- token.parametersVerified = kmParamSet2Hidl(response.token.parameters_verified);
- token.securityLevel = legacy_enum_conversion(response.token.security_level);
- token.mac = kmBlob2hidlVec(response.token.mac);
-
- _hidl_cb(legacy_enum_conversion(response.error), token);
-
- return Void();
-}
-
-Return<ErrorCode> RemoteKeymaster4Device::addRngEntropy(const hidl_vec<uint8_t>& data) {
- if (data.size() == 0) return ErrorCode::OK;
- AddEntropyRequest request(impl_->message_version());
- request.random_data.Reinitialize(data.data(), data.size());
-
- AddEntropyResponse response(impl_->message_version());
- impl_->AddRngEntropy(request, &response);
-
- return legacy_enum_conversion(response.error);
-}
-
-Return<void> RemoteKeymaster4Device::generateKey(const hidl_vec<KeyParameter>& keyParams,
- generateKey_cb _hidl_cb) {
- GenerateKeyRequest request(impl_->message_version());
- request.key_description.Reinitialize(KmParamSet(keyParams));
-
- GenerateKeyResponse response(impl_->message_version());
- impl_->GenerateKey(request, &response);
-
- KeyCharacteristics resultCharacteristics;
- hidl_vec<uint8_t> resultKeyBlob;
- if (response.error == KM_ERROR_OK) {
- resultKeyBlob = kmBlob2hidlVec(response.key_blob);
- resultCharacteristics.hardwareEnforced = kmParamSet2Hidl(response.enforced);
- resultCharacteristics.softwareEnforced = kmParamSet2Hidl(response.unenforced);
- }
- _hidl_cb(legacy_enum_conversion(response.error), resultKeyBlob, resultCharacteristics);
- return Void();
-}
-
-Return<void> RemoteKeymaster4Device::getKeyCharacteristics(const hidl_vec<uint8_t>& keyBlob,
- const hidl_vec<uint8_t>& clientId,
- const hidl_vec<uint8_t>& appData,
- getKeyCharacteristics_cb _hidl_cb) {
- GetKeyCharacteristicsRequest request(impl_->message_version());
- request.SetKeyMaterial(keyBlob.data(), keyBlob.size());
- addClientAndAppData(clientId, appData, &request.additional_params);
-
- GetKeyCharacteristicsResponse response(impl_->message_version());
- impl_->GetKeyCharacteristics(request, &response);
-
- KeyCharacteristics resultCharacteristics;
- if (response.error == KM_ERROR_OK) {
- resultCharacteristics.hardwareEnforced = kmParamSet2Hidl(response.enforced);
- resultCharacteristics.softwareEnforced = kmParamSet2Hidl(response.unenforced);
- }
- _hidl_cb(legacy_enum_conversion(response.error), resultCharacteristics);
- return Void();
-}
-
-Return<void> RemoteKeymaster4Device::importKey(const hidl_vec<KeyParameter>& params,
- KeyFormat keyFormat,
- const hidl_vec<uint8_t>& keyData,
- importKey_cb _hidl_cb) {
- ImportKeyRequest request(impl_->message_version());
- request.key_description.Reinitialize(KmParamSet(params));
- request.key_format = legacy_enum_conversion(keyFormat);
- request.key_data = KeymasterKeyBlob(keyData.data(), keyData.size());
-
- ImportKeyResponse response(impl_->message_version());
- impl_->ImportKey(request, &response);
-
- KeyCharacteristics resultCharacteristics;
- hidl_vec<uint8_t> resultKeyBlob;
- if (response.error == KM_ERROR_OK) {
- resultKeyBlob = kmBlob2hidlVec(response.key_blob);
- resultCharacteristics.hardwareEnforced = kmParamSet2Hidl(response.enforced);
- resultCharacteristics.softwareEnforced = kmParamSet2Hidl(response.unenforced);
- }
- _hidl_cb(legacy_enum_conversion(response.error), resultKeyBlob, resultCharacteristics);
- return Void();
-}
-
-Return<void> RemoteKeymaster4Device::importWrappedKey(
- const hidl_vec<uint8_t>& wrappedKeyData, const hidl_vec<uint8_t>& wrappingKeyBlob,
- const hidl_vec<uint8_t>& maskingKey, const hidl_vec<KeyParameter>& unwrappingParams,
- uint64_t passwordSid, uint64_t biometricSid, importWrappedKey_cb _hidl_cb) {
- ImportWrappedKeyRequest request(impl_->message_version());
- request.SetWrappedMaterial(wrappedKeyData.data(), wrappedKeyData.size());
- request.SetWrappingMaterial(wrappingKeyBlob.data(), wrappingKeyBlob.size());
- request.SetMaskingKeyMaterial(maskingKey.data(), maskingKey.size());
- request.additional_params.Reinitialize(KmParamSet(unwrappingParams));
- request.password_sid = passwordSid;
- request.biometric_sid = biometricSid;
-
- ImportWrappedKeyResponse response(impl_->message_version());
- impl_->ImportWrappedKey(request, &response);
-
- KeyCharacteristics resultCharacteristics;
- hidl_vec<uint8_t> resultKeyBlob;
- if (response.error == KM_ERROR_OK) {
- resultKeyBlob = kmBlob2hidlVec(response.key_blob);
- resultCharacteristics.hardwareEnforced = kmParamSet2Hidl(response.enforced);
- resultCharacteristics.softwareEnforced = kmParamSet2Hidl(response.unenforced);
- }
- _hidl_cb(legacy_enum_conversion(response.error), resultKeyBlob, resultCharacteristics);
- return Void();
-}
-
-Return<void> RemoteKeymaster4Device::exportKey(KeyFormat exportFormat,
- const hidl_vec<uint8_t>& keyBlob,
- const hidl_vec<uint8_t>& clientId,
- const hidl_vec<uint8_t>& appData,
- exportKey_cb _hidl_cb) {
- ExportKeyRequest request(impl_->message_version());
- request.key_format = legacy_enum_conversion(exportFormat);
- request.SetKeyMaterial(keyBlob.data(), keyBlob.size());
- addClientAndAppData(clientId, appData, &request.additional_params);
-
- ExportKeyResponse response(impl_->message_version());
- impl_->ExportKey(request, &response);
-
- hidl_vec<uint8_t> resultKeyBlob;
- if (response.error == KM_ERROR_OK) {
- resultKeyBlob.setToExternal(response.key_data, response.key_data_length);
- }
- _hidl_cb(legacy_enum_conversion(response.error), resultKeyBlob);
- return Void();
-}
-
-Return<void> RemoteKeymaster4Device::attestKey(const hidl_vec<uint8_t>& keyToAttest,
- const hidl_vec<KeyParameter>& attestParams,
- attestKey_cb _hidl_cb) {
- AttestKeyRequest request(impl_->message_version());
- request.SetKeyMaterial(keyToAttest.data(), keyToAttest.size());
- request.attest_params.Reinitialize(KmParamSet(attestParams));
-
- AttestKeyResponse response(impl_->message_version());
- impl_->AttestKey(request, &response);
-
- hidl_vec<hidl_vec<uint8_t>> resultCertChain;
- if (response.error == KM_ERROR_OK) {
- resultCertChain = kmCertChain2Hidl(response.certificate_chain);
- }
- _hidl_cb(legacy_enum_conversion(response.error), resultCertChain);
- return Void();
-}
-
-Return<void> RemoteKeymaster4Device::upgradeKey(const hidl_vec<uint8_t>& keyBlobToUpgrade,
- const hidl_vec<KeyParameter>& upgradeParams,
- upgradeKey_cb _hidl_cb) {
- UpgradeKeyRequest request(impl_->message_version());
- request.SetKeyMaterial(keyBlobToUpgrade.data(), keyBlobToUpgrade.size());
- request.upgrade_params.Reinitialize(KmParamSet(upgradeParams));
-
- UpgradeKeyResponse response(impl_->message_version());
- impl_->UpgradeKey(request, &response);
-
- if (response.error == KM_ERROR_OK) {
- _hidl_cb(ErrorCode::OK, kmBlob2hidlVec(response.upgraded_key));
- } else {
- _hidl_cb(legacy_enum_conversion(response.error), hidl_vec<uint8_t>());
- }
- return Void();
-}
-
-Return<ErrorCode> RemoteKeymaster4Device::deleteKey(const hidl_vec<uint8_t>& keyBlob) {
- DeleteKeyRequest request(impl_->message_version());
- request.SetKeyMaterial(keyBlob.data(), keyBlob.size());
-
- DeleteKeyResponse response(impl_->message_version());
- impl_->DeleteKey(request, &response);
-
- return legacy_enum_conversion(response.error);
-}
-
-Return<ErrorCode> RemoteKeymaster4Device::deleteAllKeys() {
- DeleteAllKeysRequest request(impl_->message_version());
- DeleteAllKeysResponse response(impl_->message_version());
- impl_->DeleteAllKeys(request, &response);
-
- return legacy_enum_conversion(response.error);
-}
-
-Return<ErrorCode> RemoteKeymaster4Device::destroyAttestationIds() {
- return ErrorCode::UNIMPLEMENTED;
-}
-
-Return<void> RemoteKeymaster4Device::begin(KeyPurpose purpose, const hidl_vec<uint8_t>& key,
- const hidl_vec<KeyParameter>& inParams,
- const HardwareAuthToken& authToken, begin_cb _hidl_cb) {
- hidl_vec<KeyParameter> extendedParams = injectAuthToken(inParams, authToken);
- BeginOperationRequest request(impl_->message_version());
- request.purpose = legacy_enum_conversion(purpose);
- request.SetKeyMaterial(key.data(), key.size());
- request.additional_params.Reinitialize(KmParamSet(extendedParams));
-
- BeginOperationResponse response(impl_->message_version());
- impl_->BeginOperation(request, &response);
-
- hidl_vec<KeyParameter> resultParams;
- if (response.error == KM_ERROR_OK) {
- resultParams = kmParamSet2Hidl(response.output_params);
- }
-
- _hidl_cb(legacy_enum_conversion(response.error), resultParams, response.op_handle);
- return Void();
-}
-
-Return<void> RemoteKeymaster4Device::update(uint64_t operationHandle,
- const hidl_vec<KeyParameter>& inParams,
- const hidl_vec<uint8_t>& input,
- const HardwareAuthToken& authToken,
- const VerificationToken& /* verificationToken */,
- update_cb _hidl_cb) {
- UpdateOperationRequest request(impl_->message_version());
- UpdateOperationResponse response(impl_->message_version());
- hidl_vec<KeyParameter> resultParams;
- hidl_vec<uint8_t> resultBlob;
- hidl_vec<KeyParameter> extendedParams = injectAuthToken(inParams, authToken);
- uint32_t resultConsumed = 0;
-
- request.op_handle = operationHandle;
- request.additional_params.Reinitialize(KmParamSet(extendedParams));
-
- // TODO(schuffelen): Set a buffer size limit.
- request.input.Reinitialize(input.data(), input.size());
-
- impl_->UpdateOperation(request, &response);
-
- if (response.error == KM_ERROR_OK) {
- resultConsumed = response.input_consumed;
- resultParams = kmParamSet2Hidl(response.output_params);
- resultBlob = kmBuffer2hidlVec(response.output);
- }
- _hidl_cb(legacy_enum_conversion(response.error), resultConsumed, resultParams, resultBlob);
- return Void();
-}
-
-Return<void> RemoteKeymaster4Device::finish(uint64_t operationHandle,
- const hidl_vec<KeyParameter>& inParams,
- const hidl_vec<uint8_t>& input,
- const hidl_vec<uint8_t>& signature,
- const HardwareAuthToken& authToken,
- const VerificationToken& verificationToken,
- finish_cb _hidl_cb) {
- (void)verificationToken;
- FinishOperationRequest request(impl_->message_version());
- hidl_vec<KeyParameter> extendedParams = injectAuthToken(inParams, authToken);
- request.op_handle = operationHandle;
- request.input.Reinitialize(input.data(), input.size());
- request.signature.Reinitialize(signature.data(), signature.size());
- request.additional_params.Reinitialize(KmParamSet(extendedParams));
-
- FinishOperationResponse response(impl_->message_version());
- impl_->FinishOperation(request, &response);
-
- hidl_vec<KeyParameter> resultParams;
- hidl_vec<uint8_t> resultBlob;
- if (response.error == KM_ERROR_OK) {
- resultParams = kmParamSet2Hidl(response.output_params);
- resultBlob = kmBuffer2hidlVec(response.output);
- }
- _hidl_cb(legacy_enum_conversion(response.error), resultParams, resultBlob);
- return Void();
-}
-
-Return<ErrorCode> RemoteKeymaster4Device::abort(uint64_t operationHandle) {
- AbortOperationRequest request(impl_->message_version());
- request.op_handle = operationHandle;
-
- AbortOperationResponse response(impl_->message_version());
- impl_->AbortOperation(request, &response);
-
- return legacy_enum_conversion(response.error);
-}
-
-Return<ErrorCodeV41> RemoteKeymaster4Device::deviceLocked(
- bool passwordOnly, const VerificationToken& verificationToken) {
- keymaster::VerificationToken internal_verification_token;
- internal_verification_token.challenge = verificationToken.challenge;
- internal_verification_token.timestamp = verificationToken.timestamp;
- internal_verification_token.parameters_verified.Reinitialize(
- KmParamSet(verificationToken.parametersVerified));
- internal_verification_token.security_level =
- static_cast<keymaster_security_level_t>(verificationToken.securityLevel);
- internal_verification_token.mac =
- KeymasterBlob(verificationToken.mac.data(), verificationToken.mac.size());
-
- DeviceLockedRequest request(impl_->message_version(),
- passwordOnly, std::move(internal_verification_token));
-
- auto response = impl_->DeviceLocked(request);
-
- return ErrorCodeV41(response.error);
-}
-
-Return<ErrorCodeV41> RemoteKeymaster4Device::earlyBootEnded() {
- auto response = impl_->EarlyBootEnded();
-
- return ErrorCodeV41(response.error);
-}
-
-} // namespace V4_1
-} // namespace keymaster
diff --git a/guest/hals/keymaster/remote/remote_keymaster4_device.h b/guest/hals/keymaster/remote/remote_keymaster4_device.h
deleted file mode 100644
index ec76f7cc6..000000000
--- a/guest/hals/keymaster/remote/remote_keymaster4_device.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- **
- ** 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 <android/hardware/keymaster/4.0/IKeymasterDevice.h>
-#include <android/hardware/keymaster/4.1/IKeymasterDevice.h>
-#include <hidl/Status.h>
-#include "guest/hals/keymaster/remote/remote_keymaster.h"
-
-namespace keymaster {
-
-namespace V4_1 {
-
-using ::android::sp;
-using ::android::hardware::hidl_vec;
-using ::android::hardware::Return;
-using ::android::hardware::Void;
-using ::android::hardware::keymaster::V4_0::ErrorCode;
-using ::android::hardware::keymaster::V4_0::HardwareAuthenticatorType;
-using ::android::hardware::keymaster::V4_0::HardwareAuthToken;
-using ::android::hardware::keymaster::V4_0::HmacSharingParameters;
-using ::android::hardware::keymaster::V4_0::KeyCharacteristics;
-using ::android::hardware::keymaster::V4_0::KeyFormat;
-using ::android::hardware::keymaster::V4_0::KeyParameter;
-using ::android::hardware::keymaster::V4_0::KeyPurpose;
-using ::android::hardware::keymaster::V4_0::SecurityLevel;
-using ::android::hardware::keymaster::V4_0::Tag;
-using ::android::hardware::keymaster::V4_0::VerificationToken;
-using ::android::hardware::keymaster::V4_1::IKeymasterDevice;
-
-using ErrorCodeV41 = ::android::hardware::keymaster::V4_1::ErrorCode;
-
-class RemoteKeymaster4Device : public IKeymasterDevice {
- public:
- explicit RemoteKeymaster4Device(RemoteKeymaster* impl);
- virtual ~RemoteKeymaster4Device();
-
- Return<void> getHardwareInfo(getHardwareInfo_cb _hidl_cb) override;
- Return<void> getHmacSharingParameters(getHmacSharingParameters_cb _hidl_cb) override;
- Return<void> computeSharedHmac(const hidl_vec<HmacSharingParameters>& params,
- computeSharedHmac_cb) override;
- Return<void> verifyAuthorization(uint64_t challenge,
- const hidl_vec<KeyParameter>& parametersToVerify,
- const HardwareAuthToken& authToken,
- verifyAuthorization_cb _hidl_cb) override;
- Return<ErrorCode> addRngEntropy(const hidl_vec<uint8_t>& data) override;
- Return<void> generateKey(const hidl_vec<KeyParameter>& keyParams,
- generateKey_cb _hidl_cb) override;
- Return<void> getKeyCharacteristics(const hidl_vec<uint8_t>& keyBlob,
- const hidl_vec<uint8_t>& clientId,
- const hidl_vec<uint8_t>& appData,
- getKeyCharacteristics_cb _hidl_cb) override;
- Return<void> importKey(const hidl_vec<KeyParameter>& params, KeyFormat keyFormat,
- const hidl_vec<uint8_t>& keyData, importKey_cb _hidl_cb) override;
- Return<void> importWrappedKey(const hidl_vec<uint8_t>& wrappedKeyData,
- const hidl_vec<uint8_t>& wrappingKeyBlob,
- const hidl_vec<uint8_t>& maskingKey,
- const hidl_vec<KeyParameter>& unwrappingParams,
- uint64_t passwordSid, uint64_t biometricSid,
- importWrappedKey_cb _hidl_cb) override;
- Return<void> exportKey(KeyFormat exportFormat, const hidl_vec<uint8_t>& keyBlob,
- const hidl_vec<uint8_t>& clientId, const hidl_vec<uint8_t>& appData,
- exportKey_cb _hidl_cb) override;
- Return<void> attestKey(const hidl_vec<uint8_t>& keyToAttest,
- const hidl_vec<KeyParameter>& attestParams,
- attestKey_cb _hidl_cb) override;
- Return<void> upgradeKey(const hidl_vec<uint8_t>& keyBlobToUpgrade,
- const hidl_vec<KeyParameter>& upgradeParams,
- upgradeKey_cb _hidl_cb) override;
- Return<ErrorCode> deleteKey(const hidl_vec<uint8_t>& keyBlob) override;
- Return<ErrorCode> deleteAllKeys() override;
- Return<ErrorCode> destroyAttestationIds() override;
- Return<void> begin(KeyPurpose purpose, const hidl_vec<uint8_t>& key,
- const hidl_vec<KeyParameter>& inParams, const HardwareAuthToken& authToken,
- begin_cb _hidl_cb) override;
- Return<void> update(uint64_t operationHandle, const hidl_vec<KeyParameter>& inParams,
- const hidl_vec<uint8_t>& input, const HardwareAuthToken& authToken,
- const VerificationToken& verificationToken, update_cb _hidl_cb) override;
- Return<void> finish(uint64_t operationHandle, const hidl_vec<KeyParameter>& inParams,
- const hidl_vec<uint8_t>& input, const hidl_vec<uint8_t>& signature,
- const HardwareAuthToken& authToken,
- const VerificationToken& verificationToken, finish_cb _hidl_cb) override;
- Return<ErrorCode> abort(uint64_t operationHandle) override;
-
- // 4.1
- Return<ErrorCodeV41> deviceLocked(
- bool passwordOnly, const VerificationToken& verificationToken) override;
- Return<ErrorCodeV41> earlyBootEnded() override;
-
- private:
- std::unique_ptr<::keymaster::RemoteKeymaster> impl_;
-};
-
-} // namespace V4_1
-} // namespace keymaster
diff --git a/guest/hals/keymaster/remote/service4.cpp b/guest/hals/keymaster/remote/service4.cpp
deleted file mode 100644
index 47f6261f8..000000000
--- a/guest/hals/keymaster/remote/service4.cpp
+++ /dev/null
@@ -1,66 +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 <android-base/logging.h>
-#include <android/hardware/keymaster/4.1/IKeymasterDevice.h>
-#include <cutils/properties.h>
-#include <gflags/gflags.h>
-#include <hidl/HidlTransportSupport.h>
-
-#include "common/libs/fs/shared_fd.h"
-#include "common/libs/security/keymaster_channel.h"
-#include <guest/hals/keymaster/remote/remote_keymaster.h>
-#include <guest/hals/keymaster/remote/remote_keymaster4_device.h>
-
-const char device[] = "/dev/hvc3";
-
-int main(int argc, char** argv) {
- ::android::base::InitLogging(argv, ::android::base::KernelLogger);
- gflags::ParseCommandLineFlags(&argc, &argv, true);
- ::android::hardware::configureRpcThreadpool(1, true);
-
- LOG(INFO) << "Starting keymaster service4";
-
- auto fd = cuttlefish::SharedFD::Open(device, O_RDWR);
- if (!fd->IsOpen()) {
- LOG(FATAL) << "Could not connect to keymaster: " << fd->StrError();
- }
-
- if (fd->SetTerminalRaw() < 0) {
- LOG(FATAL) << "Could not make " << device << " a raw terminal: "
- << fd->StrError();
- }
-
- cuttlefish::KeymasterChannel keymasterChannel(fd, fd);
-
- auto remoteKeymaster = new keymaster::RemoteKeymaster(&keymasterChannel);
-
- if (!remoteKeymaster->Initialize()) {
- LOG(FATAL) << "Could not initialize keymaster";
- }
-
- auto keymaster = new ::keymaster::V4_1::RemoteKeymaster4Device(remoteKeymaster);
-
- auto status = keymaster->registerAsService();
- if (status != android::OK) {
- LOG(FATAL) << "Could not register service for Keymaster 4.1 (" << status << ")";
- return -1;
- }
-
- android::hardware::joinRpcThreadpool();
- return -1; // Should never get here.
-}
diff --git a/guest/hals/keymint/OWNERS b/guest/hals/keymint/OWNERS
deleted file mode 100644
index fb015cbb1..000000000
--- a/guest/hals/keymint/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-include platform/system/keymaster:/OWNERS
diff --git a/guest/hals/keymint/remote/Android.bp b/guest/hals/keymint/remote/Android.bp
deleted file mode 100644
index a383c4507..000000000
--- a/guest/hals/keymint/remote/Android.bp
+++ /dev/null
@@ -1,62 +0,0 @@
-//
-// Copyright (C) 2020 The Android Open-Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-cc_binary {
- name: "android.hardware.security.keymint-service.remote",
- relative_install_path: "hw",
- init_rc: ["android.hardware.security.keymint-service.remote.rc"],
- vintf_fragments: [
- "android.hardware.security.keymint-service.remote.xml",
- "android.hardware.security.sharedsecret-service.remote.xml",
- "android.hardware.security.secureclock-service.remote.xml",
- ],
- vendor: true,
- cflags: [
- "-Wall",
- "-Wextra",
- ],
- shared_libs: [
- "android.hardware.security.keymint-V1-ndk_platform",
- "android.hardware.security.secureclock-V1-ndk_platform",
- "android.hardware.security.sharedsecret-V1-ndk_platform",
- "lib_android_keymaster_keymint_utils",
- "libbase",
- "libbinder_ndk",
- "libcppbor_external",
- "libcrypto",
- "libcuttlefish_fs",
- "libcuttlefish_security",
- "libhardware",
- "libkeymaster_messages",
- "libkeymint",
- "liblog",
- "libutils",
- ],
- srcs: [
- "remote_keymint_device.cpp",
- "remote_keymint_operation.cpp",
- "remote_keymaster.cpp",
- "remote_secure_clock.cpp",
- "remote_shared_secret.cpp",
- "service.cpp",
- ],
- defaults: [
- "cuttlefish_guest_only",
- ],
-}
diff --git a/guest/hals/keymint/remote/android.hardware.security.keymint-service.remote.rc b/guest/hals/keymint/remote/android.hardware.security.keymint-service.remote.rc
deleted file mode 100644
index 422fe17f5..000000000
--- a/guest/hals/keymint/remote/android.hardware.security.keymint-service.remote.rc
+++ /dev/null
@@ -1,3 +0,0 @@
-service vendor.keymint-remote /vendor/bin/hw/android.hardware.security.keymint-service.remote
- class early_hal
- user nobody
diff --git a/guest/hals/keymint/remote/android.hardware.security.keymint-service.remote.xml b/guest/hals/keymint/remote/android.hardware.security.keymint-service.remote.xml
deleted file mode 100644
index 4aa05efe1..000000000
--- a/guest/hals/keymint/remote/android.hardware.security.keymint-service.remote.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-<manifest version="1.0" type="device">
- <hal format="aidl">
- <name>android.hardware.security.keymint</name>
- <fqname>IKeyMintDevice/default</fqname>
- </hal>
- <hal format="aidl">
- <name>android.hardware.security.keymint</name>
- <fqname>IRemotelyProvisionedComponent/default</fqname>
- </hal>
-</manifest>
diff --git a/guest/hals/keymint/remote/android.hardware.security.secureclock-service.remote.xml b/guest/hals/keymint/remote/android.hardware.security.secureclock-service.remote.xml
deleted file mode 100644
index c0ff7752b..000000000
--- a/guest/hals/keymint/remote/android.hardware.security.secureclock-service.remote.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<manifest version="1.0" type="device">
- <hal format="aidl">
- <name>android.hardware.security.secureclock</name>
- <fqname>ISecureClock/default</fqname>
- </hal>
-</manifest>
diff --git a/guest/hals/keymint/remote/android.hardware.security.sharedsecret-service.remote.xml b/guest/hals/keymint/remote/android.hardware.security.sharedsecret-service.remote.xml
deleted file mode 100644
index d37981fe4..000000000
--- a/guest/hals/keymint/remote/android.hardware.security.sharedsecret-service.remote.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<manifest version="1.0" type="device">
- <hal format="aidl">
- <name>android.hardware.security.sharedsecret</name>
- <fqname>ISharedSecret/default</fqname>
- </hal>
-</manifest>
diff --git a/guest/hals/keymint/remote/remote_keymaster.cpp b/guest/hals/keymint/remote/remote_keymaster.cpp
deleted file mode 100644
index 5eee14325..000000000
--- a/guest/hals/keymint/remote/remote_keymaster.cpp
+++ /dev/null
@@ -1,241 +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 "remote_keymaster.h"
-
-#include <android-base/logging.h>
-#include <keymaster/android_keymaster_messages.h>
-#include <keymaster/keymaster_configuration.h>
-
-namespace keymaster {
-
-RemoteKeymaster::RemoteKeymaster(cuttlefish::KeymasterChannel* channel,
- uint32_t message_version)
- : channel_(channel), message_version_(message_version) {}
-
-RemoteKeymaster::~RemoteKeymaster() {}
-
-void RemoteKeymaster::ForwardCommand(AndroidKeymasterCommand command,
- const Serializable& req,
- KeymasterResponse* rsp) {
- if (!channel_->SendRequest(command, req)) {
- LOG(ERROR) << "Failed to send keymaster message: " << command;
- rsp->error = KM_ERROR_UNKNOWN_ERROR;
- return;
- }
- auto response = channel_->ReceiveMessage();
- if (!response) {
- LOG(ERROR) << "Failed to receive keymaster response: " << command;
- rsp->error = KM_ERROR_UNKNOWN_ERROR;
- return;
- }
- const uint8_t* buffer = response->payload;
- const uint8_t* buffer_end = response->payload + response->payload_size;
- if (!rsp->Deserialize(&buffer, buffer_end)) {
- LOG(ERROR) << "Failed to deserialize keymaster response: " << command;
- rsp->error = KM_ERROR_UNKNOWN_ERROR;
- return;
- }
-}
-
-bool RemoteKeymaster::Initialize() {
- // We don't need to bother with GetVersion, because CF HAL and remote sides
- // are always compiled together, so will never disagree about message
- // versions.
- ConfigureRequest req(message_version());
- req.os_version = GetOsVersion();
- req.os_patchlevel = GetOsPatchlevel();
-
- ConfigureResponse rsp(message_version());
- Configure(req, &rsp);
-
- if (rsp.error != KM_ERROR_OK) {
- LOG(ERROR) << "Failed to configure keymaster: " << rsp.error;
- return false;
- }
-
- return true;
-}
-
-void RemoteKeymaster::GetVersion(const GetVersionRequest& request,
- GetVersionResponse* response) {
- ForwardCommand(GET_VERSION, request, response);
-}
-
-void RemoteKeymaster::SupportedAlgorithms(
- const SupportedAlgorithmsRequest& request,
- SupportedAlgorithmsResponse* response) {
- ForwardCommand(GET_SUPPORTED_ALGORITHMS, request, response);
-}
-
-void RemoteKeymaster::SupportedBlockModes(
- const SupportedBlockModesRequest& request,
- SupportedBlockModesResponse* response) {
- ForwardCommand(GET_SUPPORTED_BLOCK_MODES, request, response);
-}
-
-void RemoteKeymaster::SupportedPaddingModes(
- const SupportedPaddingModesRequest& request,
- SupportedPaddingModesResponse* response) {
- ForwardCommand(GET_SUPPORTED_PADDING_MODES, request, response);
-}
-
-void RemoteKeymaster::SupportedDigests(const SupportedDigestsRequest& request,
- SupportedDigestsResponse* response) {
- ForwardCommand(GET_SUPPORTED_DIGESTS, request, response);
-}
-
-void RemoteKeymaster::SupportedImportFormats(
- const SupportedImportFormatsRequest& request,
- SupportedImportFormatsResponse* response) {
- ForwardCommand(GET_SUPPORTED_IMPORT_FORMATS, request, response);
-}
-
-void RemoteKeymaster::SupportedExportFormats(
- const SupportedExportFormatsRequest& request,
- SupportedExportFormatsResponse* response) {
- ForwardCommand(GET_SUPPORTED_EXPORT_FORMATS, request, response);
-}
-
-void RemoteKeymaster::AddRngEntropy(const AddEntropyRequest& request,
- AddEntropyResponse* response) {
- ForwardCommand(ADD_RNG_ENTROPY, request, response);
-}
-
-void RemoteKeymaster::Configure(const ConfigureRequest& request,
- ConfigureResponse* response) {
- ForwardCommand(CONFIGURE, request, response);
-}
-
-void RemoteKeymaster::GenerateKey(const GenerateKeyRequest& request,
- GenerateKeyResponse* response) {
- GenerateKeyRequest datedRequest(request.message_version);
- datedRequest.key_description = request.key_description;
-
- if (!request.key_description.Contains(TAG_CREATION_DATETIME)) {
- datedRequest.key_description.push_back(TAG_CREATION_DATETIME,
- java_time(time(NULL)));
- }
-
- ForwardCommand(GENERATE_KEY, datedRequest, response);
-}
-
-void RemoteKeymaster::GetKeyCharacteristics(
- const GetKeyCharacteristicsRequest& request,
- GetKeyCharacteristicsResponse* response) {
- ForwardCommand(GET_KEY_CHARACTERISTICS, request, response);
-}
-
-void RemoteKeymaster::ImportKey(const ImportKeyRequest& request,
- ImportKeyResponse* response) {
- ForwardCommand(IMPORT_KEY, request, response);
-}
-
-void RemoteKeymaster::ImportWrappedKey(const ImportWrappedKeyRequest& request,
- ImportWrappedKeyResponse* response) {
- ForwardCommand(IMPORT_WRAPPED_KEY, request, response);
-}
-
-void RemoteKeymaster::ExportKey(const ExportKeyRequest& request,
- ExportKeyResponse* response) {
- ForwardCommand(EXPORT_KEY, request, response);
-}
-
-void RemoteKeymaster::AttestKey(const AttestKeyRequest& request,
- AttestKeyResponse* response) {
- ForwardCommand(ATTEST_KEY, request, response);
-}
-
-void RemoteKeymaster::UpgradeKey(const UpgradeKeyRequest& request,
- UpgradeKeyResponse* response) {
- ForwardCommand(UPGRADE_KEY, request, response);
-}
-
-void RemoteKeymaster::DeleteKey(const DeleteKeyRequest& request,
- DeleteKeyResponse* response) {
- ForwardCommand(DELETE_KEY, request, response);
-}
-
-void RemoteKeymaster::DeleteAllKeys(const DeleteAllKeysRequest& request,
- DeleteAllKeysResponse* response) {
- ForwardCommand(DELETE_ALL_KEYS, request, response);
-}
-
-void RemoteKeymaster::BeginOperation(const BeginOperationRequest& request,
- BeginOperationResponse* response) {
- ForwardCommand(BEGIN_OPERATION, request, response);
-}
-
-void RemoteKeymaster::UpdateOperation(const UpdateOperationRequest& request,
- UpdateOperationResponse* response) {
- ForwardCommand(UPDATE_OPERATION, request, response);
-}
-
-void RemoteKeymaster::FinishOperation(const FinishOperationRequest& request,
- FinishOperationResponse* response) {
- ForwardCommand(FINISH_OPERATION, request, response);
-}
-
-void RemoteKeymaster::AbortOperation(const AbortOperationRequest& request,
- AbortOperationResponse* response) {
- ForwardCommand(ABORT_OPERATION, request, response);
-}
-
-GetHmacSharingParametersResponse RemoteKeymaster::GetHmacSharingParameters() {
- // Unused empty buffer to allow ForwardCommand to have something to serialize
- Buffer request;
- GetHmacSharingParametersResponse response(message_version());
- ForwardCommand(GET_HMAC_SHARING_PARAMETERS, request, &response);
- return response;
-}
-
-ComputeSharedHmacResponse RemoteKeymaster::ComputeSharedHmac(
- const ComputeSharedHmacRequest& request) {
- ComputeSharedHmacResponse response(message_version());
- ForwardCommand(COMPUTE_SHARED_HMAC, request, &response);
- return response;
-}
-
-VerifyAuthorizationResponse RemoteKeymaster::VerifyAuthorization(
- const VerifyAuthorizationRequest& request) {
- VerifyAuthorizationResponse response(message_version());
- ForwardCommand(VERIFY_AUTHORIZATION, request, &response);
- return response;
-}
-
-DeviceLockedResponse RemoteKeymaster::DeviceLocked(
- const DeviceLockedRequest& request) {
- DeviceLockedResponse response(message_version());
- ForwardCommand(DEVICE_LOCKED, request, &response);
- return response;
-}
-
-EarlyBootEndedResponse RemoteKeymaster::EarlyBootEnded() {
- // Unused empty buffer to allow ForwardCommand to have something to serialize
- Buffer request;
- EarlyBootEndedResponse response(message_version());
- ForwardCommand(EARLY_BOOT_ENDED, request, &response);
- return response;
-}
-
-void RemoteKeymaster::GenerateTimestampToken(
- GenerateTimestampTokenRequest& request,
- GenerateTimestampTokenResponse* response) {
- // TODO(aosp/1641315): Send a message to the host.
- ForwardCommand(GENERATE_TIMESTAMP_TOKEN, request, response);
-}
-
-} // namespace keymaster
diff --git a/guest/hals/keymint/remote/remote_keymaster.h b/guest/hals/keymint/remote/remote_keymaster.h
deleted file mode 100644
index bd8601284..000000000
--- a/guest/hals/keymint/remote/remote_keymaster.h
+++ /dev/null
@@ -1,95 +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.
- */
-
-#ifndef REMOTE_KEYMASTER_H_
-#define REMOTE_KEYMASTER_H_
-
-#include <keymaster/android_keymaster_messages.h>
-
-#include "common/libs/security/keymaster_channel.h"
-
-namespace keymaster {
-
-class RemoteKeymaster {
- private:
- cuttlefish::KeymasterChannel* channel_;
- const uint32_t message_version_;
-
- void ForwardCommand(AndroidKeymasterCommand command, const Serializable& req,
- KeymasterResponse* rsp);
-
- public:
- RemoteKeymaster(cuttlefish::KeymasterChannel*,
- uint32_t message_version = kDefaultMessageVersion);
- ~RemoteKeymaster();
- bool Initialize();
- void GetVersion(const GetVersionRequest& request,
- GetVersionResponse* response);
- void SupportedAlgorithms(const SupportedAlgorithmsRequest& request,
- SupportedAlgorithmsResponse* response);
- void SupportedBlockModes(const SupportedBlockModesRequest& request,
- SupportedBlockModesResponse* response);
- void SupportedPaddingModes(const SupportedPaddingModesRequest& request,
- SupportedPaddingModesResponse* response);
- void SupportedDigests(const SupportedDigestsRequest& request,
- SupportedDigestsResponse* response);
- void SupportedImportFormats(const SupportedImportFormatsRequest& request,
- SupportedImportFormatsResponse* response);
- void SupportedExportFormats(const SupportedExportFormatsRequest& request,
- SupportedExportFormatsResponse* response);
- void AddRngEntropy(const AddEntropyRequest& request,
- AddEntropyResponse* response);
- void Configure(const ConfigureRequest& request, ConfigureResponse* response);
- void GenerateKey(const GenerateKeyRequest& request,
- GenerateKeyResponse* response);
- void GetKeyCharacteristics(const GetKeyCharacteristicsRequest& request,
- GetKeyCharacteristicsResponse* response);
- void ImportKey(const ImportKeyRequest& request, ImportKeyResponse* response);
- void ImportWrappedKey(const ImportWrappedKeyRequest& request,
- ImportWrappedKeyResponse* response);
- void ExportKey(const ExportKeyRequest& request, ExportKeyResponse* response);
- void AttestKey(const AttestKeyRequest& request, AttestKeyResponse* response);
- void UpgradeKey(const UpgradeKeyRequest& request,
- UpgradeKeyResponse* response);
- void DeleteKey(const DeleteKeyRequest& request, DeleteKeyResponse* response);
- void DeleteAllKeys(const DeleteAllKeysRequest& request,
- DeleteAllKeysResponse* response);
- void BeginOperation(const BeginOperationRequest& request,
- BeginOperationResponse* response);
- void UpdateOperation(const UpdateOperationRequest& request,
- UpdateOperationResponse* response);
- void FinishOperation(const FinishOperationRequest& request,
- FinishOperationResponse* response);
- void AbortOperation(const AbortOperationRequest& request,
- AbortOperationResponse* response);
- GetHmacSharingParametersResponse GetHmacSharingParameters();
- ComputeSharedHmacResponse ComputeSharedHmac(
- const ComputeSharedHmacRequest& request);
- VerifyAuthorizationResponse VerifyAuthorization(
- const VerifyAuthorizationRequest& request);
- DeviceLockedResponse DeviceLocked(const DeviceLockedRequest& request);
- EarlyBootEndedResponse EarlyBootEnded();
- void GenerateTimestampToken(GenerateTimestampTokenRequest& request,
- GenerateTimestampTokenResponse* response);
-
- // CF HAL and remote sides are always compiled together, so will never
- // disagree about message versions.
- uint32_t message_version() { return message_version_; }
-};
-
-} // namespace keymaster
-
-#endif // REMOTE_KEYMASTER_H_
diff --git a/guest/hals/keymint/remote/remote_keymint_device.cpp b/guest/hals/keymint/remote/remote_keymint_device.cpp
deleted file mode 100644
index 55903b789..000000000
--- a/guest/hals/keymint/remote/remote_keymint_device.cpp
+++ /dev/null
@@ -1,422 +0,0 @@
-/*
- * Copyright 2020, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "android.hardware.security.keymint-impl.remote"
-#include <android-base/logging.h>
-
-#include "guest/hals/keymint/remote/remote_keymint_device.h"
-
-#include <aidl/android/hardware/security/keymint/ErrorCode.h>
-
-#include <keymaster/android_keymaster.h>
-#include <keymaster/contexts/pure_soft_keymaster_context.h>
-#include <keymaster/keymaster_configuration.h>
-
-#include "KeyMintUtils.h"
-#include "guest/hals/keymint/remote/remote_keymint_operation.h"
-
-namespace aidl::android::hardware::security::keymint {
-
-using namespace ::keymaster;
-using namespace km_utils;
-using secureclock::TimeStampToken;
-
-namespace {
-
-vector<KeyCharacteristics> convertKeyCharacteristics(
- SecurityLevel keyMintSecurityLevel, const AuthorizationSet& sw_enforced,
- const AuthorizationSet& hw_enforced) {
- KeyCharacteristics keyMintEnforced{keyMintSecurityLevel, {}};
-
- if (keyMintSecurityLevel != SecurityLevel::SOFTWARE) {
- // We're pretending to be TRUSTED_ENVIRONMENT or STRONGBOX.
- keyMintEnforced.authorizations = kmParamSet2Aidl(hw_enforced);
- // Put all the software authorizations in the keystore list.
- KeyCharacteristics keystoreEnforced{SecurityLevel::KEYSTORE,
- kmParamSet2Aidl(sw_enforced)};
- return {std::move(keyMintEnforced), std::move(keystoreEnforced)};
- }
-
- KeyCharacteristics keystoreEnforced{SecurityLevel::KEYSTORE, {}};
- CHECK(hw_enforced.empty())
- << "Hardware-enforced list is non-empty for pure SW KeyMint";
-
- // This is a pure software implementation, so all tags are in sw_enforced.
- // We need to walk through the SW-enforced list and figure out which tags to
- // return in the software list and which in the keystore list.
-
- for (auto& entry : sw_enforced) {
- switch (entry.tag) {
- /* Invalid and unused */
- case KM_TAG_ECIES_SINGLE_HASH_MODE:
- case KM_TAG_INVALID:
- case KM_TAG_KDF:
- case KM_TAG_ROLLBACK_RESISTANCE:
- CHECK(false) << "We shouldn't see tag " << entry.tag;
- break;
-
- /* Unimplemented */
- case KM_TAG_ALLOW_WHILE_ON_BODY:
- case KM_TAG_BOOTLOADER_ONLY:
- case KM_TAG_ROLLBACK_RESISTANT:
- case KM_TAG_STORAGE_KEY:
- break;
-
- /* Unenforceable */
- case KM_TAG_CREATION_DATETIME:
- break;
-
- /* Disallowed in KeyCharacteristics */
- case KM_TAG_APPLICATION_DATA:
- case KM_TAG_ATTESTATION_APPLICATION_ID:
- break;
-
- /* Not key characteristics */
- case KM_TAG_ASSOCIATED_DATA:
- case KM_TAG_ATTESTATION_CHALLENGE:
- case KM_TAG_ATTESTATION_ID_BRAND:
- case KM_TAG_ATTESTATION_ID_DEVICE:
- case KM_TAG_ATTESTATION_ID_IMEI:
- case KM_TAG_ATTESTATION_ID_MANUFACTURER:
- case KM_TAG_ATTESTATION_ID_MEID:
- case KM_TAG_ATTESTATION_ID_MODEL:
- case KM_TAG_ATTESTATION_ID_PRODUCT:
- case KM_TAG_ATTESTATION_ID_SERIAL:
- case KM_TAG_AUTH_TOKEN:
- case KM_TAG_CERTIFICATE_SERIAL:
- case KM_TAG_CERTIFICATE_SUBJECT:
- case KM_TAG_CERTIFICATE_NOT_AFTER:
- case KM_TAG_CERTIFICATE_NOT_BEFORE:
- case KM_TAG_CONFIRMATION_TOKEN:
- case KM_TAG_DEVICE_UNIQUE_ATTESTATION:
- case KM_TAG_IDENTITY_CREDENTIAL_KEY:
- case KM_TAG_MAC_LENGTH:
- case KM_TAG_NONCE:
- case KM_TAG_RESET_SINCE_ID_ROTATION:
- case KM_TAG_ROOT_OF_TRUST:
- case KM_TAG_UNIQUE_ID:
- break;
-
- /* KeyMint-enforced */
- case KM_TAG_ALGORITHM:
- case KM_TAG_APPLICATION_ID:
- case KM_TAG_AUTH_TIMEOUT:
- case KM_TAG_BLOB_USAGE_REQUIREMENTS:
- case KM_TAG_BLOCK_MODE:
- case KM_TAG_BOOT_PATCHLEVEL:
- case KM_TAG_CALLER_NONCE:
- case KM_TAG_DIGEST:
- case KM_TAG_EARLY_BOOT_ONLY:
- case KM_TAG_EC_CURVE:
- case KM_TAG_EXPORTABLE:
- case KM_TAG_INCLUDE_UNIQUE_ID:
- case KM_TAG_KEY_SIZE:
- case KM_TAG_MAX_USES_PER_BOOT:
- case KM_TAG_MIN_MAC_LENGTH:
- case KM_TAG_MIN_SECONDS_BETWEEN_OPS:
- case KM_TAG_NO_AUTH_REQUIRED:
- case KM_TAG_ORIGIN:
- case KM_TAG_OS_PATCHLEVEL:
- case KM_TAG_OS_VERSION:
- case KM_TAG_PADDING:
- case KM_TAG_PURPOSE:
- case KM_TAG_RSA_OAEP_MGF_DIGEST:
- case KM_TAG_RSA_PUBLIC_EXPONENT:
- case KM_TAG_UNLOCKED_DEVICE_REQUIRED:
- case KM_TAG_USER_AUTH_TYPE:
- case KM_TAG_USER_SECURE_ID:
- case KM_TAG_TRUSTED_CONFIRMATION_REQUIRED:
- case KM_TAG_TRUSTED_USER_PRESENCE_REQUIRED:
- case KM_TAG_VENDOR_PATCHLEVEL:
- keyMintEnforced.authorizations.push_back(kmParam2Aidl(entry));
- break;
-
- /* Keystore-enforced */
- case KM_TAG_ACTIVE_DATETIME:
- case KM_TAG_ALL_APPLICATIONS:
- case KM_TAG_ALL_USERS:
- case KM_TAG_MAX_BOOT_LEVEL:
- case KM_TAG_ORIGINATION_EXPIRE_DATETIME:
- case KM_TAG_USAGE_EXPIRE_DATETIME:
- case KM_TAG_USER_ID:
- case KM_TAG_USAGE_COUNT_LIMIT:
- keystoreEnforced.authorizations.push_back(kmParam2Aidl(entry));
- break;
- }
- }
-
- vector<KeyCharacteristics> retval;
- retval.reserve(2);
- if (!keyMintEnforced.authorizations.empty())
- retval.push_back(std::move(keyMintEnforced));
- if (!keystoreEnforced.authorizations.empty())
- retval.push_back(std::move(keystoreEnforced));
-
- return retval;
-}
-
-Certificate convertCertificate(const keymaster_blob_t& cert) {
- return {std::vector<uint8_t>(cert.data, cert.data + cert.data_length)};
-}
-
-vector<Certificate> convertCertificateChain(const CertificateChain& chain) {
- vector<Certificate> retval;
- retval.reserve(chain.entry_count);
- std::transform(chain.begin(), chain.end(), std::back_inserter(retval),
- convertCertificate);
- return retval;
-}
-
-} // namespace
-
-RemoteKeyMintDevice::RemoteKeyMintDevice(::keymaster::RemoteKeymaster& impl,
- SecurityLevel securityLevel)
- : impl_(impl), securityLevel_(securityLevel) {}
-
-RemoteKeyMintDevice::~RemoteKeyMintDevice() {}
-
-ScopedAStatus RemoteKeyMintDevice::getHardwareInfo(KeyMintHardwareInfo* info) {
- info->versionNumber = 1;
- info->securityLevel = securityLevel_;
- info->keyMintName = "RemoteKeyMintDevice";
- info->keyMintAuthorName = "Google";
- info->timestampTokenRequired = false;
- return ScopedAStatus::ok();
-}
-
-ScopedAStatus RemoteKeyMintDevice::addRngEntropy(const vector<uint8_t>& data) {
- if (data.size() == 0) {
- return ScopedAStatus::ok();
- }
-
- AddEntropyRequest request(impl_.message_version());
- request.random_data.Reinitialize(data.data(), data.size());
-
- AddEntropyResponse response(impl_.message_version());
- impl_.AddRngEntropy(request, &response);
-
- return kmError2ScopedAStatus(response.error);
-}
-
-ScopedAStatus RemoteKeyMintDevice::generateKey(
- const vector<KeyParameter>& keyParams,
- const optional<AttestationKey>& attestationKey,
- KeyCreationResult* creationResult) {
- GenerateKeyRequest request(impl_.message_version());
- request.key_description.Reinitialize(KmParamSet(keyParams));
- if (attestationKey) {
- request.attestation_signing_key_blob = KeymasterKeyBlob(
- attestationKey->keyBlob.data(), attestationKey->keyBlob.size());
- request.attest_key_params.Reinitialize(
- KmParamSet(attestationKey->attestKeyParams));
- request.issuer_subject =
- KeymasterBlob(attestationKey->issuerSubjectName.data(),
- attestationKey->issuerSubjectName.size());
- }
-
- GenerateKeyResponse response(impl_.message_version());
- impl_.GenerateKey(request, &response);
-
- if (response.error != KM_ERROR_OK) {
- // Note a key difference between this current aidl and previous hal, is
- // that hal returns void where as aidl returns the error status. If
- // aidl returns error, then aidl will not return any change you may make
- // to the out parameters. This is quite different from hal where all
- // output variable can be modified due to hal returning void.
- //
- // So the caller need to be aware not to expect aidl functions to clear
- // the output variables for you in case of error. If you left some
- // wrong data set in the out parameters, they will stay there.
- return kmError2ScopedAStatus(response.error);
- }
-
- creationResult->keyBlob = kmBlob2vector(response.key_blob);
- creationResult->keyCharacteristics = convertKeyCharacteristics(
- securityLevel_, response.unenforced, response.enforced);
- creationResult->certificateChain =
- convertCertificateChain(response.certificate_chain);
- return ScopedAStatus::ok();
-}
-
-ScopedAStatus RemoteKeyMintDevice::importKey(
- const vector<KeyParameter>& keyParams, KeyFormat keyFormat,
- const vector<uint8_t>& keyData,
- const optional<AttestationKey>& attestationKey,
- KeyCreationResult* creationResult) {
- ImportKeyRequest request(impl_.message_version());
- request.key_description.Reinitialize(KmParamSet(keyParams));
- request.key_format = legacy_enum_conversion(keyFormat);
- request.key_data = KeymasterKeyBlob(keyData.data(), keyData.size());
- if (attestationKey) {
- request.attestation_signing_key_blob = KeymasterKeyBlob(
- attestationKey->keyBlob.data(), attestationKey->keyBlob.size());
- request.attest_key_params.Reinitialize(
- KmParamSet(attestationKey->attestKeyParams));
- request.issuer_subject =
- KeymasterBlob(attestationKey->issuerSubjectName.data(),
- attestationKey->issuerSubjectName.size());
- }
-
- ImportKeyResponse response(impl_.message_version());
- impl_.ImportKey(request, &response);
-
- if (response.error != KM_ERROR_OK) {
- return kmError2ScopedAStatus(response.error);
- }
-
- creationResult->keyBlob = kmBlob2vector(response.key_blob);
- creationResult->keyCharacteristics = convertKeyCharacteristics(
- securityLevel_, response.unenforced, response.enforced);
- creationResult->certificateChain =
- convertCertificateChain(response.certificate_chain);
-
- return ScopedAStatus::ok();
-}
-
-ScopedAStatus RemoteKeyMintDevice::importWrappedKey(
- const vector<uint8_t>& wrappedKeyData, //
- const vector<uint8_t>& wrappingKeyBlob, //
- const vector<uint8_t>& maskingKey, //
- const vector<KeyParameter>& unwrappingParams, //
- int64_t passwordSid, int64_t biometricSid, //
- KeyCreationResult* creationResult) {
- ImportWrappedKeyRequest request(impl_.message_version());
- request.SetWrappedMaterial(wrappedKeyData.data(), wrappedKeyData.size());
- request.SetWrappingMaterial(wrappingKeyBlob.data(), wrappingKeyBlob.size());
- request.SetMaskingKeyMaterial(maskingKey.data(), maskingKey.size());
- request.additional_params.Reinitialize(KmParamSet(unwrappingParams));
- request.password_sid = static_cast<uint64_t>(passwordSid);
- request.biometric_sid = static_cast<uint64_t>(biometricSid);
-
- ImportWrappedKeyResponse response(impl_.message_version());
- impl_.ImportWrappedKey(request, &response);
-
- if (response.error != KM_ERROR_OK) {
- return kmError2ScopedAStatus(response.error);
- }
-
- creationResult->keyBlob = kmBlob2vector(response.key_blob);
- creationResult->keyCharacteristics = convertKeyCharacteristics(
- securityLevel_, response.unenforced, response.enforced);
- creationResult->certificateChain =
- convertCertificateChain(response.certificate_chain);
-
- return ScopedAStatus::ok();
-}
-
-ScopedAStatus RemoteKeyMintDevice::upgradeKey(
- const vector<uint8_t>& keyBlobToUpgrade,
- const vector<KeyParameter>& upgradeParams, vector<uint8_t>* keyBlob) {
- UpgradeKeyRequest request(impl_.message_version());
- request.SetKeyMaterial(keyBlobToUpgrade.data(), keyBlobToUpgrade.size());
- request.upgrade_params.Reinitialize(KmParamSet(upgradeParams));
-
- UpgradeKeyResponse response(impl_.message_version());
- impl_.UpgradeKey(request, &response);
-
- if (response.error != KM_ERROR_OK) {
- return kmError2ScopedAStatus(response.error);
- }
-
- *keyBlob = kmBlob2vector(response.upgraded_key);
- return ScopedAStatus::ok();
-}
-
-ScopedAStatus RemoteKeyMintDevice::deleteKey(const vector<uint8_t>& keyBlob) {
- DeleteKeyRequest request(impl_.message_version());
- request.SetKeyMaterial(keyBlob.data(), keyBlob.size());
-
- DeleteKeyResponse response(impl_.message_version());
- impl_.DeleteKey(request, &response);
-
- return kmError2ScopedAStatus(response.error);
-}
-
-ScopedAStatus RemoteKeyMintDevice::deleteAllKeys() {
- // There's nothing to be done to delete software key blobs.
- DeleteAllKeysRequest request(impl_.message_version());
- DeleteAllKeysResponse response(impl_.message_version());
- impl_.DeleteAllKeys(request, &response);
-
- return kmError2ScopedAStatus(response.error);
-}
-
-ScopedAStatus RemoteKeyMintDevice::destroyAttestationIds() {
- return kmError2ScopedAStatus(KM_ERROR_UNIMPLEMENTED);
-}
-
-ScopedAStatus RemoteKeyMintDevice::begin(
- KeyPurpose purpose, const vector<uint8_t>& keyBlob,
- const vector<KeyParameter>& params,
- const optional<HardwareAuthToken>& authToken, BeginResult* result) {
- BeginOperationRequest request(impl_.message_version());
- request.purpose = legacy_enum_conversion(purpose);
- request.SetKeyMaterial(keyBlob.data(), keyBlob.size());
- request.additional_params.Reinitialize(KmParamSet(params));
-
- vector<uint8_t> vector_token = authToken2AidlVec(authToken);
- request.additional_params.push_back(
- TAG_AUTH_TOKEN, reinterpret_cast<uint8_t*>(vector_token.data()),
- vector_token.size());
-
- BeginOperationResponse response(impl_.message_version());
- impl_.BeginOperation(request, &response);
-
- if (response.error != KM_ERROR_OK) {
- return kmError2ScopedAStatus(response.error);
- }
-
- result->params = kmParamSet2Aidl(response.output_params);
- result->challenge = response.op_handle;
- result->operation = ndk::SharedRefBase::make<RemoteKeyMintOperation>(
- impl_, response.op_handle);
- return ScopedAStatus::ok();
-}
-
-ScopedAStatus RemoteKeyMintDevice::deviceLocked(
- bool passwordOnly,
- const std::optional<secureclock::TimeStampToken>& timestampToken) {
- DeviceLockedRequest request(impl_.message_version());
- request.passwordOnly = passwordOnly;
- if (timestampToken.has_value()) {
- request.token.challenge = timestampToken->challenge;
- request.token.mac = {timestampToken->mac.data(),
- timestampToken->mac.size()};
- request.token.timestamp = timestampToken->timestamp.milliSeconds;
- }
- DeviceLockedResponse response = impl_.DeviceLocked(request);
- return kmError2ScopedAStatus(response.error);
-}
-
-ScopedAStatus RemoteKeyMintDevice::earlyBootEnded() {
- EarlyBootEndedResponse response = impl_.EarlyBootEnded();
- return kmError2ScopedAStatus(response.error);
-}
-
-ScopedAStatus RemoteKeyMintDevice::convertStorageKeyToEphemeral(
- const std::vector<uint8_t>& /* storageKeyBlob */,
- std::vector<uint8_t>* /* ephemeralKeyBlob */) {
- return kmError2ScopedAStatus(KM_ERROR_UNIMPLEMENTED);
-}
-
-ScopedAStatus RemoteKeyMintDevice::getKeyCharacteristics(
- const std::vector<uint8_t>& /* storageKeyBlob */,
- const std::vector<uint8_t>& /* appId */,
- const std::vector<uint8_t>& /* appData */,
- std::vector<KeyCharacteristics>* /* keyCharacteristics */) {
- return kmError2ScopedAStatus(KM_ERROR_UNIMPLEMENTED);
-}
-} // namespace aidl::android::hardware::security::keymint
diff --git a/guest/hals/keymint/remote/remote_keymint_device.h b/guest/hals/keymint/remote/remote_keymint_device.h
deleted file mode 100644
index c3ebad1fc..000000000
--- a/guest/hals/keymint/remote/remote_keymint_device.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright 2020, 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 <aidl/android/hardware/security/keymint/BnKeyMintDevice.h>
-#include <aidl/android/hardware/security/keymint/BnKeyMintOperation.h>
-#include <aidl/android/hardware/security/keymint/HardwareAuthToken.h>
-
-#include "guest/hals/keymint/remote/remote_keymaster.h"
-
-namespace aidl::android::hardware::security::keymint {
-using ::ndk::ScopedAStatus;
-using std::optional;
-using std::shared_ptr;
-using std::vector;
-
-using secureclock::TimeStampToken;
-
-class RemoteKeyMintDevice : public BnKeyMintDevice {
- public:
- explicit RemoteKeyMintDevice(::keymaster::RemoteKeymaster&, SecurityLevel);
- virtual ~RemoteKeyMintDevice();
-
- ScopedAStatus getHardwareInfo(KeyMintHardwareInfo* info) override;
-
- ScopedAStatus addRngEntropy(const vector<uint8_t>& data) override;
-
- ScopedAStatus generateKey(const vector<KeyParameter>& keyParams,
- const optional<AttestationKey>& attestationKey,
- KeyCreationResult* creationResult) override;
-
- ScopedAStatus importKey(const vector<KeyParameter>& keyParams,
- KeyFormat keyFormat, const vector<uint8_t>& keyData,
- const optional<AttestationKey>& attestationKey,
- KeyCreationResult* creationResult) override;
-
- ScopedAStatus importWrappedKey(const vector<uint8_t>& wrappedKeyData,
- const vector<uint8_t>& wrappingKeyBlob,
- const vector<uint8_t>& maskingKey,
- const vector<KeyParameter>& unwrappingParams,
- int64_t passwordSid, int64_t biometricSid,
- KeyCreationResult* creationResult) override;
-
- ScopedAStatus upgradeKey(const vector<uint8_t>& keyBlobToUpgrade,
- const vector<KeyParameter>& upgradeParams,
- vector<uint8_t>* keyBlob) override;
-
- ScopedAStatus deleteKey(const vector<uint8_t>& keyBlob) override;
- ScopedAStatus deleteAllKeys() override;
- ScopedAStatus destroyAttestationIds() override;
-
- ScopedAStatus begin(KeyPurpose purpose, const vector<uint8_t>& keyBlob,
- const vector<KeyParameter>& params,
- const optional<HardwareAuthToken>& authToken,
- BeginResult* result) override;
-
- ScopedAStatus deviceLocked(
- bool passwordOnly,
- const optional<TimeStampToken>& timestampToken) override;
- ScopedAStatus earlyBootEnded() override;
-
- ScopedAStatus convertStorageKeyToEphemeral(
- const std::vector<uint8_t>& storageKeyBlob,
- std::vector<uint8_t>* ephemeralKeyBlob) override;
-
- ScopedAStatus getKeyCharacteristics(
- const std::vector<uint8_t>& storageKeyBlob,
- const std::vector<uint8_t>& appId, const std::vector<uint8_t>& appData,
- std::vector<KeyCharacteristics>* keyCharacteristics) override;
-
- protected:
- ::keymaster::RemoteKeymaster& impl_;
- SecurityLevel securityLevel_;
-};
-
-} // namespace aidl::android::hardware::security::keymint
diff --git a/guest/hals/keymint/remote/remote_keymint_operation.cpp b/guest/hals/keymint/remote/remote_keymint_operation.cpp
deleted file mode 100644
index b88715a95..000000000
--- a/guest/hals/keymint/remote/remote_keymint_operation.cpp
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright 2020, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "android.hardware.security.keymint-impl.remote"
-#include <log/log.h>
-
-#include "guest/hals/keymint/remote/remote_keymint_operation.h"
-
-#include <aidl/android/hardware/security/keymint/ErrorCode.h>
-#include <aidl/android/hardware/security/secureclock/ISecureClock.h>
-
-#include <keymaster/android_keymaster.h>
-
-#include "KeyMintUtils.h"
-
-namespace aidl::android::hardware::security::keymint {
-
-using ::keymaster::AbortOperationRequest;
-using ::keymaster::AbortOperationResponse;
-using ::keymaster::Buffer;
-using ::keymaster::FinishOperationRequest;
-using ::keymaster::FinishOperationResponse;
-using ::keymaster::TAG_ASSOCIATED_DATA;
-using ::keymaster::UpdateOperationRequest;
-using ::keymaster::UpdateOperationResponse;
-using secureclock::TimeStampToken;
-using namespace km_utils;
-
-RemoteKeyMintOperation::RemoteKeyMintOperation(
- ::keymaster::RemoteKeymaster& impl, keymaster_operation_handle_t opHandle)
- : impl_(impl), opHandle_(opHandle) {}
-
-RemoteKeyMintOperation::~RemoteKeyMintOperation() {
- if (opHandle_ != 0) {
- abort();
- }
-}
-
-ScopedAStatus RemoteKeyMintOperation::updateAad(
- const vector<uint8_t>& input,
- const optional<HardwareAuthToken>& /* authToken */,
- const optional<TimeStampToken>& /* timestampToken */) {
- UpdateOperationRequest request(impl_.message_version());
- request.op_handle = opHandle_;
- request.additional_params.push_back(TAG_ASSOCIATED_DATA, input.data(),
- input.size());
-
- UpdateOperationResponse response(impl_.message_version());
- impl_.UpdateOperation(request, &response);
-
- return kmError2ScopedAStatus(response.error);
-}
-
-ScopedAStatus RemoteKeyMintOperation::update(
- const vector<uint8_t>& input,
- const optional<HardwareAuthToken>& /* authToken */,
- const optional<TimeStampToken>&
- /* timestampToken */,
- vector<uint8_t>* output) {
- if (!output) return kmError2ScopedAStatus(KM_ERROR_OUTPUT_PARAMETER_NULL);
-
- UpdateOperationRequest request(impl_.message_version());
- request.op_handle = opHandle_;
- request.input.Reinitialize(input.data(), input.size());
-
- UpdateOperationResponse response(impl_.message_version());
- impl_.UpdateOperation(request, &response);
-
- if (response.error != KM_ERROR_OK)
- return kmError2ScopedAStatus(response.error);
- if (response.input_consumed != request.input.buffer_size()) {
- return kmError2ScopedAStatus(KM_ERROR_UNKNOWN_ERROR);
- }
-
- *output = kmBuffer2vector(response.output);
- return ScopedAStatus::ok();
-}
-
-ScopedAStatus RemoteKeyMintOperation::finish(
- const optional<vector<uint8_t>>& input, //
- const optional<vector<uint8_t>>& signature, //
- const optional<HardwareAuthToken>& /* authToken */,
- const optional<TimeStampToken>& /* timestampToken */,
- const optional<vector<uint8_t>>& /* confirmationToken */,
- vector<uint8_t>* output) {
- if (!output) {
- return ScopedAStatus(AStatus_fromServiceSpecificError(
- static_cast<int32_t>(ErrorCode::OUTPUT_PARAMETER_NULL)));
- }
-
- FinishOperationRequest request(impl_.message_version());
- request.op_handle = opHandle_;
- if (input) request.input.Reinitialize(input->data(), input->size());
- if (signature)
- request.signature.Reinitialize(signature->data(), signature->size());
-
- FinishOperationResponse response(impl_.message_version());
- impl_.FinishOperation(request, &response);
- opHandle_ = 0;
-
- if (response.error != KM_ERROR_OK)
- return kmError2ScopedAStatus(response.error);
-
- *output = kmBuffer2vector(response.output);
- return ScopedAStatus::ok();
-}
-
-ScopedAStatus RemoteKeyMintOperation::abort() {
- AbortOperationRequest request(impl_.message_version());
- request.op_handle = opHandle_;
-
- AbortOperationResponse response(impl_.message_version());
- impl_.AbortOperation(request, &response);
- opHandle_ = 0;
-
- return kmError2ScopedAStatus(response.error);
-}
-
-} // namespace aidl::android::hardware::security::keymint
diff --git a/guest/hals/keymint/remote/remote_keymint_operation.h b/guest/hals/keymint/remote/remote_keymint_operation.h
deleted file mode 100644
index eb3c78b6d..000000000
--- a/guest/hals/keymint/remote/remote_keymint_operation.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright 2020, 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 <aidl/android/hardware/security/keymint/BnKeyMintOperation.h>
-#include <aidl/android/hardware/security/secureclock/ISecureClock.h>
-
-#include <hardware/keymaster_defs.h>
-
-#include "guest/hals/keymint/remote/remote_keymaster.h"
-
-namespace keymaster {
-class AndroidKeymaster;
-}
-
-namespace aidl::android::hardware::security::keymint {
-
-using ::ndk::ScopedAStatus;
-using secureclock::TimeStampToken;
-using std::optional;
-using std::shared_ptr;
-using std::string;
-using std::vector;
-
-class RemoteKeyMintOperation : public BnKeyMintOperation {
- public:
- explicit RemoteKeyMintOperation(::keymaster::RemoteKeymaster& implementation,
- keymaster_operation_handle_t opHandle);
- virtual ~RemoteKeyMintOperation();
-
- ScopedAStatus updateAad(
- const vector<uint8_t>& input,
- const optional<HardwareAuthToken>& authToken,
- const optional<TimeStampToken>& timestampToken) override;
-
- ScopedAStatus update(const vector<uint8_t>& input,
- const optional<HardwareAuthToken>& authToken,
- const optional<TimeStampToken>& timestampToken,
- vector<uint8_t>* output) override;
-
- ScopedAStatus finish(const optional<vector<uint8_t>>& input, //
- const optional<vector<uint8_t>>& signature, //
- const optional<HardwareAuthToken>& authToken, //
- const optional<TimeStampToken>& timestampToken,
- const optional<vector<uint8_t>>& confirmationToken,
- vector<uint8_t>* output) override;
-
- ScopedAStatus abort() override;
-
- protected:
- ::keymaster::RemoteKeymaster& impl_;
- keymaster_operation_handle_t opHandle_;
-};
-
-} // namespace aidl::android::hardware::security::keymint
diff --git a/guest/hals/keymint/remote/remote_secure_clock.cpp b/guest/hals/keymint/remote/remote_secure_clock.cpp
deleted file mode 100644
index 307e0ab42..000000000
--- a/guest/hals/keymint/remote/remote_secure_clock.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright 2020, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "android.hardware.security.secureclock-impl.remote"
-#include <log/log.h>
-
-#include "guest/hals/keymint/remote/remote_secure_clock.h"
-
-#include <aidl/android/hardware/security/keymint/ErrorCode.h>
-
-#include <keymaster/android_keymaster.h>
-#include <keymaster/keymaster_configuration.h>
-#include "KeyMintUtils.h"
-
-namespace aidl::android::hardware::security::secureclock {
-
-using namespace ::keymaster;
-using namespace ::aidl::android::hardware::security::keymint::km_utils;
-
-RemoteSecureClock::RemoteSecureClock(keymaster::RemoteKeymaster& impl)
- : impl_(impl) {}
-
-RemoteSecureClock::~RemoteSecureClock() {}
-
-ScopedAStatus RemoteSecureClock::generateTimeStamp(int64_t challenge,
- TimeStampToken* token) {
- GenerateTimestampTokenRequest request(impl_.message_version());
- request.challenge = challenge;
- GenerateTimestampTokenResponse response(request.message_version);
- impl_.GenerateTimestampToken(request, &response);
- if (response.error != KM_ERROR_OK) {
- return kmError2ScopedAStatus(response.error);
- }
- token->challenge = response.token.challenge;
- token->timestamp.milliSeconds =
- static_cast<int64_t>(response.token.timestamp);
- token->mac = kmBlob2vector(response.token.mac);
- return ScopedAStatus::ok();
-}
-
-} // namespace aidl::android::hardware::security::secureclock
diff --git a/guest/hals/keymint/remote/remote_secure_clock.h b/guest/hals/keymint/remote/remote_secure_clock.h
deleted file mode 100644
index a0330e254..000000000
--- a/guest/hals/keymint/remote/remote_secure_clock.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright 2020, 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 <aidl/android/hardware/security/secureclock/BnSecureClock.h>
-#include <aidl/android/hardware/security/secureclock/TimeStampToken.h>
-#include <aidl/android/hardware/security/secureclock/Timestamp.h>
-#include "guest/hals/keymint/remote/remote_keymaster.h"
-
-namespace keymaster {
-class AndroidKeymaster;
-}
-
-namespace aidl::android::hardware::security::secureclock {
-using ::ndk::ScopedAStatus;
-using std::shared_ptr;
-using std::vector;
-
-class RemoteSecureClock : public BnSecureClock {
- public:
- explicit RemoteSecureClock(::keymaster::RemoteKeymaster& keymint);
- virtual ~RemoteSecureClock();
- ScopedAStatus generateTimeStamp(int64_t challenge,
- TimeStampToken* token) override;
-
- private:
- ::keymaster::RemoteKeymaster& impl_;
-};
-} // namespace aidl::android::hardware::security::secureclock
diff --git a/guest/hals/keymint/remote/remote_shared_secret.cpp b/guest/hals/keymint/remote/remote_shared_secret.cpp
deleted file mode 100644
index 6c5090093..000000000
--- a/guest/hals/keymint/remote/remote_shared_secret.cpp
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright 2020, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "android.hardware.security.sharedsecret-impl"
-#include <log/log.h>
-
-#include "guest/hals/keymint/remote/remote_shared_secret.h"
-
-#include <aidl/android/hardware/security/keymint/ErrorCode.h>
-#include <keymaster/android_keymaster.h>
-#include "KeyMintUtils.h"
-
-namespace aidl::android::hardware::security::sharedsecret {
-
-using namespace ::keymaster;
-using namespace ::aidl::android::hardware::security::keymint::km_utils;
-
-RemoteSharedSecret::RemoteSharedSecret(::keymaster::RemoteKeymaster& keymint)
- : impl_(keymint) {}
-
-RemoteSharedSecret::~RemoteSharedSecret() {}
-
-ScopedAStatus RemoteSharedSecret::getSharedSecretParameters(
- SharedSecretParameters* params) {
- auto response = impl_.GetHmacSharingParameters();
- params->seed = kmBlob2vector(response.params.seed);
- params->nonce = {std::begin(response.params.nonce),
- std::end(response.params.nonce)};
- return kmError2ScopedAStatus(response.error);
-}
-
-ScopedAStatus RemoteSharedSecret::computeSharedSecret(
- const vector<SharedSecretParameters>& params,
- vector<uint8_t>* sharingCheck) {
- ComputeSharedHmacRequest request(impl_.message_version());
- request.params_array.params_array =
- new keymaster::HmacSharingParameters[params.size()];
- request.params_array.num_params = params.size();
- for (size_t i = 0; i < params.size(); ++i) {
- request.params_array.params_array[i].seed = {params[i].seed.data(),
- params[i].seed.size()};
- if (sizeof(request.params_array.params_array[i].nonce) !=
- params[i].nonce.size()) {
- return kmError2ScopedAStatus(KM_ERROR_INVALID_ARGUMENT);
- }
- memcpy(request.params_array.params_array[i].nonce, params[i].nonce.data(),
- params[i].nonce.size());
- }
- auto response = impl_.ComputeSharedHmac(request);
- if (response.error == KM_ERROR_OK)
- *sharingCheck = kmBlob2vector(response.sharing_check);
- return kmError2ScopedAStatus(response.error);
-}
-
-} // namespace aidl::android::hardware::security::sharedsecret
diff --git a/guest/hals/keymint/remote/remote_shared_secret.h b/guest/hals/keymint/remote/remote_shared_secret.h
deleted file mode 100644
index 9c1aae257..000000000
--- a/guest/hals/keymint/remote/remote_shared_secret.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright 2020, 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 <aidl/android/hardware/security/sharedsecret/BnSharedSecret.h>
-#include <aidl/android/hardware/security/sharedsecret/SharedSecretParameters.h>
-#include "guest/hals/keymint/remote/remote_keymaster.h"
-
-namespace keymaster {
-class AndroidKeymaster;
-}
-namespace aidl::android::hardware::security::sharedsecret {
-using ::ndk::ScopedAStatus;
-using std::shared_ptr;
-using std::vector;
-
-class RemoteSharedSecret : public BnSharedSecret {
- public:
- explicit RemoteSharedSecret(::keymaster::RemoteKeymaster& keymint);
- virtual ~RemoteSharedSecret();
- ScopedAStatus getSharedSecretParameters(
- SharedSecretParameters* params) override;
- ScopedAStatus computeSharedSecret(
- const vector<SharedSecretParameters>& params,
- vector<uint8_t>* sharingCheck) override;
-
- private:
- ::keymaster::RemoteKeymaster& impl_;
-};
-} // namespace aidl::android::hardware::security::sharedsecret
diff --git a/guest/hals/keymint/remote/service.cpp b/guest/hals/keymint/remote/service.cpp
deleted file mode 100644
index 404df77f7..000000000
--- a/guest/hals/keymint/remote/service.cpp
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright 2020, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "android.hardware.security.keymint-service"
-
-#include <android-base/logging.h>
-#include <android/binder_manager.h>
-#include <android/binder_process.h>
-
-#include <keymaster/android_keymaster_messages.h>
-#include <keymaster/km_version.h>
-#include <keymaster/soft_keymaster_logger.h>
-#include "guest/hals/keymint/remote/remote_keymint_device.h"
-
-#include <guest/hals/keymint/remote/remote_keymaster.h>
-#include <guest/hals/keymint/remote/remote_keymint_device.h>
-#include <guest/hals/keymint/remote/remote_secure_clock.h>
-#include <guest/hals/keymint/remote/remote_shared_secret.h>
-#include "common/libs/fs/shared_fd.h"
-#include "common/libs/security/keymaster_channel.h"
-
-static const char device[] = "/dev/hvc3";
-
-using aidl::android::hardware::security::keymint::RemoteKeyMintDevice;
-using aidl::android::hardware::security::keymint::SecurityLevel;
-using aidl::android::hardware::security::secureclock::RemoteSecureClock;
-using aidl::android::hardware::security::sharedsecret::RemoteSharedSecret;
-
-template <typename T, class... Args>
-static std::shared_ptr<T> addService(Args&&... args) {
- std::shared_ptr<T> ser =
- ndk::SharedRefBase::make<T>(std::forward<Args>(args)...);
- auto instanceName = std::string(T::descriptor) + "/default";
- LOG(INFO) << "adding keymint service instance: " << instanceName;
- binder_status_t status =
- AServiceManager_addService(ser->asBinder().get(), instanceName.c_str());
- CHECK(status == STATUS_OK);
- return ser;
-}
-
-int main(int, char** argv) {
- android::base::InitLogging(argv, android::base::KernelLogger);
- // Zero threads seems like a useless pool, but below we'll join this thread to
- // it, increasing the pool size to 1.
- ABinderProcess_setThreadPoolMaxThreadCount(0);
- // Add Keymint Service
- auto fd = cuttlefish::SharedFD::Open(device, O_RDWR);
- if (!fd->IsOpen()) {
- LOG(FATAL) << "Could not connect to keymaster: " << fd->StrError();
- }
-
- if (fd->SetTerminalRaw() < 0) {
- LOG(FATAL) << "Could not make " << device
- << " a raw terminal: " << fd->StrError();
- }
-
- cuttlefish::KeymasterChannel keymasterChannel(fd, fd);
-
- keymaster::RemoteKeymaster remote_keymaster(
- &keymasterChannel, keymaster::MessageVersion(
- keymaster::KmVersion::KEYMINT_1, 0 /* km_date */));
-
- addService<RemoteKeyMintDevice>(remote_keymaster,
- SecurityLevel::TRUSTED_ENVIRONMENT);
- addService<RemoteSecureClock>(remote_keymaster);
- addService<RemoteSharedSecret>(remote_keymaster);
-
- ABinderProcess_joinThreadPool();
- return EXIT_FAILURE; // should not reach
-}
diff --git a/guest/hals/ril/.clang-format b/guest/hals/ril/.clang-format
deleted file mode 120000
index 5e8e20be2..000000000
--- a/guest/hals/ril/.clang-format
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../../build/soong/scripts/system-clang-format \ No newline at end of file
diff --git a/guest/hals/ril/Android.mk b/guest/hals/ril/Android.mk
new file mode 100644
index 000000000..808d4ec17
--- /dev/null
+++ b/guest/hals/ril/Android.mk
@@ -0,0 +1,51 @@
+# Copyright (C) 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ cuttlefish_ril.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+ liblog \
+ libcutils \
+ libutils \
+ ${CUTTLEFISH_LIBRIL_NAME} \
+ libcuttlefish_fs \
+ cuttlefish_net \
+ libbase \
+ libcuttlefish_device_config \
+
+LOCAL_C_INCLUDES := \
+ device/google/cuttlefish
+
+LOCAL_CFLAGS += \
+ -Wall \
+ -Werror \
+ $(VSOC_VERSION_CFLAGS)
+
+LOCAL_MODULE:= libcuttlefish-ril
+LOCAL_MODULE_TAGS := optional
+LOCAL_VENDOR_MODULE := true
+
+# See b/67109557
+ifeq (true, $(TARGET_TRANSLATE_2ND_ARCH))
+LOCAL_MULTILIB := first
+endif
+
+include $(BUILD_SHARED_LIBRARY)
+
+include $(call first-makefiles-under,$(LOCAL_PATH))
diff --git a/guest/hals/ril/cuttlefish_ril.cpp b/guest/hals/ril/cuttlefish_ril.cpp
new file mode 100644
index 000000000..29fca7ebb
--- /dev/null
+++ b/guest/hals/ril/cuttlefish_ril.cpp
@@ -0,0 +1,2609 @@
+/*
+** 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 ioogle/s 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 "guest/hals/ril/cuttlefish_ril.h"
+
+#include <cutils/properties.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <time.h>
+
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
+
+#include "common/libs/device_config/device_config.h"
+#include "common/libs/net/netlink_client.h"
+#include "common/libs/net/network_interface.h"
+#include "common/libs/net/network_interface_manager.h"
+
+#define CUTTLEFISH_RIL_VERSION_STRING "Android Cuttlefish RIL 1.4"
+
+/* Modem Technology bits */
+#define MDM_GSM 0x01
+#define MDM_WCDMA 0x02
+#define MDM_CDMA 0x04
+#define MDM_EVDO 0x08
+#define MDM_LTE 0x10
+
+typedef enum {
+ SIM_ABSENT = 0,
+ SIM_NOT_READY = 1,
+ SIM_READY = 2, // SIM_READY means the radio state is RADIO_STATE_SIM_READY
+ SIM_PIN = 3,
+ SIM_PUK = 4,
+ SIM_NETWORK_PERSONALIZATION = 5,
+ RUIM_ABSENT = 6,
+ RUIM_NOT_READY = 7,
+ RUIM_READY = 8,
+ RUIM_PIN = 9,
+ RUIM_PUK = 10,
+ RUIM_NETWORK_PERSONALIZATION = 11
+} SIM_Status;
+
+static std::unique_ptr<cvd::DeviceConfig> global_ril_config = nullptr;
+
+static const struct RIL_Env* gce_ril_env;
+
+static const struct timeval TIMEVAL_SIMPOLL = {3, 0};
+
+static time_t gce_ril_start_time;
+
+static void pollSIMState(void* param);
+
+RIL_RadioState gRadioPowerState = RADIO_STATE_OFF;
+RIL_RadioAccessFamily default_access = RAF_LTE;
+
+struct DataCall {
+ enum AllowedAuthenticationType { kNone = 0, kPap = 1, kChap = 2, kBoth = 3 };
+
+ enum ConnectionType {
+ kConnTypeIPv4,
+ kConnTypeIPv6,
+ kConnTypeIPv4v6,
+ kConnTypePPP
+ };
+
+ enum LinkState {
+ kLinkStateInactive = 0,
+ kLinkStateDown = 1,
+ kLinkStateUp = 2,
+ };
+
+ RIL_RadioTechnology technology_;
+ RIL_DataProfile profile_;
+ std::string access_point_;
+ std::string username_;
+ std::string password_;
+ AllowedAuthenticationType auth_type_;
+ ConnectionType connection_type_;
+ LinkState link_state_;
+ RIL_DataCallFailCause fail_cause_;
+ std::string other_properties_;
+};
+
+static std::string gSimPIN = "0000";
+static const std::string gSimPUK = "11223344";
+static int gSimPINAttempts = 0;
+static const int gSimPINAttemptsMax = 3;
+static SIM_Status gSimStatus = SIM_NOT_READY;
+static bool areUiccApplicationsEnabled = true;
+
+// SetUpNetworkInterface configures IP and Broadcast addresses on a RIL
+// controlled network interface.
+// This call returns true, if operation was successful.
+bool SetUpNetworkInterface(const char* ipaddr, int prefixlen,
+ const char* bcaddr) {
+ auto factory = cvd::NetlinkClientFactory::Default();
+ std::unique_ptr<cvd::NetlinkClient> nl(factory->New(NETLINK_ROUTE));
+ std::unique_ptr<cvd::NetworkInterfaceManager> nm(
+ cvd::NetworkInterfaceManager::New(factory));
+ std::unique_ptr<cvd::NetworkInterface> ni(nm->Open("rmnet0", "eth1"));
+
+ if (ni) {
+ ni->SetName("rmnet0");
+ ni->SetAddress(ipaddr);
+ ni->SetBroadcastAddress(bcaddr);
+ ni->SetPrefixLength(prefixlen);
+ ni->SetOperational(true);
+ bool res = nm->ApplyChanges(*ni);
+ if (!res) ALOGE("Could not configure rmnet0");
+ return res;
+ }
+ return false;
+}
+
+// TearDownNetworkInterface disables network interface.
+// This call returns true, if operation was successful.
+bool TearDownNetworkInterface() {
+ auto nm(cvd::NetworkInterfaceManager::New(nullptr));
+ auto ni(nm->Open("rmnet0", "eth1"));
+
+ if (ni) {
+ ni->SetOperational(false);
+ bool res = nm->ApplyChanges(*ni);
+ if (!res) ALOGE("Could not disable rmnet0");
+ return res;
+ }
+ return false;
+}
+
+static int gNextDataCallId = 8;
+static std::map<int, DataCall> gDataCalls;
+static bool gRilConnected = false;
+
+static int request_or_send_data_calllist(RIL_Token* t) {
+ RIL_Data_Call_Response_v11* responses =
+ new RIL_Data_Call_Response_v11[gDataCalls.size()];
+
+ int index = 0;
+
+ ALOGV("Query data call list: %zu data calls tracked.", gDataCalls.size());
+
+ for (std::map<int, DataCall>::iterator iter = gDataCalls.begin();
+ iter != gDataCalls.end(); ++iter, ++index) {
+ responses[index].status = iter->second.fail_cause_;
+ responses[index].suggestedRetryTime = -1;
+ responses[index].cid = iter->first;
+ responses[index].active = iter->second.link_state_;
+
+ switch (iter->second.connection_type_) {
+ case DataCall::kConnTypeIPv4:
+ responses[index].type = (char*)"IP";
+ break;
+ case DataCall::kConnTypeIPv6:
+ responses[index].type = (char*)"IPV6";
+ break;
+ case DataCall::kConnTypeIPv4v6:
+ responses[index].type = (char*)"IPV4V6";
+ break;
+ case DataCall::kConnTypePPP:
+ responses[index].type = (char*)"PPP";
+ break;
+ default:
+ responses[index].type = (char*)"IP";
+ break;
+ }
+
+ responses[index].ifname = (char*)"rmnet0";
+ responses[index].addresses =
+ const_cast<char*>(global_ril_config->ril_address_and_prefix());
+ responses[index].dnses = const_cast<char*>(global_ril_config->ril_dns());
+ responses[index].gateways = const_cast<char*>(global_ril_config->ril_gateway());
+ responses[index].pcscf = (char*)"";
+ responses[index].mtu = 1440;
+ }
+
+ bool new_conn_state = (gDataCalls.size() > 0);
+
+ if (gRilConnected != new_conn_state) {
+ time_t curr_time;
+ time(&curr_time);
+ double diff_in_secs = difftime(curr_time, gce_ril_start_time);
+
+ gRilConnected = new_conn_state;
+
+ if (new_conn_state) {
+ ALOGV("MOBILE_DATA_CONNECTED %.2lf seconds", diff_in_secs);
+ } else {
+ ALOGV("MOBILE_DATA_DISCONNECTED %.2lf seconds", diff_in_secs);
+ }
+
+ if (property_set("ril.net_connected", new_conn_state ? "1" : "0")) {
+ ALOGE("Couldn't set a system property ril.net_connected.");
+ }
+ }
+
+ if (t != NULL) {
+ gce_ril_env->OnRequestComplete(*t, RIL_E_SUCCESS, responses,
+ gDataCalls.size() * sizeof(*responses));
+ } else {
+ gce_ril_env->OnUnsolicitedResponse(RIL_UNSOL_DATA_CALL_LIST_CHANGED,
+ responses,
+ gDataCalls.size() * sizeof(*responses));
+ }
+ delete[] responses;
+ return 0;
+}
+
+static void request_datacall_fail_cause(RIL_Token t) {
+ RIL_DataCallFailCause fail = PDP_FAIL_DATA_REGISTRATION_FAIL;
+
+ if (gDataCalls.size() > 0) {
+ fail = gDataCalls.rbegin()->second.fail_cause_;
+ }
+
+ ALOGV("Requesting last data call setup fail cause (%d)", fail);
+ gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, &fail, sizeof(fail));
+};
+
+static void request_data_calllist(void* /*data*/, size_t /*datalen*/,
+ RIL_Token t) {
+ request_or_send_data_calllist(&t);
+}
+
+static void request_setup_data_call(void* data, size_t datalen, RIL_Token t) {
+ char** details = static_cast<char**>(data);
+ const size_t fields = datalen / sizeof(details[0]);
+
+ // There are two different versions of this interface, one providing 7 strings
+ // and the other providing 8. The code below will assume the presence of 7
+ // strings in all cases, so bail out here if things appear to be wrong. We
+ // protect the 8 string case below.
+ if (fields < 7) {
+ ALOGE("%s returning: called with small datalen %zu", __FUNCTION__, datalen);
+ return;
+ }
+
+ DataCall call;
+ int tech = atoi(details[0]);
+ switch (tech) {
+ case 0:
+ case 2 + RADIO_TECH_1xRTT:
+ call.technology_ = RADIO_TECH_1xRTT;
+ break;
+
+ case 1:
+ case 2 + RADIO_TECH_EDGE:
+ call.technology_ = RADIO_TECH_EDGE;
+ break;
+
+ default:
+ call.technology_ = RIL_RadioTechnology(tech - 2);
+ break;
+ }
+
+ int profile = atoi(details[1]);
+ call.profile_ = RIL_DataProfile(profile);
+
+ if (details[2]) call.access_point_ = details[2];
+ if (details[3]) call.username_ = details[3];
+ if (details[4]) call.password_ = details[4];
+
+ int auth_type = atoi(details[5]);
+ call.auth_type_ = DataCall::AllowedAuthenticationType(auth_type);
+
+ if (!strcmp("IP", details[6])) {
+ call.connection_type_ = DataCall::kConnTypeIPv4;
+ } else if (!strcmp("IPV6", details[6])) {
+ call.connection_type_ = DataCall::kConnTypeIPv6;
+ } else if (!strcmp("IPV4V6", details[6])) {
+ call.connection_type_ = DataCall::kConnTypeIPv4v6;
+ } else if (!strcmp("PPP", details[6])) {
+ call.connection_type_ = DataCall::kConnTypePPP;
+ } else {
+ ALOGW("Unknown / unsupported connection type %s. Falling back to IPv4",
+ details[6]);
+ call.connection_type_ = DataCall::kConnTypeIPv4;
+ }
+
+ if (call.connection_type_ != DataCall::kConnTypeIPv4) {
+ ALOGE("Non-IPv4 connections are not supported by Cuttlefish RIL.");
+ gce_ril_env->OnRequestComplete(t, RIL_E_INVALID_ARGUMENTS, NULL, 0);
+ return;
+ }
+
+ call.link_state_ = DataCall::kLinkStateUp;
+ call.fail_cause_ = PDP_FAIL_NONE;
+ if (fields > 7) {
+ if (details[7]) call.other_properties_ = details[7];
+ }
+
+ if (gDataCalls.empty()) {
+ SetUpNetworkInterface(global_ril_config->ril_ipaddr(),
+ global_ril_config->ril_prefixlen(),
+ global_ril_config->ril_broadcast());
+ }
+
+ gDataCalls[gNextDataCallId] = call;
+ gNextDataCallId++;
+
+ ALOGV("Requesting data call setup to APN %s, technology %s, prof %s",
+ details[2], details[0], details[1]);
+
+ request_or_send_data_calllist(&t);
+
+ gRilConnected = (gDataCalls.size() > 0);
+}
+
+static void request_teardown_data_call(void* data, size_t /*datalen*/,
+ RIL_Token t) {
+ char** data_strs = (char**)data;
+ int call_id = atoi(data_strs[0]);
+ int reason = atoi(data_strs[1]);
+
+ ALOGV("Tearing down data call %d, reason: %d", call_id, reason);
+
+ gDataCalls.erase(call_id);
+ gRilConnected = (gDataCalls.size() > 0);
+
+ if (!gRilConnected) {
+ TearDownNetworkInterface();
+ }
+ gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
+}
+
+static void set_radio_state(RIL_RadioState new_state, RIL_Token t) {
+ // From header:
+ // Toggle radio on and off (for "airplane" mode)
+ // If the radio is is turned off/on the radio modem subsystem
+ // is expected return to an initialized state. For instance,
+ // any voice and data calls will be terminated and all associated
+ // lists emptied.
+ gDataCalls.clear();
+
+ gSimStatus = SIM_NOT_READY;
+ ALOGV("RIL_RadioState change %d to %d", gRadioPowerState, new_state);
+ gRadioPowerState = new_state;
+
+ if (new_state == RADIO_STATE_OFF) {
+ TearDownNetworkInterface();
+ }
+
+ if (t != NULL) {
+ gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
+ }
+
+ gce_ril_env->OnUnsolicitedResponse(RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED,
+ NULL, 0);
+
+ pollSIMState(NULL);
+}
+
+// returns 1 if on, 0 if off, and -1 on error
+static void request_radio_power(void* data, size_t /*datalen*/, RIL_Token t) {
+ int on = ((int*)data)[0];
+ set_radio_state(on ? RADIO_STATE_ON : RADIO_STATE_OFF, t);
+}
+
+// TODO(ender): this should be a class member. Move where it belongs.
+struct CallState {
+ RIL_CallState state; // e.g. RIL_CALL_HOLDING;
+ bool isInternational;
+ bool isMobileTerminated;
+ bool isVoice;
+ bool isMultiParty;
+
+ std::string number;
+ std::string name;
+ std::string dtmf;
+
+ bool canPresentNumber;
+ bool canPresentName;
+
+ CallState()
+ : state(RIL_CallState(0)),
+ isInternational(false),
+ isMobileTerminated(true),
+ isVoice(true),
+ isMultiParty(false),
+ canPresentNumber(true),
+ canPresentName(true) {}
+
+ CallState(const std::string& number)
+ : state(RIL_CALL_INCOMING),
+ isInternational(false),
+ isMobileTerminated(true),
+ isVoice(true),
+ isMultiParty(false),
+ number(number),
+ name(number),
+ canPresentNumber(true),
+ canPresentName(true) {}
+
+ bool isBackground() { return state == RIL_CALL_HOLDING; }
+
+ bool isActive() { return state == RIL_CALL_ACTIVE; }
+
+ bool isDialing() { return state == RIL_CALL_DIALING; }
+
+ bool isIncoming() { return state == RIL_CALL_INCOMING; }
+
+ bool isWaiting() { return state == RIL_CALL_WAITING; }
+
+ void addDtmfDigit(char c) {
+ dtmf.push_back(c);
+ ALOGV("Call to %s: DTMF %s", number.c_str(), dtmf.c_str());
+ }
+
+ bool makeBackground() {
+ if (state == RIL_CALL_ACTIVE) {
+ state = RIL_CALL_HOLDING;
+ return true;
+ }
+
+ return false;
+ }
+
+ bool makeActive() {
+ if (state == RIL_CALL_INCOMING || state == RIL_CALL_WAITING ||
+ state == RIL_CALL_DIALING || state == RIL_CALL_HOLDING) {
+ state = RIL_CALL_ACTIVE;
+ return true;
+ }
+
+ return false;
+ }
+};
+
+static int gLastActiveCallIndex = 1;
+static int gMicrophoneMute = 0;
+static std::map<int, CallState> gActiveCalls;
+
+static void request_get_current_calls(void* /*data*/, size_t /*datalen*/,
+ RIL_Token t) {
+ const int countCalls = gActiveCalls.size();
+
+ RIL_Call** pp_calls = (RIL_Call**)alloca(countCalls * sizeof(RIL_Call*));
+ RIL_Call* p_calls = (RIL_Call*)alloca(countCalls * sizeof(RIL_Call));
+
+ memset(p_calls, 0, countCalls * sizeof(RIL_Call));
+
+ /* init the pointer array */
+ for (int i = 0; i < countCalls; i++) {
+ pp_calls[i] = &(p_calls[i]);
+ }
+
+ // TODO(ender): This should be built from calls requested via RequestDial.
+ for (std::map<int, CallState>::iterator iter = gActiveCalls.begin();
+ iter != gActiveCalls.end(); ++iter, ++p_calls) {
+ p_calls->state = iter->second.state;
+ p_calls->index = iter->first;
+ p_calls->toa = iter->second.isInternational ? 145 : 129;
+ p_calls->isMpty = iter->second.isMultiParty;
+ p_calls->isMT = iter->second.isMobileTerminated;
+ p_calls->als = iter->first;
+ p_calls->isVoice = iter->second.isVoice;
+ p_calls->isVoicePrivacy = 0;
+ p_calls->number = strdup(iter->second.number.c_str());
+ p_calls->numberPresentation = iter->second.canPresentNumber ? 0 : 1;
+ p_calls->name = strdup(iter->second.name.c_str());
+ p_calls->namePresentation = iter->second.canPresentName ? 0 : 1;
+ p_calls->uusInfo = NULL;
+
+ ALOGV("Call to %s (%s): voice=%d mt=%d type=%d state=%d index=%d",
+ p_calls->name, p_calls->number, p_calls->isVoice, p_calls->isMT,
+ p_calls->toa, p_calls->state, p_calls->index);
+ }
+
+ gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, pp_calls,
+ countCalls * sizeof(RIL_Call*));
+
+ ALOGV("Get Current calls: %d calls found.\n", countCalls);
+}
+
+static void simulate_pending_calls_answered(void* /*ignore*/) {
+ ALOGV("Simulating outgoing call answered.");
+ // This also resumes held calls.
+ for (std::map<int, CallState>::iterator iter = gActiveCalls.begin();
+ iter != gActiveCalls.end(); ++iter) {
+ if (iter->second.isDialing()) {
+ iter->second.makeActive();
+ }
+ }
+
+ // Only unsolicited here.
+ gce_ril_env->OnUnsolicitedResponse(RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED,
+ NULL, 0);
+}
+
+static void request_dial(void* data, size_t /*datalen*/, RIL_Token t) {
+ RIL_Dial* p_dial = (RIL_Dial*)data;
+
+ ALOGV("Dialing %s, number presentation is %s.", p_dial->address,
+ (p_dial->clir == 0) ? "defined by operator"
+ : (p_dial->clir == 1) ? "allowed" : "restricted");
+
+ CallState state(p_dial->address);
+ state.isMobileTerminated = false;
+ state.state = RIL_CALL_DIALING;
+
+ switch (p_dial->clir) {
+ case 0: // default
+ case 1: // allow
+ state.canPresentNumber = true;
+ break;
+
+ case 2: // restrict
+ state.canPresentNumber = false;
+ break;
+ }
+
+ int call_index = gLastActiveCallIndex++;
+ gActiveCalls[call_index] = state;
+
+ static const struct timeval kAnswerTime = {5, 0};
+ gce_ril_env->RequestTimedCallback(simulate_pending_calls_answered, NULL,
+ &kAnswerTime);
+
+ // success or failure is ignored by the upper layer here.
+ // it will call GET_CURRENT_CALLS and determine success that way
+ gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
+}
+
+void request_set_mute(void* data, size_t /*datalen*/, RIL_Token t) {
+ gMicrophoneMute = ((int*)data)[0] != 0;
+ gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
+}
+
+void request_get_mute(RIL_Token t) {
+ gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, &gMicrophoneMute,
+ sizeof(gMicrophoneMute));
+}
+
+// TODO(ender): this should be a class member. Move where it belongs.
+struct SmsMessage {
+ enum SmsStatus { kUnread = 0, kRead = 1, kUnsent = 2, kSent = 3 };
+
+ std::string message;
+ SmsStatus status;
+};
+
+static int gNextMessageId = 1;
+static std::map<int, SmsMessage> gMessagesOnSimCard;
+
+static void request_write_sms_to_sim(void* data, size_t /*datalen*/,
+ RIL_Token t) {
+ RIL_SMS_WriteArgs* p_args = (RIL_SMS_WriteArgs*)data;
+
+ SmsMessage message;
+ message.status = SmsMessage::SmsStatus(p_args->status);
+ message.message = p_args->pdu;
+
+ ALOGV("Storing SMS message: '%s' with state: %s.", message.message.c_str(),
+ (message.status < SmsMessage::kUnsent)
+ ? ((message.status == SmsMessage::kRead) ? "READ" : "UNREAD")
+ : ((message.status == SmsMessage::kSent) ? "SENT" : "UNSENT"));
+
+ // TODO(ender): simulate SIM FULL?
+ int index = gNextMessageId++;
+ gMessagesOnSimCard[index] = message;
+
+ gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, &index, sizeof(index));
+}
+
+static void request_delete_sms_on_sim(void* data, size_t /*datalen*/,
+ RIL_Token t) {
+ int index = *(int*)data;
+
+ ALOGV("Delete SMS message %d", index);
+
+ if (gMessagesOnSimCard.erase(index) == 0) {
+ // No such message
+ gce_ril_env->OnRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
+ return;
+ }
+
+ gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
+}
+
+static void request_hangup(void* data, size_t /*datalen*/, RIL_Token t) {
+ int* p_line = (int*)data;
+
+ ALOGV("Hanging up call %d.", *p_line);
+ std::map<int, CallState>::iterator iter = gActiveCalls.find(*p_line);
+
+ if (iter == gActiveCalls.end()) {
+ ALOGV("No such call: %d.", *p_line);
+ gce_ril_env->OnRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
+ } else {
+ gActiveCalls.erase(iter);
+ gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
+ }
+}
+
+static void request_hangup_waiting(void* /*data*/, size_t /*datalen*/,
+ RIL_Token t) {
+ ALOGV("Hanging up background/held calls.");
+ for (std::map<int, CallState>::iterator iter = gActiveCalls.begin();
+ iter != gActiveCalls.end();) {
+ if (iter->second.isBackground()) {
+ // C++98 -- std::map::erase doesn't return iterator.
+ std::map<int, CallState>::iterator temp = iter++;
+ gActiveCalls.erase(temp);
+ } else {
+ ++iter;
+ }
+ }
+ gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
+}
+
+static void request_hangup_current(RIL_Token t) {
+ ALOGV("Hanging up foreground/active calls.");
+ // This also resumes held calls.
+ for (std::map<int, CallState>::iterator iter = gActiveCalls.begin();
+ iter != gActiveCalls.end();) {
+ if (iter->second.isBackground()) {
+ iter->second.makeActive();
+ ++iter;
+ } else {
+ // C++98 -- std::map::erase doesn't return iterator.
+ std::map<int, CallState>::iterator temp = iter++;
+ gActiveCalls.erase(temp);
+ }
+ }
+ gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
+}
+
+static void request_switch_current_and_waiting(RIL_Token t) {
+ ALOGV("Toggle foreground and background calls.");
+ // TODO(ender): fix all states. Max 2 calls.
+ // BEFORE AFTER
+ // Call 1 Call 2 Call 1 Call 2
+ // ACTIVE HOLDING HOLDING ACTIVE
+ // ACTIVE WAITING HOLDING ACTIVE
+ // HOLDING WAITING HOLDING ACTIVE
+ // ACTIVE IDLE HOLDING IDLE
+ // IDLE IDLE IDLE IDLE
+ for (std::map<int, CallState>::iterator iter = gActiveCalls.begin();
+ iter != gActiveCalls.end(); ++iter) {
+ // TODO(ender): call could also be waiting or dialing or...
+ if (iter->second.isBackground()) {
+ iter->second.makeActive();
+ } else {
+ iter->second.makeBackground();
+ }
+ }
+ gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
+}
+
+static void request_answer_incoming(RIL_Token t) {
+ ALOGV("Answering incoming call.");
+
+ // There's two types of incoming calls:
+ // - incoming: we are receiving this call while nothing happens,
+ // - waiting: we are receiving this call while we're already talking.
+ // We only accept the incoming ones.
+ for (std::map<int, CallState>::iterator iter = gActiveCalls.begin();
+ iter != gActiveCalls.end(); ++iter) {
+ if (iter->second.isIncoming()) {
+ iter->second.makeActive();
+ }
+ }
+ gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
+}
+
+static void request_combine_multiparty_call(void* /*data*/, size_t /*datalen*/,
+ RIL_Token t) {
+ ALOGW("Conference calls are not supported.");
+ gce_ril_env->OnRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
+}
+
+static void request_split_multiparty_call(void* /*data*/, size_t /*datalen*/,
+ RIL_Token t) {
+ ALOGW("Conference calls are not supported.");
+ gce_ril_env->OnRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
+}
+
+static void request_udub_on_incoming_calls(RIL_Token t) {
+ // UDUB = user determined user busy.
+ // We don't exactly do that. We simply drop these calls.
+ ALOGV("Reporting busy signal to incoming calls.");
+ for (std::map<int, CallState>::iterator iter = gActiveCalls.begin();
+ iter != gActiveCalls.end();) {
+ // If we have an incoming call, there should be no waiting call.
+ // If we have a waiting call, then previous incoming call has been answered.
+ if (iter->second.isIncoming() || iter->second.isWaiting()) {
+ // C++98 -- std::map::erase doesn't return iterator.
+ std::map<int, CallState>::iterator temp = iter++;
+ gActiveCalls.erase(temp);
+ } else {
+ ++iter;
+ }
+ }
+ gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
+}
+
+static void request_send_dtmf(void* data, size_t /*datalen*/, RIL_Token t) {
+ char c = ((char*)data)[0];
+ ALOGV("Sending DTMF digit '%c'", c);
+
+ for (std::map<int, CallState>::iterator iter = gActiveCalls.begin();
+ iter != gActiveCalls.end(); ++iter) {
+ if (iter->second.isActive()) {
+ iter->second.addDtmfDigit(c);
+ break;
+ }
+ }
+
+ gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
+}
+
+static void request_send_dtmf_stop(RIL_Token t) {
+ ALOGV("DTMF tone end.");
+
+ gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
+}
+
+// Check SignalStrength.java file for more details on how these map to signal
+// strength bars.
+const int kGatewaySignalStrengthMin = 4;
+const int kGatewaySignalStrengthMax = 30;
+const int kCDMASignalStrengthMin = -110;
+const int kCDMASignalStrengthMax = -60;
+const int kEVDOSignalStrengthMin = -160;
+const int kEVDOSignalStrengthMax = -70;
+const int kLTESignalStrengthMin = 4;
+const int kLTESignalStrengthMax = 30;
+
+static int gGatewaySignalStrength = kGatewaySignalStrengthMax;
+static int gCDMASignalStrength = kCDMASignalStrengthMax;
+static int gEVDOSignalStrength = kEVDOSignalStrengthMax;
+static int gLTESignalStrength = kLTESignalStrengthMax;
+
+static void request_signal_strength(void* /*data*/, size_t /*datalen*/,
+ RIL_Token t) {
+ // TODO(ender): possible to support newer APIs here.
+ RIL_SignalStrength_v10 strength;
+
+ gGatewaySignalStrength += (rand() % 3 - 1);
+ gCDMASignalStrength += (rand() % 3 - 1);
+ gEVDOSignalStrength += (rand() % 3 - 1);
+ gLTESignalStrength += (rand() % 3 - 1);
+
+ if (gGatewaySignalStrength < kGatewaySignalStrengthMin)
+ gGatewaySignalStrength = kGatewaySignalStrengthMin;
+ if (gGatewaySignalStrength > kGatewaySignalStrengthMax)
+ gGatewaySignalStrength = kGatewaySignalStrengthMax;
+ if (gCDMASignalStrength < kCDMASignalStrengthMin)
+ gCDMASignalStrength = kCDMASignalStrengthMin;
+ if (gCDMASignalStrength > kCDMASignalStrengthMax)
+ gCDMASignalStrength = kCDMASignalStrengthMax;
+ if (gEVDOSignalStrength < kEVDOSignalStrengthMin)
+ gEVDOSignalStrength = kEVDOSignalStrengthMin;
+ if (gEVDOSignalStrength > kEVDOSignalStrengthMax)
+ gEVDOSignalStrength = kEVDOSignalStrengthMax;
+ if (gLTESignalStrength < kLTESignalStrengthMin)
+ gLTESignalStrength = kLTESignalStrengthMin;
+ if (gLTESignalStrength > kLTESignalStrengthMax)
+ gLTESignalStrength = kLTESignalStrengthMax;
+
+ strength.GW_SignalStrength.signalStrength = gGatewaySignalStrength;
+ strength.GW_SignalStrength.bitErrorRate = 0; // 0..7%
+
+ strength.CDMA_SignalStrength.dbm = gCDMASignalStrength;
+ strength.CDMA_SignalStrength.ecio = 0; // Ec/Io; keep high to use dbm.
+
+ strength.EVDO_SignalStrength.dbm = gEVDOSignalStrength;
+ strength.EVDO_SignalStrength.ecio = 0; // Ec/Io; keep high to use dbm.
+
+ strength.LTE_SignalStrength.signalStrength = gLTESignalStrength;
+ strength.LTE_SignalStrength.rsrp = INT_MAX; // Invalid = Use signalStrength.
+ strength.LTE_SignalStrength.rsrq = INT_MAX; // Invalid = Use signalStrength.
+ strength.LTE_SignalStrength.rssnr = INT_MAX; // Invalid = Use signalStrength.
+ strength.LTE_SignalStrength.cqi = INT_MAX; // Invalid = Use signalStrength.
+
+ ALOGV("Reporting signal strength: GW=%d CDMA=%d EVDO=%d LTE=%d",
+ gGatewaySignalStrength, gCDMASignalStrength, gEVDOSignalStrength,
+ gLTESignalStrength);
+
+ gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, &strength, sizeof(strength));
+}
+
+static std::map<RIL_PreferredNetworkType, int> gModemSupportedNetworkTypes;
+
+static void init_modem_supported_network_types() {
+ gModemSupportedNetworkTypes[PREF_NET_TYPE_GSM_WCDMA] = MDM_GSM | MDM_WCDMA;
+ gModemSupportedNetworkTypes[PREF_NET_TYPE_GSM_ONLY] = MDM_GSM;
+ gModemSupportedNetworkTypes[PREF_NET_TYPE_WCDMA] = MDM_WCDMA;
+ gModemSupportedNetworkTypes[PREF_NET_TYPE_GSM_WCDMA_AUTO] =
+ MDM_GSM | MDM_WCDMA;
+ gModemSupportedNetworkTypes[PREF_NET_TYPE_CDMA_EVDO_AUTO] =
+ MDM_CDMA | MDM_EVDO;
+ gModemSupportedNetworkTypes[PREF_NET_TYPE_CDMA_ONLY] = MDM_CDMA;
+ gModemSupportedNetworkTypes[PREF_NET_TYPE_EVDO_ONLY] = MDM_EVDO;
+ gModemSupportedNetworkTypes[PREF_NET_TYPE_GSM_WCDMA_CDMA_EVDO_AUTO] =
+ MDM_GSM | MDM_WCDMA | MDM_CDMA | MDM_EVDO;
+ gModemSupportedNetworkTypes[PREF_NET_TYPE_LTE_CDMA_EVDO] =
+ MDM_LTE | MDM_CDMA | MDM_EVDO;
+ gModemSupportedNetworkTypes[PREF_NET_TYPE_LTE_GSM_WCDMA] =
+ MDM_LTE | MDM_GSM | MDM_WCDMA;
+ gModemSupportedNetworkTypes[PREF_NET_TYPE_LTE_CMDA_EVDO_GSM_WCDMA] =
+ MDM_LTE | MDM_CDMA | MDM_EVDO | MDM_GSM | MDM_WCDMA;
+ gModemSupportedNetworkTypes[PREF_NET_TYPE_LTE_ONLY] = MDM_LTE;
+}
+
+static std::map<RIL_PreferredNetworkType, int> gModemTechnologies;
+
+RIL_RadioTechnology gDataTechnologiesPreferenceOrder[] = {
+ RADIO_TECH_LTE, RADIO_TECH_EHRPD, RADIO_TECH_HSPAP, RADIO_TECH_HSPA,
+ RADIO_TECH_HSDPA, RADIO_TECH_HSUPA, RADIO_TECH_EVDO_B, RADIO_TECH_EVDO_A,
+ RADIO_TECH_EVDO_0, RADIO_TECH_1xRTT, RADIO_TECH_UMTS, RADIO_TECH_EDGE,
+ RADIO_TECH_GPRS};
+
+RIL_RadioTechnology gVoiceTechnologiesPreferenceOrder[] = {
+ RADIO_TECH_LTE, RADIO_TECH_EHRPD, RADIO_TECH_EVDO_B, RADIO_TECH_EVDO_A,
+ RADIO_TECH_EVDO_0, RADIO_TECH_1xRTT, RADIO_TECH_IS95B, RADIO_TECH_IS95A,
+ RADIO_TECH_UMTS, RADIO_TECH_GSM};
+
+static void init_modem_technologies() {
+ gModemTechnologies[PREF_NET_TYPE_GSM_WCDMA] =
+ (1 << RADIO_TECH_GSM) | (1 << RADIO_TECH_GPRS) | (1 << RADIO_TECH_EDGE) |
+ (1 << RADIO_TECH_UMTS);
+ gModemTechnologies[PREF_NET_TYPE_GSM_ONLY] =
+ (1 << RADIO_TECH_GSM) | (1 << RADIO_TECH_GPRS) | (1 << RADIO_TECH_EDGE);
+ gModemTechnologies[PREF_NET_TYPE_WCDMA] =
+ (1 << RADIO_TECH_EDGE) | (1 << RADIO_TECH_UMTS);
+ gModemTechnologies[PREF_NET_TYPE_GSM_WCDMA_AUTO] =
+ (1 << RADIO_TECH_GSM) | (1 << RADIO_TECH_GPRS) | (1 << RADIO_TECH_EDGE) |
+ (1 << RADIO_TECH_UMTS);
+ gModemTechnologies[PREF_NET_TYPE_CDMA_EVDO_AUTO] =
+ (1 << RADIO_TECH_IS95A) | (1 << RADIO_TECH_IS95B) |
+ (1 << RADIO_TECH_1xRTT) | (1 << RADIO_TECH_EVDO_0) |
+ (1 << RADIO_TECH_EVDO_A) | (1 << RADIO_TECH_HSDPA) |
+ (1 << RADIO_TECH_HSUPA) | (1 << RADIO_TECH_HSPA) |
+ (1 << RADIO_TECH_EVDO_B);
+ gModemTechnologies[PREF_NET_TYPE_CDMA_ONLY] = (1 << RADIO_TECH_IS95A) |
+ (1 << RADIO_TECH_IS95B) |
+ (1 << RADIO_TECH_1xRTT);
+ gModemTechnologies[PREF_NET_TYPE_EVDO_ONLY] =
+ (1 << RADIO_TECH_EVDO_0) | (1 << RADIO_TECH_EVDO_A) |
+ (1 << RADIO_TECH_EVDO_A) | (1 << RADIO_TECH_HSDPA) |
+ (1 << RADIO_TECH_HSUPA) | (1 << RADIO_TECH_HSPA) |
+ (1 << RADIO_TECH_EVDO_B);
+ gModemTechnologies[PREF_NET_TYPE_GSM_WCDMA_CDMA_EVDO_AUTO] =
+ (1 << RADIO_TECH_GSM) | (1 << RADIO_TECH_GPRS) | (1 << RADIO_TECH_EDGE) |
+ (1 << RADIO_TECH_UMTS) | (1 << RADIO_TECH_IS95A) |
+ (1 << RADIO_TECH_IS95B) | (1 << RADIO_TECH_1xRTT) |
+ (1 << RADIO_TECH_EVDO_0) | (1 << RADIO_TECH_EVDO_A) |
+ (1 << RADIO_TECH_HSDPA) | (1 << RADIO_TECH_HSUPA) |
+ (1 << RADIO_TECH_HSPA) | (1 << RADIO_TECH_EVDO_B);
+ gModemTechnologies[PREF_NET_TYPE_LTE_CDMA_EVDO] =
+ (1 << RADIO_TECH_HSPAP) | (1 << RADIO_TECH_LTE) |
+ (1 << RADIO_TECH_EHRPD) | (1 << RADIO_TECH_IS95A) |
+ (1 << RADIO_TECH_IS95B) | (1 << RADIO_TECH_1xRTT) |
+ (1 << RADIO_TECH_EVDO_0) | (1 << RADIO_TECH_EVDO_A) |
+ (1 << RADIO_TECH_HSDPA) | (1 << RADIO_TECH_HSUPA) |
+ (1 << RADIO_TECH_HSPA) | (1 << RADIO_TECH_EVDO_B);
+ gModemTechnologies[PREF_NET_TYPE_LTE_GSM_WCDMA] =
+ (1 << RADIO_TECH_HSPAP) | (1 << RADIO_TECH_LTE) |
+ (1 << RADIO_TECH_EHRPD) | (1 << RADIO_TECH_GSM) | (1 << RADIO_TECH_GPRS) |
+ (1 << RADIO_TECH_EDGE) | (1 << RADIO_TECH_UMTS);
+
+ gModemTechnologies[PREF_NET_TYPE_LTE_CMDA_EVDO_GSM_WCDMA] =
+ (1 << RADIO_TECH_HSPAP) | (1 << RADIO_TECH_LTE) |
+ (1 << RADIO_TECH_EHRPD) | (1 << RADIO_TECH_IS95A) |
+ (1 << RADIO_TECH_IS95B) | (1 << RADIO_TECH_1xRTT) |
+ (1 << RADIO_TECH_EVDO_0) | (1 << RADIO_TECH_EVDO_A) |
+ (1 << RADIO_TECH_HSDPA) | (1 << RADIO_TECH_HSUPA) |
+ (1 << RADIO_TECH_HSPA) | (1 << RADIO_TECH_EVDO_B) |
+ (1 << RADIO_TECH_GSM) | (1 << RADIO_TECH_GPRS) | (1 << RADIO_TECH_EDGE) |
+ (1 << RADIO_TECH_UMTS);
+ gModemTechnologies[PREF_NET_TYPE_LTE_ONLY] =
+ (1 << RADIO_TECH_HSPAP) | (1 << RADIO_TECH_LTE) | (1 << RADIO_TECH_EHRPD);
+}
+
+static const RIL_PreferredNetworkType gModemDefaultType =
+ PREF_NET_TYPE_LTE_GSM_WCDMA;
+static RIL_PreferredNetworkType gModemCurrentType = gModemDefaultType;
+static RIL_RadioTechnology gModemVoiceTechnology = RADIO_TECH_LTE;
+
+// Report technology change.
+// Select best technology from the list of supported techs.
+// Demotes RADIO_TECH_GSM as it's voice-only.
+static RIL_RadioTechnology getBestDataTechnology(
+ RIL_PreferredNetworkType network_type) {
+ RIL_RadioTechnology technology = RADIO_TECH_GPRS;
+
+ std::map<RIL_PreferredNetworkType, int>::iterator iter =
+ gModemTechnologies.find(network_type);
+
+ ALOGV("Searching for best data technology for network type %d...",
+ network_type);
+
+ // Find which technology bits are lit. Pick the top most.
+ for (size_t tech_index = 0;
+ tech_index < sizeof(gDataTechnologiesPreferenceOrder) /
+ sizeof(gDataTechnologiesPreferenceOrder[0]);
+ ++tech_index) {
+ if (iter->second & (1 << gDataTechnologiesPreferenceOrder[tech_index])) {
+ technology = gDataTechnologiesPreferenceOrder[tech_index];
+ break;
+ }
+ }
+
+ ALOGV("Best data technology: %d.", technology);
+ return technology;
+}
+
+static RIL_RadioTechnology getBestVoiceTechnology(
+ RIL_PreferredNetworkType network_type) {
+ RIL_RadioTechnology technology = RADIO_TECH_GSM;
+
+ std::map<RIL_PreferredNetworkType, int>::iterator iter =
+ gModemTechnologies.find(network_type);
+
+ ALOGV("Searching for best voice technology for network type %d...",
+ network_type);
+
+ // Find which technology bits are lit. Pick the top most.
+ for (size_t tech_index = 0;
+ tech_index < sizeof(gVoiceTechnologiesPreferenceOrder) /
+ sizeof(gVoiceTechnologiesPreferenceOrder[0]);
+ ++tech_index) {
+ if (iter->second & (1 << gVoiceTechnologiesPreferenceOrder[tech_index])) {
+ technology = gVoiceTechnologiesPreferenceOrder[tech_index];
+ break;
+ }
+ }
+
+ ALOGV("Best voice technology: %d.", technology);
+ return technology;
+}
+
+static void setRadioTechnology(RIL_PreferredNetworkType network_type) {
+ RIL_RadioTechnology technology = getBestVoiceTechnology(network_type);
+
+ if (technology != gModemVoiceTechnology) {
+ gModemVoiceTechnology = technology;
+ gce_ril_env->OnUnsolicitedResponse(RIL_UNSOL_VOICE_RADIO_TECH_CHANGED,
+ &gModemVoiceTechnology,
+ sizeof(gModemVoiceTechnology));
+ }
+}
+
+static void request_get_radio_capability(RIL_Token t) {
+ ALOGV("Requesting radio capability.");
+ RIL_RadioCapability rc;
+ rc.version = RIL_RADIO_CAPABILITY_VERSION;
+ rc.session = 1;
+ rc.phase = RC_PHASE_CONFIGURED;
+ rc.rat = RAF_HSPAP;
+ strncpy(rc.logicalModemUuid, "com.google.cvdgce1.modem", MAX_UUID_LENGTH);
+ rc.status = RC_STATUS_SUCCESS;
+ gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, &rc, sizeof(rc));
+}
+
+static void request_set_radio_capability(void* data, size_t datalen,
+ RIL_Token t) {
+ RIL_RadioCapability* rc = (RIL_RadioCapability*)data;
+ ALOGV(
+ "RadioCapability version %d session %d phase %d rat %d "
+ "logicalModemUuid %s status %d",
+ rc->version, rc->session, rc->phase, rc->rat, rc->logicalModemUuid,
+ rc->status);
+ // TODO(ender): do something about these numbers.
+ gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, rc, datalen);
+}
+
+static void request_set_preferred_network_type(int /*request*/, void* data,
+ size_t /*datalen*/,
+ RIL_Token t) {
+ RIL_PreferredNetworkType desired_type = *(RIL_PreferredNetworkType*)(data);
+
+ // TODO(ender): telephony still believes this phone is GSM only.
+ ALOGV("Requesting modem technology change -> %d", desired_type);
+
+ if (gModemSupportedNetworkTypes.find(desired_type) ==
+ gModemSupportedNetworkTypes.end()) {
+ desired_type = gModemSupportedNetworkTypes.begin()->first;
+ }
+
+ if (gModemCurrentType == desired_type) {
+ ALOGV("Modem technology already set to %d.", desired_type);
+ gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
+ return;
+ }
+
+ int supported_technologies = gModemSupportedNetworkTypes[gModemDefaultType];
+ int desired_technologies = gModemSupportedNetworkTypes[desired_type];
+
+ ALOGV("Requesting modem technology change %d -> %d", gModemCurrentType,
+ desired_type);
+
+ // Check if we support this technology.
+ if ((supported_technologies & desired_technologies) != desired_technologies) {
+ ALOGV("Desired technology is not supported.");
+ gce_ril_env->OnRequestComplete(t, RIL_E_MODE_NOT_SUPPORTED, NULL, 0);
+ return;
+ }
+
+ gModemCurrentType = desired_type;
+ setRadioTechnology(desired_type);
+ ALOGV("Technology change successful.");
+ gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
+}
+
+static void request_get_preferred_network_type(int /*request*/, void* /*data*/,
+ size_t /*datalen*/,
+ RIL_Token t) {
+ gce_ril_env->OnRequestComplete(
+ t, RIL_E_SUCCESS,
+ const_cast<RIL_PreferredNetworkType*>(&gModemDefaultType),
+ sizeof(gModemDefaultType));
+}
+
+enum RegistrationState {
+ kUnregistered = 0,
+ kRegisteredInHomeNetwork = 1,
+ kSearchingForOperators = 2,
+ kRegistrationDenied = 3,
+ kUnknown = 4,
+ kRegisteredInRoamingMode = 5,
+
+ kUnregistered_EmergencyCallsOnly = 10,
+ kSearchingForOperators_EmergencyCallsOnly = 12,
+ kRegistrationDenied_EmergencyCallsOnly = 13,
+ kUnknown_EmergencyCallsOnly = 14
+};
+
+static const char kCdmaMobileDeviceNumber[] = "5551234567";
+static const char kCdmaSID[] = "123";
+static const char kCdmaNID[] = "65535"; // special: indicates free roaming.
+
+static void request_registration_state(int request, void* /*data*/,
+ size_t /*datalen*/, RIL_Token t) {
+ char** responseStr = NULL;
+ int numElements = 0;
+
+ // See RIL_REQUEST_VOICE_REGISTRATION_STATE and
+ // RIL_REQUEST_DATA_REGISTRATION_STATE.
+ numElements = (request == RIL_REQUEST_VOICE_REGISTRATION_STATE) ? 15 : 6;
+ responseStr = (char**)malloc(numElements * sizeof(char*));
+
+ asprintf(&responseStr[0], "%d", kRegisteredInHomeNetwork);
+ responseStr[1] = NULL; // LAC - needed for GSM / WCDMA only.
+ responseStr[2] = NULL; // CID - needed for GSM / WCDMA only.
+
+ // This is (and always has been) a huge memory leak.
+ if (request == RIL_REQUEST_VOICE_REGISTRATION_STATE) {
+ ALOGV("Requesting voice registration state.");
+ asprintf(&responseStr[3], "%d", getBestVoiceTechnology(gModemCurrentType));
+ responseStr[4] = strdup("1"); // BSID
+ responseStr[5] = strdup("123"); // Latitude
+ responseStr[6] = strdup("222"); // Longitude
+ responseStr[7] = strdup("0"); // CSS Indicator
+ responseStr[8] = strdup(kCdmaSID); // SID
+ responseStr[9] = strdup(kCdmaNID); // NID
+ responseStr[10] = strdup("0"); // Roaming indicator
+ responseStr[11] = strdup("1"); // System is in PRL
+ responseStr[12] = strdup("0"); // Default Roaming indicator
+ responseStr[13] = strdup("0"); // Reason for denial
+ responseStr[14] = strdup("0"); // Primary Scrambling Code of Current
+ } else if (request == RIL_REQUEST_DATA_REGISTRATION_STATE) {
+ ALOGV("Requesting data registration state.");
+ asprintf(&responseStr[3], "%d", getBestDataTechnology(gModemCurrentType));
+ responseStr[4] = strdup(""); // DataServiceDenyReason
+ responseStr[5] = strdup("1"); // Max simultaneous data calls.
+ } else {
+ ALOGV("Unexpected request type: %d", request);
+ return;
+ }
+
+ gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, responseStr,
+ numElements * sizeof(responseStr));
+}
+
+static void request_baseband_version(RIL_Token t) {
+ const char* response_str = "CVD_R1.0.0";
+
+ ALOGV("Requested phone baseband version.");
+
+ gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, strdup(response_str),
+ sizeof(response_str));
+}
+
+// Returns true, if modem is CDMA capable.
+static bool isCDMA() {
+ switch (gModemCurrentType) {
+ case PREF_NET_TYPE_GSM_WCDMA:
+ case PREF_NET_TYPE_GSM_ONLY:
+ case PREF_NET_TYPE_WCDMA:
+ case PREF_NET_TYPE_GSM_WCDMA_AUTO:
+ case PREF_NET_TYPE_LTE_GSM_WCDMA:
+ case PREF_NET_TYPE_LTE_ONLY:
+ return false;
+
+ case PREF_NET_TYPE_CDMA_EVDO_AUTO:
+ case PREF_NET_TYPE_CDMA_ONLY:
+ case PREF_NET_TYPE_EVDO_ONLY:
+ case PREF_NET_TYPE_LTE_CDMA_EVDO:
+ case PREF_NET_TYPE_LTE_CMDA_EVDO_GSM_WCDMA:
+ case PREF_NET_TYPE_GSM_WCDMA_CDMA_EVDO_AUTO:
+ return true;
+ default:
+ break;
+ }
+
+ ALOGE("INVALID MODEM TYPE: %d", gModemCurrentType);
+ return false;
+}
+
+// Returns true, if modem is GSM capable.
+// Note, this is not same as !isCDMA().
+static bool isGSM() {
+ switch (gModemCurrentType) {
+ case PREF_NET_TYPE_GSM_WCDMA:
+ case PREF_NET_TYPE_GSM_ONLY:
+ case PREF_NET_TYPE_WCDMA:
+ case PREF_NET_TYPE_GSM_WCDMA_AUTO:
+ case PREF_NET_TYPE_LTE_GSM_WCDMA:
+ case PREF_NET_TYPE_LTE_ONLY:
+ case PREF_NET_TYPE_GSM_WCDMA_CDMA_EVDO_AUTO:
+ return true;
+
+ case PREF_NET_TYPE_CDMA_EVDO_AUTO:
+ case PREF_NET_TYPE_CDMA_ONLY:
+ case PREF_NET_TYPE_EVDO_ONLY:
+ case PREF_NET_TYPE_LTE_CDMA_EVDO:
+ case PREF_NET_TYPE_LTE_CMDA_EVDO_GSM_WCDMA:
+ return false;
+ default:
+ break;
+ }
+
+ ALOGE("INVALID MODEM TYPE: %d", gModemCurrentType);
+ return false;
+}
+
+static const char gIdentityGsmImei[] = "12345678902468"; // Luhn cksum = 0.
+static const char gIdentityGsmImeiSv[] = "01"; // Arbitrary version.
+static const char gIdentityCdmaEsn[] = "A0123456"; // 8 digits, ^[A-F].*
+static const char gIdentityCdmaMeid[] =
+ "A0123456789012"; // 14 digits, ^[A-F].*
+
+static void request_get_imei(RIL_Token t) {
+ ALOGV("Requesting IMEI");
+ gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS,
+ const_cast<char*>(gIdentityGsmImei),
+ strlen(gIdentityGsmImei));
+}
+
+static void request_get_imei_sv(RIL_Token t) {
+ ALOGV("Requesting IMEI SV");
+ gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS,
+ const_cast<char*>(gIdentityGsmImeiSv),
+ strlen(gIdentityGsmImeiSv));
+}
+
+static void request_device_identity(int /*request*/, void* /*data*/,
+ size_t /*datalen*/, RIL_Token t) {
+ char* response[4] = {NULL};
+
+ ALOGV("Requesting device identity...");
+
+ if (isCDMA()) {
+ response[2] = strdup(&gIdentityCdmaEsn[0]);
+ response[3] = strdup(&gIdentityCdmaMeid[0]);
+ }
+
+ if (isGSM()) {
+ response[0] = strdup(&gIdentityGsmImei[0]);
+ response[1] = strdup(&gIdentityGsmImeiSv[0]);
+ }
+
+ gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, &response, sizeof(response));
+
+ free(response[0]);
+ free(response[1]);
+}
+
+// Let's pretend we have SIM for CDMA (by default).
+static bool gCdmaHasSim = true;
+static RIL_CdmaSubscriptionSource gCdmaSubscriptionType =
+ CDMA_SUBSCRIPTION_SOURCE_RUIM_SIM;
+
+static void request_cdma_get_subscription_source(int /*request*/,
+ void* /*data*/,
+ size_t /*datalen*/,
+ RIL_Token t) {
+ ALOGV("Requesting CDMA Subscription source.");
+
+ if (!isCDMA()) {
+ // No such radio.
+ gce_ril_env->OnRequestComplete(t, RIL_E_RADIO_NOT_AVAILABLE, NULL, 0);
+ return;
+ }
+
+ gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, &gCdmaSubscriptionType,
+ sizeof(gCdmaSubscriptionType));
+}
+
+static void request_cdma_set_subscription_source(int /*request*/, void* data,
+ size_t /*datalen*/,
+ RIL_Token t) {
+ ALOGV("Setting CDMA Subscription source.");
+
+ if (!isCDMA()) {
+ // No such radio.
+ gce_ril_env->OnRequestComplete(t, RIL_E_RADIO_NOT_AVAILABLE, NULL, 0);
+ return;
+ }
+
+ RIL_CdmaSubscriptionSource new_source = *(RIL_CdmaSubscriptionSource*)(data);
+
+ if (new_source == CDMA_SUBSCRIPTION_SOURCE_RUIM_SIM && !gCdmaHasSim) {
+ // No such radio.
+ gce_ril_env->OnRequestComplete(t, RIL_E_SIM_ABSENT, NULL, 0);
+ return;
+ }
+
+ ALOGV("Changed CDMA subscription type from %d to %d", gCdmaSubscriptionType,
+ new_source);
+ gCdmaSubscriptionType = new_source;
+
+ gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
+ gce_ril_env->OnUnsolicitedResponse(RIL_UNSOL_CDMA_SUBSCRIPTION_SOURCE_CHANGED,
+ &gCdmaSubscriptionType,
+ sizeof(gCdmaSubscriptionType));
+}
+
+static void request_cdma_subscription(int /*request*/, void* /*data*/,
+ size_t /*datalen*/, RIL_Token t) {
+ ALOGV("Requesting CDMA Subscription.");
+
+ if (!isCDMA()) {
+ // No such radio.
+ gce_ril_env->OnRequestComplete(t, RIL_E_RADIO_NOT_AVAILABLE, NULL, 0);
+ return;
+ }
+
+ char* responseStr[5] = {NULL};
+ responseStr[0] = strdup(&kCdmaMobileDeviceNumber[0]); // MDN
+ responseStr[1] = strdup(&kCdmaSID[0]); // SID
+ responseStr[2] = strdup(&kCdmaNID[0]); // NID
+ responseStr[3] = strdup(&kCdmaMobileDeviceNumber[0]); // MIN
+ responseStr[4] = strdup("1"); // PRL Version
+ gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, responseStr,
+ sizeof(responseStr));
+}
+
+static const int gMaxConcurrentVoiceCalls = 4;
+static const int gMaxConcurrentDataCalls = 4;
+static const int gMaxConcurrentStandbyConnections = 4;
+
+static void request_hardware_config(RIL_Token t) {
+ RIL_HardwareConfig hw_cfg[2];
+
+ ALOGV("Requesting hardware configuration.");
+
+ strncpy(hw_cfg[0].uuid, "com.google.cvdgce1.modem", sizeof(hw_cfg[0].uuid));
+ strncpy(hw_cfg[1].uuid, "com.google.cvdgce1.sim", sizeof(hw_cfg[1].uuid));
+
+ int technologies = 0; // = unknown.
+ std::map<RIL_PreferredNetworkType, int>::iterator iter =
+ gModemTechnologies.find(gModemDefaultType);
+ if (iter != gModemTechnologies.end()) {
+ technologies = iter->second;
+ }
+
+ hw_cfg[0].type = RIL_HARDWARE_CONFIG_MODEM;
+ hw_cfg[0].state = RIL_HARDWARE_CONFIG_STATE_ENABLED;
+ hw_cfg[0].cfg.modem.rilModel = 0;
+ hw_cfg[0].cfg.modem.rat = technologies;
+ hw_cfg[0].cfg.modem.maxVoice = gMaxConcurrentVoiceCalls;
+ hw_cfg[0].cfg.modem.maxData = gMaxConcurrentDataCalls;
+ hw_cfg[0].cfg.modem.maxStandby = gMaxConcurrentStandbyConnections;
+
+ hw_cfg[1].type = RIL_HARDWARE_CONFIG_SIM;
+ hw_cfg[1].state = RIL_HARDWARE_CONFIG_STATE_ENABLED;
+ memcpy(hw_cfg[1].cfg.sim.modemUuid, hw_cfg[0].uuid,
+ sizeof(hw_cfg[1].cfg.sim.modemUuid));
+
+ gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, &hw_cfg, sizeof(hw_cfg));
+}
+
+// 0 = Home network only, 1 = preferred networks only, 2 = all networks.
+static int gCdmaRoamingPreference = 2;
+
+static void request_cdma_get_roaming_preference(int /*request*/, void* /*data*/,
+ size_t /*datalen*/,
+ RIL_Token t) {
+ if (!isCDMA()) {
+ // No such radio.
+ gce_ril_env->OnRequestComplete(t, RIL_E_RADIO_NOT_AVAILABLE, NULL, 0);
+ return;
+ }
+
+ ALOGV("Requesting CDMA Roaming preference");
+
+ gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, &gCdmaRoamingPreference,
+ sizeof(gCdmaRoamingPreference));
+}
+
+static void request_cdma_set_roaming_preference(int /*request*/, void* data,
+ size_t /*datalen*/,
+ RIL_Token t) {
+ if (!isCDMA()) {
+ // No such radio.
+ gce_ril_env->OnRequestComplete(t, RIL_E_RADIO_NOT_AVAILABLE, NULL, 0);
+ return;
+ }
+
+ int pref = *(int*)data;
+ ALOGV("Changing CDMA roaming preference: %d -> %d", gCdmaRoamingPreference,
+ pref);
+
+ if ((pref < 0) || (pref > 2)) {
+ ALOGV("Unsupported roaming preference: %d", pref);
+ gce_ril_env->OnRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
+ return;
+ }
+
+ gCdmaRoamingPreference = pref;
+ gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
+}
+
+static void request_send_ussd(void* /*data*/, size_t /*datalen*/, RIL_Token t) {
+ ALOGV("Sending USSD code is currently not supported");
+ // TODO(ender): support this feature
+ gce_ril_env->OnRequestComplete(t, RIL_E_REQUEST_NOT_SUPPORTED, NULL, 0);
+}
+
+static void request_cancel_ussd(RIL_Token t) {
+ ALOGV("Cancelling USSD code is currently not supported");
+ // TODO(ender): support this feature
+ gce_ril_env->OnRequestComplete(t, RIL_E_REQUEST_NOT_SUPPORTED, NULL, 0);
+}
+
+static void request_exit_emergency_mode(void* /*data*/, size_t /*datalen*/,
+ RIL_Token t) {
+ ALOGV("Exiting emergency callback mode.");
+
+ gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
+}
+
+static RIL_RadioState gce_ril_current_state() {
+ ALOGV("Reporting radio state %d", gRadioPowerState);
+ return gRadioPowerState;
+}
+
+static int gce_ril_on_supports(int requestCode) {
+ ALOGE("%s: Request code %d not implemented", __FUNCTION__, requestCode);
+ return 1;
+}
+
+static void gce_ril_on_cancel(RIL_Token /*t*/) {
+ ALOGE("Cancel operation not implemented");
+}
+
+static const char* gce_ril_get_version(void) {
+ ALOGV("Reporting Cuttlefish version " CUTTLEFISH_RIL_VERSION_STRING);
+ return CUTTLEFISH_RIL_VERSION_STRING;
+}
+
+static int s_cell_info_rate_ms = INT_MAX;
+static int s_mcc = 0;
+static int s_mnc = 0;
+static int s_lac = 0;
+static int s_cid = 0;
+
+std::vector<RIL_NeighboringCell> gGSMNeighboringCells;
+
+static void request_get_neighboring_cell_ids(void* /*data*/, size_t /*datalen*/,
+ RIL_Token t) {
+ ALOGV("Requesting GSM neighboring cell ids");
+
+ if (!isGSM() || gGSMNeighboringCells.empty()) {
+ gce_ril_env->OnRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
+ return;
+ }
+
+ RIL_NeighboringCell** cells =
+ new RIL_NeighboringCell*[gGSMNeighboringCells.size()];
+
+ for (size_t index = 0; index < gGSMNeighboringCells.size(); ++index) {
+ cells[index] = &gGSMNeighboringCells[index];
+ }
+
+ gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, cells,
+ sizeof(RIL_NeighboringCell*));
+ delete[] cells;
+}
+
+static void request_get_cell_info_list(void* /*data*/, size_t /*datalen*/,
+ RIL_Token t) {
+ struct timespec now;
+ uint64_t curTime;
+
+ ALOGV("Requesting Cell Info List");
+
+ clock_gettime(CLOCK_MONOTONIC, &now);
+ curTime = now.tv_sec * 1000000000LL + now.tv_nsec;
+
+ RIL_CellInfo_v12 ci;
+
+ if (isGSM()) {
+ ci.cellInfoType = RIL_CELL_INFO_TYPE_GSM;
+ ci.registered = 1;
+ ci.timeStampType = RIL_TIMESTAMP_TYPE_ANTENNA; // Our own timestamp.
+ ci.timeStamp = curTime - 1000; // Fake time in the past.
+ ci.CellInfo.gsm.cellIdentityGsm.mcc = s_mcc;
+ ci.CellInfo.gsm.cellIdentityGsm.mnc = s_mnc;
+ ci.CellInfo.gsm.cellIdentityGsm.lac = s_lac;
+ ci.CellInfo.gsm.cellIdentityGsm.cid = s_cid;
+ ci.CellInfo.gsm.signalStrengthGsm.signalStrength = 10;
+ ci.CellInfo.gsm.signalStrengthGsm.bitErrorRate = 0;
+
+ gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, &ci, sizeof(ci));
+ } else if (isCDMA()) {
+ // TODO(ender): CDMA cell support. And LTE.
+ gce_ril_env->OnRequestComplete(t, RIL_E_RADIO_NOT_AVAILABLE, NULL, 0);
+ } else {
+ gce_ril_env->OnRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
+ }
+}
+
+struct NetworkOperator {
+ std::string long_name;
+ std::string short_name;
+ bool is_accessible;
+
+ NetworkOperator() {}
+
+ NetworkOperator(const std::string& long_name, const std::string& short_name,
+ bool is_accessible)
+ : long_name(long_name),
+ short_name(short_name),
+ is_accessible(is_accessible) {}
+};
+
+static std::map<std::string, NetworkOperator> gNetworkOperators;
+static std::string gCurrentNetworkOperator = "";
+
+enum OperatorSelectionMethod {
+ kOperatorAutomatic = 0,
+ kOperatorManual = 1,
+ kOperatorDeregistered = 2,
+ kOperatorManualThenAutomatic = 4
+};
+
+static void init_virtual_network() {
+ gGSMNeighboringCells.resize(1);
+ gGSMNeighboringCells[0].cid = (char*)"0000";
+ gGSMNeighboringCells[0].rssi = 75;
+ gNetworkOperators["311740"] =
+ NetworkOperator("Android Virtual Operator", "Android", true);
+ gNetworkOperators["310300"] =
+ NetworkOperator("Alternative Operator", "Alternative", true);
+ gNetworkOperators["310400"] =
+ NetworkOperator("Hermetic Network Operator", "Hermetic", false);
+}
+
+static OperatorSelectionMethod gOperatorSelectionMethod = kOperatorDeregistered;
+
+static void request_query_network_selection_mode(void* /*data*/,
+ size_t /*datalen*/,
+ RIL_Token t) {
+ ALOGV("Query operator selection mode (%d)", gOperatorSelectionMethod);
+ gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, &gOperatorSelectionMethod,
+ sizeof(gOperatorSelectionMethod));
+}
+
+static void request_operator(void* /*data*/, size_t /*datalen*/, RIL_Token t) {
+ std::map<std::string, NetworkOperator>::iterator iter =
+ gNetworkOperators.find(gCurrentNetworkOperator);
+
+ ALOGV("Requesting current operator info");
+
+ if (iter == gNetworkOperators.end()) {
+ gce_ril_env->OnRequestComplete(t, RIL_E_RADIO_NOT_AVAILABLE, NULL, 0);
+ return;
+ }
+
+ const char* response[] = {iter->second.long_name.c_str(),
+ iter->second.short_name.c_str(),
+ iter->first.c_str()};
+
+ gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, response, sizeof(response));
+}
+
+static void request_query_available_networks(void* /*data*/, size_t /*datalen*/,
+ RIL_Token t) {
+ const char** available_networks =
+ new const char*[gNetworkOperators.size() * 4];
+
+ ALOGV("Querying available networks.");
+
+ // TODO(ender): this should only respond once operator is selected and
+ // registered.
+ int index = 0;
+ for (std::map<std::string, NetworkOperator>::iterator iter =
+ gNetworkOperators.begin();
+ iter != gNetworkOperators.end(); ++iter) {
+ // TODO(ender): wrap in a neat structure maybe?
+ available_networks[index++] = iter->second.long_name.c_str();
+ available_networks[index++] = iter->second.short_name.c_str();
+ available_networks[index++] = iter->first.c_str();
+ if (!iter->second.is_accessible) {
+ available_networks[index++] = "forbidden";
+ } else if (iter->first == gCurrentNetworkOperator) {
+ available_networks[index++] = "current";
+ } else {
+ available_networks[index++] = "available";
+ }
+ }
+
+ gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, &available_networks,
+ 4 * gNetworkOperators.size());
+ delete[] available_networks;
+}
+
+static void request_set_automatic_network_selection(RIL_Token t) {
+ ALOGV("Requesting automatic operator selection");
+ gCurrentNetworkOperator = gNetworkOperators.begin()->first;
+ gOperatorSelectionMethod = kOperatorAutomatic;
+ gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
+}
+
+static void request_set_manual_network_selection(void* data, size_t /*datalen*/,
+ RIL_Token t) {
+ char* mccmnc = (char*)data;
+
+ ALOGV("Requesting manual operator selection: %s", mccmnc);
+
+ std::map<std::string, NetworkOperator>::iterator iter =
+ gNetworkOperators.find(mccmnc);
+
+ if (iter == gNetworkOperators.end() || iter->second.is_accessible) {
+ gce_ril_env->OnRequestComplete(t, RIL_E_ILLEGAL_SIM_OR_ME, NULL, 0);
+ return;
+ }
+
+ gCurrentNetworkOperator = mccmnc;
+ gOperatorSelectionMethod = kOperatorManual;
+
+ gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
+}
+
+static const char kDefaultSMSC[] = "00";
+static int gNextSmsMessageId = 1;
+
+static void request_cdma_send_SMS(void* /*data*/, RIL_Token t) {
+ RIL_SMS_Response response = {0, 0, 0};
+ // RIL_CDMA_SMS_Message* rcsm = (RIL_CDMA_SMS_Message*) data;
+
+ ALOGW("CDMA SMS Send is currently not implemented.");
+
+ // Cdma Send SMS implementation will go here:
+ // But it is not implemented yet.
+ memset(&response, 0, sizeof(response));
+ response.messageRef = -1; // This must be BearerData MessageId.
+ gce_ril_env->OnRequestComplete(t, RIL_E_SMS_SEND_FAIL_RETRY, &response,
+ sizeof(response));
+}
+
+static void request_send_SMS(void* data, RIL_Token t) {
+ RIL_SMS_Response response = {0, 0, 0};
+
+ ALOGV("Send GSM SMS Message");
+
+ // SMSC is an address of SMS center or NULL for default.
+ const char* smsc = ((const char**)data)[0];
+ if (smsc == NULL) smsc = &kDefaultSMSC[0];
+
+ response.messageRef = gNextSmsMessageId++;
+ response.ackPDU = NULL;
+ response.errorCode = 0;
+
+ gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, &response, sizeof(response));
+
+ // response.messageRef = -1;
+ // gce_ril_env->OnRequestComplete(t, RIL_E_SMS_SEND_FAIL_RETRY, &response,
+ // sizeof(response));
+}
+
+static void request_set_cell_info_list_rate(void* data, size_t /*datalen*/,
+ RIL_Token t) {
+ // For now we'll save the rate but no RIL_UNSOL_CELL_INFO_LIST messages
+ // will be sent.
+ ALOGV("Setting cell info list rate.");
+ s_cell_info_rate_ms = ((int*)data)[0];
+ gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
+}
+static void request_ims_send_SMS(void* data, size_t /*datalen*/, RIL_Token t) {
+ RIL_IMS_SMS_Message* args = (RIL_IMS_SMS_Message*)data;
+ RIL_SMS_Response response{};
+
+ ALOGV("Send IMS SMS Message");
+
+ switch (args->tech) {
+ case RADIO_TECH_3GPP:
+ return request_send_SMS(args->message.gsmMessage, t);
+
+ case RADIO_TECH_3GPP2:
+ return request_cdma_send_SMS(args->message.gsmMessage, t);
+
+ default:
+ ALOGE("Invalid SMS format value: %d", args->tech);
+ response.messageRef = -2;
+ gce_ril_env->OnRequestComplete(t, RIL_E_GENERIC_FAILURE, &response,
+ sizeof(response));
+ }
+}
+
+static void request_SMS_acknowledge(void* data, size_t /*datalen*/,
+ RIL_Token t) {
+ int* ack = (int*)data;
+
+ // TODO(ender): we should retain "incoming" sms for later reception.
+ ALOGV("SMS receipt %ssuccessful (reason %d).", ack[0] ? "" : "un", ack[1]);
+
+ gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
+}
+
+struct SimFileCommand {
+ uint8_t command;
+ uint16_t efid;
+ uint8_t param1;
+ uint8_t param2;
+ uint8_t param3;
+
+ bool operator<(const SimFileCommand& other) const {
+ uint64_t sum1, sum2;
+ sum1 = (command * 1ull << 40) | (efid * 1ull << 24) | (param1 << 16) |
+ (param2 << 8) | (param3);
+ sum2 = (other.command * 1ull << 40) | (other.efid * 1ull << 24) |
+ (other.param1 << 16) | (other.param2 << 8) | (other.param3);
+ return sum1 < sum2;
+ }
+
+ SimFileCommand(uint8_t cmd, uint16_t efid, uint8_t p1, uint8_t p2, uint8_t p3)
+ : command(cmd), efid(efid), param1(p1), param2(p2), param3(p3) {}
+};
+
+struct SimFileResponse {
+ uint8_t sw1;
+ uint8_t sw2;
+ const char* data;
+
+ SimFileResponse() : sw1(0), sw2(0), data(NULL) {}
+
+ SimFileResponse(uint8_t sw1, uint8_t sw2, const char* data)
+ : sw1(sw1), sw2(sw2), data(data) {}
+};
+
+// TODO(ender): Double check & rewrite these.
+std::map<SimFileCommand, SimFileResponse> gSimFileSystem;
+
+static void init_sim_file_system() {
+ gSimFileSystem[SimFileCommand(192, 28436, 0, 0, 15)] =
+ SimFileResponse(144, 0, "000000146f1404001aa0aa01020000");
+ gSimFileSystem[SimFileCommand(176, 28436, 0, 0, 20)] =
+ SimFileResponse(144, 0, "416e64726f6964ffffffffffffffffffffffffff");
+ gSimFileSystem[SimFileCommand(192, 28433, 0, 0, 15)] =
+ SimFileResponse(144, 0, "000000016f11040011a0aa01020000");
+ gSimFileSystem[SimFileCommand(176, 28433, 0, 0, 1)] =
+ SimFileResponse(144, 0, "55");
+ gSimFileSystem[SimFileCommand(192, 12258, 0, 0, 15)] =
+ SimFileResponse(144, 0, "0000000a2fe204000fa0aa01020000");
+ gSimFileSystem[SimFileCommand(176, 12258, 0, 0, 10)] =
+ SimFileResponse(144, 0, "98101430121181157002");
+ gSimFileSystem[SimFileCommand(192, 28435, 0, 0, 15)] =
+ SimFileResponse(144, 0, "000000016f13040011a0aa01020000");
+ gSimFileSystem[SimFileCommand(176, 28435, 0, 0, 1)] =
+ SimFileResponse(144, 0, "55");
+ gSimFileSystem[SimFileCommand(192, 28472, 0, 0, 15)] =
+ SimFileResponse(144, 0, "0000000f6f3804001aa0aa01020000");
+ gSimFileSystem[SimFileCommand(176, 28472, 0, 0, 15)] =
+ SimFileResponse(144, 0, "ff30ffff3c003c03000c0000f03f00");
+ gSimFileSystem[SimFileCommand(192, 28617, 0, 0, 15)] =
+ SimFileResponse(144, 0, "000000086fc9040011a0aa01020104");
+ gSimFileSystem[SimFileCommand(178, 28617, 1, 4, 4)] =
+ SimFileResponse(144, 0, "01000000");
+ gSimFileSystem[SimFileCommand(192, 28618, 0, 0, 15)] =
+ SimFileResponse(144, 0, "0000000a6fca040011a0aa01020105");
+ gSimFileSystem[SimFileCommand(178, 28618, 1, 4, 5)] =
+ SimFileResponse(144, 0, "0000000000");
+ gSimFileSystem[SimFileCommand(192, 28589, 0, 0, 15)] =
+ SimFileResponse(144, 0, "000000046fad04000aa0aa01020000");
+ gSimFileSystem[SimFileCommand(176, 28589, 0, 0, 4)] =
+ SimFileResponse(144, 0, "00000003");
+ gSimFileSystem[SimFileCommand(192, 28438, 0, 0, 15)] =
+ SimFileResponse(144, 0, "000000026f1604001aa0aa01020000");
+ gSimFileSystem[SimFileCommand(176, 28438, 0, 0, 2)] =
+ SimFileResponse(144, 0, "0233");
+ gSimFileSystem[SimFileCommand(192, 28486, 0, 0, 15)] =
+ SimFileResponse(148, 4, NULL);
+ gSimFileSystem[SimFileCommand(192, 28621, 0, 0, 15)] =
+ SimFileResponse(148, 4, NULL);
+ gSimFileSystem[SimFileCommand(192, 28613, 0, 0, 15)] =
+ SimFileResponse(144, 0, "000000f06fc504000aa0aa01020118");
+ gSimFileSystem[SimFileCommand(178, 28613, 1, 4, 24)] = SimFileResponse(
+ 144, 0, "43058441aa890affffffffffffffffffffffffffffffffff");
+ gSimFileSystem[SimFileCommand(192, 28480, 0, 0, 15)] =
+ SimFileResponse(144, 0, "000000806f40040011a0aa01020120");
+ // Primary phone number encapsulated
+ // [51][55][21][43][65][f7] = 1 555 1234 567$
+ gSimFileSystem[SimFileCommand(178, 28480, 1, 4, 32)] = SimFileResponse(
+ 144, 0,
+ "ffffffffffffffffffffffffffffffffffff07915155214365f7ffffffffffff");
+ gSimFileSystem[SimFileCommand(192, 28615, 0, 0, 15)] =
+ SimFileResponse(144, 0, "000000406fc7040011a0aa01020120");
+ // Voice mail number encapsulated
+ // [56][6f][69][63][65][6d][61][69][6c] = 'Voicemail'
+ // [51][55][67][45][23][f1] = 1 555 7654 321$
+ gSimFileSystem[SimFileCommand(178, 28615, 1, 4, 32)] = SimFileResponse(
+ 144, 0,
+ "566f6963656d61696cffffffffffffffffff07915155674523f1ffffffffffff");
+ gSimFileSystem[SimFileCommand(192, 12037, 0, 0, 15)] =
+ SimFileResponse(148, 4, NULL);
+ gSimFileSystem[SimFileCommand(192, 28437, 0, 0, 15)] =
+ SimFileResponse(148, 4, NULL);
+ gSimFileSystem[SimFileCommand(192, 28478, 0, 0, 15)] =
+ SimFileResponse(148, 4, NULL);
+ gSimFileSystem[SimFileCommand(192, 28450, 0, 0, 15)] =
+ SimFileResponse(148, 4, NULL);
+ gSimFileSystem[SimFileCommand(192, 28456, 0, 0, 15)] =
+ SimFileResponse(148, 4, NULL);
+ gSimFileSystem[SimFileCommand(192, 28474, 0, 0, 15)] =
+ SimFileResponse(148, 4, NULL);
+ gSimFileSystem[SimFileCommand(192, 28481, 0, 0, 15)] =
+ SimFileResponse(148, 4, NULL);
+ gSimFileSystem[SimFileCommand(192, 28484, 0, 0, 15)] =
+ SimFileResponse(148, 4, NULL);
+ gSimFileSystem[SimFileCommand(192, 28493, 0, 0, 15)] =
+ SimFileResponse(148, 4, NULL);
+ gSimFileSystem[SimFileCommand(192, 28619, 0, 0, 15)] =
+ SimFileResponse(148, 4, NULL);
+ gSimFileSystem[SimFileCommand(176, 28506, 0, 0, 4)] =
+ SimFileResponse(144, 0, "00000013");
+}
+
+static void request_SIM_IO(void* data, size_t /*datalen*/, RIL_Token t) {
+ const RIL_SIM_IO_v6& args = *(RIL_SIM_IO_v6*)data;
+ RIL_SIM_IO_Response sr = {0, 0, 0};
+
+ ALOGV(
+ "Requesting SIM File IO: %d EFID %x, Params: %d, %d, %d, path: %s, "
+ "data %s PIN: %s AID: %s",
+ args.command, args.fileid, args.p1, args.p2, args.p3, args.path,
+ args.data, args.pin2, args.aidPtr);
+
+ SimFileCommand cmd(args.command, args.fileid, args.p1, args.p2, args.p3);
+
+ std::map<SimFileCommand, SimFileResponse>::iterator resp =
+ gSimFileSystem.find(cmd);
+
+ if (resp != gSimFileSystem.end()) {
+ sr.sw1 = resp->second.sw1;
+ sr.sw2 = resp->second.sw2;
+ if (resp->second.data) sr.simResponse = strdup(resp->second.data);
+ gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, &sr, sizeof(sr));
+ return;
+ }
+
+ ALOGW("Unsupported SIM File IO command.");
+ gce_ril_env->OnRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
+}
+
+static void request_enter_sim_pin(void* data, size_t /*datalen*/, RIL_Token t) {
+ const char** pin_aid = (const char**)data;
+
+ ALOGV("Entering PIN: %s / %s", pin_aid[0], pin_aid[1]);
+
+ ++gSimPINAttempts;
+ int remaining_attempts = gSimPINAttemptsMax - gSimPINAttempts;
+
+ bool is_valid = false;
+
+ if (gSimStatus == SIM_PIN) {
+ is_valid = (gSimPIN == pin_aid[0]);
+ } else if (gSimStatus == SIM_PUK) {
+ is_valid = (gSimPUK == pin_aid[0]);
+ } else {
+ ALOGV("Unexpected SIM status for unlock: %d", gSimStatus);
+ gce_ril_env->OnRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
+ return;
+ }
+
+ if (!is_valid) {
+ if (gSimPINAttempts == gSimPINAttemptsMax) {
+ if (gSimStatus == SIM_PIN) {
+ gSimStatus = SIM_PUK;
+ gSimPINAttempts = 0;
+ } else {
+ ALOGV("PIN and PUK verification failed; locking SIM card.");
+ gSimStatus = SIM_NOT_READY;
+ gce_ril_env->OnRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
+ return;
+ }
+ }
+
+ gce_ril_env->OnRequestComplete(t, RIL_E_PASSWORD_INCORRECT,
+ &remaining_attempts,
+ sizeof(remaining_attempts));
+ } else {
+ if (gSimStatus == SIM_PUK) {
+ ALOGV("Resetting SIM PIN to %s", pin_aid[1]);
+ gSimPIN = pin_aid[1];
+ }
+
+ gSimPINAttempts = 0;
+ gSimStatus = SIM_READY;
+ gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, &remaining_attempts,
+ sizeof(remaining_attempts));
+ }
+
+ pollSIMState(NULL);
+}
+
+/**
+ * No longer POLL.
+ */
+static void pollSIMState(void* /*param*/) {
+ // TODO(ender): check radio state?
+
+ ALOGV("Polling SIM Status.");
+
+ switch (gSimStatus) {
+ case SIM_ABSENT:
+ case SIM_PIN:
+ case SIM_PUK:
+ case SIM_NETWORK_PERSONALIZATION:
+ default:
+ ALOGV("SIM Absent or Locked");
+ break;
+
+ case SIM_NOT_READY:
+ // Transition directly to READY. Set default network operator.
+ if (gRadioPowerState == RADIO_STATE_ON) {
+ gSimStatus = SIM_READY;
+ gCurrentNetworkOperator = "311740";
+ }
+
+ gce_ril_env->RequestTimedCallback(pollSIMState, NULL, &TIMEVAL_SIMPOLL);
+ break;
+
+ case SIM_READY:
+ ALOGV("SIM Ready. Notifying network state changed.");
+ break;
+ }
+
+ if (gRadioPowerState != RADIO_STATE_OFF) {
+ gce_ril_env->OnUnsolicitedResponse(RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED,
+ NULL, 0);
+ gce_ril_env->OnUnsolicitedResponse(
+ RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED, NULL, 0);
+ }
+}
+
+std::map<SIM_Status, RIL_AppStatus> gRilAppStatus;
+
+static void init_sim_status() {
+ gRilAppStatus[SIM_ABSENT] = (RIL_AppStatus){RIL_APPTYPE_UNKNOWN,
+ RIL_APPSTATE_UNKNOWN,
+ RIL_PERSOSUBSTATE_UNKNOWN,
+ NULL,
+ NULL,
+ 0,
+ RIL_PINSTATE_UNKNOWN,
+ RIL_PINSTATE_UNKNOWN};
+ gRilAppStatus[SIM_NOT_READY] =
+ (RIL_AppStatus){RIL_APPTYPE_SIM,
+ RIL_APPSTATE_DETECTED,
+ RIL_PERSOSUBSTATE_UNKNOWN,
+ NULL,
+ NULL,
+ 0,
+ RIL_PINSTATE_ENABLED_NOT_VERIFIED,
+ RIL_PINSTATE_ENABLED_NOT_VERIFIED};
+ gRilAppStatus[SIM_READY] = (RIL_AppStatus){
+ RIL_APPTYPE_SIM,
+ RIL_APPSTATE_READY,
+ RIL_PERSOSUBSTATE_READY,
+ NULL,
+ NULL,
+ 0,
+ RIL_PINSTATE_ENABLED_VERIFIED,
+ RIL_PINSTATE_ENABLED_VERIFIED,
+ };
+ gRilAppStatus[SIM_PIN] = (RIL_AppStatus){RIL_APPTYPE_SIM,
+ RIL_APPSTATE_PIN,
+ RIL_PERSOSUBSTATE_UNKNOWN,
+ NULL,
+ NULL,
+ 0,
+ RIL_PINSTATE_ENABLED_NOT_VERIFIED,
+ RIL_PINSTATE_UNKNOWN};
+ gRilAppStatus[SIM_PUK] = (RIL_AppStatus){RIL_APPTYPE_SIM,
+ RIL_APPSTATE_PUK,
+ RIL_PERSOSUBSTATE_UNKNOWN,
+ NULL,
+ NULL,
+ 0,
+ RIL_PINSTATE_ENABLED_BLOCKED,
+ RIL_PINSTATE_UNKNOWN};
+ gRilAppStatus[SIM_NETWORK_PERSONALIZATION] =
+ (RIL_AppStatus){RIL_APPTYPE_SIM,
+ RIL_APPSTATE_SUBSCRIPTION_PERSO,
+ RIL_PERSOSUBSTATE_SIM_NETWORK,
+ NULL,
+ NULL,
+ 0,
+ RIL_PINSTATE_ENABLED_NOT_VERIFIED,
+ RIL_PINSTATE_UNKNOWN};
+ gRilAppStatus[RUIM_ABSENT] = (RIL_AppStatus){RIL_APPTYPE_UNKNOWN,
+ RIL_APPSTATE_UNKNOWN,
+ RIL_PERSOSUBSTATE_UNKNOWN,
+ NULL,
+ NULL,
+ 0,
+ RIL_PINSTATE_UNKNOWN,
+ RIL_PINSTATE_UNKNOWN};
+ gRilAppStatus[RUIM_NOT_READY] = (RIL_AppStatus){RIL_APPTYPE_RUIM,
+ RIL_APPSTATE_DETECTED,
+ RIL_PERSOSUBSTATE_UNKNOWN,
+ NULL,
+ NULL,
+ 0,
+ RIL_PINSTATE_UNKNOWN,
+ RIL_PINSTATE_UNKNOWN};
+ gRilAppStatus[RUIM_READY] = (RIL_AppStatus){RIL_APPTYPE_RUIM,
+ RIL_APPSTATE_READY,
+ RIL_PERSOSUBSTATE_READY,
+ NULL,
+ NULL,
+ 0,
+ RIL_PINSTATE_UNKNOWN,
+ RIL_PINSTATE_UNKNOWN};
+ gRilAppStatus[RUIM_PIN] = (RIL_AppStatus){RIL_APPTYPE_RUIM,
+ RIL_APPSTATE_PIN,
+ RIL_PERSOSUBSTATE_UNKNOWN,
+ NULL,
+ NULL,
+ 0,
+ RIL_PINSTATE_ENABLED_NOT_VERIFIED,
+ RIL_PINSTATE_UNKNOWN};
+ gRilAppStatus[RUIM_PUK] = (RIL_AppStatus){RIL_APPTYPE_RUIM,
+ RIL_APPSTATE_PUK,
+ RIL_PERSOSUBSTATE_UNKNOWN,
+ NULL,
+ NULL,
+ 0,
+ RIL_PINSTATE_ENABLED_BLOCKED,
+ RIL_PINSTATE_UNKNOWN};
+ gRilAppStatus[RUIM_NETWORK_PERSONALIZATION] =
+ (RIL_AppStatus){RIL_APPTYPE_RUIM,
+ RIL_APPSTATE_SUBSCRIPTION_PERSO,
+ RIL_PERSOSUBSTATE_SIM_NETWORK,
+ NULL,
+ NULL,
+ 0,
+ RIL_PINSTATE_ENABLED_NOT_VERIFIED,
+ RIL_PINSTATE_UNKNOWN};
+}
+
+/**
+ * Get the current card status.
+ */
+static void getCardStatus(RIL_Token t) {
+ ALOGV("Querying SIM status.");
+ RIL_CardStatus_v6 card_status;
+
+ if (gSimStatus == SIM_ABSENT) {
+ card_status.card_state = RIL_CARDSTATE_ABSENT;
+ card_status.num_applications = 0;
+ } else {
+ card_status.card_state = RIL_CARDSTATE_PRESENT;
+ card_status.num_applications = 1;
+ }
+
+ card_status.universal_pin_state = RIL_PINSTATE_UNKNOWN;
+ card_status.gsm_umts_subscription_app_index = -1;
+ card_status.cdma_subscription_app_index = -1;
+ card_status.ims_subscription_app_index = -1;
+
+ // Initialize application status
+ for (int i = 0; i < RIL_CARD_MAX_APPS; i++) {
+ card_status.applications[i] = gRilAppStatus[SIM_ABSENT];
+ }
+
+ if (card_status.num_applications > 0) {
+ card_status.gsm_umts_subscription_app_index = 0;
+
+ card_status.applications[0] = gRilAppStatus[gSimStatus];
+ card_status.universal_pin_state = card_status.applications[0].pin1;
+ // To enable basic CDMA (currently neither supported nor functional):
+ // card_status.num_applications = 2;
+ // card_status.cdma_subscription_app_index = 1;
+ // card_status.applications[1] =
+ // gRilAppStatus[SIM_Status(gSimStatus + RUIM_ABSENT)];
+ }
+
+ gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, &card_status,
+ sizeof(card_status));
+}
+
+struct SimSession {
+ std::string aid;
+};
+
+static int gNextSimSessionId = 1;
+static std::map<int, SimSession> gSimSessions;
+
+static void request_sim_open_channel(void* data, size_t /*datalen*/,
+ RIL_Token t) {
+ char* aid = (char*)data;
+ SimSession session;
+
+ ALOGV("Requesting new SIM session");
+
+ if (aid != NULL) {
+ session.aid = aid;
+ }
+
+ int response = gNextSimSessionId++;
+ gSimSessions[response] = session;
+
+ gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, &response, sizeof(response));
+}
+
+static void request_sim_close_channel(void* data, size_t /*datalen*/,
+ RIL_Token t) {
+ int session = *(int*)(data);
+
+ ALOGV("Closing SIM session %d", session);
+
+ if (gSimSessions.erase(session) == 0) {
+ // No such session.
+ gce_ril_env->OnRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
+ } else {
+ gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
+ }
+}
+
+static void request_sim_apdu(void* data, size_t /*datalen*/, RIL_Token t) {
+ RIL_SIM_APDU* apdu = (RIL_SIM_APDU*)data;
+
+ ALOGV("Requesting APDU: Session %d CLA %d INST %d Params: %d %d %d, data %s",
+ apdu->sessionid, apdu->cla, apdu->instruction, apdu->p1, apdu->p2,
+ apdu->p3, apdu->data);
+
+ if (gSimSessions.find(apdu->sessionid) != gSimSessions.end()) {
+ RIL_SIM_IO_Response sr{};
+
+ // Fallback / default behavior.
+ sr.sw1 = 144;
+ sr.sw2 = 0;
+ sr.simResponse = NULL;
+
+ gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, &sr, sizeof(sr));
+ } else {
+ gce_ril_env->OnRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
+ }
+}
+
+// 0 = Lock is available, but disabled.
+// 1 = Lock is available and enabled,
+// 2 = lock is neither available nor enabled
+static const int kFacilityLockAllDisabled = 0;
+
+static void request_facility_lock(void* data, size_t /*datalen*/, RIL_Token t) {
+ char** data_vec = (char**)data;
+
+ // TODO(ender): implement this; essentially: AT+CLCK
+ // See http://www.activexperts.com/sms-component/at/commands/?at=%2BCLCK
+ // and
+ // opt/telephony/src/java/com/android/internal/telephony/CommandsInterface.java
+ // opt/telephony/src/java/com/android/internal/telephony/uicc/UiccCardApplication.java
+
+ ALOGV("Query Facility Lock Code: %s PIN2: %s Service(s): %s AID: %s",
+ data_vec[0], data_vec[1], data_vec[2], data_vec[3]);
+
+ // TODO(ender): there should be a bit vector of responses for each of the
+ // services requested.
+ // Depending on lock code, facilities may be unlocked or locked. We report
+ // these are all unlocked, regardless of the query.
+ gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS,
+ const_cast<int*>(&kFacilityLockAllDisabled),
+ sizeof(kFacilityLockAllDisabled));
+}
+
+static void request_international_subscriber_id_number(RIL_Token t) {
+ // TODO(ender): Reuse MCC and MNC.
+ std::string subscriber_id = gCurrentNetworkOperator.c_str();
+ subscriber_id += "123456789";
+
+ gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS,
+ strdup(subscriber_id.c_str()), sizeof(char*));
+}
+
+static bool gScreenIsOn = true;
+
+static void request_set_screen_state(void* data, size_t /*datalen*/,
+ RIL_Token t) {
+ gScreenIsOn = *(int*)data ? true : false;
+ ALOGV("Screen is %s", gScreenIsOn ? "on" : "off");
+ gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
+}
+
+// Unsure which section this belongs in.
+
+static int gModemTtyMode = 1; // 0 = off, 1 = full, 2 = HCO, 3 = VCO.
+static void request_set_tty_mode(void* data, size_t /*datalen*/, RIL_Token t) {
+ int new_tty_mode = *(int*)(data);
+ ALOGV("Switching modem TTY mode %d -> %d", gModemTtyMode, new_tty_mode);
+
+ if (new_tty_mode >= 0 && new_tty_mode <= 3) {
+ gModemTtyMode = new_tty_mode;
+ gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
+ } else {
+ gce_ril_env->OnRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
+ }
+}
+
+static void request_get_tty_mode(RIL_Token t) {
+ ALOGV("Querying TTY mode");
+ gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, &gModemTtyMode,
+ sizeof(gModemTtyMode));
+}
+
+static bool gImsRegistered = false;
+static int gImsFormat = RADIO_TECH_3GPP;
+
+static void request_ims_registration_state(RIL_Token t) {
+ ALOGV("Querying IMS mode");
+ int reply[2];
+ reply[0] = gImsRegistered;
+ reply[1] = gImsFormat;
+
+ ALOGV("Requesting IMS Registration state: %d, format=%d ", reply[0],
+ reply[1]);
+
+ gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, reply, sizeof(reply));
+}
+
+// New functions after P.
+static void request_start_network_scan(RIL_Token t) {
+ ALOGV("Scanning network - void");
+ gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
+ return;
+}
+
+static void request_set_preferred_network_type_bitmap(int /*request*/, void* data,
+ size_t /*datalen*/,
+ RIL_Token t) {
+ RIL_RadioAccessFamily desired_access = *(RIL_RadioAccessFamily*)(data);
+
+ ALOGV("Requesting modem technology change %d -> %d", default_access, desired_access);
+
+ /** TODO future implementation: set modem type based on radio access family.
+ * 1) find supported_technologies and desired_technologies
+ * 2) return RIL_E_MODE_NOT_SUPPORTED error if not supported
+ */
+ default_access = desired_access;
+ gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
+ return;
+}
+
+static void request_get_preferred_network_type_bitmap(int /*request*/, void* /*data*/,
+ size_t /*datalen*/,
+ RIL_Token t) {
+ ALOGV("Requesting modem radio access family: %d", default_access);
+ gce_ril_env->OnRequestComplete(
+ t, RIL_E_SUCCESS, (RIL_RadioAccessFamily*)(&default_access), sizeof(default_access));
+}
+
+static void request_emergency_dial(int /*request*/, void* /*data*/, size_t /*datalen*/,
+ RIL_Token t) {
+ ALOGV("Emergency dial");
+ gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
+ return;
+}
+
+static void request_set_sim_card_power(int /*request*/, void* /*data*/, size_t /*datalen*/,
+ RIL_Token t) {
+ ALOGV("Set sim card power - void");
+ gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
+ return;
+}
+
+static void request_get_modem_stack_status(int /*request*/, RIL_Token t) {
+ ALOGV("Getting modem stack status - void");
+ gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
+ return;
+}
+
+static void request_enable_modem(int /*request*/, RIL_Token t) {
+ ALOGV("Enabling modem - void");
+ gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
+ return;
+}
+
+static void request_set_system_selection_channels(int /*request*/, RIL_Token t) {
+ ALOGV("request_set_system_selection_channels - void");
+ gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
+ return;
+}
+
+// New functions after Q.
+static void request_set_signal_strength_reporting_criteria(int /*request*/, void* /*data*/,
+ size_t /*datalen*/, RIL_Token t) {
+ ALOGV("request_set_signal_strength_reporting_criteria - void");
+ gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
+ return;
+}
+
+static void request_set_link_capacity_reporting_criteria(int /*request*/, void* /*data*/,
+ size_t /*datalen*/, RIL_Token t) {
+ ALOGV("request_set_link_capacity_reporting_criteria - void");
+ gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
+ return;
+}
+
+static void request_enable_uicc_applications(int /*request*/, void* data,
+ size_t datalen,
+ RIL_Token t) {
+ ALOGV("Enable uicc applications.");
+
+ if (data == NULL || datalen != sizeof(int)) {
+ gce_ril_env->OnRequestComplete(t, RIL_E_INTERNAL_ERR, NULL, 0);
+ return;
+ }
+
+ bool enable = *(int *)(data) != 0;
+
+ ALOGV("areUiccApplicationsEnabled change from %d to %d", areUiccApplicationsEnabled, enable);
+
+ areUiccApplicationsEnabled = enable;
+
+ gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
+}
+
+static void request_are_uicc_applications_enabled(int /*request*/, void* /*data*/,
+ size_t /*datalen*/,
+ RIL_Token t) {
+ ALOGV("Getting whether uicc applications are enabled.");
+
+ gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, &areUiccApplicationsEnabled, sizeof(bool));
+}
+
+static void request_enter_sim_depersonalization(RIL_Token t) {
+ ALOGV("request_enter_sim_depersonalization - void");
+ gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
+ return;
+}
+
+static void request_cdma_send_sms_expect_more(RIL_Token t) {
+ ALOGV("request_cdma_send_sms_expect_more - void");
+ gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
+ return;
+}
+
+static void gce_ril_on_request(int request, void* data, size_t datalen,
+ RIL_Token t) {
+ // Ignore all requests except RIL_REQUEST_GET_SIM_STATUS
+ // when RADIO_STATE_UNAVAILABLE.
+ if (gRadioPowerState == RADIO_STATE_UNAVAILABLE &&
+ request != RIL_REQUEST_GET_SIM_STATUS) {
+ gce_ril_env->OnRequestComplete(t, RIL_E_RADIO_NOT_AVAILABLE, NULL, 0);
+ return;
+ }
+
+ // Ignore all non-power requests when RADIO_STATE_OFF.
+ if (gRadioPowerState == RADIO_STATE_OFF) {
+ switch (request) {
+ case RIL_REQUEST_GET_SIM_STATUS:
+ case RIL_REQUEST_OPERATOR:
+ case RIL_REQUEST_RADIO_POWER:
+ case RIL_REQUEST_QUERY_NETWORK_SELECTION_MODE:
+ // Process all the above, even though the radio is off
+ break;
+ default:
+ gce_ril_env->OnRequestComplete(t, RIL_E_RADIO_NOT_AVAILABLE, NULL, 0);
+ return;
+ }
+ }
+
+ ALOGV("Received request %d", request);
+
+ switch (request) {
+ case RIL_REQUEST_QUERY_AVAILABLE_NETWORKS:
+ request_query_available_networks(data, datalen, t);
+ break;
+ case RIL_REQUEST_GET_IMEI:
+ request_get_imei(t);
+ break;
+ case RIL_REQUEST_GET_IMEISV:
+ request_get_imei_sv(t);
+ break;
+ case RIL_REQUEST_DEACTIVATE_DATA_CALL:
+ request_teardown_data_call(data, datalen, t);
+ break;
+ case RIL_REQUEST_SCREEN_STATE:
+ request_set_screen_state(data, datalen, t);
+ break;
+ case RIL_REQUEST_GET_SIM_STATUS:
+ getCardStatus(t);
+ break;
+ case RIL_REQUEST_GET_CURRENT_CALLS:
+ request_get_current_calls(data, datalen, t);
+ break;
+ case RIL_REQUEST_DIAL:
+ request_dial(data, datalen, t);
+ break;
+ case RIL_REQUEST_HANGUP:
+ request_hangup(data, datalen, t);
+ break;
+ case RIL_REQUEST_HANGUP_WAITING_OR_BACKGROUND:
+ request_hangup_waiting(data, datalen, t);
+ break;
+ case RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND:
+ request_hangup_current(t);
+ break;
+ case RIL_REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE:
+ request_switch_current_and_waiting(t);
+ break;
+ case RIL_REQUEST_ANSWER:
+ request_answer_incoming(t);
+ break;
+ case RIL_REQUEST_SET_MUTE:
+ request_set_mute(data, datalen, t);
+ break;
+ case RIL_REQUEST_GET_MUTE:
+ request_get_mute(t);
+ break;
+ case RIL_REQUEST_CONFERENCE:
+ request_combine_multiparty_call(data, datalen, t);
+ break;
+ case RIL_REQUEST_SEPARATE_CONNECTION:
+ request_split_multiparty_call(data, datalen, t);
+ break;
+ case RIL_REQUEST_UDUB:
+ request_udub_on_incoming_calls(t);
+ break;
+ case RIL_REQUEST_SIGNAL_STRENGTH:
+ request_signal_strength(data, datalen, t);
+ break;
+ case RIL_REQUEST_VOICE_REGISTRATION_STATE:
+ case RIL_REQUEST_DATA_REGISTRATION_STATE:
+ request_registration_state(request, data, datalen, t);
+ break;
+ case RIL_REQUEST_OPERATOR:
+ request_operator(data, datalen, t);
+ break;
+ case RIL_REQUEST_RADIO_POWER:
+ request_radio_power(data, datalen, t);
+ break;
+ case RIL_REQUEST_DTMF:
+ case RIL_REQUEST_DTMF_START:
+ request_send_dtmf(data, datalen, t);
+ break;
+ case RIL_REQUEST_DTMF_STOP:
+ request_send_dtmf_stop(t);
+ break;
+ case RIL_REQUEST_SEND_SMS:
+ request_send_SMS(data, t);
+ break;
+ case RIL_REQUEST_CDMA_SEND_SMS:
+ request_cdma_send_SMS(data, t);
+ break;
+ case RIL_REQUEST_SETUP_DATA_CALL:
+ request_setup_data_call(data, datalen, t);
+ break;
+ case RIL_REQUEST_SMS_ACKNOWLEDGE:
+ request_SMS_acknowledge(data, datalen, t);
+ break;
+ case RIL_REQUEST_GET_IMSI:
+ request_international_subscriber_id_number(t);
+ break;
+ case RIL_REQUEST_QUERY_FACILITY_LOCK:
+ request_facility_lock(data, datalen, t);
+ break;
+ case RIL_REQUEST_SIM_IO:
+ request_SIM_IO(data, datalen, t);
+ break;
+ case RIL_REQUEST_SEND_USSD:
+ request_send_ussd(data, datalen, t);
+ break;
+ case RIL_REQUEST_CANCEL_USSD:
+ request_cancel_ussd(t);
+ break;
+ case RIL_REQUEST_SET_NETWORK_SELECTION_AUTOMATIC:
+ request_set_automatic_network_selection(t);
+ break;
+ case RIL_REQUEST_SET_NETWORK_SELECTION_MANUAL:
+ request_set_manual_network_selection(data, datalen, t);
+ break;
+ case RIL_REQUEST_DATA_CALL_LIST:
+ request_data_calllist(data, datalen, t);
+ break;
+ case RIL_REQUEST_LAST_DATA_CALL_FAIL_CAUSE:
+ request_datacall_fail_cause(t);
+ break;
+ case RIL_REQUEST_QUERY_NETWORK_SELECTION_MODE:
+ request_query_network_selection_mode(data, datalen, t);
+ break;
+ case RIL_REQUEST_OEM_HOOK_RAW:
+ case RIL_REQUEST_OEM_HOOK_STRINGS:
+ ALOGV("OEM Hooks not supported!");
+ gce_ril_env->OnRequestComplete(t, RIL_E_REQUEST_NOT_SUPPORTED, NULL, 0);
+ break;
+ case RIL_REQUEST_WRITE_SMS_TO_SIM:
+ request_write_sms_to_sim(data, datalen, t);
+ break;
+ case RIL_REQUEST_DELETE_SMS_ON_SIM:
+ request_delete_sms_on_sim(data, datalen, t);
+ break;
+ case RIL_REQUEST_ENTER_SIM_PIN:
+ case RIL_REQUEST_ENTER_SIM_PUK:
+ case RIL_REQUEST_ENTER_SIM_PIN2:
+ case RIL_REQUEST_ENTER_SIM_PUK2:
+ case RIL_REQUEST_CHANGE_SIM_PIN:
+ case RIL_REQUEST_CHANGE_SIM_PIN2:
+ request_enter_sim_pin(data, datalen, t);
+ break;
+ case RIL_REQUEST_VOICE_RADIO_TECH: {
+ RIL_RadioTechnology tech = getBestVoiceTechnology(gModemCurrentType);
+ gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, &tech, sizeof(tech));
+ break;
+ }
+ case RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE:
+ request_set_preferred_network_type(request, data, datalen, t);
+ break;
+ case RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE:
+ request_get_preferred_network_type(request, data, datalen, t);
+ break;
+ case RIL_REQUEST_GET_NEIGHBORING_CELL_IDS:
+ request_get_neighboring_cell_ids(data, datalen, t);
+ break;
+ case RIL_REQUEST_GET_CELL_INFO_LIST:
+ request_get_cell_info_list(data, datalen, t);
+ break;
+ case RIL_REQUEST_SET_UNSOL_CELL_INFO_LIST_RATE:
+ request_set_cell_info_list_rate(data, datalen, t);
+ break;
+ case RIL_REQUEST_BASEBAND_VERSION:
+ request_baseband_version(t);
+ break;
+ case RIL_REQUEST_SET_TTY_MODE:
+ request_set_tty_mode(data, datalen, t);
+ break;
+ case RIL_REQUEST_QUERY_TTY_MODE:
+ request_get_tty_mode(t);
+ break;
+ case RIL_REQUEST_GET_RADIO_CAPABILITY:
+ request_get_radio_capability(t);
+ break;
+ case RIL_REQUEST_SET_RADIO_CAPABILITY:
+ request_set_radio_capability(data, datalen, t);
+ break;
+ case RIL_REQUEST_SET_DATA_PROFILE:
+ gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
+ break;
+ case RIL_REQUEST_GET_HARDWARE_CONFIG:
+ request_hardware_config(t);
+ break;
+ case RIL_REQUEST_IMS_REGISTRATION_STATE:
+ request_ims_registration_state(t);
+ break;
+ case RIL_REQUEST_SIM_TRANSMIT_APDU_CHANNEL:
+ request_sim_apdu(data, datalen, t);
+ break;
+ case RIL_REQUEST_SIM_OPEN_CHANNEL:
+ request_sim_open_channel(data, datalen, t);
+ break;
+ case RIL_REQUEST_SIM_CLOSE_CHANNEL:
+ request_sim_close_channel(data, datalen, t);
+ break;
+ case RIL_REQUEST_IMS_SEND_SMS:
+ request_ims_send_SMS(data, datalen, t);
+ break;
+ case RIL_REQUEST_SET_INITIAL_ATTACH_APN:
+ ALOGW("INITIAL ATTACH APN");
+ gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
+ break;
+
+// New requests after P.
+ case RIL_REQUEST_START_NETWORK_SCAN:
+ request_start_network_scan(t);
+ break;
+ case RIL_REQUEST_GET_MODEM_STACK_STATUS:
+ request_get_modem_stack_status(request, t);
+ break;
+ case RIL_REQUEST_ENABLE_MODEM:
+ request_enable_modem(request, t);
+ break;
+ case RIL_REQUEST_EMERGENCY_DIAL:
+ request_emergency_dial(request, data, datalen, t);
+ break;
+ case RIL_REQUEST_SET_SIM_CARD_POWER:
+ request_set_sim_card_power(request, data, datalen, t);
+ break;
+ case RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE_BITMAP:
+ request_get_preferred_network_type_bitmap(request, data, datalen, t);
+ break;
+ case RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE_BITMAP:
+ request_set_preferred_network_type_bitmap(request, data, datalen, t);
+ break;
+ case RIL_REQUEST_SET_SYSTEM_SELECTION_CHANNELS:
+ request_set_system_selection_channels(request, t);
+ break;
+ case RIL_REQUEST_REPORT_STK_SERVICE_IS_RUNNING:
+ gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
+ break;
+ case RIL_REQUEST_DEVICE_IDENTITY:
+ request_device_identity(request, data, datalen, t);
+ break;
+ case RIL_REQUEST_CDMA_GET_SUBSCRIPTION_SOURCE:
+ request_cdma_get_subscription_source(request, data, datalen, t);
+ break;
+ case RIL_REQUEST_CDMA_SUBSCRIPTION:
+ request_cdma_subscription(request, data, datalen, t);
+ break;
+ case RIL_REQUEST_CDMA_SET_SUBSCRIPTION_SOURCE:
+ request_cdma_set_subscription_source(request, data, datalen, t);
+ break;
+ case RIL_REQUEST_CDMA_QUERY_ROAMING_PREFERENCE:
+ request_cdma_get_roaming_preference(request, data, datalen, t);
+ break;
+ case RIL_REQUEST_CDMA_SET_ROAMING_PREFERENCE:
+ request_cdma_set_roaming_preference(request, data, datalen, t);
+ break;
+ case RIL_REQUEST_EXIT_EMERGENCY_CALLBACK_MODE:
+ request_exit_emergency_mode(data, datalen, t);
+ break;
+
+// New requests after Q.
+ case RIL_REQUEST_SET_SIGNAL_STRENGTH_REPORTING_CRITERIA:
+ request_set_signal_strength_reporting_criteria(request, data, datalen, t);
+ break;
+ case RIL_REQUEST_SET_LINK_CAPACITY_REPORTING_CRITERIA:
+ request_set_link_capacity_reporting_criteria(request, data, datalen, t);
+ break;
+ case RIL_REQUEST_ENABLE_UICC_APPLICATIONS:
+ request_enable_uicc_applications(request, data, datalen, t);
+ break;
+ case RIL_REQUEST_ARE_UICC_APPLICATIONS_ENABLED:
+ request_are_uicc_applications_enabled(request, data, datalen, t);
+ break;
+ case RIL_REQUEST_ENTER_SIM_DEPERSONALIZATION:
+ request_enter_sim_depersonalization(t);
+ break;
+ case RIL_REQUEST_CDMA_SEND_SMS_EXPECT_MORE:
+ request_cdma_send_sms_expect_more(t);
+ break;
+ default:
+ ALOGE("Request %d not supported.", request);
+ gce_ril_env->OnRequestComplete(t, RIL_E_REQUEST_NOT_SUPPORTED, NULL, 0);
+ break;
+ }
+}
+
+#define CUTTLEFISH_RIL_VERSION 6
+
+static const RIL_RadioFunctions ril_callbacks = {
+ CUTTLEFISH_RIL_VERSION, gce_ril_on_request, gce_ril_current_state,
+ gce_ril_on_supports, gce_ril_on_cancel, gce_ril_get_version};
+
+extern "C" {
+
+const RIL_RadioFunctions* RIL_Init(const struct RIL_Env* env, int /*argc*/,
+ char** /*argv*/) {
+ time(&gce_ril_start_time);
+ gce_ril_env = env;
+
+ global_ril_config = cvd::DeviceConfig::Get();
+ if (!global_ril_config) {
+ ALOGE("Failed to open device configuration!!!");
+ return nullptr;
+ }
+
+ TearDownNetworkInterface();
+
+ init_modem_supported_network_types();
+ init_modem_technologies();
+ init_virtual_network();
+ init_sim_file_system();
+ init_sim_status();
+
+ return &ril_callbacks;
+}
+
+} // extern "C"
diff --git a/host/commands/run_cvd/server_loop.h b/guest/hals/ril/cuttlefish_ril.h
index 327aff4ab..97d4ae150 100644
--- a/host/commands/run_cvd/server_loop.h
+++ b/guest/hals/ril/cuttlefish_ril.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2006 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.
@@ -16,11 +16,15 @@
#pragma once
-#include "common/libs/fs/shared_fd.h"
-#include "host/commands/run_cvd/process_monitor.h"
+#define RIL_SHLIB
-namespace cuttlefish {
+#define LOG_TAG "CuttlefishRil"
-void ServerLoop(SharedFD server, ProcessMonitor* process_monitor);
+#include <log/log.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <sys/time.h>
-}
+#include <guest/hals/ril/libril/ril.h>
+
+#include <telephony/ril_cdma_sms.h> \ No newline at end of file
diff --git a/guest/hals/ril/libril/Android.mk b/guest/hals/ril/libril/Android.mk
new file mode 100644
index 000000000..1fe498608
--- /dev/null
+++ b/guest/hals/ril/libril/Android.mk
@@ -0,0 +1,65 @@
+# 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.
+
+# We're forced to use Android.mk here because:
+# This depends on headers in hardware/ril/libril
+# hardware/ril/libril is still on Android.mk
+
+ifeq (libril-cuttlefish-fork,$(CUTTLEFISH_LIBRIL_NAME))
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_VENDOR_MODULE := true
+LOCAL_MODULE := libril-cuttlefish-fork
+LOCAL_SRC_FILES:= \
+ ril.cpp \
+ ril_service.cpp \
+ ril_event.cpp \
+ RilSapSocket.cpp \
+ sap_service.cpp \
+
+
+LOCAL_SHARED_LIBRARIES := \
+ liblog \
+ libutils \
+ libcutils \
+ libhardware_legacy \
+ libhidlbase \
+ librilutils \
+ android.hardware.radio@1.0 \
+ android.hardware.radio@1.1 \
+ android.hardware.radio.deprecated@1.0 \
+ android.hardware.radio@1.2 \
+ android.hardware.radio@1.3 \
+ android.hardware.radio@1.4 \
+ android.hardware.radio@1.5 \
+
+LOCAL_STATIC_LIBRARIES := \
+ libprotobuf-c-nano-enable_malloc \
+
+LOCAL_C_INCLUDES += \
+ device/google/cuttlefish \
+ hardware/include \
+ external/nanopb-c \
+ hardware/ril/include \
+ hardware/ril/libril
+
+LOCAL_CFLAGS += \
+ -Wextra \
+ -Wno-unused-parameter
+
+LOCAL_EXPORT_C_INCLUDE_DIRS := hardware/ril/include
+
+include $(BUILD_SHARED_LIBRARY)
+endif
diff --git a/guest/hals/ril/reference-libril/RilSapSocket.cpp b/guest/hals/ril/libril/RilSapSocket.cpp
index 7a76036e2..34658079d 100644
--- a/guest/hals/ril/reference-libril/RilSapSocket.cpp
+++ b/guest/hals/ril/libril/RilSapSocket.cpp
@@ -26,7 +26,7 @@
#include <arpa/inet.h>
#include <errno.h>
#include <sap_service.h>
-#include <guest/hals/ril/reference-libril/ril.h>
+#include <guest/hals/ril/libril/ril.h>
static RilSapSocket::RilSapSocketList *head = NULL;
diff --git a/guest/hals/ril/reference-libril/ril.cpp b/guest/hals/ril/libril/ril.cpp
index 9196ef45a..1c385dfe3 100644
--- a/guest/hals/ril/reference-libril/ril.cpp
+++ b/guest/hals/ril/libril/ril.cpp
@@ -18,7 +18,7 @@
#define LOG_TAG "RILC"
#include <hardware_legacy/power.h>
-#include <guest/hals/ril/reference-libril/ril.h>
+#include <guest/hals/ril/libril/ril.h>
#include <telephony/ril_cdma_sms.h>
#include <cutils/sockets.h>
#include <telephony/record_stream.h>
@@ -44,7 +44,7 @@
#include <netinet/in.h>
#include <cutils/properties.h>
#include <RilSapSocket.h>
-#include <guest/hals/ril/reference-libril/ril_service.h>
+#include <guest/hals/ril/libril/ril_service.h>
#include <sap_service.h>
extern "C" void
@@ -182,30 +182,20 @@ static UserCallbackInfo * internalRequestTimedCallback
/** Index == requestNumber */
static CommandInfo s_commands[] = {
-#include "./ril_commands.h"
+#include "ril_commands.h"
};
static UnsolResponseInfo s_unsolResponses[] = {
-#include "./ril_unsol_commands.h"
+#include "ril_unsol_commands.h"
};
-/* Radio Config Request @{ */
-static CommandInfo s_configCommands[] = {
-#include "./ril_config_commands.h"
-};
-
-static UnsolResponseInfo s_configUnsolResponses[] = {
-#include "./ril_config_unsol_commands.h"
-};
-/* }@ */
-
char * RIL_getServiceName() {
return ril_service_name;
}
RequestInfo *
addRequestToList(int serial, int slotId, int request) {
- RequestInfo *pRI = nullptr;
+ RequestInfo *pRI;
int ret;
RIL_SOCKET_ID socket_id = (RIL_SOCKET_ID) slotId;
/* Hook for current context */
@@ -241,13 +231,6 @@ addRequestToList(int serial, int slotId, int request) {
pRI->token = serial;
pRI->pCI = &(s_commands[request]);
-
- if (request >= RIL_REQUEST_RADIO_CONFIG_BASE &&
- request <= RIL_REQUEST_RADIO_CONFIG_LAST) {
- request = request - RIL_REQUEST_RADIO_CONFIG_BASE;
- pRI->pCI = &(s_configCommands[request]);
- }
-
pRI->socket_id = socket_id;
ret = pthread_mutex_lock(pendingRequestsMutexHook);
@@ -302,12 +285,12 @@ static void resendLastNITZTimeData(RIL_SOCKET_ID socket_id) {
: RESPONSE_UNSOLICITED;
// acquire read lock for the service before calling nitzTimeReceivedInd() since it reads
// nitzTimeReceived in ril_service
- pthread_rwlock_t *radioServiceRwlockPtr = radio_1_6::getRadioServiceRwlock(
+ pthread_rwlock_t *radioServiceRwlockPtr = radio_1_5::getRadioServiceRwlock(
(int) socket_id);
int rwlockRet = pthread_rwlock_rdlock(radioServiceRwlockPtr);
assert(rwlockRet == 0);
- int ret = radio_1_6::nitzTimeReceivedInd(
+ int ret = radio_1_5::nitzTimeReceivedInd(
(int)socket_id, responseType, 0,
RIL_E_SUCCESS, s_lastNITZTimeData, s_lastNITZTimeDataSize);
if (ret == 0) {
@@ -473,23 +456,9 @@ RIL_register (const RIL_RadioFunctions *callbacks) {
== s_unsolResponses[i].requestNumber);
}
- radio_1_6::registerService(&s_callbacks, s_commands);
+ radio_1_5::registerService(&s_callbacks, s_commands);
RLOGI("RILHIDL called registerService");
- /* Radio Config Request @{ */
- for (int i = 1; i < (int)NUM_ELEMS(s_configCommands); i++) {
- assert(i == s_configCommands[i].requestNumber -
- RIL_REQUEST_RADIO_CONFIG_BASE);
- }
-
- for (int i = 0; i < (int)NUM_ELEMS(s_configUnsolResponses); i++) {
- assert(i == s_configUnsolResponses[i].requestNumber -
- RIL_UNSOL_RESPONSE_RADIO_CONFIG_BASE);
- }
- radio_1_6::registerConfigService(&s_callbacks, s_configCommands);
- /* }@ */
-
-
}
extern "C" void
@@ -605,12 +574,12 @@ RIL_onRequestAck(RIL_Token t) {
appendPrintBuf("Ack [%04d]< %s", pRI->token, requestToString(pRI->pCI->requestNumber));
if (pRI->cancelled == 0) {
- pthread_rwlock_t *radioServiceRwlockPtr = radio_1_6::getRadioServiceRwlock(
+ pthread_rwlock_t *radioServiceRwlockPtr = radio_1_5::getRadioServiceRwlock(
(int) socket_id);
int rwlockRet = pthread_rwlock_rdlock(radioServiceRwlockPtr);
assert(rwlockRet == 0);
- radio_1_6::acknowledgeRequest((int) socket_id, pRI->token);
+ radio_1_5::acknowledgeRequest((int) socket_id, pRI->token);
rwlockRet = pthread_rwlock_unlock(radioServiceRwlockPtr);
assert(rwlockRet == 0);
@@ -663,7 +632,7 @@ RIL_onRequestComplete(RIL_Token t, RIL_Errno e, void *response, size_t responsel
RLOGE ("Calling responseFunction() for token %d", pRI->token);
#endif
- pthread_rwlock_t *radioServiceRwlockPtr = radio_1_6::getRadioServiceRwlock((int) socket_id);
+ pthread_rwlock_t *radioServiceRwlockPtr = radio_1_5::getRadioServiceRwlock((int) socket_id);
int rwlockRet = pthread_rwlock_rdlock(radioServiceRwlockPtr);
assert(rwlockRet == 0);
@@ -763,7 +732,6 @@ void RIL_onUnsolicitedResponse(int unsolResponse, const void *data,
int ret;
bool shouldScheduleTimeout = false;
RIL_SOCKET_ID soc_id = RIL_SOCKET_1;
- UnsolResponseInfo *pURI = NULL;
#if defined(ANDROID_MULTI_SIM)
soc_id = socket_id;
@@ -778,24 +746,12 @@ void RIL_onUnsolicitedResponse(int unsolResponse, const void *data,
unsolResponseIndex = unsolResponse - RIL_UNSOL_RESPONSE_BASE;
- if ((unsolResponse < RIL_UNSOL_RESPONSE_BASE)
- || (unsolResponse > RIL_UNSOL_RESPONSE_LAST
- && unsolResponse < RIL_UNSOL_RESPONSE_RADIO_CONFIG_BASE)
- || (unsolResponse > RIL_UNSOL_RESPONSE_RADIO_CONFIG_LAST)) {
+ if ((unsolResponseIndex < 0)
+ || (unsolResponseIndex >= (int32_t)NUM_ELEMS(s_unsolResponses))) {
RLOGE("unsupported unsolicited response code %d", unsolResponse);
return;
}
- if (unsolResponse >= RIL_UNSOL_RESPONSE_BASE
- && unsolResponse <= RIL_UNSOL_RESPONSE_LAST) {
- unsolResponseIndex = unsolResponse - RIL_UNSOL_RESPONSE_BASE;
- pURI = &(s_unsolResponses[unsolResponseIndex]);
- } else if (unsolResponse >= RIL_UNSOL_RESPONSE_RADIO_CONFIG_BASE
- && unsolResponse <= RIL_UNSOL_RESPONSE_RADIO_CONFIG_LAST) {
- unsolResponseIndex = unsolResponse - RIL_UNSOL_RESPONSE_RADIO_CONFIG_BASE;
- pURI = &(s_configUnsolResponses[unsolResponseIndex]);
- }
-
// Grab a wake lock if needed for this reponse,
// as we exit we'll either release it immediately
// or set a timer to release it later.
@@ -822,22 +778,24 @@ void RIL_onUnsolicitedResponse(int unsolResponse, const void *data,
responseType = RESPONSE_UNSOLICITED;
}
- pthread_rwlock_t *radioServiceRwlockPtr = radio_1_6::getRadioServiceRwlock((int) soc_id);
+ pthread_rwlock_t *radioServiceRwlockPtr = radio_1_5::getRadioServiceRwlock((int) soc_id);
int rwlockRet;
if (unsolResponse == RIL_UNSOL_NITZ_TIME_RECEIVED) {
// get a write lock in caes of NITZ since setNitzTimeReceived() is called
rwlockRet = pthread_rwlock_wrlock(radioServiceRwlockPtr);
assert(rwlockRet == 0);
- radio_1_6::setNitzTimeReceived((int) soc_id, android::elapsedRealtime());
+ radio_1_5::setNitzTimeReceived((int) soc_id, android::elapsedRealtime());
} else {
rwlockRet = pthread_rwlock_rdlock(radioServiceRwlockPtr);
assert(rwlockRet == 0);
}
- if (pURI != NULL && pURI->responseFunction != NULL) {
- ret = pURI->responseFunction((int) soc_id, responseType, 0, RIL_E_SUCCESS,
- const_cast<void*>(data), datalen);
+ if (s_unsolResponses[unsolResponseIndex].responseFunction) {
+ RLOGD("calling UNSOLICITED responseFunction for index %d", unsolResponseIndex);
+ ret = s_unsolResponses[unsolResponseIndex].responseFunction(
+ (int) soc_id, responseType, 0, RIL_E_SUCCESS, const_cast<void*>(data),
+ datalen);
} else {
RLOGW("No call responseFunction defined for UNSOLICITED");
}
@@ -1058,12 +1016,12 @@ callStateToString(RIL_CallState s) {
const char *
requestToString(int request) {
/*
- cat guest/hals/ril/reference-libril/ril_commands.h \
+ cat guest/hals/ril/libril/ril_commands.h \
| egrep "^ *{RIL_" \
| sed -re 's/\{RIL_([^,]+),[^,]+,([^}]+).+/case RIL_\1: return "\1";/'
- cat guest/hals/ril/reference-libril/ril_unsol_commands.h \
+ cat guest/hals/ril/libril/ril_unsol_commands.h \
| egrep "^ *{RIL_" \
| sed -re 's/\{RIL_([^,]+),([^}]+).+/case RIL_\1: return "\1";/'
@@ -1115,7 +1073,6 @@ requestToString(int request) {
case RIL_REQUEST_CHANGE_BARRING_PASSWORD: return "CHANGE_BARRING_PASSWORD";
case RIL_REQUEST_QUERY_NETWORK_SELECTION_MODE: return "QUERY_NETWORK_SELECTION_MODE";
case RIL_REQUEST_SET_SYSTEM_SELECTION_CHANNELS: return "RIL_REQUEST_SET_SYSTEM_SELECTION_CHANNELS";
- case RIL_REQUEST_GET_SYSTEM_SELECTION_CHANNELS: return "RIL_REQUEST_GET_SYSTEM_SELECTION_CHANNELS";
case RIL_REQUEST_START_NETWORK_SCAN: return "RIL_REQUEST_START_NETWORK_SCAN";
case RIL_REQUEST_SET_NETWORK_SELECTION_AUTOMATIC: return "SET_NETWORK_SELECTION_AUTOMATIC";
case RIL_REQUEST_SET_NETWORK_SELECTION_MANUAL: return "SET_NETWORK_SELECTION_MANUAL";
@@ -1212,16 +1169,8 @@ requestToString(int request) {
case RIL_REQUEST_SET_CARRIER_INFO_IMSI_ENCRYPTION: return "SET_CARRIER_INFO_IMSI_ENCRYPTION";
case RIL_REQUEST_SET_SIGNAL_STRENGTH_REPORTING_CRITERIA: return "SET_SIGNAL_STRENGTH_REPORTING_CRITERIA";
case RIL_REQUEST_SET_LINK_CAPACITY_REPORTING_CRITERIA: return "SET_LINK_CAPACITY_REPORTING_CRITERIA";
- case RIL_REQUEST_ENABLE_UICC_APPLICATIONS: return "ENABLE_UICC_APPLICATIONS";
- case RIL_REQUEST_ARE_UICC_APPLICATIONS_ENABLED: return "ARE_UICC_APPLICATIONS_ENABLED";
- case RIL_REQUEST_ENTER_SIM_DEPERSONALIZATION: return "ENTER_SIM_DEPERSONALIZATION";
case RIL_REQUEST_CDMA_SEND_SMS_EXPECT_MORE: return "CDMA_SEND_SMS_EXPECT_MORE";
- case RIL_REQUEST_GET_BARRING_INFO: return "GET_BARRING_INFO";
- case RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE_BITMAP: return "SET_PREFERRED_NETWORK_TYPE_BITMAP";
- case RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE_BITMAP: return "GET_PREFERRED_NETWORK_TYPE_BITMAP";
- case RIL_REQUEST_SET_ALLOWED_NETWORK_TYPES_BITMAP: return "SET_ALLOWED_NETWORK_TYPES_BITMAP";
- case RIL_REQUEST_GET_ALLOWED_NETWORK_TYPES_BITMAP: return "GET_ALLOWED_NETWORK_TYPES_BITMAP";
- case RIL_REQUEST_GET_SLICING_CONFIG: return "GET_SLICING_CONFIG";
+ case RIL_REQUEST_ENTER_SIM_DEPERSONALIZATION: return "ENTER_SIM_DEPERSONALIZATION";
case RIL_RESPONSE_ACKNOWLEDGEMENT: return "RESPONSE_ACKNOWLEDGEMENT";
case RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED: return "UNSOL_RESPONSE_RADIO_STATE_CHANGED";
case RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED: return "UNSOL_RESPONSE_CALL_STATE_CHANGED";
diff --git a/guest/hals/ril/reference-libril/ril.h b/guest/hals/ril/libril/ril.h
index 586de42ba..a2479eb38 100644
--- a/guest/hals/ril/reference-libril/ril.h
+++ b/guest/hals/ril/libril/ril.h
@@ -19,7 +19,6 @@
#include <stdlib.h>
#include <stdint.h>
-#include <stdbool.h>
#include <telephony/ril_cdma_sms.h>
#include <telephony/ril_nv_items.h>
#include <telephony/ril_msim.h>
@@ -53,32 +52,26 @@ extern "C" {
* Value of RIL_VERSION should not be changed in future. Here onwards,
* when a new change is supposed to be introduced which could involve new
* schemes added like Wakelocks, data structures added/updated, etc, we would
- * just document RIL version associated with that change below. When OEM updates
- * its RIL with those changes, they would return that new RIL version during
- * RIL_REGISTER. We should make use of the returned version by vendor to
- * identify appropriate scheme or data structure version to use.
+ * just document RIL version associated with that change below. When OEM updates its
+ * RIL with those changes, they would return that new RIL version during RIL_REGISTER.
+ * We should make use of the returned version by vendor to identify appropriate scheme
+ * or data structure version to use.
*
* Documentation of RIL version and associated changes
- * RIL_VERSION = 12 : Updated data structures: RIL_Data_Call_Response_v11,
- * RIL_SIM_IO_v6, RIL_CardStatus_v6,
+ * RIL_VERSION = 12 : This version corresponds to updated data structures namely
+ * RIL_Data_Call_Response_v11, RIL_SIM_IO_v6, RIL_CardStatus_v6,
* RIL_SimRefreshResponse_v7, RIL_CDMA_CallWaiting_v6,
- * RIL_LTE_SignalStrength_v8, RIL_SignalStrength_v10,
- * RIL_CellIdentityGsm_v12, RIL_CellIdentityWcdma_v12,
- * RIL_CellIdentityLte_v12, RIL_CellInfoGsm_v12,
- * RIL_CellInfoWcdma_v12, RIL_CellInfoLte_v12,
- * RIL_CellInfo_v12
+ * RIL_LTE_SignalStrength_v8, RIL_SignalStrength_v10, RIL_CellIdentityGsm_v12
+ * RIL_CellIdentityWcdma_v12, RIL_CellIdentityLte_v12,RIL_CellInfoGsm_v12,
+ * RIL_CellInfoWcdma_v12, RIL_CellInfoLte_v12, RIL_CellInfo_v12.
*
- * RIL_VERSION = 13 : This version includes new wakelock semantics and as the
- * first strongly versioned version it enforces structure
- * use.
- *
- * RIL_VERSION = 14 : New commands added:
- * RIL_REQUEST_SET_CARRIER_RESTRICTIONS,
- * RIL_REQUEST_SET_CARRIER_RESTRICTIONS,
- * RIL_UNSOL_PCO_DATA
- * New data structures are added: RIL_CarrierMatchType,
- * RIL_Carrier, RIL_CarrierRestrictions, RIL_PCO_Data
+ * RIL_VERSION = 13 : This version includes new wakelock semantics and as the first
+ * strongly versioned version it enforces structure use.
*
+ * RIL_VERSION = 14 : New data structures are added, namely RIL_CarrierMatchType,
+ * RIL_Carrier, RIL_CarrierRestrictions and RIL_PCO_Data.
+ * New commands added: RIL_REQUEST_SET_CARRIER_RESTRICTIONS,
+ * RIL_REQUEST_SET_CARRIER_RESTRICTIONS and RIL_UNSOL_PCO_DATA.
*
* RIL_VERSION = 15 : New commands added:
* RIL_UNSOL_MODEM_RESTART,
@@ -100,31 +93,15 @@ extern "C" {
* RIL_REQUEST_ARE_UICC_APPLICATIONS_ENABLED
* RIL_REQUEST_ENTER_SIM_DEPERSONALIZATION
* RIL_REQUEST_CDMA_SEND_SMS_EXPECT_MORE
- * New parameters for RIL_REQUEST_SETUP_DATA_CALL
- * Updated data structures: RIL_DataProfileInfo_v15,
- * RIL_InitialAttachApn_v15, RIL_Data_Call_Response_v12
- * New data structures: RIL_DataRegistrationStateResponse,
- * RIL_OpenChannelParams,
- * RIL_VoiceRegistrationStateResponse same is used in
- * RIL_REQUEST_DATA_REGISTRATION_STATE and
+ * The new parameters for RIL_REQUEST_SETUP_DATA_CALL,
+ * Updated data structures: RIL_DataProfileInfo_v15, RIL_InitialAttachApn_v15,
+ * RIL_Data_Call_Response_v12.
+ * New data structure RIL_DataRegistrationStateResponse, RIL_OpenChannelParams,
+ * RIL_VoiceRegistrationStateResponse same is
+ * used in RIL_REQUEST_DATA_REGISTRATION_STATE and
* RIL_REQUEST_VOICE_REGISTRATION_STATE respectively.
- * RIL_VERSION = 16 : New commands added:
- * RIL_REQUEST_ENABLE_NR_DUAL_CONNECTIVITY
- * RIL_REQUEST_IS_NR_DUAL_CONNECTIVITY_ENABLED
- * RIL_REQUEST_ALLOCATE_PDU_SESSION_ID
- * RIL_REQUEST_RELEASE_PDU_SESSION_ID
- * RIL_REQUEST_START_HANDOVER
- * RIL_REQUEST_CANCEL_HANDOVER
- * RIL_REQUEST_SET_ALLOWED_NETWORK_TYPES_BITMAP
- * RIL_REQUEST_SET_DATA_THROTTLING
- * RIL_REQUEST_GET_SYSTEM_SELECTION_CHANNELS
- * RIL_REQUEST_GET_ALLOWED_NETWORK_TYPES_BITMAP
- * RIL_REQUEST_GET_SLICING_CONFIG
- * New parameters for RIL_REQUEST_SETUP_DATA_CALL
- * Updated data structures: RIL_CarrierInfoForImsiEncryption_v16
- * New data structure: RIL_PublicKeyType
- */
-#define RIL_VERSION 16
+ */
+#define RIL_VERSION 12
#define LAST_IMPRECISE_RIL_VERSION 12 // Better self-documented name
#define RIL_VERSION_MIN 6 /* Minimum RIL_VERSION supported */
@@ -142,7 +119,6 @@ extern "C" {
#define MAX_RADIO_ACCESS_NETWORKS 8
#define MAX_BROADCAST_SMS_CONFIG_INFO 25
-#define RIL_RADIO_ACCESS_SPECIFIER_MAX_SIZE 8
typedef void * RIL_Token;
@@ -296,8 +272,7 @@ typedef enum {
RADIO_TECH_GSM = 16, // Only supports voice
RADIO_TECH_TD_SCDMA = 17,
RADIO_TECH_IWLAN = 18,
- RADIO_TECH_LTE_CA = 19,
- RADIO_TECH_NR = 20
+ RADIO_TECH_LTE_CA = 19
} RIL_RadioTechnology;
typedef enum {
@@ -319,8 +294,7 @@ typedef enum {
RAF_HSPAP = (1 << RADIO_TECH_HSPAP),
RAF_GSM = (1 << RADIO_TECH_GSM),
RAF_TD_SCDMA = (1 << RADIO_TECH_TD_SCDMA),
- RAF_LTE_CA = (1 << RADIO_TECH_LTE_CA),
- RAF_NR = (1 << RADIO_TECH_NR)
+ RAF_LTE_CA = (1 << RADIO_TECH_LTE_CA)
} RIL_RadioAccessFamily;
typedef enum {
@@ -819,8 +793,8 @@ typedef struct {
typedef struct {
int32_t len_allowed_carriers; /* length of array allowed_carriers */
int32_t len_excluded_carriers; /* length of array excluded_carriers */
- RIL_Carrier * allowed_carriers; /* allowed carriers */
- RIL_Carrier * excluded_carriers; /* excluded carriers
+ RIL_Carrier * allowed_carriers; /* whitelist for allowed carriers */
+ RIL_Carrier * excluded_carriers; /* blacklist for explicitly excluded carriers
* which match allowed_carriers. Eg. allowed_carriers match
* mcc/mnc, excluded_carriers has same mcc/mnc and gid1
* is ABCD. It means except the carrier whose gid1 is ABCD,
@@ -838,8 +812,8 @@ typedef enum {
typedef struct {
int32_t len_allowed_carriers; /* length of array allowed_carriers */
int32_t len_excluded_carriers; /* length of array excluded_carriers */
- RIL_Carrier * allowed_carriers; /* allowed carriers */
- RIL_Carrier * excluded_carriers; /* explicitly excluded carriers
+ RIL_Carrier * allowed_carriers; /* whitelist for allowed carriers */
+ RIL_Carrier * excluded_carriers; /* blacklist for explicitly excluded carriers
* which match allowed_carriers. Eg. allowed_carriers match
* mcc/mnc, excluded_carriers has same mcc/mnc and gid1
* is ABCD. It means except the carrier whose gid1 is ABCD,
@@ -864,30 +838,6 @@ typedef struct {
} RIL_CarrierInfoForImsiEncryption;
-/**
- * Public key type from carrier certificate.
- */
-typedef enum {
- EPDG = 1, /* Key type to be used for ePDG */
- WLAN = 2, /* Key type to be used for WLAN */
-} RIL_PublicKeyType;
-
-typedef struct {
- char* mcc; /* MCC of the Carrier. */
- char* mnc; /* MNC of the Carrier. */
- uint8_t* carrierKey; /* Public Key from the Carrier used to encrypt the
- * IMSI/IMPI.
- */
- int32_t carrierKeyLength; /* Length of the Public Key. */
- char* keyIdentifier; /* The keyIdentifier Attribute value pair that helps
- * a server locate the private key to decrypt the
- * permanent identity.
- */
- int64_t expirationTime; /* Date-Time (in UTC) when the key will expire. */
- RIL_PublicKeyType keyType; /* Public key type */
-
-} RIL_CarrierInfoForImsiEncryption_v16;
-
/* See RIL_REQUEST_LAST_CALL_FAIL_CAUSE */
typedef enum {
CALL_FAIL_UNOBTAINABLE_NUMBER = 1,
@@ -1010,21 +960,21 @@ typedef enum {
then it should return one of the following values,
as the UI layer needs to distinguish these
cases for error notification and potential retries. */
- PDP_FAIL_OPERATOR_BARRED = 0x08, /* no retry */
+ PDP_FAIL_OPERATOR_BARRED = 0x08, /* no retry */
PDP_FAIL_NAS_SIGNALLING = 0x0E,
PDP_FAIL_LLC_SNDCP = 0x19,
PDP_FAIL_INSUFFICIENT_RESOURCES = 0x1A,
- PDP_FAIL_MISSING_UNKNOWN_APN = 0x1B, /* no retry */
- PDP_FAIL_UNKNOWN_PDP_ADDRESS_TYPE = 0x1C, /* no retry */
- PDP_FAIL_USER_AUTHENTICATION = 0x1D, /* no retry */
- PDP_FAIL_ACTIVATION_REJECT_GGSN = 0x1E, /* no retry */
+ PDP_FAIL_MISSING_UKNOWN_APN = 0x1B, /* no retry */
+ PDP_FAIL_UNKNOWN_PDP_ADDRESS_TYPE = 0x1C, /* no retry */
+ PDP_FAIL_USER_AUTHENTICATION = 0x1D, /* no retry */
+ PDP_FAIL_ACTIVATION_REJECT_GGSN = 0x1E, /* no retry */
PDP_FAIL_ACTIVATION_REJECT_UNSPECIFIED = 0x1F,
PDP_FAIL_SERVICE_OPTION_NOT_SUPPORTED = 0x20, /* no retry */
PDP_FAIL_SERVICE_OPTION_NOT_SUBSCRIBED = 0x21, /* no retry */
PDP_FAIL_SERVICE_OPTION_OUT_OF_ORDER = 0x22,
- PDP_FAIL_NSAPI_IN_USE = 0x23, /* no retry */
- PDP_FAIL_REGULAR_DEACTIVATION = 0x24, /* possibly restart radio,
- based on framework config */
+ PDP_FAIL_NSAPI_IN_USE = 0x23, /* no retry */
+ PDP_FAIL_REGULAR_DEACTIVATION = 0x24, /* possibly restart radio,
+ based on framework config */
PDP_FAIL_QOS_NOT_ACCEPTED = 0x25,
PDP_FAIL_NETWORK_FAILURE = 0x26,
PDP_FAIL_UMTS_REACTIVATION_REQ = 0x27,
@@ -1035,8 +985,8 @@ typedef enum {
PDP_FAIL_FILTER_SEMANTIC_ERROR = 0x2C,
PDP_FAIL_FILTER_SYTAX_ERROR = 0x2D,
PDP_FAIL_PDP_WITHOUT_ACTIVE_TFT = 0x2E,
- PDP_FAIL_ONLY_IPV4_ALLOWED = 0x32, /* no retry */
- PDP_FAIL_ONLY_IPV6_ALLOWED = 0x33, /* no retry */
+ PDP_FAIL_ONLY_IPV4_ALLOWED = 0x32, /* no retry */
+ PDP_FAIL_ONLY_IPV6_ALLOWED = 0x33, /* no retry */
PDP_FAIL_ONLY_SINGLE_BEARER_ALLOWED = 0x34,
PDP_FAIL_ESM_INFO_NOT_RECEIVED = 0x35,
PDP_FAIL_PDN_CONN_DOES_NOT_EXIST = 0x36,
@@ -1051,7 +1001,7 @@ typedef enum {
PDP_FAIL_UNKNOWN_INFO_ELEMENT = 0x63,
PDP_FAIL_CONDITIONAL_IE_ERROR = 0x64,
PDP_FAIL_MSG_AND_PROTOCOL_STATE_UNCOMPATIBLE = 0x65,
- PDP_FAIL_PROTOCOL_ERRORS = 0x6F, /* no retry */
+ PDP_FAIL_PROTOCOL_ERRORS = 0x6F, /* no retry */
PDP_FAIL_APN_TYPE_CONFLICT = 0x70,
PDP_FAIL_INVALID_PCSCF_ADDR = 0x71,
PDP_FAIL_INTERNAL_CALL_PREEMPT_BY_HIGH_PRIO_APN = 0x72,
@@ -1063,10 +1013,6 @@ typedef enum {
PDP_FAIL_IFACE_AND_POL_FAMILY_MISMATCH = 0x78,
PDP_FAIL_EMM_ACCESS_BARRED_INFINITE_RETRY = 0x79,
PDP_FAIL_AUTH_FAILURE_ON_EMERGENCY_CALL = 0x7A,
- // TODO: add new fail causes from IRadio 1.4 types.hal
- PDP_FAIL_SLICE_REJECTED = 0x8CC,
- PDP_FAIL_MATCH_ALL_RULE_NOT_ALLOWED = 0x8CD,
- ALL_MATCHING_RULES_FAILED = 0x8CE,
// OEM specific error codes. To be used by OEMs when they don't want to
// reveal error code which would be replaced by PDP_FAIL_ERROR_UNSPECIFIED
@@ -1090,18 +1036,18 @@ typedef enum {
PDP_FAIL_VOICE_REGISTRATION_FAIL = -1,
PDP_FAIL_DATA_REGISTRATION_FAIL = -2,
- /* reasons for data call drop - network/modem disconnect */
+ /* reasons for data call drop - network/modem disconnect */
PDP_FAIL_SIGNAL_LOST = -3,
- PDP_FAIL_PREF_RADIO_TECH_CHANGED = -4, /* preferred technology has changed, should retry
- with parameters appropriate for new technology */
- PDP_FAIL_RADIO_POWER_OFF = -5, /* data call was disconnected because radio was resetting,
- powered off - no retry */
- PDP_FAIL_TETHERED_CALL_ACTIVE = -6, /* data call was disconnected by modem because tethered
- mode was up on same APN/data profile - no retry until
- tethered call is off */
-
- PDP_FAIL_ERROR_UNSPECIFIED = 0xffff, /* retry silently. Will be deprecated soon as
- new error codes are added making this unnecessary */
+ PDP_FAIL_PREF_RADIO_TECH_CHANGED = -4,/* preferred technology has changed, should retry
+ with parameters appropriate for new technology */
+ PDP_FAIL_RADIO_POWER_OFF = -5, /* data call was disconnected because radio was resetting,
+ powered off - no retry */
+ PDP_FAIL_TETHERED_CALL_ACTIVE = -6, /* data call was disconnected by modem because tethered
+ mode was up on same APN/data profile - no retry until
+ tethered call is off */
+
+ PDP_FAIL_ERROR_UNSPECIFIED = 0xffff, /* retry silently. Will be deprecated soon as
+ new error codes are added making this unnecessary */
} RIL_DataCallFailCause;
/* See RIL_REQUEST_SETUP_DATA_CALL */
@@ -1262,112 +1208,6 @@ typedef struct
RIL_AppStatus applications[RIL_CARD_MAX_APPS];
} RIL_CardStatus_v6;
-typedef struct {
- RIL_CardStatus_v6 base;
-
- uint32_t physicalSlotId;
- /**
- * An Answer To Reset (ATR) is a message output by a Smart Card conforming to ISO/IEC 7816
- * standards, following electrical reset of the card's chip. The ATR conveys information about
- * the communication parameters proposed by the card, and the card's nature and state.
- *
- * This data is applicable only when cardState is CardState:PRESENT.
- */
- char *atr;
- /**
- * Integrated Circuit Card IDentifier (ICCID) is Unique Identifier of the SIM CARD. File is
- * located in the SIM card at EFiccid (0x2FE2) as per ETSI 102.221. The ICCID is defined by
- * the ITU-T recommendation E.118 ISO/IEC 7816.
- *
- * This data is applicable only when cardState is CardState:PRESENT.
- */
- char *iccid;
-} RIL_CardStatus_v1_2;
-
-typedef struct {
- RIL_CardStatus_v1_2 base;
- char * eid; /* The EID is the eUICC identifier. The EID shall be stored within the ECASD and can be
- * retrieved by the Device at any time using the standard GlobalPlatform GET DATA command.
- *
- * This data is mandatory and applicable only when cardState is CardState:PRESENT and SIM card
- * supports eUICC. */
-} RIL_CardStatus_v1_4;
-
-typedef enum {
- RIL_PERSOSUBSTATE_UNKNOWN_1_5 = 0, /* initial state */
- RIL_PERSOSUBSTATE_IN_PROGRESS_1_5 = 1, /* in between each lock transition */
- RIL_PERSOSUBSTATE_READY_1_5 = 2, /* when either SIM or RUIM Perso is finished
- since each app can only have 1 active perso
- involved */
- RIL_PERSOSUBSTATE_SIM_NETWORK_1_5 = 3,
- RIL_PERSOSUBSTATE_SIM_NETWORK_SUBSET_1_5 = 4,
- RIL_PERSOSUBSTATE_SIM_CORPORATE_1_5 = 5,
- RIL_PERSOSUBSTATE_SIM_SERVICE_PROVIDER_1_5 = 6,
- RIL_PERSOSUBSTATE_SIM_SIM_1_5 = 7,
- RIL_PERSOSUBSTATE_SIM_NETWORK_PUK_1_5 = 8, /* The corresponding perso lock is blocked */
- RIL_PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_1_5 = 9,
- RIL_PERSOSUBSTATE_SIM_CORPORATE_PUK_1_5 = 10,
- RIL_PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_1_5 = 11,
- RIL_PERSOSUBSTATE_SIM_SIM_PUK_1_5 = 12,
- RIL_PERSOSUBSTATE_RUIM_NETWORK1_1_5 = 13,
- RIL_PERSOSUBSTATE_RUIM_NETWORK2_1_5 = 14,
- RIL_PERSOSUBSTATE_RUIM_HRPD_1_5 = 15,
- RIL_PERSOSUBSTATE_RUIM_CORPORATE_1_5 = 16,
- RIL_PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_1_5 = 17,
- RIL_PERSOSUBSTATE_RUIM_RUIM_1_5 = 18,
- RIL_PERSOSUBSTATE_RUIM_NETWORK1_PUK_1_5 = 19, /* The corresponding perso lock is blocked */
- RIL_PERSOSUBSTATE_RUIM_NETWORK2_PUK_1_5 = 20,
- RIL_PERSOSUBSTATE_RUIM_HRPD_PUK_1_5 = 21,
- RIL_PERSOSUBSTATE_RUIM_CORPORATE_PUK_1_5 = 22,
- RIL_PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_1_5 = 23,
- RIL_PERSOSUBSTATE_RUIM_RUIM_PUK_1_5 = 24,
- /**
- * The device is personalized using the content of the Service Provider Name (SPN) in the SIM
- * card.
- */
- RIL_PERSOSUBSTATE_SIM_SPN,
- RIL_PERSOSUBSTATE_SIM_SPN_PUK,
- /**
- * Service Provider and Equivalent Home PLMN
- * The device is personalized using both the content of the GID1 (equivalent to service provider
- * personalization) and the content of the Equivalent Home PLMN (EHPLMN) in the SIM card.
- * If the GID1 in the SIM is absent, then just the content of the Equivalent Home PLMN
- * is matched.
- */
- RIL_PERSOSUBSTATE_SIM_SP_EHPLMN,
- RIL_PERSOSUBSTATE_SIM_SP_EHPLMN_PUK,
- /**
- * Device is personalized using the first digits of the ICCID of the SIM card.
- */
- RIL_PERSOSUBSTATE_SIM_ICCID,
- RIL_PERSOSUBSTATE_SIM_ICCID_PUK,
- /**
- * Device is personalized using the content of the IMPI in the ISIM.
- */
- RIL_PERSOSUBSTATE_SIM_IMPI,
- RIL_PERSOSUBSTATE_SIM_IMPI_PUK,
- /**
- * Network Subset and Service Provider
- * Device is personalized using both the content of GID1 (equivalent to service provider
- * personalization) and the first digits of the IMSI (equivalent to network subset
- * personalization).
- */
- RIL_PERSOSUBSTATE_SIM_NS_SP,
- RIL_PERSOSUBSTATE_SIM_NS_SP_PUK,
-} RIL_PersoSubstateV1_5;
-
-typedef struct {
- RIL_AppStatus base;
- RIL_PersoSubstateV1_5 persoSubstate;
-} RIL_AppStatusV1_5;
-
-typedef struct {
- RIL_CardStatus_v1_4 base;
-
- /** size <= RadioConst::CARD_MAX_APPS */
- RIL_AppStatusV1_5 applications[RIL_CARD_MAX_APPS];
-} RIL_CardStatus_v1_5; // 1.5
-
/** The result of a SIM refresh, returned in data[0] of RIL_UNSOL_SIM_REFRESH
* or as part of RIL_SimRefreshResponse_v7
*/
@@ -1495,6 +1335,7 @@ typedef struct {
*/
} RIL_CDMA_SignalStrength;
+
typedef struct {
int dbm; /* Valid values are positive integers. This value is the actual RSSI value
* multiplied by -1. Example: If the actual RSSI is -75, then this response
@@ -1560,27 +1401,6 @@ typedef struct {
* Reference: 3GPP TS 25.123, section 9.1.1.1 */
} RIL_TD_SCDMA_SignalStrength;
-typedef struct {
- int32_t ssRsrp; /* SS reference signal received power, multiplied by -1.
- * Reference: 3GPP TS 38.215.
- * Range [44, 140], INT_MAX means invalid/unreported. */
- int32_t ssRsrq; /* SS reference signal received quality, multiplied by -1.
- * Reference: 3GPP TS 38.215.
- * Range [3, 20], INT_MAX means invalid/unreported. */
- int32_t ssSinr; /* SS signal-to-noise and interference ratio.
- * Reference: 3GPP TS 38.215 section 5.1.*, 3GPP TS 38.133 section 10.1.16.1.
- * Range [-23, 40], INT_MAX means invalid/unreported. */
- int32_t csiRsrp; /* CSI reference signal received power, multiplied by -1.
- * Reference: 3GPP TS 38.215.
- * Range [44, 140], INT_MAX means invalid/unreported. */
- int32_t csiRsrq; /* CSI reference signal received quality, multiplied by -1.
- * Reference: 3GPP TS 38.215.
- * Range [3, 20], INT_MAX means invalid/unreported. */
- int32_t csiSinr; /* CSI signal-to-noise and interference ratio.
- * Reference: 3GPP TS 138.215 section 5.1.*, 3GPP TS 38.133 section 10.1.16.1.
- * Range [-23, 40], INT_MAX means invalid/unreported. */
-} RIL_NR_SignalStrength;
-
/* Deprecated, use RIL_SignalStrength_v6 */
typedef struct {
RIL_GW_SignalStrength GW_SignalStrength;
@@ -1611,112 +1431,6 @@ typedef struct {
} RIL_SignalStrength_v10;
typedef struct {
- RIL_GW_SignalStrength GW_SignalStrength;
- RIL_CDMA_SignalStrength CDMA_SignalStrength;
- RIL_EVDO_SignalStrength EVDO_SignalStrength;
- RIL_LTE_SignalStrength_v8 LTE_SignalStrength;
- RIL_TD_SCDMA_SignalStrength TD_SCDMA_SignalStrength;
- RIL_SignalStrengthWcdma WCDMA_SignalStrength;
- RIL_NR_SignalStrength NR_SignalStrength;
-} RIL_SignalStrength_v12;
-
-/**
- * Defining signal strength type.
- */
-typedef enum {
- /**
- * Received Signal Strength Indication.
- * Range: -113 dBm and -51 dBm
- * Used RAN: GERAN, CDMA2000
- * Reference: 3GPP TS 27.007 section 8.5.
- */
- RSSI = 1,
- /**
- * Received Signal Code Power.
- * Range: -120 dBm to -25 dBm;
- * Used RAN: UTRAN
- * Reference: 3GPP TS 25.123, section 9.1.1.1
- */
- RSCP = 2,
- /**
- * Reference Signal Received Power.
- * Range: -140 dBm to -44 dBm;
- * Used RAN: EUTRAN
- * Reference: 3GPP TS 36.133 9.1.4
- */
- RSRP = 3,
- /**
- * Reference Signal Received Quality
- * Range: -34 dB to 3 dB;
- * Used RAN: EUTRAN
- * Reference: 3GPP TS 36.133 v12.6.0 section 9.1.7
- */
- RSRQ = 4,
- /**
- * Reference Signal Signal to Noise Ratio
- * Range: -20 dB to 30 dB;
- * Used RAN: EUTRAN
- * Note: this field is optional; how to support it can be decided by the
- * corresponding vendor. Though the response code is not enforced,
- * vendor's implementation must ensure this interface not crashing.
- */
- RSSNR = 5,
- /**
- * 5G SS reference signal received power.
- * Range: -140 dBm to -44 dBm.
- * Used RAN: NGRAN
- * Reference: 3GPP TS 38.215.
- */
- SSRSRP = 6,
- /**
- * 5G SS reference signal received quality.
- * Range: -20 dB to -3 dB.
- * Used RAN: NGRAN
- * Reference: 3GPP TS 38.215.
- */
- SSRSRQ = 7,
- /**
- * 5G SS signal-to-noise and interference ratio.
- * Range: -23 dB to 40 dB
- * Used RAN: NGRAN
- * Reference: 3GPP TS 38.215 section 5.1.*, 3GPP TS 38.133 section 10.1.16.1.
- */
- SSSINR = 8,
-} SignalMeasurementType;
-
-typedef enum {
- RADIO_ACCESS_UNKNOWN = 0, /* Unknown access network */
- RADIO_ACCESS_NET_GERAN = 1, /* GSM EDGE Radio Access Network */
- RADIO_ACCESS_NET_UTRAN = 2, /* Universal Terrestrial Radio Access Network */
- RADIO_ACCESS_NET_EUTRAN = 3, /* Evolved Universal Terrestrial Radio Access Network */
- RADIO_ACCESS_NET_CDMA2000 = 4, /* CDMA 2000 network */
- RADIO_ACCESS_NET_IWLAN = 5, /* Interworking Wireless LAN */
- RADIO_ACCESS_NET_NGRAN = 6, /* Next-Generation Radio Access Network */
-/* the following definitions are extended in radio/1.4 */
-} RIL_RadioAccessNetworks_v1_5;
-
-typedef struct {
- int32_t hysteresisMs;
- int32_t hysteresisDb;
- int32_t thresholdsDbmNumber;
- int32_t *thresholdsDbm;
- bool isEnabled;
- SignalMeasurementType signalMeasurement;
- RIL_RadioAccessNetworks_v1_5 accessNetwork;
-} RIL_SignalStrengthReportingCriteria_v1_5;
-
-typedef struct {
- int32_t hysteresisMs;
- int32_t hysteresisDlKbps;
- int32_t hysteresisUlKbps;
- int32_t thresholdsDownlinkKbpsLength;
- int32_t *thresholdsDownlinkKbps;
- int32_t thresholdsUplinkKbpsLength;
- int32_t *thresholdsUplinkKbps;
- RIL_RadioAccessNetworks_v1_5 accessNetwork;
-} RIL_LinkCapacityReportingCriteria;
-
-typedef struct {
int mcc; /* 3-digit Mobile Country Code, 0..999, INT_MAX if unknown */
int mnc; /* 2 or 3-digit Mobile Network Code, 0..999;
the most significant nibble encodes the number of digits - {2, 3, 0 (unset)};
@@ -1803,28 +1517,6 @@ typedef struct {
int cpid; /* 8-bit Cell Parameters ID described in TS 25.331, 0..127, INT_MAX if unknown */
} RIL_CellIdentityTdscdma;
-typedef struct {
- char alphaLong[32]; /* Long alpha Operator Name String or Enhanced Operator Name String.*/
- char alphaShort[32]; /* Short alpha Operator Name String or Enhanced Operator Name String */
-} RIL_CellIdentityOperatorNames;
-
-typedef struct {
- int mcc; /* 3-digit Mobile Country Code, in range[0, 999]; This value must
- * be valid for registered or camped cells; INT_MAX means invalid/unreported. */
- int mnc; /* 2 or 3-digit Mobile Network Code, in range [0, 999], This value must be valid for
- * registered or camped cells; INT_MAX means invalid/unreported. */
- uint64_t nci; /* NR Cell Identity in range [0, 68719476735] (36 bits) described in 3GPP TS 38.331, which
- * unambiguously identifies a cell within a PLMN. This value must be valid for registered or
- * camped cells; LONG_MAX (2^63-1) means invalid/unreported.*/
- uint32_t pci; /* Physical cell id in range [0, 1007] described in 3GPP TS 38.331. This value must be valid. */
- int32_t tac; /* 16-bit tracking area code, INT_MAX means invalid/unreported. */
- int32_t nrarfcn; /* NR Absolute Radio Frequency Channel Number, in range [0, 3279165].
- * Reference: 3GPP TS 38.101-1 and 3GPP TS 38.101-2 section 5.4.2.1.
- * This value must be valid. */
-
- RIL_CellIdentityOperatorNames operatorNames;
-} RIL_CellIdentityNr;
-
typedef struct {
RIL_CellIdentityGsm cellIdentityGsm;
RIL_GW_SignalStrength signalStrengthGsm;
@@ -1862,15 +1554,10 @@ typedef struct {
} RIL_CellInfoLte_v12;
typedef struct {
- RIL_CellIdentityTdscdma cellIdentityTdscdma;
+ RIL_CellIdentityTdscdma cellIdentityTdscdma;
RIL_TD_SCDMA_SignalStrength signalStrengthTdscdma;
} RIL_CellInfoTdscdma;
-typedef struct {
- RIL_CellIdentityNr cellidentity;
- RIL_NR_SignalStrength signalStrength;
-} RIL_CellInfoNr;
-
// Must be the same as CellInfo.TYPE_XXX
typedef enum {
RIL_CELL_INFO_TYPE_NONE = 0, /* indicates no cell information */
@@ -1878,8 +1565,7 @@ typedef enum {
RIL_CELL_INFO_TYPE_CDMA = 2,
RIL_CELL_INFO_TYPE_LTE = 3,
RIL_CELL_INFO_TYPE_WCDMA = 4,
- RIL_CELL_INFO_TYPE_TD_SCDMA = 5,
- RIL_CELL_INFO_TYPE_NR = 6
+ RIL_CELL_INFO_TYPE_TD_SCDMA = 5
} RIL_CellInfoType;
// Must be the same as CellInfo.TIMESTAMP_TYPE_XXX
@@ -1891,13 +1577,6 @@ typedef enum {
RIL_TIMESTAMP_TYPE_JAVA_RIL = 4,
} RIL_TimeStampType;
-typedef enum {
- CELL_CONNECTION_NONE = 0, // Cell is not a serving cell.
- CELL_CONNECTION_PRIMARY_SERVING, // UE has connection to cell for signalling and
- // possibly data (3GPP 36.331, 25.331).
- CELL_CONNECTION_SECONDARY_SERVING, // UE has connection to cell for data (3GPP 36.331, 25.331).
-} RIL_CellConnectionStatus;
-
typedef struct {
RIL_CellInfoType cellInfoType; /* cell type for selecting from union CellInfo */
int registered; /* !0 if this cell is registered 0 if not registered */
@@ -1927,20 +1606,6 @@ typedef struct {
} RIL_CellInfo_v12;
typedef struct {
- RIL_CellInfoType cellInfoType; /* cell type for selecting from union CellInfo */
- int registered; /* !0 if this cell is registered 0 if not registered */
- RIL_CellConnectionStatus connectionStatus; /* Connection status for the cell. */
- union {
- RIL_CellInfoGsm_v12 gsm;
- RIL_CellInfoCdma cdma;
- RIL_CellInfoLte_v12 lte;
- RIL_CellInfoWcdma_v12 wcdma;
- RIL_CellInfoTdscdma tdscdma;
- RIL_CellInfoNr nr;
- } CellInfo;
-} RIL_CellInfo_v16;
-
-typedef struct {
RIL_CellInfoType cellInfoType; /* cell type for selecting from union CellInfo */
union {
RIL_CellIdentityGsm_v12 cellIdentityGsm;
@@ -1952,101 +1617,6 @@ typedef struct {
}RIL_CellIdentity_v16;
typedef struct {
- RIL_CellInfoType cellInfoType; /* cell type for selecting from union CellInfo */
- union {
- RIL_CellIdentityGsm_v12 cellIdentityGsm;
- RIL_CellIdentityWcdma_v12 cellIdentityWcdma;
- RIL_CellIdentityLte_v12 cellIdentityLte;
- RIL_CellIdentityTdscdma cellIdentityTdscdma;
- RIL_CellIdentityCdma cellIdentityCdma;
- RIL_CellIdentityNr cellIdentityNr;
- };
-} RIL_CellIdentity_v20;
-
-typedef struct {
- int mcc; /* 3-digit Mobile Country Code, 0..999, INT_MAX if unknown */
- int mnc; /* 2 or 3-digit Mobile Network Code, 0..999, INT_MAX if unknown */
- int mnc_digit;/*2 or 3-digit*/
- int lac; /* 16-bit Location Area Code, 0..65535, INT_MAX if unknown */
- int cid; /* 16-bit GSM Cell Identity described in TS 27.007, 0..65535, INT_MAX if unknown */
- int arfcn; /* 16-bit GSM Absolute RF channel number, INT_MAX if unknown */
- uint8_t bsic;/* 6-bit Base Station Identity Code, 0xFF if unknown */
-
- RIL_CellIdentityOperatorNames operatorNames;
-} RIL_CellIdentityGsm_v1_2;
-
-typedef struct {
- int mcc; /* 3-digit Mobile Country Code, 0..999, INT_MAX if unknown */
- int mnc; /* 2 or 3-digit Mobile Network Code, 0..999, INT_MAX if unknown */
- int mnc_digit;/*2 or 3-digit*/
- int lac; /* 16-bit Location Area Code, 0..65535, INT_MAX if unknown */
- int cid; /* 28-bit UMTS Cell Identity described in TS 25.331, 0..268435455, INT_MAX if unknown */
- int psc; /* 9-bit UMTS Primary Scrambling Code described in TS 25.331, 0..511, INT_MAX if unknown */
- int uarfcn; /* 16-bit UMTS Absolute RF Channel Number, INT_MAX if unknown */
-
- RIL_CellIdentityOperatorNames operatorNames;
-} RIL_CellIdentityWcdma_v1_2;
-
-typedef struct {
- int mcc; /* 3-digit Mobile Country Code, 0..999, INT_MAX if unknown */
- int mnc; /* 2 or 3-digit Mobile Network Code, 0..999, INT_MAX if unknown */
- int mnc_digit;/*2 or 3-digit*/
- int ci; /* 28-bit Cell Identity described in TS ???, INT_MAX if unknown */
- int pci; /* physical cell id 0..503; this value must be reported */
- int tac; /* 16-bit tracking area code, INT_MAX if unknown */
- int earfcn; /* 18-bit LTE Absolute RF Channel Number; this value must be reported */
-
- RIL_CellIdentityOperatorNames operatorNames;
- int32_t bandwidth; /* Cell bandwidth, in kHz. */
-} RIL_CellIdentityLte_v1_2;
-
-typedef struct {
- int mcc; /* 3-digit Mobile Country Code, 0..999, INT_MAX if unknown */
- int mnc; /* 2 or 3-digit Mobile Network Code, 0..999, INT_MAX if unknown */
- int mnc_digit;/*2 or 3-digit*/
- int lac; /* 16-bit Location Area Code, 0..65535, INT_MAX if unknown */
- int cid; /* 28-bit UMTS Cell Identity described in TS 25.331, 0..268435455, INT_MAX if unknown */
- int cpid; /* 8-bit Cell Parameters ID described in TS 25.331, 0..127, INT_MAX if unknown */
-
- int32_t uarfcn; /* 16-bit UMTS Absolute RF Channel Number defined in TS 25.102 5.4.4; this value must be valid. */
- RIL_CellIdentityOperatorNames operatorNames;
-} RIL_CellIdentityTdscdma_v1_2;
-
-typedef struct {
- int networkId; /* Network Id 0..65535, INT_MAX if unknown */
- int systemId; /* CDMA System Id 0..32767, INT_MAX if unknown */
- int basestationId; /* Base Station Id 0..65535, INT_MAX if unknown */
- int longitude; /* Longitude is a decimal number as specified in 3GPP2 C.S0005-A v6.0.
- * It is represented in units of 0.25 seconds and ranges from -2592000
- * to 2592000, both values inclusive (corresponding to a range of -180
- * to +180 degrees). INT_MAX if unknown */
-
- int latitude; /* Latitude is a decimal number as specified in 3GPP2 C.S0005-A v6.0.
- * It is represented in units of 0.25 seconds and ranges from -1296000
- * to 1296000, both values inclusive (corresponding to a range of -90
- * to +90 degrees). INT_MAX if unknown */
-
- RIL_CellIdentityOperatorNames operatorNames;
-} RIL_CellIdentityCdma_v1_2;
-
-typedef struct {
- /**
- * Cell type for selecting from union CellInfo.
- * Only one of the below vectors must be of size 1 based on a
- * valid CellInfoType and others must be of size 0.
- * If cell info type is NONE, then all the vectors must be of size 0.
- */
- RIL_CellInfoType cellInfoType;
- union {
- RIL_CellIdentityGsm_v1_2 cellIdentityGsm;
- RIL_CellIdentityWcdma_v1_2 cellIdentityWcdma;
- RIL_CellIdentityLte_v1_2 cellIdentityLte;
- RIL_CellIdentityTdscdma_v1_2 cellIdentityTdscdma;
- RIL_CellIdentityCdma_v1_2 cellIdentityCdma;
- };
-} RIL_CellIdentity_v1_2;
-
-typedef struct {
RIL_RegState regState; // Valid reg states are RIL_NOT_REG_AND_NOT_SEARCHING,
// REG_HOME, RIL_NOT_REG_AND_SEARCHING, REG_DENIED,
// UNKNOWN, REG_ROAMING defined in RegState
@@ -2106,6 +1676,7 @@ typedef struct {
RIL_CellIdentity_v16 cellIdentity; // current cell information
}RIL_VoiceRegistrationStateResponse;
+
typedef struct {
RIL_RegState regState; // Valid reg states are RIL_NOT_REG_AND_NOT_SEARCHING,
// REG_HOME, RIL_NOT_REG_AND_SEARCHING, REG_DENIED,
@@ -2581,11 +2152,6 @@ typedef enum {
CDMA2000 = 0x05, // CDMA 2000 Radio AccessNetwork
} RIL_RadioAccessNetworks;
-typedef struct {
- char *operatorNumeric;
- RIL_RadioAccessNetworks act;
-} RIL_NetworkOperator;
-
typedef enum {
GERAN_BAND_T380 = 1,
GERAN_BAND_T410 = 2,
@@ -2739,45 +2305,6 @@ typedef struct {
// with bands/channels.
} RIL_NetworkScanRequest;
-typedef struct {
- RIL_RadioAccessNetworks_v1_5 radio_access_network; // The type of network to scan.
- uint32_t bands_length; // Length of bands
- union {
- RIL_GeranBands geran_bands[MAX_BANDS];
- RIL_UtranBands utran_bands[MAX_BANDS];
- RIL_EutranBands eutran_bands[MAX_BANDS];
- RIL_NgranBands ngran_bands[MAX_BANDS];
- } bands;
- uint32_t channels_length; // Length of channels
- uint32_t channels[MAX_CHANNELS]; // Frequency channels to scan
-} RIL_RadioAccessSpecifier_v1_5;
-
-typedef struct {
- RIL_ScanType type;
-
- int32_t interval;
-
- uint32_t specifiers_length; // Length of specifiers
-
- RIL_RadioAccessSpecifier_v1_5 specifiers[RIL_RADIO_ACCESS_SPECIFIER_MAX_SIZE];
-
- int32_t maxSearchTime;
-
- int32_t incrementalResults;
-
- int32_t incrementalResultsPeriodicity;
-
- uint32_t mccMncsNumbers;
-
- char **mccMncs;
-} RIL_NetworkScanRequest_v1_5;
-
-typedef struct {
- int specifyChannels;
- uint32_t specifiers_length; // Length of specifiers
- RIL_RadioAccessSpecifier_v1_5 specifiers[RIL_RADIO_ACCESS_SPECIFIER_MAX_SIZE]; // Radio access networks with bands/channels.
-} RIL_SystemSelectionChannels_v1_5;
-
typedef enum {
PARTIAL = 0x01, // The result contains a part of the scan results
COMPLETE = 0x02, // The result contains the last part of the scan results
@@ -2790,182 +2317,6 @@ typedef struct {
RIL_Errno error;
} RIL_NetworkScanResult;
-
-
-/*********************Structs and Enums Extended in 1.4************************/
-/**
- * Defining Emergency Service Category as follows:
- * - General emergency call, all categories;
- * - Police;
- * - Ambulance;
- * - Fire Brigade;
- * - Marine Guard;
- * - Mountain Rescue;
- * - Manually Initiated eCall (MIeC);
- * - Automatically Initiated eCall (AIeC);
- *
- * Category UNSPECIFIED (General emergency call, all categories) indicates that no specific
- * services are associated with this emergency number.
- *
- * Reference: 3gpp 22.101, Section 10 - Emergency Calls
- */
-typedef enum {
- CATEGORY_UNSPECIFIED = 0, /* General emergency call, all categories */
- CATEGORY_POLICE = 1 << 0,
- CATEGORY_AMBULANCE = 1 << 1,
- CATEGORY_FIRE_BRIGADE = 1 << 2,
- CATEGORY_MARINE_GUARD = 1 << 3,
- CATEGORY_MOUNTAIN_RESCUE = 1 << 4,
- CATEGORY_MIEC = 1 << 5, /* Manually Initiated eCall (MIeC) */
- CATEGORY_AIEC = 1 << 6, /* Automatically Initiated eCall (AIeC) */
-} RIL_EmergencyServiceCategory;
-
-/**
- * The source to tell where the corresponding @1.4::EmergencyNumber comes from.
- * Reference: 3gpp 22.101, Section 10 - Emergency Calls
- */
-typedef enum {
- SOURCE_NETWORK_SIGNALING = 1 << 0, /* Indicates the number is from the network signal. */
- SOURCE_SIM = 1 << 1, /* Indicates the number is from the sim card. */
- SOURCE_MODEM_CONFIG = 1 << 2, /* Indicates the number is from the modem config. */
- SOURCE_DEFAULT = 1 << 3, /* Indicates the number is available as default.
- * Per the reference, 112, 911 must always be available;
- * additionally, 000, 08, 110, 999, 118 and 119 must be available
- * when sim is not present. */
-} RIL_EmergencyNumberSource;
-
-/**
- * Indicates how the implementation should handle the emergency call if it is required by Android.
- */
-typedef enum {
- ROUTING_UNKNOWN = 0, /* Indicates Android does not require how to handle
- * the corresponding emergency call; it is decided by implementation. */
- ROUTING_MERGENCY = 1, /* Indicates the implementation must handle the call through emergency routing. */
- ROUTING_NORMAL = 2, /* Indicates the implementation must handle the call through normal call routing. */
-} RIL_EmergencyCallRouting;
-
-/**
- * Emergency number contains information of number, one or more service category(s), zero or more
- * emergency uniform resource names, mobile country code (mcc), mobile network country (mnc) and
- * source(s) that indicate where it comes from.
- *
- * If the emergency number is associated with country, field ‘mcc’ must be provided, otherwise
- * field ‘mcc’ must be an empty string. If the emergency number is associated with network
- * operator, field ‘mcc’ and 'mnc' must be provided, otherwise field ‘mnc’ must be an empty
- * string. If the emergency number is specified with emergency service category(s), field
- * 'categories' must be provided, otherwise field 'categories' must be
- * @1.4::EmergencyServiceCategories::UNSPECIFIED. If the emergency number is specified with
- * emergency uniform resource names (URN), field 'urns' must be provided, otherwise field 'urns'
- * must be an empty list.
- *
- * A unique EmergencyNumber has a unique combination of ‘number’, ‘mcc’, 'mnc', 'categories' and
- * 'urns' fields. Multiple @1.4::EmergencyNumberSource should be merged into one 'sources' field
- * via bitwise-OR combination for the same EmergencyNumber.
- *
- * Reference: 3gpp 22.101, Section 10 - Emergency Calls;
- * 3gpp 23.167, Section 6 - Functional description;
- * 3gpp 24.503, Section 5.1.6.8.1 - General;
- * RFC 5031
- */
-typedef struct {
- RIL_Dial dialInfo;
- RIL_EmergencyServiceCategory categories; /* The bitfield of @1.4::EmergencyServiceCategory(s).
- * See RIL_EmergencyServiceCategory for the value of each bit. */
- uint32_t urnsNumber;
- char ** urns; /* The list of emergency Uniform Resource Names (URN). */
- RIL_EmergencyNumberSource sources; /* The bitfield of @1.4::EmergencyNumberSource(s).
- * See RIL_EmergencyNumberSource for the value of each bit. */
- RIL_EmergencyCallRouting routing;
- bool fromEmergencyDialer;
-} RIL_EmergencyDial;
-
-/******************************************************************************/
-/* Radio Config structure @{ */
-typedef enum {
- /* Physical slot is inactive*/
- SLOT_STATE_INACTIVE = 0x00,
- /* Physical slot is active */
- SLOT_STATE_ACTIVE = 0x01,
-} RIL_SlotState;
-
-typedef struct {
- /* Card state in the physical slot*/
- RIL_CardState cardState;
- /* Slot state Active/Inactive */
- RIL_SlotState slotState;
- /**
- * An Answer To Reset (ATR) is a message output by a Smart Card conforming to ISO/IEC 7816
- * standards, following electrical reset of the card's chip. The ATR conveys information about
- * the communication parameters proposed by the card, and the card's nature and state.
- * This data is applicable only when cardState is CardState:PRESENT.
- */
- char* atr;
- int logicalSlotId;
- /**
- * Integrated Circuit Card IDentifier (ICCID) is Unique Identifier of the SIM CARD. File is
- * located in the SIM card at EFiccid (0x2FE2) as per ETSI 102.221. The ICCID is defined by
- * the ITU-T recommendation E.118 ISO/IEC 7816.
- * This data is applicable only when cardState is CardState:PRESENT.
- */
- char* iccid;
-} RIL_SimSlotStatus;
-
-typedef struct {
- RIL_SimSlotStatus base;
- /**
- * The EID is the eUICC identifier. The EID shall be stored within the ECASD and can be
- * retrieved by the Device at any time using the standard GlobalPlatform GET DATA command.
- *
- * This data is mandatory and applicable only when cardState is CardState:PRESENT and SIM card
- * supports eUICC.
- */
- char* eid;
-} RIL_SimSlotStatus_V1_2;
-
-#define MAX_LOGICAL_MODEM_NUM 4
-
-typedef struct {
- /* Logical modem ID. */
- int modemId;
-} RIL_ModemInfo;
-
-typedef struct {
- /**
- * maxActiveData defines how many logical modems can have
- * PS attached simultaneously. For example, for L+L modem it
- * should be 2.
- */
- int maxActiveData;
- /**
- * maxActiveData defines how many logical modems can have
- * internet PDN connections simultaneously. For example, for L+L
- * DSDS modem it’s 1, and for DSDA modem it’s 2.
- */
- int maxActiveInternetData;
- /**
- * Whether modem supports both internet PDN up so
- * that we can do ping test before tearing down the
- * other one.
- */
- int isInternetLingeringSupported;
- /**
- * List of logical modem information.
- */
- RIL_ModemInfo logicalModemList[MAX_LOGICAL_MODEM_NUM];
-} RIL_PhoneCapability;
-
-typedef struct {
- int numOfLiveModems;
-} RIL_ModemConfig;
-/* }@ */
-
-typedef enum {
- DATA_REQ_REASOPN_NORMAL = 0x01, // The reason of the data request is normal
- DATA_REQ_REASOPN_SHUTDOWN = 0x02, // The reason of the data request is device shutdown
- DATA_REQ_REASOPN_HANDOVER = 0x03, // The reason of the data request is IWLAN data handover
- // to another transport (e.g. from cellular to wifi or vise versa)
-} RIL_DataRequestReason;
-
/**
* RIL_REQUEST_GET_SIM_STATUS
*
@@ -7381,280 +6732,6 @@ typedef enum {
*/
#define RIL_REQUEST_CDMA_SEND_SMS_EXPECT_MORE 157
-/**
- * Get all the barring info for the current camped cell applicable to the current user.
- *
- * @param serial Serial number of request.
- *
- * Response callback is IRadioResponse.getBarringInfoResponse()
- */
-#define RIL_REQUEST_GET_BARRING_INFO 158
-
-/**
- * RIL_REQUEST_ENABLE_NR_DUAL_CONNECTIVITY
- *
- * Enable or disable E-UTRA-NR dual connectivity.
- *
- * Valid errors:
- * SUCCESS
- * RADIO_NOT_AVAILABLE
- * SIM_ABSENT
- * INTERNAL_ERR
- */
-#define RIL_REQUEST_ENABLE_NR_DUAL_CONNECTIVITY 159
-
-/**
- * RIL_REQUEST_IS_NR_DUAL_CONNECTIVITY_ENABLED
- *
- * Whether E-UTRA-NR dual connectivity is enabled.
- *
- * Response: a boolean of enable or not.
- *
- * Valid errors:
- * SUCCESS
- * RADIO_NOT_AVAILABLE
- * SIM_ABSENT
- * INTERNAL_ERR
- */
-#define RIL_REQUEST_IS_NR_DUAL_CONNECTIVITY_ENABLED 160
-
-/**
- * Allocates a pdu session id
- *
- * @param serial Serial number of request.
- *
- * Response callback is IRadioResponse.allocatePduSessionIdResponse()
- */
-#define RIL_REQUEST_ALLOCATE_PDU_SESSION_ID 161
-
-/**
- * Releases a pdu session id
- *
- * @param serial Serial number of request.
- * @param id Pdu session id to release
- *
- * Response callback is IRadioResponse.releasePduSessionIdResponse()
- */
-#define RIL_REQUEST_RELEASE_PDU_SESSION_ID 162
-
-/**
- * Indicates that handover has begun
- *
- * @param serial Serial number of request.
- * @param callId The unique identifier of the corresponding data call
- *
- * Response callback is IRadioResponse.startHandoverResponse()
- */
-#define RIL_REQUEST_START_HANDOVER 163
-
-/**
- * Indicates that a handover has been cancelled
- *
- * @param serial Serial number of request.
- * @param callId The unique identifier of the corresponding data call
- *
- * Response callback is IRadioResponse.cancelHandoverResponse()
- */
-#define RIL_REQUEST_CANCEL_HANDOVER 164
-
-/**
- * RIL_REQUEST_SET_ALLOWED_NETWORK_TYPES_BITMAP
- *
- * Instruct the radio to *only* accept the types of network provided. This
- * is stronger than setPreferredNetworkType which is a suggestion.
- *
- * Valid errors:
- * SUCCESS
- * RADIO_NOT_AVAILABLE (radio resetting)
- * OPERATION_NOT_ALLOWED
- * MODE_NOT_SUPPORTED
- * NO_MEMORY
- * INTERNAL_ERR
- * SYSTEM_ERR
- * INVALID_ARGUMENTS
- * MODEM_ERR
- * REQUEST_NOT_SUPPORTED
- * NO_RESOURCES
- * CANCELLED
- */
-#define RIL_REQUEST_SET_ALLOWED_NETWORK_TYPES_BITMAP 165
-
-/**
-* RIL_REQUEST_SET_DATA_THROTTLING
-*
-* Set the data throttling on device.
-*
-* Response: an int enum of type ThermalMitigationResult as defined in
-* android.telephony.Annotation.
-*
-* Valid errors:
-* SUCCESS
-* RADIO_NOT_AVAILABLE
-* MODEM_ERR
-* INVALID_ARGUMENTS
-*/
-#define RIL_REQUEST_SET_DATA_THROTTLING 166
-
-/**
- * Get which bands the modem's background scan is acting on.
- *
- * Valid errors:
- * SUCCESS
- * RADIO_NOT_AVAILABLE
- * INTERNAL_ERR
- *
- */
-#define RIL_REQUEST_GET_SYSTEM_SELECTION_CHANNELS 167
-
-/**
- * RIL_REQUEST_GET_ALLOWED_NETWORK_TYPES_BITMAP
- *
- * Request previously set allowed network types from the radio.
- *
- * Valid errors:
- * SUCCESS
- * RADIO_NOT_AVAILABLE (radio resetting)
- * OPERATION_NOT_ALLOWED
- * MODE_NOT_SUPPORTED
- * NO_MEMORY
- * INTERNAL_ERR
- * SYSTEM_ERR
- * INVALID_ARGUMENTS
- * MODEM_ERR
- * REQUEST_NOT_SUPPORTED
- * NO_RESOURCES
- * CANCELLED
- */
-#define RIL_REQUEST_GET_ALLOWED_NETWORK_TYPES_BITMAP 168
-
-/**
- * RIL_REQUEST_GET_SLICING_CONFIG
- *
- * Request to get the current slicing configuration including URSP rules and
- * NSSAIs (configured, allowed and rejected).
- *
- * Response callback is IRadioResponse.getSlicingConfigResponse()
- */
-#define RIL_REQUEST_GET_SLICING_CONFIG 169
-
-#define RIL_REQUEST_GET_SIM_PHONEBOOK_RECORDS 170
-
-#define RIL_REQUEST_GET_SIM_PHONEBOOK_CAPACITY 171
-
-#define RIL_REQUEST_UPDATE_SIM_PHONEBOOK_RECORDS 172
-
-
-#define RIL_REQUEST_LAST RIL_REQUEST_UPDATE_SIM_PHONEBOOK_RECORDS
-
-/***********************************************************************/
-
-/* Radio Config @{ */
-#define RIL_REQUEST_RADIO_CONFIG_BASE 600
-
-/**
- * Get SIM Slot status.
- *
- * Request provides the slot status of all active and inactive SIM slots and whether card is
- * present in the slots or not.
- *
- * @param serial Serial number of request.
- *
- * Response callback is IRadioConfigResponse.getSimSlotsStatusResponse()
- */
-#define RIL_REQUEST_CONFIG_GET_SLOT_STATUS 601
-
-/**
- * Set SIM Slot mapping.
-
- * Maps the logical slots to the physical slots. Logical slot is the slot that is seen by modem.
- * Physical slot is the actual physical slot. Request maps the physical slot to logical slot.
- * Logical slots that are already mapped to the requested physical slot are not impacted.
- *
- * Example no. of logical slots 1 and physical slots 2:
- * The only logical slot (index 0) can be mapped to first physical slot (value 0) or second
- * physical slot(value 1), while the other physical slot remains unmapped and inactive.
- * slotMap[0] = 1 or slotMap[0] = 0
- *
- * Example no. of logical slots 2 and physical slots 2:
- * First logical slot (index 0) can be mapped to physical slot 1 or 2 and other logical slot
- * can be mapped to other physical slot. Each logical slot must be mapped to a physical slot.
- * slotMap[0] = 0 and slotMap[1] = 1 or slotMap[0] = 1 and slotMap[1] = 0
- *
- * @param serial Serial number of request
- * @param slotMap Logical to physical slot mapping, size == no. of radio instances. Index is
- * mapping to logical slot and value to physical slot, need to provide all the slots
- * mapping when sending request in case of multi slot device.
- * EX: uint32_t slotMap[logical slot] = physical slot
- * index 0 is the first logical_slot number of logical slots is equal to number of Radio
- * instances and number of physical slots is equal to size of slotStatus in
- * getSimSlotsStatusResponse
- *
- * Response callback is IRadioConfigResponse.setSimSlotsMappingResponse()
- */
-#define RIL_REQUEST_CONFIG_SET_SLOT_MAPPING 602
-
-/**
- * Request current phone capability.
- *
- * @param serial Serial number of request.
- *
- * Response callback is IRadioResponse.getPhoneCapabilityResponse() which
- * will return <@1.1::PhoneCapability>.
- */
-#define RIL_REQUEST_CONFIG_GET_PHONE_CAPABILITY 603
-
-/**
- * Set preferred data modem Id.
- * In a multi-SIM device, notify modem layer which logical modem will be used primarily
- * for data. It helps modem with resource optimization and decisions of what data connections
- * should be satisfied.
- *
- * @param serial Serial number of request.
- * @param modem Id the logical modem ID, which should match one of modem IDs returned
- * from getPhoneCapability().
- *
- * Response callback is IRadioConfigResponse.setPreferredDataModemResponse()
- */
-#define RIL_REQUEST_CONFIG_SET_PREFER_DATA_MODEM 604
-
-/**
- * Set modems configurations by specifying the number of live modems (i.e modems that are
- * enabled and actively working as part of a working telephony stack).
- *
- * Example: this interface can be used to switch to single/multi sim mode by specifying
- * the number of live modems as 1, 2, etc
- *
- * Note: by setting the number of live modems in this API, that number of modems will
- * subsequently get enabled/disabled
- *
- * @param serial serial number of request.
- * @param modemsConfig ModemsConfig object including the number of live modems
- *
- * Response callback is IRadioResponse.setModemsConfigResponse()
- */
-#define RIL_REQUEST_CONFIG_SET_MODEM_CONFIG 605
-
-/**
- * Get modems configurations. This interface is used to get modem configurations
- * which includes the number of live modems (i.e modems that are
- * enabled and actively working as part of a working telephony stack)
- *
- * Note: in order to get the overall number of modems available on the phone,
- * refer to getPhoneCapability API
- *
- * @param serial Serial number of request.
- *
- * Response callback is IRadioResponse.getModemsConfigResponse() which
- * will return <@1.1::ModemsConfig>.
- */
-#define RIL_REQUEST_CONFIG_GET_MODEM_CONFIG 606
-
-#define RIL_REQUEST_CONFIG_GET_HAL_DEVICE_CAPABILITIES 607
-
-/* Make sure to update ril_config_commands.h when changing this constant. */
-#define RIL_REQUEST_RADIO_CONFIG_LAST RIL_REQUEST_CONFIG_GET_HAL_DEVICE_CAPABILITIES
-/* }@ */
-
/***********************************************************************/
/**
@@ -8339,22 +7416,6 @@ typedef enum {
*/
#define RIL_UNSOL_KEEPALIVE_STATUS 1050
-#define RIL_UNSOL_PHYSICAL_CHANNEL_CONFIGS 1051
-
-#define RIL_UNSOL_RESPONSE_LAST RIL_UNSOL_PHYSICAL_CHANNEL_CONFIGS
-
-/***********************************************************************/
-
-#define RIL_UNSOL_RESPONSE_RADIO_CONFIG_BASE 1100
-/**
- * RIL_UNSOL_CONFIG_ICC_SLOT_STATUS
- *
- * "data" is the RIL_SimSlotStatus_V1_2 structure
- */
-#define RIL_UNSOL_CONFIG_ICC_SLOT_STATUS 1052
-
-#define RIL_UNSOL_RESPONSE_RADIO_CONFIG_LAST RIL_UNSOL_CONFIG_ICC_SLOT_STATUS
-
/***********************************************************************/
diff --git a/guest/hals/ril/libril/ril_commands.h b/guest/hals/ril/libril/ril_commands.h
new file mode 100644
index 000000000..0f8a161b1
--- /dev/null
+++ b/guest/hals/ril/libril/ril_commands.h
@@ -0,0 +1,174 @@
+/* //guest/hals/ril/libril/ril_commands.h
+**
+** Copyright 2006, 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.
+*/
+ {0, NULL}, //none
+ {RIL_REQUEST_GET_SIM_STATUS, radio_1_5::getIccCardStatusResponse},
+ {RIL_REQUEST_ENTER_SIM_PIN, radio_1_5::supplyIccPinForAppResponse},
+ {RIL_REQUEST_ENTER_SIM_PUK, radio_1_5::supplyIccPukForAppResponse},
+ {RIL_REQUEST_ENTER_SIM_PIN2, radio_1_5::supplyIccPin2ForAppResponse},
+ {RIL_REQUEST_ENTER_SIM_PUK2, radio_1_5::supplyIccPuk2ForAppResponse},
+ {RIL_REQUEST_CHANGE_SIM_PIN, radio_1_5::changeIccPinForAppResponse},
+ {RIL_REQUEST_CHANGE_SIM_PIN2, radio_1_5::changeIccPin2ForAppResponse},
+ {RIL_REQUEST_ENTER_NETWORK_DEPERSONALIZATION, radio_1_5::supplyNetworkDepersonalizationResponse},
+ {RIL_REQUEST_GET_CURRENT_CALLS, radio_1_5::getCurrentCallsResponse},
+ {RIL_REQUEST_DIAL, radio_1_5::dialResponse},
+ {RIL_REQUEST_GET_IMSI, radio_1_5::getIMSIForAppResponse},
+ {RIL_REQUEST_HANGUP, radio_1_5::hangupConnectionResponse},
+ {RIL_REQUEST_HANGUP_WAITING_OR_BACKGROUND, radio_1_5::hangupWaitingOrBackgroundResponse},
+ {RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND, radio_1_5::hangupForegroundResumeBackgroundResponse},
+ {RIL_REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE, radio_1_5::switchWaitingOrHoldingAndActiveResponse},
+ {RIL_REQUEST_CONFERENCE, radio_1_5::conferenceResponse},
+ {RIL_REQUEST_UDUB, radio_1_5::rejectCallResponse},
+ {RIL_REQUEST_LAST_CALL_FAIL_CAUSE, radio_1_5::getLastCallFailCauseResponse},
+ {RIL_REQUEST_SIGNAL_STRENGTH, radio_1_5::getSignalStrengthResponse},
+ {RIL_REQUEST_VOICE_REGISTRATION_STATE, radio_1_5::getVoiceRegistrationStateResponse},
+ {RIL_REQUEST_DATA_REGISTRATION_STATE, radio_1_5::getDataRegistrationStateResponse},
+ {RIL_REQUEST_OPERATOR, radio_1_5::getOperatorResponse},
+ {RIL_REQUEST_RADIO_POWER, radio_1_5::setRadioPowerResponse},
+ {RIL_REQUEST_DTMF, radio_1_5::sendDtmfResponse},
+ {RIL_REQUEST_SEND_SMS, radio_1_5::sendSmsResponse},
+ {RIL_REQUEST_SEND_SMS_EXPECT_MORE, radio_1_5::sendSMSExpectMoreResponse},
+ {RIL_REQUEST_SETUP_DATA_CALL, radio_1_5::setupDataCallResponse},
+ {RIL_REQUEST_SIM_IO, radio_1_5::iccIOForAppResponse},
+ {RIL_REQUEST_SEND_USSD, radio_1_5::sendUssdResponse},
+ {RIL_REQUEST_CANCEL_USSD, radio_1_5::cancelPendingUssdResponse},
+ {RIL_REQUEST_GET_CLIR, radio_1_5::getClirResponse},
+ {RIL_REQUEST_SET_CLIR, radio_1_5::setClirResponse},
+ {RIL_REQUEST_QUERY_CALL_FORWARD_STATUS, radio_1_5::getCallForwardStatusResponse},
+ {RIL_REQUEST_SET_CALL_FORWARD, radio_1_5::setCallForwardResponse},
+ {RIL_REQUEST_QUERY_CALL_WAITING, radio_1_5::getCallWaitingResponse},
+ {RIL_REQUEST_SET_CALL_WAITING, radio_1_5::setCallWaitingResponse},
+ {RIL_REQUEST_SMS_ACKNOWLEDGE, radio_1_5::acknowledgeLastIncomingGsmSmsResponse},
+ {RIL_REQUEST_GET_IMEI, NULL},
+ {RIL_REQUEST_GET_IMEISV, NULL},
+ {RIL_REQUEST_ANSWER, radio_1_5::acceptCallResponse},
+ {RIL_REQUEST_DEACTIVATE_DATA_CALL, radio_1_5::deactivateDataCallResponse},
+ {RIL_REQUEST_QUERY_FACILITY_LOCK, radio_1_5::getFacilityLockForAppResponse},
+ {RIL_REQUEST_SET_FACILITY_LOCK, radio_1_5::setFacilityLockForAppResponse},
+ {RIL_REQUEST_CHANGE_BARRING_PASSWORD, radio_1_5::setBarringPasswordResponse},
+ {RIL_REQUEST_QUERY_NETWORK_SELECTION_MODE, radio_1_5::getNetworkSelectionModeResponse},
+ {RIL_REQUEST_SET_NETWORK_SELECTION_AUTOMATIC, radio_1_5::setNetworkSelectionModeAutomaticResponse},
+ {RIL_REQUEST_SET_NETWORK_SELECTION_MANUAL, radio_1_5::setNetworkSelectionModeManualResponse},
+ {RIL_REQUEST_QUERY_AVAILABLE_NETWORKS , radio_1_5::getAvailableNetworksResponse},
+ {RIL_REQUEST_DTMF_START, radio_1_5::startDtmfResponse},
+ {RIL_REQUEST_DTMF_STOP, radio_1_5::stopDtmfResponse},
+ {RIL_REQUEST_BASEBAND_VERSION, radio_1_5::getBasebandVersionResponse},
+ {RIL_REQUEST_SEPARATE_CONNECTION, radio_1_5::separateConnectionResponse},
+ {RIL_REQUEST_SET_MUTE, radio_1_5::setMuteResponse},
+ {RIL_REQUEST_GET_MUTE, radio_1_5::getMuteResponse},
+ {RIL_REQUEST_QUERY_CLIP, radio_1_5::getClipResponse},
+ {RIL_REQUEST_LAST_DATA_CALL_FAIL_CAUSE, NULL},
+ {RIL_REQUEST_DATA_CALL_LIST, radio_1_5::getDataCallListResponse},
+ {RIL_REQUEST_RESET_RADIO, NULL},
+ {RIL_REQUEST_OEM_HOOK_RAW, radio_1_5::sendRequestRawResponse},
+ {RIL_REQUEST_OEM_HOOK_STRINGS, radio_1_5::sendRequestStringsResponse},
+ {RIL_REQUEST_SCREEN_STATE, radio_1_5::sendDeviceStateResponse}, // Note the response function is different.
+ {RIL_REQUEST_SET_SUPP_SVC_NOTIFICATION, radio_1_5::setSuppServiceNotificationsResponse},
+ {RIL_REQUEST_WRITE_SMS_TO_SIM, radio_1_5::writeSmsToSimResponse},
+ {RIL_REQUEST_DELETE_SMS_ON_SIM, radio_1_5::deleteSmsOnSimResponse},
+ {RIL_REQUEST_SET_BAND_MODE, radio_1_5::setBandModeResponse},
+ {RIL_REQUEST_QUERY_AVAILABLE_BAND_MODE, radio_1_5::getAvailableBandModesResponse},
+ {RIL_REQUEST_STK_GET_PROFILE, NULL},
+ {RIL_REQUEST_STK_SET_PROFILE, NULL},
+ {RIL_REQUEST_STK_SEND_ENVELOPE_COMMAND, radio_1_5::sendEnvelopeResponse},
+ {RIL_REQUEST_STK_SEND_TERMINAL_RESPONSE, radio_1_5::sendTerminalResponseToSimResponse},
+ {RIL_REQUEST_STK_HANDLE_CALL_SETUP_REQUESTED_FROM_SIM, radio_1_5::handleStkCallSetupRequestFromSimResponse},
+ {RIL_REQUEST_EXPLICIT_CALL_TRANSFER, radio_1_5::explicitCallTransferResponse},
+ {RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE, radio_1_5::setPreferredNetworkTypeResponse},
+ {RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE, radio_1_5::getPreferredNetworkTypeResponse},
+ {RIL_REQUEST_GET_NEIGHBORING_CELL_IDS, radio_1_5::getNeighboringCidsResponse},
+ {RIL_REQUEST_SET_LOCATION_UPDATES, radio_1_5::setLocationUpdatesResponse},
+ {RIL_REQUEST_CDMA_SET_SUBSCRIPTION_SOURCE, radio_1_5::setCdmaSubscriptionSourceResponse},
+ {RIL_REQUEST_CDMA_SET_ROAMING_PREFERENCE, radio_1_5::setCdmaRoamingPreferenceResponse},
+ {RIL_REQUEST_CDMA_QUERY_ROAMING_PREFERENCE, radio_1_5::getCdmaRoamingPreferenceResponse},
+ {RIL_REQUEST_SET_TTY_MODE, radio_1_5::setTTYModeResponse},
+ {RIL_REQUEST_QUERY_TTY_MODE, radio_1_5::getTTYModeResponse},
+ {RIL_REQUEST_CDMA_SET_PREFERRED_VOICE_PRIVACY_MODE, radio_1_5::setPreferredVoicePrivacyResponse},
+ {RIL_REQUEST_CDMA_QUERY_PREFERRED_VOICE_PRIVACY_MODE, radio_1_5::getPreferredVoicePrivacyResponse},
+ {RIL_REQUEST_CDMA_FLASH, radio_1_5::sendCDMAFeatureCodeResponse},
+ {RIL_REQUEST_CDMA_BURST_DTMF, radio_1_5::sendBurstDtmfResponse},
+ {RIL_REQUEST_CDMA_VALIDATE_AND_WRITE_AKEY, NULL},
+ {RIL_REQUEST_CDMA_SEND_SMS, radio_1_5::sendCdmaSmsResponse},
+ {RIL_REQUEST_CDMA_SMS_ACKNOWLEDGE, radio_1_5::acknowledgeLastIncomingCdmaSmsResponse},
+ {RIL_REQUEST_GSM_GET_BROADCAST_SMS_CONFIG, radio_1_5::getGsmBroadcastConfigResponse},
+ {RIL_REQUEST_GSM_SET_BROADCAST_SMS_CONFIG, radio_1_5::setGsmBroadcastConfigResponse},
+ {RIL_REQUEST_GSM_SMS_BROADCAST_ACTIVATION, radio_1_5::setGsmBroadcastActivationResponse},
+ {RIL_REQUEST_CDMA_GET_BROADCAST_SMS_CONFIG, radio_1_5::getCdmaBroadcastConfigResponse},
+ {RIL_REQUEST_CDMA_SET_BROADCAST_SMS_CONFIG, radio_1_5::setCdmaBroadcastConfigResponse},
+ {RIL_REQUEST_CDMA_SMS_BROADCAST_ACTIVATION, radio_1_5::setCdmaBroadcastActivationResponse},
+ {RIL_REQUEST_CDMA_SUBSCRIPTION, radio_1_5::getCDMASubscriptionResponse},
+ {RIL_REQUEST_CDMA_WRITE_SMS_TO_RUIM, radio_1_5::writeSmsToRuimResponse},
+ {RIL_REQUEST_CDMA_DELETE_SMS_ON_RUIM, radio_1_5::deleteSmsOnRuimResponse},
+ {RIL_REQUEST_DEVICE_IDENTITY, radio_1_5::getDeviceIdentityResponse},
+ {RIL_REQUEST_EXIT_EMERGENCY_CALLBACK_MODE, radio_1_5::exitEmergencyCallbackModeResponse},
+ {RIL_REQUEST_GET_SMSC_ADDRESS, radio_1_5::getSmscAddressResponse},
+ {RIL_REQUEST_SET_SMSC_ADDRESS, radio_1_5::setSmscAddressResponse},
+ {RIL_REQUEST_REPORT_SMS_MEMORY_STATUS, radio_1_5::reportSmsMemoryStatusResponse},
+ {RIL_REQUEST_REPORT_STK_SERVICE_IS_RUNNING, radio_1_5::reportStkServiceIsRunningResponse},
+ {RIL_REQUEST_CDMA_GET_SUBSCRIPTION_SOURCE, radio_1_5::getCdmaSubscriptionSourceResponse},
+ {RIL_REQUEST_ISIM_AUTHENTICATION, radio_1_5::requestIsimAuthenticationResponse},
+ {RIL_REQUEST_ACKNOWLEDGE_INCOMING_GSM_SMS_WITH_PDU, radio_1_5::acknowledgeIncomingGsmSmsWithPduResponse},
+ {RIL_REQUEST_STK_SEND_ENVELOPE_WITH_STATUS, radio_1_5::sendEnvelopeWithStatusResponse},
+ {RIL_REQUEST_VOICE_RADIO_TECH, radio_1_5::getVoiceRadioTechnologyResponse},
+ {RIL_REQUEST_GET_CELL_INFO_LIST, radio_1_5::getCellInfoListResponse},
+ {RIL_REQUEST_SET_UNSOL_CELL_INFO_LIST_RATE, radio_1_5::setCellInfoListRateResponse},
+ {RIL_REQUEST_SET_INITIAL_ATTACH_APN, radio_1_5::setInitialAttachApnResponse},
+ {RIL_REQUEST_IMS_REGISTRATION_STATE, radio_1_5::getImsRegistrationStateResponse},
+ {RIL_REQUEST_IMS_SEND_SMS, radio_1_5::sendImsSmsResponse},
+ {RIL_REQUEST_SIM_TRANSMIT_APDU_BASIC, radio_1_5::iccTransmitApduBasicChannelResponse},
+ {RIL_REQUEST_SIM_OPEN_CHANNEL, radio_1_5::iccOpenLogicalChannelResponse},
+ {RIL_REQUEST_SIM_CLOSE_CHANNEL, radio_1_5::iccCloseLogicalChannelResponse},
+ {RIL_REQUEST_SIM_TRANSMIT_APDU_CHANNEL, radio_1_5::iccTransmitApduLogicalChannelResponse},
+ {RIL_REQUEST_NV_READ_ITEM, radio_1_5::nvReadItemResponse},
+ {RIL_REQUEST_NV_WRITE_ITEM, radio_1_5::nvWriteItemResponse},
+ {RIL_REQUEST_NV_WRITE_CDMA_PRL, radio_1_5::nvWriteCdmaPrlResponse},
+ {RIL_REQUEST_NV_RESET_CONFIG, radio_1_5::nvResetConfigResponse},
+ {RIL_REQUEST_SET_UICC_SUBSCRIPTION, radio_1_5::setUiccSubscriptionResponse},
+ {RIL_REQUEST_ALLOW_DATA, radio_1_5::setDataAllowedResponse},
+ {RIL_REQUEST_GET_HARDWARE_CONFIG, radio_1_5::getHardwareConfigResponse},
+ {RIL_REQUEST_SIM_AUTHENTICATION, radio_1_5::requestIccSimAuthenticationResponse},
+ {RIL_REQUEST_GET_DC_RT_INFO, NULL},
+ {RIL_REQUEST_SET_DC_RT_INFO_RATE, NULL},
+ {RIL_REQUEST_SET_DATA_PROFILE, radio_1_5::setDataProfileResponse},
+ {RIL_REQUEST_SHUTDOWN, radio_1_5::requestShutdownResponse},
+ {RIL_REQUEST_GET_RADIO_CAPABILITY, radio_1_5::getRadioCapabilityResponse},
+ {RIL_REQUEST_SET_RADIO_CAPABILITY, radio_1_5::setRadioCapabilityResponse},
+ {RIL_REQUEST_START_LCE, radio_1_5::startLceServiceResponse},
+ {RIL_REQUEST_STOP_LCE, radio_1_5::stopLceServiceResponse},
+ {RIL_REQUEST_PULL_LCEDATA, radio_1_5::pullLceDataResponse},
+ {RIL_REQUEST_GET_ACTIVITY_INFO, radio_1_5::getModemActivityInfoResponse},
+ {RIL_REQUEST_SET_CARRIER_RESTRICTIONS, radio_1_5::setAllowedCarriersResponse},
+ {RIL_REQUEST_GET_CARRIER_RESTRICTIONS, radio_1_5::getAllowedCarriersResponse},
+ {RIL_REQUEST_SEND_DEVICE_STATE, radio_1_5::sendDeviceStateResponse},
+ {RIL_REQUEST_SET_UNSOLICITED_RESPONSE_FILTER, radio_1_5::setIndicationFilterResponse},
+ {RIL_REQUEST_SET_SIM_CARD_POWER, radio_1_5::setSimCardPowerResponse},
+ {RIL_REQUEST_SET_CARRIER_INFO_IMSI_ENCRYPTION, radio_1_5::setCarrierInfoForImsiEncryptionResponse},
+ {RIL_REQUEST_START_NETWORK_SCAN, radio_1_5::startNetworkScanResponse},
+ {RIL_REQUEST_STOP_NETWORK_SCAN, radio_1_5::stopNetworkScanResponse},
+ {RIL_REQUEST_START_KEEPALIVE, radio_1_5::startKeepaliveResponse},
+ {RIL_REQUEST_STOP_KEEPALIVE, radio_1_5::stopKeepaliveResponse},
+ {RIL_REQUEST_GET_MODEM_STACK_STATUS, radio_1_5::getModemStackStatusResponse},
+ {RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE_BITMAP, radio_1_5::getPreferredNetworkTypeBitmapResponse},
+ {RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE_BITMAP, radio_1_5::setPreferredNetworkTypeBitmapResponse},
+ {RIL_REQUEST_EMERGENCY_DIAL, radio_1_5::emergencyDialResponse},
+ {RIL_REQUEST_SET_SYSTEM_SELECTION_CHANNELS, radio_1_5::setSystemSelectionChannelsResponse},
+ {RIL_REQUEST_ENABLE_MODEM, radio_1_5::enableModemResponse},
+ {RIL_REQUEST_SET_SIGNAL_STRENGTH_REPORTING_CRITERIA, radio_1_5::setSignalStrengthReportingCriteriaResponse},
+ {RIL_REQUEST_SET_LINK_CAPACITY_REPORTING_CRITERIA, radio_1_5::setLinkCapacityReportingCriteriaResponse},
+ {RIL_REQUEST_ENABLE_UICC_APPLICATIONS, radio_1_5::enableUiccApplicationsResponse},
+ {RIL_REQUEST_ARE_UICC_APPLICATIONS_ENABLED, radio_1_5::areUiccApplicationsEnabledResponse},
+ {RIL_REQUEST_ENTER_SIM_DEPERSONALIZATION, radio_1_5::supplySimDepersonalizationResponse},
+ {RIL_REQUEST_CDMA_SEND_SMS_EXPECT_MORE, radio_1_5::sendCdmaSmsExpectMoreResponse}
diff --git a/guest/hals/ril/reference-libril/ril_event.cpp b/guest/hals/ril/libril/ril_event.cpp
index 84b8b72a7..84b8b72a7 100644
--- a/guest/hals/ril/reference-libril/ril_event.cpp
+++ b/guest/hals/ril/libril/ril_event.cpp
diff --git a/guest/hals/ril/reference-libril/ril_ex.h b/guest/hals/ril/libril/ril_ex.h
index bda71273c..e0fcd7bfc 100644
--- a/guest/hals/ril/reference-libril/ril_ex.h
+++ b/guest/hals/ril/libril/ril_ex.h
@@ -17,7 +17,7 @@
#ifndef RIL_EX_H_INCLUDED
#define RIL_EX_H_INCLUDED
-#include <guest/hals/ril/reference-libril/ril.h>
+#include <guest/hals/ril/libril/ril.h>
#include <telephony/record_stream.h>
#define NUM_ELEMS_SOCKET(a) (sizeof (a) / sizeof (a)[0])
diff --git a/guest/hals/ril/reference-libril/ril_service.cpp b/guest/hals/ril/libril/ril_service.cpp
index c7b80a6d9..42e2caee9 100644
--- a/guest/hals/ril/reference-libril/ril_service.cpp
+++ b/guest/hals/ril/libril/ril_service.cpp
@@ -16,18 +16,18 @@
#define LOG_TAG "RILC"
-#include <android/hardware/radio/1.6/IRadio.h>
-#include <android/hardware/radio/1.6/IRadioIndication.h>
-#include <android/hardware/radio/1.6/IRadioResponse.h>
-#include <android/hardware/radio/1.6/types.h>
+#include <android/hardware/radio/1.5/IRadio.h>
+#include <android/hardware/radio/1.5/IRadioResponse.h>
+#include <android/hardware/radio/1.5/IRadioIndication.h>
+#include <android/hardware/radio/1.5/types.h>
#include <android/hardware/radio/deprecated/1.0/IOemHook.h>
#include <hwbinder/IPCThreadState.h>
#include <hwbinder/ProcessState.h>
-#include <guest/hals/ril/reference-libril/ril.h>
+#include <guest/hals/ril/libril/ril.h>
#include <telephony/ril_mnc.h>
-#include <guest/hals/ril/reference-libril/ril_service.h>
+#include <guest/hals/ril/libril/ril_service.h>
#include <hidl/HidlTransportSupport.h>
#include <utils/SystemClock.h>
#include <inttypes.h>
@@ -50,12 +50,6 @@ using android::RequestInfo;
using android::requestToString;
using android::sp;
-using RegStateResultV1_6 = android::hardware::radio::V1_6::RegStateResult;
-using RegStateResultV1_5 = android::hardware::radio::V1_5::RegStateResult;
-using PhysicalChannelConfigV1_4 =
- android::hardware::radio::V1_4::PhysicalChannelConfig;
-using RadioTechnologyV1_4 = android::hardware::radio::V1_4::RadioTechnology;
-
#define BOOL_TO_INT(x) (x ? 1 : 0)
#define ATOI_NULL_HANDLED(x) (x ? atoi(x) : -1)
#define ATOI_NULL_HANDLED_DEF(x, defaultVal) (x ? atoi(x) : defaultVal)
@@ -78,18 +72,18 @@ constexpr bool kOemHookEnabled = true;
RIL_RadioFunctions *s_vendorFunctions = NULL;
static CommandInfo *s_commands;
-struct RadioImpl_1_6;
+struct RadioImpl_1_5;
struct OemHookImpl;
#if (SIM_COUNT >= 2)
-sp<RadioImpl_1_6> radioService[SIM_COUNT];
+sp<RadioImpl_1_5> radioService[SIM_COUNT];
sp<OemHookImpl> oemHookService[SIM_COUNT];
int64_t nitzTimeReceived[SIM_COUNT];
// counter used for synchronization. It is incremented every time response callbacks are updated.
volatile int32_t mCounterRadio[SIM_COUNT];
volatile int32_t mCounterOemHook[SIM_COUNT];
#else
-sp<RadioImpl_1_6> radioService[1];
+sp<RadioImpl_1_5> radioService[1];
sp<OemHookImpl> oemHookService[1];
int64_t nitzTimeReceived[1];
// counter used for synchronization. It is incremented every time response callbacks are updated.
@@ -122,38 +116,24 @@ void convertRilSignalStrengthToHal(void *response, size_t responseLen,
void convertRilDataCallToHal(RIL_Data_Call_Response_v11 *dcResponse,
SetupDataCallResult& dcResult);
-void convertRilSignalStrengthToHal_1_4(void *response, size_t responseLen,
- V1_4::SignalStrength& signalStrength);
-
void convertRilDataCallToHal(RIL_Data_Call_Response_v11 *dcResponse,
::android::hardware::radio::V1_4::SetupDataCallResult& dcResult);
void convertRilDataCallToHal(RIL_Data_Call_Response_v12 *dcResponse,
::android::hardware::radio::V1_5::SetupDataCallResult& dcResult);
-void convertRilDataCallToHal(RIL_Data_Call_Response_v12 *dcResponse,
- ::android::hardware::radio::V1_6::SetupDataCallResult& dcResult);
-
void convertRilDataCallListToHal(void *response, size_t responseLen,
hidl_vec<SetupDataCallResult>& dcResultList);
void convertRilCellInfoListToHal(void *response, size_t responseLen, hidl_vec<CellInfo>& records);
-void convertRilCellInfoListToHal_1_2(void *response, size_t responseLen, hidl_vec<V1_2::CellInfo>& records);
void populateResponseInfo(RadioResponseInfo& responseInfo, int serial, int responseType,
RIL_Errno e);
-void populateResponseInfo_1_6(
- ::android::hardware::radio::V1_6::RadioResponseInfo &responseInfo,
- int serial, int responseType, RIL_Errno e);
-
-struct RadioImpl_1_6 : public V1_6::IRadio {
+struct RadioImpl_1_5 : public V1_5::IRadio {
int32_t mSlotId;
- V1_1::CardPowerState mSimCardPowerState;
sp<IRadioResponse> mRadioResponse;
sp<IRadioIndication> mRadioIndication;
- sp<V1_1::IRadioResponse> mRadioResponseV1_1;
- sp<V1_1::IRadioIndication> mRadioIndicationV1_1;
sp<V1_2::IRadioResponse> mRadioResponseV1_2;
sp<V1_2::IRadioIndication> mRadioIndicationV1_2;
sp<V1_3::IRadioResponse> mRadioResponseV1_3;
@@ -162,8 +142,6 @@ struct RadioImpl_1_6 : public V1_6::IRadio {
sp<V1_4::IRadioIndication> mRadioIndicationV1_4;
sp<V1_5::IRadioResponse> mRadioResponseV1_5;
sp<V1_5::IRadioIndication> mRadioIndicationV1_5;
- sp<V1_6::IRadioResponse> mRadioResponseV1_6;
- sp<V1_6::IRadioIndication> mRadioIndicationV1_6;
Return<void> setResponseFunctions(
const ::android::sp<IRadioResponse>& radioResponse,
@@ -194,8 +172,6 @@ struct RadioImpl_1_6 : public V1_6::IRadio {
Return<void> getCurrentCalls(int32_t serial);
- Return<void> getCurrentCalls_1_6(int32_t serial);
-
Return<void> dial(int32_t serial, const Dial& dialInfo);
Return<void> getImsiForApp(int32_t serial,
@@ -217,8 +193,6 @@ struct RadioImpl_1_6 : public V1_6::IRadio {
Return<void> getSignalStrength(int32_t serial);
- Return<void> getSignalStrength_1_6(int32_t serial);
-
Return<void> getVoiceRegistrationState(int32_t serial);
Return<void> getDataRegistrationState(int32_t serial);
@@ -425,8 +399,6 @@ struct RadioImpl_1_6 : public V1_6::IRadio {
Return<void> getCellInfoList(int32_t serial);
- Return<void> getCellInfoList_1_6(int32_t serial);
-
Return<void> setCellInfoListRate(int32_t serial, int32_t rate);
Return<void> setInitialAttachApn(int32_t serial, const DataProfileInfo& dataProfileInfo,
@@ -499,8 +471,6 @@ struct RadioImpl_1_6 : public V1_6::IRadio {
Return<void> setSimCardPower(int32_t serial, bool powerUp);
Return<void> setSimCardPower_1_1(int32_t serial,
const V1_1::CardPowerState state);
- Return<void> setSimCardPower_1_6(int32_t serial,
- const V1_1::CardPowerState state);
Return<void> responseAcknowledgement();
@@ -553,12 +523,6 @@ struct RadioImpl_1_6 : public V1_6::IRadio {
const hidl_vec<hidl_string>& urns,
::android::hardware::radio::V1_4::EmergencyCallRouting routing,
bool fromEmergencyDialer, bool isTesting);
- Return<void> emergencyDial_1_6(int32_t serial,
- const ::android::hardware::radio::V1_0::Dial& dialInfo,
- hidl_bitfield<android::hardware::radio::V1_4::EmergencyServiceCategory> categories,
- const hidl_vec<hidl_string>& urns,
- ::android::hardware::radio::V1_4::EmergencyCallRouting routing,
- bool fromEmergencyDialer, bool isTesting);
Return<void> startNetworkScan_1_4(int32_t serial,
const ::android::hardware::radio::V1_2::NetworkScanRequest& request);
Return<void> getPreferredNetworkTypeBitmap(int32_t serial);
@@ -607,50 +571,6 @@ struct RadioImpl_1_6 : public V1_6::IRadio {
Return<void> sendCdmaSmsExpectMore(int32_t serial, const CdmaSmsMessage& sms);
Return<void> supplySimDepersonalization(int32_t serial, V1_5::PersoSubstate persoType,
const hidl_string& controlKey);
- Return<void> setNrDualConnectivityState(int32_t serial,
- V1_6::NrDualConnectivityState nrDualConnectivityState);
- Return<void> isNrDualConnectivityEnabled(int32_t serial);
-
- // Methods from ::android::hardware::radio::V1_6::IRadio follow.
- Return<void> getDataCallList_1_6(int32_t serial);
- Return<void> setupDataCall_1_6(int32_t serial,
- ::android::hardware::radio::V1_5::AccessNetwork accessNetwork,
- const ::android::hardware::radio::V1_5::DataProfileInfo& dataProfileInfo,
- bool roamingAllowed, ::android::hardware::radio::V1_2::DataRequestReason reason,
- const hidl_vec<::android::hardware::radio::V1_5::LinkAddress>& addresses,
- const hidl_vec<hidl_string>& dnses,
- int32_t pduSessionId,
- const ::android::hardware::radio::V1_6::OptionalSliceInfo& sliceInfo,
- const ::android::hardware::radio::V1_6::OptionalTrafficDescriptor& trafficDescriptor,
- bool matchAllRuleAllowed);
- Return<void> sendSms_1_6(int32_t serial, const GsmSmsMessage& message);
- Return<void> sendSmsExpectMore_1_6(int32_t serial, const GsmSmsMessage& message);
- Return<void> sendCdmaSms_1_6(int32_t serial, const CdmaSmsMessage& sms);
- Return<void> sendCdmaSmsExpectMore_1_6(int32_t serial, const CdmaSmsMessage& sms);
- Return<void> setRadioPower_1_6(int32_t serial, bool powerOn, bool forEmergencyCall,
- bool preferredForEmergencyCall);
- Return<void> allocatePduSessionId(int32_t serial);
- Return<void> releasePduSessionId(int32_t serial, int32_t id);
- Return<void> startHandover(int32_t serial, int32_t callId);
- Return<void> cancelHandover(int32_t serial, int32_t callId);
- Return<void> setAllowedNetworkTypesBitmap(uint32_t serial,
- hidl_bitfield<::android::hardware::radio::V1_4::RadioAccessFamily> networkTypeBitmap);
- Return<void> setDataThrottling(int32_t serial,
- V1_6::DataThrottlingAction dataThrottlingAction,
- int64_t completionDurationMillis);
- Return<void> getSystemSelectionChannels(int32_t serial);
- Return<void> getVoiceRegistrationState_1_6(int32_t serial);
- Return<void> getDataRegistrationState_1_6(int32_t serial);
- Return<void> getAllowedNetworkTypesBitmap(int32_t serial);
- Return<void> getSlicingConfig(int32_t serial);
- Return<void> setCarrierInfoForImsiEncryption_1_6(
- int32_t serial,
- const ::android::hardware::radio::V1_6::ImsiEncryptionInfo& imsiEncryptionInfo);
- Return<void> getSimPhonebookRecords(int32_t serial);
- Return<void> getSimPhonebookCapacity(int32_t serial);
- Return<void> updateSimPhonebookRecords(
- int32_t serial,
- const ::android::hardware::radio::V1_6::PhonebookRecordInfo& recordInfo);
};
struct OemHookImpl : public IOemHook {
@@ -951,7 +871,7 @@ void checkReturnStatus(int32_t slotId, Return<void>& ret, bool isRadioService) {
// note the current counter to avoid overwriting updates made by another thread before
// write lock is acquired.
int counter = isRadioService ? mCounterRadio[slotId] : mCounterOemHook[slotId];
- pthread_rwlock_t *radioServiceRwlockPtr = radio_1_6::getRadioServiceRwlock(slotId);
+ pthread_rwlock_t *radioServiceRwlockPtr = radio_1_5::getRadioServiceRwlock(slotId);
int ret = pthread_rwlock_unlock(radioServiceRwlockPtr);
assert(ret == 0);
@@ -972,8 +892,6 @@ void checkReturnStatus(int32_t slotId, Return<void>& ret, bool isRadioService) {
radioService[slotId]->mRadioIndicationV1_4 = NULL;
radioService[slotId]->mRadioResponseV1_5 = NULL;
radioService[slotId]->mRadioIndicationV1_5 = NULL;
- radioService[slotId]->mRadioResponseV1_6 = NULL;
- radioService[slotId]->mRadioIndicationV1_6 = NULL;
} else {
oemHookService[slotId]->mOemHookResponse = NULL;
oemHookService[slotId]->mOemHookIndication = NULL;
@@ -994,29 +912,22 @@ void checkReturnStatus(int32_t slotId, Return<void>& ret, bool isRadioService) {
}
}
-void RadioImpl_1_6::checkReturnStatus(Return<void>& ret) {
+void RadioImpl_1_5::checkReturnStatus(Return<void>& ret) {
::checkReturnStatus(mSlotId, ret, true);
}
-Return<void> RadioImpl_1_6::setResponseFunctions(
+Return<void> RadioImpl_1_5::setResponseFunctions(
const ::android::sp<IRadioResponse>& radioResponseParam,
const ::android::sp<IRadioIndication>& radioIndicationParam) {
RLOGD("setResponseFunctions");
- pthread_rwlock_t *radioServiceRwlockPtr = radio_1_6::getRadioServiceRwlock(mSlotId);
+ pthread_rwlock_t *radioServiceRwlockPtr = radio_1_5::getRadioServiceRwlock(mSlotId);
int ret = pthread_rwlock_wrlock(radioServiceRwlockPtr);
assert(ret == 0);
mRadioResponse = radioResponseParam;
mRadioIndication = radioIndicationParam;
- mRadioResponseV1_6 = V1_6::IRadioResponse::castFrom(mRadioResponse).withDefault(nullptr);
- mRadioIndicationV1_6 = V1_6::IRadioIndication::castFrom(mRadioIndication).withDefault(nullptr);
- if (mRadioResponseV1_6 == nullptr || mRadioIndicationV1_6 == nullptr) {
- mRadioResponseV1_6 = nullptr;
- mRadioIndicationV1_6 = nullptr;
- }
-
mRadioResponseV1_5 = V1_5::IRadioResponse::castFrom(mRadioResponse).withDefault(nullptr);
mRadioIndicationV1_5 = V1_5::IRadioIndication::castFrom(mRadioIndication).withDefault(nullptr);
if (mRadioResponseV1_5 == nullptr || mRadioIndicationV1_5 == nullptr) {
@@ -1045,13 +956,6 @@ Return<void> RadioImpl_1_6::setResponseFunctions(
mRadioIndicationV1_2 = nullptr;
}
- mRadioResponseV1_1 = V1_1::IRadioResponse::castFrom(mRadioResponse).withDefault(nullptr);
- mRadioIndicationV1_1 = V1_1::IRadioIndication::castFrom(mRadioIndication).withDefault(nullptr);
- if (mRadioResponseV1_1 == nullptr || mRadioIndicationV1_1 == nullptr) {
- mRadioResponseV1_1 = nullptr;
- mRadioIndicationV1_1 = nullptr;
- }
-
mCounterRadio[mSlotId]++;
ret = pthread_rwlock_unlock(radioServiceRwlockPtr);
@@ -1063,7 +967,7 @@ Return<void> RadioImpl_1_6::setResponseFunctions(
return Void();
}
-Return<void> RadioImpl_1_6::getIccCardStatus(int32_t serial) {
+Return<void> RadioImpl_1_5::getIccCardStatus(int32_t serial) {
#if VDBG
RLOGD("getIccCardStatus: serial %d", serial);
#endif
@@ -1071,7 +975,7 @@ Return<void> RadioImpl_1_6::getIccCardStatus(int32_t serial) {
return Void();
}
-Return<void> RadioImpl_1_6::supplyIccPinForApp(int32_t serial, const hidl_string& pin,
+Return<void> RadioImpl_1_5::supplyIccPinForApp(int32_t serial, const hidl_string& pin,
const hidl_string& aid) {
#if VDBG
RLOGD("supplyIccPinForApp: serial %d", serial);
@@ -1081,7 +985,7 @@ Return<void> RadioImpl_1_6::supplyIccPinForApp(int32_t serial, const hidl_string
return Void();
}
-Return<void> RadioImpl_1_6::supplyIccPukForApp(int32_t serial, const hidl_string& puk,
+Return<void> RadioImpl_1_5::supplyIccPukForApp(int32_t serial, const hidl_string& puk,
const hidl_string& pin, const hidl_string& aid) {
#if VDBG
RLOGD("supplyIccPukForApp: serial %d", serial);
@@ -1091,7 +995,7 @@ Return<void> RadioImpl_1_6::supplyIccPukForApp(int32_t serial, const hidl_string
return Void();
}
-Return<void> RadioImpl_1_6::supplyIccPin2ForApp(int32_t serial, const hidl_string& pin2,
+Return<void> RadioImpl_1_5::supplyIccPin2ForApp(int32_t serial, const hidl_string& pin2,
const hidl_string& aid) {
#if VDBG
RLOGD("supplyIccPin2ForApp: serial %d", serial);
@@ -1101,7 +1005,7 @@ Return<void> RadioImpl_1_6::supplyIccPin2ForApp(int32_t serial, const hidl_strin
return Void();
}
-Return<void> RadioImpl_1_6::supplyIccPuk2ForApp(int32_t serial, const hidl_string& puk2,
+Return<void> RadioImpl_1_5::supplyIccPuk2ForApp(int32_t serial, const hidl_string& puk2,
const hidl_string& pin2, const hidl_string& aid) {
#if VDBG
RLOGD("supplyIccPuk2ForApp: serial %d", serial);
@@ -1111,7 +1015,7 @@ Return<void> RadioImpl_1_6::supplyIccPuk2ForApp(int32_t serial, const hidl_strin
return Void();
}
-Return<void> RadioImpl_1_6::changeIccPinForApp(int32_t serial, const hidl_string& oldPin,
+Return<void> RadioImpl_1_5::changeIccPinForApp(int32_t serial, const hidl_string& oldPin,
const hidl_string& newPin, const hidl_string& aid) {
#if VDBG
RLOGD("changeIccPinForApp: serial %d", serial);
@@ -1121,7 +1025,7 @@ Return<void> RadioImpl_1_6::changeIccPinForApp(int32_t serial, const hidl_string
return Void();
}
-Return<void> RadioImpl_1_6::changeIccPin2ForApp(int32_t serial, const hidl_string& oldPin2,
+Return<void> RadioImpl_1_5::changeIccPin2ForApp(int32_t serial, const hidl_string& oldPin2,
const hidl_string& newPin2, const hidl_string& aid) {
#if VDBG
RLOGD("changeIccPin2ForApp: serial %d", serial);
@@ -1131,7 +1035,7 @@ Return<void> RadioImpl_1_6::changeIccPin2ForApp(int32_t serial, const hidl_strin
return Void();
}
-Return<void> RadioImpl_1_6::supplyNetworkDepersonalization(int32_t serial,
+Return<void> RadioImpl_1_5::supplyNetworkDepersonalization(int32_t serial,
const hidl_string& netPin) {
#if VDBG
RLOGD("supplyNetworkDepersonalization: serial %d", serial);
@@ -1141,7 +1045,7 @@ Return<void> RadioImpl_1_6::supplyNetworkDepersonalization(int32_t serial,
return Void();
}
-Return<void> RadioImpl_1_6::getCurrentCalls(int32_t serial) {
+Return<void> RadioImpl_1_5::getCurrentCalls(int32_t serial) {
#if VDBG
RLOGD("getCurrentCalls: serial %d", serial);
#endif
@@ -1149,15 +1053,7 @@ Return<void> RadioImpl_1_6::getCurrentCalls(int32_t serial) {
return Void();
}
-Return<void> RadioImpl_1_6::getCurrentCalls_1_6(int32_t serial) {
-#if VDBG
- RLOGD("getCurrentCalls_1_6: serial %d", serial);
-#endif
- dispatchVoid(serial, mSlotId, RIL_REQUEST_GET_CURRENT_CALLS);
- return Void();
-}
-
-Return<void> RadioImpl_1_6::dial(int32_t serial, const Dial& dialInfo) {
+Return<void> RadioImpl_1_5::dial(int32_t serial, const Dial& dialInfo) {
#if VDBG
RLOGD("dial: serial %d", serial);
#endif
@@ -1199,7 +1095,7 @@ Return<void> RadioImpl_1_6::dial(int32_t serial, const Dial& dialInfo) {
return Void();
}
-Return<void> RadioImpl_1_6::getImsiForApp(int32_t serial, const hidl_string& aid) {
+Return<void> RadioImpl_1_5::getImsiForApp(int32_t serial, const hidl_string& aid) {
#if VDBG
RLOGD("getImsiForApp: serial %d", serial);
#endif
@@ -1208,7 +1104,7 @@ Return<void> RadioImpl_1_6::getImsiForApp(int32_t serial, const hidl_string& aid
return Void();
}
-Return<void> RadioImpl_1_6::hangup(int32_t serial, int32_t gsmIndex) {
+Return<void> RadioImpl_1_5::hangup(int32_t serial, int32_t gsmIndex) {
#if VDBG
RLOGD("hangup: serial %d", serial);
#endif
@@ -1216,7 +1112,7 @@ Return<void> RadioImpl_1_6::hangup(int32_t serial, int32_t gsmIndex) {
return Void();
}
-Return<void> RadioImpl_1_6::hangupWaitingOrBackground(int32_t serial) {
+Return<void> RadioImpl_1_5::hangupWaitingOrBackground(int32_t serial) {
#if VDBG
RLOGD("hangupWaitingOrBackground: serial %d", serial);
#endif
@@ -1224,7 +1120,7 @@ Return<void> RadioImpl_1_6::hangupWaitingOrBackground(int32_t serial) {
return Void();
}
-Return<void> RadioImpl_1_6::hangupForegroundResumeBackground(int32_t serial) {
+Return<void> RadioImpl_1_5::hangupForegroundResumeBackground(int32_t serial) {
#if VDBG
RLOGD("hangupForegroundResumeBackground: serial %d", serial);
#endif
@@ -1232,7 +1128,7 @@ Return<void> RadioImpl_1_6::hangupForegroundResumeBackground(int32_t serial) {
return Void();
}
-Return<void> RadioImpl_1_6::switchWaitingOrHoldingAndActive(int32_t serial) {
+Return<void> RadioImpl_1_5::switchWaitingOrHoldingAndActive(int32_t serial) {
#if VDBG
RLOGD("switchWaitingOrHoldingAndActive: serial %d", serial);
#endif
@@ -1240,7 +1136,7 @@ Return<void> RadioImpl_1_6::switchWaitingOrHoldingAndActive(int32_t serial) {
return Void();
}
-Return<void> RadioImpl_1_6::conference(int32_t serial) {
+Return<void> RadioImpl_1_5::conference(int32_t serial) {
#if VDBG
RLOGD("conference: serial %d", serial);
#endif
@@ -1248,7 +1144,7 @@ Return<void> RadioImpl_1_6::conference(int32_t serial) {
return Void();
}
-Return<void> RadioImpl_1_6::rejectCall(int32_t serial) {
+Return<void> RadioImpl_1_5::rejectCall(int32_t serial) {
#if VDBG
RLOGD("rejectCall: serial %d", serial);
#endif
@@ -1256,7 +1152,7 @@ Return<void> RadioImpl_1_6::rejectCall(int32_t serial) {
return Void();
}
-Return<void> RadioImpl_1_6::getLastCallFailCause(int32_t serial) {
+Return<void> RadioImpl_1_5::getLastCallFailCause(int32_t serial) {
#if VDBG
RLOGD("getLastCallFailCause: serial %d", serial);
#endif
@@ -1264,7 +1160,7 @@ Return<void> RadioImpl_1_6::getLastCallFailCause(int32_t serial) {
return Void();
}
-Return<void> RadioImpl_1_6::getSignalStrength(int32_t serial) {
+Return<void> RadioImpl_1_5::getSignalStrength(int32_t serial) {
#if VDBG
RLOGD("getSignalStrength: serial %d", serial);
#endif
@@ -1272,7 +1168,7 @@ Return<void> RadioImpl_1_6::getSignalStrength(int32_t serial) {
return Void();
}
-Return<void> RadioImpl_1_6::getVoiceRegistrationState(int32_t serial) {
+Return<void> RadioImpl_1_5::getVoiceRegistrationState(int32_t serial) {
#if VDBG
RLOGD("getVoiceRegistrationState: serial %d", serial);
#endif
@@ -1280,7 +1176,7 @@ Return<void> RadioImpl_1_6::getVoiceRegistrationState(int32_t serial) {
return Void();
}
-Return<void> RadioImpl_1_6::getDataRegistrationState(int32_t serial) {
+Return<void> RadioImpl_1_5::getDataRegistrationState(int32_t serial) {
#if VDBG
RLOGD("getDataRegistrationState: serial %d", serial);
#endif
@@ -1288,7 +1184,7 @@ Return<void> RadioImpl_1_6::getDataRegistrationState(int32_t serial) {
return Void();
}
-Return<void> RadioImpl_1_6::getOperator(int32_t serial) {
+Return<void> RadioImpl_1_5::getOperator(int32_t serial) {
#if VDBG
RLOGD("getOperator: serial %d", serial);
#endif
@@ -1296,7 +1192,7 @@ Return<void> RadioImpl_1_6::getOperator(int32_t serial) {
return Void();
}
-Return<void> RadioImpl_1_6::setRadioPower(int32_t serial, bool on) {
+Return<void> RadioImpl_1_5::setRadioPower(int32_t serial, bool on) {
#if VDBG
RLOGD("setRadioPower: serial %d on %d", serial, on);
#endif
@@ -1304,7 +1200,7 @@ Return<void> RadioImpl_1_6::setRadioPower(int32_t serial, bool on) {
return Void();
}
-Return<void> RadioImpl_1_6::sendDtmf(int32_t serial, const hidl_string& s) {
+Return<void> RadioImpl_1_5::sendDtmf(int32_t serial, const hidl_string& s) {
#if VDBG
RLOGD("sendDtmf: serial %d", serial);
#endif
@@ -1312,7 +1208,7 @@ Return<void> RadioImpl_1_6::sendDtmf(int32_t serial, const hidl_string& s) {
return Void();
}
-Return<void> RadioImpl_1_6::sendSms(int32_t serial, const GsmSmsMessage& message) {
+Return<void> RadioImpl_1_5::sendSms(int32_t serial, const GsmSmsMessage& message) {
#if VDBG
RLOGD("sendSms: serial %d", serial);
#endif
@@ -1321,27 +1217,9 @@ Return<void> RadioImpl_1_6::sendSms(int32_t serial, const GsmSmsMessage& message
return Void();
}
-Return<void> RadioImpl_1_6::sendSms_1_6(int32_t serial, const GsmSmsMessage& message) {
+Return<void> RadioImpl_1_5::sendSMSExpectMore(int32_t serial, const GsmSmsMessage& message) {
#if VDBG
- RLOGD("sendSms: serial %d", serial);
-#endif
- dispatchStrings(serial, mSlotId, RIL_REQUEST_SEND_SMS, false,
- 2, message.smscPdu.c_str(), message.pdu.c_str());
- return Void();
-}
-
-Return<void> RadioImpl_1_6::sendSMSExpectMore(int32_t serial, const GsmSmsMessage& message) {
-#if VDBG
- RLOGD("sendSmsExpectMore: serial %d", serial);
-#endif
- dispatchStrings(serial, mSlotId, RIL_REQUEST_SEND_SMS_EXPECT_MORE, false,
- 2, message.smscPdu.c_str(), message.pdu.c_str());
- return Void();
-}
-
-Return<void> RadioImpl_1_6::sendSmsExpectMore_1_6(int32_t serial, const GsmSmsMessage& message) {
-#if VDBG
- RLOGD("sendSmsExpectMore: serial %d", serial);
+ RLOGD("sendSMSExpectMore: serial %d", serial);
#endif
dispatchStrings(serial, mSlotId, RIL_REQUEST_SEND_SMS_EXPECT_MORE, false,
2, message.smscPdu.c_str(), message.pdu.c_str());
@@ -1366,7 +1244,7 @@ static bool convertMvnoTypeToString(MvnoType type, char *&str) {
return false;
}
-Return<void> RadioImpl_1_6::setupDataCall(int32_t serial, RadioTechnology radioTechnology,
+Return<void> RadioImpl_1_5::setupDataCall(int32_t serial, RadioTechnology radioTechnology,
const DataProfileInfo& dataProfileInfo, bool modemCognitive,
bool roamingAllowed, bool isRoaming) {
@@ -1385,7 +1263,7 @@ Return<void> RadioImpl_1_6::setupDataCall(int32_t serial, RadioTechnology radioT
dataProfileInfo.password.c_str(),
std::to_string((int) dataProfileInfo.authType).c_str(),
protocol.c_str());
- } else if (s_vendorFunctions->version == 15) {
+ } else if (s_vendorFunctions->version >= 15) {
char *mvnoTypeStr = NULL;
if (!convertMvnoTypeToString(dataProfileInfo.mvnoType, mvnoTypeStr)) {
RequestInfo *pRI = android::addRequestToList(serial, mSlotId,
@@ -1411,34 +1289,6 @@ Return<void> RadioImpl_1_6::setupDataCall(int32_t serial, RadioTechnology radioT
mvnoTypeStr,
dataProfileInfo.mvnoMatchData.c_str(),
roamingAllowed ? "1" : "0");
- } else if (s_vendorFunctions->version >= 16) {
- char *mvnoTypeStr = NULL;
- if (!convertMvnoTypeToString(dataProfileInfo.mvnoType, mvnoTypeStr)) {
- RequestInfo *pRI = android::addRequestToList(serial, mSlotId,
- RIL_REQUEST_SETUP_DATA_CALL);
- if (pRI != NULL) {
- sendErrorResponse(pRI, RIL_E_INVALID_ARGUMENTS);
- }
- return Void();
- }
- dispatchStrings(serial, mSlotId, RIL_REQUEST_SETUP_DATA_CALL, true, 16,
- std::to_string((int) radioTechnology + 2).c_str(),
- std::to_string((int) dataProfileInfo.profileId).c_str(),
- dataProfileInfo.apn.c_str(),
- dataProfileInfo.user.c_str(),
- dataProfileInfo.password.c_str(),
- std::to_string((int) dataProfileInfo.authType).c_str(),
- dataProfileInfo.protocol.c_str(),
- dataProfileInfo.roamingProtocol.c_str(),
- std::to_string(dataProfileInfo.supportedApnTypesBitmap).c_str(),
- std::to_string(dataProfileInfo.bearerBitmap).c_str(),
- modemCognitive ? "1" : "0",
- std::to_string(dataProfileInfo.mtu).c_str(),
- mvnoTypeStr,
- dataProfileInfo.mvnoMatchData.c_str(),
- roamingAllowed ? "1" : "0",
- "-1",
- "");
} else {
RLOGE("Unsupported RIL version %d, min version expected 4", s_vendorFunctions->version);
RequestInfo *pRI = android::addRequestToList(serial, mSlotId,
@@ -1450,7 +1300,7 @@ Return<void> RadioImpl_1_6::setupDataCall(int32_t serial, RadioTechnology radioT
return Void();
}
-Return<void> RadioImpl_1_6::iccIOForApp(int32_t serial, const IccIo& iccIo) {
+Return<void> RadioImpl_1_5::iccIOForApp(int32_t serial, const IccIo& iccIo) {
#if VDBG
RLOGD("iccIOForApp: serial %d", serial);
#endif
@@ -1492,7 +1342,7 @@ Return<void> RadioImpl_1_6::iccIOForApp(int32_t serial, const IccIo& iccIo) {
return Void();
}
-Return<void> RadioImpl_1_6::sendUssd(int32_t serial, const hidl_string& ussd) {
+Return<void> RadioImpl_1_5::sendUssd(int32_t serial, const hidl_string& ussd) {
#if VDBG
RLOGD("sendUssd: serial %d", serial);
#endif
@@ -1500,7 +1350,7 @@ Return<void> RadioImpl_1_6::sendUssd(int32_t serial, const hidl_string& ussd) {
return Void();
}
-Return<void> RadioImpl_1_6::cancelPendingUssd(int32_t serial) {
+Return<void> RadioImpl_1_5::cancelPendingUssd(int32_t serial) {
#if VDBG
RLOGD("cancelPendingUssd: serial %d", serial);
#endif
@@ -1508,7 +1358,7 @@ Return<void> RadioImpl_1_6::cancelPendingUssd(int32_t serial) {
return Void();
}
-Return<void> RadioImpl_1_6::getClir(int32_t serial) {
+Return<void> RadioImpl_1_5::getClir(int32_t serial) {
#if VDBG
RLOGD("getClir: serial %d", serial);
#endif
@@ -1516,7 +1366,7 @@ Return<void> RadioImpl_1_6::getClir(int32_t serial) {
return Void();
}
-Return<void> RadioImpl_1_6::setClir(int32_t serial, int32_t status) {
+Return<void> RadioImpl_1_5::setClir(int32_t serial, int32_t status) {
#if VDBG
RLOGD("setClir: serial %d", serial);
#endif
@@ -1524,7 +1374,7 @@ Return<void> RadioImpl_1_6::setClir(int32_t serial, int32_t status) {
return Void();
}
-Return<void> RadioImpl_1_6::getCallForwardStatus(int32_t serial, const CallForwardInfo& callInfo) {
+Return<void> RadioImpl_1_5::getCallForwardStatus(int32_t serial, const CallForwardInfo& callInfo) {
#if VDBG
RLOGD("getCallForwardStatus: serial %d", serial);
#endif
@@ -1533,7 +1383,7 @@ Return<void> RadioImpl_1_6::getCallForwardStatus(int32_t serial, const CallForwa
return Void();
}
-Return<void> RadioImpl_1_6::setCallForward(int32_t serial, const CallForwardInfo& callInfo) {
+Return<void> RadioImpl_1_5::setCallForward(int32_t serial, const CallForwardInfo& callInfo) {
#if VDBG
RLOGD("setCallForward: serial %d", serial);
#endif
@@ -1542,7 +1392,7 @@ Return<void> RadioImpl_1_6::setCallForward(int32_t serial, const CallForwardInfo
return Void();
}
-Return<void> RadioImpl_1_6::getCallWaiting(int32_t serial, int32_t serviceClass) {
+Return<void> RadioImpl_1_5::getCallWaiting(int32_t serial, int32_t serviceClass) {
#if VDBG
RLOGD("getCallWaiting: serial %d", serial);
#endif
@@ -1550,7 +1400,7 @@ Return<void> RadioImpl_1_6::getCallWaiting(int32_t serial, int32_t serviceClass)
return Void();
}
-Return<void> RadioImpl_1_6::setCallWaiting(int32_t serial, bool enable, int32_t serviceClass) {
+Return<void> RadioImpl_1_5::setCallWaiting(int32_t serial, bool enable, int32_t serviceClass) {
#if VDBG
RLOGD("setCallWaiting: serial %d", serial);
#endif
@@ -1559,7 +1409,7 @@ Return<void> RadioImpl_1_6::setCallWaiting(int32_t serial, bool enable, int32_t
return Void();
}
-Return<void> RadioImpl_1_6::acknowledgeLastIncomingGsmSms(int32_t serial,
+Return<void> RadioImpl_1_5::acknowledgeLastIncomingGsmSms(int32_t serial,
bool success, SmsAcknowledgeFailCause cause) {
#if VDBG
RLOGD("acknowledgeLastIncomingGsmSms: serial %d", serial);
@@ -1569,7 +1419,7 @@ Return<void> RadioImpl_1_6::acknowledgeLastIncomingGsmSms(int32_t serial,
return Void();
}
-Return<void> RadioImpl_1_6::acceptCall(int32_t serial) {
+Return<void> RadioImpl_1_5::acceptCall(int32_t serial) {
#if VDBG
RLOGD("acceptCall: serial %d", serial);
#endif
@@ -1577,7 +1427,7 @@ Return<void> RadioImpl_1_6::acceptCall(int32_t serial) {
return Void();
}
-Return<void> RadioImpl_1_6::deactivateDataCall(int32_t serial,
+Return<void> RadioImpl_1_5::deactivateDataCall(int32_t serial,
int32_t cid, bool reasonRadioShutDown) {
#if VDBG
RLOGD("deactivateDataCall: serial %d", serial);
@@ -1587,7 +1437,7 @@ Return<void> RadioImpl_1_6::deactivateDataCall(int32_t serial,
return Void();
}
-Return<void> RadioImpl_1_6::getFacilityLockForApp(int32_t serial, const hidl_string& facility,
+Return<void> RadioImpl_1_5::getFacilityLockForApp(int32_t serial, const hidl_string& facility,
const hidl_string& password, int32_t serviceClass,
const hidl_string& appId) {
#if VDBG
@@ -1599,7 +1449,7 @@ Return<void> RadioImpl_1_6::getFacilityLockForApp(int32_t serial, const hidl_str
return Void();
}
-Return<void> RadioImpl_1_6::setFacilityLockForApp(int32_t serial, const hidl_string& facility,
+Return<void> RadioImpl_1_5::setFacilityLockForApp(int32_t serial, const hidl_string& facility,
bool lockState, const hidl_string& password,
int32_t serviceClass, const hidl_string& appId) {
#if VDBG
@@ -1611,7 +1461,7 @@ Return<void> RadioImpl_1_6::setFacilityLockForApp(int32_t serial, const hidl_str
return Void();
}
-Return<void> RadioImpl_1_6::setBarringPassword(int32_t serial, const hidl_string& facility,
+Return<void> RadioImpl_1_5::setBarringPassword(int32_t serial, const hidl_string& facility,
const hidl_string& oldPassword,
const hidl_string& newPassword) {
#if VDBG
@@ -1622,7 +1472,7 @@ Return<void> RadioImpl_1_6::setBarringPassword(int32_t serial, const hidl_string
return Void();
}
-Return<void> RadioImpl_1_6::getNetworkSelectionMode(int32_t serial) {
+Return<void> RadioImpl_1_5::getNetworkSelectionMode(int32_t serial) {
#if VDBG
RLOGD("getNetworkSelectionMode: serial %d", serial);
#endif
@@ -1630,7 +1480,7 @@ Return<void> RadioImpl_1_6::getNetworkSelectionMode(int32_t serial) {
return Void();
}
-Return<void> RadioImpl_1_6::setNetworkSelectionModeAutomatic(int32_t serial) {
+Return<void> RadioImpl_1_5::setNetworkSelectionModeAutomatic(int32_t serial) {
#if VDBG
RLOGD("setNetworkSelectionModeAutomatic: serial %d", serial);
#endif
@@ -1638,30 +1488,17 @@ Return<void> RadioImpl_1_6::setNetworkSelectionModeAutomatic(int32_t serial) {
return Void();
}
-Return<void> RadioImpl_1_6::setNetworkSelectionModeManual(int32_t serial,
+Return<void> RadioImpl_1_5::setNetworkSelectionModeManual(int32_t serial,
const hidl_string& operatorNumeric) {
#if VDBG
RLOGD("setNetworkSelectionModeManual: serial %d", serial);
#endif
- RequestInfo *pRI = android::addRequestToList(serial, mSlotId,
- RIL_REQUEST_SET_NETWORK_SELECTION_MANUAL);
- if (pRI == NULL) {
- return Void();
- }
-
- RIL_NetworkOperator networkOperator = {};
-
- networkOperator.act = UNKNOWN;
- if (!copyHidlStringToRil(&networkOperator.operatorNumeric, operatorNumeric, pRI)) {
- return Void();
- }
- CALL_ONREQUEST(pRI->pCI->requestNumber, &networkOperator,
- sizeof(networkOperator), pRI, mSlotId);
-
+ dispatchString(serial, mSlotId, RIL_REQUEST_SET_NETWORK_SELECTION_MANUAL,
+ operatorNumeric.c_str());
return Void();
}
-Return<void> RadioImpl_1_6::getAvailableNetworks(int32_t serial) {
+Return<void> RadioImpl_1_5::getAvailableNetworks(int32_t serial) {
#if VDBG
RLOGD("getAvailableNetworks: serial %d", serial);
#endif
@@ -1669,7 +1506,7 @@ Return<void> RadioImpl_1_6::getAvailableNetworks(int32_t serial) {
return Void();
}
-Return<void> RadioImpl_1_6::startNetworkScan(int32_t serial, const V1_1::NetworkScanRequest& request) {
+Return<void> RadioImpl_1_5::startNetworkScan(int32_t serial, const V1_1::NetworkScanRequest& request) {
#if VDBG
RLOGD("startNetworkScan: serial %d", serial);
#endif
@@ -1735,7 +1572,7 @@ Return<void> RadioImpl_1_6::startNetworkScan(int32_t serial, const V1_1::Network
return Void();
}
-Return<void> RadioImpl_1_6::stopNetworkScan(int32_t serial) {
+Return<void> RadioImpl_1_5::stopNetworkScan(int32_t serial) {
#if VDBG
RLOGD("stopNetworkScan: serial %d", serial);
#endif
@@ -1743,7 +1580,7 @@ Return<void> RadioImpl_1_6::stopNetworkScan(int32_t serial) {
return Void();
}
-Return<void> RadioImpl_1_6::startDtmf(int32_t serial, const hidl_string& s) {
+Return<void> RadioImpl_1_5::startDtmf(int32_t serial, const hidl_string& s) {
#if VDBG
RLOGD("startDtmf: serial %d", serial);
#endif
@@ -1752,7 +1589,7 @@ Return<void> RadioImpl_1_6::startDtmf(int32_t serial, const hidl_string& s) {
return Void();
}
-Return<void> RadioImpl_1_6::stopDtmf(int32_t serial) {
+Return<void> RadioImpl_1_5::stopDtmf(int32_t serial) {
#if VDBG
RLOGD("stopDtmf: serial %d", serial);
#endif
@@ -1760,7 +1597,7 @@ Return<void> RadioImpl_1_6::stopDtmf(int32_t serial) {
return Void();
}
-Return<void> RadioImpl_1_6::getBasebandVersion(int32_t serial) {
+Return<void> RadioImpl_1_5::getBasebandVersion(int32_t serial) {
#if VDBG
RLOGD("getBasebandVersion: serial %d", serial);
#endif
@@ -1768,7 +1605,7 @@ Return<void> RadioImpl_1_6::getBasebandVersion(int32_t serial) {
return Void();
}
-Return<void> RadioImpl_1_6::separateConnection(int32_t serial, int32_t gsmIndex) {
+Return<void> RadioImpl_1_5::separateConnection(int32_t serial, int32_t gsmIndex) {
#if VDBG
RLOGD("separateConnection: serial %d", serial);
#endif
@@ -1776,7 +1613,7 @@ Return<void> RadioImpl_1_6::separateConnection(int32_t serial, int32_t gsmIndex)
return Void();
}
-Return<void> RadioImpl_1_6::setMute(int32_t serial, bool enable) {
+Return<void> RadioImpl_1_5::setMute(int32_t serial, bool enable) {
#if VDBG
RLOGD("setMute: serial %d", serial);
#endif
@@ -1784,7 +1621,7 @@ Return<void> RadioImpl_1_6::setMute(int32_t serial, bool enable) {
return Void();
}
-Return<void> RadioImpl_1_6::getMute(int32_t serial) {
+Return<void> RadioImpl_1_5::getMute(int32_t serial) {
#if VDBG
RLOGD("getMute: serial %d", serial);
#endif
@@ -1792,7 +1629,7 @@ Return<void> RadioImpl_1_6::getMute(int32_t serial) {
return Void();
}
-Return<void> RadioImpl_1_6::getClip(int32_t serial) {
+Return<void> RadioImpl_1_5::getClip(int32_t serial) {
#if VDBG
RLOGD("getClip: serial %d", serial);
#endif
@@ -1800,7 +1637,7 @@ Return<void> RadioImpl_1_6::getClip(int32_t serial) {
return Void();
}
-Return<void> RadioImpl_1_6::getDataCallList(int32_t serial) {
+Return<void> RadioImpl_1_5::getDataCallList(int32_t serial) {
#if VDBG
RLOGD("getDataCallList: serial %d", serial);
#endif
@@ -1808,96 +1645,7 @@ Return<void> RadioImpl_1_6::getDataCallList(int32_t serial) {
return Void();
}
-Return<void> RadioImpl_1_6::getDataCallList_1_6(int32_t serial) {
-#if VDBG
- RLOGD("getDataCallList_1_6: serial %d", serial);
-#endif
- dispatchVoid(serial, mSlotId, RIL_REQUEST_DATA_CALL_LIST);
- return Void();
-}
-
-Return<void> RadioImpl_1_6::emergencyDial_1_6(int32_t serial,
- const ::android::hardware::radio::V1_0::Dial& dialInfo,
- hidl_bitfield<android::hardware::radio::V1_4::EmergencyServiceCategory> categories,
- const hidl_vec<hidl_string>& urns ,
- ::android::hardware::radio::V1_4::EmergencyCallRouting routing,
- bool fromEmergencyDialer, bool /* isTesting */) {
-#if VDBG
- RLOGD("emergencyDial: serial %d", serial);
-#endif
-
- RequestInfo *pRI = android::addRequestToList(serial, mSlotId, RIL_REQUEST_EMERGENCY_DIAL);
- if (pRI == NULL) {
- return Void();
- }
-
- RIL_EmergencyDial eccDial = {};
- RIL_Dial& dial = eccDial.dialInfo;
- RIL_UUS_Info uusInfo = {};
-
- if (!copyHidlStringToRil(&dial.address, dialInfo.address, pRI)) {
- return Void();
- }
- dial.clir = (int) dialInfo.clir;
-
- if (dialInfo.uusInfo.size() != 0) {
- uusInfo.uusType = (RIL_UUS_Type) dialInfo.uusInfo[0].uusType;
- uusInfo.uusDcs = (RIL_UUS_DCS) dialInfo.uusInfo[0].uusDcs;
-
- if (dialInfo.uusInfo[0].uusData.size() == 0) {
- uusInfo.uusData = NULL;
- uusInfo.uusLength = 0;
- } else {
- if (!copyHidlStringToRil(&uusInfo.uusData, dialInfo.uusInfo[0].uusData, pRI)) {
- memsetAndFreeStrings(1, dial.address);
- return Void();
- }
- uusInfo.uusLength = dialInfo.uusInfo[0].uusData.size();
- }
-
- dial.uusInfo = &uusInfo;
- }
-
- eccDial.urnsNumber = urns.size();
- if (eccDial.urnsNumber != 0) {
- char **ppUrns = (char **)calloc(eccDial.urnsNumber, sizeof(char *));
- if (ppUrns == NULL) {
- RLOGE("Memory allocation failed for request %s",
- requestToString(pRI->pCI->requestNumber));
- sendErrorResponse(pRI, RIL_E_NO_MEMORY);
- memsetAndFreeStrings(2, dial.address, uusInfo.uusData);
- return Void();
- }
- for (uint32_t i = 0; i < eccDial.urnsNumber; i++) {
- if (!copyHidlStringToRil(&ppUrns[i], hidl_string(urns[i]), pRI)) {
- for (uint32_t j = 0; j < i; j++) {
- memsetAndFreeStrings(1, ppUrns[j]);
- }
- memsetAndFreeStrings(2, dial.address, uusInfo.uusData);
- free(ppUrns);
- return Void();
- }
- }
- eccDial.urns = ppUrns;
- }
-
- eccDial.categories = (RIL_EmergencyServiceCategory)categories;
- eccDial.routing = (RIL_EmergencyCallRouting)routing;
- eccDial.fromEmergencyDialer = fromEmergencyDialer;
-
- CALL_ONREQUEST(RIL_REQUEST_EMERGENCY_DIAL, &eccDial, sizeof(RIL_EmergencyDial), pRI, mSlotId);
-
- memsetAndFreeStrings(2, dial.address, uusInfo.uusData);
- if (eccDial.urns != NULL) {
- for (size_t i = 0; i < eccDial.urnsNumber; i++) {
- memsetAndFreeStrings(1, eccDial.urns[i]);
- }
- free(eccDial.urns);
- }
- return Void();
-}
-
-Return<void> RadioImpl_1_6::setSuppServiceNotifications(int32_t serial, bool enable) {
+Return<void> RadioImpl_1_5::setSuppServiceNotifications(int32_t serial, bool enable) {
#if VDBG
RLOGD("setSuppServiceNotifications: serial %d", serial);
#endif
@@ -1906,7 +1654,7 @@ Return<void> RadioImpl_1_6::setSuppServiceNotifications(int32_t serial, bool ena
return Void();
}
-Return<void> RadioImpl_1_6::writeSmsToSim(int32_t serial, const SmsWriteArgs& smsWriteArgs) {
+Return<void> RadioImpl_1_5::writeSmsToSim(int32_t serial, const SmsWriteArgs& smsWriteArgs) {
#if VDBG
RLOGD("writeSmsToSim: serial %d", serial);
#endif
@@ -1934,7 +1682,7 @@ Return<void> RadioImpl_1_6::writeSmsToSim(int32_t serial, const SmsWriteArgs& sm
return Void();
}
-Return<void> RadioImpl_1_6::deleteSmsOnSim(int32_t serial, int32_t index) {
+Return<void> RadioImpl_1_5::deleteSmsOnSim(int32_t serial, int32_t index) {
#if VDBG
RLOGD("deleteSmsOnSim: serial %d", serial);
#endif
@@ -1942,7 +1690,7 @@ Return<void> RadioImpl_1_6::deleteSmsOnSim(int32_t serial, int32_t index) {
return Void();
}
-Return<void> RadioImpl_1_6::setBandMode(int32_t serial, RadioBandMode mode) {
+Return<void> RadioImpl_1_5::setBandMode(int32_t serial, RadioBandMode mode) {
#if VDBG
RLOGD("setBandMode: serial %d", serial);
#endif
@@ -1950,7 +1698,7 @@ Return<void> RadioImpl_1_6::setBandMode(int32_t serial, RadioBandMode mode) {
return Void();
}
-Return<void> RadioImpl_1_6::getAvailableBandModes(int32_t serial) {
+Return<void> RadioImpl_1_5::getAvailableBandModes(int32_t serial) {
#if VDBG
RLOGD("getAvailableBandModes: serial %d", serial);
#endif
@@ -1958,7 +1706,7 @@ Return<void> RadioImpl_1_6::getAvailableBandModes(int32_t serial) {
return Void();
}
-Return<void> RadioImpl_1_6::sendEnvelope(int32_t serial, const hidl_string& command) {
+Return<void> RadioImpl_1_5::sendEnvelope(int32_t serial, const hidl_string& command) {
#if VDBG
RLOGD("sendEnvelope: serial %d", serial);
#endif
@@ -1967,7 +1715,7 @@ Return<void> RadioImpl_1_6::sendEnvelope(int32_t serial, const hidl_string& comm
return Void();
}
-Return<void> RadioImpl_1_6::sendTerminalResponseToSim(int32_t serial,
+Return<void> RadioImpl_1_5::sendTerminalResponseToSim(int32_t serial,
const hidl_string& commandResponse) {
#if VDBG
RLOGD("sendTerminalResponseToSim: serial %d", serial);
@@ -1977,7 +1725,7 @@ Return<void> RadioImpl_1_6::sendTerminalResponseToSim(int32_t serial,
return Void();
}
-Return<void> RadioImpl_1_6::handleStkCallSetupRequestFromSim(int32_t serial, bool accept) {
+Return<void> RadioImpl_1_5::handleStkCallSetupRequestFromSim(int32_t serial, bool accept) {
#if VDBG
RLOGD("handleStkCallSetupRequestFromSim: serial %d", serial);
#endif
@@ -1986,7 +1734,7 @@ Return<void> RadioImpl_1_6::handleStkCallSetupRequestFromSim(int32_t serial, boo
return Void();
}
-Return<void> RadioImpl_1_6::explicitCallTransfer(int32_t serial) {
+Return<void> RadioImpl_1_5::explicitCallTransfer(int32_t serial) {
#if VDBG
RLOGD("explicitCallTransfer: serial %d", serial);
#endif
@@ -1994,7 +1742,7 @@ Return<void> RadioImpl_1_6::explicitCallTransfer(int32_t serial) {
return Void();
}
-Return<void> RadioImpl_1_6::setPreferredNetworkType(int32_t serial, PreferredNetworkType nwType) {
+Return<void> RadioImpl_1_5::setPreferredNetworkType(int32_t serial, PreferredNetworkType nwType) {
#if VDBG
RLOGD("setPreferredNetworkType: serial %d", serial);
#endif
@@ -2002,7 +1750,7 @@ Return<void> RadioImpl_1_6::setPreferredNetworkType(int32_t serial, PreferredNet
return Void();
}
-Return<void> RadioImpl_1_6::getPreferredNetworkType(int32_t serial) {
+Return<void> RadioImpl_1_5::getPreferredNetworkType(int32_t serial) {
#if VDBG
RLOGD("getPreferredNetworkType: serial %d", serial);
#endif
@@ -2010,7 +1758,7 @@ Return<void> RadioImpl_1_6::getPreferredNetworkType(int32_t serial) {
return Void();
}
-Return<void> RadioImpl_1_6::getNeighboringCids(int32_t serial) {
+Return<void> RadioImpl_1_5::getNeighboringCids(int32_t serial) {
#if VDBG
RLOGD("getNeighboringCids: serial %d", serial);
#endif
@@ -2018,7 +1766,7 @@ Return<void> RadioImpl_1_6::getNeighboringCids(int32_t serial) {
return Void();
}
-Return<void> RadioImpl_1_6::setLocationUpdates(int32_t serial, bool enable) {
+Return<void> RadioImpl_1_5::setLocationUpdates(int32_t serial, bool enable) {
#if VDBG
RLOGD("setLocationUpdates: serial %d", serial);
#endif
@@ -2026,7 +1774,7 @@ Return<void> RadioImpl_1_6::setLocationUpdates(int32_t serial, bool enable) {
return Void();
}
-Return<void> RadioImpl_1_6::setCdmaSubscriptionSource(int32_t serial, CdmaSubscriptionSource cdmaSub) {
+Return<void> RadioImpl_1_5::setCdmaSubscriptionSource(int32_t serial, CdmaSubscriptionSource cdmaSub) {
#if VDBG
RLOGD("setCdmaSubscriptionSource: serial %d", serial);
#endif
@@ -2034,7 +1782,7 @@ Return<void> RadioImpl_1_6::setCdmaSubscriptionSource(int32_t serial, CdmaSubscr
return Void();
}
-Return<void> RadioImpl_1_6::setCdmaRoamingPreference(int32_t serial, CdmaRoamingType type) {
+Return<void> RadioImpl_1_5::setCdmaRoamingPreference(int32_t serial, CdmaRoamingType type) {
#if VDBG
RLOGD("setCdmaRoamingPreference: serial %d", serial);
#endif
@@ -2042,7 +1790,7 @@ Return<void> RadioImpl_1_6::setCdmaRoamingPreference(int32_t serial, CdmaRoaming
return Void();
}
-Return<void> RadioImpl_1_6::getCdmaRoamingPreference(int32_t serial) {
+Return<void> RadioImpl_1_5::getCdmaRoamingPreference(int32_t serial) {
#if VDBG
RLOGD("getCdmaRoamingPreference: serial %d", serial);
#endif
@@ -2050,7 +1798,7 @@ Return<void> RadioImpl_1_6::getCdmaRoamingPreference(int32_t serial) {
return Void();
}
-Return<void> RadioImpl_1_6::setTTYMode(int32_t serial, TtyMode mode) {
+Return<void> RadioImpl_1_5::setTTYMode(int32_t serial, TtyMode mode) {
#if VDBG
RLOGD("setTTYMode: serial %d", serial);
#endif
@@ -2058,7 +1806,7 @@ Return<void> RadioImpl_1_6::setTTYMode(int32_t serial, TtyMode mode) {
return Void();
}
-Return<void> RadioImpl_1_6::getTTYMode(int32_t serial) {
+Return<void> RadioImpl_1_5::getTTYMode(int32_t serial) {
#if VDBG
RLOGD("getTTYMode: serial %d", serial);
#endif
@@ -2066,7 +1814,7 @@ Return<void> RadioImpl_1_6::getTTYMode(int32_t serial) {
return Void();
}
-Return<void> RadioImpl_1_6::setPreferredVoicePrivacy(int32_t serial, bool enable) {
+Return<void> RadioImpl_1_5::setPreferredVoicePrivacy(int32_t serial, bool enable) {
#if VDBG
RLOGD("setPreferredVoicePrivacy: serial %d", serial);
#endif
@@ -2075,7 +1823,7 @@ Return<void> RadioImpl_1_6::setPreferredVoicePrivacy(int32_t serial, bool enable
return Void();
}
-Return<void> RadioImpl_1_6::getPreferredVoicePrivacy(int32_t serial) {
+Return<void> RadioImpl_1_5::getPreferredVoicePrivacy(int32_t serial) {
#if VDBG
RLOGD("getPreferredVoicePrivacy: serial %d", serial);
#endif
@@ -2083,7 +1831,7 @@ Return<void> RadioImpl_1_6::getPreferredVoicePrivacy(int32_t serial) {
return Void();
}
-Return<void> RadioImpl_1_6::sendCDMAFeatureCode(int32_t serial, const hidl_string& featureCode) {
+Return<void> RadioImpl_1_5::sendCDMAFeatureCode(int32_t serial, const hidl_string& featureCode) {
#if VDBG
RLOGD("sendCDMAFeatureCode: serial %d", serial);
#endif
@@ -2092,7 +1840,7 @@ Return<void> RadioImpl_1_6::sendCDMAFeatureCode(int32_t serial, const hidl_strin
return Void();
}
-Return<void> RadioImpl_1_6::sendBurstDtmf(int32_t serial, const hidl_string& dtmf, int32_t on,
+Return<void> RadioImpl_1_5::sendBurstDtmf(int32_t serial, const hidl_string& dtmf, int32_t on,
int32_t off) {
#if VDBG
RLOGD("sendBurstDtmf: serial %d", serial);
@@ -2134,7 +1882,7 @@ void constructCdmaSms(RIL_CDMA_SMS_Message &rcsm, const CdmaSmsMessage& sms) {
}
}
-Return<void> RadioImpl_1_6::sendCdmaSms(int32_t serial, const CdmaSmsMessage& sms) {
+Return<void> RadioImpl_1_5::sendCdmaSms(int32_t serial, const CdmaSmsMessage& sms) {
#if VDBG
RLOGD("sendCdmaSms: serial %d", serial);
#endif
@@ -2150,23 +1898,7 @@ Return<void> RadioImpl_1_6::sendCdmaSms(int32_t serial, const CdmaSmsMessage& sm
return Void();
}
-Return<void> RadioImpl_1_6::sendCdmaSms_1_6(int32_t serial, const CdmaSmsMessage& sms) {
-#if VDBG
- RLOGD("sendCdmaSms: serial %d", serial);
-#endif
- RequestInfo *pRI = android::addRequestToList(serial, mSlotId, RIL_REQUEST_CDMA_SEND_SMS);
- if (pRI == NULL) {
- return Void();
- }
-
- RIL_CDMA_SMS_Message rcsm = {};
- constructCdmaSms(rcsm, sms);
-
- CALL_ONREQUEST(pRI->pCI->requestNumber, &rcsm, sizeof(rcsm), pRI, mSlotId);
- return Void();
-}
-
-Return<void> RadioImpl_1_6::acknowledgeLastIncomingCdmaSms(int32_t serial, const CdmaSmsAck& smsAck) {
+Return<void> RadioImpl_1_5::acknowledgeLastIncomingCdmaSms(int32_t serial, const CdmaSmsAck& smsAck) {
#if VDBG
RLOGD("acknowledgeLastIncomingCdmaSms: serial %d", serial);
#endif
@@ -2184,7 +1916,7 @@ Return<void> RadioImpl_1_6::acknowledgeLastIncomingCdmaSms(int32_t serial, const
return Void();
}
-Return<void> RadioImpl_1_6::getGsmBroadcastConfig(int32_t serial) {
+Return<void> RadioImpl_1_5::getGsmBroadcastConfig(int32_t serial) {
#if VDBG
RLOGD("getGsmBroadcastConfig: serial %d", serial);
#endif
@@ -2192,7 +1924,7 @@ Return<void> RadioImpl_1_6::getGsmBroadcastConfig(int32_t serial) {
return Void();
}
-Return<void> RadioImpl_1_6::setGsmBroadcastConfig(int32_t serial,
+Return<void> RadioImpl_1_5::setGsmBroadcastConfig(int32_t serial,
const hidl_vec<GsmBroadcastSmsConfigInfo>&
configInfo) {
#if VDBG
@@ -2228,7 +1960,7 @@ Return<void> RadioImpl_1_6::setGsmBroadcastConfig(int32_t serial,
return Void();
}
-Return<void> RadioImpl_1_6::setGsmBroadcastActivation(int32_t serial, bool activate) {
+Return<void> RadioImpl_1_5::setGsmBroadcastActivation(int32_t serial, bool activate) {
#if VDBG
RLOGD("setGsmBroadcastActivation: serial %d", serial);
#endif
@@ -2237,7 +1969,7 @@ Return<void> RadioImpl_1_6::setGsmBroadcastActivation(int32_t serial, bool activ
return Void();
}
-Return<void> RadioImpl_1_6::getCdmaBroadcastConfig(int32_t serial) {
+Return<void> RadioImpl_1_5::getCdmaBroadcastConfig(int32_t serial) {
#if VDBG
RLOGD("getCdmaBroadcastConfig: serial %d", serial);
#endif
@@ -2245,7 +1977,7 @@ Return<void> RadioImpl_1_6::getCdmaBroadcastConfig(int32_t serial) {
return Void();
}
-Return<void> RadioImpl_1_6::setCdmaBroadcastConfig(int32_t serial,
+Return<void> RadioImpl_1_5::setCdmaBroadcastConfig(int32_t serial,
const hidl_vec<CdmaBroadcastSmsConfigInfo>&
configInfo) {
#if VDBG
@@ -2279,7 +2011,7 @@ Return<void> RadioImpl_1_6::setCdmaBroadcastConfig(int32_t serial,
return Void();
}
-Return<void> RadioImpl_1_6::setCdmaBroadcastActivation(int32_t serial, bool activate) {
+Return<void> RadioImpl_1_5::setCdmaBroadcastActivation(int32_t serial, bool activate) {
#if VDBG
RLOGD("setCdmaBroadcastActivation: serial %d", serial);
#endif
@@ -2288,7 +2020,7 @@ Return<void> RadioImpl_1_6::setCdmaBroadcastActivation(int32_t serial, bool acti
return Void();
}
-Return<void> RadioImpl_1_6::getCDMASubscription(int32_t serial) {
+Return<void> RadioImpl_1_5::getCDMASubscription(int32_t serial) {
#if VDBG
RLOGD("getCDMASubscription: serial %d", serial);
#endif
@@ -2296,7 +2028,7 @@ Return<void> RadioImpl_1_6::getCDMASubscription(int32_t serial) {
return Void();
}
-Return<void> RadioImpl_1_6::writeSmsToRuim(int32_t serial, const CdmaSmsWriteArgs& cdmaSms) {
+Return<void> RadioImpl_1_5::writeSmsToRuim(int32_t serial, const CdmaSmsWriteArgs& cdmaSms) {
#if VDBG
RLOGD("writeSmsToRuim: serial %d", serial);
#endif
@@ -2314,7 +2046,7 @@ Return<void> RadioImpl_1_6::writeSmsToRuim(int32_t serial, const CdmaSmsWriteArg
return Void();
}
-Return<void> RadioImpl_1_6::deleteSmsOnRuim(int32_t serial, int32_t index) {
+Return<void> RadioImpl_1_5::deleteSmsOnRuim(int32_t serial, int32_t index) {
#if VDBG
RLOGD("deleteSmsOnRuim: serial %d", serial);
#endif
@@ -2322,7 +2054,7 @@ Return<void> RadioImpl_1_6::deleteSmsOnRuim(int32_t serial, int32_t index) {
return Void();
}
-Return<void> RadioImpl_1_6::getDeviceIdentity(int32_t serial) {
+Return<void> RadioImpl_1_5::getDeviceIdentity(int32_t serial) {
#if VDBG
RLOGD("getDeviceIdentity: serial %d", serial);
#endif
@@ -2330,7 +2062,7 @@ Return<void> RadioImpl_1_6::getDeviceIdentity(int32_t serial) {
return Void();
}
-Return<void> RadioImpl_1_6::exitEmergencyCallbackMode(int32_t serial) {
+Return<void> RadioImpl_1_5::exitEmergencyCallbackMode(int32_t serial) {
#if VDBG
RLOGD("exitEmergencyCallbackMode: serial %d", serial);
#endif
@@ -2338,7 +2070,7 @@ Return<void> RadioImpl_1_6::exitEmergencyCallbackMode(int32_t serial) {
return Void();
}
-Return<void> RadioImpl_1_6::getSmscAddress(int32_t serial) {
+Return<void> RadioImpl_1_5::getSmscAddress(int32_t serial) {
#if VDBG
RLOGD("getSmscAddress: serial %d", serial);
#endif
@@ -2346,7 +2078,7 @@ Return<void> RadioImpl_1_6::getSmscAddress(int32_t serial) {
return Void();
}
-Return<void> RadioImpl_1_6::setSmscAddress(int32_t serial, const hidl_string& smsc) {
+Return<void> RadioImpl_1_5::setSmscAddress(int32_t serial, const hidl_string& smsc) {
#if VDBG
RLOGD("setSmscAddress: serial %d", serial);
#endif
@@ -2355,7 +2087,7 @@ Return<void> RadioImpl_1_6::setSmscAddress(int32_t serial, const hidl_string& sm
return Void();
}
-Return<void> RadioImpl_1_6::reportSmsMemoryStatus(int32_t serial, bool available) {
+Return<void> RadioImpl_1_5::reportSmsMemoryStatus(int32_t serial, bool available) {
#if VDBG
RLOGD("reportSmsMemoryStatus: serial %d", serial);
#endif
@@ -2364,7 +2096,7 @@ Return<void> RadioImpl_1_6::reportSmsMemoryStatus(int32_t serial, bool available
return Void();
}
-Return<void> RadioImpl_1_6::reportStkServiceIsRunning(int32_t serial) {
+Return<void> RadioImpl_1_5::reportStkServiceIsRunning(int32_t serial) {
#if VDBG
RLOGD("reportStkServiceIsRunning: serial %d", serial);
#endif
@@ -2372,7 +2104,7 @@ Return<void> RadioImpl_1_6::reportStkServiceIsRunning(int32_t serial) {
return Void();
}
-Return<void> RadioImpl_1_6::getCdmaSubscriptionSource(int32_t serial) {
+Return<void> RadioImpl_1_5::getCdmaSubscriptionSource(int32_t serial) {
#if VDBG
RLOGD("getCdmaSubscriptionSource: serial %d", serial);
#endif
@@ -2380,7 +2112,7 @@ Return<void> RadioImpl_1_6::getCdmaSubscriptionSource(int32_t serial) {
return Void();
}
-Return<void> RadioImpl_1_6::requestIsimAuthentication(int32_t serial, const hidl_string& challenge) {
+Return<void> RadioImpl_1_5::requestIsimAuthentication(int32_t serial, const hidl_string& challenge) {
#if VDBG
RLOGD("requestIsimAuthentication: serial %d", serial);
#endif
@@ -2389,7 +2121,7 @@ Return<void> RadioImpl_1_6::requestIsimAuthentication(int32_t serial, const hidl
return Void();
}
-Return<void> RadioImpl_1_6::acknowledgeIncomingGsmSmsWithPdu(int32_t serial, bool success,
+Return<void> RadioImpl_1_5::acknowledgeIncomingGsmSmsWithPdu(int32_t serial, bool success,
const hidl_string& ackPdu) {
#if VDBG
RLOGD("acknowledgeIncomingGsmSmsWithPdu: serial %d", serial);
@@ -2399,7 +2131,7 @@ Return<void> RadioImpl_1_6::acknowledgeIncomingGsmSmsWithPdu(int32_t serial, boo
return Void();
}
-Return<void> RadioImpl_1_6::sendEnvelopeWithStatus(int32_t serial, const hidl_string& contents) {
+Return<void> RadioImpl_1_5::sendEnvelopeWithStatus(int32_t serial, const hidl_string& contents) {
#if VDBG
RLOGD("sendEnvelopeWithStatus: serial %d", serial);
#endif
@@ -2408,7 +2140,7 @@ Return<void> RadioImpl_1_6::sendEnvelopeWithStatus(int32_t serial, const hidl_st
return Void();
}
-Return<void> RadioImpl_1_6::getVoiceRadioTechnology(int32_t serial) {
+Return<void> RadioImpl_1_5::getVoiceRadioTechnology(int32_t serial) {
#if VDBG
RLOGD("getVoiceRadioTechnology: serial %d", serial);
#endif
@@ -2416,7 +2148,7 @@ Return<void> RadioImpl_1_6::getVoiceRadioTechnology(int32_t serial) {
return Void();
}
-Return<void> RadioImpl_1_6::getCellInfoList(int32_t serial) {
+Return<void> RadioImpl_1_5::getCellInfoList(int32_t serial) {
#if VDBG
RLOGD("getCellInfoList: serial %d", serial);
#endif
@@ -2424,15 +2156,7 @@ Return<void> RadioImpl_1_6::getCellInfoList(int32_t serial) {
return Void();
}
-Return<void> RadioImpl_1_6::getCellInfoList_1_6(int32_t serial) {
-#if VDBG
- RLOGD("getCellInfoList_1_6: serial %d", serial);
-#endif
- dispatchVoid(serial, mSlotId, RIL_REQUEST_GET_CELL_INFO_LIST);
- return Void();
-}
-
-Return<void> RadioImpl_1_6::setCellInfoListRate(int32_t serial, int32_t rate) {
+Return<void> RadioImpl_1_5::setCellInfoListRate(int32_t serial, int32_t rate) {
#if VDBG
RLOGD("setCellInfoListRate: serial %d", serial);
#endif
@@ -2440,7 +2164,7 @@ Return<void> RadioImpl_1_6::setCellInfoListRate(int32_t serial, int32_t rate) {
return Void();
}
-Return<void> RadioImpl_1_6::setInitialAttachApn(int32_t serial, const DataProfileInfo& dataProfileInfo,
+Return<void> RadioImpl_1_5::setInitialAttachApn(int32_t serial, const DataProfileInfo& dataProfileInfo,
bool modemCognitive, bool isRoaming) {
#if VDBG
RLOGD("setInitialAttachApn: serial %d", serial);
@@ -2529,7 +2253,7 @@ Return<void> RadioImpl_1_6::setInitialAttachApn(int32_t serial, const DataProfil
return Void();
}
-Return<void> RadioImpl_1_6::getImsRegistrationState(int32_t serial) {
+Return<void> RadioImpl_1_5::getImsRegistrationState(int32_t serial) {
#if VDBG
RLOGD("getImsRegistrationState: serial %d", serial);
#endif
@@ -2626,7 +2350,7 @@ bool dispatchImsCdmaSms(const ImsSmsMessage& message, RequestInfo *pRI) {
return true;
}
-Return<void> RadioImpl_1_6::sendImsSms(int32_t serial, const ImsSmsMessage& message) {
+Return<void> RadioImpl_1_5::sendImsSms(int32_t serial, const ImsSmsMessage& message) {
#if VDBG
RLOGD("sendImsSms: serial %d", serial);
#endif
@@ -2649,7 +2373,7 @@ Return<void> RadioImpl_1_6::sendImsSms(int32_t serial, const ImsSmsMessage& mess
return Void();
}
-Return<void> RadioImpl_1_6::iccTransmitApduBasicChannel(int32_t serial, const SimApdu& message) {
+Return<void> RadioImpl_1_5::iccTransmitApduBasicChannel(int32_t serial, const SimApdu& message) {
#if VDBG
RLOGD("iccTransmitApduBasicChannel: serial %d", serial);
#endif
@@ -2657,30 +2381,34 @@ Return<void> RadioImpl_1_6::iccTransmitApduBasicChannel(int32_t serial, const Si
return Void();
}
-Return<void> RadioImpl_1_6::iccOpenLogicalChannel(int32_t serial, const hidl_string& aid, int32_t p2) {
+Return<void> RadioImpl_1_5::iccOpenLogicalChannel(int32_t serial, const hidl_string& aid, int32_t p2) {
#if VDBG
RLOGD("iccOpenLogicalChannel: serial %d", serial);
#endif
- RequestInfo *pRI = android::addRequestToList(serial, mSlotId, RIL_REQUEST_SIM_OPEN_CHANNEL);
- if (pRI == NULL) {
- return Void();
- }
+ if (s_vendorFunctions->version < 15) {
+ dispatchString(serial, mSlotId, RIL_REQUEST_SIM_OPEN_CHANNEL, aid.c_str());
+ } else {
+ RequestInfo *pRI = android::addRequestToList(serial, mSlotId, RIL_REQUEST_SIM_OPEN_CHANNEL);
+ if (pRI == NULL) {
+ return Void();
+ }
- RIL_OpenChannelParams params = {};
+ RIL_OpenChannelParams params = {};
- params.p2 = p2;
+ params.p2 = p2;
- if (!copyHidlStringToRil(&params.aidPtr, aid, pRI)) {
- return Void();
- }
+ if (!copyHidlStringToRil(&params.aidPtr, aid, pRI)) {
+ return Void();
+ }
- CALL_ONREQUEST(pRI->pCI->requestNumber, &params, sizeof(params), pRI, mSlotId);
+ CALL_ONREQUEST(pRI->pCI->requestNumber, &params, sizeof(params), pRI, mSlotId);
- memsetAndFreeStrings(1, params.aidPtr);
+ memsetAndFreeStrings(1, params.aidPtr);
+ }
return Void();
}
-Return<void> RadioImpl_1_6::iccCloseLogicalChannel(int32_t serial, int32_t channelId) {
+Return<void> RadioImpl_1_5::iccCloseLogicalChannel(int32_t serial, int32_t channelId) {
#if VDBG
RLOGD("iccCloseLogicalChannel: serial %d", serial);
#endif
@@ -2688,7 +2416,7 @@ Return<void> RadioImpl_1_6::iccCloseLogicalChannel(int32_t serial, int32_t chann
return Void();
}
-Return<void> RadioImpl_1_6::iccTransmitApduLogicalChannel(int32_t serial, const SimApdu& message) {
+Return<void> RadioImpl_1_5::iccTransmitApduLogicalChannel(int32_t serial, const SimApdu& message) {
#if VDBG
RLOGD("iccTransmitApduLogicalChannel: serial %d", serial);
#endif
@@ -2696,7 +2424,7 @@ Return<void> RadioImpl_1_6::iccTransmitApduLogicalChannel(int32_t serial, const
return Void();
}
-Return<void> RadioImpl_1_6::nvReadItem(int32_t serial, NvItem itemId) {
+Return<void> RadioImpl_1_5::nvReadItem(int32_t serial, NvItem itemId) {
#if VDBG
RLOGD("nvReadItem: serial %d", serial);
#endif
@@ -2712,7 +2440,7 @@ Return<void> RadioImpl_1_6::nvReadItem(int32_t serial, NvItem itemId) {
return Void();
}
-Return<void> RadioImpl_1_6::nvWriteItem(int32_t serial, const NvWriteItem& item) {
+Return<void> RadioImpl_1_5::nvWriteItem(int32_t serial, const NvWriteItem& item) {
#if VDBG
RLOGD("nvWriteItem: serial %d", serial);
#endif
@@ -2735,7 +2463,7 @@ Return<void> RadioImpl_1_6::nvWriteItem(int32_t serial, const NvWriteItem& item)
return Void();
}
-Return<void> RadioImpl_1_6::nvWriteCdmaPrl(int32_t serial, const hidl_vec<uint8_t>& prl) {
+Return<void> RadioImpl_1_5::nvWriteCdmaPrl(int32_t serial, const hidl_vec<uint8_t>& prl) {
#if VDBG
RLOGD("nvWriteCdmaPrl: serial %d", serial);
#endif
@@ -2743,7 +2471,7 @@ Return<void> RadioImpl_1_6::nvWriteCdmaPrl(int32_t serial, const hidl_vec<uint8_
return Void();
}
-Return<void> RadioImpl_1_6::nvResetConfig(int32_t serial, ResetNvType resetType) {
+Return<void> RadioImpl_1_5::nvResetConfig(int32_t serial, ResetNvType resetType) {
int rilResetType = -1;
#if VDBG
RLOGD("nvResetConfig: serial %d", serial);
@@ -2769,7 +2497,7 @@ Return<void> RadioImpl_1_6::nvResetConfig(int32_t serial, ResetNvType resetType)
return Void();
}
-Return<void> RadioImpl_1_6::setUiccSubscription(int32_t serial, const SelectUiccSub& uiccSub) {
+Return<void> RadioImpl_1_5::setUiccSubscription(int32_t serial, const SelectUiccSub& uiccSub) {
#if VDBG
RLOGD("setUiccSubscription: serial %d", serial);
#endif
@@ -2790,7 +2518,7 @@ Return<void> RadioImpl_1_6::setUiccSubscription(int32_t serial, const SelectUicc
return Void();
}
-Return<void> RadioImpl_1_6::setDataAllowed(int32_t serial, bool allow) {
+Return<void> RadioImpl_1_5::setDataAllowed(int32_t serial, bool allow) {
#if VDBG
RLOGD("setDataAllowed: serial %d", serial);
#endif
@@ -2798,7 +2526,7 @@ Return<void> RadioImpl_1_6::setDataAllowed(int32_t serial, bool allow) {
return Void();
}
-Return<void> RadioImpl_1_6::getHardwareConfig(int32_t serial) {
+Return<void> RadioImpl_1_5::getHardwareConfig(int32_t serial) {
#if VDBG
RLOGD("getHardwareConfig: serial %d", serial);
#endif
@@ -2807,7 +2535,7 @@ Return<void> RadioImpl_1_6::getHardwareConfig(int32_t serial) {
return Void();
}
-Return<void> RadioImpl_1_6::requestIccSimAuthentication(int32_t serial, int32_t authContext,
+Return<void> RadioImpl_1_5::requestIccSimAuthentication(int32_t serial, int32_t authContext,
const hidl_string& authData, const hidl_string& aid) {
#if VDBG
RLOGD("requestIccSimAuthentication: serial %d", serial);
@@ -2870,7 +2598,7 @@ void freeSetDataProfileData(int numProfiles, T *dataProfiles, T **dataProfilePtr
free(dataProfilePtrs);
}
-Return<void> RadioImpl_1_6::setDataProfile(int32_t serial, const hidl_vec<DataProfileInfo>& profiles,
+Return<void> RadioImpl_1_5::setDataProfile(int32_t serial, const hidl_vec<DataProfileInfo>& profiles,
bool isRoaming) {
#if VDBG
RLOGD("setDataProfile: serial %d", serial);
@@ -3032,7 +2760,7 @@ Return<void> RadioImpl_1_6::setDataProfile(int32_t serial, const hidl_vec<DataPr
return Void();
}
-Return<void> RadioImpl_1_6::requestShutdown(int32_t serial) {
+Return<void> RadioImpl_1_5::requestShutdown(int32_t serial) {
#if VDBG
RLOGD("requestShutdown: serial %d", serial);
#endif
@@ -3040,7 +2768,7 @@ Return<void> RadioImpl_1_6::requestShutdown(int32_t serial) {
return Void();
}
-Return<void> RadioImpl_1_6::getRadioCapability(int32_t serial) {
+Return<void> RadioImpl_1_5::getRadioCapability(int32_t serial) {
#if VDBG
RLOGD("getRadioCapability: serial %d", serial);
#endif
@@ -3048,7 +2776,7 @@ Return<void> RadioImpl_1_6::getRadioCapability(int32_t serial) {
return Void();
}
-Return<void> RadioImpl_1_6::setRadioCapability(int32_t serial, const RadioCapability& rc) {
+Return<void> RadioImpl_1_5::setRadioCapability(int32_t serial, const RadioCapability& rc) {
#if VDBG
RLOGD("setRadioCapability: serial %d", serial);
#endif
@@ -3071,7 +2799,7 @@ Return<void> RadioImpl_1_6::setRadioCapability(int32_t serial, const RadioCapabi
return Void();
}
-Return<void> RadioImpl_1_6::startLceService(int32_t serial, int32_t reportInterval, bool pullMode) {
+Return<void> RadioImpl_1_5::startLceService(int32_t serial, int32_t reportInterval, bool pullMode) {
#if VDBG
RLOGD("startLceService: serial %d", serial);
#endif
@@ -3080,7 +2808,7 @@ Return<void> RadioImpl_1_6::startLceService(int32_t serial, int32_t reportInterv
return Void();
}
-Return<void> RadioImpl_1_6::stopLceService(int32_t serial) {
+Return<void> RadioImpl_1_5::stopLceService(int32_t serial) {
#if VDBG
RLOGD("stopLceService: serial %d", serial);
#endif
@@ -3088,7 +2816,7 @@ Return<void> RadioImpl_1_6::stopLceService(int32_t serial) {
return Void();
}
-Return<void> RadioImpl_1_6::pullLceData(int32_t serial) {
+Return<void> RadioImpl_1_5::pullLceData(int32_t serial) {
#if VDBG
RLOGD("pullLceData: serial %d", serial);
#endif
@@ -3096,7 +2824,7 @@ Return<void> RadioImpl_1_6::pullLceData(int32_t serial) {
return Void();
}
-Return<void> RadioImpl_1_6::getModemActivityInfo(int32_t serial) {
+Return<void> RadioImpl_1_5::getModemActivityInfo(int32_t serial) {
#if VDBG
RLOGD("getModemActivityInfo: serial %d", serial);
#endif
@@ -3168,7 +2896,7 @@ void freeCarrierRestrictions(RIL_CarrierRestrictions &request) {
}
}
-Return<void> RadioImpl_1_6::setAllowedCarriers(int32_t serial, bool allAllowed,
+Return<void> RadioImpl_1_5::setAllowedCarriers(int32_t serial, bool allAllowed,
const CarrierRestrictions& carriers) {
#if VDBG
RLOGD("setAllowedCarriers: serial %d", serial);
@@ -3192,7 +2920,7 @@ Return<void> RadioImpl_1_6::setAllowedCarriers(int32_t serial, bool allAllowed,
return Void();
}
-Return<void> RadioImpl_1_6::getAllowedCarriers(int32_t serial) {
+Return<void> RadioImpl_1_5::getAllowedCarriers(int32_t serial) {
#if VDBG
RLOGD("getAllowedCarriers: serial %d", serial);
#endif
@@ -3200,7 +2928,7 @@ Return<void> RadioImpl_1_6::getAllowedCarriers(int32_t serial) {
return Void();
}
-Return<void> RadioImpl_1_6::sendDeviceState(int32_t serial, DeviceStateType deviceStateType,
+Return<void> RadioImpl_1_5::sendDeviceState(int32_t serial, DeviceStateType deviceStateType,
bool state) {
#if VDBG
RLOGD("sendDeviceState: serial %d", serial);
@@ -3221,7 +2949,7 @@ Return<void> RadioImpl_1_6::sendDeviceState(int32_t serial, DeviceStateType devi
return Void();
}
-Return<void> RadioImpl_1_6::setIndicationFilter(int32_t serial, int32_t indicationFilter) {
+Return<void> RadioImpl_1_5::setIndicationFilter(int32_t serial, int32_t indicationFilter) {
#if VDBG
RLOGD("setIndicationFilter: serial %d", serial);
#endif
@@ -3235,7 +2963,7 @@ Return<void> RadioImpl_1_6::setIndicationFilter(int32_t serial, int32_t indicati
return Void();
}
-Return<void> RadioImpl_1_6::setSimCardPower(int32_t serial, bool powerUp) {
+Return<void> RadioImpl_1_5::setSimCardPower(int32_t serial, bool powerUp) {
#if VDBG
RLOGD("setSimCardPower: serial %d", serial);
#endif
@@ -3243,7 +2971,7 @@ Return<void> RadioImpl_1_6::setSimCardPower(int32_t serial, bool powerUp) {
return Void();
}
-Return<void> RadioImpl_1_6::setSimCardPower_1_1(int32_t serial, const V1_1::CardPowerState state) {
+Return<void> RadioImpl_1_5::setSimCardPower_1_1(int32_t serial, const V1_1::CardPowerState state) {
#if VDBG
RLOGD("setSimCardPower_1_1: serial %d state %d", serial, state);
#endif
@@ -3251,16 +2979,7 @@ Return<void> RadioImpl_1_6::setSimCardPower_1_1(int32_t serial, const V1_1::Card
return Void();
}
-Return<void> RadioImpl_1_6::setSimCardPower_1_6(int32_t serial, const V1_1::CardPowerState state) {
-#if VDBG
- RLOGD("setSimCardPower_1_6: serial %d state %d", serial, state);
-#endif
- dispatchInts(serial, mSlotId, RIL_REQUEST_SET_SIM_CARD_POWER, 1, state);
- mSimCardPowerState = state;
- return Void();
-}
-
-Return<void> RadioImpl_1_6::setCarrierInfoForImsiEncryption(int32_t serial,
+Return<void> RadioImpl_1_5::setCarrierInfoForImsiEncryption(int32_t serial,
const V1_1::ImsiEncryptionInfo& data) {
#if VDBG
RLOGD("setCarrierInfoForImsiEncryption: serial %d", serial);
@@ -3294,7 +3013,7 @@ Return<void> RadioImpl_1_6::setCarrierInfoForImsiEncryption(int32_t serial,
return Void();
}
-Return<void> RadioImpl_1_6::startKeepalive(int32_t serial, const V1_1::KeepaliveRequest& keepalive) {
+Return<void> RadioImpl_1_5::startKeepalive(int32_t serial, const V1_1::KeepaliveRequest& keepalive) {
#if VDBG
RLOGD("%s(): %d", __FUNCTION__, serial);
#endif
@@ -3343,7 +3062,7 @@ Return<void> RadioImpl_1_6::startKeepalive(int32_t serial, const V1_1::Keepalive
return Void();
}
-Return<void> RadioImpl_1_6::stopKeepalive(int32_t serial, int32_t sessionHandle) {
+Return<void> RadioImpl_1_5::stopKeepalive(int32_t serial, int32_t sessionHandle) {
#if VDBG
RLOGD("%s(): %d", __FUNCTION__, serial);
#endif
@@ -3356,7 +3075,7 @@ Return<void> RadioImpl_1_6::stopKeepalive(int32_t serial, int32_t sessionHandle)
return Void();
}
-Return<void> RadioImpl_1_6::responseAcknowledgement() {
+Return<void> RadioImpl_1_5::responseAcknowledgement() {
android::releaseWakeLock();
return Void();
}
@@ -3450,7 +3169,7 @@ int prepareNetworkScanRequest_1_2(RIL_NetworkScanRequest &scan_request,
return 0;
}
-Return<void> RadioImpl_1_6::startNetworkScan_1_2(int32_t serial,
+Return<void> RadioImpl_1_5::startNetworkScan_1_2(int32_t serial,
const ::android::hardware::radio::V1_2::NetworkScanRequest& request) {
#if VDBG
RLOGD("startNetworkScan_1_2: serial %d", serial);
@@ -3473,156 +3192,62 @@ Return<void> RadioImpl_1_6::startNetworkScan_1_2(int32_t serial,
return Void();
}
-Return<void> RadioImpl_1_6::setIndicationFilter_1_2(int32_t serial,
- ::android::hardware::hidl_bitfield<V1_2::IndicationFilter> indicationFilter) {
+Return<void> RadioImpl_1_5::setIndicationFilter_1_2(int32_t /* serial */,
+ hidl_bitfield<::android::hardware::radio::V1_2::IndicationFilter> /* indicationFilter */) {
+ // TODO implement
#if VDBG
- RLOGD("setIndicationFilter_1_2: serial %d", serial);
+ RLOGE("[%04d]< %s", serial, "Method is not implemented");
#endif
-
- RequestInfo *pRI = android::addRequestToList(serial, mSlotId,
- RIL_REQUEST_SET_UNSOLICITED_RESPONSE_FILTER);
- sendErrorResponse(pRI, RIL_E_SUCCESS); // TODO: for vts
return Void();
}
-Return<void> RadioImpl_1_6::setSignalStrengthReportingCriteria(int32_t serial,
- int32_t hysteresisMs, int32_t hysteresisDb,
- const hidl_vec<int32_t>& thresholdsDbm,
- ::android::hardware::radio::V1_2::AccessNetwork accessNetwork) {
+Return<void> RadioImpl_1_5::setSignalStrengthReportingCriteria(int32_t /* serial */,
+ int32_t /* hysteresisMs */, int32_t /* hysteresisDb */,
+ const hidl_vec<int32_t>& /* thresholdsDbm */,
+ ::android::hardware::radio::V1_2::AccessNetwork /* accessNetwork */) {
+ // TODO implement
#if VDBG
- RLOGD("setSignalStrengthReportingCriteria: %d", serial);
+ RLOGE("[%04d]< %s", serial, "Method is not implemented");
#endif
- RIL_Errno e;
- if (radioService[mSlotId]->mRadioResponseV1_2 != NULL) {
- RadioResponseInfo responseInfo = {};
- if (hysteresisDb >= 10) {
- e = RIL_E_INVALID_ARGUMENTS;
- } else {
- e = RIL_E_SUCCESS;
- }
- populateResponseInfo(responseInfo, serial, RESPONSE_SOLICITED, e);
- Return<void> retStatus
- = radioService[mSlotId]->mRadioResponseV1_2->setSignalStrengthReportingCriteriaResponse(responseInfo);
- radioService[mSlotId]->checkReturnStatus(retStatus);
- } else {
- RLOGE("setIndicationFilterResponse: radioService[%d]->mRadioResponse == NULL",
- mSlotId);
- }
return Void();
}
-Return<void> RadioImpl_1_6::setLinkCapacityReportingCriteria(int32_t serial,
- int32_t hysteresisMs, int32_t hysteresisDlKbps, int32_t hysteresisUlKbps,
- const hidl_vec<int32_t>& thresholdsDownlinkKbps,
- const hidl_vec<int32_t>& thresholdsUplinkKbps,
- V1_2::AccessNetwork accessNetwork) {
+Return<void> RadioImpl_1_5::setLinkCapacityReportingCriteria(int32_t /* serial */,
+ int32_t /* hysteresisMs */, int32_t /* hysteresisDlKbps */, int32_t /* hysteresisUlKbps */,
+ const hidl_vec<int32_t>& /* thresholdsDownlinkKbps */,
+ const hidl_vec<int32_t>& /* thresholdsUplinkKbps */,
+ ::android::hardware::radio::V1_2::AccessNetwork /* accessNetwork */) {
+ // TODO implement
#if VDBG
RLOGE("[%04d]< %s", serial, "Method is not implemented");
- RLOGD("setLinkCapacityReportingCriteria: %d", serial);
#endif
-
- RequestInfo *pRI = android::addRequestToList(serial, mSlotId,
- RIL_REQUEST_SET_LINK_CAPACITY_REPORTING_CRITERIA);
- if (pRI == NULL) {
- return Void();
- }
- // TODO: for vts. hysteresisDlKbps and hysteresisUlKbps range not confirmed
- if (hysteresisDlKbps >= 5000 || hysteresisUlKbps >= 1000) {
- sendErrorResponse(pRI, RIL_E_INVALID_ARGUMENTS);
- return Void();
- } else {
- sendErrorResponse(pRI, RIL_E_SUCCESS);
- }
return Void();
}
-Return<void> RadioImpl_1_6::setupDataCall_1_2(int32_t serial, V1_2::AccessNetwork accessNetwork,
- const V1_0::DataProfileInfo& dataProfileInfo, bool modemCognitive,
- bool roamingAllowed, bool isRoaming, V1_2::DataRequestReason reason,
- const hidl_vec<hidl_string>& addresses, const hidl_vec<hidl_string>& dnses) {
+Return<void> RadioImpl_1_5::setupDataCall_1_2(int32_t /* serial */,
+ ::android::hardware::radio::V1_2::AccessNetwork /* accessNetwork */,
+ const ::android::hardware::radio::V1_0::DataProfileInfo& /* dataProfileInfo */,
+ bool /* modemCognitive */, bool /* roamingAllowed */, bool /* isRoaming */,
+ ::android::hardware::radio::V1_2::DataRequestReason /* reason */,
+ const hidl_vec<hidl_string>& /* addresses */, const hidl_vec<hidl_string>& /* dnses */) {
+ // TODO implement
#if VDBG
RLOGE("[%04d]< %s", serial, "Method is not implemented");
- RLOGD("setupDataCall_1_2: serial %d", serial);
#endif
-
- if (s_vendorFunctions->version >= 4 && s_vendorFunctions->version <= 14) {
- const hidl_string &protocol =
- (isRoaming ? dataProfileInfo.roamingProtocol : dataProfileInfo.protocol);
- dispatchStrings(serial, mSlotId, RIL_REQUEST_SETUP_DATA_CALL, true, 7,
- std::to_string((int)accessNetwork).c_str(),
- std::to_string((int)dataProfileInfo.profileId).c_str(),
- dataProfileInfo.apn.c_str(),
- dataProfileInfo.user.c_str(),
- dataProfileInfo.password.c_str(),
- std::to_string((int)dataProfileInfo.authType).c_str(),
- protocol.c_str());
- } else if (s_vendorFunctions->version >= 15) {
- char *mvnoTypeStr = NULL;
- if (!convertMvnoTypeToString(dataProfileInfo.mvnoType, mvnoTypeStr)) {
- RequestInfo *pRI = android::addRequestToList(serial, mSlotId,
- RIL_REQUEST_SETUP_DATA_CALL);
- if (pRI != NULL) {
- sendErrorResponse(pRI, RIL_E_INVALID_ARGUMENTS);
- }
- return Void();
- }
- dispatchStrings(serial, mSlotId, RIL_REQUEST_SETUP_DATA_CALL, true, 15,
- std::to_string((int)accessNetwork).c_str(),
- std::to_string((int)dataProfileInfo.profileId).c_str(),
- dataProfileInfo.apn.c_str(),
- dataProfileInfo.user.c_str(),
- dataProfileInfo.password.c_str(),
- std::to_string((int) dataProfileInfo.authType).c_str(),
- dataProfileInfo.protocol.c_str(),
- dataProfileInfo.roamingProtocol.c_str(),
- std::to_string(dataProfileInfo.supportedApnTypesBitmap).c_str(),
- std::to_string(dataProfileInfo.bearerBitmap).c_str(),
- modemCognitive ? "1" : "0",
- std::to_string(dataProfileInfo.mtu).c_str(),
- mvnoTypeStr,
- dataProfileInfo.mvnoMatchData.c_str(),
- roamingAllowed ? "1" : "0");
- } else {
- RLOGE("Unsupported RIL version %d, min version expected 4", s_vendorFunctions->version);
- RequestInfo *pRI = android::addRequestToList(serial, mSlotId,
- RIL_REQUEST_SETUP_DATA_CALL);
- if (pRI != NULL) {
- sendErrorResponse(pRI, RIL_E_REQUEST_NOT_SUPPORTED);
- }
- }
return Void();
}
-Return<void> RadioImpl_1_6::deactivateDataCall_1_2(int32_t serial, int32_t cid,
- ::android::hardware::radio::V1_2::DataRequestReason reason) {
+Return<void> RadioImpl_1_5::deactivateDataCall_1_2(int32_t /* serial */, int32_t /* cid */,
+ ::android::hardware::radio::V1_2::DataRequestReason /* reason */) {
+ // TODO implement
#if VDBG
- RLOGD("deactivateDataCall_1_2: serial %d", serial);
+ RLOGE("[%04d]< %s", serial, "Method is not implemented");
#endif
-
- RIL_DataRequestReason dataRequestReason = (RIL_DataRequestReason)reason;
- const char *reasonStr = NULL;
- switch (dataRequestReason) {
- case DATA_REQ_REASOPN_NORMAL:
- reasonStr = "normal";
- break;
- case DATA_REQ_REASOPN_SHUTDOWN:
- reasonStr = "shutdown";
- break;
- case DATA_REQ_REASOPN_HANDOVER:
- reasonStr = "handover";
- break;
- default:
- reasonStr = "unknown";
- break;
- }
-
- dispatchStrings(serial, mSlotId, RIL_REQUEST_DEACTIVATE_DATA_CALL, false,
- 2, (std::to_string(cid)).c_str(), reasonStr);
return Void();
}
// Methods from ::android::hardware::radio::V1_3::IRadio follow.
-Return<void> RadioImpl_1_6::setSystemSelectionChannels(int32_t serial, bool /* specifyChannels */,
+Return<void> RadioImpl_1_5::setSystemSelectionChannels(int32_t serial, bool /* specifyChannels */,
const hidl_vec<::android::hardware::radio::V1_1::RadioAccessSpecifier>& /* specifiers */) {
#if VDBG
RLOGD("setSystemSelectionChannels: serial %d", serial);
@@ -3631,15 +3256,15 @@ Return<void> RadioImpl_1_6::setSystemSelectionChannels(int32_t serial, bool /* s
return Void();
}
-Return<void> RadioImpl_1_6::enableModem(int32_t serial, bool /* on */) {
+Return<void> RadioImpl_1_5::enableModem(int32_t serial, bool /* on */) {
#if VDBG
- RLOGE("enableModem: serial = %d", serial);
+ RLOGE("enableModem: serial = %d, enable = %s", serial, on);
#endif
dispatchVoid(serial, mSlotId, RIL_REQUEST_ENABLE_MODEM);
return Void();
}
-Return<void> RadioImpl_1_6::getModemStackStatus(int32_t serial) {
+Return<void> RadioImpl_1_5::getModemStackStatus(int32_t serial) {
#if VDBG
RLOGD("getModemStackStatus: serial %d", serial);
#endif
@@ -3667,7 +3292,7 @@ const char * getProtocolString(const ::android::hardware::radio::V1_4::PdpProtoc
}
// Methods from ::android::hardware::radio::V1_4::IRadio follow.
-Return<void> RadioImpl_1_6::setAllowedCarriers_1_4(int32_t serial,
+Return<void> RadioImpl_1_5::setAllowedCarriers_1_4(int32_t serial,
const V1_4::CarrierRestrictionsWithPriority& carriers,
V1_4::SimLockMultiSimPolicy multiSimPolicy) {
#if VDBG
@@ -3703,7 +3328,7 @@ Return<void> RadioImpl_1_6::setAllowedCarriers_1_4(int32_t serial,
return Void();
}
-Return<void> RadioImpl_1_6::getAllowedCarriers_1_4(int32_t serial) {
+Return<void> RadioImpl_1_5::getAllowedCarriers_1_4(int32_t serial) {
#if VDBG
RLOGD("getAllowedCarriers_1_4: serial %d", serial);
#endif
@@ -3711,7 +3336,7 @@ Return<void> RadioImpl_1_6::getAllowedCarriers_1_4(int32_t serial) {
return Void();
}
-Return<void> RadioImpl_1_6::setupDataCall_1_4(int32_t serial ,
+Return<void> RadioImpl_1_5::setupDataCall_1_4(int32_t serial ,
::android::hardware::radio::V1_4::AccessNetwork /* accessNetwork */,
const ::android::hardware::radio::V1_4::DataProfileInfo& dataProfileInfo,
bool roamingAllowed, ::android::hardware::radio::V1_2::DataRequestReason /* reason */,
@@ -3730,7 +3355,7 @@ Return<void> RadioImpl_1_6::setupDataCall_1_4(int32_t serial ,
}
return Void();
}
- dispatchStrings(serial, mSlotId, RIL_REQUEST_SETUP_DATA_CALL, true, 16,
+ dispatchStrings(serial, mSlotId, RIL_REQUEST_SETUP_DATA_CALL, true, 15,
std::to_string((int) RadioTechnology::UNKNOWN + 2).c_str(),
std::to_string((int) dataProfileInfo.profileId).c_str(),
dataProfileInfo.apn.c_str(),
@@ -3745,12 +3370,11 @@ Return<void> RadioImpl_1_6::setupDataCall_1_4(int32_t serial ,
std::to_string(dataProfileInfo.mtu).c_str(),
mvnoTypeStr,
"302720x94",
- roamingAllowed ? "1" : "0",
- "-1");
+ roamingAllowed ? "1" : "0");
return Void();
}
-Return<void> RadioImpl_1_6::setInitialAttachApn_1_4(int32_t serial ,
+Return<void> RadioImpl_1_5::setInitialAttachApn_1_4(int32_t serial ,
const ::android::hardware::radio::V1_4::DataProfileInfo& dataProfileInfo) {
RequestInfo *pRI = android::addRequestToList(serial, mSlotId,
RIL_REQUEST_SET_INITIAL_ATTACH_APN);
@@ -3776,7 +3400,7 @@ Return<void> RadioImpl_1_6::setInitialAttachApn_1_4(int32_t serial ,
return Void();
}
-Return<void> RadioImpl_1_6::setDataProfile_1_4(int32_t serial ,
+Return<void> RadioImpl_1_5::setDataProfile_1_4(int32_t serial ,
const hidl_vec<::android::hardware::radio::V1_4::DataProfileInfo>& /* profiles */) {
RequestInfo *pRI = android::addRequestToList(serial, mSlotId,
RIL_REQUEST_SET_DATA_PROFILE);
@@ -3802,12 +3426,12 @@ Return<void> RadioImpl_1_6::setDataProfile_1_4(int32_t serial ,
return Void();
}
-Return<void> RadioImpl_1_6::emergencyDial(int32_t serial,
+Return<void> RadioImpl_1_5::emergencyDial(int32_t serial,
const ::android::hardware::radio::V1_0::Dial& dialInfo,
- hidl_bitfield<android::hardware::radio::V1_4::EmergencyServiceCategory> categories,
- const hidl_vec<hidl_string>& urns ,
- ::android::hardware::radio::V1_4::EmergencyCallRouting routing,
- bool fromEmergencyDialer, bool /* isTesting */) {
+ hidl_bitfield<android::hardware::radio::V1_4::EmergencyServiceCategory> /* categories */,
+ const hidl_vec<hidl_string>& /* urns */,
+ ::android::hardware::radio::V1_4::EmergencyCallRouting /* routing */,
+ bool /* fromEmergencyDialer */, bool /* isTesting */) {
#if VDBG
RLOGD("emergencyDial: serial %d", serial);
#endif
@@ -3816,10 +3440,9 @@ Return<void> RadioImpl_1_6::emergencyDial(int32_t serial,
if (pRI == NULL) {
return Void();
}
-
- RIL_EmergencyDial eccDial = {};
- RIL_Dial& dial = eccDial.dialInfo;
+ RIL_Dial dial = {};
RIL_UUS_Info uusInfo = {};
+ int32_t sizeOfDial = sizeof(dial);
if (!copyHidlStringToRil(&dial.address, dialInfo.address, pRI)) {
return Void();
@@ -3844,46 +3467,14 @@ Return<void> RadioImpl_1_6::emergencyDial(int32_t serial,
dial.uusInfo = &uusInfo;
}
- eccDial.urnsNumber = urns.size();
- if (eccDial.urnsNumber != 0) {
- char **ppUrns = (char **)calloc(eccDial.urnsNumber, sizeof(char *));
- if (ppUrns == NULL) {
- RLOGE("Memory allocation failed for request %s",
- requestToString(pRI->pCI->requestNumber));
- sendErrorResponse(pRI, RIL_E_NO_MEMORY);
- memsetAndFreeStrings(2, dial.address, uusInfo.uusData);
- return Void();
- }
- for (uint32_t i = 0; i < eccDial.urnsNumber; i++) {
- if (!copyHidlStringToRil(&ppUrns[i], hidl_string(urns[i]), pRI)) {
- for (uint32_t j = 0; j < i; j++) {
- memsetAndFreeStrings(1, ppUrns[j]);
- }
- memsetAndFreeStrings(2, dial.address, uusInfo.uusData);
- free(ppUrns);
- return Void();
- }
- }
- eccDial.urns = ppUrns;
- }
-
- eccDial.categories = (RIL_EmergencyServiceCategory)categories;
- eccDial.routing = (RIL_EmergencyCallRouting)routing;
- eccDial.fromEmergencyDialer = fromEmergencyDialer;
-
- CALL_ONREQUEST(RIL_REQUEST_EMERGENCY_DIAL, &eccDial, sizeof(RIL_EmergencyDial), pRI, mSlotId);
+ CALL_ONREQUEST(RIL_REQUEST_EMERGENCY_DIAL, &dial, sizeOfDial, pRI, mSlotId);
memsetAndFreeStrings(2, dial.address, uusInfo.uusData);
- if (eccDial.urns != NULL) {
- for (size_t i = 0; i < eccDial.urnsNumber; i++) {
- memsetAndFreeStrings(1, eccDial.urns[i]);
- }
- free(eccDial.urns);
- }
+
return Void();
}
-Return<void> RadioImpl_1_6::startNetworkScan_1_4(int32_t serial,
+Return<void> RadioImpl_1_5::startNetworkScan_1_4(int32_t serial,
const ::android::hardware::radio::V1_2::NetworkScanRequest& request) {
#if VDBG
RLOGD("startNetworkScan_1_4: serial %d", serial);
@@ -3906,7 +3497,7 @@ Return<void> RadioImpl_1_6::startNetworkScan_1_4(int32_t serial,
return Void();
}
-Return<void> RadioImpl_1_6::getPreferredNetworkTypeBitmap(int32_t serial ) {
+Return<void> RadioImpl_1_5::getPreferredNetworkTypeBitmap(int32_t serial ) {
#if VDBG
RLOGD("getPreferredNetworkTypeBitmap: serial %d", serial);
#endif
@@ -3914,7 +3505,7 @@ Return<void> RadioImpl_1_6::getPreferredNetworkTypeBitmap(int32_t serial ) {
return Void();
}
-Return<void> RadioImpl_1_6::setPreferredNetworkTypeBitmap(
+Return<void> RadioImpl_1_5::setPreferredNetworkTypeBitmap(
int32_t serial, hidl_bitfield<RadioAccessFamily> networkTypeBitmap) {
#if VDBG
RLOGD("setPreferredNetworkTypeBitmap: serial %d", serial);
@@ -3923,24 +3514,7 @@ Return<void> RadioImpl_1_6::setPreferredNetworkTypeBitmap(
return Void();
}
-Return<void> RadioImpl_1_6::setAllowedNetworkTypesBitmap(
- uint32_t serial, hidl_bitfield<RadioAccessFamily> networkTypeBitmap) {
-#if VDBG
- RLOGD("setAllowedNetworkTypesBitmap: serial %d", serial);
-#endif
- dispatchInts(serial, mSlotId, RIL_REQUEST_SET_ALLOWED_NETWORK_TYPES_BITMAP, 1, networkTypeBitmap);
- return Void();
-}
-
-Return<void> RadioImpl_1_6::getAllowedNetworkTypesBitmap(int32_t serial) {
-#if VDBG
- RLOGD("getAllowedNetworkTypesBitmap: serial %d", serial);
-#endif
- dispatchVoid(serial, mSlotId, RIL_REQUEST_GET_ALLOWED_NETWORK_TYPES_BITMAP);
- return Void();
-}
-
-Return<void> RadioImpl_1_6::getSignalStrength_1_4(int32_t serial) {
+Return<void> RadioImpl_1_5::getSignalStrength_1_4(int32_t serial) {
#if VDBG
RLOGD("getSignalStrength_1_4: serial %d", serial);
#endif
@@ -3948,107 +3522,30 @@ Return<void> RadioImpl_1_6::getSignalStrength_1_4(int32_t serial) {
return Void();
}
-Return<void> RadioImpl_1_6::getSignalStrength_1_6(int32_t serial) {
-#if VDBG
- RLOGD("getSignalStrength_1_6: serial %d", serial);
-#endif
- dispatchVoid(serial, mSlotId, RIL_REQUEST_SIGNAL_STRENGTH);
- return Void();
-}
-
// Methods from ::android::hardware::radio::V1_5::IRadio follow.
-Return<void> RadioImpl_1_6::setSignalStrengthReportingCriteria_1_5(int32_t serial,
- const V1_5::SignalThresholdInfo& signalThresholdInfo,
- V1_5::AccessNetwork accessNetwork) {
+Return<void> RadioImpl_1_5::setSignalStrengthReportingCriteria_1_5(int32_t /* serial */,
+ const ::android::hardware::radio::V1_5::SignalThresholdInfo& /* signalThresholdInfo */,
+ const ::android::hardware::radio::V1_5::AccessNetwork /* accessNetwork */) {
+ // TODO implement
#if VDBG
- RLOGD("setSignalStrengthReportingCriteria_1_5: %d", serial);
+ RLOGE("[%04d]< %s", serial, "Method is not implemented");
#endif
-
- RequestInfo *pRI = android::addRequestToList(serial, mSlotId,
- RIL_REQUEST_SET_SIGNAL_STRENGTH_REPORTING_CRITERIA);
- if (pRI == NULL) {
- return Void();
- }
-
- if (signalThresholdInfo.hysteresisDb >= 10) { // TODO: for vts. hysteresisDb range not checked
- sendErrorResponse(pRI, RIL_E_INVALID_ARGUMENTS);
- return Void();
- }
-
- RIL_SignalStrengthReportingCriteria_v1_5 *criteria = (RIL_SignalStrengthReportingCriteria_v1_5 *)
- calloc(1, sizeof(RIL_SignalStrengthReportingCriteria_v1_5));
- if (criteria == NULL) {
- RLOGE("Memory allocation failed for request %s",
- requestToString(pRI->pCI->requestNumber));
- sendErrorResponse(pRI, RIL_E_NO_MEMORY);
- return Void();
- }
-
- criteria->signalMeasurement = (SignalMeasurementType)signalThresholdInfo.signalMeasurement;
- criteria->isEnabled = signalThresholdInfo.isEnabled;
- criteria->hysteresisMs = signalThresholdInfo.hysteresisMs;
- criteria->hysteresisDb = signalThresholdInfo.hysteresisDb;
- criteria->thresholdsDbmNumber = signalThresholdInfo.thresholds.size();
- criteria->thresholdsDbm = new int32_t[criteria->thresholdsDbmNumber];
- memcpy(criteria->thresholdsDbm, signalThresholdInfo.thresholds.data(),
- criteria->thresholdsDbmNumber * sizeof(int32_t));
- criteria->accessNetwork = (RIL_RadioAccessNetworks_v1_5)accessNetwork;
-
- CALL_ONREQUEST(pRI->pCI->requestNumber, criteria,
- sizeof(RIL_SignalStrengthReportingCriteria_v1_5), pRI, mSlotId);
-
return Void();
}
-Return<void> RadioImpl_1_6::setLinkCapacityReportingCriteria_1_5(int32_t serial,
- int32_t hysteresisMs, int32_t hysteresisDlKbps, int32_t hysteresisUlKbps,
- const hidl_vec<int32_t>& thresholdsDownlinkKbps,
- const hidl_vec<int32_t>& thresholdsUplinkKbps,
- V1_5::AccessNetwork accessNetwork) {
+Return<void> RadioImpl_1_5::setLinkCapacityReportingCriteria_1_5(int32_t /* serial */,
+ int32_t /* hysteresisMs */, int32_t /* hysteresisDlKbps */, int32_t /* hysteresisUlKbps */,
+ const hidl_vec<int32_t>& /* thresholdsDownlinkKbps */,
+ const hidl_vec<int32_t>& /* thresholdsUplinkKbps */,
+ V1_5::AccessNetwork /* accessNetwork */) {
+ // TODO implement
#if VDBG
- RLOGD("setLinkCapacityReportingCriteria_1_5: %d", serial);
+ RLOGE("[%04d]< %s", serial, "Method is not implemented");
#endif
-
- RequestInfo *pRI = android::addRequestToList(serial, mSlotId,
- RIL_REQUEST_SET_LINK_CAPACITY_REPORTING_CRITERIA);
- if (pRI == NULL) {
- return Void();
- }
- // TODO: for vts. hysteresisDlKbps and hysteresisUlKbps range not confirmed
- if (hysteresisDlKbps >= 5000 || hysteresisUlKbps >= 1000) {
- sendErrorResponse(pRI, RIL_E_INVALID_ARGUMENTS);
- return Void();
- }
-
- RIL_LinkCapacityReportingCriteria *criteria = (RIL_LinkCapacityReportingCriteria *)
- calloc(1, sizeof(RIL_LinkCapacityReportingCriteria));
- if (criteria == NULL) {
- RLOGE("Memory allocation failed for request %s",
- requestToString(pRI->pCI->requestNumber));
- sendErrorResponse(pRI, RIL_E_NO_MEMORY);
- return Void();
- }
-
- criteria->hysteresisMs = hysteresisMs;
- criteria->hysteresisDlKbps = hysteresisDlKbps;
- criteria->hysteresisUlKbps = hysteresisUlKbps;
- criteria->thresholdsDownlinkKbpsLength = thresholdsDownlinkKbps.size();
- criteria->thresholdsUplinkKbpsLength = thresholdsUplinkKbps.size();
- criteria->thresholdsDownlinkKbps = new int32_t[criteria->thresholdsDownlinkKbpsLength];
- criteria->thresholdsUplinkKbps = new int32_t[criteria->thresholdsUplinkKbpsLength];
- memcpy(criteria->thresholdsDownlinkKbps, thresholdsDownlinkKbps.data(),
- criteria->thresholdsDownlinkKbpsLength * sizeof(int32_t));
- memcpy(criteria->thresholdsUplinkKbps, thresholdsUplinkKbps.data(),
- criteria->thresholdsUplinkKbpsLength * sizeof(int32_t));
- criteria->accessNetwork = (RIL_RadioAccessNetworks_v1_5)accessNetwork;
-
- CALL_ONREQUEST(pRI->pCI->requestNumber, criteria,
- sizeof(RIL_LinkCapacityReportingCriteria), pRI, pRI->socket_id);
-
- return Void();
+ return Void();
}
-Return<void> RadioImpl_1_6::enableUiccApplications(int32_t serial, bool enable) {
+Return<void> RadioImpl_1_5::enableUiccApplications(int32_t serial, bool enable) {
#if VDBG
RLOGD("enableUiccApplications: serial %d enable %d", serial, enable);
#endif
@@ -4056,27 +3553,17 @@ Return<void> RadioImpl_1_6::enableUiccApplications(int32_t serial, bool enable)
return Void();
}
-Return<void> RadioImpl_1_6::setRadioPower_1_5(int32_t serial, bool powerOn, bool forEmergencyCall,
+Return<void> RadioImpl_1_5::setRadioPower_1_5(int32_t serial, bool powerOn, bool forEmergencyCall,
bool preferredForEmergencyCall) {
#if VDBG
- RLOGD("setRadioPower_1_6: serial %d powerOn %d forEmergency %d preferredForEmergencyCall %d",
+ RLOGD("setRadioPower_1_5: serial %d powerOn %d forEmergency %d preferredForEmergencyCall %d",
serial, powerOn, forEmergencyCall, preferredForEmergencyCall);
#endif
dispatchInts(serial, mSlotId, RIL_REQUEST_RADIO_POWER, 1, BOOL_TO_INT(powerOn));
return Void();
}
-Return<void> RadioImpl_1_6::setRadioPower_1_6(int32_t serial, bool powerOn, bool forEmergencyCall,
- bool preferredForEmergencyCall) {
-#if VDBG
- RLOGD("setRadioPower_1_6: serial %d powerOn %d forEmergency %d preferredForEmergencyCall %d",
- serial, powerOn, forEmergencyCall, preferredForEmergencyCall);
-#endif
- dispatchInts(serial, mSlotId, RIL_REQUEST_RADIO_POWER, 1, BOOL_TO_INT(powerOn));
- return Void();
-}
-
-Return<void> RadioImpl_1_6::areUiccApplicationsEnabled(int32_t serial) {
+Return<void> RadioImpl_1_5::areUiccApplicationsEnabled(int32_t serial) {
#if VDBG
RLOGD("areUiccApplicationsEnabled: serial %d", serial);
#endif
@@ -4084,119 +3571,36 @@ Return<void> RadioImpl_1_6::areUiccApplicationsEnabled(int32_t serial) {
return Void();
}
-Return<void> RadioImpl_1_6::getVoiceRegistrationState_1_5(int32_t serial) {
+Return<void> RadioImpl_1_5::getVoiceRegistrationState_1_5(int32_t serial) {
#if VDBG
- RLOGD("getVoiceRegistrationState_1_5: serial %d", serial);
+ RLOGD("getVoiceRegistrationState: serial %d", serial);
#endif
dispatchVoid(serial, mSlotId, RIL_REQUEST_VOICE_REGISTRATION_STATE);
return Void();
}
-Return<void> RadioImpl_1_6::getDataRegistrationState_1_5(int32_t serial) {
+Return<void> RadioImpl_1_5::getDataRegistrationState_1_5(int32_t serial) {
#if VDBG
- RLOGD("getDataRegistrationState_1_5: serial %d", serial);
+ RLOGD("getDataRegistrationState: serial %d", serial);
#endif
dispatchVoid(serial, mSlotId, RIL_REQUEST_DATA_REGISTRATION_STATE);
return Void();
}
-Return<void> RadioImpl_1_6::getVoiceRegistrationState_1_6(int32_t serial) {
-#if VDBG
- RLOGD("getVoiceRegistrationState_1_6: serial %d", serial);
-#endif
- dispatchVoid(serial, mSlotId, RIL_REQUEST_VOICE_REGISTRATION_STATE);
- return Void();
-}
-
-Return<void> RadioImpl_1_6::getDataRegistrationState_1_6(int32_t serial) {
+Return<void> RadioImpl_1_5::setSystemSelectionChannels_1_5(int32_t serial,
+ bool /* specifyChannels */, const hidl_vec<V1_5::RadioAccessSpecifier>& /* specifiers */) {
#if VDBG
- RLOGD("getDataRegistrationState_1_6: serial %d", serial);
+ RLOGD("setSystemSelectionChannels_1_5: serial %d", serial);
#endif
- dispatchVoid(serial, mSlotId, RIL_REQUEST_DATA_REGISTRATION_STATE);
+ dispatchVoid(serial, mSlotId, RIL_REQUEST_SET_SYSTEM_SELECTION_CHANNELS);
return Void();
}
-Return<void> RadioImpl_1_6::setSystemSelectionChannels_1_5(int32_t serial,
- bool specifyChannels, const hidl_vec<V1_5::RadioAccessSpecifier>& specifiers) {
-
-#if VDBG
-RLOGD("setSystemSelectionChannels_1_5: %d", serial);
-#endif
-
- RequestInfo *pRI = android::addRequestToList(serial, mSlotId,
- RIL_REQUEST_SET_SYSTEM_SELECTION_CHANNELS);
- if (pRI == NULL) {
- return Void();
- }
-
- if (specifiers.size() > RIL_RADIO_ACCESS_SPECIFIER_MAX_SIZE) {
- sendErrorResponse(pRI, RIL_E_INVALID_ARGUMENTS);
- return Void();
- }
-
- RIL_SystemSelectionChannels_v1_5 *sysSelectionChannels =
- (RIL_SystemSelectionChannels_v1_5 *)calloc(1, sizeof(RIL_SystemSelectionChannels_v1_5));
- if (sysSelectionChannels == NULL) {
- RLOGE("Memory allocation failed for request %s",
- requestToString(pRI->pCI->requestNumber));
- sendErrorResponse(pRI, RIL_E_NO_MEMORY);
- return Void();
- }
- sysSelectionChannels->specifyChannels = specifyChannels;
- sysSelectionChannels->specifiers_length = specifiers.size();
- for (size_t i = 0; i < specifiers.size(); ++i) {
- const V1_5::RadioAccessSpecifier& ras_from = specifiers[i];
- RIL_RadioAccessSpecifier_v1_5 &ras_to = sysSelectionChannels->specifiers[i];
-
- ras_to.radio_access_network = (RIL_RadioAccessNetworks_v1_5)ras_from.radioAccessNetwork;
- ras_to.channels_length = ras_from.channels.size();
-
- std::copy(ras_from.channels.begin(), ras_from.channels.end(), ras_to.channels);
- const std::vector<uint32_t> * bands = nullptr;
- switch (specifiers[i].radioAccessNetwork) {
- case V1_5::RadioAccessNetworks::GERAN:
- ras_to.bands_length = ras_from.bands.geranBands().size();
- bands = (std::vector<uint32_t> *) &ras_from.bands.geranBands();
- break;
- case V1_5::RadioAccessNetworks::UTRAN:
- ras_to.bands_length = ras_from.bands.utranBands().size();
- bands = (std::vector<uint32_t> *) &ras_from.bands.utranBands();
- break;
- case V1_5::RadioAccessNetworks::EUTRAN:
- ras_to.bands_length = ras_from.bands.eutranBands().size();
- bands = (std::vector<uint32_t> *) &ras_from.bands.eutranBands();
- break;
- case V1_5::RadioAccessNetworks::NGRAN:
- ras_to.bands_length = ras_from.bands.ngranBands().size();
- bands = (std::vector<uint32_t> *) &ras_from.bands.ngranBands();
- break;
- default: {
- sendErrorResponse(pRI, RIL_E_INVALID_ARGUMENTS);
- free(sysSelectionChannels);
- return Void();
- }
- }
- // safe to copy to geran_bands because it's a union member
- for (size_t idx = 0; idx < ras_to.bands_length; ++idx) {
- ras_to.bands.geran_bands[idx] = (RIL_GeranBands)(*bands)[idx];
- }
- }
-
- CALL_ONREQUEST(RIL_REQUEST_SET_SYSTEM_SELECTION_CHANNELS, sysSelectionChannels,
- sizeof(RIL_SystemSelectionChannels_v1_5), pRI, mSlotId);
-
- return Void();
-}
-
-int prepareNetworkScanRequest_1_5(RIL_NetworkScanRequest_v1_5 &scan_request,
+int prepareNetworkScanRequest_1_5(RIL_NetworkScanRequest &scan_request,
const V1_5::NetworkScanRequest& request, RequestInfo *pRI) {
scan_request.type = (RIL_ScanType) request.type;
scan_request.interval = request.interval;
scan_request.specifiers_length = request.specifiers.size();
- scan_request.maxSearchTime = request.maxSearchTime;
- scan_request.incrementalResults = request.incrementalResults;
- scan_request.incrementalResultsPeriodicity = request.incrementalResultsPeriodicity;
- scan_request.mccMncsNumbers = request.mccMncs.size();
int intervalLow = static_cast<int>(V1_2::ScanIntervalRange::MIN);
int intervalHigh = static_cast<int>(V1_2::ScanIntervalRange::MAX);
@@ -4231,49 +3635,18 @@ int prepareNetworkScanRequest_1_5(RIL_NetworkScanRequest_v1_5 &scan_request,
}
for (size_t i = 0; i < request.specifiers.size(); ++i) {
- if (request.specifiers[i].channels.size() > MAX_CHANNELS) {
+ if (request.specifiers[i].bands.geranBands().size() > MAX_BANDS
+ || request.specifiers[i].bands.utranBands().size() > MAX_BANDS
+ || request.specifiers[i].bands.eutranBands().size() > MAX_BANDS
+ || request.specifiers[i].bands.ngranBands().size() > MAX_BANDS
+ || request.specifiers[i].channels.size() > MAX_CHANNELS) {
sendErrorResponse(pRI, RIL_E_INVALID_ARGUMENTS);
return -1;
}
- switch (request.specifiers[i].bands.getDiscriminator()) {
- case V1_5::RadioAccessSpecifier::Bands::hidl_discriminator::geranBands:
- if (request.specifiers[i].bands.geranBands().size() > MAX_BANDS) {
- sendErrorResponse(pRI, RIL_E_INVALID_ARGUMENTS);
- return -1;
- }
- break;
- case V1_5::RadioAccessSpecifier::Bands::hidl_discriminator::utranBands:
- if (request.specifiers[i].bands.utranBands().size() > MAX_BANDS) {
- sendErrorResponse(pRI, RIL_E_INVALID_ARGUMENTS);
- return -1;
- }
- break;
- case V1_5::RadioAccessSpecifier::Bands::hidl_discriminator::eutranBands:
- if (request.specifiers[i].bands.eutranBands().size() > MAX_BANDS) {
- sendErrorResponse(pRI, RIL_E_INVALID_ARGUMENTS);
- return -1;
- }
- break;
- case V1_5::RadioAccessSpecifier::Bands::hidl_discriminator::ngranBands:
- if (request.specifiers[i].bands.ngranBands().size() > MAX_BANDS) {
- sendErrorResponse(pRI, RIL_E_INVALID_ARGUMENTS);
- return -1;
- }
- break;
- default:
- sendErrorResponse(pRI, RIL_E_INVALID_ARGUMENTS);
- return -1;
- }
-
- if (request.specifiers[i].channels.size() > MAX_CHANNELS) {
- sendErrorResponse(pRI, RIL_E_INVALID_ARGUMENTS);
- return -1;
- }
-
const V1_5::RadioAccessSpecifier& ras_from = request.specifiers[i];
- RIL_RadioAccessSpecifier_v1_5& ras_to = scan_request.specifiers[i];
+ RIL_RadioAccessSpecifier& ras_to = scan_request.specifiers[i];
- ras_to.radio_access_network = (RIL_RadioAccessNetworks_v1_5) ras_from.radioAccessNetwork;
+ ras_to.radio_access_network = (RIL_RadioAccessNetworks) ras_from.radioAccessNetwork;
ras_to.channels_length = ras_from.channels.size();
std::copy(ras_from.channels.begin(), ras_from.channels.end(), ras_to.channels);
@@ -4281,68 +3654,37 @@ int prepareNetworkScanRequest_1_5(RIL_NetworkScanRequest_v1_5 &scan_request,
switch (request.specifiers[i].radioAccessNetwork) {
case V1_5::RadioAccessNetworks::GERAN:
ras_to.bands_length = ras_from.bands.geranBands().size();
-
- bands = (std::vector<uint32_t> *) &ras_from.bands.geranBands();
- // safe to copy to geran_bands because it's a union member
- for (size_t idx = 0; idx < ras_to.bands_length; ++idx) {
- ras_to.bands.geran_bands[idx] = (RIL_GeranBands) (*bands)[idx];
- }
+ bands = (std::vector<uint32_t> *) &ras_from.bands;
break;
case V1_5::RadioAccessNetworks::UTRAN:
ras_to.bands_length = ras_from.bands.utranBands().size();
bands = (std::vector<uint32_t> *) &ras_from.bands;
- // safe to copy to geran_bands because it's a union member
- for (size_t idx = 0; idx < ras_to.bands_length; ++idx) {
- ras_to.bands.utran_bands[idx] = (RIL_UtranBands) (*bands)[idx];
- }
break;
case V1_5::RadioAccessNetworks::EUTRAN:
ras_to.bands_length = ras_from.bands.eutranBands().size();
bands = (std::vector<uint32_t> *) &ras_from.bands;
- // safe to copy to geran_bands because it's a union member
- for (size_t idx = 0; idx < ras_to.bands_length; ++idx) {
- ras_to.bands.eutran_bands[idx] = (RIL_EutranBands) (*bands)[idx];
- }
break;
case V1_5::RadioAccessNetworks::NGRAN:
ras_to.bands_length = ras_from.bands.ngranBands().size();
bands = (std::vector<uint32_t> *) &ras_from.bands;
- // safe to copy to geran_bands because it's a union member
- for (size_t idx = 0; idx < ras_to.bands_length; ++idx) {
- ras_to.bands.ngran_bands[idx] = (RIL_NgranBands) (*bands)[idx];
- }
break;
default:
sendErrorResponse(pRI, RIL_E_INVALID_ARGUMENTS);
return -1;
}
- }
- if (scan_request.mccMncsNumbers != 0) {
- char **pStrings = (char **)calloc(scan_request.mccMncsNumbers, sizeof(char *));
- if (pStrings == NULL) {
- RLOGE("Memory allocation failed for request %s",
- requestToString(pRI->pCI->requestNumber));
- sendErrorResponse(pRI, RIL_E_NO_MEMORY);
- return -1;
- }
- for (size_t i = 0; i < request.mccMncs.size(); ++i) {
- if (!copyHidlStringToRil(&pStrings[i], hidl_string(request.mccMncs[i]), pRI)) {
- for (size_t j = 0; j < i; j++) {
- memsetAndFreeStrings(1, pStrings[j]);
- }
- free(pStrings);
- return -1;
- }
+ // safe to copy to geran_bands because it's a union member
+ for (size_t idx = 0; idx < ras_to.bands_length; ++idx) {
+ ras_to.bands.geran_bands[idx] = (RIL_GeranBands) (*bands)[idx];
}
- scan_request.mccMncs = pStrings;
}
+
return 0;
}
-Return<void> RadioImpl_1_6::startNetworkScan_1_5(int32_t serial,
+Return<void> RadioImpl_1_5::startNetworkScan_1_5(int32_t serial,
const ::android::hardware::radio::V1_5::NetworkScanRequest& request) {
#if VDBG
- RLOGD("startNetworkScan_1_6: serial %d", serial);
+ RLOGD("startNetworkScan_1_5: serial %d", serial);
#endif
RequestInfo *pRI = android::addRequestToList(serial, mSlotId, RIL_REQUEST_START_NETWORK_SCAN);
@@ -4350,7 +3692,7 @@ Return<void> RadioImpl_1_6::startNetworkScan_1_5(int32_t serial,
return Void();
}
- RIL_NetworkScanRequest_v1_5 scan_request = {};
+ RIL_NetworkScanRequest scan_request = {};
if (prepareNetworkScanRequest_1_5(scan_request, request, pRI) < 0) {
return Void();
@@ -4362,7 +3704,7 @@ Return<void> RadioImpl_1_6::startNetworkScan_1_5(int32_t serial,
return Void();
}
-Return<void> RadioImpl_1_6::setupDataCall_1_5(int32_t serial ,
+Return<void> RadioImpl_1_5::setupDataCall_1_5(int32_t serial ,
::android::hardware::radio::V1_5::AccessNetwork /* accessNetwork */,
const ::android::hardware::radio::V1_5::DataProfileInfo& dataProfileInfo,
bool roamingAllowed, ::android::hardware::radio::V1_2::DataRequestReason /* reason */,
@@ -4402,51 +3744,7 @@ Return<void> RadioImpl_1_6::setupDataCall_1_5(int32_t serial ,
return Void();
}
-Return<void> RadioImpl_1_6::setupDataCall_1_6(int32_t serial ,
- ::android::hardware::radio::V1_5::AccessNetwork /* accessNetwork */,
- const ::android::hardware::radio::V1_5::DataProfileInfo& dataProfileInfo,
- bool roamingAllowed, ::android::hardware::radio::V1_2::DataRequestReason /* reason */,
- const hidl_vec<::android::hardware::radio::V1_5::LinkAddress>& /* addresses */,
- const hidl_vec<hidl_string>& /* dnses */,
- int32_t /* pduSessionId */,
- const ::android::hardware::radio::V1_6::OptionalSliceInfo& /* sliceInfo */,
- const ::android::hardware::radio::V1_6::OptionalTrafficDescriptor& /*trafficDescriptor*/,
- bool matchAllRuleAllowed) {
-
-#if VDBG
- RLOGD("setupDataCall_1_6: serial %d", serial);
-#endif
-
- char *mvnoTypeStr = NULL;
- if (!convertMvnoTypeToString(MvnoType::IMSI, mvnoTypeStr)) {
- RequestInfo *pRI = android::addRequestToList(serial, mSlotId,
- RIL_REQUEST_SETUP_DATA_CALL);
- if (pRI != NULL) {
- sendErrorResponse(pRI, RIL_E_INVALID_ARGUMENTS);
- }
- return Void();
- }
- dispatchStrings(serial, mSlotId, RIL_REQUEST_SETUP_DATA_CALL, true, 16,
- std::to_string((int) RadioTechnology::UNKNOWN + 2).c_str(),
- std::to_string((int) dataProfileInfo.profileId).c_str(),
- dataProfileInfo.apn.c_str(),
- dataProfileInfo.user.c_str(),
- dataProfileInfo.password.c_str(),
- std::to_string((int) dataProfileInfo.authType).c_str(),
- getProtocolString(dataProfileInfo.protocol),
- getProtocolString(dataProfileInfo.roamingProtocol),
- std::to_string(dataProfileInfo.supportedApnTypesBitmap).c_str(),
- std::to_string(dataProfileInfo.bearerBitmap).c_str(),
- dataProfileInfo.persistent ? "1" : "0",
- std::to_string(dataProfileInfo.mtuV4).c_str(),
- std::to_string(dataProfileInfo.mtuV6).c_str(),
- mvnoTypeStr,
- "302720x94",
- roamingAllowed ? "1" : "0");
- return Void();
-}
-
-Return<void> RadioImpl_1_6::setInitialAttachApn_1_5(int32_t serial ,
+Return<void> RadioImpl_1_5::setInitialAttachApn_1_5(int32_t serial ,
const ::android::hardware::radio::V1_5::DataProfileInfo& dataProfileInfo) {
RequestInfo *pRI = android::addRequestToList(serial, mSlotId,
RIL_REQUEST_SET_INITIAL_ATTACH_APN);
@@ -4475,7 +3773,7 @@ Return<void> RadioImpl_1_6::setInitialAttachApn_1_5(int32_t serial ,
return Void();
}
-Return<void> RadioImpl_1_6::setDataProfile_1_5(int32_t serial ,
+Return<void> RadioImpl_1_5::setDataProfile_1_5(int32_t serial ,
const hidl_vec<::android::hardware::radio::V1_5::DataProfileInfo>& /* profiles */) {
RequestInfo *pRI = android::addRequestToList(serial, mSlotId,
RIL_REQUEST_SET_DATA_PROFILE);
@@ -4504,65 +3802,33 @@ Return<void> RadioImpl_1_6::setDataProfile_1_5(int32_t serial ,
return Void();
}
-Return<void> RadioImpl_1_6::setIndicationFilter_1_5(int32_t /* serial */,
+Return<void> RadioImpl_1_5::setIndicationFilter_1_5(int32_t /* serial */,
hidl_bitfield<::android::hardware::radio::V1_5::IndicationFilter> /* indicationFilter */) {
// TODO implement
#if VDBG
- RLOGE("setIndicationFilter_1_5: Method is not implemented");
+ RLOGE("[%04d]< %s", serial, "Method is not implemented");
#endif
return Void();
}
-Return<void> RadioImpl_1_6::getBarringInfo(int32_t serial) {
+Return<void> RadioImpl_1_5::getBarringInfo(int32_t /* serial */) {
+ // TODO implement
#if VDBG
- RLOGD("getBarringInfo: serial %d", serial);
+ RLOGE("[%04d]< %s", serial, "Method is not implemented");
#endif
- dispatchVoid(serial, mSlotId, RIL_REQUEST_GET_BARRING_INFO);
return Void();
}
-Return<void> RadioImpl_1_6::setNetworkSelectionModeManual_1_5(int32_t serial,
+Return<void> RadioImpl_1_5::setNetworkSelectionModeManual_1_5(int32_t serial,
const hidl_string& operatorNumeric, V1_5::RadioAccessNetworks ran) {
#if VDBG
- RLOGD("setNetworkSelectionModeManual_1_6: serial %d", serial);
+ RLOGD("setNetworkSelectionModeManual_1_5: serial %d", serial);
#endif
- RequestInfo *pRI = android::addRequestToList(serial, mSlotId,
- RIL_REQUEST_SET_NETWORK_SELECTION_MANUAL);
- if (pRI == NULL) {
- return Void();
- }
-
- RIL_NetworkOperator networkOperator = {};
-
- networkOperator.act = (RIL_RadioAccessNetworks)ran;
- if (!copyHidlStringToRil(&networkOperator.operatorNumeric, operatorNumeric, pRI)) {
- return Void();
- }
- CALL_ONREQUEST(pRI->pCI->requestNumber, &networkOperator,
- sizeof(networkOperator), pRI, mSlotId);
-
- return Void();
-}
-
-Return<void> RadioImpl_1_6::sendCdmaSmsExpectMore(int32_t serial, const CdmaSmsMessage& sms) {
-#if VDBG
- RLOGD("sendCdmaSmsExpectMore: serial %d", serial);
-#endif
- RequestInfo *pRI = android::addRequestToList(serial, mSlotId,
- RIL_REQUEST_CDMA_SEND_SMS_EXPECT_MORE);
- if (pRI == NULL) {
- return Void();
- }
-
- RIL_CDMA_SMS_Message rcsm = {};
- constructCdmaSms(rcsm, sms);
-
- CALL_ONREQUEST(pRI->pCI->requestNumber, &rcsm, sizeof(rcsm), pRI, mSlotId);
+ dispatchVoid(serial, mSlotId, RIL_REQUEST_SET_NETWORK_SELECTION_MANUAL);
return Void();
}
-// Methods from ::android::hardware::radio::V1_6::IRadio follow.
-Return<void> RadioImpl_1_6::sendCdmaSmsExpectMore_1_6(int32_t serial, const CdmaSmsMessage& sms) {
+Return<void> RadioImpl_1_5::sendCdmaSmsExpectMore(int32_t serial, const CdmaSmsMessage& sms) {
#if VDBG
RLOGD("sendCdmaSmsExpectMore: serial %d", serial);
#endif
@@ -4579,7 +3845,7 @@ Return<void> RadioImpl_1_6::sendCdmaSmsExpectMore_1_6(int32_t serial, const Cdma
return Void();
}
-Return<void> RadioImpl_1_6::supplySimDepersonalization(int32_t serial,
+Return<void> RadioImpl_1_5::supplySimDepersonalization(int32_t serial,
V1_5::PersoSubstate persoType, const hidl_string& controlKey) {
#if VDBG
RLOGD("supplySimDepersonalization: serial %d", serial);
@@ -4589,146 +3855,6 @@ Return<void> RadioImpl_1_6::supplySimDepersonalization(int32_t serial,
return Void();
}
-Return<void> RadioImpl_1_6::setNrDualConnectivityState(int32_t serial,
- V1_6::NrDualConnectivityState nrDualConnectivityState) {
-#if VDBG
- RLOGD("setNrDualConnectivityState: serial %d", serial);
-#endif
- dispatchInts(serial, mSlotId, RIL_REQUEST_ENABLE_NR_DUAL_CONNECTIVITY, 1,
- nrDualConnectivityState);
- return Void();
-}
-
-Return<void> RadioImpl_1_6::isNrDualConnectivityEnabled(int32_t serial) {
-#if VDBG
- RLOGD("isNrDualConnectivityEnabled: serial %d", serial);
-#endif
- dispatchVoid(serial, mSlotId, RIL_REQUEST_IS_NR_DUAL_CONNECTIVITY_ENABLED);
- return Void();
-}
-
-Return<void> RadioImpl_1_6::allocatePduSessionId(int32_t serial) {
-#if VDBG
- RLOGD("allocatePduSessionId: serial %d", serial);
-#endif
- dispatchVoid(serial, mSlotId, RIL_REQUEST_ALLOCATE_PDU_SESSION_ID);
- return Void();
-}
-
-Return<void> RadioImpl_1_6::releasePduSessionId(int32_t serial, int32_t id) {
-#if VDBG
- RLOGD("releasePduSessionId: serial %d, pduSessionId: %d", serial, id);
-#endif
- dispatchVoid(serial, mSlotId, RIL_REQUEST_RELEASE_PDU_SESSION_ID);
- return Void();
-}
-
-Return<void> RadioImpl_1_6::startHandover(int32_t serial, int32_t callId) {
-#if VDBG
- RLOGD("startHandover: serial %d, callId: %d", serial, callId);
-#endif
- dispatchVoid(serial, mSlotId, RIL_REQUEST_START_HANDOVER);
- return Void();
-}
-
-Return<void> RadioImpl_1_6::cancelHandover(int32_t serial, int32_t callId) {
-#if VDBG
- RLOGD("cancelHandover: serial %d, callId: %d", serial, callId);
-#endif
- dispatchVoid(serial, mSlotId, RIL_REQUEST_CANCEL_HANDOVER);
- return Void();
-}
-
-
-Return<void> RadioImpl_1_6::setDataThrottling(int32_t serial, V1_6::DataThrottlingAction dataThrottlingAction, int64_t completionDurationMillis) {
- #if VDBG
- RLOGD("OemHookImpl::sendRequestRaw: serial %d", serial);
- #endif
- dispatchInts(serial, mSlotId, RIL_REQUEST_SET_DATA_THROTTLING, 2,
- dataThrottlingAction, completionDurationMillis);
- return Void();
-}
-
-Return<void> RadioImpl_1_6::getSystemSelectionChannels(int32_t serial) {
-#if VDBG
- RLOGD("getSystemSelectionChannels: serial %d", serial);
-#endif
- dispatchVoid(serial, mSlotId, RIL_REQUEST_GET_SYSTEM_SELECTION_CHANNELS);
- return Void();
-}
-
-Return<void> RadioImpl_1_6::getSlicingConfig(int32_t serial) {
-#if VDBG
- RLOGD("getSlicingConfig: serial %d", serial);
-#endif
- dispatchVoid(serial, mSlotId, RIL_REQUEST_GET_SLICING_CONFIG);
- return Void();
-}
-
-Return<void> RadioImpl_1_6::setCarrierInfoForImsiEncryption_1_6(
- int32_t serial, const V1_6::ImsiEncryptionInfo& data) {
-#if VDBG
- RLOGD("setCarrierInfoForImsiEncryption_1_6: serial %d", serial);
-#endif
- RequestInfo* pRI = android::addRequestToList(serial, mSlotId,
- RIL_REQUEST_SET_CARRIER_INFO_IMSI_ENCRYPTION);
- if (pRI == NULL) {
- return Void();
- }
-
- RIL_CarrierInfoForImsiEncryption_v16 imsiEncryption = {};
-
- if (!copyHidlStringToRil(&imsiEncryption.mnc, data.base.mnc, pRI)) {
- return Void();
- }
- if (!copyHidlStringToRil(&imsiEncryption.mcc, data.base.mcc, pRI)) {
- memsetAndFreeStrings(1, imsiEncryption.mnc);
- return Void();
- }
- if (!copyHidlStringToRil(&imsiEncryption.keyIdentifier, data.base.keyIdentifier, pRI)) {
- memsetAndFreeStrings(2, imsiEncryption.mnc, imsiEncryption.mcc);
- return Void();
- }
- imsiEncryption.carrierKeyLength = data.base.carrierKey.size();
- imsiEncryption.carrierKey = new uint8_t[imsiEncryption.carrierKeyLength];
- memcpy(imsiEncryption.carrierKey, data.base.carrierKey.data(), imsiEncryption.carrierKeyLength);
- imsiEncryption.expirationTime = data.base.expirationTime;
- imsiEncryption.keyType = (RIL_PublicKeyType)data.keyType;
-
- CALL_ONREQUEST(pRI->pCI->requestNumber, &imsiEncryption,
- sizeof(RIL_CarrierInfoForImsiEncryption_v16), pRI, mSlotId);
- delete (imsiEncryption.carrierKey);
- return Void();
-}
-
-
-Return<void> RadioImpl_1_6::getSimPhonebookRecords(int32_t serial) {
-#if VDBG
- RLOGD("getSimPhonebookRecords: serial %d", serial);
-#endif
- dispatchVoid(serial, mSlotId, RIL_REQUEST_GET_SIM_PHONEBOOK_RECORDS);
- return Void();
-}
-
-Return<void> RadioImpl_1_6::getSimPhonebookCapacity(int32_t serial) {
-#if VDBG
- RLOGD("getSimPhonebookCapacity: serial %d", serial);
-#endif
- dispatchVoid(serial, mSlotId, RIL_REQUEST_GET_SIM_PHONEBOOK_CAPACITY);
- return Void();
-}
-
-Return<void> RadioImpl_1_6::updateSimPhonebookRecords(
- int32_t serial,
- const ::android::hardware::radio::V1_6::PhonebookRecordInfo& recordInfo) {
-#if VDBG
- RLOGD("updateSimPhonebookRecords: serial %d", serial);
-#endif
- dispatchVoid(serial, mSlotId, RIL_REQUEST_UPDATE_SIM_PHONEBOOK_RECORDS);
- return Void();
-}
-
-
// OEM hook methods:
Return<void> OemHookImpl::setResponseFunctions(
const ::android::sp<IOemHookResponse>& oemHookResponseParam,
@@ -4737,7 +3863,7 @@ Return<void> OemHookImpl::setResponseFunctions(
RLOGD("OemHookImpl::setResponseFunctions");
#endif
- pthread_rwlock_t *radioServiceRwlockPtr = radio_1_6::getRadioServiceRwlock(mSlotId);
+ pthread_rwlock_t *radioServiceRwlockPtr = radio_1_5::getRadioServiceRwlock(mSlotId);
int ret = pthread_rwlock_wrlock(radioServiceRwlockPtr);
assert(ret == 0);
@@ -4774,7 +3900,7 @@ Return<void> OemHookImpl::sendRequestStrings(int32_t serial,
* responses for those requests coming back from the vendor code.
**************************************************************************************************/
-void radio_1_6::acknowledgeRequest(int slotId, int serial) {
+void radio_1_5::acknowledgeRequest(int slotId, int serial) {
if (radioService[slotId]->mRadioResponse != NULL) {
Return<void> retStatus = radioService[slotId]->mRadioResponse->acknowledgeRequest(serial);
radioService[slotId]->checkReturnStatus(retStatus);
@@ -4797,21 +3923,6 @@ void populateResponseInfo(RadioResponseInfo& responseInfo, int serial, int respo
responseInfo.error = (RadioError) e;
}
-void populateResponseInfo_1_6(
- ::android::hardware::radio::V1_6::RadioResponseInfo &responseInfo,
- int serial, int responseType, RIL_Errno e) {
- responseInfo.serial = serial;
- switch (responseType) {
- case RESPONSE_SOLICITED:
- responseInfo.type = RadioResponseType::SOLICITED;
- break;
- case RESPONSE_SOLICITED_ACK_EXP:
- responseInfo.type = RadioResponseType::SOLICITED_ACK_EXP;
- break;
- }
- responseInfo.error = (::android::hardware::radio::V1_6::RadioError)e;
-}
-
int responseIntOrEmpty(RadioResponseInfo& responseInfo, int serial, int responseType, RIL_Errno e,
void *response, size_t responseLen) {
populateResponseInfo(responseInfo, serial, responseType, e);
@@ -4846,55 +3957,36 @@ int responseInt(RadioResponseInfo& responseInfo, int serial, int responseType, R
return ret;
}
-int responseInt_1_6(::android::hardware::radio::V1_6::RadioResponseInfo &responseInfo, int serial, int responseType, RIL_Errno e,
- void *response, size_t responseLen) {
- populateResponseInfo_1_6(responseInfo, serial, responseType, e);
- int ret = -1;
-
- if (response == NULL || responseLen != sizeof(int)) {
- RLOGE("responseInt_1_6: Invalid response");
- if (e == RIL_E_SUCCESS) responseInfo.error = ::android::hardware::radio::V1_6::RadioError::INVALID_RESPONSE;
- } else {
- int *p_int = (int *) response;
- ret = p_int[0];
- }
- return ret;
-}
-
-int radio_1_6::getIccCardStatusResponse(int slotId,
+int radio_1_5::getIccCardStatusResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
-#if VDBG
- RLOGD("getIccCardStatusResponse: serial %d", serial);
-#endif
- if (radioService[slotId]->mRadioResponseV1_5 != NULL
- || radioService[slotId]->mRadioResponseV1_4 != NULL
+ if (radioService[slotId]->mRadioResponseV1_4 != NULL
|| radioService[slotId]->mRadioResponseV1_2 != NULL
|| radioService[slotId]->mRadioResponse != NULL) {
RadioResponseInfo responseInfo = {};
populateResponseInfo(responseInfo, serial, responseType, e);
CardStatus cardStatus = {CardState::ABSENT, PinState::UNKNOWN, -1, -1, -1, {}};
- RIL_AppStatus *rilAppStatus = NULL;
- RIL_CardStatus_v1_5 *p_cur = ((RIL_CardStatus_v1_5 *) response);
- if (response == NULL || responseLen != sizeof(RIL_CardStatus_v1_5)
- || p_cur->base.base.base.gsm_umts_subscription_app_index >= p_cur->base.base.base.num_applications
- || p_cur->base.base.base.cdma_subscription_app_index >= p_cur->base.base.base.num_applications
- || p_cur->base.base.base.ims_subscription_app_index >= p_cur->base.base.base.num_applications) {
+ RIL_CardStatus_v6 *p_cur = ((RIL_CardStatus_v6 *) response);
+ if (response == NULL || responseLen != sizeof(RIL_CardStatus_v6)
+ || p_cur->gsm_umts_subscription_app_index >= p_cur->num_applications
+ || p_cur->cdma_subscription_app_index >= p_cur->num_applications
+ || p_cur->ims_subscription_app_index >= p_cur->num_applications) {
RLOGE("getIccCardStatusResponse: Invalid response");
if (e == RIL_E_SUCCESS) responseInfo.error = RadioError::INVALID_RESPONSE;
} else {
- cardStatus.cardState = (CardState) p_cur->base.base.base.card_state;
- cardStatus.universalPinState = (PinState) p_cur->base.base.base.universal_pin_state;
- cardStatus.gsmUmtsSubscriptionAppIndex = p_cur->base.base.base.gsm_umts_subscription_app_index;
- cardStatus.cdmaSubscriptionAppIndex = p_cur->base.base.base.cdma_subscription_app_index;
- cardStatus.imsSubscriptionAppIndex = p_cur->base.base.base.ims_subscription_app_index;
- rilAppStatus = p_cur->base.base.base.applications;
- cardStatus.applications.resize(p_cur->base.base.base.num_applications);
+ cardStatus.cardState = (CardState) p_cur->card_state;
+ cardStatus.universalPinState = (PinState) p_cur->universal_pin_state;
+ cardStatus.gsmUmtsSubscriptionAppIndex = p_cur->gsm_umts_subscription_app_index;
+ cardStatus.cdmaSubscriptionAppIndex = p_cur->cdma_subscription_app_index;
+ cardStatus.imsSubscriptionAppIndex = p_cur->ims_subscription_app_index;
+
+ RIL_AppStatus *rilAppStatus = p_cur->applications;
+ cardStatus.applications.resize(p_cur->num_applications);
AppStatus *appStatus = cardStatus.applications.data();
#if VDBG
- RLOGD("getIccCardStatusResponse: num_applications %d", p_cur->base.base.base.num_applications);
+ RLOGD("getIccCardStatusResponse: num_applications %d", p_cur->num_applications);
#endif
- for (int i = 0; i < p_cur->base.base.base.num_applications; i++) {
+ for (int i = 0; i < p_cur->num_applications; i++) {
appStatus[i].appType = (AppType) rilAppStatus[i].app_type;
appStatus[i].appState = (AppState) rilAppStatus[i].app_state;
appStatus[i].persoSubstate = (PersoSubstate) rilAppStatus[i].perso_substate;
@@ -4906,43 +3998,12 @@ int radio_1_6::getIccCardStatusResponse(int slotId,
appStatus[i].pin2 = (PinState) rilAppStatus[i].pin2;
}
}
- if (radioService[slotId]->mRadioResponseV1_5 != NULL) {
- ::android::hardware::radio::V1_2::CardStatus cardStatusV1_2;
- ::android::hardware::radio::V1_4::CardStatus cardStatusV1_4;
- ::android::hardware::radio::V1_5::CardStatus cardStatusV1_5;
- cardStatusV1_2.base = cardStatus;
- cardStatusV1_2.physicalSlotId = -1;
- cardStatusV1_2.iccid = convertCharPtrToHidlString(p_cur->base.base.iccid);
- cardStatusV1_4.base = cardStatusV1_2;
- cardStatusV1_5.base = cardStatusV1_4;
- cardStatusV1_5.applications.resize(p_cur->base.base.base.num_applications);
- for (int i = 0; i < p_cur->base.base.base.num_applications; i++) {
- cardStatusV1_5.applications[i].base.appType = (AppType) rilAppStatus[i].app_type;
- cardStatusV1_5.applications[i].base.appState = (AppState) rilAppStatus[i].app_state;
- cardStatusV1_5.applications[i].base.persoSubstate = (PersoSubstate) rilAppStatus[i].perso_substate;
- cardStatusV1_5.applications[i].base.aidPtr = convertCharPtrToHidlString(rilAppStatus[i].aid_ptr);
- cardStatusV1_5.applications[i].base.appLabelPtr = convertCharPtrToHidlString(
- rilAppStatus[i].app_label_ptr);
- cardStatusV1_5.applications[i].base.pin1Replaced = rilAppStatus[i].pin1_replaced;
- cardStatusV1_5.applications[i].base.pin1 = (PinState) rilAppStatus[i].pin1;
- cardStatusV1_5.applications[i].base.pin2 = (PinState) rilAppStatus[i].pin2;
- cardStatusV1_5.applications[i].persoSubstate = (V1_5::PersoSubstate)rilAppStatus[i].perso_substate;
- }
- // If POWER_DOWN then set applications to empty
- if (radioService[slotId]->mSimCardPowerState == V1_1::CardPowerState::POWER_DOWN) {
- RLOGD("getIccCardStatusResponse: state is POWER_DOWN so clearing apps");
- cardStatusV1_5.applications = {};
- }
- Return<void> retStatus = radioService[slotId]->mRadioResponseV1_5->
- getIccCardStatusResponse_1_5(responseInfo, cardStatusV1_5);
- radioService[slotId]->checkReturnStatus(retStatus);
- } else if (radioService[slotId]->mRadioResponseV1_4 != NULL) {
+ if (radioService[slotId]->mRadioResponseV1_4 != NULL) {
::android::hardware::radio::V1_2::CardStatus cardStatusV1_2;
::android::hardware::radio::V1_4::CardStatus cardStatusV1_4;
cardStatusV1_2.base = cardStatus;
cardStatusV1_2.physicalSlotId = -1;
- cardStatusV1_2.iccid = convertCharPtrToHidlString(p_cur->base.base.iccid);
cardStatusV1_4.base = cardStatusV1_2;
Return<void> retStatus = radioService[slotId]->mRadioResponseV1_4->
getIccCardStatusResponse_1_4(responseInfo, cardStatusV1_4);
@@ -4951,7 +4012,6 @@ int radio_1_6::getIccCardStatusResponse(int slotId,
::android::hardware::radio::V1_2::CardStatus cardStatusV1_2;
cardStatusV1_2.base = cardStatus;
cardStatusV1_2.physicalSlotId = -1;
- cardStatusV1_2.iccid = convertCharPtrToHidlString(p_cur->base.base.iccid);
Return<void> retStatus = radioService[slotId]->mRadioResponseV1_3->
getIccCardStatusResponse_1_2(responseInfo, cardStatusV1_2);
radioService[slotId]->checkReturnStatus(retStatus);
@@ -4959,7 +4019,6 @@ int radio_1_6::getIccCardStatusResponse(int slotId,
::android::hardware::radio::V1_2::CardStatus cardStatusV1_2;
cardStatusV1_2.base = cardStatus;
cardStatusV1_2.physicalSlotId = -1;
- cardStatusV1_2.iccid = convertCharPtrToHidlString(p_cur->base.base.iccid);
Return<void> retStatus = radioService[slotId]->mRadioResponseV1_2->
getIccCardStatusResponse_1_2(responseInfo, cardStatusV1_2);
radioService[slotId]->checkReturnStatus(retStatus);
@@ -4972,10 +4031,11 @@ int radio_1_6::getIccCardStatusResponse(int slotId,
} else {
RLOGE("getIccCardStatusResponse: radioService[%d]->mRadioResponse == NULL", slotId);
}
+
return 0;
}
-int radio_1_6::supplyIccPinForAppResponse(int slotId,
+int radio_1_5::supplyIccPinForAppResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -4997,7 +4057,7 @@ int radio_1_6::supplyIccPinForAppResponse(int slotId,
return 0;
}
-int radio_1_6::supplyIccPukForAppResponse(int slotId,
+int radio_1_5::supplyIccPukForAppResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -5018,7 +4078,7 @@ int radio_1_6::supplyIccPukForAppResponse(int slotId,
return 0;
}
-int radio_1_6::supplyIccPin2ForAppResponse(int slotId,
+int radio_1_5::supplyIccPin2ForAppResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -5039,7 +4099,7 @@ int radio_1_6::supplyIccPin2ForAppResponse(int slotId,
return 0;
}
-int radio_1_6::supplyIccPuk2ForAppResponse(int slotId,
+int radio_1_5::supplyIccPuk2ForAppResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -5060,7 +4120,7 @@ int radio_1_6::supplyIccPuk2ForAppResponse(int slotId,
return 0;
}
-int radio_1_6::changeIccPinForAppResponse(int slotId,
+int radio_1_5::changeIccPinForAppResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -5081,7 +4141,7 @@ int radio_1_6::changeIccPinForAppResponse(int slotId,
return 0;
}
-int radio_1_6::changeIccPin2ForAppResponse(int slotId,
+int radio_1_5::changeIccPin2ForAppResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -5102,7 +4162,7 @@ int radio_1_6::changeIccPin2ForAppResponse(int slotId,
return 0;
}
-int radio_1_6::supplyNetworkDepersonalizationResponse(int slotId,
+int radio_1_5::supplyNetworkDepersonalizationResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -5123,7 +4183,7 @@ int radio_1_6::supplyNetworkDepersonalizationResponse(int slotId,
return 0;
}
-int radio_1_6::getCurrentCallsResponse(int slotId,
+int radio_1_5::getCurrentCallsResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -5181,7 +4241,7 @@ int radio_1_6::getCurrentCallsResponse(int slotId,
return 0;
}
-int radio_1_6::dialResponse(int slotId,
+int radio_1_5::dialResponse(int slotId,
int responseType, int serial, RIL_Errno e, void *response,
size_t responseLen) {
#if VDBG
@@ -5200,7 +4260,7 @@ int radio_1_6::dialResponse(int slotId,
return 0;
}
-int radio_1_6::getIMSIForAppResponse(int slotId,
+int radio_1_5::getIMSIForAppResponse(int slotId,
int responseType, int serial, RIL_Errno e, void *response,
size_t responseLen) {
#if VDBG
@@ -5221,7 +4281,7 @@ int radio_1_6::getIMSIForAppResponse(int slotId,
return 0;
}
-int radio_1_6::hangupConnectionResponse(int slotId,
+int radio_1_5::hangupConnectionResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -5242,7 +4302,7 @@ int radio_1_6::hangupConnectionResponse(int slotId,
return 0;
}
-int radio_1_6::hangupWaitingOrBackgroundResponse(int slotId,
+int radio_1_5::hangupWaitingOrBackgroundResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -5264,7 +4324,7 @@ int radio_1_6::hangupWaitingOrBackgroundResponse(int slotId,
return 0;
}
-int radio_1_6::hangupForegroundResumeBackgroundResponse(int slotId, int responseType, int serial,
+int radio_1_5::hangupForegroundResumeBackgroundResponse(int slotId, int responseType, int serial,
RIL_Errno e, void *response,
size_t responseLen) {
#if VDBG
@@ -5286,7 +4346,7 @@ int radio_1_6::hangupForegroundResumeBackgroundResponse(int slotId, int response
return 0;
}
-int radio_1_6::switchWaitingOrHoldingAndActiveResponse(int slotId, int responseType, int serial,
+int radio_1_5::switchWaitingOrHoldingAndActiveResponse(int slotId, int responseType, int serial,
RIL_Errno e, void *response,
size_t responseLen) {
#if VDBG
@@ -5308,7 +4368,7 @@ int radio_1_6::switchWaitingOrHoldingAndActiveResponse(int slotId, int responseT
return 0;
}
-int radio_1_6::conferenceResponse(int slotId, int responseType,
+int radio_1_5::conferenceResponse(int slotId, int responseType,
int serial, RIL_Errno e, void *response, size_t responseLen) {
#if VDBG
RLOGD("conferenceResponse: serial %d", serial);
@@ -5328,7 +4388,7 @@ int radio_1_6::conferenceResponse(int slotId, int responseType,
return 0;
}
-int radio_1_6::rejectCallResponse(int slotId, int responseType,
+int radio_1_5::rejectCallResponse(int slotId, int responseType,
int serial, RIL_Errno e, void *response, size_t responseLen) {
#if VDBG
RLOGD("rejectCallResponse: serial %d", serial);
@@ -5348,7 +4408,7 @@ int radio_1_6::rejectCallResponse(int slotId, int responseType,
return 0;
}
-int radio_1_6::getLastCallFailCauseResponse(int slotId,
+int radio_1_5::getLastCallFailCauseResponse(int slotId,
int responseType, int serial, RIL_Errno e, void *response,
size_t responseLen) {
#if VDBG
@@ -5387,7 +4447,7 @@ int radio_1_6::getLastCallFailCauseResponse(int slotId,
return 0;
}
-int radio_1_6::getSignalStrengthResponse(int slotId,
+int radio_1_5::getSignalStrengthResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -5397,14 +4457,19 @@ int radio_1_6::getSignalStrengthResponse(int slotId,
if (radioService[slotId]->mRadioResponseV1_4 != NULL) {
RadioResponseInfo responseInfo = {};
populateResponseInfo(responseInfo, serial, responseType, e);
- ::android::hardware::radio::V1_4::SignalStrength signalStrength_1_4 = {};
- if (response == NULL || responseLen != sizeof(RIL_SignalStrength_v12)) {
+ SignalStrength signalStrength = {};
+ if (response == NULL || responseLen != sizeof(RIL_SignalStrength_v10)) {
RLOGE("getSignalStrengthResponse: Invalid response");
if (e == RIL_E_SUCCESS) responseInfo.error = RadioError::INVALID_RESPONSE;
} else {
- convertRilSignalStrengthToHal_1_4(response, responseLen, signalStrength_1_4);
+ convertRilSignalStrengthToHal(response, responseLen, signalStrength);
}
+ ::android::hardware::radio::V1_4::SignalStrength signalStrength_1_4;
+ signalStrength_1_4.gsm = signalStrength.gw;
+ signalStrength_1_4.cdma = signalStrength.cdma;
+ signalStrength_1_4.evdo = signalStrength.evdo;
+ signalStrength_1_4.lte = signalStrength.lte;
//TODO: future implementation needs to fill tdScdma, wcdma and nr signal strength.
Return<void> retStatus = radioService[slotId]->mRadioResponseV1_4->
@@ -5414,7 +4479,7 @@ int radio_1_6::getSignalStrengthResponse(int slotId,
RadioResponseInfo responseInfo = {};
populateResponseInfo(responseInfo, serial, responseType, e);
SignalStrength signalStrength = {};
- if (response == NULL || responseLen != sizeof(RIL_SignalStrength_v12)) {
+ if (response == NULL || responseLen != sizeof(RIL_SignalStrength_v10)) {
RLOGE("getSignalStrengthResponse: Invalid response");
if (e == RIL_E_SUCCESS) responseInfo.error = RadioError::INVALID_RESPONSE;
} else {
@@ -5561,187 +4626,6 @@ void fillCellIdentityResponse(CellIdentity &cellIdentity, RIL_CellIdentity_v16 &
}
}
-void fillCellIdentityResponse_1_5(V1_5::CellIdentity &cellIdentity,
- RIL_CellIdentity_v16 &rilCellIdentity) {
-
- switch (rilCellIdentity.cellInfoType) {
- case RIL_CELL_INFO_TYPE_GSM: {
- V1_5::CellIdentityGsm gsm;
- gsm.base.base.mcc = std::to_string(rilCellIdentity.cellIdentityGsm.mcc);
- gsm.base.base.mnc = ril::util::mnc::decode(rilCellIdentity.cellIdentityGsm.mnc);
- if (gsm.base.base.mcc == "-1") {
- gsm.base.base.mcc = "";
- }
- gsm.base.base.lac = rilCellIdentity.cellIdentityGsm.lac;
- gsm.base.base.cid = rilCellIdentity.cellIdentityGsm.cid;
- gsm.base.base.arfcn = rilCellIdentity.cellIdentityGsm.arfcn;
- gsm.base.base.bsic = rilCellIdentity.cellIdentityGsm.bsic;
- cellIdentity.gsm(gsm);
- break;
- }
-
- case RIL_CELL_INFO_TYPE_WCDMA: {
- V1_5::CellIdentityWcdma wcdma;
- wcdma.base.base.mcc = std::to_string(rilCellIdentity.cellIdentityGsm.mcc);
- wcdma.base.base.mnc = ril::util::mnc::decode(rilCellIdentity.cellIdentityWcdma.mnc);
- if (wcdma.base.base.mcc == "-1") {
- wcdma.base.base.mcc = "";
- }
- wcdma.base.base.lac = rilCellIdentity.cellIdentityWcdma.lac;
- wcdma.base.base.cid = rilCellIdentity.cellIdentityWcdma.cid;
- wcdma.base.base.psc = rilCellIdentity.cellIdentityWcdma.psc;
- wcdma.base.base.uarfcn = rilCellIdentity.cellIdentityWcdma.uarfcn;
- cellIdentity.wcdma(wcdma);
- break;
- }
-
- case RIL_CELL_INFO_TYPE_CDMA: {
- V1_2::CellIdentityCdma cdma;
- cdma.base.networkId = rilCellIdentity.cellIdentityCdma.networkId;
- cdma.base.systemId = rilCellIdentity.cellIdentityCdma.systemId;
- cdma.base.baseStationId =
- rilCellIdentity.cellIdentityCdma.basestationId;
- cdma.base.longitude = rilCellIdentity.cellIdentityCdma.longitude;
- cdma.base.latitude = rilCellIdentity.cellIdentityCdma.latitude;
- cellIdentity.cdma(cdma);
- break;
- }
-
- case RIL_CELL_INFO_TYPE_LTE: {
- V1_5::CellIdentityLte lte;
- lte.base.base.mcc = std::to_string(rilCellIdentity.cellIdentityGsm.mcc);
- lte.base.base.mnc = ril::util::mnc::decode(rilCellIdentity.cellIdentityLte.mnc);
- if (lte.base.base.mcc == "-1") {
- lte.base.base.mcc = "";
- }
- lte.base.base.ci = rilCellIdentity.cellIdentityLte.ci;
- lte.base.base.pci = rilCellIdentity.cellIdentityLte.pci;
- lte.base.base.tac = rilCellIdentity.cellIdentityLte.tac;
- lte.base.base.earfcn = rilCellIdentity.cellIdentityLte.earfcn;
- cellIdentity.lte(lte);
- break;
- }
-
- case RIL_CELL_INFO_TYPE_TD_SCDMA: {
- V1_5::CellIdentityTdscdma tdscdma;
- tdscdma.base.base.mcc = std::to_string(rilCellIdentity.cellIdentityGsm.mcc);
- tdscdma.base.base.mnc = ril::util::mnc::decode(rilCellIdentity.cellIdentityTdscdma.mnc);
- if (tdscdma.base.base.mcc == "-1") {
- tdscdma.base.base.mcc = "";
- }
- tdscdma.base.base.lac = rilCellIdentity.cellIdentityTdscdma.lac;
- tdscdma.base.base.cid = rilCellIdentity.cellIdentityTdscdma.cid;
- tdscdma.base.base.cpid = rilCellIdentity.cellIdentityTdscdma.cpid;
- cellIdentity.tdscdma(tdscdma);
- break;
- }
-
- default: {
- break;
- }
- }
-}
-
-void fillCellIdentityResponse_1_2(V1_2::CellIdentity &cellIdentity,
- RIL_CellIdentity_v1_2 &rilCellIdentity) {
- cellIdentity.cellIdentityGsm.resize(0);
- cellIdentity.cellIdentityWcdma.resize(0);
- cellIdentity.cellIdentityCdma.resize(0);
- cellIdentity.cellIdentityTdscdma.resize(0);
- cellIdentity.cellIdentityLte.resize(0);
- cellIdentity.cellInfoType = (CellInfoType)rilCellIdentity.cellInfoType;
- switch(rilCellIdentity.cellInfoType) {
-
- case RIL_CELL_INFO_TYPE_GSM: {
- cellIdentity.cellIdentityGsm.resize(1);
- cellIdentity.cellIdentityGsm[0].base.mcc =
- std::to_string(rilCellIdentity.cellIdentityGsm.mcc);
- cellIdentity.cellIdentityGsm[0].base.mnc =
- ril::util::mnc::decode(rilCellIdentity.cellIdentityGsm.mnc);
-
- if (cellIdentity.cellIdentityGsm[0].base.mcc == "-1") {
- cellIdentity.cellIdentityGsm[0].base.mcc = "";
- }
-
- cellIdentity.cellIdentityGsm[0].base.lac = rilCellIdentity.cellIdentityGsm.lac;
- cellIdentity.cellIdentityGsm[0].base.cid = rilCellIdentity.cellIdentityGsm.cid;
- cellIdentity.cellIdentityGsm[0].base.arfcn = rilCellIdentity.cellIdentityGsm.arfcn;
- cellIdentity.cellIdentityGsm[0].base.bsic = rilCellIdentity.cellIdentityGsm.bsic;
- break;
- }
-
- case RIL_CELL_INFO_TYPE_WCDMA: {
- cellIdentity.cellIdentityWcdma.resize(1);
- cellIdentity.cellIdentityWcdma[0].base.mcc =
- std::to_string(rilCellIdentity.cellIdentityWcdma.mcc);
- cellIdentity.cellIdentityWcdma[0].base.mnc =
- ril::util::mnc::decode(rilCellIdentity.cellIdentityWcdma.mnc);
-
- if (cellIdentity.cellIdentityWcdma[0].base.mcc == "-1") {
- cellIdentity.cellIdentityWcdma[0].base.mcc = "";
- }
-
- cellIdentity.cellIdentityWcdma[0].base.lac = rilCellIdentity.cellIdentityWcdma.lac;
- cellIdentity.cellIdentityWcdma[0].base.cid = rilCellIdentity.cellIdentityWcdma.cid;
- cellIdentity.cellIdentityWcdma[0].base.psc = rilCellIdentity.cellIdentityWcdma.psc;
- cellIdentity.cellIdentityWcdma[0].base.uarfcn = rilCellIdentity.cellIdentityWcdma.uarfcn;
- break;
- }
-
- case RIL_CELL_INFO_TYPE_CDMA: {
- cellIdentity.cellIdentityCdma.resize(1);
- cellIdentity.cellIdentityCdma[0].base.networkId = rilCellIdentity.cellIdentityCdma.networkId;
- cellIdentity.cellIdentityCdma[0].base.systemId = rilCellIdentity.cellIdentityCdma.systemId;
- cellIdentity.cellIdentityCdma[0].base.baseStationId =
- rilCellIdentity.cellIdentityCdma.basestationId;
- cellIdentity.cellIdentityCdma[0].base.longitude = rilCellIdentity.cellIdentityCdma.longitude;
- cellIdentity.cellIdentityCdma[0].base.latitude = rilCellIdentity.cellIdentityCdma.latitude;
- break;
- }
-
- case RIL_CELL_INFO_TYPE_LTE: {
- cellIdentity.cellIdentityLte.resize(1);
- cellIdentity.cellIdentityLte[0].base.mcc =
- std::to_string(rilCellIdentity.cellIdentityLte.mcc);
- cellIdentity.cellIdentityLte[0].base.mnc =
- ril::util::mnc::decode(rilCellIdentity.cellIdentityLte.mnc);
-
- if (cellIdentity.cellIdentityLte[0].base.mcc == "-1") {
- cellIdentity.cellIdentityLte[0].base.mcc = "";
- }
-
- cellIdentity.cellIdentityLte[0].base.ci = rilCellIdentity.cellIdentityLte.ci;
- cellIdentity.cellIdentityLte[0].base.pci = rilCellIdentity.cellIdentityLte.pci;
- cellIdentity.cellIdentityLte[0].base.tac = rilCellIdentity.cellIdentityLte.tac;
- cellIdentity.cellIdentityLte[0].base.earfcn = rilCellIdentity.cellIdentityLte.earfcn;
- cellIdentity.cellIdentityLte[0].bandwidth = rilCellIdentity.cellIdentityLte.bandwidth;
- break;
- }
-
- case RIL_CELL_INFO_TYPE_TD_SCDMA: {
- cellIdentity.cellIdentityTdscdma.resize(1);
- cellIdentity.cellIdentityTdscdma[0].base.mcc =
- std::to_string(rilCellIdentity.cellIdentityTdscdma.mcc);
- cellIdentity.cellIdentityTdscdma[0].base.mnc =
- ril::util::mnc::decode(rilCellIdentity.cellIdentityTdscdma.mnc);
-
- if (cellIdentity.cellIdentityTdscdma[0].base.mcc == "-1") {
- cellIdentity.cellIdentityTdscdma[0].base.mcc = "";
- }
-
- cellIdentity.cellIdentityTdscdma[0].base.lac = rilCellIdentity.cellIdentityTdscdma.lac;
- cellIdentity.cellIdentityTdscdma[0].base.cid = rilCellIdentity.cellIdentityTdscdma.cid;
- cellIdentity.cellIdentityTdscdma[0].base.cpid = rilCellIdentity.cellIdentityTdscdma.cpid;
- cellIdentity.cellIdentityTdscdma[0].uarfcn = rilCellIdentity.cellIdentityTdscdma.uarfcn;
- break;
- }
-
- default: {
- break;
- }
- }
-}
-
int convertResponseStringEntryToInt(char **response, int index, int numStrings) {
if ((response != NULL) && (numStrings > index) && (response[index] != NULL)) {
return atoi(response[index]);
@@ -5764,7 +4648,7 @@ int convertResponseHexStringEntryToInt(char **response, int index, int numString
* Response is a "char **".
* First and Second entries are in hex string format
* and rest are integers represented in ascii format. */
-void fillCellIdentityFromVoiceRegStateResponseString(V1_5::CellIdentity &cellIdentity,
+void fillCellIdentityFromVoiceRegStateResponseString(CellIdentity &cellIdentity,
int numStrings, char** response) {
RIL_CellIdentity_v16 rilCellIdentity;
@@ -5781,14 +4665,6 @@ void fillCellIdentityFromVoiceRegStateResponseString(V1_5::CellIdentity &cellIde
/* valid CID are hexstrings in the range 0x00000000 - 0xffffffff */
rilCellIdentity.cellIdentityGsm.cid =
convertResponseHexStringEntryToInt(response, 2, numStrings);
-
- if (numStrings > 15) {
- rilCellIdentity.cellIdentityGsm.mcc =
- convertResponseStringEntryToInt(response, 15, numStrings);
-
- rilCellIdentity.cellIdentityGsm.mnc =
- convertResponseStringEntryToInt(response, 16, numStrings);
- }
break;
}
@@ -5802,14 +4678,6 @@ void fillCellIdentityFromVoiceRegStateResponseString(V1_5::CellIdentity &cellIde
convertResponseHexStringEntryToInt(response, 2, numStrings);
rilCellIdentity.cellIdentityWcdma.psc =
convertResponseStringEntryToInt(response, 14, numStrings);
-
- if (numStrings > 15) {
- rilCellIdentity.cellIdentityGsm.mcc =
- convertResponseStringEntryToInt(response, 15, numStrings);
-
- rilCellIdentity.cellIdentityGsm.mnc =
- convertResponseStringEntryToInt(response, 16, numStrings);
- }
break;
}
@@ -5821,14 +4689,6 @@ void fillCellIdentityFromVoiceRegStateResponseString(V1_5::CellIdentity &cellIde
/* valid CID are hexstrings in the range 0x00000000 - 0xffffffff */
rilCellIdentity.cellIdentityTdscdma.cid =
convertResponseHexStringEntryToInt(response, 2, numStrings);
-
- if (numStrings > 15) {
- rilCellIdentity.cellIdentityGsm.mcc =
- convertResponseStringEntryToInt(response, 15, numStrings);
-
- rilCellIdentity.cellIdentityGsm.mnc =
- convertResponseStringEntryToInt(response, 16, numStrings);
- }
break;
}
@@ -5855,14 +4715,6 @@ void fillCellIdentityFromVoiceRegStateResponseString(V1_5::CellIdentity &cellIde
/* valid CID are hexstrings in the range 0x00000000 - 0xffffffff */
rilCellIdentity.cellIdentityLte.ci =
convertResponseHexStringEntryToInt(response, 2, numStrings);
-
- if (numStrings > 15) {
- rilCellIdentity.cellIdentityGsm.mcc =
- convertResponseStringEntryToInt(response, 15, numStrings);
-
- rilCellIdentity.cellIdentityGsm.mnc =
- convertResponseStringEntryToInt(response, 16, numStrings);
- }
break;
}
@@ -5871,117 +4723,7 @@ void fillCellIdentityFromVoiceRegStateResponseString(V1_5::CellIdentity &cellIde
}
}
- fillCellIdentityResponse_1_5(cellIdentity, rilCellIdentity);
-}
-
-void fillCellIdentityFromVoiceRegStateResponseString_1_2(V1_2::CellIdentity &cellIdentity,
- int numStrings, char** response) {
- RIL_CellIdentity_v1_2 rilCellIdentity;
- memset(&rilCellIdentity, -1, sizeof(RIL_CellIdentity_v1_2));
-
- rilCellIdentity.cellInfoType = getCellInfoTypeRadioTechnology(response[3]);
-
- switch(rilCellIdentity.cellInfoType) {
- case RIL_CELL_INFO_TYPE_GSM: {
- /* valid LAC are hexstrings in the range 0x0000 - 0xffff */
- rilCellIdentity.cellIdentityGsm.lac =
- convertResponseHexStringEntryToInt(response, 1, numStrings);
-
- /* valid CID are hexstrings in the range 0x00000000 - 0xffffffff */
- rilCellIdentity.cellIdentityGsm.cid =
- convertResponseHexStringEntryToInt(response, 2, numStrings);
-
- if (numStrings > 15) {
- rilCellIdentity.cellIdentityGsm.mcc =
- convertResponseStringEntryToInt(response, 15, numStrings);
-
- rilCellIdentity.cellIdentityGsm.mnc =
- convertResponseStringEntryToInt(response, 16, numStrings);
- }
- break;
- }
-
- case RIL_CELL_INFO_TYPE_WCDMA: {
- /* valid LAC are hexstrings in the range 0x0000 - 0xffff */
- rilCellIdentity.cellIdentityWcdma.lac =
- convertResponseHexStringEntryToInt(response, 1, numStrings);
-
- /* valid CID are hexstrings in the range 0x00000000 - 0xffffffff */
- rilCellIdentity.cellIdentityWcdma.cid =
- convertResponseHexStringEntryToInt(response, 2, numStrings);
- rilCellIdentity.cellIdentityWcdma.psc =
- convertResponseStringEntryToInt(response, 14, numStrings);
-
- if (numStrings > 15) {
- rilCellIdentity.cellIdentityWcdma.mcc =
- convertResponseStringEntryToInt(response, 15, numStrings);
-
- rilCellIdentity.cellIdentityWcdma.mnc =
- convertResponseStringEntryToInt(response, 16, numStrings);
- }
- break;
- }
-
- case RIL_CELL_INFO_TYPE_TD_SCDMA:{
- /* valid LAC are hexstrings in the range 0x0000 - 0xffff */
- rilCellIdentity.cellIdentityTdscdma.lac =
- convertResponseHexStringEntryToInt(response, 1, numStrings);
-
- /* valid CID are hexstrings in the range 0x00000000 - 0xffffffff */
- rilCellIdentity.cellIdentityTdscdma.cid =
- convertResponseHexStringEntryToInt(response, 2, numStrings);
-
- if (numStrings > 15) {
- rilCellIdentity.cellIdentityTdscdma.mcc =
- convertResponseStringEntryToInt(response, 15, numStrings);
-
- rilCellIdentity.cellIdentityTdscdma.mnc =
- convertResponseStringEntryToInt(response, 16, numStrings);
- }
- break;
- }
-
- case RIL_CELL_INFO_TYPE_CDMA:{
- rilCellIdentity.cellIdentityCdma.basestationId =
- convertResponseStringEntryToInt(response, 4, numStrings);
- /* Order of Lat. and Long. swapped between RIL and HIDL interface versions. */
- rilCellIdentity.cellIdentityCdma.latitude =
- convertResponseStringEntryToInt(response, 5, numStrings);
- rilCellIdentity.cellIdentityCdma.longitude =
- convertResponseStringEntryToInt(response, 6, numStrings);
- rilCellIdentity.cellIdentityCdma.systemId =
- convertResponseStringEntryToInt(response, 8, numStrings);
- rilCellIdentity.cellIdentityCdma.networkId =
- convertResponseStringEntryToInt(response, 9, numStrings);
- break;
- }
-
- case RIL_CELL_INFO_TYPE_LTE:{
- /* valid TAC are hexstrings in the range 0x0000 - 0xffff */
- rilCellIdentity.cellIdentityLte.tac =
- convertResponseHexStringEntryToInt(response, 1, numStrings);
-
- /* valid CID are hexstrings in the range 0x00000000 - 0xffffffff */
- rilCellIdentity.cellIdentityLte.ci =
- convertResponseHexStringEntryToInt(response, 2, numStrings);
-
- if (numStrings > 15) {
- rilCellIdentity.cellIdentityLte.mcc =
- convertResponseStringEntryToInt(response, 15, numStrings);
-
- rilCellIdentity.cellIdentityLte.mnc =
- convertResponseStringEntryToInt(response, 16, numStrings);
- }
- rilCellIdentity.cellIdentityLte.bandwidth = INT_MAX;
- break;
- }
-
- default: {
- break;
- }
- }
-
- fillCellIdentityResponse_1_2(cellIdentity, rilCellIdentity);
+ fillCellIdentityResponse(cellIdentity, rilCellIdentity);
}
/* Fill Cell Identity info from Data Registration State Response.
@@ -5989,7 +4731,7 @@ void fillCellIdentityFromVoiceRegStateResponseString_1_2(V1_2::CellIdentity &cel
* Response is a "char **".
* First and Second entries are in hex string format
* and rest are integers represented in ascii format. */
-void fillCellIdentityFromDataRegStateResponseString_1_5(V1_5::CellIdentity &cellIdentity,
+void fillCellIdentityFromDataRegStateResponseString(CellIdentity &cellIdentity,
int numStrings, char** response) {
RIL_CellIdentity_v16 rilCellIdentity;
@@ -6005,18 +4747,6 @@ void fillCellIdentityFromDataRegStateResponseString_1_5(V1_5::CellIdentity &cell
/* valid CID are hexstrings in the range 0x00000000 - 0xffffffff */
rilCellIdentity.cellIdentityGsm.cid =
convertResponseHexStringEntryToInt(response, 2, numStrings);
-
- if (numStrings >= 13) {
- rilCellIdentity.cellIdentityGsm.mcc =
- convertResponseStringEntryToInt(response, 11, numStrings);
-
- rilCellIdentity.cellIdentityGsm.mnc =
- convertResponseStringEntryToInt(response, 12, numStrings);
- } else {
- /* vts check the mcc [0, 999] and mnc [0, 999]. */
- rilCellIdentity.cellIdentityGsm.mnc = 0;
- rilCellIdentity.cellIdentityGsm.mcc = 0;
- }
break;
}
case RIL_CELL_INFO_TYPE_WCDMA: {
@@ -6027,18 +4757,6 @@ void fillCellIdentityFromDataRegStateResponseString_1_5(V1_5::CellIdentity &cell
/* valid CID are hexstrings in the range 0x00000000 - 0xffffffff */
rilCellIdentity.cellIdentityWcdma.cid =
convertResponseHexStringEntryToInt(response, 2, numStrings);
-
- if (numStrings >= 13) {
- rilCellIdentity.cellIdentityWcdma.mcc =
- convertResponseStringEntryToInt(response, 11, numStrings);
-
- rilCellIdentity.cellIdentityWcdma.mnc =
- convertResponseStringEntryToInt(response, 12, numStrings);
- } else {
- /* vts check the mcc [0, 999] and mnc [0, 999]. */
- rilCellIdentity.cellIdentityWcdma.mnc = 0;
- rilCellIdentity.cellIdentityWcdma.mcc = 0;
- }
break;
}
case RIL_CELL_INFO_TYPE_TD_SCDMA:{
@@ -6049,121 +4767,6 @@ void fillCellIdentityFromDataRegStateResponseString_1_5(V1_5::CellIdentity &cell
/* valid CID are hexstrings in the range 0x00000000 - 0xffffffff */
rilCellIdentity.cellIdentityTdscdma.cid =
convertResponseHexStringEntryToInt(response, 2, numStrings);
-
- if (numStrings >= 13) {
- rilCellIdentity.cellIdentityTdscdma.mcc =
- convertResponseStringEntryToInt(response, 11, numStrings);
-
- rilCellIdentity.cellIdentityTdscdma.mnc =
- convertResponseStringEntryToInt(response, 12, numStrings);
- } else {
- /* vts check the mcc [0, 999] and mnc [0, 999]. */
- rilCellIdentity.cellIdentityTdscdma.mnc = 0;
- rilCellIdentity.cellIdentityTdscdma.mcc = 0;
- }
- break;
- }
- case RIL_CELL_INFO_TYPE_LTE: {
- rilCellIdentity.cellIdentityLte.tac =
- convertResponseStringEntryToInt(response, 6, numStrings);
- rilCellIdentity.cellIdentityLte.pci =
- convertResponseStringEntryToInt(response, 7, numStrings);
- rilCellIdentity.cellIdentityLte.ci =
- convertResponseStringEntryToInt(response, 8, numStrings);
-
- if (numStrings >= 13) {
- rilCellIdentity.cellIdentityLte.mcc =
- convertResponseStringEntryToInt(response, 11, numStrings);
-
- rilCellIdentity.cellIdentityLte.mnc =
- convertResponseStringEntryToInt(response, 12, numStrings);
- } else {
- /* vts check the mcc [0, 999] and mnc [0, 999]. */
- rilCellIdentity.cellIdentityLte.mnc = 0;
- rilCellIdentity.cellIdentityLte.mcc = 0;
- }
- break;
- }
- default: {
- break;
- }
- }
-
- fillCellIdentityResponse_1_5(cellIdentity, rilCellIdentity);
-}
-
-void fillCellIdentityFromDataRegStateResponseString_1_2(V1_2::CellIdentity &cellIdentity,
- int numStrings, char** response) {
-
- RIL_CellIdentity_v1_2 rilCellIdentity;
- memset(&rilCellIdentity, -1, sizeof(RIL_CellIdentity_v1_2));
-
- rilCellIdentity.cellInfoType = getCellInfoTypeRadioTechnology(response[3]);
- switch(rilCellIdentity.cellInfoType) {
- case RIL_CELL_INFO_TYPE_GSM: {
- /* valid LAC are hexstrings in the range 0x0000 - 0xffff */
- rilCellIdentity.cellIdentityGsm.lac =
- convertResponseHexStringEntryToInt(response, 1, numStrings);
-
- /* valid CID are hexstrings in the range 0x00000000 - 0xffffffff */
- rilCellIdentity.cellIdentityGsm.cid =
- convertResponseHexStringEntryToInt(response, 2, numStrings);
-
- if (numStrings >= 13) {
- rilCellIdentity.cellIdentityGsm.mcc =
- convertResponseStringEntryToInt(response, 11, numStrings);
-
- rilCellIdentity.cellIdentityGsm.mnc =
- convertResponseStringEntryToInt(response, 12, numStrings);
- } else {
- /* vts check the mcc [0, 999] and mnc [0, 999]. */
- rilCellIdentity.cellIdentityGsm.mnc = 0;
- rilCellIdentity.cellIdentityGsm.mcc = 0;
- }
- break;
- }
- case RIL_CELL_INFO_TYPE_WCDMA: {
- /* valid LAC are hexstrings in the range 0x0000 - 0xffff */
- rilCellIdentity.cellIdentityWcdma.lac =
- convertResponseHexStringEntryToInt(response, 1, numStrings);
-
- /* valid CID are hexstrings in the range 0x00000000 - 0xffffffff */
- rilCellIdentity.cellIdentityWcdma.cid =
- convertResponseHexStringEntryToInt(response, 2, numStrings);
-
- if (numStrings >= 13) {
- rilCellIdentity.cellIdentityWcdma.mcc =
- convertResponseStringEntryToInt(response, 11, numStrings);
-
- rilCellIdentity.cellIdentityWcdma.mnc =
- convertResponseStringEntryToInt(response, 12, numStrings);
- } else {
- /* vts check the mcc [0, 999] and mnc [0, 999]. */
- rilCellIdentity.cellIdentityWcdma.mnc = 0;
- rilCellIdentity.cellIdentityWcdma.mcc = 0;
- }
- break;
- }
- case RIL_CELL_INFO_TYPE_TD_SCDMA: {
- /* valid LAC are hexstrings in the range 0x0000 - 0xffff */
- rilCellIdentity.cellIdentityTdscdma.lac =
- convertResponseHexStringEntryToInt(response, 1, numStrings);
-
- /* valid CID are hexstrings in the range 0x00000000 - 0xffffffff */
- rilCellIdentity.cellIdentityTdscdma.cid =
- convertResponseHexStringEntryToInt(response, 2, numStrings);
-
- if (numStrings >= 13) {
- rilCellIdentity.cellIdentityTdscdma.mcc =
- convertResponseStringEntryToInt(response, 11, numStrings);
-
- rilCellIdentity.cellIdentityTdscdma.mnc =
- convertResponseStringEntryToInt(response, 12, numStrings);
- } else {
- /* vts check the mcc [0, 999] and mnc [0, 999]. */
- rilCellIdentity.cellIdentityTdscdma.mnc = 0;
- rilCellIdentity.cellIdentityTdscdma.mcc = 0;
- }
break;
}
case RIL_CELL_INFO_TYPE_LTE: {
@@ -6173,21 +4776,6 @@ void fillCellIdentityFromDataRegStateResponseString_1_2(V1_2::CellIdentity &cell
convertResponseStringEntryToInt(response, 7, numStrings);
rilCellIdentity.cellIdentityLte.ci =
convertResponseStringEntryToInt(response, 8, numStrings);
-
- if (numStrings >= 13) {
- rilCellIdentity.cellIdentityLte.mcc =
- convertResponseStringEntryToInt(response, 11, numStrings);
-
- rilCellIdentity.cellIdentityLte.mnc =
- convertResponseStringEntryToInt(response, 12, numStrings);
- } else {
- /* vts check the mcc [0, 999] and mnc [0, 999]. */
- rilCellIdentity.cellIdentityLte.mnc = 0;
- rilCellIdentity.cellIdentityLte.mcc = 0;
- }
- break;
- }
- case RIL_CELL_INFO_TYPE_CDMA: {
break;
}
default: {
@@ -6195,123 +4783,17 @@ void fillCellIdentityFromDataRegStateResponseString_1_2(V1_2::CellIdentity &cell
}
}
- fillCellIdentityResponse_1_2(cellIdentity, rilCellIdentity);
-}
-
-void fillCellIdentityFromDataRegStateResponseString(CellIdentity &cellIdentity,
- int numStrings, char** response) {
-
- RIL_CellIdentity_v16 rilCellIdentity;
- memset(&rilCellIdentity, -1, sizeof(RIL_CellIdentity_v16));
-
- rilCellIdentity.cellInfoType = getCellInfoTypeRadioTechnology(response[3]);
- switch(rilCellIdentity.cellInfoType) {
- case RIL_CELL_INFO_TYPE_GSM: {
- /* valid LAC are hexstrings in the range 0x0000 - 0xffff */
- rilCellIdentity.cellIdentityGsm.lac =
- convertResponseHexStringEntryToInt(response, 1, numStrings);
-
- /* valid CID are hexstrings in the range 0x00000000 - 0xffffffff */
- rilCellIdentity.cellIdentityGsm.cid =
- convertResponseHexStringEntryToInt(response, 2, numStrings);
-
- if (numStrings >= 13) {
- rilCellIdentity.cellIdentityGsm.mcc =
- convertResponseStringEntryToInt(response, 11, numStrings);
-
- rilCellIdentity.cellIdentityGsm.mnc =
- convertResponseStringEntryToInt(response, 12, numStrings);
- } else {
- /* vts check the mcc [0, 999] and mnc [0, 999]. */
- rilCellIdentity.cellIdentityGsm.mnc = 0;
- rilCellIdentity.cellIdentityGsm.mcc = 0;
- }
- break;
- }
- case RIL_CELL_INFO_TYPE_WCDMA: {
- /* valid LAC are hexstrings in the range 0x0000 - 0xffff */
- rilCellIdentity.cellIdentityWcdma.lac =
- convertResponseHexStringEntryToInt(response, 1, numStrings);
-
- /* valid CID are hexstrings in the range 0x00000000 - 0xffffffff */
- rilCellIdentity.cellIdentityWcdma.cid =
- convertResponseHexStringEntryToInt(response, 2, numStrings);
-
- if (numStrings >= 13) {
- rilCellIdentity.cellIdentityWcdma.mcc =
- convertResponseStringEntryToInt(response, 11, numStrings);
-
- rilCellIdentity.cellIdentityWcdma.mnc =
- convertResponseStringEntryToInt(response, 12, numStrings);
- } else {
- /* vts check the mcc [0, 999] and mnc [0, 999]. */
- rilCellIdentity.cellIdentityWcdma.mnc = 0;
- rilCellIdentity.cellIdentityWcdma.mcc = 0;
- }
-
- break;
- }
- case RIL_CELL_INFO_TYPE_TD_SCDMA:{
- /* valid LAC are hexstrings in the range 0x0000 - 0xffff */
- rilCellIdentity.cellIdentityTdscdma.lac =
- convertResponseHexStringEntryToInt(response, 1, numStrings);
-
- /* valid CID are hexstrings in the range 0x00000000 - 0xffffffff */
- rilCellIdentity.cellIdentityTdscdma.cid =
- convertResponseHexStringEntryToInt(response, 2, numStrings);
-
- if (numStrings >= 13) {
- rilCellIdentity.cellIdentityTdscdma.mcc =
- convertResponseStringEntryToInt(response, 11, numStrings);
-
- rilCellIdentity.cellIdentityTdscdma.mnc =
- convertResponseStringEntryToInt(response, 12, numStrings);
- } else {
- /* vts check the mcc [0, 999] and mnc [0, 999]. */
- rilCellIdentity.cellIdentityTdscdma.mnc = 0;
- rilCellIdentity.cellIdentityTdscdma.mcc = 0;
- }
- break;
- }
- case RIL_CELL_INFO_TYPE_LTE: {
- rilCellIdentity.cellIdentityLte.tac =
- convertResponseHexStringEntryToInt(response, 1, numStrings);
- rilCellIdentity.cellIdentityLte.ci =
- convertResponseHexStringEntryToInt(response, 2, numStrings);
-
- if (numStrings >= 13) {
- rilCellIdentity.cellIdentityLte.mcc =
- convertResponseStringEntryToInt(response, 11, numStrings);
-
- rilCellIdentity.cellIdentityLte.mnc =
- convertResponseStringEntryToInt(response, 12, numStrings);
- } else {
- /* vts check the mcc [0, 999] and mnc [0, 999]. */
- rilCellIdentity.cellIdentityLte.mnc = 0;
- rilCellIdentity.cellIdentityLte.mcc = 0;
- }
- break;
- }
- // TODO add CDMA
- default: {
- break;
- }
- }
-
fillCellIdentityResponse(cellIdentity, rilCellIdentity);
}
-int radio_1_6::getVoiceRegistrationStateResponse(int slotId,
+int radio_1_5::getVoiceRegistrationStateResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
RLOGD("getVoiceRegistrationStateResponse: serial %d", serial);
#endif
- if (radioService[slotId]->mRadioResponse != NULL ||
- radioService[slotId]->mRadioResponseV1_2 != NULL ||
- radioService[slotId]->mRadioResponseV1_5 != NULL ||
- radioService[slotId]->mRadioResponseV1_6 != NULL) {
+ if (radioService[slotId]->mRadioResponse != NULL) {
RadioResponseInfo responseInfo = {};
populateResponseInfo(responseInfo, serial, responseType, e);
@@ -6320,301 +4802,71 @@ int radio_1_6::getVoiceRegistrationStateResponse(int slotId,
if (response == NULL) {
RLOGE("getVoiceRegistrationStateResponse Invalid response: NULL");
if (e == RIL_E_SUCCESS) responseInfo.error = RadioError::INVALID_RESPONSE;
- } else if (s_vendorFunctions->version >= 15 &&
- radioService[slotId]->mRadioResponseV1_6 != NULL) {
- ::android::hardware::radio::V1_6::RadioResponseInfo responseInfo_1_6 = {};
- populateResponseInfo_1_6(responseInfo_1_6, serial, responseType, e);
- RegStateResultV1_6 regResponse = {};
- if (numStrings != 18) {
- RLOGE("getVoiceRegistrationStateResponse_1_6 Invalid response: NULL");
- if (e == RIL_E_SUCCESS) responseInfo_1_6.error =
- ::android::hardware::radio::V1_6::RadioError::INVALID_RESPONSE;
- } else {
- char **resp = (char **) response;
- regResponse.regState = (RegState)ATOI_NULL_HANDLED_DEF(resp[0], 4);
- int rat = ATOI_NULL_HANDLED_DEF(resp[3], 0);
- regResponse.rat = (V1_4::RadioTechnology)rat;
- if (rat == RADIO_TECH_EVDO_0 || rat == RADIO_TECH_EVDO_A ||
- rat == RADIO_TECH_EVDO_B || rat == RADIO_TECH_1xRTT ||
- rat == RADIO_TECH_IS95A || rat == RADIO_TECH_IS95B ||
- rat == RADIO_TECH_EHRPD) {
- V1_5::RegStateResult::AccessTechnologySpecificInfo::
- Cdma2000RegistrationInfo cdmaInfo;
- cdmaInfo.cssSupported = ATOI_NULL_HANDLED_DEF(resp[7], 0);
- cdmaInfo.roamingIndicator = ATOI_NULL_HANDLED(resp[10]);
- cdmaInfo.systemIsInPrl = (V1_5::PrlIndicator)ATOI_NULL_HANDLED_DEF(resp[11], 0);
- cdmaInfo.defaultRoamingIndicator= ATOI_NULL_HANDLED_DEF(resp[12], 0);
- regResponse.accessTechnologySpecificInfo.cdmaInfo(cdmaInfo);
- } else if (rat == RADIO_TECH_NR) {
- // rat is NR only for NR SA
- V1_6::NrVopsInfo nrVopsInfo;
- nrVopsInfo.vopsSupported =
- ::android::hardware::radio::V1_6::VopsIndicator::VOPS_NOT_SUPPORTED;
- nrVopsInfo.emcSupported =
- ::android::hardware::radio::V1_6::EmcIndicator::EMC_NOT_SUPPORTED;
- nrVopsInfo.emfSupported =
- ::android::hardware::radio::V1_6::EmfIndicator::EMF_NOT_SUPPORTED;
- regResponse.accessTechnologySpecificInfo.ngranNrVopsInfo(nrVopsInfo);
-
- } else {
- V1_5::RegStateResult::AccessTechnologySpecificInfo::
- EutranRegistrationInfo eutranInfo;
- if (rat == RADIO_TECH_LTE || rat == RADIO_TECH_LTE_CA) {
- eutranInfo.lteVopsInfo.isVopsSupported = false;
- eutranInfo.lteVopsInfo.isEmcBearerSupported = false;
- }
- eutranInfo.nrIndicators.isEndcAvailable = false;
- eutranInfo.nrIndicators.isDcNrRestricted = false;
- eutranInfo.nrIndicators.isEndcAvailable = false;
- regResponse.accessTechnologySpecificInfo.eutranInfo(eutranInfo);
- }
- regResponse.reasonForDenial = (V1_5::RegistrationFailCause)
- ATOI_NULL_HANDLED_DEF(resp[13], 0);
- regResponse.registeredPlmn = convertCharPtrToHidlString(resp[17]);
-
- fillCellIdentityFromVoiceRegStateResponseString(regResponse.cellIdentity,
- numStrings, resp);
-
- Return<void> retStatus =
- radioService[slotId]
- ->mRadioResponseV1_6
- ->getVoiceRegistrationStateResponse_1_6(
- responseInfo_1_6, regResponse);
- radioService[slotId]->checkReturnStatus(retStatus);
- }
- } else if (s_vendorFunctions->version <= 14 &&
- radioService[slotId]->mRadioResponseV1_5 != NULL) {
- RegStateResultV1_5 regResponse = {};
- if (numStrings != 18) {
- RLOGE("getVoiceRegistrationStateResponse_1_5 Invalid response: NULL");
- if (e == RIL_E_SUCCESS) responseInfo.error = RadioError::INVALID_RESPONSE;
- } else {
- char **resp = (char **) response;
- regResponse.regState = (RegState)ATOI_NULL_HANDLED_DEF(resp[0], 4);
- int rat = ATOI_NULL_HANDLED_DEF(resp[3], 0);
- regResponse.rat = (V1_4::RadioTechnology)rat;
- if (rat == RADIO_TECH_EVDO_0 || rat == RADIO_TECH_EVDO_A ||
- rat == RADIO_TECH_EVDO_B || rat == RADIO_TECH_1xRTT ||
- rat == RADIO_TECH_IS95A || rat == RADIO_TECH_IS95B ||
- rat == RADIO_TECH_EHRPD) {
- V1_5::RegStateResult::AccessTechnologySpecificInfo::
- Cdma2000RegistrationInfo cdmaInfo;
- cdmaInfo.cssSupported = ATOI_NULL_HANDLED_DEF(resp[7], 0);
- cdmaInfo.roamingIndicator = ATOI_NULL_HANDLED(resp[10]);
- cdmaInfo.systemIsInPrl = (V1_5::PrlIndicator)ATOI_NULL_HANDLED_DEF(resp[11], 0);
- cdmaInfo.defaultRoamingIndicator= ATOI_NULL_HANDLED_DEF(resp[12], 0);
- regResponse.accessTechnologySpecificInfo.cdmaInfo(cdmaInfo);
- } else {
- V1_5::RegStateResult::AccessTechnologySpecificInfo::
- EutranRegistrationInfo eutranInfo;
- if (rat == RADIO_TECH_LTE || rat == RADIO_TECH_LTE_CA ||
- rat == RADIO_TECH_NR) {
- eutranInfo.lteVopsInfo.isVopsSupported = false;
- eutranInfo.lteVopsInfo.isEmcBearerSupported = false;
- }
- eutranInfo.nrIndicators.isEndcAvailable = false;
- eutranInfo.nrIndicators.isDcNrRestricted = false;
- eutranInfo.nrIndicators.isEndcAvailable = false;
- regResponse.accessTechnologySpecificInfo.eutranInfo(eutranInfo);
- }
- regResponse.reasonForDenial = (V1_5::RegistrationFailCause)
- ATOI_NULL_HANDLED_DEF(resp[13], 0);
- regResponse.registeredPlmn = convertCharPtrToHidlString(resp[17]);
-
- fillCellIdentityFromVoiceRegStateResponseString(regResponse.cellIdentity,
- numStrings, resp);
-
- Return<void> retStatus =
- radioService[slotId]
- ->mRadioResponseV1_5
- ->getVoiceRegistrationStateResponse_1_5(
- responseInfo, regResponse);
- radioService[slotId]->checkReturnStatus(retStatus);
- }
- } else if (s_vendorFunctions->version <= 14 &&
- radioService[slotId]->mRadioResponseV1_2 != NULL) {
- V1_2::VoiceRegStateResult voiceRegResponse = {};
- int numStrings = responseLen / sizeof(char *);
- if (numStrings != 18) {
- RLOGE("getVoiceRegistrationStateResponse_1_21 Invalid response: NULL");
+ } else if (s_vendorFunctions->version <= 14) {
+ if (numStrings != 15) {
+ RLOGE("getVoiceRegistrationStateResponse Invalid response: NULL");
if (e == RIL_E_SUCCESS) responseInfo.error = RadioError::INVALID_RESPONSE;
} else {
char **resp = (char **) response;
voiceRegResponse.regState = (RegState) ATOI_NULL_HANDLED_DEF(resp[0], 4);
- voiceRegResponse.rat = ATOI_NULL_HANDLED_DEF(resp[3], 0);
+ voiceRegResponse.rat = ATOI_NULL_HANDLED(resp[3]);
voiceRegResponse.cssSupported = ATOI_NULL_HANDLED_DEF(resp[7], 0);
voiceRegResponse.roamingIndicator = ATOI_NULL_HANDLED(resp[10]);
voiceRegResponse.systemIsInPrl = ATOI_NULL_HANDLED_DEF(resp[11], 0);
voiceRegResponse.defaultRoamingIndicator = ATOI_NULL_HANDLED_DEF(resp[12], 0);
voiceRegResponse.reasonForDenial = ATOI_NULL_HANDLED_DEF(resp[13], 0);
- fillCellIdentityFromVoiceRegStateResponseString_1_2(
- voiceRegResponse.cellIdentity, numStrings, resp);
- }
- Return<void> retStatus = radioService[slotId]->mRadioResponseV1_2->
- getVoiceRegistrationStateResponse_1_2(responseInfo, voiceRegResponse);
- radioService[slotId]->checkReturnStatus(retStatus);
+ fillCellIdentityFromVoiceRegStateResponseString(voiceRegResponse.cellIdentity,
+ numStrings, resp);
+ }
} else {
- RIL_VoiceRegistrationStateResponse *voiceRegState =
+ RIL_VoiceRegistrationStateResponse *voiceRegState =
(RIL_VoiceRegistrationStateResponse *)response;
- if (responseLen != sizeof(RIL_VoiceRegistrationStateResponse)) {
- RLOGE("getVoiceRegistrationStateResponse Invalid response: NULL");
- if (e == RIL_E_SUCCESS) responseInfo.error = RadioError::INVALID_RESPONSE;
- } else {
- voiceRegResponse.regState = (RegState) voiceRegState->regState;
- voiceRegResponse.rat = voiceRegState->rat;;
- voiceRegResponse.cssSupported = voiceRegState->cssSupported;
- voiceRegResponse.roamingIndicator = voiceRegState->roamingIndicator;
- voiceRegResponse.systemIsInPrl = voiceRegState->systemIsInPrl;
- voiceRegResponse.defaultRoamingIndicator = voiceRegState->defaultRoamingIndicator;
- voiceRegResponse.reasonForDenial = voiceRegState->reasonForDenial;
- fillCellIdentityResponse(voiceRegResponse.cellIdentity,
- voiceRegState->cellIdentity);
- }
- Return<void> retStatus =
- radioService[slotId]->mRadioResponse->getVoiceRegistrationStateResponse(
- responseInfo, voiceRegResponse);
- radioService[slotId]->checkReturnStatus(retStatus);
+
+ if (responseLen != sizeof(RIL_VoiceRegistrationStateResponse)) {
+ RLOGE("getVoiceRegistrationStateResponse Invalid response: NULL");
+ if (e == RIL_E_SUCCESS) responseInfo.error = RadioError::INVALID_RESPONSE;
+ } else {
+ voiceRegResponse.regState = (RegState) voiceRegState->regState;
+ voiceRegResponse.rat = voiceRegState->rat;;
+ voiceRegResponse.cssSupported = voiceRegState->cssSupported;
+ voiceRegResponse.roamingIndicator = voiceRegState->roamingIndicator;
+ voiceRegResponse.systemIsInPrl = voiceRegState->systemIsInPrl;
+ voiceRegResponse.defaultRoamingIndicator = voiceRegState->defaultRoamingIndicator;
+ voiceRegResponse.reasonForDenial = voiceRegState->reasonForDenial;
+ fillCellIdentityResponse(voiceRegResponse.cellIdentity,
+ voiceRegState->cellIdentity);
+ }
}
+ Return<void> retStatus =
+ radioService[slotId]->mRadioResponse->getVoiceRegistrationStateResponse(
+ responseInfo, voiceRegResponse);
+ radioService[slotId]->checkReturnStatus(retStatus);
} else {
RLOGE("getVoiceRegistrationStateResponse: radioService[%d]->mRadioResponse == NULL",
slotId);
}
+
return 0;
}
-int radio_1_6::getDataRegistrationStateResponse(int slotId,
+int radio_1_5::getDataRegistrationStateResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
RLOGD("getDataRegistrationStateResponse: serial %d", serial);
#endif
- if (radioService[slotId]->mRadioResponse != NULL ||
- radioService[slotId]->mRadioResponseV1_2 != NULL ||
- radioService[slotId]->mRadioResponseV1_5 != NULL ||
- radioService[slotId]->mRadioResponseV1_6 != NULL) {
+
+ if (radioService[slotId]->mRadioResponse != NULL) {
RadioResponseInfo responseInfo = {};
- DataRegStateResult dataRegResponse = {};
populateResponseInfo(responseInfo, serial, responseType, e);
+ DataRegStateResult dataRegResponse = {};
if (response == NULL) {
RLOGE("getDataRegistrationStateResponse Invalid response: NULL");
if (e == RIL_E_SUCCESS) responseInfo.error = RadioError::INVALID_RESPONSE;
- } else if (s_vendorFunctions->version >= 15 &&
- radioService[slotId]->mRadioResponseV1_6 != NULL) {
- ::android::hardware::radio::V1_6::RadioResponseInfo responseInfo_1_6 = {};
- populateResponseInfo_1_6(responseInfo_1_6, serial, responseType, e);
- RegStateResultV1_6 regResponse = {};
- int numStrings = responseLen / sizeof(char *);
- if ((numStrings != 6) && (numStrings != 11) && (numStrings != 14)) {
- RLOGE("getDataRegistrationStateResponse Invalid response: NULL");
- if (e == RIL_E_SUCCESS) responseInfo_1_6.error =
- ::android::hardware::radio::V1_6::RadioError::INVALID_RESPONSE;
- } else {
- char **resp = (char **) response;
- int rat = ATOI_NULL_HANDLED_DEF(resp[3], 0);
- regResponse.regState = (RegState)ATOI_NULL_HANDLED_DEF(resp[0], 4);
- regResponse.rat = (V1_4::RadioTechnology)rat;
- regResponse.reasonForDenial =
- (V1_5::RegistrationFailCause)ATOI_NULL_HANDLED(resp[4]);
- if (numStrings > 13) {
- regResponse.registeredPlmn = convertCharPtrToHidlString(resp[13]);
- }
-
- fillCellIdentityFromDataRegStateResponseString_1_5(regResponse.cellIdentity,
- numStrings, resp);
- if (rat == RADIO_TECH_NR) {
- // rat is NR only for NR SA
- V1_6::NrVopsInfo nrVopsInfo;
- nrVopsInfo.vopsSupported =
- ::android::hardware::radio::V1_6::VopsIndicator::VOPS_NOT_SUPPORTED;
- nrVopsInfo.emcSupported =
- ::android::hardware::radio::V1_6::EmcIndicator::EMC_NOT_SUPPORTED;
- nrVopsInfo.emfSupported =
- ::android::hardware::radio::V1_6::EmfIndicator::EMF_NOT_SUPPORTED;
- regResponse.accessTechnologySpecificInfo.ngranNrVopsInfo(nrVopsInfo);
-
- } else {
- V1_5::RegStateResult::AccessTechnologySpecificInfo::
- EutranRegistrationInfo eutranInfo;
- if (rat == RADIO_TECH_LTE || rat == RADIO_TECH_LTE_CA) {
- eutranInfo.lteVopsInfo.isVopsSupported = false;
- eutranInfo.lteVopsInfo.isEmcBearerSupported = false;
- }
- eutranInfo.nrIndicators.isEndcAvailable = false;
- eutranInfo.nrIndicators.isDcNrRestricted = false;
- eutranInfo.nrIndicators.isEndcAvailable = false;
- regResponse.accessTechnologySpecificInfo.eutranInfo(eutranInfo);
- }
-
- Return<void> retStatus =
- radioService[slotId]
- ->mRadioResponseV1_6
- ->getVoiceRegistrationStateResponse_1_6(
- responseInfo_1_6, regResponse);
- radioService[slotId]->checkReturnStatus(retStatus);
- }
- } else if (s_vendorFunctions->version <= 14 &&
- radioService[slotId]->mRadioResponseV1_5 != NULL) {
- RegStateResultV1_5 regResponse = {};
- int numStrings = responseLen / sizeof(char *);
- if ((numStrings != 6) && (numStrings != 11) && (numStrings != 14)) {
- RLOGE("getDataRegistrationStateResponse Invalid response: NULL");
- if (e == RIL_E_SUCCESS) responseInfo.error = RadioError::INVALID_RESPONSE;
- } else {
- char **resp = (char **) response;
- int rat = ATOI_NULL_HANDLED_DEF(resp[3], 0);
- regResponse.regState = (RegState)ATOI_NULL_HANDLED_DEF(resp[0], 4);
- regResponse.rat = (V1_4::RadioTechnology)rat;
- regResponse.reasonForDenial =
- (V1_5::RegistrationFailCause)ATOI_NULL_HANDLED(resp[4]);
- if (numStrings > 13) {
- regResponse.registeredPlmn = convertCharPtrToHidlString(resp[13]);
- }
-
- V1_5::RegStateResult::AccessTechnologySpecificInfo::
- EutranRegistrationInfo eutranInfo;
- if (rat == RADIO_TECH_LTE || rat == RADIO_TECH_LTE_CA ||
- rat == RADIO_TECH_NR) {
- eutranInfo.lteVopsInfo.isVopsSupported = false;
- eutranInfo.lteVopsInfo.isEmcBearerSupported = false;
- }
- eutranInfo.nrIndicators.isEndcAvailable = false;
- eutranInfo.nrIndicators.isDcNrRestricted = false;
- eutranInfo.nrIndicators.isEndcAvailable = false;
- regResponse.accessTechnologySpecificInfo.eutranInfo(eutranInfo);
-
- fillCellIdentityFromDataRegStateResponseString_1_5(regResponse.cellIdentity,
- numStrings, resp);
-
- Return<void> retStatus =
- radioService[slotId]
- ->mRadioResponseV1_5
- ->getDataRegistrationStateResponse_1_5(
- responseInfo, regResponse);
- radioService[slotId]->checkReturnStatus(retStatus);
- }
- } else if (s_vendorFunctions->version <= 14 &&
- radioService[slotId]->mRadioResponseV1_2 != NULL) {
- V1_2::DataRegStateResult dataRegResponse = {};
+ } else if (s_vendorFunctions->version <= 14) {
int numStrings = responseLen / sizeof(char *);
- if ((numStrings != 11) && (numStrings != 13) && (numStrings != 14)) {
- RLOGE("getDataRegistrationStateResponse_1_2 Invalid response: NULL");
- if (e == RIL_E_SUCCESS) responseInfo.error = RadioError::INVALID_RESPONSE;
- } else {
- char **resp = (char **)response;
- dataRegResponse.regState = (RegState)ATOI_NULL_HANDLED_DEF(resp[0], 4);
- dataRegResponse.rat = ATOI_NULL_HANDLED_DEF(resp[3], 0);
- dataRegResponse.reasonDataDenied = ATOI_NULL_HANDLED(resp[4]);
- dataRegResponse.maxDataCalls = ATOI_NULL_HANDLED_DEF(resp[5], 1);
- fillCellIdentityFromDataRegStateResponseString_1_2(dataRegResponse.cellIdentity,
- numStrings, resp);
- Return<void> retStatus = radioService[slotId]->mRadioResponseV1_2->
- getDataRegistrationStateResponse_1_2(responseInfo, dataRegResponse);
- radioService[slotId]->checkReturnStatus(retStatus);
- }
- } else if (s_vendorFunctions->version <= 14) {
- int numStrings = responseLen / sizeof(char *);
- if ((numStrings != 11) && (numStrings != 13) && (numStrings != 14)) {
+ if ((numStrings != 6) && (numStrings != 11)) {
RLOGE("getDataRegistrationStateResponse Invalid response: NULL");
if (e == RIL_E_SUCCESS) responseInfo.error = RadioError::INVALID_RESPONSE;
} else {
@@ -6654,7 +4906,7 @@ int radio_1_6::getDataRegistrationStateResponse(int slotId,
return 0;
}
-int radio_1_6::getOperatorResponse(int slotId,
+int radio_1_5::getOperatorResponse(int slotId,
int responseType, int serial, RIL_Errno e, void *response,
size_t responseLen) {
#if VDBG
@@ -6689,22 +4941,16 @@ int radio_1_6::getOperatorResponse(int slotId,
return 0;
}
-int radio_1_6::setRadioPowerResponse(int slotId,
+int radio_1_5::setRadioPowerResponse(int slotId,
int responseType, int serial, RIL_Errno e, void *response,
size_t responseLen) {
#if VDBG
RLOGD("setRadioPowerResponse: serial %d", serial);
#endif
RadioResponseInfo responseInfo = {};
- ::android::hardware::radio::V1_6::RadioResponseInfo responseInfo_1_6 = {};
populateResponseInfo(responseInfo, serial, responseType, e);
- populateResponseInfo_1_6(responseInfo_1_6, serial, responseType, e);
- if (radioService[slotId]->mRadioResponseV1_6 != NULL) {
- Return<void> retStatus = radioService[slotId]->mRadioResponseV1_6
- ->setRadioPowerResponse_1_6(responseInfo_1_6);
- radioService[slotId]->checkReturnStatus(retStatus);
- } else if (radioService[slotId]->mRadioResponseV1_5 != NULL) {
+ if (radioService[slotId]->mRadioResponseV1_5 != NULL) {
Return<void> retStatus = radioService[slotId]->mRadioResponseV1_5
->setRadioPowerResponse_1_5(responseInfo);
radioService[slotId]->checkReturnStatus(retStatus);
@@ -6719,7 +4965,7 @@ int radio_1_6::setRadioPowerResponse(int slotId,
return 0;
}
-int radio_1_6::sendDtmfResponse(int slotId,
+int radio_1_5::sendDtmfResponse(int slotId,
int responseType, int serial, RIL_Errno e, void *response,
size_t responseLen) {
#if VDBG
@@ -6758,43 +5004,14 @@ SendSmsResult makeSendSmsResult(RadioResponseInfo& responseInfo, int serial, int
return result;
}
-SendSmsResult makeSendSmsResult_1_6(
- ::android::hardware::radio::V1_6::RadioResponseInfo &responseInfo, int serial,
- int responseType, RIL_Errno e, void *response, size_t responseLen) {
- populateResponseInfo_1_6(responseInfo, serial, responseType, e);
- SendSmsResult result = {};
-
- if (response == NULL || responseLen != sizeof(RIL_SMS_Response)) {
- RLOGE("Invalid response: NULL");
- if (e == RIL_E_SUCCESS) {
- responseInfo.error = ::android::hardware::radio::V1_6::RadioError::INVALID_RESPONSE;
- }
- result.ackPDU = hidl_string();
- } else {
- RIL_SMS_Response *resp = (RIL_SMS_Response *) response;
- result.messageRef = resp->messageRef;
- result.ackPDU = convertCharPtrToHidlString(resp->ackPDU);
- result.errorCode = resp->errorCode;
- }
- return result;
-}
-
-int radio_1_6::sendSmsResponse(int slotId,
+int radio_1_5::sendSmsResponse(int slotId,
int responseType, int serial, RIL_Errno e, void *response,
size_t responseLen) {
#if VDBG
RLOGD("sendSmsResponse: serial %d", serial);
#endif
- if (radioService[slotId]->mRadioResponseV1_6 != NULL) {
- ::android::hardware::radio::V1_6::RadioResponseInfo responseInfo_1_6 = {};
- SendSmsResult result = makeSendSmsResult_1_6(responseInfo_1_6, serial, responseType, e, response,
- responseLen);
-
- Return<void> retStatus = radioService[slotId]->mRadioResponseV1_6
- ->sendSmsResponse_1_6(responseInfo_1_6, result);
- radioService[slotId]->checkReturnStatus(retStatus);
- } else if (radioService[slotId]->mRadioResponse != NULL) {
+ if (radioService[slotId]->mRadioResponse != NULL) {
RadioResponseInfo responseInfo = {};
SendSmsResult result = makeSendSmsResult(responseInfo, serial, responseType, e, response,
responseLen);
@@ -6809,22 +5026,14 @@ int radio_1_6::sendSmsResponse(int slotId,
return 0;
}
-int radio_1_6::sendSmsExpectMoreResponse(int slotId,
+int radio_1_5::sendSMSExpectMoreResponse(int slotId,
int responseType, int serial, RIL_Errno e, void *response,
size_t responseLen) {
#if VDBG
- RLOGD("sendSmsExpectMoreResponse: serial %d", serial);
+ RLOGD("sendSMSExpectMoreResponse: serial %d", serial);
#endif
- if (radioService[slotId]->mRadioResponseV1_6 != NULL) {
- ::android::hardware::radio::V1_6::RadioResponseInfo responseInfo_1_6 = {};
- SendSmsResult result = makeSendSmsResult_1_6(responseInfo_1_6, serial, responseType, e, response,
- responseLen);
-
- Return<void> retStatus = radioService[slotId]->mRadioResponseV1_6
- ->sendSmsExpectMoreResponse_1_6(responseInfo_1_6, result);
- radioService[slotId]->checkReturnStatus(retStatus);
- } else if (radioService[slotId]->mRadioResponse != NULL) {
+ if (radioService[slotId]->mRadioResponse != NULL) {
RadioResponseInfo responseInfo = {};
SendSmsResult result = makeSendSmsResult(responseInfo, serial, responseType, e, response,
responseLen);
@@ -6839,39 +5048,13 @@ int radio_1_6::sendSmsExpectMoreResponse(int slotId,
return 0;
}
-int radio_1_6::setupDataCallResponse(int slotId,
+int radio_1_5::setupDataCallResponse(int slotId,
int responseType, int serial, RIL_Errno e, void *response,
size_t responseLen) {
#if VDBG
RLOGD("setupDataCallResponse: serial %d", serial);
#endif
- if (radioService[slotId]->mRadioResponseV1_6 != NULL) {
- ::android::hardware::radio::V1_6::RadioResponseInfo responseInfo_1_6 = {};
- populateResponseInfo_1_6(responseInfo_1_6, serial, responseType, e);
- ::android::hardware::radio::V1_6::SetupDataCallResult result;
- if (response == NULL || (responseLen % sizeof(RIL_Data_Call_Response_v11)) != 0) {
- if (response != NULL) {
- RLOGE("setupDataCallResponse_1_6: Invalid response");
- if (e == RIL_E_SUCCESS) responseInfo_1_6.error =
- ::android::hardware::radio::V1_6::RadioError::INVALID_RESPONSE;
- }
- result.cause = ::android::hardware::radio::V1_6::DataCallFailCause::ERROR_UNSPECIFIED;
- result.type = ::android::hardware::radio::V1_4::PdpProtocolType::UNKNOWN;
- result.ifname = hidl_string();
- result.addresses = hidl_vec<::android::hardware::radio::V1_5::LinkAddress>();
- result.dnses = hidl_vec<hidl_string>();
- result.gateways = hidl_vec<hidl_string>();
- result.pcscf = hidl_vec<hidl_string>();
- result.trafficDescriptors =
- hidl_vec<::android::hardware::radio::V1_6::TrafficDescriptor>();
- } else {
- convertRilDataCallToHal((RIL_Data_Call_Response_v12 *) response, result);
- }
-
- Return<void> retStatus = radioService[slotId]->mRadioResponseV1_6->setupDataCallResponse_1_6(
- responseInfo_1_6, result);
- radioService[slotId]->checkReturnStatus(retStatus);
- } else if (radioService[slotId]->mRadioResponseV1_5 != NULL) {
+ if (radioService[slotId]->mRadioResponseV1_5 != NULL) {
RadioResponseInfo responseInfo = {};
populateResponseInfo(responseInfo, serial, responseType, e);
::android::hardware::radio::V1_5::SetupDataCallResult result;
@@ -6966,7 +5149,7 @@ IccIoResult responseIccIo(RadioResponseInfo& responseInfo, int serial, int respo
return result;
}
-int radio_1_6::iccIOForAppResponse(int slotId,
+int radio_1_5::iccIOForAppResponse(int slotId,
int responseType, int serial, RIL_Errno e, void *response,
size_t responseLen) {
#if VDBG
@@ -6988,7 +5171,7 @@ int radio_1_6::iccIOForAppResponse(int slotId,
return 0;
}
-int radio_1_6::sendUssdResponse(int slotId,
+int radio_1_5::sendUssdResponse(int slotId,
int responseType, int serial, RIL_Errno e, void *response,
size_t responseLen) {
#if VDBG
@@ -7009,7 +5192,7 @@ int radio_1_6::sendUssdResponse(int slotId,
return 0;
}
-int radio_1_6::cancelPendingUssdResponse(int slotId,
+int radio_1_5::cancelPendingUssdResponse(int slotId,
int responseType, int serial, RIL_Errno e, void *response,
size_t responseLen) {
#if VDBG
@@ -7030,7 +5213,7 @@ int radio_1_6::cancelPendingUssdResponse(int slotId,
return 0;
}
-int radio_1_6::getClirResponse(int slotId,
+int radio_1_5::getClirResponse(int slotId,
int responseType, int serial, RIL_Errno e, void *response,
size_t responseLen) {
#if VDBG
@@ -7060,7 +5243,7 @@ int radio_1_6::getClirResponse(int slotId,
return 0;
}
-int radio_1_6::setClirResponse(int slotId,
+int radio_1_5::setClirResponse(int slotId,
int responseType, int serial, RIL_Errno e, void *response,
size_t responseLen) {
#if VDBG
@@ -7080,7 +5263,7 @@ int radio_1_6::setClirResponse(int slotId,
return 0;
}
-int radio_1_6::getCallForwardStatusResponse(int slotId,
+int radio_1_5::getCallForwardStatusResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -7121,7 +5304,7 @@ int radio_1_6::getCallForwardStatusResponse(int slotId,
return 0;
}
-int radio_1_6::setCallForwardResponse(int slotId,
+int radio_1_5::setCallForwardResponse(int slotId,
int responseType, int serial, RIL_Errno e, void *response,
size_t responseLen) {
#if VDBG
@@ -7141,7 +5324,7 @@ int radio_1_6::setCallForwardResponse(int slotId,
return 0;
}
-int radio_1_6::getCallWaitingResponse(int slotId,
+int radio_1_5::getCallWaitingResponse(int slotId,
int responseType, int serial, RIL_Errno e, void *response,
size_t responseLen) {
#if VDBG
@@ -7172,7 +5355,7 @@ int radio_1_6::getCallWaitingResponse(int slotId,
return 0;
}
-int radio_1_6::setCallWaitingResponse(int slotId,
+int radio_1_5::setCallWaitingResponse(int slotId,
int responseType, int serial, RIL_Errno e, void *response,
size_t responseLen) {
#if VDBG
@@ -7192,7 +5375,7 @@ int radio_1_6::setCallWaitingResponse(int slotId,
return 0;
}
-int radio_1_6::acknowledgeLastIncomingGsmSmsResponse(int slotId,
+int radio_1_5::acknowledgeLastIncomingGsmSmsResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -7214,7 +5397,7 @@ int radio_1_6::acknowledgeLastIncomingGsmSmsResponse(int slotId,
return 0;
}
-int radio_1_6::acceptCallResponse(int slotId,
+int radio_1_5::acceptCallResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -7235,7 +5418,7 @@ int radio_1_6::acceptCallResponse(int slotId,
return 0;
}
-int radio_1_6::deactivateDataCallResponse(int slotId,
+int radio_1_5::deactivateDataCallResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -7256,7 +5439,7 @@ int radio_1_6::deactivateDataCallResponse(int slotId,
return 0;
}
-int radio_1_6::getFacilityLockForAppResponse(int slotId,
+int radio_1_5::getFacilityLockForAppResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -7277,7 +5460,7 @@ int radio_1_6::getFacilityLockForAppResponse(int slotId,
return 0;
}
-int radio_1_6::setFacilityLockForAppResponse(int slotId,
+int radio_1_5::setFacilityLockForAppResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -7299,7 +5482,7 @@ int radio_1_6::setFacilityLockForAppResponse(int slotId,
return 0;
}
-int radio_1_6::setBarringPasswordResponse(int slotId,
+int radio_1_5::setBarringPasswordResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -7320,7 +5503,7 @@ int radio_1_6::setBarringPasswordResponse(int slotId,
return 0;
}
-int radio_1_6::getNetworkSelectionModeResponse(int slotId,
+int radio_1_5::getNetworkSelectionModeResponse(int slotId,
int responseType, int serial, RIL_Errno e, void *response,
size_t responseLen) {
#if VDBG
@@ -7351,7 +5534,7 @@ int radio_1_6::getNetworkSelectionModeResponse(int slotId,
return 0;
}
-int radio_1_6::setNetworkSelectionModeAutomaticResponse(int slotId, int responseType, int serial,
+int radio_1_5::setNetworkSelectionModeAutomaticResponse(int slotId, int responseType, int serial,
RIL_Errno e, void *response,
size_t responseLen) {
#if VDBG
@@ -7373,7 +5556,7 @@ int radio_1_6::setNetworkSelectionModeAutomaticResponse(int slotId, int response
return 0;
}
-int radio_1_6::setNetworkSelectionModeManualResponse(int slotId,
+int radio_1_5::setNetworkSelectionModeManualResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -7412,7 +5595,7 @@ int convertOperatorStatusToInt(const char *str) {
}
}
-int radio_1_6::getAvailableNetworksResponse(int slotId,
+int radio_1_5::getAvailableNetworksResponse(int slotId,
int responseType, int serial, RIL_Errno e, void *response,
size_t responseLen) {
#if VDBG
@@ -7455,7 +5638,7 @@ int radio_1_6::getAvailableNetworksResponse(int slotId,
return 0;
}
-int radio_1_6::startDtmfResponse(int slotId,
+int radio_1_5::startDtmfResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -7475,7 +5658,7 @@ int radio_1_6::startDtmfResponse(int slotId,
return 0;
}
-int radio_1_6::stopDtmfResponse(int slotId,
+int radio_1_5::stopDtmfResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -7495,7 +5678,7 @@ int radio_1_6::stopDtmfResponse(int slotId,
return 0;
}
-int radio_1_6::getBasebandVersionResponse(int slotId,
+int radio_1_5::getBasebandVersionResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -7516,7 +5699,7 @@ int radio_1_6::getBasebandVersionResponse(int slotId,
return 0;
}
-int radio_1_6::separateConnectionResponse(int slotId,
+int radio_1_5::separateConnectionResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -7537,7 +5720,7 @@ int radio_1_6::separateConnectionResponse(int slotId,
return 0;
}
-int radio_1_6::setMuteResponse(int slotId,
+int radio_1_5::setMuteResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -7557,7 +5740,7 @@ int radio_1_6::setMuteResponse(int slotId,
return 0;
}
-int radio_1_6::getMuteResponse(int slotId,
+int radio_1_5::getMuteResponse(int slotId,
int responseType, int serial, RIL_Errno e, void *response,
size_t responseLen) {
#if VDBG
@@ -7585,7 +5768,7 @@ int radio_1_6::getMuteResponse(int slotId,
return 0;
}
-int radio_1_6::getClipResponse(int slotId,
+int radio_1_5::getClipResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -7605,7 +5788,7 @@ int radio_1_6::getClipResponse(int slotId,
return 0;
}
-int radio_1_6::getDataCallListResponse(int slotId,
+int radio_1_5::getDataCallListResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -7635,7 +5818,7 @@ int radio_1_6::getDataCallListResponse(int slotId,
return 0;
}
-int radio_1_6::setSuppServiceNotificationsResponse(int slotId,
+int radio_1_5::setSuppServiceNotificationsResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -7657,7 +5840,7 @@ int radio_1_6::setSuppServiceNotificationsResponse(int slotId,
return 0;
}
-int radio_1_6::deleteSmsOnSimResponse(int slotId,
+int radio_1_5::deleteSmsOnSimResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -7677,7 +5860,7 @@ int radio_1_6::deleteSmsOnSimResponse(int slotId,
return 0;
}
-int radio_1_6::setBandModeResponse(int slotId,
+int radio_1_5::setBandModeResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -7697,7 +5880,7 @@ int radio_1_6::setBandModeResponse(int slotId,
return 0;
}
-int radio_1_6::writeSmsToSimResponse(int slotId,
+int radio_1_5::writeSmsToSimResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -7717,7 +5900,7 @@ int radio_1_6::writeSmsToSimResponse(int slotId,
return 0;
}
-int radio_1_6::getAvailableBandModesResponse(int slotId,
+int radio_1_5::getAvailableBandModesResponse(int slotId,
int responseType, int serial, RIL_Errno e, void *response,
size_t responseLen) {
#if VDBG
@@ -7751,7 +5934,7 @@ int radio_1_6::getAvailableBandModesResponse(int slotId,
return 0;
}
-int radio_1_6::sendEnvelopeResponse(int slotId,
+int radio_1_5::sendEnvelopeResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -7772,7 +5955,7 @@ int radio_1_6::sendEnvelopeResponse(int slotId,
return 0;
}
-int radio_1_6::sendTerminalResponseToSimResponse(int slotId,
+int radio_1_5::sendTerminalResponseToSimResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -7794,7 +5977,7 @@ int radio_1_6::sendTerminalResponseToSimResponse(int slotId,
return 0;
}
-int radio_1_6::handleStkCallSetupRequestFromSimResponse(int slotId,
+int radio_1_5::handleStkCallSetupRequestFromSimResponse(int slotId,
int responseType, int serial,
RIL_Errno e, void *response,
size_t responseLen) {
@@ -7817,7 +6000,7 @@ int radio_1_6::handleStkCallSetupRequestFromSimResponse(int slotId,
return 0;
}
-int radio_1_6::explicitCallTransferResponse(int slotId,
+int radio_1_5::explicitCallTransferResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -7838,7 +6021,7 @@ int radio_1_6::explicitCallTransferResponse(int slotId,
return 0;
}
-int radio_1_6::setPreferredNetworkTypeResponse(int slotId,
+int radio_1_5::setPreferredNetworkTypeResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -7860,54 +6043,8 @@ int radio_1_6::setPreferredNetworkTypeResponse(int slotId,
return 0;
}
-int radio_1_6::setAllowedNetworkTypesBitmapResponse(int slotId,
- int responseType, int serial, RIL_Errno e,
- void *response, size_t responseLen) {
-#if VDBG
- RLOGD("setAllowedNetworkTypesBitmapResponse: serial %d", serial);
-#endif
-
- V1_6::RadioResponseInfo responseInfo = {};
- populateResponseInfo_1_6(responseInfo, serial, responseType, e);
- // If we don't have a radio service, there's nothing we can do
- if (radioService[slotId]->mRadioResponseV1_6 == NULL) {
- RLOGE("%s: radioService[%d]->mRadioResponseV1_6 == NULL", __FUNCTION__, slotId);
- return 0;
- }
-
- Return<void> retStatus =
- radioService[slotId]->mRadioResponseV1_6->setAllowedNetworkTypesBitmapResponse(
- responseInfo);
- radioService[slotId]->checkReturnStatus(retStatus);
- return 0;
-}
-
-int radio_1_6::getAllowedNetworkTypesBitmapResponse(int slotId,
- int responseType, int serial, RIL_Errno e,
- void *response, size_t responseLen) {
-#if VDBG
- RLOGD("getAllowedNetworkTypesBitmapResponse: serial %d", serial);
-#endif
-
- if (radioService[slotId]->mRadioResponseV1_6 != NULL) {
- V1_6::RadioResponseInfo responseInfo = {};
- int ret = responseInt_1_6(responseInfo, serial, responseType, e, response, responseLen);
- Return<void> retStatus
- = radioService[slotId]->mRadioResponseV1_6->getAllowedNetworkTypesBitmapResponse(
- responseInfo,
- (const ::android::hardware::hidl_bitfield<
- ::android::hardware::radio::V1_4::RadioAccessFamily>) ret);
- radioService[slotId]->checkReturnStatus(retStatus);
- } else {
- RLOGE("getAllowedNetworkTypesBitmapResponse: radioService[%d]->mRadioResponseV1_6 == NULL",
- slotId);
- }
-
- return 0;
-}
-
-int radio_1_6::getPreferredNetworkTypeResponse(int slotId,
+int radio_1_5::getPreferredNetworkTypeResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -7929,7 +6066,7 @@ int radio_1_6::getPreferredNetworkTypeResponse(int slotId,
return 0;
}
-int radio_1_6::setPreferredNetworkTypeBitmapResponse(int slotId,
+int radio_1_5::setPreferredNetworkTypeBitmapResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -7952,7 +6089,7 @@ int radio_1_6::setPreferredNetworkTypeBitmapResponse(int slotId,
}
-int radio_1_6::getPreferredNetworkTypeBitmapResponse(int slotId,
+int radio_1_5::getPreferredNetworkTypeBitmapResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -7976,7 +6113,7 @@ int radio_1_6::getPreferredNetworkTypeBitmapResponse(int slotId,
return 0;
}
-int radio_1_6::getNeighboringCidsResponse(int slotId,
+int radio_1_5::getNeighboringCidsResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -8014,7 +6151,7 @@ int radio_1_6::getNeighboringCidsResponse(int slotId,
return 0;
}
-int radio_1_6::setLocationUpdatesResponse(int slotId,
+int radio_1_5::setLocationUpdatesResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -8035,7 +6172,7 @@ int radio_1_6::setLocationUpdatesResponse(int slotId,
return 0;
}
-int radio_1_6::setCdmaSubscriptionSourceResponse(int slotId,
+int radio_1_5::setCdmaSubscriptionSourceResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -8057,7 +6194,7 @@ int radio_1_6::setCdmaSubscriptionSourceResponse(int slotId,
return 0;
}
-int radio_1_6::setCdmaRoamingPreferenceResponse(int slotId,
+int radio_1_5::setCdmaRoamingPreferenceResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -8079,7 +6216,7 @@ int radio_1_6::setCdmaRoamingPreferenceResponse(int slotId,
return 0;
}
-int radio_1_6::getCdmaRoamingPreferenceResponse(int slotId,
+int radio_1_5::getCdmaRoamingPreferenceResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -8101,7 +6238,7 @@ int radio_1_6::getCdmaRoamingPreferenceResponse(int slotId,
return 0;
}
-int radio_1_6::setTTYModeResponse(int slotId,
+int radio_1_5::setTTYModeResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -8121,7 +6258,7 @@ int radio_1_6::setTTYModeResponse(int slotId,
return 0;
}
-int radio_1_6::getTTYModeResponse(int slotId,
+int radio_1_5::getTTYModeResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -8142,7 +6279,7 @@ int radio_1_6::getTTYModeResponse(int slotId,
return 0;
}
-int radio_1_6::setPreferredVoicePrivacyResponse(int slotId,
+int radio_1_5::setPreferredVoicePrivacyResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -8164,7 +6301,7 @@ int radio_1_6::setPreferredVoicePrivacyResponse(int slotId,
return 0;
}
-int radio_1_6::getPreferredVoicePrivacyResponse(int slotId,
+int radio_1_5::getPreferredVoicePrivacyResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -8195,7 +6332,7 @@ int radio_1_6::getPreferredVoicePrivacyResponse(int slotId,
return 0;
}
-int radio_1_6::sendCDMAFeatureCodeResponse(int slotId,
+int radio_1_5::sendCDMAFeatureCodeResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -8216,7 +6353,7 @@ int radio_1_6::sendCDMAFeatureCodeResponse(int slotId,
return 0;
}
-int radio_1_6::sendBurstDtmfResponse(int slotId,
+int radio_1_5::sendBurstDtmfResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -8236,22 +6373,14 @@ int radio_1_6::sendBurstDtmfResponse(int slotId,
return 0;
}
-int radio_1_6::sendCdmaSmsResponse(int slotId,
+int radio_1_5::sendCdmaSmsResponse(int slotId,
int responseType, int serial, RIL_Errno e, void *response,
size_t responseLen) {
#if VDBG
RLOGD("sendCdmaSmsResponse: serial %d", serial);
#endif
- if (radioService[slotId]->mRadioResponseV1_6 != NULL) {
- ::android::hardware::radio::V1_6::RadioResponseInfo responseInfo_1_6 = {};
- SendSmsResult result = makeSendSmsResult_1_6(responseInfo_1_6, serial, responseType, e,
- response, responseLen);
-
- Return<void> retStatus = radioService[slotId]->mRadioResponseV1_6
- ->sendCdmaSmsResponse_1_6(responseInfo_1_6, result);
- radioService[slotId]->checkReturnStatus(retStatus);
- } else if (radioService[slotId]->mRadioResponse != NULL) {
+ if (radioService[slotId]->mRadioResponse != NULL) {
RadioResponseInfo responseInfo = {};
SendSmsResult result = makeSendSmsResult(responseInfo, serial, responseType, e, response,
responseLen);
@@ -8266,7 +6395,7 @@ int radio_1_6::sendCdmaSmsResponse(int slotId,
return 0;
}
-int radio_1_6::acknowledgeLastIncomingCdmaSmsResponse(int slotId,
+int radio_1_5::acknowledgeLastIncomingCdmaSmsResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -8288,7 +6417,7 @@ int radio_1_6::acknowledgeLastIncomingCdmaSmsResponse(int slotId,
return 0;
}
-int radio_1_6::getGsmBroadcastConfigResponse(int slotId,
+int radio_1_5::getGsmBroadcastConfigResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -8330,7 +6459,7 @@ int radio_1_6::getGsmBroadcastConfigResponse(int slotId,
return 0;
}
-int radio_1_6::setGsmBroadcastConfigResponse(int slotId,
+int radio_1_5::setGsmBroadcastConfigResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -8351,7 +6480,7 @@ int radio_1_6::setGsmBroadcastConfigResponse(int slotId,
return 0;
}
-int radio_1_6::setGsmBroadcastActivationResponse(int slotId,
+int radio_1_5::setGsmBroadcastActivationResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -8373,7 +6502,7 @@ int radio_1_6::setGsmBroadcastActivationResponse(int slotId,
return 0;
}
-int radio_1_6::getCdmaBroadcastConfigResponse(int slotId,
+int radio_1_5::getCdmaBroadcastConfigResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -8413,7 +6542,7 @@ int radio_1_6::getCdmaBroadcastConfigResponse(int slotId,
return 0;
}
-int radio_1_6::setCdmaBroadcastConfigResponse(int slotId,
+int radio_1_5::setCdmaBroadcastConfigResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -8435,7 +6564,7 @@ int radio_1_6::setCdmaBroadcastConfigResponse(int slotId,
return 0;
}
-int radio_1_6::setCdmaBroadcastActivationResponse(int slotId,
+int radio_1_5::setCdmaBroadcastActivationResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -8457,7 +6586,7 @@ int radio_1_6::setCdmaBroadcastActivationResponse(int slotId,
return 0;
}
-int radio_1_6::getCDMASubscriptionResponse(int slotId,
+int radio_1_5::getCDMASubscriptionResponse(int slotId,
int responseType, int serial, RIL_Errno e, void *response,
size_t responseLen) {
#if VDBG
@@ -8497,7 +6626,7 @@ int radio_1_6::getCDMASubscriptionResponse(int slotId,
return 0;
}
-int radio_1_6::writeSmsToRuimResponse(int slotId,
+int radio_1_5::writeSmsToRuimResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -8517,7 +6646,7 @@ int radio_1_6::writeSmsToRuimResponse(int slotId,
return 0;
}
-int radio_1_6::deleteSmsOnRuimResponse(int slotId,
+int radio_1_5::deleteSmsOnRuimResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -8537,7 +6666,7 @@ int radio_1_6::deleteSmsOnRuimResponse(int slotId,
return 0;
}
-int radio_1_6::getDeviceIdentityResponse(int slotId,
+int radio_1_5::getDeviceIdentityResponse(int slotId,
int responseType, int serial, RIL_Errno e, void *response,
size_t responseLen) {
#if VDBG
@@ -8575,7 +6704,7 @@ int radio_1_6::getDeviceIdentityResponse(int slotId,
return 0;
}
-int radio_1_6::exitEmergencyCallbackModeResponse(int slotId,
+int radio_1_5::exitEmergencyCallbackModeResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -8597,7 +6726,7 @@ int radio_1_6::exitEmergencyCallbackModeResponse(int slotId,
return 0;
}
-int radio_1_6::getSmscAddressResponse(int slotId,
+int radio_1_5::getSmscAddressResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -8618,7 +6747,7 @@ int radio_1_6::getSmscAddressResponse(int slotId,
return 0;
}
-int radio_1_6::setSmscAddressResponse(int slotId,
+int radio_1_5::setSmscAddressResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -8638,7 +6767,7 @@ int radio_1_6::setSmscAddressResponse(int slotId,
return 0;
}
-int radio_1_6::reportSmsMemoryStatusResponse(int slotId,
+int radio_1_5::reportSmsMemoryStatusResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -8659,7 +6788,7 @@ int radio_1_6::reportSmsMemoryStatusResponse(int slotId,
return 0;
}
-int radio_1_6::reportStkServiceIsRunningResponse(int slotId,
+int radio_1_5::reportStkServiceIsRunningResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -8680,7 +6809,7 @@ int radio_1_6::reportStkServiceIsRunningResponse(int slotId,
return 0;
}
-int radio_1_6::getCdmaSubscriptionSourceResponse(int slotId,
+int radio_1_5::getCdmaSubscriptionSourceResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -8702,7 +6831,7 @@ int radio_1_6::getCdmaSubscriptionSourceResponse(int slotId,
return 0;
}
-int radio_1_6::requestIsimAuthenticationResponse(int slotId,
+int radio_1_5::requestIsimAuthenticationResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -8725,7 +6854,7 @@ int radio_1_6::requestIsimAuthenticationResponse(int slotId,
return 0;
}
-int radio_1_6::acknowledgeIncomingGsmSmsWithPduResponse(int slotId,
+int radio_1_5::acknowledgeIncomingGsmSmsWithPduResponse(int slotId,
int responseType,
int serial, RIL_Errno e, void *response,
size_t responseLen) {
@@ -8748,7 +6877,7 @@ int radio_1_6::acknowledgeIncomingGsmSmsWithPduResponse(int slotId,
return 0;
}
-int radio_1_6::sendEnvelopeWithStatusResponse(int slotId,
+int radio_1_5::sendEnvelopeWithStatusResponse(int slotId,
int responseType, int serial, RIL_Errno e, void *response,
size_t responseLen) {
#if VDBG
@@ -8772,7 +6901,7 @@ int radio_1_6::sendEnvelopeWithStatusResponse(int slotId,
return 0;
}
-int radio_1_6::getVoiceRadioTechnologyResponse(int slotId,
+int radio_1_5::getVoiceRadioTechnologyResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -8794,7 +6923,7 @@ int radio_1_6::getVoiceRadioTechnologyResponse(int slotId,
return 0;
}
-int radio_1_6::getCellInfoListResponse(int slotId,
+int radio_1_5::getCellInfoListResponse(int slotId,
int responseType,
int serial, RIL_Errno e, void *response,
size_t responseLen) {
@@ -8802,40 +6931,21 @@ int radio_1_6::getCellInfoListResponse(int slotId,
RLOGD("getCellInfoListResponse: serial %d", serial);
#endif
- if (radioService[slotId]->mRadioResponse != NULL ||
- radioService[slotId]->mRadioResponseV1_2 != NULL) {
+ if (radioService[slotId]->mRadioResponse != NULL) {
RadioResponseInfo responseInfo = {};
populateResponseInfo(responseInfo, serial, responseType, e);
- Return<void> retStatus;
hidl_vec<CellInfo> ret;
if ((response == NULL && responseLen != 0)
|| responseLen % sizeof(RIL_CellInfo_v12) != 0) {
RLOGE("getCellInfoListResponse: Invalid response");
if (e == RIL_E_SUCCESS) responseInfo.error = RadioError::INVALID_RESPONSE;
-
- if (radioService[slotId]->mRadioResponseV1_2 != NULL) {
- hidl_vec<V1_2::CellInfo> ret;
- retStatus = radioService[slotId]->mRadioResponseV1_2->
- getCellInfoListResponse_1_2(responseInfo, ret);
- } else {
- hidl_vec<CellInfo> ret;
- retStatus = radioService[slotId]->mRadioResponse->
- getCellInfoListResponse(responseInfo, ret);
- }
} else {
- if (radioService[slotId]->mRadioResponseV1_2 != NULL) {
- hidl_vec<V1_2::CellInfo> ret;
- convertRilCellInfoListToHal_1_2(response, responseLen, ret);
- retStatus = radioService[slotId]->mRadioResponseV1_2->
- getCellInfoListResponse_1_2(responseInfo, ret);
- } else {
- hidl_vec<CellInfo> ret;
- convertRilCellInfoListToHal(response, responseLen, ret);
- retStatus = radioService[slotId]->mRadioResponse->
- getCellInfoListResponse(responseInfo, ret);
- }
+ convertRilCellInfoListToHal(response, responseLen, ret);
}
+
+ Return<void> retStatus = radioService[slotId]->mRadioResponse->getCellInfoListResponse(
+ responseInfo, ret);
radioService[slotId]->checkReturnStatus(retStatus);
} else {
RLOGE("getCellInfoListResponse: radioService[%d]->mRadioResponse == NULL", slotId);
@@ -8844,7 +6954,7 @@ int radio_1_6::getCellInfoListResponse(int slotId,
return 0;
}
-int radio_1_6::setCellInfoListRateResponse(int slotId,
+int radio_1_5::setCellInfoListRateResponse(int slotId,
int responseType,
int serial, RIL_Errno e, void *response,
size_t responseLen) {
@@ -8866,7 +6976,7 @@ int radio_1_6::setCellInfoListRateResponse(int slotId,
return 0;
}
-int radio_1_6::setInitialAttachApnResponse(int slotId,
+int radio_1_5::setInitialAttachApnResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -8893,7 +7003,7 @@ int radio_1_6::setInitialAttachApnResponse(int slotId,
return 0;
}
-int radio_1_6::getImsRegistrationStateResponse(int slotId,
+int radio_1_5::getImsRegistrationStateResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -8926,7 +7036,7 @@ int radio_1_6::getImsRegistrationStateResponse(int slotId,
return 0;
}
-int radio_1_6::sendImsSmsResponse(int slotId,
+int radio_1_5::sendImsSmsResponse(int slotId,
int responseType, int serial, RIL_Errno e, void *response,
size_t responseLen) {
#if VDBG
@@ -8948,7 +7058,7 @@ int radio_1_6::sendImsSmsResponse(int slotId,
return 0;
}
-int radio_1_6::iccTransmitApduBasicChannelResponse(int slotId,
+int radio_1_5::iccTransmitApduBasicChannelResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -8972,7 +7082,7 @@ int radio_1_6::iccTransmitApduBasicChannelResponse(int slotId,
return 0;
}
-int radio_1_6::iccOpenLogicalChannelResponse(int slotId,
+int radio_1_5::iccOpenLogicalChannelResponse(int slotId,
int responseType, int serial, RIL_Errno e, void *response,
size_t responseLen) {
#if VDBG
@@ -9010,7 +7120,7 @@ int radio_1_6::iccOpenLogicalChannelResponse(int slotId,
return 0;
}
-int radio_1_6::iccCloseLogicalChannelResponse(int slotId,
+int radio_1_5::iccCloseLogicalChannelResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -9032,7 +7142,7 @@ int radio_1_6::iccCloseLogicalChannelResponse(int slotId,
return 0;
}
-int radio_1_6::iccTransmitApduLogicalChannelResponse(int slotId,
+int radio_1_5::iccTransmitApduLogicalChannelResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -9056,7 +7166,7 @@ int radio_1_6::iccTransmitApduLogicalChannelResponse(int slotId,
return 0;
}
-int radio_1_6::nvReadItemResponse(int slotId,
+int radio_1_5::nvReadItemResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -9077,7 +7187,7 @@ int radio_1_6::nvReadItemResponse(int slotId,
return 0;
}
-int radio_1_6::nvWriteItemResponse(int slotId,
+int radio_1_5::nvWriteItemResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -9097,7 +7207,7 @@ int radio_1_6::nvWriteItemResponse(int slotId,
return 0;
}
-int radio_1_6::nvWriteCdmaPrlResponse(int slotId,
+int radio_1_5::nvWriteCdmaPrlResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -9117,7 +7227,7 @@ int radio_1_6::nvWriteCdmaPrlResponse(int slotId,
return 0;
}
-int radio_1_6::nvResetConfigResponse(int slotId,
+int radio_1_5::nvResetConfigResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -9137,7 +7247,7 @@ int radio_1_6::nvResetConfigResponse(int slotId,
return 0;
}
-int radio_1_6::setUiccSubscriptionResponse(int slotId,
+int radio_1_5::setUiccSubscriptionResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -9158,7 +7268,7 @@ int radio_1_6::setUiccSubscriptionResponse(int slotId,
return 0;
}
-int radio_1_6::setDataAllowedResponse(int slotId,
+int radio_1_5::setDataAllowedResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -9178,7 +7288,7 @@ int radio_1_6::setDataAllowedResponse(int slotId,
return 0;
}
-int radio_1_6::getHardwareConfigResponse(int slotId,
+int radio_1_5::getHardwareConfigResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -9208,7 +7318,7 @@ int radio_1_6::getHardwareConfigResponse(int slotId,
return 0;
}
-int radio_1_6::requestIccSimAuthenticationResponse(int slotId,
+int radio_1_5::requestIccSimAuthenticationResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -9232,7 +7342,7 @@ int radio_1_6::requestIccSimAuthenticationResponse(int slotId,
return 0;
}
-int radio_1_6::setDataProfileResponse(int slotId,
+int radio_1_5::setDataProfileResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -9258,7 +7368,7 @@ int radio_1_6::setDataProfileResponse(int slotId,
return 0;
}
-int radio_1_6::requestShutdownResponse(int slotId,
+int radio_1_5::requestShutdownResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -9291,7 +7401,7 @@ void responseRadioCapability(RadioResponseInfo& responseInfo, int serial,
}
}
-int radio_1_6::getRadioCapabilityResponse(int slotId,
+int radio_1_5::getRadioCapabilityResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -9313,7 +7423,7 @@ int radio_1_6::getRadioCapabilityResponse(int slotId,
return 0;
}
-int radio_1_6::setRadioCapabilityResponse(int slotId,
+int radio_1_5::setRadioCapabilityResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -9351,7 +7461,7 @@ LceStatusInfo responseLceStatusInfo(RadioResponseInfo& responseInfo, int serial,
return result;
}
-int radio_1_6::startLceServiceResponse(int slotId,
+int radio_1_5::startLceServiceResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -9374,7 +7484,7 @@ int radio_1_6::startLceServiceResponse(int slotId,
return 0;
}
-int radio_1_6::stopLceServiceResponse(int slotId,
+int radio_1_5::stopLceServiceResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -9397,7 +7507,7 @@ int radio_1_6::stopLceServiceResponse(int slotId,
return 0;
}
-int radio_1_6::pullLceDataResponse(int slotId,
+int radio_1_5::pullLceDataResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -9426,7 +7536,7 @@ int radio_1_6::pullLceDataResponse(int slotId,
return 0;
}
-int radio_1_6::getModemActivityInfoResponse(int slotId,
+int radio_1_5::getModemActivityInfoResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -9462,7 +7572,7 @@ int radio_1_6::getModemActivityInfoResponse(int slotId,
return 0;
}
-int radio_1_6::setAllowedCarriersResponse(int slotId,
+int radio_1_5::setAllowedCarriersResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -9514,7 +7624,7 @@ void prepareCarrierRestrictionsResponse(hidl_vec<Carrier>& allowedCarriers,
}
}
-int radio_1_6::getAllowedCarriersResponse(int slotId,
+int radio_1_5::getAllowedCarriersResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -9591,7 +7701,7 @@ int radio_1_6::getAllowedCarriersResponse(int slotId,
return 0;
}
-int radio_1_6::sendDeviceStateResponse(int slotId,
+int radio_1_5::sendDeviceStateResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responselen) {
#if VDBG
@@ -9611,24 +7721,24 @@ int radio_1_6::sendDeviceStateResponse(int slotId,
return 0;
}
-int radio_1_6::setCarrierInfoForImsiEncryptionResponse(int slotId,
+int radio_1_5::setCarrierInfoForImsiEncryptionResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
- RLOGD("setCarrierInfoForImsiEncryptionResponse: serial %d", serial);
- if (radioService[slotId]->mRadioResponseV1_1 != NULL) {
- RadioResponseInfo responseInfo = {};
- populateResponseInfo(responseInfo, serial, responseType, e);
- Return<void> retStatus = radioService[slotId]->mRadioResponseV1_1->
- setCarrierInfoForImsiEncryptionResponse(responseInfo);
- radioService[slotId]->checkReturnStatus(retStatus);
- } else {
- RLOGE("setCarrierInfoForImsiEncryptionResponse: radioService[%d]->mRadioResponseV1_1 == "
- "NULL", slotId);
- }
- return 0;
-}
-
-int radio_1_6::setIndicationFilterResponse(int slotId,
+ RLOGD("setCarrierInfoForImsiEncryptionResponse: serial %d", serial);
+ if (radioService[slotId]->mRadioResponseV1_4 != NULL) {
+ RadioResponseInfo responseInfo = {};
+ populateResponseInfo(responseInfo, serial, responseType, e);
+ Return<void> retStatus = radioService[slotId]->mRadioResponseV1_4->
+ setCarrierInfoForImsiEncryptionResponse(responseInfo);
+ radioService[slotId]->checkReturnStatus(retStatus);
+ } else {
+ RLOGE("setCarrierInfoForImsiEncryptionResponse: radioService[%d]->mRadioResponseV1_4 == "
+ "NULL", slotId);
+ }
+ return 0;
+}
+
+int radio_1_5::setIndicationFilterResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responselen) {
#if VDBG
@@ -9652,7 +7762,7 @@ int radio_1_6::setIndicationFilterResponse(int slotId,
return 0;
}
-int radio_1_6::setSimCardPowerResponse(int slotId,
+int radio_1_5::setSimCardPowerResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -9660,95 +7770,74 @@ int radio_1_6::setSimCardPowerResponse(int slotId,
#endif
if (radioService[slotId]->mRadioResponse != NULL
- || radioService[slotId]->mRadioResponseV1_1 != NULL
- || radioService[slotId]->mRadioResponseV1_6 != NULL) {
- if (radioService[slotId]->mRadioResponseV1_6 != NULL) {
- ::android::hardware::radio::V1_6::RadioResponseInfo responseInfo = {};
- populateResponseInfo_1_6(responseInfo, serial, responseType, e);
- Return<void> retStatus = radioService[slotId]->mRadioResponseV1_6->
- setSimCardPowerResponse_1_6(responseInfo);
- radioService[slotId]->checkReturnStatus(retStatus);
- } else if (radioService[slotId]->mRadioResponseV1_1 != NULL) {
- RLOGD("setSimCardPowerResponse: radioService[%d]->mRadioResponseV1_6 == NULL", slotId);
- RadioResponseInfo responseInfo = {};
- populateResponseInfo(responseInfo, serial, responseType, e);
- Return<void> retStatus = radioService[slotId]->mRadioResponseV1_1->
+ || radioService[slotId]->mRadioResponseV1_4 != NULL) {
+ RadioResponseInfo responseInfo = {};
+ populateResponseInfo(responseInfo, serial, responseType, e);
+ if (radioService[slotId]->mRadioResponseV1_4 != NULL) {
+ Return<void> retStatus = radioService[slotId]->mRadioResponseV1_4->
setSimCardPowerResponse_1_1(responseInfo);
radioService[slotId]->checkReturnStatus(retStatus);
} else {
- RLOGD("setSimCardPowerResponse: radioService[%d]->mRadioResponseV1_6 and V1_1 == NULL",
+ RLOGD("setSimCardPowerResponse: radioService[%d]->mRadioResponseV1_4 == NULL",
slotId);
- RadioResponseInfo responseInfo = {};
- populateResponseInfo(responseInfo, serial, responseType, e);
- Return<void> retStatus = radioService[slotId]->mRadioResponse
- ->setSimCardPowerResponse(responseInfo);
+ Return<void> retStatus
+ = radioService[slotId]->mRadioResponse->setSimCardPowerResponse(responseInfo);
radioService[slotId]->checkReturnStatus(retStatus);
}
} else {
RLOGE("setSimCardPowerResponse: radioService[%d]->mRadioResponse == NULL && "
- "radioService[%d]->mRadioResponseV1_1 and V1_6 == NULL", slotId, slotId);
+ "radioService[%d]->mRadioResponseV1_4 == NULL", slotId, slotId);
}
return 0;
}
-int radio_1_6::startNetworkScanResponse(int slotId, int responseType, int serial, RIL_Errno e,
- void *response, size_t responseLen) {
+int radio_1_5::startNetworkScanResponse(int slotId, int responseType, int serial, RIL_Errno e,
+ void *response, size_t responseLen) {
#if VDBG
RLOGD("startNetworkScanResponse: serial %d", serial);
#endif
+ RadioResponseInfo responseInfo = {};
+ populateResponseInfo(responseInfo, serial, responseType, e);
- if (radioService[slotId]->mRadioResponseV1_1 != NULL ||
- radioService[slotId]->mRadioResponseV1_2 != NULL ||
- radioService[slotId]->mRadioResponseV1_4 != NULL ||
- radioService[slotId]->mRadioResponseV1_6 != NULL) {
- RadioResponseInfo responseInfo = {};
- populateResponseInfo(responseInfo, serial, responseType, e);
-
- if (radioService[slotId]->mRadioResponseV1_6 != NULL) {
- Return<void> retStatus = radioService[slotId]->mRadioResponseV1_6
- ->startNetworkScanResponse_1_5(responseInfo);
- radioService[slotId]->checkReturnStatus(retStatus);
- } else if (radioService[slotId]->mRadioResponseV1_4 != NULL) {
- Return<void> retStatus = radioService[slotId]->mRadioResponseV1_4
- ->startNetworkScanResponse_1_4(responseInfo);
- radioService[slotId]->checkReturnStatus(retStatus);
- } else if (radioService[slotId]->mRadioResponseV1_2 != NULL) {
- Return<void> retStatus = radioService[slotId]->mRadioResponseV1_2
- ->startNetworkScanResponse(responseInfo);
- radioService[slotId]->checkReturnStatus(retStatus);
- } else if (radioService[slotId]->mRadioResponseV1_1 != NULL) {
- Return<void> retStatus = radioService[slotId]->mRadioResponseV1_1
- ->startNetworkScanResponse(responseInfo);
- radioService[slotId]->checkReturnStatus(retStatus);
- } else {
- RLOGE("startNetworkScanResponse: radioService[%d]->mRadioResponseV1_1 == NULL or "
- "radioService[%d]->mRadioResponseV1_4 == NULL", slotId, slotId);
- }
+ if (radioService[slotId]->mRadioResponseV1_5 != NULL) {
+ Return<void> retStatus = radioService[slotId]->mRadioResponseV1_5
+ ->startNetworkScanResponse_1_5(responseInfo);
+ radioService[slotId]->checkReturnStatus(retStatus);
+ } else if (radioService[slotId]->mRadioResponseV1_4 != NULL) {
+ Return<void> retStatus = radioService[slotId]->mRadioResponseV1_4
+ ->startNetworkScanResponse_1_4(responseInfo);
+ radioService[slotId]->checkReturnStatus(retStatus);
+ } else if (radioService[slotId]->mRadioResponseV1_2 != NULL) {
+ Return<void> retStatus = radioService[slotId]->mRadioResponseV1_2
+ ->startNetworkScanResponse(responseInfo);
+ radioService[slotId]->checkReturnStatus(retStatus);
+ } else {
+ RLOGE("startNetworkScanResponse: radioService[%d]->mRadioResponse == NULL", slotId);
}
return 0;
}
-int radio_1_6::stopNetworkScanResponse(int slotId, int responseType, int serial, RIL_Errno e,
+int radio_1_5::stopNetworkScanResponse(int slotId, int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
RLOGD("stopNetworkScanResponse: serial %d", serial);
#endif
- if (radioService[slotId]->mRadioResponseV1_1 != NULL) {
+ if (radioService[slotId]->mRadioResponseV1_4 != NULL) {
RadioResponseInfo responseInfo = {};
populateResponseInfo(responseInfo, serial, responseType, e);
Return<void> retStatus
- = radioService[slotId]->mRadioResponseV1_1->stopNetworkScanResponse(responseInfo);
+ = radioService[slotId]->mRadioResponseV1_4->stopNetworkScanResponse(responseInfo);
radioService[slotId]->checkReturnStatus(retStatus);
} else {
- RLOGE("stopNetworkScanResponse: radioService[%d]->mRadioResponseV1_1 == NULL", slotId);
+ RLOGE("stopNetworkScanResponse: radioService[%d]->mRadioResponseV1_4 == NULL", slotId);
}
return 0;
}
-int radio_1_6::emergencyDialResponse(int slotId, int responseType, int serial, RIL_Errno e,
+int radio_1_5::emergencyDialResponse(int slotId, int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
RLOGD("emergencyDialResponse: serial %d", serial);
@@ -9772,7 +7861,7 @@ void convertRilKeepaliveStatusToHal(const RIL_KeepaliveStatus *rilStatus,
halStatus.code = static_cast<V1_1::KeepaliveStatusCode>(rilStatus->code);
}
-int radio_1_6::startKeepaliveResponse(int slotId, int responseType, int serial, RIL_Errno e,
+int radio_1_5::startKeepaliveResponse(int slotId, int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
RLOGD("%s(): %d", __FUNCTION__, serial);
@@ -9781,8 +7870,8 @@ int radio_1_6::startKeepaliveResponse(int slotId, int responseType, int serial,
populateResponseInfo(responseInfo, serial, responseType, e);
// If we don't have a radio service, there's nothing we can do
- if (radioService[slotId]->mRadioResponseV1_1 == NULL) {
- RLOGE("%s: radioService[%d]->mRadioResponseV1_1 == NULL", __FUNCTION__, slotId);
+ if (radioService[slotId]->mRadioResponseV1_4 == NULL) {
+ RLOGE("%s: radioService[%d]->mRadioResponseV1_4 == NULL", __FUNCTION__, slotId);
return 0;
}
@@ -9795,12 +7884,12 @@ int radio_1_6::startKeepaliveResponse(int slotId, int responseType, int serial,
}
Return<void> retStatus =
- radioService[slotId]->mRadioResponseV1_1->startKeepaliveResponse(responseInfo, ks);
+ radioService[slotId]->mRadioResponseV1_4->startKeepaliveResponse(responseInfo, ks);
radioService[slotId]->checkReturnStatus(retStatus);
return 0;
}
-int radio_1_6::stopKeepaliveResponse(int slotId, int responseType, int serial, RIL_Errno e,
+int radio_1_5::stopKeepaliveResponse(int slotId, int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
RLOGD("%s(): %d", __FUNCTION__, serial);
@@ -9809,18 +7898,18 @@ int radio_1_6::stopKeepaliveResponse(int slotId, int responseType, int serial, R
populateResponseInfo(responseInfo, serial, responseType, e);
// If we don't have a radio service, there's nothing we can do
- if (radioService[slotId]->mRadioResponseV1_1 == NULL) {
- RLOGE("%s: radioService[%d]->mRadioResponseV1_1 == NULL", __FUNCTION__, slotId);
+ if (radioService[slotId]->mRadioResponseV1_4 == NULL) {
+ RLOGE("%s: radioService[%d]->mRadioResponseV1_4 == NULL", __FUNCTION__, slotId);
return 0;
}
Return<void> retStatus =
- radioService[slotId]->mRadioResponseV1_1->stopKeepaliveResponse(responseInfo);
+ radioService[slotId]->mRadioResponseV1_4->stopKeepaliveResponse(responseInfo);
radioService[slotId]->checkReturnStatus(retStatus);
return 0;
}
-int radio_1_6::getModemStackStatusResponse(int slotId, int responseType, int serial, RIL_Errno e,
+int radio_1_5::getModemStackStatusResponse(int slotId, int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
RLOGD("%s(): %d", __FUNCTION__, serial);
@@ -9841,7 +7930,7 @@ int radio_1_6::getModemStackStatusResponse(int slotId, int responseType, int ser
return 0;
}
-int radio_1_6::enableModemResponse(int slotId, int responseType, int serial, RIL_Errno e,
+int radio_1_5::enableModemResponse(int slotId, int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
RLOGD("%s(): %d", __FUNCTION__, serial);
@@ -9861,7 +7950,7 @@ int radio_1_6::enableModemResponse(int slotId, int responseType, int serial, RIL
return 0;
}
-int radio_1_6::sendRequestRawResponse(int slotId,
+int radio_1_5::sendRequestRawResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -9892,7 +7981,7 @@ int radio_1_6::sendRequestRawResponse(int slotId,
return 0;
}
-int radio_1_6::sendRequestStringsResponse(int slotId,
+int radio_1_5::sendRequestStringsResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
@@ -9929,8 +8018,8 @@ int radio_1_6::sendRequestStringsResponse(int slotId,
return 0;
}
-int radio_1_6::setSystemSelectionChannelsResponse(int slotId, int responseType, int serial,
- RIL_Errno e, void* response, size_t responseLen) {
+int radio_1_5::setSystemSelectionChannelsResponse(int slotId, int responseType, int serial,
+ RIL_Errno e, void* /* response */, size_t responseLen) {
#if VDBG
RLOGD("setSystemSelectionChannelsResponse: serial %d", serial);
#endif
@@ -9953,31 +8042,8 @@ int radio_1_6::setSystemSelectionChannelsResponse(int slotId, int responseType,
return 0;
}
-int radio_1_6::getSystemSelectionChannelsResponse(int slotId, int responseType, int serial,
- RIL_Errno e, void* response, size_t responseLen) {
-#if VDBG
- RLOGD("getSystemSelectionChannelsResponse: serial %d", serial);
-#endif
- V1_6::RadioResponseInfo responseInfo = {};
- populateResponseInfo_1_6(responseInfo, serial, responseType, e);
-
- if (radioService[slotId]->mRadioResponseV1_6 != NULL) {
- hidl_vec<::android::hardware::radio::V1_5::RadioAccessSpecifier> ret;
- Return<void> retStatus =
- radioService[slotId]
- ->mRadioResponseV1_6->getSystemSelectionChannelsResponse(
- responseInfo, ret);
- radioService[slotId]->checkReturnStatus(retStatus);
- } else {
- RLOGE("getSystemSelectionChannelsResponse: radioService[%d]->mRadioResponse == NULL",
- slotId);
- }
-
- return 0;
-}
-
-int radio_1_6::setSignalStrengthReportingCriteriaResponse(int slotId, int responseType, int serial,
- RIL_Errno e, void* response, size_t responseLen) {
+int radio_1_5::setSignalStrengthReportingCriteriaResponse(int slotId, int responseType, int serial,
+ RIL_Errno e, void* /* response */, size_t responseLen) {
#if VDBG
RLOGD("setSignalStrengthReportingCriteriaResponse: serial %d", serial);
#endif
@@ -10000,8 +8066,8 @@ int radio_1_6::setSignalStrengthReportingCriteriaResponse(int slotId, int respon
return 0;
}
-int radio_1_6::setLinkCapacityReportingCriteriaResponse(int slotId, int responseType, int serial,
- RIL_Errno e, void* response, size_t responseLen) {
+int radio_1_5::setLinkCapacityReportingCriteriaResponse(int slotId, int responseType, int serial,
+ RIL_Errno e, void* /* response */, size_t responseLen) {
#if VDBG
RLOGD("setLinkCapacityReportingCriteriaResponse: serial %d", serial);
#endif
@@ -10024,7 +8090,7 @@ int radio_1_6::setLinkCapacityReportingCriteriaResponse(int slotId, int response
return 0;
}
-int radio_1_6::enableUiccApplicationsResponse(int slotId, int responseType, int serial,
+int radio_1_5::enableUiccApplicationsResponse(int slotId, int responseType, int serial,
RIL_Errno e, void* /* response */, size_t responseLen) {
#if VDBG
RLOGD("%s(): %d", __FUNCTION__, serial);
@@ -10045,7 +8111,7 @@ int radio_1_6::enableUiccApplicationsResponse(int slotId, int responseType, int
return 0;
}
-int radio_1_6::areUiccApplicationsEnabledResponse(int slotId, int responseType, int serial,
+int radio_1_5::areUiccApplicationsEnabledResponse(int slotId, int responseType, int serial,
RIL_Errno e, void* response, size_t responseLen) {
#if VDBG
RLOGD("%s(): %d", __FUNCTION__, serial);
@@ -10073,7 +8139,7 @@ int radio_1_6::areUiccApplicationsEnabledResponse(int slotId, int responseType,
return 0;
}
-int radio_1_6::getBarringInfoResponse(int slotId,
+int radio_1_5::getBarringInfoResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responselen) {
#if VDBG
@@ -10084,45 +8150,26 @@ int radio_1_6::getBarringInfoResponse(int slotId,
RadioResponseInfo responseInfo = {};
populateResponseInfo(responseInfo, serial, responseType, e);
::android::hardware::radio::V1_5::CellIdentity cellIdentity;
- hidl_vec<::android::hardware::radio::V1_5::BarringInfo> barringInfos = {};
-
- if (response == NULL) { /* data for vts */
- V1_5::BarringInfo barringInfo = {};
- barringInfo.serviceType = V1_5::BarringInfo::ServiceType::CS_SERVICE;
- barringInfo.barringType = V1_5::BarringInfo::BarringType::NONE;
-
- V1_5::CellIdentityLte cellIdentityLte = {};
- cellIdentity.lte(cellIdentityLte);
- barringInfos.resize(1);
- barringInfos[0] = barringInfo;
-
+ hidl_vec<::android::hardware::radio::V1_5::BarringInfo> barringInfo;
Return<void> retStatus
= radioService[slotId]->mRadioResponseV1_5->
- getBarringInfoResponse(responseInfo, cellIdentity, barringInfos);
+ getBarringInfoResponse(responseInfo, cellIdentity, barringInfo);
radioService[slotId]->checkReturnStatus(retStatus);
- } else {
- RLOGE("getBarringInfoResponse: radioService[%d]->mRadioResponse == NULL",
- slotId);
- }
+ } else {
+ RLOGE("getBarringInfoResponse: radioService[%d]->mRadioResponse == NULL",
+ slotId);
}
+
return 0;
}
-int radio_1_6::sendCdmaSmsExpectMoreResponse(int slotId, int responseType, int serial, RIL_Errno e,
+int radio_1_5::sendCdmaSmsExpectMoreResponse(int slotId, int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
#if VDBG
RLOGD("sendCdmaSmsExpectMoreResponse: serial %d", serial);
#endif
- if (radioService[slotId]->mRadioResponseV1_6 != NULL) {
- ::android::hardware::radio::V1_6::RadioResponseInfo responseInfo_1_6 = {};
- SendSmsResult result = makeSendSmsResult_1_6(responseInfo_1_6, serial, responseType, e,
- response, responseLen);
-
- Return<void> retStatus = radioService[slotId]->mRadioResponseV1_6
- ->sendCdmaSmsExpectMoreResponse_1_6(responseInfo_1_6, result);
- radioService[slotId]->checkReturnStatus(retStatus);
- } else if (radioService[slotId]->mRadioResponseV1_5 != NULL) {
+ if (radioService[slotId]->mRadioResponseV1_5 != NULL) {
RadioResponseInfo responseInfo = {};
SendSmsResult result = makeSendSmsResult(responseInfo, serial, responseType, e, response,
responseLen);
@@ -10137,7 +8184,7 @@ int radio_1_6::sendCdmaSmsExpectMoreResponse(int slotId, int responseType, int s
return 0;
}
-int radio_1_6::supplySimDepersonalizationResponse(int slotId, int responseType, int serial,
+int radio_1_5::supplySimDepersonalizationResponse(int slotId, int responseType, int serial,
RIL_Errno e, void *response, size_t responseLen) {
#if VDBG
RLOGD("supplySimDepersonalizationResponse: serial %d", serial);
@@ -10167,200 +8214,6 @@ int radio_1_6::supplySimDepersonalizationResponse(int slotId, int responseType,
return 0;
}
-int radio_1_6::setNrDualConnectivityStateResponse(int slotId, int responseType, int serial,
- RIL_Errno e, void* /* response */, size_t responseLen) {
-#if VDBG
- RLOGD("%s(): %d", __FUNCTION__, serial);
-#endif
- V1_6::RadioResponseInfo responseInfo = {};
- populateResponseInfo_1_6(responseInfo, serial, responseType, e);
-
- // If we don't have a radio service, there's nothing we can do
- if (radioService[slotId]->mRadioResponseV1_6 == NULL) {
- RLOGE("%s: radioService[%d]->mRadioResponseV1_6 == NULL", __FUNCTION__, slotId);
- return 0;
- }
-
- Return<void> retStatus =
- radioService[slotId]->mRadioResponseV1_6->setNrDualConnectivityStateResponse(
- responseInfo);
- radioService[slotId]->checkReturnStatus(retStatus);
- return 0;
-}
-
-int radio_1_6::isNrDualConnectivityEnabledResponse(int slotId, int responseType, int serial,
- RIL_Errno e, void* response, size_t responseLen) {
-#if VDBG
- RLOGD("%s(): %d", __FUNCTION__, serial);
-#endif
- V1_6::RadioResponseInfo responseInfo = {};
- populateResponseInfo_1_6(responseInfo, serial, responseType, e);
-
- // If we don't have a radio service, there's nothing we can do
- if (radioService[slotId]->mRadioResponseV1_6 == NULL) {
- RLOGE("%s: radioService[%d]->mRadioResponseV1_6 == NULL", __FUNCTION__, slotId);
- return 0;
- }
-
- bool enable = false;
- if (response == NULL || responseLen != sizeof(bool)) {
- RLOGE("isNrDualConnectivityEnabledResponseInvalid response.");
- } else {
- enable = (*((bool *) response));
- }
-
- Return<void> retStatus =
- radioService[slotId]->mRadioResponseV1_6->isNrDualConnectivityEnabledResponse(
- responseInfo, enable);
- radioService[slotId]->checkReturnStatus(retStatus);
- return 0;
-}
-
-int radio_1_6::allocatePduSessionIdResponse(int slotId, int responseType, int serial,
- RIL_Errno e, void* response, size_t responseLen) {
-#if VDBG
- RLOGD("%s(): %d", __FUNCTION__, serial);
-#endif
- // If we don't have a radio service, there's nothing we can do
- if (radioService[slotId]->mRadioResponseV1_6 == NULL) {
- RLOGE("%s: radioService[%d]->mRadioResponseV1_6 == NULL", __FUNCTION__, slotId);
- return 0;
- }
- V1_6::RadioResponseInfo responseInfo = {};
- populateResponseInfo_1_6(responseInfo, serial, responseType, e);
-
- Return<void> retStatus =
- radioService[slotId]->mRadioResponseV1_6->allocatePduSessionIdResponse(responseInfo, -1);
- radioService[slotId]->checkReturnStatus(retStatus);
- return 0;
-}
-
-int radio_1_6::releasePduSessionIdResponse(int slotId, int responseType, int serial,
- RIL_Errno e, void* response, size_t responseLen) {
-#if VDBG
- RLOGD("%s(): %d", __FUNCTION__, serial);
-#endif
- // If we don't have a radio service, there's nothing we can do
- if (radioService[slotId]->mRadioResponseV1_6 == NULL) {
- RLOGE("%s: radioService[%d]->mRadioResponseV1_6 == NULL", __FUNCTION__, slotId);
- return 0;
- }
-
- V1_6::RadioResponseInfo responseInfo = {};
- populateResponseInfo_1_6(responseInfo, serial, responseType, e);
-
- Return<void> retStatus =
- radioService[slotId]->mRadioResponseV1_6->releasePduSessionIdResponse(responseInfo);
- radioService[slotId]->checkReturnStatus(retStatus);
- return 0;
-}
-
-int radio_1_6::startHandoverResponse(int slotId, int responseType, int serial,
- RIL_Errno e, void* response, size_t responseLen) {
- // If we don't have a radio service, there's nothing we can do
- if (radioService[slotId]->mRadioResponseV1_6 == NULL) {
- RLOGE("%s: radioService[%d]->mRadioResponseV1_6 == NULL", __FUNCTION__, slotId);
- return 0;
- }
- V1_6::RadioResponseInfo responseInfo = {};
- populateResponseInfo_1_6(responseInfo, serial, responseType, e);
-
- Return<void> retStatus =
- radioService[slotId]->mRadioResponseV1_6->startHandoverResponse(responseInfo);
-
-#if VDBG
- RLOGD("%s(): %d", __FUNCTION__, serial);
-#endif
- return 0;
-}
-
-int radio_1_6::cancelHandoverResponse(int slotId, int responseType, int serial,
- RIL_Errno e, void* response, size_t responseLen) {
- // If we don't have a radio service, there's nothing we can do
- if (radioService[slotId]->mRadioResponseV1_6 == NULL) {
- RLOGE("%s: radioService[%d]->mRadioResponseV1_6 == NULL", __FUNCTION__, slotId);
- return 0;
- }
- V1_6::RadioResponseInfo responseInfo = {};
- populateResponseInfo_1_6(responseInfo, serial, responseType, e);
-
- Return<void> retStatus =
- radioService[slotId]->mRadioResponseV1_6->cancelHandoverResponse(responseInfo);
-
-#if VDBG
- RLOGD("%s(): %d", __FUNCTION__, serial);
-#endif
- return 0;
-}
-
-
-int radio_1_6::setDataThrottlingResponse(int slotId, int responseType,
- int serial, RIL_Errno e, void *response, size_t responselen) {
-#if VDBG
- RLOGD("setDataThrottlingResponse: serial %d", serial);
-#endif
-
- if (radioService[slotId]->mRadioResponseV1_6 == NULL) {
- RLOGE("%s: radioService[%d]->mRadioResponseV1_6 == NULL", __FUNCTION__, slotId);
- return 0;
- }
-
- V1_6::RadioResponseInfo responseInfo = {};
- populateResponseInfo_1_6(responseInfo, serial, responseType, e);
-
-
- Return<void> retstatus =
- radioService[slotId]->mRadioResponseV1_6->setDataThrottlingResponse(
- responseInfo);
- radioService[slotId]->checkReturnStatus(retstatus);
- return 0;
-}
-
-int radio_1_6::getSlicingConfigResponse(int slotId, int responseType, int serial,
- RIL_Errno e, void* response, size_t responseLen) {
-#if VDBG
- RLOGD("getSlicingConfigResponse: serial %d", serial);
-#endif
-
- if (radioService[slotId]->mRadioResponse != NULL) {
- V1_6::RadioResponseInfo responseInfo = {};
- populateResponseInfo_1_6(responseInfo, serial, responseType, e);
-
- V1_6::SlicingConfig slicingConfig = {};
- Return<void> retStatus = radioService[slotId]->mRadioResponseV1_6->
- getSlicingConfigResponse(responseInfo, slicingConfig);
- radioService[slotId]->checkReturnStatus(retStatus);
- } else {
- RLOGE("getSlicingConfigResponse: radioService[%d]->mRadioResponse == NULL", slotId);
- }
-
- return 0;
-}
-
-int radio_1_6::getSimPhonebookRecordsResponse(int slotId, int responseType, int serial,
- RIL_Errno e, void *response, size_t responseLen) {
-#if VDBG
- RLOGD("getSimPhonebookRecordsResponse: serial %d", serial);
-#endif
- return 0;
-}
-
-int radio_1_6::getSimPhonebookCapacityResponse(int slotId, int responseType, int serial,
- RIL_Errno e, void *response, size_t responseLen) {
-#if VDBG
- RLOGD("getSimPhonebookRecordsResponse: serial %d", serial);
-#endif
- return 0;
-}
-
-int radio_1_6::updateSimPhonebookRecordsResponse(int slotId, int responseType, int serial,
- RIL_Errno e, void *response, size_t responseLen) {
-#if VDBG
- RLOGD("getSimPhonebookRecordsResponse: serial %d", serial);
-#endif
- return 0;
-}
-
/***************************************************************************************************
* INDICATION FUNCTIONS
* The below function handle unsolicited messages coming from the Radio
@@ -10372,7 +8225,7 @@ RadioIndicationType convertIntToRadioIndicationType(int indicationType) {
(RadioIndicationType::UNSOLICITED_ACK_EXP);
}
-int radio_1_6::radioStateChangedInd(int slotId,
+int radio_1_5::radioStateChangedInd(int slotId,
int indicationType, int token, RIL_Errno e, void *response,
size_t responseLen) {
if (radioService[slotId] != NULL && radioService[slotId]->mRadioIndication != NULL) {
@@ -10389,7 +8242,7 @@ int radio_1_6::radioStateChangedInd(int slotId,
return 0;
}
-int radio_1_6::callStateChangedInd(int slotId,
+int radio_1_5::callStateChangedInd(int slotId,
int indicationType, int token, RIL_Errno e, void *response,
size_t responseLen) {
if (radioService[slotId] != NULL && radioService[slotId]->mRadioIndication != NULL) {
@@ -10406,7 +8259,7 @@ int radio_1_6::callStateChangedInd(int slotId,
return 0;
}
-int radio_1_6::networkStateChangedInd(int slotId,
+int radio_1_5::networkStateChangedInd(int slotId,
int indicationType, int token, RIL_Errno e, void *response,
size_t responseLen) {
if (radioService[slotId] != NULL && radioService[slotId]->mRadioIndication != NULL) {
@@ -10424,7 +8277,7 @@ int radio_1_6::networkStateChangedInd(int slotId,
return 0;
}
-extern "C" uint8_t hexCharToInt(uint8_t c) {
+uint8_t hexCharToInt(uint8_t c) {
if (c >= '0' && c <= '9') return (c - '0');
if (c >= 'A' && c <= 'F') return (c - 'A' + 10);
if (c >= 'a' && c <= 'f') return (c - 'a' + 10);
@@ -10432,7 +8285,7 @@ extern "C" uint8_t hexCharToInt(uint8_t c) {
return INVALID_HEX_CHAR;
}
-extern "C" uint8_t * convertHexStringToBytes(void *response, size_t responseLen) {
+uint8_t * convertHexStringToBytes(void *response, size_t responseLen) {
if (responseLen % 2 != 0) {
return NULL;
}
@@ -10460,7 +8313,7 @@ extern "C" uint8_t * convertHexStringToBytes(void *response, size_t responseLen)
return bytes;
}
-int radio_1_6::newSmsInd(int slotId, int indicationType,
+int radio_1_5::newSmsInd(int slotId, int indicationType,
int token, RIL_Errno e, void *response, size_t responseLen) {
if (radioService[slotId] != NULL && radioService[slotId]->mRadioIndication != NULL) {
if (response == NULL || responseLen == 0) {
@@ -10490,7 +8343,7 @@ int radio_1_6::newSmsInd(int slotId, int indicationType,
return 0;
}
-int radio_1_6::newSmsStatusReportInd(int slotId,
+int radio_1_5::newSmsStatusReportInd(int slotId,
int indicationType, int token, RIL_Errno e, void *response,
size_t responseLen) {
if (radioService[slotId] != NULL && radioService[slotId]->mRadioIndication != NULL) {
@@ -10521,7 +8374,7 @@ int radio_1_6::newSmsStatusReportInd(int slotId,
return 0;
}
-int radio_1_6::newSmsOnSimInd(int slotId, int indicationType,
+int radio_1_5::newSmsOnSimInd(int slotId, int indicationType,
int token, RIL_Errno e, void *response, size_t responseLen) {
if (radioService[slotId] != NULL && radioService[slotId]->mRadioIndication != NULL) {
if (response == NULL || responseLen != sizeof(int)) {
@@ -10542,7 +8395,7 @@ int radio_1_6::newSmsOnSimInd(int slotId, int indicationType,
return 0;
}
-int radio_1_6::onUssdInd(int slotId, int indicationType,
+int radio_1_5::onUssdInd(int slotId, int indicationType,
int token, RIL_Errno e, void *response, size_t responseLen) {
if (radioService[slotId] != NULL && radioService[slotId]->mRadioIndication != NULL) {
if (response == NULL || responseLen != 2 * sizeof(char *)) {
@@ -10566,7 +8419,7 @@ int radio_1_6::onUssdInd(int slotId, int indicationType,
return 0;
}
-int radio_1_6::nitzTimeReceivedInd(int slotId,
+int radio_1_5::nitzTimeReceivedInd(int slotId,
int indicationType, int token, RIL_Errno e, void *response,
size_t responseLen) {
if (radioService[slotId] != NULL && radioService[slotId]->mRadioIndication != NULL) {
@@ -10593,7 +8446,7 @@ int radio_1_6::nitzTimeReceivedInd(int slotId,
void convertRilSignalStrengthToHal(void *response, size_t responseLen,
SignalStrength& signalStrength) {
- RIL_SignalStrength_v12 *rilSignalStrength = (RIL_SignalStrength_v12 *) response;
+ RIL_SignalStrength_v10 *rilSignalStrength = (RIL_SignalStrength_v10 *) response;
// Fixup LTE for backwards compatibility
// signalStrength: -1 -> 99
@@ -10638,61 +8491,23 @@ void convertRilSignalStrengthToHal(void *response, size_t responseLen,
signalStrength.tdScdma.rscp = rilSignalStrength->TD_SCDMA_SignalStrength.rscp;
}
-void convertRilSignalStrengthToHal_1_4(void *response, size_t responseLen,
- V1_4::SignalStrength& signalStrength_1_4) {
- SignalStrength signalStrength = {};
- convertRilSignalStrengthToHal(response, responseLen, signalStrength);
- signalStrength_1_4.gsm = signalStrength.gw;
- signalStrength_1_4.cdma = signalStrength.cdma;
- signalStrength_1_4.evdo = signalStrength.evdo;
- signalStrength_1_4.lte = signalStrength.lte;
-
- RIL_SignalStrength_v12 *rilSignalStrength = (RIL_SignalStrength_v12 *) response;
- signalStrength_1_4.wcdma.base.signalStrength =
- rilSignalStrength->WCDMA_SignalStrength.signalStrength;
- signalStrength_1_4.wcdma.base.bitErrorRate =
- rilSignalStrength->WCDMA_SignalStrength.bitErrorRate;
- signalStrength_1_4.wcdma.rscp = INT_MAX;
- signalStrength_1_4.wcdma.ecno = INT_MAX;
-
- signalStrength_1_4.tdscdma.signalStrength = INT_MAX;
- signalStrength_1_4.tdscdma.bitErrorRate = INT_MAX;
- signalStrength_1_4.tdscdma.rscp = INT_MAX;
-
- signalStrength_1_4.nr.ssRsrp = rilSignalStrength->NR_SignalStrength.ssRsrp;
- signalStrength_1_4.nr.ssRsrq = rilSignalStrength->NR_SignalStrength.ssRsrq;
- signalStrength_1_4.nr.ssSinr = rilSignalStrength->NR_SignalStrength.ssSinr;
- signalStrength_1_4.nr.csiRsrp = rilSignalStrength->NR_SignalStrength.csiRsrp;
- signalStrength_1_4.nr.csiRsrq = rilSignalStrength->NR_SignalStrength.csiRsrq;
- signalStrength_1_4.nr.csiSinr = rilSignalStrength->NR_SignalStrength.ssSinr;
-}
-
-int radio_1_6::currentSignalStrengthInd(int slotId,
+int radio_1_5::currentSignalStrengthInd(int slotId,
int indicationType, int token, RIL_Errno e,
void *response, size_t responseLen) {
- if (radioService[slotId] != NULL &&
- (radioService[slotId]->mRadioIndication != NULL ||
- radioService[slotId]->mRadioIndicationV1_4 != NULL)) {
- if (response == NULL || responseLen != sizeof(RIL_SignalStrength_v12)) {
+ if (radioService[slotId] != NULL && radioService[slotId]->mRadioIndication != NULL) {
+ if (response == NULL || responseLen != sizeof(RIL_SignalStrength_v10)) {
RLOGE("currentSignalStrengthInd: invalid response");
return 0;
}
+ SignalStrength signalStrength = {};
+ convertRilSignalStrengthToHal(response, responseLen, signalStrength);
+
#if VDBG
RLOGD("currentSignalStrengthInd");
#endif
- Return<void> retStatus;
- if (radioService[slotId]->mRadioIndicationV1_4 != NULL) {
- V1_4::SignalStrength signalStrength_1_4 = {};
- convertRilSignalStrengthToHal_1_4(response, responseLen, signalStrength_1_4);
- retStatus = radioService[slotId]->mRadioIndicationV1_4->currentSignalStrength_1_4(
- convertIntToRadioIndicationType(indicationType), signalStrength_1_4);
- } else {
- SignalStrength signalStrength = {};
- convertRilSignalStrengthToHal(response, responseLen, signalStrength);
- retStatus = radioService[slotId]->mRadioIndication->currentSignalStrength(
- convertIntToRadioIndicationType(indicationType), signalStrength);
- }
+ Return<void> retStatus = radioService[slotId]->mRadioIndication->currentSignalStrength(
+ convertIntToRadioIndicationType(indicationType), signalStrength);
radioService[slotId]->checkReturnStatus(retStatus);
} else {
RLOGE("currentSignalStrengthInd: radioService[%d]->mRadioIndication == NULL",
@@ -10792,43 +8607,6 @@ void convertRilDataCallToHal(RIL_Data_Call_Response_v12 *dcResponse,
dcResult.mtuV6 = dcResponse->mtuV6;
}
-void convertRilDataCallToHal(RIL_Data_Call_Response_v12 *dcResponse,
- ::android::hardware::radio::V1_6::SetupDataCallResult& dcResult) {
- dcResult.cause = (::android::hardware::radio::V1_6::DataCallFailCause) dcResponse->status;
- dcResult.suggestedRetryTime = dcResponse->suggestedRetryTime;
- dcResult.cid = dcResponse->cid;
- dcResult.active = (::android::hardware::radio::V1_4::DataConnActiveStatus)dcResponse->active;
- dcResult.type = convertToPdpProtocolType(convertCharPtrToHidlString(dcResponse->type));
- dcResult.ifname = convertCharPtrToHidlString(dcResponse->ifname);
-
- std::vector<::android::hardware::radio::V1_5::LinkAddress> linkAddresses;
- std::stringstream ss(static_cast<std::string>(dcResponse->addresses));
- std::string tok;
- while(getline(ss, tok, ' ')) {
- ::android::hardware::radio::V1_5::LinkAddress la;
- la.address = hidl_string(tok);
- la.properties = 0;
- la.deprecationTime = 0;
- la.expirationTime = 0;
- linkAddresses.push_back(la);
- }
-
- dcResult.addresses = linkAddresses;
- dcResult.dnses = split(convertCharPtrToHidlString(dcResponse->dnses));
- dcResult.gateways = split(convertCharPtrToHidlString(dcResponse->gateways));
- dcResult.pcscf = split(convertCharPtrToHidlString(dcResponse->pcscf));
- dcResult.mtuV4 = dcResponse->mtuV4;
- dcResult.mtuV6 = dcResponse->mtuV6;
-
- std::vector<::android::hardware::radio::V1_6::TrafficDescriptor> trafficDescriptors;
- ::android::hardware::radio::V1_6::TrafficDescriptor trafficDescriptor;
- ::android::hardware::radio::V1_6::OsAppId osAppId;
-
- osAppId.osAppId = 1;
- trafficDescriptor.osAppId.value(osAppId);
- trafficDescriptors.push_back(trafficDescriptor);
- dcResult.trafficDescriptors = trafficDescriptors;
-}
void convertRilDataCallListToHal(void *response, size_t responseLen,
hidl_vec<SetupDataCallResult>& dcResultList) {
@@ -10841,7 +8619,7 @@ void convertRilDataCallListToHal(void *response, size_t responseLen,
}
}
-int radio_1_6::dataCallListChangedInd(int slotId,
+int radio_1_5::dataCallListChangedInd(int slotId,
int indicationType, int token, RIL_Errno e, void *response,
size_t responseLen) {
if (radioService[slotId] != NULL && radioService[slotId]->mRadioIndication != NULL) {
@@ -10865,7 +8643,7 @@ int radio_1_6::dataCallListChangedInd(int slotId,
return 0;
}
-int radio_1_6::suppSvcNotifyInd(int slotId, int indicationType,
+int radio_1_5::suppSvcNotifyInd(int slotId, int indicationType,
int token, RIL_Errno e, void *response, size_t responseLen) {
if (radioService[slotId] != NULL && radioService[slotId]->mRadioIndication != NULL) {
if (response == NULL || responseLen != sizeof(RIL_SuppSvcNotification)) {
@@ -10895,7 +8673,7 @@ int radio_1_6::suppSvcNotifyInd(int slotId, int indicationType,
return 0;
}
-int radio_1_6::stkSessionEndInd(int slotId, int indicationType,
+int radio_1_5::stkSessionEndInd(int slotId, int indicationType,
int token, RIL_Errno e, void *response, size_t responseLen) {
if (radioService[slotId] != NULL && radioService[slotId]->mRadioIndication != NULL) {
#if VDBG
@@ -10911,7 +8689,7 @@ int radio_1_6::stkSessionEndInd(int slotId, int indicationType,
return 0;
}
-int radio_1_6::stkProactiveCommandInd(int slotId,
+int radio_1_5::stkProactiveCommandInd(int slotId,
int indicationType, int token, RIL_Errno e, void *response,
size_t responseLen) {
if (radioService[slotId] != NULL && radioService[slotId]->mRadioIndication != NULL) {
@@ -10933,7 +8711,7 @@ int radio_1_6::stkProactiveCommandInd(int slotId,
return 0;
}
-int radio_1_6::stkEventNotifyInd(int slotId, int indicationType,
+int radio_1_5::stkEventNotifyInd(int slotId, int indicationType,
int token, RIL_Errno e, void *response, size_t responseLen) {
if (radioService[slotId] != NULL && radioService[slotId]->mRadioIndication != NULL) {
if (response == NULL || responseLen == 0) {
@@ -10954,7 +8732,7 @@ int radio_1_6::stkEventNotifyInd(int slotId, int indicationType,
return 0;
}
-int radio_1_6::stkCallSetupInd(int slotId, int indicationType,
+int radio_1_5::stkCallSetupInd(int slotId, int indicationType,
int token, RIL_Errno e, void *response, size_t responseLen) {
if (radioService[slotId] != NULL && radioService[slotId]->mRadioIndication != NULL) {
if (response == NULL || responseLen != sizeof(int)) {
@@ -10975,7 +8753,7 @@ int radio_1_6::stkCallSetupInd(int slotId, int indicationType,
return 0;
}
-int radio_1_6::simSmsStorageFullInd(int slotId,
+int radio_1_5::simSmsStorageFullInd(int slotId,
int indicationType, int token, RIL_Errno e, void *response,
size_t responseLen) {
if (radioService[slotId] != NULL && radioService[slotId]->mRadioIndication != NULL) {
@@ -10992,7 +8770,7 @@ int radio_1_6::simSmsStorageFullInd(int slotId,
return 0;
}
-int radio_1_6::simRefreshInd(int slotId, int indicationType,
+int radio_1_5::simRefreshInd(int slotId, int indicationType,
int token, RIL_Errno e, void *response, size_t responseLen) {
if (radioService[slotId] != NULL && radioService[slotId]->mRadioIndication != NULL) {
if (response == NULL || responseLen != sizeof(RIL_SimRefreshResponse_v7)) {
@@ -11028,7 +8806,7 @@ void convertRilCdmaSignalInfoRecordToHal(RIL_CDMA_SignalInfoRecord *signalInfoRe
record.signal = signalInfoRecord->signal;
}
-int radio_1_6::callRingInd(int slotId, int indicationType,
+int radio_1_5::callRingInd(int slotId, int indicationType,
int token, RIL_Errno e, void *response, size_t responseLen) {
if (radioService[slotId] != NULL && radioService[slotId]->mRadioIndication != NULL) {
bool isGsm;
@@ -11057,7 +8835,7 @@ int radio_1_6::callRingInd(int slotId, int indicationType,
return 0;
}
-int radio_1_6::simStatusChangedInd(int slotId,
+int radio_1_5::simStatusChangedInd(int slotId,
int indicationType, int token, RIL_Errno e, void *response,
size_t responseLen) {
if (radioService[slotId] != NULL && radioService[slotId]->mRadioIndication != NULL) {
@@ -11074,7 +8852,7 @@ int radio_1_6::simStatusChangedInd(int slotId,
return 0;
}
-int radio_1_6::cdmaNewSmsInd(int slotId, int indicationType,
+int radio_1_5::cdmaNewSmsInd(int slotId, int indicationType,
int token, RIL_Errno e, void *response, size_t responseLen) {
if (radioService[slotId] != NULL && radioService[slotId]->mRadioIndication != NULL) {
if (response == NULL || responseLen != sizeof(RIL_CDMA_SMS_Message)) {
@@ -11122,7 +8900,7 @@ int radio_1_6::cdmaNewSmsInd(int slotId, int indicationType,
return 0;
}
-int radio_1_6::newBroadcastSmsInd(int slotId,
+int radio_1_5::newBroadcastSmsInd(int slotId,
int indicationType, int token, RIL_Errno e, void *response,
size_t responseLen) {
if (radioService[slotId] != NULL && radioService[slotId]->mRadioIndication != NULL) {
@@ -11146,7 +8924,7 @@ int radio_1_6::newBroadcastSmsInd(int slotId,
return 0;
}
-int radio_1_6::cdmaRuimSmsStorageFullInd(int slotId,
+int radio_1_5::cdmaRuimSmsStorageFullInd(int slotId,
int indicationType, int token, RIL_Errno e, void *response,
size_t responseLen) {
if (radioService[slotId] != NULL && radioService[slotId]->mRadioIndication != NULL) {
@@ -11164,7 +8942,7 @@ int radio_1_6::cdmaRuimSmsStorageFullInd(int slotId,
return 0;
}
-int radio_1_6::restrictedStateChangedInd(int slotId,
+int radio_1_5::restrictedStateChangedInd(int slotId,
int indicationType, int token, RIL_Errno e, void *response,
size_t responseLen) {
if (radioService[slotId] != NULL && radioService[slotId]->mRadioIndication != NULL) {
@@ -11187,7 +8965,7 @@ int radio_1_6::restrictedStateChangedInd(int slotId,
return 0;
}
-int radio_1_6::enterEmergencyCallbackModeInd(int slotId,
+int radio_1_5::enterEmergencyCallbackModeInd(int slotId,
int indicationType, int token, RIL_Errno e, void *response,
size_t responseLen) {
if (radioService[slotId] != NULL && radioService[slotId]->mRadioIndication != NULL) {
@@ -11205,7 +8983,7 @@ int radio_1_6::enterEmergencyCallbackModeInd(int slotId,
return 0;
}
-int radio_1_6::cdmaCallWaitingInd(int slotId,
+int radio_1_5::cdmaCallWaitingInd(int slotId,
int indicationType, int token, RIL_Errno e, void *response,
size_t responseLen) {
if (radioService[slotId] != NULL && radioService[slotId]->mRadioIndication != NULL) {
@@ -11238,7 +9016,7 @@ int radio_1_6::cdmaCallWaitingInd(int slotId,
return 0;
}
-int radio_1_6::cdmaOtaProvisionStatusInd(int slotId,
+int radio_1_5::cdmaOtaProvisionStatusInd(int slotId,
int indicationType, int token, RIL_Errno e, void *response,
size_t responseLen) {
if (radioService[slotId] != NULL && radioService[slotId]->mRadioIndication != NULL) {
@@ -11261,7 +9039,7 @@ int radio_1_6::cdmaOtaProvisionStatusInd(int slotId,
return 0;
}
-int radio_1_6::cdmaInfoRecInd(int slotId,
+int radio_1_5::cdmaInfoRecInd(int slotId,
int indicationType, int token, RIL_Errno e, void *response,
size_t responseLen) {
if (radioService[slotId] != NULL && radioService[slotId]->mRadioIndication != NULL) {
@@ -11439,7 +9217,7 @@ int radio_1_6::cdmaInfoRecInd(int slotId,
return 0;
}
-int radio_1_6::indicateRingbackToneInd(int slotId,
+int radio_1_5::indicateRingbackToneInd(int slotId,
int indicationType, int token, RIL_Errno e, void *response,
size_t responseLen) {
if (radioService[slotId] != NULL && radioService[slotId]->mRadioIndication != NULL) {
@@ -11461,7 +9239,7 @@ int radio_1_6::indicateRingbackToneInd(int slotId,
return 0;
}
-int radio_1_6::resendIncallMuteInd(int slotId,
+int radio_1_5::resendIncallMuteInd(int slotId,
int indicationType, int token, RIL_Errno e, void *response,
size_t responseLen) {
if (radioService[slotId] != NULL && radioService[slotId]->mRadioIndication != NULL) {
@@ -11478,7 +9256,7 @@ int radio_1_6::resendIncallMuteInd(int slotId,
return 0;
}
-int radio_1_6::cdmaSubscriptionSourceChangedInd(int slotId,
+int radio_1_5::cdmaSubscriptionSourceChangedInd(int slotId,
int indicationType, int token, RIL_Errno e,
void *response, size_t responseLen) {
if (radioService[slotId] != NULL && radioService[slotId]->mRadioIndication != NULL) {
@@ -11502,7 +9280,7 @@ int radio_1_6::cdmaSubscriptionSourceChangedInd(int slotId,
return 0;
}
-int radio_1_6::cdmaPrlChangedInd(int slotId,
+int radio_1_5::cdmaPrlChangedInd(int slotId,
int indicationType, int token, RIL_Errno e, void *response,
size_t responseLen) {
if (radioService[slotId] != NULL && radioService[slotId]->mRadioIndication != NULL) {
@@ -11524,7 +9302,7 @@ int radio_1_6::cdmaPrlChangedInd(int slotId,
return 0;
}
-int radio_1_6::exitEmergencyCallbackModeInd(int slotId,
+int radio_1_5::exitEmergencyCallbackModeInd(int slotId,
int indicationType, int token, RIL_Errno e, void *response,
size_t responseLen) {
if (radioService[slotId] != NULL && radioService[slotId]->mRadioIndication != NULL) {
@@ -11542,7 +9320,7 @@ int radio_1_6::exitEmergencyCallbackModeInd(int slotId,
return 0;
}
-int radio_1_6::rilConnectedInd(int slotId,
+int radio_1_5::rilConnectedInd(int slotId,
int indicationType, int token, RIL_Errno e, void *response,
size_t responseLen) {
if (radioService[slotId] != NULL && radioService[slotId]->mRadioIndication != NULL) {
@@ -11557,7 +9335,7 @@ int radio_1_6::rilConnectedInd(int slotId,
return 0;
}
-int radio_1_6::voiceRadioTechChangedInd(int slotId,
+int radio_1_5::voiceRadioTechChangedInd(int slotId,
int indicationType, int token, RIL_Errno e, void *response,
size_t responseLen) {
if (radioService[slotId] != NULL && radioService[slotId]->mRadioIndication != NULL) {
@@ -11726,326 +9504,7 @@ void convertRilCellInfoListToHal(void *response, size_t responseLen, hidl_vec<Ce
}
}
-void convertRilCellInfoListToHal_1_2(void *response, size_t responseLen, hidl_vec<V1_2::CellInfo>& records) {
- int num = responseLen / sizeof(RIL_CellInfo_v12);
- records.resize(num);
- RIL_CellInfo_v12 *rillCellInfo = (RIL_CellInfo_v12 *) response;
- for (int i = 0; i < num; i++) {
- records[i].cellInfoType = (CellInfoType) rillCellInfo->cellInfoType;
- records[i].registered = rillCellInfo->registered;
- records[i].timeStampType = (TimeStampType) rillCellInfo->timeStampType;
- records[i].timeStamp = rillCellInfo->timeStamp;
- records[i].connectionStatus =(V1_2::CellConnectionStatus)0;
- // All vectors should be size 0 except one which will be size 1. Set everything to
- // size 0 initially.
- records[i].gsm.resize(0);
- records[i].wcdma.resize(0);
- records[i].cdma.resize(0);
- records[i].lte.resize(0);
- records[i].tdscdma.resize(0);
- switch(rillCellInfo->cellInfoType) {
- case RIL_CELL_INFO_TYPE_GSM: {
- records[i].gsm.resize(1);
- V1_2::CellInfoGsm *cellInfoGsm = &records[i].gsm[0];
- cellInfoGsm->cellIdentityGsm.base.mcc =
- std::to_string(rillCellInfo->CellInfo.gsm.cellIdentityGsm.mcc);
- cellInfoGsm->cellIdentityGsm.base.mnc =
- ril::util::mnc::decode(rillCellInfo->CellInfo.gsm.cellIdentityGsm.mnc);
- cellInfoGsm->cellIdentityGsm.base.lac =
- rillCellInfo->CellInfo.gsm.cellIdentityGsm.lac;
- cellInfoGsm->cellIdentityGsm.base.cid =
- rillCellInfo->CellInfo.gsm.cellIdentityGsm.cid;
- cellInfoGsm->cellIdentityGsm.base.arfcn =
- rillCellInfo->CellInfo.gsm.cellIdentityGsm.arfcn;
- cellInfoGsm->cellIdentityGsm.base.bsic =
- rillCellInfo->CellInfo.gsm.cellIdentityGsm.bsic;
- cellInfoGsm->signalStrengthGsm.signalStrength =
- rillCellInfo->CellInfo.gsm.signalStrengthGsm.signalStrength;
- cellInfoGsm->signalStrengthGsm.bitErrorRate =
- rillCellInfo->CellInfo.gsm.signalStrengthGsm.bitErrorRate;
- cellInfoGsm->signalStrengthGsm.timingAdvance =
- rillCellInfo->CellInfo.gsm.signalStrengthGsm.timingAdvance;
- break;
- }
-
- case RIL_CELL_INFO_TYPE_WCDMA: {
- records[i].wcdma.resize(1);
- V1_2::CellInfoWcdma *cellInfoWcdma = &records[i].wcdma[0];
- cellInfoWcdma->cellIdentityWcdma.base.mcc =
- std::to_string(rillCellInfo->CellInfo.wcdma.cellIdentityWcdma.mcc);
- cellInfoWcdma->cellIdentityWcdma.base.mnc =
- ril::util::mnc::decode(rillCellInfo->CellInfo.wcdma.cellIdentityWcdma.mnc);
- cellInfoWcdma->cellIdentityWcdma.base.lac =
- rillCellInfo->CellInfo.wcdma.cellIdentityWcdma.lac;
- cellInfoWcdma->cellIdentityWcdma.base.cid =
- rillCellInfo->CellInfo.wcdma.cellIdentityWcdma.cid;
- cellInfoWcdma->cellIdentityWcdma.base.psc =
- rillCellInfo->CellInfo.wcdma.cellIdentityWcdma.psc;
- cellInfoWcdma->cellIdentityWcdma.base.uarfcn =
- rillCellInfo->CellInfo.wcdma.cellIdentityWcdma.uarfcn;
- cellInfoWcdma->signalStrengthWcdma.base.signalStrength =
- rillCellInfo->CellInfo.wcdma.signalStrengthWcdma.signalStrength;
- cellInfoWcdma->signalStrengthWcdma.base.bitErrorRate =
- rillCellInfo->CellInfo.wcdma.signalStrengthWcdma.bitErrorRate;
- break;
- }
-
- case RIL_CELL_INFO_TYPE_CDMA: {
- records[i].cdma.resize(1);
- V1_2::CellInfoCdma *cellInfoCdma = &records[i].cdma[0];
- cellInfoCdma->cellIdentityCdma.base.networkId =
- rillCellInfo->CellInfo.cdma.cellIdentityCdma.networkId;
- cellInfoCdma->cellIdentityCdma.base.systemId =
- rillCellInfo->CellInfo.cdma.cellIdentityCdma.systemId;
- cellInfoCdma->cellIdentityCdma.base.baseStationId =
- rillCellInfo->CellInfo.cdma.cellIdentityCdma.basestationId;
- cellInfoCdma->cellIdentityCdma.base.longitude =
- rillCellInfo->CellInfo.cdma.cellIdentityCdma.longitude;
- cellInfoCdma->cellIdentityCdma.base.latitude =
- rillCellInfo->CellInfo.cdma.cellIdentityCdma.latitude;
- cellInfoCdma->signalStrengthCdma.dbm =
- rillCellInfo->CellInfo.cdma.signalStrengthCdma.dbm;
- cellInfoCdma->signalStrengthCdma.ecio =
- rillCellInfo->CellInfo.cdma.signalStrengthCdma.ecio;
- cellInfoCdma->signalStrengthEvdo.dbm =
- rillCellInfo->CellInfo.cdma.signalStrengthEvdo.dbm;
- cellInfoCdma->signalStrengthEvdo.ecio =
- rillCellInfo->CellInfo.cdma.signalStrengthEvdo.ecio;
- cellInfoCdma->signalStrengthEvdo.signalNoiseRatio =
- rillCellInfo->CellInfo.cdma.signalStrengthEvdo.signalNoiseRatio;
- break;
- }
-
- case RIL_CELL_INFO_TYPE_LTE: {
- records[i].lte.resize(1);
- V1_2::CellInfoLte *cellInfoLte = &records[i].lte[0];
- cellInfoLte->cellIdentityLte.base.mcc =
- std::to_string(rillCellInfo->CellInfo.lte.cellIdentityLte.mcc);
- cellInfoLte->cellIdentityLte.base.mnc =
- ril::util::mnc::decode(rillCellInfo->CellInfo.lte.cellIdentityLte.mnc);
- cellInfoLte->cellIdentityLte.base.ci =
- rillCellInfo->CellInfo.lte.cellIdentityLte.ci;
- cellInfoLte->cellIdentityLte.base.pci =
- rillCellInfo->CellInfo.lte.cellIdentityLte.pci;
- cellInfoLte->cellIdentityLte.base.tac =
- rillCellInfo->CellInfo.lte.cellIdentityLte.tac;
- cellInfoLte->cellIdentityLte.base.earfcn =
- rillCellInfo->CellInfo.lte.cellIdentityLte.earfcn;
- cellInfoLte->signalStrengthLte.signalStrength =
- rillCellInfo->CellInfo.lte.signalStrengthLte.signalStrength;
- cellInfoLte->signalStrengthLte.rsrp =
- rillCellInfo->CellInfo.lte.signalStrengthLte.rsrp;
- cellInfoLte->signalStrengthLte.rsrq =
- rillCellInfo->CellInfo.lte.signalStrengthLte.rsrq;
- cellInfoLte->signalStrengthLte.rssnr =
- rillCellInfo->CellInfo.lte.signalStrengthLte.rssnr;
- cellInfoLte->signalStrengthLte.cqi =
- rillCellInfo->CellInfo.lte.signalStrengthLte.cqi;
- cellInfoLte->signalStrengthLte.timingAdvance =
- rillCellInfo->CellInfo.lte.signalStrengthLte.timingAdvance;
- break;
- }
-
- case RIL_CELL_INFO_TYPE_TD_SCDMA: {
- records[i].tdscdma.resize(1);
- V1_2::CellInfoTdscdma *cellInfoTdscdma = &records[i].tdscdma[0];
- cellInfoTdscdma->cellIdentityTdscdma.base.mcc =
- std::to_string(rillCellInfo->CellInfo.tdscdma.cellIdentityTdscdma.mcc);
- cellInfoTdscdma->cellIdentityTdscdma.base.mnc =
- ril::util::mnc::decode(
- rillCellInfo->CellInfo.tdscdma.cellIdentityTdscdma.mnc);
- cellInfoTdscdma->cellIdentityTdscdma.base.lac =
- rillCellInfo->CellInfo.tdscdma.cellIdentityTdscdma.lac;
- cellInfoTdscdma->cellIdentityTdscdma.base.cid =
- rillCellInfo->CellInfo.tdscdma.cellIdentityTdscdma.cid;
- cellInfoTdscdma->cellIdentityTdscdma.base.cpid =
- rillCellInfo->CellInfo.tdscdma.cellIdentityTdscdma.cpid;
- cellInfoTdscdma->signalStrengthTdscdma.rscp =
- rillCellInfo->CellInfo.tdscdma.signalStrengthTdscdma.rscp;
- break;
- }
- default: {
- break;
- }
- }
- rillCellInfo += 1;
- }
-}
-
-void convertRilCellInfoListToHal_1_4(void *response, size_t responseLen, hidl_vec<V1_4::CellInfo>& records) {
- int num = responseLen / sizeof(RIL_CellInfo_v16);
- records.resize(num);
- RIL_CellInfo_v16 *rillCellInfo = (RIL_CellInfo_v16 *) response;
- for (int i = 0; i < num; i++) {
- records[i].isRegistered = rillCellInfo->registered;
- records[i].connectionStatus = (V1_2::CellConnectionStatus)rillCellInfo->connectionStatus;
-
- switch(rillCellInfo->cellInfoType) {
- case RIL_CELL_INFO_TYPE_GSM: {
- V1_2::CellInfoGsm cellInfoGsm;
- cellInfoGsm.cellIdentityGsm.base.mcc =
- std::to_string(rillCellInfo->CellInfo.gsm.cellIdentityGsm.mcc);
- cellInfoGsm.cellIdentityGsm.base.mnc =
- ril::util::mnc::decode(rillCellInfo->CellInfo.gsm.cellIdentityGsm.mnc);
- cellInfoGsm.cellIdentityGsm.base.lac =
- rillCellInfo->CellInfo.gsm.cellIdentityGsm.lac;
- cellInfoGsm.cellIdentityGsm.base.cid =
- rillCellInfo->CellInfo.gsm.cellIdentityGsm.cid;
- cellInfoGsm.cellIdentityGsm.base.arfcn =
- rillCellInfo->CellInfo.gsm.cellIdentityGsm.arfcn;
- cellInfoGsm.cellIdentityGsm.base.bsic =
- rillCellInfo->CellInfo.gsm.cellIdentityGsm.bsic;
- cellInfoGsm.signalStrengthGsm.signalStrength =
- rillCellInfo->CellInfo.gsm.signalStrengthGsm.signalStrength;
- cellInfoGsm.signalStrengthGsm.bitErrorRate =
- rillCellInfo->CellInfo.gsm.signalStrengthGsm.bitErrorRate;
- cellInfoGsm.signalStrengthGsm.timingAdvance =
- rillCellInfo->CellInfo.gsm.signalStrengthGsm.timingAdvance;
- records[i].info.gsm(cellInfoGsm);
- break;
- }
-
- case RIL_CELL_INFO_TYPE_WCDMA: {
- V1_2::CellInfoWcdma cellInfoWcdma;
- cellInfoWcdma.cellIdentityWcdma.base.mcc =
- std::to_string(rillCellInfo->CellInfo.wcdma.cellIdentityWcdma.mcc);
- cellInfoWcdma.cellIdentityWcdma.base.mnc =
- ril::util::mnc::decode(rillCellInfo->CellInfo.wcdma.cellIdentityWcdma.mnc);
- cellInfoWcdma.cellIdentityWcdma.base.lac =
- rillCellInfo->CellInfo.wcdma.cellIdentityWcdma.lac;
- cellInfoWcdma.cellIdentityWcdma.base.cid =
- rillCellInfo->CellInfo.wcdma.cellIdentityWcdma.cid;
- cellInfoWcdma.cellIdentityWcdma.base.psc =
- rillCellInfo->CellInfo.wcdma.cellIdentityWcdma.psc;
- cellInfoWcdma.cellIdentityWcdma.base.uarfcn =
- rillCellInfo->CellInfo.wcdma.cellIdentityWcdma.uarfcn;
- cellInfoWcdma.signalStrengthWcdma.base.signalStrength =
- rillCellInfo->CellInfo.wcdma.signalStrengthWcdma.signalStrength;
- cellInfoWcdma.signalStrengthWcdma.base.bitErrorRate =
- rillCellInfo->CellInfo.wcdma.signalStrengthWcdma.bitErrorRate;
- records[i].info.wcdma(cellInfoWcdma);
- break;
- }
-
- case RIL_CELL_INFO_TYPE_CDMA: {
- V1_2::CellInfoCdma cellInfoCdma;
- cellInfoCdma.cellIdentityCdma.base.networkId =
- rillCellInfo->CellInfo.cdma.cellIdentityCdma.networkId;
- cellInfoCdma.cellIdentityCdma.base.systemId =
- rillCellInfo->CellInfo.cdma.cellIdentityCdma.systemId;
- cellInfoCdma.cellIdentityCdma.base.baseStationId =
- rillCellInfo->CellInfo.cdma.cellIdentityCdma.basestationId;
- cellInfoCdma.cellIdentityCdma.base.longitude =
- rillCellInfo->CellInfo.cdma.cellIdentityCdma.longitude;
- cellInfoCdma.cellIdentityCdma.base.latitude =
- rillCellInfo->CellInfo.cdma.cellIdentityCdma.latitude;
- cellInfoCdma.signalStrengthCdma.dbm =
- rillCellInfo->CellInfo.cdma.signalStrengthCdma.dbm;
- cellInfoCdma.signalStrengthCdma.ecio =
- rillCellInfo->CellInfo.cdma.signalStrengthCdma.ecio;
- cellInfoCdma.signalStrengthEvdo.dbm =
- rillCellInfo->CellInfo.cdma.signalStrengthEvdo.dbm;
- cellInfoCdma.signalStrengthEvdo.ecio =
- rillCellInfo->CellInfo.cdma.signalStrengthEvdo.ecio;
- cellInfoCdma.signalStrengthEvdo.signalNoiseRatio =
- rillCellInfo->CellInfo.cdma.signalStrengthEvdo.signalNoiseRatio;
- records[i].info.cdma(cellInfoCdma);
- break;
- }
-
- case RIL_CELL_INFO_TYPE_LTE: {
- V1_4::CellInfoLte cellInfoLte;
- cellInfoLte.base.cellIdentityLte.base.mcc =
- std::to_string(rillCellInfo->CellInfo.lte.cellIdentityLte.mcc);
- cellInfoLte.base.cellIdentityLte.base.mnc =
- ril::util::mnc::decode(rillCellInfo->CellInfo.lte.cellIdentityLte.mnc);
- cellInfoLte.base.cellIdentityLte.base.ci =
- rillCellInfo->CellInfo.lte.cellIdentityLte.ci;
- cellInfoLte.base.cellIdentityLte.base.pci =
- rillCellInfo->CellInfo.lte.cellIdentityLte.pci;
- cellInfoLte.base.cellIdentityLte.base.tac =
- rillCellInfo->CellInfo.lte.cellIdentityLte.tac;
- cellInfoLte.base.cellIdentityLte.base.earfcn =
- rillCellInfo->CellInfo.lte.cellIdentityLte.earfcn;
- cellInfoLte.base.signalStrengthLte.signalStrength =
- rillCellInfo->CellInfo.lte.signalStrengthLte.signalStrength;
- cellInfoLte.base.signalStrengthLte.rsrp =
- rillCellInfo->CellInfo.lte.signalStrengthLte.rsrp;
- cellInfoLte.base.signalStrengthLte.rsrq =
- rillCellInfo->CellInfo.lte.signalStrengthLte.rsrq;
- cellInfoLte.base.signalStrengthLte.rssnr =
- rillCellInfo->CellInfo.lte.signalStrengthLte.rssnr;
- cellInfoLte.base.signalStrengthLte.cqi =
- rillCellInfo->CellInfo.lte.signalStrengthLte.cqi;
- cellInfoLte.base.signalStrengthLte.timingAdvance =
- rillCellInfo->CellInfo.lte.signalStrengthLte.timingAdvance;
- records[i].info.lte(cellInfoLte);
- break;
- }
-
- case RIL_CELL_INFO_TYPE_TD_SCDMA: {
- V1_2::CellInfoTdscdma cellInfoTdscdma;
- cellInfoTdscdma.cellIdentityTdscdma.base.mcc =
- std::to_string(rillCellInfo->CellInfo.tdscdma.cellIdentityTdscdma.mcc);
- cellInfoTdscdma.cellIdentityTdscdma.base.mnc =
- ril::util::mnc::decode(
- rillCellInfo->CellInfo.tdscdma.cellIdentityTdscdma.mnc);
- cellInfoTdscdma.cellIdentityTdscdma.base.lac =
- rillCellInfo->CellInfo.tdscdma.cellIdentityTdscdma.lac;
- cellInfoTdscdma.cellIdentityTdscdma.base.cid =
- rillCellInfo->CellInfo.tdscdma.cellIdentityTdscdma.cid;
- cellInfoTdscdma.cellIdentityTdscdma.base.cpid =
- rillCellInfo->CellInfo.tdscdma.cellIdentityTdscdma.cpid;
- cellInfoTdscdma.signalStrengthTdscdma.rscp =
- rillCellInfo->CellInfo.tdscdma.signalStrengthTdscdma.rscp;
- records[i].info.tdscdma(cellInfoTdscdma);
- break;
- }
-
- case RIL_CELL_INFO_TYPE_NR: {
- V1_4::CellInfoNr cellInfoNr;
- cellInfoNr.cellidentity.mcc =
- std::to_string(rillCellInfo->CellInfo.nr.cellidentity.mcc);
- cellInfoNr.cellidentity.mnc =
- ril::util::mnc::decode(
- rillCellInfo->CellInfo.nr.cellidentity.mnc);
- cellInfoNr.cellidentity.nci =
- rillCellInfo->CellInfo.nr.cellidentity.nci;
- cellInfoNr.cellidentity.pci =
- rillCellInfo->CellInfo.nr.cellidentity.pci;
- cellInfoNr.cellidentity.tac =
- rillCellInfo->CellInfo.nr.cellidentity.tac;
- cellInfoNr.cellidentity.nrarfcn =
- rillCellInfo->CellInfo.nr.cellidentity.nrarfcn;
- cellInfoNr.cellidentity.operatorNames.alphaLong =
- convertCharPtrToHidlString(rillCellInfo->CellInfo.nr.cellidentity.operatorNames.alphaLong);
- cellInfoNr.cellidentity.operatorNames.alphaShort =
- convertCharPtrToHidlString(rillCellInfo->CellInfo.nr.cellidentity.operatorNames.alphaShort);
-
- cellInfoNr.signalStrength.ssRsrp =
- rillCellInfo->CellInfo.nr.signalStrength.ssRsrp;
- cellInfoNr.signalStrength.ssRsrq =
- rillCellInfo->CellInfo.nr.signalStrength.ssRsrq;
- cellInfoNr.signalStrength.ssSinr =
- rillCellInfo->CellInfo.nr.signalStrength.ssSinr;
- cellInfoNr.signalStrength.csiRsrp =
- rillCellInfo->CellInfo.nr.signalStrength.csiRsrp;
- cellInfoNr.signalStrength.csiRsrq =
- rillCellInfo->CellInfo.nr.signalStrength.csiRsrq;
- cellInfoNr.signalStrength.csiSinr =
- rillCellInfo->CellInfo.nr.signalStrength.csiSinr;
- records[i].info.nr(cellInfoNr);
- break;
- }
- default: {
- break;
- }
- }
- rillCellInfo += 1;
- }
-}
-
-int radio_1_6::cellInfoListInd(int slotId,
+int radio_1_5::cellInfoListInd(int slotId,
int indicationType, int token, RIL_Errno e, void *response,
size_t responseLen) {
if (radioService[slotId] != NULL && radioService[slotId]->mRadioIndication != NULL) {
@@ -12070,7 +9529,7 @@ int radio_1_6::cellInfoListInd(int slotId,
return 0;
}
-int radio_1_6::imsNetworkStateChangedInd(int slotId,
+int radio_1_5::imsNetworkStateChangedInd(int slotId,
int indicationType, int token, RIL_Errno e, void *response,
size_t responseLen) {
if (radioService[slotId] != NULL && radioService[slotId]->mRadioIndication != NULL) {
@@ -12088,7 +9547,7 @@ int radio_1_6::imsNetworkStateChangedInd(int slotId,
return 0;
}
-int radio_1_6::subscriptionStatusChangedInd(int slotId,
+int radio_1_5::subscriptionStatusChangedInd(int slotId,
int indicationType, int token, RIL_Errno e, void *response,
size_t responseLen) {
if (radioService[slotId] != NULL && radioService[slotId]->mRadioIndication != NULL) {
@@ -12111,7 +9570,7 @@ int radio_1_6::subscriptionStatusChangedInd(int slotId,
return 0;
}
-int radio_1_6::srvccStateNotifyInd(int slotId,
+int radio_1_5::srvccStateNotifyInd(int slotId,
int indicationType, int token, RIL_Errno e, void *response,
size_t responseLen) {
if (radioService[slotId] != NULL && radioService[slotId]->mRadioIndication != NULL) {
@@ -12166,7 +9625,7 @@ void convertRilHardwareConfigListToHal(void *response, size_t responseLen,
}
}
-int radio_1_6::hardwareConfigChangedInd(int slotId,
+int radio_1_5::hardwareConfigChangedInd(int slotId,
int indicationType, int token, RIL_Errno e, void *response,
size_t responseLen) {
if (radioService[slotId] != NULL && radioService[slotId]->mRadioIndication != NULL) {
@@ -12202,7 +9661,7 @@ void convertRilRadioCapabilityToHal(void *response, size_t responseLen, RadioCap
rc.status = (V1_0::RadioCapabilityStatus) rilRadioCapability->status;
}
-int radio_1_6::radioCapabilityIndicationInd(int slotId,
+int radio_1_5::radioCapabilityIndicationInd(int slotId,
int indicationType, int token, RIL_Errno e, void *response,
size_t responseLen) {
if (radioService[slotId] != NULL && radioService[slotId]->mRadioIndication != NULL) {
@@ -12241,7 +9700,7 @@ bool isServiceTypeCfQuery(RIL_SsServiceType serType, RIL_SsRequestType reqType)
return false;
}
-int radio_1_6::onSupplementaryServiceIndicationInd(int slotId,
+int radio_1_5::onSupplementaryServiceIndicationInd(int slotId,
int indicationType, int token, RIL_Errno e,
void *response, size_t responseLen) {
if (radioService[slotId] != NULL && radioService[slotId]->mRadioIndication != NULL) {
@@ -12321,7 +9780,7 @@ int radio_1_6::onSupplementaryServiceIndicationInd(int slotId,
return 0;
}
-int radio_1_6::stkCallControlAlphaNotifyInd(int slotId,
+int radio_1_5::stkCallControlAlphaNotifyInd(int slotId,
int indicationType, int token, RIL_Errno e, void *response,
size_t responseLen) {
if (radioService[slotId] != NULL && radioService[slotId]->mRadioIndication != NULL) {
@@ -12351,7 +9810,7 @@ void convertRilLceDataInfoToHal(void *response, size_t responseLen, LceDataInfo&
lce.lceSuspended = rilLceDataInfo->lce_suspended;
}
-int radio_1_6::lceDataInd(int slotId,
+int radio_1_5::lceDataInd(int slotId,
int indicationType, int token, RIL_Errno e, void *response,
size_t responseLen) {
if (radioService[slotId] != NULL && radioService[slotId]->mRadioIndication != NULL) {
@@ -12375,7 +9834,7 @@ int radio_1_6::lceDataInd(int slotId,
return 0;
}
-int radio_1_6::pcoDataInd(int slotId,
+int radio_1_5::pcoDataInd(int slotId,
int indicationType, int token, RIL_Errno e, void *response,
size_t responseLen) {
if (radioService[slotId] != NULL && radioService[slotId]->mRadioIndication != NULL) {
@@ -12404,7 +9863,7 @@ int radio_1_6::pcoDataInd(int slotId,
return 0;
}
-int radio_1_6::modemResetInd(int slotId,
+int radio_1_5::modemResetInd(int slotId,
int indicationType, int token, RIL_Errno e, void *response,
size_t responseLen) {
if (radioService[slotId] != NULL && radioService[slotId]->mRadioIndication != NULL) {
@@ -12426,7 +9885,7 @@ int radio_1_6::modemResetInd(int slotId,
return 0;
}
-int radio_1_6::networkScanResultInd(int slotId,
+int radio_1_5::networkScanResultInd(int slotId,
int indicationType, int token, RIL_Errno e, void *response,
size_t responseLen) {
#if VDBG
@@ -12462,7 +9921,7 @@ int radio_1_6::networkScanResultInd(int slotId,
return 0;
}
-int radio_1_6::carrierInfoForImsiEncryption(int slotId,
+int radio_1_5::carrierInfoForImsiEncryption(int slotId,
int indicationType, int token, RIL_Errno e, void *response,
size_t responseLen) {
if (radioService[slotId] != NULL && radioService[slotId]->mRadioIndicationV1_4 != NULL) {
@@ -12482,58 +9941,7 @@ int radio_1_6::carrierInfoForImsiEncryption(int slotId,
return 0;
}
-int radio_1_6::reportPhysicalChannelConfigs(int slotId, int indicationType,
- int token, RIL_Errno e,
- void *response,
- size_t responseLen) {
- if (radioService[slotId] != NULL &&
- radioService[slotId]->mRadioIndicationV1_4 != NULL) {
- int *configs = (int *)response;
- ::android::hardware::hidl_vec<PhysicalChannelConfigV1_4> physChanConfig;
- physChanConfig.resize(1);
- physChanConfig[0].base.status =
- (::android::hardware::radio::V1_2::CellConnectionStatus)configs[0];
- physChanConfig[0].base.cellBandwidthDownlink = configs[1];
- physChanConfig[0].rat =
- (::android::hardware::radio::V1_4::RadioTechnology)configs[2];
- physChanConfig[0].rfInfo.range(
- (::android::hardware::radio::V1_4::FrequencyRange)configs[3]);
- physChanConfig[0].contextIds.resize(1);
- physChanConfig[0].contextIds[0] = configs[4];
- RLOGD("reportPhysicalChannelConfigs: %d %d %d %d %d", configs[0],
- configs[1], configs[2], configs[3], configs[4]);
- Return<void> retStatus = radioService[slotId]
- ->mRadioIndicationV1_4->currentPhysicalChannelConfigs_1_4(
- RadioIndicationType::UNSOLICITED, physChanConfig);
- radioService[slotId]->checkReturnStatus(retStatus);
- {
- // just send the link estimate along with physical channel
- // config, as it has at least the downlink bandwidth.
- // Note: the bandwidth is just some hardcoded
- // value, as there is not way to get that reliably on
- // virtual devices, as of now.
- V1_2::LinkCapacityEstimate lce = {
- .downlinkCapacityKbps = static_cast<uint32_t>(configs[1]),
- .uplinkCapacityKbps = static_cast<uint32_t>(configs[1])
- };
- RLOGD("reporting link capacity estimate download: %d upload: %d",
- lce.downlinkCapacityKbps, lce.uplinkCapacityKbps );
- Return<void> retStatus = radioService[slotId]->mRadioIndicationV1_4->
- currentLinkCapacityEstimate(RadioIndicationType::UNSOLICITED, lce);
- radioService[slotId]->checkReturnStatus(retStatus);
- }
- } else {
- RLOGE(
- "reportPhysicalChannelConfigs: radioService[%d]->mRadioIndicationV1_4 "
- "== NULL",
- slotId);
- return -1;
- }
-
- return 0;
-}
-
-int radio_1_6::keepaliveStatusInd(int slotId,
+int radio_1_5::keepaliveStatusInd(int slotId,
int indicationType, int token, RIL_Errno e, void *response,
size_t responseLen) {
#if VDBG
@@ -12566,7 +9974,7 @@ int radio_1_6::keepaliveStatusInd(int slotId,
return 0;
}
-int radio_1_6::oemHookRawInd(int slotId,
+int radio_1_5::oemHookRawInd(int slotId,
int indicationType, int token, RIL_Errno e, void *response,
size_t responseLen) {
if (!kOemHookEnabled) return 0;
@@ -12592,7 +10000,7 @@ int radio_1_6::oemHookRawInd(int slotId,
return 0;
}
-void radio_1_6::registerService(RIL_RadioFunctions *callbacks, CommandInfo *commands) {
+void radio_1_5::registerService(RIL_RadioFunctions *callbacks, CommandInfo *commands) {
using namespace android::hardware;
int simCount = 1;
const char *serviceNames[] = {
@@ -12623,11 +10031,9 @@ void radio_1_6::registerService(RIL_RadioFunctions *callbacks, CommandInfo *comm
RLOGD("sim i = %d registering ...", i);
- radioService[i] = new RadioImpl_1_6;
+ radioService[i] = new RadioImpl_1_5;
radioService[i]->mSlotId = i;
- RLOGD("registerService: initializing power state to POWER_UP");
- radioService[i]->mSimCardPowerState = V1_1::CardPowerState::POWER_UP;
- RLOGD("registerService: starting android::hardware::radio::V1_6::IRadio %s for slot %d",
+ RLOGD("registerService: starting android::hardware::radio::V1_5::IRadio %s for slot %d",
serviceNames[i], i);
android::status_t status = radioService[i]->registerAsService(serviceNames[i]);
LOG_ALWAYS_FATAL_IF(status != android::OK, "status %d", status);
@@ -12648,7 +10054,7 @@ void rilc_thread_pool() {
joinRpcThreadpool();
}
-pthread_rwlock_t * radio_1_6::getRadioServiceRwlock(int slotId) {
+pthread_rwlock_t * radio_1_5::getRadioServiceRwlock(int slotId) {
pthread_rwlock_t *radioServiceRwlockPtr = &radioServiceRwlock;
#if (SIM_COUNT >= 2)
@@ -12665,6 +10071,6 @@ pthread_rwlock_t * radio_1_6::getRadioServiceRwlock(int slotId) {
}
// should acquire write lock for the corresponding service before calling this
-void radio_1_6::setNitzTimeReceived(int slotId, long timeReceived) {
+void radio_1_5::setNitzTimeReceived(int slotId, long timeReceived) {
nitzTimeReceived[slotId] = timeReceived;
}
diff --git a/guest/hals/ril/reference-libril/ril_service.h b/guest/hals/ril/libril/ril_service.h
index 6821f2cc1..ded9776c2 100644
--- a/guest/hals/ril/reference-libril/ril_service.h
+++ b/guest/hals/ril/libril/ril_service.h
@@ -17,10 +17,10 @@
#ifndef RIL_SERVICE_H
#define RIL_SERVICE_H
-#include <guest/hals/ril/reference-libril/ril.h>
+#include <guest/hals/ril/libril/ril.h>
#include <ril_internal.h>
-namespace radio_1_6 {
+namespace radio_1_5 {
void registerService(RIL_RadioFunctions *callbacks, android::CommandInfo *commands);
int getIccCardStatusResponse(int slotId, int responseType,
@@ -117,7 +117,7 @@ int sendSmsResponse(int slotId,
int responseType, int serial, RIL_Errno e, void *response,
size_t responselen);
-int sendSmsExpectMoreResponse(int slotId,
+int sendSMSExpectMoreResponse(int slotId,
int responseType, int serial, RIL_Errno e, void *response,
size_t responselen);
@@ -736,9 +736,6 @@ int networkScanResultInd(int slotId,
int indicationType, int token, RIL_Errno e, void *response,
size_t responselen);
-int reportPhysicalChannelConfigs(int slotId, int indicationType,
- int token, RIL_Errno e, void *response, size_t responselen);
-
int keepaliveStatusInd(int slotId,
int indicationType, int token, RIL_Errno e, void *response,
size_t responselen);
@@ -763,11 +760,9 @@ int carrierInfoForImsiEncryption(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen);
-int setSystemSelectionChannelsResponse(int slotId, int responseType, int serial,
- RIL_Errno e, void *response, size_t responseLen);
-
-int getSystemSelectionChannelsResponse(int slotId, int responseType, int serial,
- RIL_Errno e, void *response, size_t responseLen);
+int setSystemSelectionChannelsResponse(int slotId,
+ int responseType, int serial, RIL_Errno e,
+ void *response, size_t responseLen);
int setSignalStrengthReportingCriteriaResponse(int slotId, int responseType, int serial,
RIL_Errno e, void *response, size_t responselen);
@@ -795,78 +790,10 @@ int sendCdmaSmsExpectMoreResponse(int slotId, int responseType, int serial, RIL_
int supplySimDepersonalizationResponse(int slotId, int responseType, int serial, RIL_Errno e,
void *response, size_t responselen);
-int setNrDualConnectivityStateResponse(int slotId, int responseType, int serial,
- RIL_Errno e, void* /* response */, size_t responseLen);
-int isNrDualConnectivityEnabledResponse(int slotId, int responseType, int serial,
- RIL_Errno e, void* response, size_t responseLen);
-
-int allocatePduSessionIdResponse(int slotId, int responseType, int serial,
- RIL_Errno e, void* response, size_t responseLen);
-int releasePduSessionIdResponse(int slotId, int responseType, int serial,
- RIL_Errno e, void* response, size_t responseLen);
-int startHandoverResponse(int slotId, int responseType, int serial,
- RIL_Errno e, void* response, size_t responseLen);
-int cancelHandoverResponse(int slotId, int responseType, int serial,
- RIL_Errno e, void* response, size_t responseLen);
-
-int setAllowedNetworkTypesBitmapResponse(int slotId, int responseType, int serial,
- RIL_Errno e, void *response, size_t responselen);
-
-int setDataThrottlingResponse(int slotId, int responseType, int serial,
- RIL_Errno e, void *response, size_t responselen);
-
-int getAllowedNetworkTypesBitmapResponse(int slotId, int responseType, int serial,
- RIL_Errno e, void *response, size_t responselen);
-
-int getSlicingConfigResponse(int slotId, int responseType, int serial,
- RIL_Errno e, void *response, size_t responseLen);
-
-int getSimPhonebookRecordsResponse(int slotId, int responseType, int serial,
- RIL_Errno e, void *response, size_t responseLen);
-
-int getSimPhonebookCapacityResponse(int slotId, int responseType, int serial,
- RIL_Errno e, void *response, size_t responseLen);
-
-int updateSimPhonebookRecordsResponse(int slotId, int responseType, int serial,
- RIL_Errno e, void *response, size_t responseLen);
-
-
pthread_rwlock_t * getRadioServiceRwlock(int slotId);
void setNitzTimeReceived(int slotId, long timeReceived);
-/******************************************************************************/
-/* Radio Config interfaces' corresponding responseFunction */
-/******************************************************************************/
-void registerConfigService(RIL_RadioFunctions *callbacks, android::CommandInfo *commands);
-
-int getSimSlotsStatusResponse(int slotId, int responseType, int serial,
- RIL_Errno e, void *response, size_t responseLen);
-
-int setSimSlotsMappingResponse(int slotId, int responseType, int serial,
- RIL_Errno e, void *response, size_t responseLen);
-
-int getPhoneCapabilityResponse(int slotId, int responseType, int serial,
- RIL_Errno e, void *response, size_t responseLen);
-
-int setPreferredDataModemResponse(int slotId, int responseType, int serial,
- RIL_Errno e, void *response, size_t responseLen);
-
-int setModemsConfigResponse(int slotId, int responseType, int serial,
- RIL_Errno e, void *response, size_t responseLen);
-
-int getModemsConfigResponse(int slotId, int responseType, int serial,
- RIL_Errno e, void *response, size_t responseLen);
-
-int getHalDeviceCapabilitiesResponse(int slotId, int responseType, int serial,
- RIL_Errno e, void *response, size_t responseLen);
-
-/******************************************************************************/
-/* Radio Config unsolicited interfaces' corresponding responseFunction */
-/******************************************************************************/
-int simSlotsStatusChanged(int slotId, int indicationType, int token,
- RIL_Errno e, void *response, size_t responseLen);
-
} // namespace radio
#endif // RIL_SERVICE_H
diff --git a/guest/hals/ril/libril/ril_unsol_commands.h b/guest/hals/ril/libril/ril_unsol_commands.h
new file mode 100644
index 000000000..89c1f558f
--- /dev/null
+++ b/guest/hals/ril/libril/ril_unsol_commands.h
@@ -0,0 +1,66 @@
+/* ///guest/hals/ril/libril/ril_unsol_commands.h
+**
+** Copyright 2006, 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.
+*/
+ {RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED, radio_1_5::radioStateChangedInd, WAKE_PARTIAL},
+ {RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED, radio_1_5::callStateChangedInd, WAKE_PARTIAL},
+ {RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED, radio_1_5::networkStateChangedInd, WAKE_PARTIAL},
+ {RIL_UNSOL_RESPONSE_NEW_SMS, radio_1_5::newSmsInd, WAKE_PARTIAL},
+ {RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT, radio_1_5::newSmsStatusReportInd, WAKE_PARTIAL},
+ {RIL_UNSOL_RESPONSE_NEW_SMS_ON_SIM, radio_1_5::newSmsOnSimInd, WAKE_PARTIAL},
+ {RIL_UNSOL_ON_USSD, radio_1_5::onUssdInd, WAKE_PARTIAL},
+ {RIL_UNSOL_ON_USSD_REQUEST, radio_1_5::onUssdInd, DONT_WAKE},
+ {RIL_UNSOL_NITZ_TIME_RECEIVED, radio_1_5::nitzTimeReceivedInd, WAKE_PARTIAL},
+ {RIL_UNSOL_SIGNAL_STRENGTH, radio_1_5::currentSignalStrengthInd, DONT_WAKE},
+ {RIL_UNSOL_DATA_CALL_LIST_CHANGED, radio_1_5::dataCallListChangedInd, WAKE_PARTIAL},
+ {RIL_UNSOL_SUPP_SVC_NOTIFICATION, radio_1_5::suppSvcNotifyInd, WAKE_PARTIAL},
+ {RIL_UNSOL_STK_SESSION_END, radio_1_5::stkSessionEndInd, WAKE_PARTIAL},
+ {RIL_UNSOL_STK_PROACTIVE_COMMAND, radio_1_5::stkProactiveCommandInd, WAKE_PARTIAL},
+ {RIL_UNSOL_STK_EVENT_NOTIFY, radio_1_5::stkEventNotifyInd, WAKE_PARTIAL},
+ {RIL_UNSOL_STK_CALL_SETUP, radio_1_5::stkCallSetupInd, WAKE_PARTIAL},
+ {RIL_UNSOL_SIM_SMS_STORAGE_FULL, radio_1_5::simSmsStorageFullInd, WAKE_PARTIAL},
+ {RIL_UNSOL_SIM_REFRESH, radio_1_5::simRefreshInd, WAKE_PARTIAL},
+ {RIL_UNSOL_CALL_RING, radio_1_5::callRingInd, WAKE_PARTIAL},
+ {RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED, radio_1_5::simStatusChangedInd, WAKE_PARTIAL},
+ {RIL_UNSOL_RESPONSE_CDMA_NEW_SMS, radio_1_5::cdmaNewSmsInd, WAKE_PARTIAL},
+ {RIL_UNSOL_RESPONSE_NEW_BROADCAST_SMS, radio_1_5::newBroadcastSmsInd, WAKE_PARTIAL},
+ {RIL_UNSOL_CDMA_RUIM_SMS_STORAGE_FULL, radio_1_5::cdmaRuimSmsStorageFullInd, WAKE_PARTIAL},
+ {RIL_UNSOL_RESTRICTED_STATE_CHANGED, radio_1_5::restrictedStateChangedInd, WAKE_PARTIAL},
+ {RIL_UNSOL_ENTER_EMERGENCY_CALLBACK_MODE, radio_1_5::enterEmergencyCallbackModeInd, WAKE_PARTIAL},
+ {RIL_UNSOL_CDMA_CALL_WAITING, radio_1_5::cdmaCallWaitingInd, WAKE_PARTIAL},
+ {RIL_UNSOL_CDMA_OTA_PROVISION_STATUS, radio_1_5::cdmaOtaProvisionStatusInd, WAKE_PARTIAL},
+ {RIL_UNSOL_CDMA_INFO_REC, radio_1_5::cdmaInfoRecInd, WAKE_PARTIAL},
+ {RIL_UNSOL_OEM_HOOK_RAW, radio_1_5::oemHookRawInd, WAKE_PARTIAL},
+ {RIL_UNSOL_RINGBACK_TONE, radio_1_5::indicateRingbackToneInd, WAKE_PARTIAL},
+ {RIL_UNSOL_RESEND_INCALL_MUTE, radio_1_5::resendIncallMuteInd, WAKE_PARTIAL},
+ {RIL_UNSOL_CDMA_SUBSCRIPTION_SOURCE_CHANGED, radio_1_5::cdmaSubscriptionSourceChangedInd, WAKE_PARTIAL},
+ {RIL_UNSOL_CDMA_PRL_CHANGED, radio_1_5::cdmaPrlChangedInd, WAKE_PARTIAL},
+ {RIL_UNSOL_EXIT_EMERGENCY_CALLBACK_MODE, radio_1_5::exitEmergencyCallbackModeInd, WAKE_PARTIAL},
+ {RIL_UNSOL_RIL_CONNECTED, radio_1_5::rilConnectedInd, WAKE_PARTIAL},
+ {RIL_UNSOL_VOICE_RADIO_TECH_CHANGED, radio_1_5::voiceRadioTechChangedInd, WAKE_PARTIAL},
+ {RIL_UNSOL_CELL_INFO_LIST, radio_1_5::cellInfoListInd, WAKE_PARTIAL},
+ {RIL_UNSOL_RESPONSE_IMS_NETWORK_STATE_CHANGED, radio_1_5::imsNetworkStateChangedInd, WAKE_PARTIAL},
+ {RIL_UNSOL_UICC_SUBSCRIPTION_STATUS_CHANGED, radio_1_5::subscriptionStatusChangedInd, WAKE_PARTIAL},
+ {RIL_UNSOL_SRVCC_STATE_NOTIFY, radio_1_5::srvccStateNotifyInd, WAKE_PARTIAL},
+ {RIL_UNSOL_HARDWARE_CONFIG_CHANGED, radio_1_5::hardwareConfigChangedInd, WAKE_PARTIAL},
+ {RIL_UNSOL_DC_RT_INFO_CHANGED, NULL, WAKE_PARTIAL},
+ {RIL_UNSOL_RADIO_CAPABILITY, radio_1_5::radioCapabilityIndicationInd, WAKE_PARTIAL},
+ {RIL_UNSOL_ON_SS, radio_1_5::onSupplementaryServiceIndicationInd, WAKE_PARTIAL},
+ {RIL_UNSOL_STK_CC_ALPHA_NOTIFY, radio_1_5::stkCallControlAlphaNotifyInd, WAKE_PARTIAL},
+ {RIL_UNSOL_LCEDATA_RECV, radio_1_5::lceDataInd, WAKE_PARTIAL},
+ {RIL_UNSOL_PCO_DATA, radio_1_5::pcoDataInd, WAKE_PARTIAL},
+ {RIL_UNSOL_MODEM_RESTART, radio_1_5::modemResetInd, WAKE_PARTIAL},
+ {RIL_UNSOL_CARRIER_INFO_IMSI_ENCRYPTION, radio_1_5::carrierInfoForImsiEncryption, WAKE_PARTIAL},
+ {RIL_UNSOL_NETWORK_SCAN_RESULT, radio_1_5::networkScanResultInd, WAKE_PARTIAL},
diff --git a/guest/hals/ril/reference-libril/sap_service.cpp b/guest/hals/ril/libril/sap_service.cpp
index cd5b13783..cd5b13783 100644
--- a/guest/hals/ril/reference-libril/sap_service.cpp
+++ b/guest/hals/ril/libril/sap_service.cpp
diff --git a/guest/hals/ril/reference-libril/Android.bp b/guest/hals/ril/reference-libril/Android.bp
deleted file mode 100644
index db265e3b2..000000000
--- a/guest/hals/ril/reference-libril/Android.bp
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-cc_library {
- name: "libril-modem-lib",
- vendor: true,
- cflags: [
- "-Wextra",
- "-Wno-unused-parameter",
- ],
- srcs: [
- "ril.cpp",
- "RilSapSocket.cpp",
- "ril_config.cpp",
- "ril_event.cpp",
- "ril_service.cpp",
- "sap_service.cpp",
- ],
- include_dirs: [
- "device/google/cuttlefish",
- "hardware/ril/include",
- ],
- shared_libs: [
- "android.hardware.radio@1.0",
- "android.hardware.radio@1.1",
- "android.hardware.radio@1.2",
- "android.hardware.radio@1.3",
- "android.hardware.radio@1.4",
- "android.hardware.radio@1.5",
- "android.hardware.radio@1.6",
- "android.hardware.radio.config@1.0",
- "android.hardware.radio.config@1.1",
- "android.hardware.radio.config@1.2",
- "android.hardware.radio.config@1.3",
- "android.hardware.radio.deprecated@1.0",
- "libcutils",
- "libhardware_legacy",
- "libhidlbase",
- "liblog",
- "librilutils",
- "libutils",
- ],
- static_libs: [
- "libprotobuf-c-nano-enable_malloc"
- ],
-}
diff --git a/guest/hals/ril/reference-libril/RilSapSocket.h b/guest/hals/ril/reference-libril/RilSapSocket.h
deleted file mode 100644
index 1a816c587..000000000
--- a/guest/hals/ril/reference-libril/RilSapSocket.h
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
-* 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.
-*/
-
-#ifndef RIL_UIM_SOCKET_H_INCLUDED
-#define RIL_UIM_SOCKET_H_INCLUDED
-#define RIL_SHLIB
-#include "telephony/ril.h"
-#include "RilSocket.h"
-#include <hardware/ril/librilutils/proto/sap-api.pb.h>
-
-/**
- * RilSapSocket is a derived class, derived from the RilSocket abstract
- * class, representing sockets for communication between bluetooth SAP module and
- * the ril daemon.
- * <p>
- * This class performs the following functions :
- * <ul>
- * <li>Initialize the socket.
- * <li>Process the requests coming on the socket.
- * <li>Provide handlers for Unsolicited and request responses.
- * <li>Request and pending response queue handling.
- * </ul>
- */
-class RilSapSocket : public RilSocket {
- /**
- * Place holder for the radio functions returned by the initialization
- * function. Currenty only onRequest handler is being used.
- */
- const RIL_RadioFunctions* uimFuncs;
-
- /**
- * Wrapper struct for handling the requests in the queue.
- */
- typedef struct SapSocketRequest {
- int token;
- MsgHeader* curr;
- struct SapSocketRequest* p_next;
- RIL_SOCKET_ID socketId;
- } SapSocketRequest;
-
- /**
- * Queue for requests that are pending dispatch.
- */
- Ril_queue<SapSocketRequest> dispatchQueue;
-
- /**
- * Queue for requests that are dispatched but are pending response
- */
- Ril_queue<SapSocketRequest> pendingResponseQueue;
-
- public:
- /**
- * Initialize the socket and add the socket to the list.
- *
- * @param Name of the socket.
- * @param Radio functions to be used by the socket.
- */
- static void initSapSocket(const char *socketName,
- const RIL_RadioFunctions *uimFuncs);
-
- /**
- * Ril envoronment variable that holds the request and
- * unsol response handlers.
- */
- static struct RIL_Env uimRilEnv;
-
- /**
- * Function to print the socket list.
- */
- static void printList();
-
- /**
- * Dispatches the request to the lower layers.
- * It calls the on request function.
- *
- * @param request The request message.
- */
- void dispatchRequest(MsgHeader *request);
-
- /**
- * Class method to get the socket from the socket list.
- *
- * @param socketId Socket id.
- * @return the sap socket.
- */
- static RilSapSocket* getSocketById(RIL_SOCKET_ID socketId);
-
- /**
- * Datatype to handle the socket list.
- */
- typedef struct RilSapSocketList {
- RilSapSocket* socket;
- RilSapSocketList *next;
- } RilSapSocketList;
-
- protected:
- /**
- * Socket handler to be called when a request has
- * been completed.
- *
- * @param Token associated with the request.
- * @param Error, if any, while processing the request.
- * @param The response payload.
- * @param Response payload length.
- */
- void onRequestComplete(RIL_Token t,RIL_Errno e,
- void *response, size_t response_len);
-
- /**
- * Socket handler to be called when there is an
- * unsolicited response.
- *
- * @param Message id.
- * @param Response data.
- * @param Response data length.
- */
- void onUnsolicitedResponse(int unsolResponse,
- void *data, size_t datalen);
-
- /**
- * Class method to add the sap socket to the list of sockets.
- * Does nothing if the socket is already present in the list.
- * Otherwise, calls the constructor of the parent class(To startlistening)
- * and add socket to the socket list.
- */
- static void addSocketToList(const char *socketName, RIL_SOCKET_ID socketid,
- const RIL_RadioFunctions *uimFuncs);
-
- /**
- * Check if a socket of the given name exists in the socket list.
- *
- * @param Socket name.
- * @return true if exists, false otherwise.
- */
- static bool SocketExists(const char *socketName);
-
- private:
- /**
- * Constructor.
- *
- * @param Socket name.
- * @param Socket id.
- * @param Radio functions.
- */
- RilSapSocket(const char *socketName,
- RIL_SOCKET_ID socketId,
- const RIL_RadioFunctions *inputUimFuncs);
-
- /**
- * Class method that selects the socket on which the onRequestComplete
- * is called.
- *
- * @param Token associated with the request.
- * @param Error, if any, while processing the request.
- * @param The response payload.
- * @param Response payload length.
- */
- static void sOnRequestComplete(RIL_Token t,
- RIL_Errno e, void *response, size_t responselen);
-
-#if defined(ANDROID_MULTI_SIM)
- /**
- * Class method that selects the socket on which the onUnsolicitedResponse
- * is called.
- *
- * @param Message id.
- * @param Response data.
- * @param Response data length.
- * @param Socket id.
- */
- static void sOnUnsolicitedResponse(int unsolResponse, const void *data,
- size_t datalen, RIL_SOCKET_ID socket_id);
-#else
- /**
- * Class method that selects the socket on which the onUnsolicitedResponse
- * is called.
- *
- * @param Message id.
- * @param Response data.
- * @param Response data length.
- */
- static void sOnUnsolicitedResponse(int unsolResponse, const void *data,
- size_t datalen);
-#endif
-};
-
-#endif /*RIL_UIM_SOCKET_H_INCLUDED*/
diff --git a/guest/hals/ril/reference-libril/RilSocket.h b/guest/hals/ril/reference-libril/RilSocket.h
deleted file mode 100644
index 53b00c9d9..000000000
--- a/guest/hals/ril/reference-libril/RilSocket.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
-* 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.
-*/
-
-#ifndef RIL_SOCKET_H_INCLUDED
-#define RIL_SOCKET_H_INCLUDED
-#include <libril/ril_ex.h>
-#include "rilSocketQueue.h"
-#include <ril_event.h>
-
-/**
- * Abstract socket class representing sockets in rild.
- * <p>
- * This class performs the following functions :
- * <ul>
- * <li> Start socket listen.
- * <li> Handle socket listen and command callbacks.
- * </ul>
- */
-class RilSocket {
- protected:
-
- /**
- * Socket name.
- */
- const char* name;
-
- /**
- * Socket id.
- */
- RIL_SOCKET_ID id;
-
- public:
-
- /**
- * Constructor.
- *
- * @param Socket name.
- * @param Socket id.
- */
- RilSocket(const char* socketName, RIL_SOCKET_ID socketId) {
- name = socketName;
- id = socketId;
- }
-
- /**
- * Get socket id.
- *
- * @return RIL_SOCKET_ID socket id.
- */
- RIL_SOCKET_ID getSocketId(void) {
- return id;
- }
-
- virtual ~RilSocket(){}
-};
-
-#endif
diff --git a/guest/hals/ril/reference-libril/rilSocketQueue.h b/guest/hals/ril/reference-libril/rilSocketQueue.h
deleted file mode 100644
index eaa515526..000000000
--- a/guest/hals/ril/reference-libril/rilSocketQueue.h
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
-* 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.
-*/
-
-#include "pb_decode.h"
-#include <pthread.h>
-#include <hardware/ril/librilutils/proto/sap-api.pb.h>
-#include <utils/Log.h>
-
-using namespace std;
-
-/**
- * Template queue class to handling requests for a rild socket.
- * <p>
- * This class performs the following functions :
- * <ul>
- * <li>Enqueue.
- * <li>Dequeue.
- * <li>Check and dequeue.
- * </ul>
- */
-
-template <typename T>
-class Ril_queue {
-
- /**
- * Mutex attribute used in queue mutex initialization.
- */
- pthread_mutexattr_t attr;
-
- /**
- * Queue mutex variable for synchronized queue access.
- */
- pthread_mutex_t mutex_instance;
-
- /**
- * Condition to be waited on for dequeuing.
- */
- pthread_cond_t cond;
-
- /**
- * Front of the queue.
- */
- T *front;
-
- public:
-
- /**
- * Remove the first element of the queue.
- *
- * @return first element of the queue.
- */
- T* dequeue(void);
-
- /**
- * Add a request to the front of the queue.
- *
- * @param Request to be added.
- */
- void enqueue(T* request);
-
- /**
- * Check if the queue is empty.
- */
- int empty(void);
-
- /**
- * Check and remove an element with a particular message id and token.
- *
- * @param Request message id.
- * @param Request token.
- */
- int checkAndDequeue( MsgId id, int token);
-
- /**
- * Queue constructor.
- */
- Ril_queue(void);
-};
-
-template <typename T>
-Ril_queue<T>::Ril_queue(void) {
- pthread_mutexattr_init(&attr);
- pthread_mutex_init(&mutex_instance, &attr);
- cond = PTHREAD_COND_INITIALIZER;
- front = NULL;
-}
-
-template <typename T>
-T* Ril_queue<T>::dequeue(void) {
- T* temp = NULL;
-
- pthread_mutex_lock(&mutex_instance);
- while(empty()) {
- pthread_cond_wait(&cond, &mutex_instance);
- }
- temp = this->front;
- if(NULL != this->front->p_next) {
- this->front = this->front->p_next;
- } else {
- this->front = NULL;
- }
- pthread_mutex_unlock(&mutex_instance);
-
- return temp;
-}
-
-template <typename T>
-void Ril_queue<T>::enqueue(T* request) {
-
- pthread_mutex_lock(&mutex_instance);
-
- if(NULL == this->front) {
- this->front = request;
- request->p_next = NULL;
- } else {
- request->p_next = this->front;
- this->front = request;
- }
- pthread_cond_broadcast(&cond);
- pthread_mutex_unlock(&mutex_instance);
-}
-
-template <typename T>
-int Ril_queue<T>::checkAndDequeue(MsgId id, int token) {
- int ret = 0;
- T* temp;
-
- pthread_mutex_lock(&mutex_instance);
-
- for(T **ppCur = &(this->front); *ppCur != NULL; ppCur = &((*ppCur)->p_next)) {
- if (token == (*ppCur)->token && id == (*ppCur)->curr->id) {
- ret = 1;
- temp = *ppCur;
- *ppCur = (*ppCur)->p_next;
- free(temp);
- break;
- }
- }
-
- pthread_mutex_unlock(&mutex_instance);
-
- return ret;
-}
-
-
-template <typename T>
-int Ril_queue<T>::empty(void) {
-
- if(this->front == NULL) {
- return 1;
- } else {
- return 0;
- }
-}
diff --git a/guest/hals/ril/reference-libril/ril_commands.h b/guest/hals/ril/reference-libril/ril_commands.h
deleted file mode 100644
index a100b484e..000000000
--- a/guest/hals/ril/reference-libril/ril_commands.h
+++ /dev/null
@@ -1,189 +0,0 @@
-/* //guest/hals/ril/reference-libril/ril_commands.h
-**
-** Copyright 2006, 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.
-*/
- {0, NULL}, //none
- {RIL_REQUEST_GET_SIM_STATUS, radio_1_6::getIccCardStatusResponse},
- {RIL_REQUEST_ENTER_SIM_PIN, radio_1_6::supplyIccPinForAppResponse},
- {RIL_REQUEST_ENTER_SIM_PUK, radio_1_6::supplyIccPukForAppResponse},
- {RIL_REQUEST_ENTER_SIM_PIN2, radio_1_6::supplyIccPin2ForAppResponse},
- {RIL_REQUEST_ENTER_SIM_PUK2, radio_1_6::supplyIccPuk2ForAppResponse},
- {RIL_REQUEST_CHANGE_SIM_PIN, radio_1_6::changeIccPinForAppResponse},
- {RIL_REQUEST_CHANGE_SIM_PIN2, radio_1_6::changeIccPin2ForAppResponse},
- {RIL_REQUEST_ENTER_NETWORK_DEPERSONALIZATION, radio_1_6::supplyNetworkDepersonalizationResponse},
- {RIL_REQUEST_GET_CURRENT_CALLS, radio_1_6::getCurrentCallsResponse},
- {RIL_REQUEST_DIAL, radio_1_6::dialResponse},
- {RIL_REQUEST_GET_IMSI, radio_1_6::getIMSIForAppResponse},
- {RIL_REQUEST_HANGUP, radio_1_6::hangupConnectionResponse},
- {RIL_REQUEST_HANGUP_WAITING_OR_BACKGROUND, radio_1_6::hangupWaitingOrBackgroundResponse},
- {RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND, radio_1_6::hangupForegroundResumeBackgroundResponse},
- {RIL_REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE, radio_1_6::switchWaitingOrHoldingAndActiveResponse},
- {RIL_REQUEST_CONFERENCE, radio_1_6::conferenceResponse},
- {RIL_REQUEST_UDUB, radio_1_6::rejectCallResponse},
- {RIL_REQUEST_LAST_CALL_FAIL_CAUSE, radio_1_6::getLastCallFailCauseResponse},
- {RIL_REQUEST_SIGNAL_STRENGTH, radio_1_6::getSignalStrengthResponse},
- {RIL_REQUEST_VOICE_REGISTRATION_STATE, radio_1_6::getVoiceRegistrationStateResponse},
- {RIL_REQUEST_DATA_REGISTRATION_STATE, radio_1_6::getDataRegistrationStateResponse},
- {RIL_REQUEST_OPERATOR, radio_1_6::getOperatorResponse},
- {RIL_REQUEST_RADIO_POWER, radio_1_6::setRadioPowerResponse},
- {RIL_REQUEST_DTMF, radio_1_6::sendDtmfResponse},
- {RIL_REQUEST_SEND_SMS, radio_1_6::sendSmsResponse},
- {RIL_REQUEST_SEND_SMS_EXPECT_MORE, radio_1_6::sendSmsExpectMoreResponse},
- {RIL_REQUEST_SETUP_DATA_CALL, radio_1_6::setupDataCallResponse},
- {RIL_REQUEST_SIM_IO, radio_1_6::iccIOForAppResponse},
- {RIL_REQUEST_SEND_USSD, radio_1_6::sendUssdResponse},
- {RIL_REQUEST_CANCEL_USSD, radio_1_6::cancelPendingUssdResponse},
- {RIL_REQUEST_GET_CLIR, radio_1_6::getClirResponse},
- {RIL_REQUEST_SET_CLIR, radio_1_6::setClirResponse},
- {RIL_REQUEST_QUERY_CALL_FORWARD_STATUS, radio_1_6::getCallForwardStatusResponse},
- {RIL_REQUEST_SET_CALL_FORWARD, radio_1_6::setCallForwardResponse},
- {RIL_REQUEST_QUERY_CALL_WAITING, radio_1_6::getCallWaitingResponse},
- {RIL_REQUEST_SET_CALL_WAITING, radio_1_6::setCallWaitingResponse},
- {RIL_REQUEST_SMS_ACKNOWLEDGE, radio_1_6::acknowledgeLastIncomingGsmSmsResponse},
- {RIL_REQUEST_GET_IMEI, NULL},
- {RIL_REQUEST_GET_IMEISV, NULL},
- {RIL_REQUEST_ANSWER, radio_1_6::acceptCallResponse},
- {RIL_REQUEST_DEACTIVATE_DATA_CALL, radio_1_6::deactivateDataCallResponse},
- {RIL_REQUEST_QUERY_FACILITY_LOCK, radio_1_6::getFacilityLockForAppResponse},
- {RIL_REQUEST_SET_FACILITY_LOCK, radio_1_6::setFacilityLockForAppResponse},
- {RIL_REQUEST_CHANGE_BARRING_PASSWORD, radio_1_6::setBarringPasswordResponse},
- {RIL_REQUEST_QUERY_NETWORK_SELECTION_MODE, radio_1_6::getNetworkSelectionModeResponse},
- {RIL_REQUEST_SET_NETWORK_SELECTION_AUTOMATIC, radio_1_6::setNetworkSelectionModeAutomaticResponse},
- {RIL_REQUEST_SET_NETWORK_SELECTION_MANUAL, radio_1_6::setNetworkSelectionModeManualResponse},
- {RIL_REQUEST_QUERY_AVAILABLE_NETWORKS , radio_1_6::getAvailableNetworksResponse},
- {RIL_REQUEST_DTMF_START, radio_1_6::startDtmfResponse},
- {RIL_REQUEST_DTMF_STOP, radio_1_6::stopDtmfResponse},
- {RIL_REQUEST_BASEBAND_VERSION, radio_1_6::getBasebandVersionResponse},
- {RIL_REQUEST_SEPARATE_CONNECTION, radio_1_6::separateConnectionResponse},
- {RIL_REQUEST_SET_MUTE, radio_1_6::setMuteResponse},
- {RIL_REQUEST_GET_MUTE, radio_1_6::getMuteResponse},
- {RIL_REQUEST_QUERY_CLIP, radio_1_6::getClipResponse},
- {RIL_REQUEST_LAST_DATA_CALL_FAIL_CAUSE, NULL},
- {RIL_REQUEST_DATA_CALL_LIST, radio_1_6::getDataCallListResponse},
- {RIL_REQUEST_RESET_RADIO, NULL},
- {RIL_REQUEST_OEM_HOOK_RAW, radio_1_6::sendRequestRawResponse},
- {RIL_REQUEST_OEM_HOOK_STRINGS, radio_1_6::sendRequestStringsResponse},
- {RIL_REQUEST_SCREEN_STATE, radio_1_6::sendDeviceStateResponse}, // Note the response function is different.
- {RIL_REQUEST_SET_SUPP_SVC_NOTIFICATION, radio_1_6::setSuppServiceNotificationsResponse},
- {RIL_REQUEST_WRITE_SMS_TO_SIM, radio_1_6::writeSmsToSimResponse},
- {RIL_REQUEST_DELETE_SMS_ON_SIM, radio_1_6::deleteSmsOnSimResponse},
- {RIL_REQUEST_SET_BAND_MODE, radio_1_6::setBandModeResponse},
- {RIL_REQUEST_QUERY_AVAILABLE_BAND_MODE, radio_1_6::getAvailableBandModesResponse},
- {RIL_REQUEST_STK_GET_PROFILE, NULL},
- {RIL_REQUEST_STK_SET_PROFILE, NULL},
- {RIL_REQUEST_STK_SEND_ENVELOPE_COMMAND, radio_1_6::sendEnvelopeResponse},
- {RIL_REQUEST_STK_SEND_TERMINAL_RESPONSE, radio_1_6::sendTerminalResponseToSimResponse},
- {RIL_REQUEST_STK_HANDLE_CALL_SETUP_REQUESTED_FROM_SIM, radio_1_6::handleStkCallSetupRequestFromSimResponse},
- {RIL_REQUEST_EXPLICIT_CALL_TRANSFER, radio_1_6::explicitCallTransferResponse},
- {RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE, radio_1_6::setPreferredNetworkTypeResponse},
- {RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE, radio_1_6::getPreferredNetworkTypeResponse},
- {RIL_REQUEST_GET_NEIGHBORING_CELL_IDS, radio_1_6::getNeighboringCidsResponse},
- {RIL_REQUEST_SET_LOCATION_UPDATES, radio_1_6::setLocationUpdatesResponse},
- {RIL_REQUEST_CDMA_SET_SUBSCRIPTION_SOURCE, radio_1_6::setCdmaSubscriptionSourceResponse},
- {RIL_REQUEST_CDMA_SET_ROAMING_PREFERENCE, radio_1_6::setCdmaRoamingPreferenceResponse},
- {RIL_REQUEST_CDMA_QUERY_ROAMING_PREFERENCE, radio_1_6::getCdmaRoamingPreferenceResponse},
- {RIL_REQUEST_SET_TTY_MODE, radio_1_6::setTTYModeResponse},
- {RIL_REQUEST_QUERY_TTY_MODE, radio_1_6::getTTYModeResponse},
- {RIL_REQUEST_CDMA_SET_PREFERRED_VOICE_PRIVACY_MODE, radio_1_6::setPreferredVoicePrivacyResponse},
- {RIL_REQUEST_CDMA_QUERY_PREFERRED_VOICE_PRIVACY_MODE, radio_1_6::getPreferredVoicePrivacyResponse},
- {RIL_REQUEST_CDMA_FLASH, radio_1_6::sendCDMAFeatureCodeResponse},
- {RIL_REQUEST_CDMA_BURST_DTMF, radio_1_6::sendBurstDtmfResponse},
- {RIL_REQUEST_CDMA_VALIDATE_AND_WRITE_AKEY, NULL},
- {RIL_REQUEST_CDMA_SEND_SMS, radio_1_6::sendCdmaSmsResponse},
- {RIL_REQUEST_CDMA_SMS_ACKNOWLEDGE, radio_1_6::acknowledgeLastIncomingCdmaSmsResponse},
- {RIL_REQUEST_GSM_GET_BROADCAST_SMS_CONFIG, radio_1_6::getGsmBroadcastConfigResponse},
- {RIL_REQUEST_GSM_SET_BROADCAST_SMS_CONFIG, radio_1_6::setGsmBroadcastConfigResponse},
- {RIL_REQUEST_GSM_SMS_BROADCAST_ACTIVATION, radio_1_6::setGsmBroadcastActivationResponse},
- {RIL_REQUEST_CDMA_GET_BROADCAST_SMS_CONFIG, radio_1_6::getCdmaBroadcastConfigResponse},
- {RIL_REQUEST_CDMA_SET_BROADCAST_SMS_CONFIG, radio_1_6::setCdmaBroadcastConfigResponse},
- {RIL_REQUEST_CDMA_SMS_BROADCAST_ACTIVATION, radio_1_6::setCdmaBroadcastActivationResponse},
- {RIL_REQUEST_CDMA_SUBSCRIPTION, radio_1_6::getCDMASubscriptionResponse},
- {RIL_REQUEST_CDMA_WRITE_SMS_TO_RUIM, radio_1_6::writeSmsToRuimResponse},
- {RIL_REQUEST_CDMA_DELETE_SMS_ON_RUIM, radio_1_6::deleteSmsOnRuimResponse},
- {RIL_REQUEST_DEVICE_IDENTITY, radio_1_6::getDeviceIdentityResponse},
- {RIL_REQUEST_EXIT_EMERGENCY_CALLBACK_MODE, radio_1_6::exitEmergencyCallbackModeResponse},
- {RIL_REQUEST_GET_SMSC_ADDRESS, radio_1_6::getSmscAddressResponse},
- {RIL_REQUEST_SET_SMSC_ADDRESS, radio_1_6::setSmscAddressResponse},
- {RIL_REQUEST_REPORT_SMS_MEMORY_STATUS, radio_1_6::reportSmsMemoryStatusResponse},
- {RIL_REQUEST_REPORT_STK_SERVICE_IS_RUNNING, radio_1_6::reportStkServiceIsRunningResponse},
- {RIL_REQUEST_CDMA_GET_SUBSCRIPTION_SOURCE, radio_1_6::getCdmaSubscriptionSourceResponse},
- {RIL_REQUEST_ISIM_AUTHENTICATION, radio_1_6::requestIsimAuthenticationResponse},
- {RIL_REQUEST_ACKNOWLEDGE_INCOMING_GSM_SMS_WITH_PDU, radio_1_6::acknowledgeIncomingGsmSmsWithPduResponse},
- {RIL_REQUEST_STK_SEND_ENVELOPE_WITH_STATUS, radio_1_6::sendEnvelopeWithStatusResponse},
- {RIL_REQUEST_VOICE_RADIO_TECH, radio_1_6::getVoiceRadioTechnologyResponse},
- {RIL_REQUEST_GET_CELL_INFO_LIST, radio_1_6::getCellInfoListResponse},
- {RIL_REQUEST_SET_UNSOL_CELL_INFO_LIST_RATE, radio_1_6::setCellInfoListRateResponse},
- {RIL_REQUEST_SET_INITIAL_ATTACH_APN, radio_1_6::setInitialAttachApnResponse},
- {RIL_REQUEST_IMS_REGISTRATION_STATE, radio_1_6::getImsRegistrationStateResponse},
- {RIL_REQUEST_IMS_SEND_SMS, radio_1_6::sendImsSmsResponse},
- {RIL_REQUEST_SIM_TRANSMIT_APDU_BASIC, radio_1_6::iccTransmitApduBasicChannelResponse},
- {RIL_REQUEST_SIM_OPEN_CHANNEL, radio_1_6::iccOpenLogicalChannelResponse},
- {RIL_REQUEST_SIM_CLOSE_CHANNEL, radio_1_6::iccCloseLogicalChannelResponse},
- {RIL_REQUEST_SIM_TRANSMIT_APDU_CHANNEL, radio_1_6::iccTransmitApduLogicalChannelResponse},
- {RIL_REQUEST_NV_READ_ITEM, radio_1_6::nvReadItemResponse},
- {RIL_REQUEST_NV_WRITE_ITEM, radio_1_6::nvWriteItemResponse},
- {RIL_REQUEST_NV_WRITE_CDMA_PRL, radio_1_6::nvWriteCdmaPrlResponse},
- {RIL_REQUEST_NV_RESET_CONFIG, radio_1_6::nvResetConfigResponse},
- {RIL_REQUEST_SET_UICC_SUBSCRIPTION, radio_1_6::setUiccSubscriptionResponse},
- {RIL_REQUEST_ALLOW_DATA, radio_1_6::setDataAllowedResponse},
- {RIL_REQUEST_GET_HARDWARE_CONFIG, radio_1_6::getHardwareConfigResponse},
- {RIL_REQUEST_SIM_AUTHENTICATION, radio_1_6::requestIccSimAuthenticationResponse},
- {RIL_REQUEST_GET_DC_RT_INFO, NULL},
- {RIL_REQUEST_SET_DC_RT_INFO_RATE, NULL},
- {RIL_REQUEST_SET_DATA_PROFILE, radio_1_6::setDataProfileResponse},
- {RIL_REQUEST_SHUTDOWN, radio_1_6::requestShutdownResponse},
- {RIL_REQUEST_GET_RADIO_CAPABILITY, radio_1_6::getRadioCapabilityResponse},
- {RIL_REQUEST_SET_RADIO_CAPABILITY, radio_1_6::setRadioCapabilityResponse},
- {RIL_REQUEST_START_LCE, radio_1_6::startLceServiceResponse},
- {RIL_REQUEST_STOP_LCE, radio_1_6::stopLceServiceResponse},
- {RIL_REQUEST_PULL_LCEDATA, radio_1_6::pullLceDataResponse},
- {RIL_REQUEST_GET_ACTIVITY_INFO, radio_1_6::getModemActivityInfoResponse},
- {RIL_REQUEST_SET_CARRIER_RESTRICTIONS, radio_1_6::setAllowedCarriersResponse},
- {RIL_REQUEST_GET_CARRIER_RESTRICTIONS, radio_1_6::getAllowedCarriersResponse},
- {RIL_REQUEST_SEND_DEVICE_STATE, radio_1_6::sendDeviceStateResponse},
- {RIL_REQUEST_SET_UNSOLICITED_RESPONSE_FILTER, radio_1_6::setIndicationFilterResponse},
- {RIL_REQUEST_SET_SIM_CARD_POWER, radio_1_6::setSimCardPowerResponse},
- {RIL_REQUEST_SET_CARRIER_INFO_IMSI_ENCRYPTION, radio_1_6::setCarrierInfoForImsiEncryptionResponse},
- {RIL_REQUEST_START_NETWORK_SCAN, radio_1_6::startNetworkScanResponse},
- {RIL_REQUEST_STOP_NETWORK_SCAN, radio_1_6::stopNetworkScanResponse},
- {RIL_REQUEST_START_KEEPALIVE, radio_1_6::startKeepaliveResponse},
- {RIL_REQUEST_STOP_KEEPALIVE, radio_1_6::stopKeepaliveResponse},
- {RIL_REQUEST_GET_MODEM_STACK_STATUS, radio_1_6::getModemStackStatusResponse},
- {RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE_BITMAP, radio_1_6::getPreferredNetworkTypeBitmapResponse},
- {RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE_BITMAP, radio_1_6::setPreferredNetworkTypeBitmapResponse},
- {RIL_REQUEST_EMERGENCY_DIAL, radio_1_6::emergencyDialResponse},
- {RIL_REQUEST_SET_SYSTEM_SELECTION_CHANNELS, radio_1_6::setSystemSelectionChannelsResponse},
- {RIL_REQUEST_ENABLE_MODEM, radio_1_6::enableModemResponse},
- {RIL_REQUEST_SET_SIGNAL_STRENGTH_REPORTING_CRITERIA, radio_1_6::setSignalStrengthReportingCriteriaResponse},
- {RIL_REQUEST_SET_LINK_CAPACITY_REPORTING_CRITERIA, radio_1_6::setLinkCapacityReportingCriteriaResponse},
- {RIL_REQUEST_ENABLE_UICC_APPLICATIONS, radio_1_6::enableUiccApplicationsResponse},
- {RIL_REQUEST_ARE_UICC_APPLICATIONS_ENABLED, radio_1_6::areUiccApplicationsEnabledResponse},
- {RIL_REQUEST_ENTER_SIM_DEPERSONALIZATION, radio_1_6::supplySimDepersonalizationResponse},
- {RIL_REQUEST_CDMA_SEND_SMS_EXPECT_MORE, radio_1_6::sendCdmaSmsExpectMoreResponse},
- {RIL_REQUEST_GET_BARRING_INFO, radio_1_6::getBarringInfoResponse},
- {RIL_REQUEST_ENABLE_NR_DUAL_CONNECTIVITY, radio_1_6::setNrDualConnectivityStateResponse},
- {RIL_REQUEST_IS_NR_DUAL_CONNECTIVITY_ENABLED, radio_1_6::isNrDualConnectivityEnabledResponse},
- {RIL_REQUEST_ALLOCATE_PDU_SESSION_ID, radio_1_6::allocatePduSessionIdResponse},
- {RIL_REQUEST_RELEASE_PDU_SESSION_ID, radio_1_6::releasePduSessionIdResponse},
- {RIL_REQUEST_START_HANDOVER, radio_1_6::startHandoverResponse},
- {RIL_REQUEST_CANCEL_HANDOVER, radio_1_6::cancelHandoverResponse},
- {RIL_REQUEST_SET_ALLOWED_NETWORK_TYPES_BITMAP, radio_1_6::setAllowedNetworkTypesBitmapResponse},
- {RIL_REQUEST_SET_DATA_THROTTLING, radio_1_6::setDataThrottlingResponse},
- {RIL_REQUEST_GET_SYSTEM_SELECTION_CHANNELS, radio_1_6::getSystemSelectionChannelsResponse},
- {RIL_REQUEST_GET_ALLOWED_NETWORK_TYPES_BITMAP, radio_1_6::getAllowedNetworkTypesBitmapResponse},
- {RIL_REQUEST_GET_SLICING_CONFIG, radio_1_6::getSlicingConfigResponse},
- {RIL_REQUEST_GET_SIM_PHONEBOOK_RECORDS, radio_1_6::getSimPhonebookRecordsResponse},
- {RIL_REQUEST_GET_SIM_PHONEBOOK_CAPACITY, radio_1_6::getSimPhonebookCapacityResponse},
- {RIL_REQUEST_UPDATE_SIM_PHONEBOOK_RECORDS, radio_1_6::updateSimPhonebookRecordsResponse}
diff --git a/guest/hals/ril/reference-libril/ril_config.cpp b/guest/hals/ril/reference-libril/ril_config.cpp
deleted file mode 100644
index 5a72db980..000000000
--- a/guest/hals/ril/reference-libril/ril_config.cpp
+++ /dev/null
@@ -1,574 +0,0 @@
-/*
-**
-** Copyright 2020, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#define LOG_TAG "RILC"
-
-#include <android/hardware/radio/config/1.1/IRadioConfig.h>
-#include <android/hardware/radio/config/1.2/IRadioConfigResponse.h>
-#include <android/hardware/radio/config/1.3/IRadioConfigResponse.h>
-#include <android/hardware/radio/config/1.3/IRadioConfig.h>
-#include <android/hardware/radio/config/1.2/IRadioConfigIndication.h>
-#include <android/hardware/radio/1.1/types.h>
-
-#include <ril.h>
-#include <guest/hals/ril/reference-libril/ril_service.h>
-#include <hidl/HidlTransportSupport.h>
-
-using namespace android::hardware::radio::V1_0;
-using namespace android::hardware::radio::config;
-using namespace android::hardware::radio::config::V1_0;
-using namespace android::hardware::radio::config::V1_3;
-using ::android::hardware::configureRpcThreadpool;
-using ::android::hardware::joinRpcThreadpool;
-using ::android::hardware::Return;
-using ::android::hardware::hidl_string;
-using ::android::hardware::hidl_vec;
-using ::android::hardware::Void;
-using android::CommandInfo;
-using android::RequestInfo;
-using android::requestToString;
-using android::sp;
-
-RIL_RadioFunctions *s_vendorFunctions_config = NULL;
-static CommandInfo *s_configCommands;
-struct RadioConfigImpl;
-sp<RadioConfigImpl> radioConfigService;
-volatile int32_t mCounterRadioConfig;
-
-#if defined (ANDROID_MULTI_SIM)
-#define RIL_UNSOL_RESPONSE(a, b, c, d) RIL_onUnsolicitedResponse((a), (b), (c), (d))
-#define CALL_ONREQUEST(a, b, c, d, e) s_vendorFunctions_config->onRequest((a), (b), (c), (d), (e))
-#define CALL_ONSTATEREQUEST(a) s_vendorFunctions_config->onStateRequest(a)
-#else
-#define RIL_UNSOL_RESPONSE(a, b, c, d) RIL_onUnsolicitedResponse((a), (b), (c))
-#define CALL_ONREQUEST(a, b, c, d, e) s_vendorFunctions_config->onRequest((a), (b), (c), (d))
-#define CALL_ONSTATEREQUEST(a) s_vendorFunctions_config->onStateRequest()
-#endif
-
-extern void populateResponseInfo(RadioResponseInfo& responseInfo, int serial, int responseType,
- RIL_Errno e);
-
-extern void populateResponseInfo_1_6(
- ::android::hardware::radio::V1_6::RadioResponseInfo &responseInfo,
- int serial, int responseType, RIL_Errno e);
-
-extern bool dispatchVoid(int serial, int slotId, int request);
-extern bool dispatchString(int serial, int slotId, int request, const char * str);
-extern bool dispatchStrings(int serial, int slotId, int request, bool allowEmpty,
- int countStrings, ...);
-extern bool dispatchInts(int serial, int slotId, int request, int countInts, ...);
-extern hidl_string convertCharPtrToHidlString(const char *ptr);
-extern void sendErrorResponse(android::RequestInfo *pRI, RIL_Errno err);
-extern RadioIndicationType convertIntToRadioIndicationType(int indicationType);
-
-extern bool isChangeSlotId(int serviceId, int slotId);
-
-struct RadioConfigImpl : public V1_3::IRadioConfig {
- int32_t mSlotId;
- sp<V1_0::IRadioConfigResponse> mRadioConfigResponse;
- sp<V1_0::IRadioConfigIndication> mRadioConfigIndication;
- sp<V1_1::IRadioConfigResponse> mRadioConfigResponseV1_1;
- sp<V1_2::IRadioConfigResponse> mRadioConfigResponseV1_2;
- sp<V1_2::IRadioConfigIndication> mRadioConfigIndicationV1_2;
- sp<V1_3::IRadioConfigResponse> mRadioConfigResponseV1_3;
-
- Return<void> setResponseFunctions(
- const ::android::sp<V1_0::IRadioConfigResponse>& radioConfigResponse,
- const ::android::sp<V1_0::IRadioConfigIndication>& radioConfigIndication);
-
- Return<void> getSimSlotsStatus(int32_t serial);
-
- Return<void> setSimSlotsMapping(int32_t serial, const hidl_vec<uint32_t>& slotMap);
-
- Return<void> getPhoneCapability(int32_t serial);
-
- Return<void> setPreferredDataModem(int32_t serial, uint8_t modemId);
-
- Return<void> setModemsConfig(int32_t serial, const V1_1::ModemsConfig& modemsConfig);
-
- Return<void> getModemsConfig(int32_t serial);
-
- Return<void> getHalDeviceCapabilities(int32_t serial);
-
- void checkReturnStatus_config(Return<void>& ret);
-};
-Return<void> RadioConfigImpl::setResponseFunctions(
- const ::android::sp<V1_0::IRadioConfigResponse>& radioConfigResponse,
- const ::android::sp<V1_0::IRadioConfigIndication>& radioConfigIndication) {
- pthread_rwlock_t *radioServiceRwlockPtr = radio_1_6::getRadioServiceRwlock(RIL_SOCKET_1);
- int ret = pthread_rwlock_wrlock(radioServiceRwlockPtr);
- assert(ret == 0);
-
- mRadioConfigResponse = radioConfigResponse;
- mRadioConfigIndication = radioConfigIndication;
-
-
- mRadioConfigResponseV1_1 =
- V1_1::IRadioConfigResponse::castFrom(mRadioConfigResponse).withDefault(nullptr);
- if (mRadioConfigResponseV1_1 == nullptr) {
- mRadioConfigResponseV1_1 = nullptr;
- }
-
- mRadioConfigResponseV1_2 =
- V1_2::IRadioConfigResponse::castFrom(mRadioConfigResponse).withDefault(nullptr);
- mRadioConfigIndicationV1_2 =
- V1_2::IRadioConfigIndication::castFrom(mRadioConfigIndication).withDefault(nullptr);
- if (mRadioConfigResponseV1_2 == nullptr || mRadioConfigIndicationV1_2 == nullptr) {
- mRadioConfigResponseV1_2 = nullptr;
- mRadioConfigIndicationV1_2 = nullptr;
- }
-
- mRadioConfigResponseV1_3 =
- V1_3::IRadioConfigResponse::castFrom(mRadioConfigResponse).withDefault(nullptr);
- if (mRadioConfigResponseV1_3 == nullptr || mRadioConfigResponseV1_3 == nullptr) {
- mRadioConfigResponseV1_3 = nullptr;
- }
-
- mCounterRadioConfig++;
-
- ret = pthread_rwlock_unlock(radioServiceRwlockPtr);
- assert(ret == 0);
-
- return Void();
-}
-
-Return<void> RadioConfigImpl::getSimSlotsStatus(int32_t serial) {
-#if VDBG
- RLOGD("getSimSlotsStatus: serial %d", serial);
-#endif
- dispatchVoid(serial, mSlotId, RIL_REQUEST_CONFIG_GET_SLOT_STATUS);
-
- return Void();
-}
-
-Return<void> RadioConfigImpl::setSimSlotsMapping(int32_t serial, const hidl_vec<uint32_t>& slotMap) {
-#if VDBG
- RLOGD("setSimSlotsMapping: serial %d", serial);
-#endif
- RequestInfo *pRI = android::addRequestToList(serial, RIL_SOCKET_1,
- RIL_REQUEST_CONFIG_SET_SLOT_MAPPING);
- if (pRI == NULL) {
- return Void();
- }
- size_t slotNum = slotMap.size();
-
- if (slotNum > RIL_SOCKET_NUM) {
- RLOGE("setSimSlotsMapping: invalid parameter");
- sendErrorResponse(pRI, RIL_E_INVALID_ARGUMENTS);
- return Void();
- }
-
- for (size_t socket_id = 0; socket_id < slotNum; socket_id++) {
- if (slotMap[socket_id] >= RIL_SOCKET_NUM) {
- RLOGE("setSimSlotsMapping: invalid parameter[%zu]", socket_id);
- sendErrorResponse(pRI, RIL_E_INVALID_ARGUMENTS);
- return Void();
- }
- // confirm logical id is not duplicate
- for (size_t nextId = socket_id + 1; nextId < slotNum; nextId++) {
- if (slotMap[socket_id] == slotMap[nextId]) {
- RLOGE("setSimSlotsMapping: slot parameter is the same:[%zu] and [%zu]",
- socket_id, nextId);
- sendErrorResponse(pRI, RIL_E_INVALID_ARGUMENTS);
- return Void();
- }
- }
- }
- int *pSlotMap = (int *)calloc(slotNum, sizeof(int));
-
- for (size_t socket_id = 0; socket_id < slotNum; socket_id++) {
- pSlotMap[socket_id] = slotMap[socket_id];
- }
-
- CALL_ONREQUEST(RIL_REQUEST_CONFIG_SET_SLOT_MAPPING, pSlotMap,
- slotNum * sizeof(int), pRI, pRI->socket_id);
- if (pSlotMap != NULL) {
- free(pSlotMap);
- }
-
- return Void();
-}
-
-Return<void> RadioConfigImpl::getPhoneCapability(int32_t serial) {
-#if VDBG
- RLOGD("getPhoneCapability: serial %d", serial);
-#endif
- dispatchVoid(serial, mSlotId, RIL_REQUEST_CONFIG_GET_PHONE_CAPABILITY);
- return Void();
-}
-
-Return<void> RadioConfigImpl::setPreferredDataModem(int32_t serial, uint8_t modemId) {
-#if VDBG
- RLOGD("setPreferredDataModem: serial %d", serial);
-#endif
- dispatchInts(serial, mSlotId, RIL_REQUEST_CONFIG_SET_PREFER_DATA_MODEM, 1, modemId);
- return Void();
-}
-
-Return<void> RadioConfigImpl::setModemsConfig(int32_t serial, const V1_1::ModemsConfig& modemsConfig) {
-#if VDBG
- RLOGD("setModemsConfig: serial %d", serial);
-#endif
- RequestInfo *pRI = android::addRequestToList(serial, mSlotId,
- RIL_REQUEST_CONFIG_SET_MODEM_CONFIG);
- if (pRI == NULL) {
- return Void();
- }
-
- RIL_ModemConfig mdConfig = {};
-
- mdConfig.numOfLiveModems = modemsConfig.numOfLiveModems;
-
-
- CALL_ONREQUEST(RIL_REQUEST_CONFIG_SET_MODEM_CONFIG, &mdConfig,
- sizeof(RIL_ModemConfig), pRI, pRI->socket_id);
-
- return Void();
-}
-
-Return<void> RadioConfigImpl::getModemsConfig(int32_t serial) {
-#if VDBG
- RLOGD("getModemsConfig: serial %d", serial);
-#endif
- dispatchVoid(serial, mSlotId, RIL_REQUEST_CONFIG_GET_MODEM_CONFIG);
- return Void();
-}
-
-Return<void> RadioConfigImpl::getHalDeviceCapabilities(int32_t serial) {
-#if VDBG
- RLOGD("getHalDeviceCapabilities: serial %d", serial);
-#endif
- dispatchVoid(serial, mSlotId, RIL_REQUEST_CONFIG_GET_HAL_DEVICE_CAPABILITIES);
- return Void();
-}
-
-void radio_1_6::registerConfigService(RIL_RadioFunctions *callbacks, CommandInfo *commands) {
- using namespace android::hardware;
- RLOGD("Entry %s", __FUNCTION__);
- const char *serviceNames = "default";
-
- s_vendorFunctions_config = callbacks;
- s_configCommands = commands;
-
- int slotId = RIL_SOCKET_1;
-
- pthread_rwlock_t *radioServiceRwlockPtr = getRadioServiceRwlock(0);
- int ret = pthread_rwlock_wrlock(radioServiceRwlockPtr);
- assert(ret == 0);
- RLOGD("registerConfigService: starting V1_2::IConfigRadio %s", serviceNames);
- radioConfigService = new RadioConfigImpl;
-
- radioConfigService->mSlotId = slotId;
- radioConfigService->mRadioConfigResponse = NULL;
- radioConfigService->mRadioConfigIndication = NULL;
- radioConfigService->mRadioConfigResponseV1_1 = NULL;
- radioConfigService->mRadioConfigResponseV1_2 = NULL;
- radioConfigService->mRadioConfigResponseV1_3 = NULL;
- radioConfigService->mRadioConfigIndicationV1_2 = NULL;
- android::status_t status = radioConfigService->registerAsService(serviceNames);
- RLOGD("registerConfigService registerService: status %d", status);
- ret = pthread_rwlock_unlock(radioServiceRwlockPtr);
- assert(ret == 0);
-}
-
-void checkReturnStatus(Return<void>& ret) {
- if (ret.isOk() == false) {
- RLOGE("checkReturnStatus_config: unable to call response/indication callback");
- // Remote process hosting the callbacks must be dead. Reset the callback objects;
- // there's no other recovery to be done here. When the client process is back up, it will
- // call setResponseFunctions()
-
- // Caller should already hold rdlock, release that first
- // note the current counter to avoid overwriting updates made by another thread before
- // write lock is acquired.
- int counter = mCounterRadioConfig;
- pthread_rwlock_t *radioServiceRwlockPtr = radio_1_6::getRadioServiceRwlock(0);
- int ret = pthread_rwlock_unlock(radioServiceRwlockPtr);
- assert(ret == 0);
-
- // acquire wrlock
- ret = pthread_rwlock_wrlock(radioServiceRwlockPtr);
- assert(ret == 0);
-
- // make sure the counter value has not changed
- if (counter == mCounterRadioConfig) {
- radioConfigService->mRadioConfigResponse = NULL;
- radioConfigService->mRadioConfigIndication = NULL;
- radioConfigService->mRadioConfigResponseV1_1 = NULL;
- radioConfigService->mRadioConfigResponseV1_2 = NULL;
- radioConfigService->mRadioConfigResponseV1_3 = NULL;
- radioConfigService->mRadioConfigIndicationV1_2 = NULL;
- mCounterRadioConfig++;
- } else {
- RLOGE("checkReturnStatus_config: not resetting responseFunctions as they likely "
- "got updated on another thread");
- }
-
- // release wrlock
- ret = pthread_rwlock_unlock(radioServiceRwlockPtr);
- assert(ret == 0);
-
- // Reacquire rdlock
- ret = pthread_rwlock_rdlock(radioServiceRwlockPtr);
- assert(ret == 0);
- }
-}
-
-void RadioConfigImpl::checkReturnStatus_config(Return<void>& ret) {
- ::checkReturnStatus(ret);
-}
-
-int radio_1_6::getSimSlotsStatusResponse(int slotId, int responseType, int serial,
- RIL_Errno e, void *response, size_t responseLen) {
-#if VDBG
- RLOGD("getSimSlotsResponse: serial %d", serial);
-#endif
-
- if (radioConfigService->mRadioConfigResponse != NULL) {
- RadioResponseInfo responseInfo = {};
- populateResponseInfo(responseInfo, serial, responseType, e);
- hidl_vec<SimSlotStatus> simSlotStatus = {};
-
- if ((response == NULL) || (responseLen % sizeof(RIL_SimSlotStatus_V1_2) != 0)) {
- RLOGE("getSimSlotsStatusResponse: Invalid response");
- if (e == RIL_E_SUCCESS) responseInfo.error = RadioError::INVALID_RESPONSE;
- } else {
- RIL_SimSlotStatus_V1_2 *psimSlotStatus = ((RIL_SimSlotStatus_V1_2 *) response);
- int num = responseLen / sizeof(RIL_SimSlotStatus_V1_2);
- simSlotStatus.resize(num);
- for (int i = 0; i < num; i++) {
- simSlotStatus[i].cardState = (CardState)psimSlotStatus->base.cardState;
- simSlotStatus[i].slotState = (SlotState)psimSlotStatus->base.slotState;
- simSlotStatus[i].atr = convertCharPtrToHidlString(psimSlotStatus->base.atr);
- simSlotStatus[i].logicalSlotId = psimSlotStatus->base.logicalSlotId;
- simSlotStatus[i].iccid = convertCharPtrToHidlString(psimSlotStatus->base.iccid);
- psimSlotStatus += 1;
- }
- }
- Return<void> retStatus = radioConfigService->mRadioConfigResponse->getSimSlotsStatusResponse(
- responseInfo, simSlotStatus);
- radioConfigService->checkReturnStatus_config(retStatus);
- } else {
- RLOGE("getSimSlotsResponse: radioConfigService->mRadioConfigResponse == NULL");
- }
-
- return 0;
-}
-
-int radio_1_6::setSimSlotsMappingResponse(int slotId, int responseType, int serial,
- RIL_Errno e, void *response, size_t responseLen) {
-#if VDBG
- RLOGD("setSimSlotsMappingResponse: serial %d", serial);
-#endif
-
- if (radioConfigService->mRadioConfigResponse != NULL) {
- RadioResponseInfo responseInfo = {};
- populateResponseInfo(responseInfo, serial, responseType, e);
- Return<void> retStatus = radioConfigService->mRadioConfigResponse->setSimSlotsMappingResponse(
- responseInfo);
- radioConfigService->checkReturnStatus_config(retStatus);
- } else {
- RLOGE("setSimSlotsMappingResponse: radioConfigService->mRadioConfigResponse == NULL");
- }
-
- return 0;
-}
-
-int radio_1_6::getPhoneCapabilityResponse(int slotId, int responseType, int serial,
- RIL_Errno e, void *response, size_t responseLen) {
-#if VDBG
- RLOGD("getPhoneCapabilityResponse: serial %d", serial);
-#endif
-
- if (radioConfigService->mRadioConfigResponseV1_1 != NULL) {
- RadioResponseInfo responseInfo = {};
- populateResponseInfo(responseInfo, serial, responseType, e);
- V1_1::PhoneCapability phoneCapability = {};
- if ((response == NULL) || (responseLen % sizeof(RIL_PhoneCapability) != 0)) {
- RLOGE("getPhoneCapabilityResponse Invalid response: NULL");
- if (e == RIL_E_SUCCESS) responseInfo.error = RadioError::INVALID_RESPONSE;
- } else {
- RIL_PhoneCapability *pCapability = (RIL_PhoneCapability *)response;
- phoneCapability.maxActiveData = pCapability->maxActiveData;
- phoneCapability.maxActiveInternetData = pCapability->maxActiveInternetData;
- phoneCapability.isInternetLingeringSupported = pCapability->isInternetLingeringSupported;
- phoneCapability.logicalModemList.resize(SIM_COUNT);
- for (int i = 0 ; i < SIM_COUNT; i++) {
- RIL_ModemInfo logicalModemInfo = pCapability->logicalModemList[i];
- phoneCapability.logicalModemList[i].modemId = logicalModemInfo.modemId;
- }
- }
- Return<void> retStatus = radioConfigService->mRadioConfigResponseV1_1->getPhoneCapabilityResponse(
- responseInfo, phoneCapability);
- radioConfigService->checkReturnStatus_config(retStatus);
- } else {
- RLOGE("getPhoneCapabilityResponse: radioConfigService->mRadioConfigResponseV1_1 == NULL");
- }
-
- return 0;
-}
-
-int radio_1_6::setPreferredDataModemResponse(int slotId, int responseType, int serial,
- RIL_Errno e, void *response, size_t responseLen) {
-#if VDBG
- RLOGD("setPreferredDataModemResponse: serial %d", serial);
-#endif
-
- if (radioConfigService->mRadioConfigResponseV1_1 != NULL) {
- RadioResponseInfo responseInfo = {};
- populateResponseInfo(responseInfo, serial, responseType, e);
- Return<void> retStatus = radioConfigService->mRadioConfigResponseV1_1->setPreferredDataModemResponse(
- responseInfo);
- radioConfigService->checkReturnStatus_config(retStatus);
- } else {
- RLOGE("setPreferredDataModemResponse: radioConfigService->mRadioConfigResponseV1_1 == NULL");
- }
-
- return 0;
-}
-
-int radio_1_6::setModemsConfigResponse(int slotId, int responseType, int serial,
- RIL_Errno e, void *response, size_t responseLen) {
-#if VDBG
- RLOGD("setModemsConfigResponse: serial %d", serial);
-#endif
-
- if (radioConfigService->mRadioConfigResponseV1_1 != NULL) {
- RadioResponseInfo responseInfo = {};
- populateResponseInfo(responseInfo, serial, responseType, e);
- Return<void> retStatus = radioConfigService->mRadioConfigResponseV1_1->setModemsConfigResponse(
- responseInfo);
- radioConfigService->checkReturnStatus_config(retStatus);
- } else {
- RLOGE("setModemsConfigResponse: radioConfigService->mRadioConfigResponseV1_1 == NULL");
- }
-
- return 0;
-}
-
-int radio_1_6::getModemsConfigResponse(int slotId, int responseType, int serial,
- RIL_Errno e, void *response, size_t responseLen) {
-#if VDBG
- RLOGD("getModemsConfigResponse: serial %d", serial);
-#endif
-
- if (radioConfigService->mRadioConfigResponseV1_1 != NULL) {
- RadioResponseInfo responseInfo = {};
- populateResponseInfo(responseInfo, serial, responseType, e);
- V1_1::ModemsConfig mdCfg = {};
- RIL_ModemConfig *pMdCfg = (RIL_ModemConfig *)response;
- if ((response == NULL) || (responseLen != sizeof(RIL_ModemConfig))) {
- RLOGE("getModemsConfigResponse Invalid response: NULL");
- if (e == RIL_E_SUCCESS) responseInfo.error = RadioError::INVALID_RESPONSE;
- } else {
- mdCfg.numOfLiveModems = pMdCfg->numOfLiveModems;
- }
- Return<void> retStatus = radioConfigService->mRadioConfigResponseV1_1->getModemsConfigResponse(
- responseInfo, mdCfg);
- radioConfigService->checkReturnStatus_config(retStatus);
- } else {
- RLOGE("getModemsConfigResponse: radioConfigService->mRadioConfigResponseV1_1 == NULL");
- }
-
- return 0;
-}
-
-int radio_1_6::getHalDeviceCapabilitiesResponse(int slotId, int responseType, int serial,
- RIL_Errno e, void *response, size_t responseLen) {
-#if VDBG
- RLOGD("getHalDeviceCapabilitiesResponse: serial %d", serial);
-#endif
-
- if (radioConfigService->mRadioConfigResponseV1_3 != NULL) {
- ::android::hardware::radio::V1_6::RadioResponseInfo responseInfo = {};
- populateResponseInfo_1_6(responseInfo, serial, responseType, e);
-
- bool modemReducedFeatureSet1 = false;
- if (response == NULL || responseLen != sizeof(bool)) {
- RLOGE("getHalDeviceCapabilitiesResponse Invalid response.");
- } else {
- modemReducedFeatureSet1 = (*((bool *) response));
- }
-
- Return<void> retStatus = radioConfigService->mRadioConfigResponseV1_3->getHalDeviceCapabilitiesResponse(
- responseInfo, modemReducedFeatureSet1);
- radioConfigService->checkReturnStatus_config(retStatus);
- } else {
- RLOGE("getHalDeviceCapabilitiesResponse: radioConfigService->getHalDeviceCapabilities == NULL");
- }
-
- return 0;
-}
-
-int radio_1_6::simSlotsStatusChanged(int slotId, int indicationType, int token, RIL_Errno e,
- void *response, size_t responseLen) {
- if (radioConfigService != NULL &&
- (radioConfigService->mRadioConfigIndication != NULL ||
- radioConfigService->mRadioConfigIndicationV1_2 != NULL)) {
- if ((response == NULL) || (responseLen % sizeof(RIL_SimSlotStatus_V1_2) != 0)) {
- RLOGE("simSlotsStatusChanged: invalid response");
- return 0;
- }
-
- RIL_SimSlotStatus_V1_2 *psimSlotStatus = ((RIL_SimSlotStatus_V1_2 *)response);
- int num = responseLen / sizeof(RIL_SimSlotStatus_V1_2);
- if (radioConfigService->mRadioConfigIndication != NULL) {
- hidl_vec<SimSlotStatus> simSlotStatus = {};
- simSlotStatus.resize(num);
- for (int i = 0; i < num; i++) {
- simSlotStatus[i].cardState = (CardState) psimSlotStatus->base.cardState;
- simSlotStatus[i].slotState = (SlotState) psimSlotStatus->base.slotState;
- simSlotStatus[i].atr = convertCharPtrToHidlString(psimSlotStatus->base.atr);
- simSlotStatus[i].logicalSlotId = psimSlotStatus->base.logicalSlotId;
- simSlotStatus[i].iccid = convertCharPtrToHidlString(psimSlotStatus->base.iccid);
-#if VDBG
- RLOGD("simSlotsStatusChanged: cardState %d slotState %d", simSlotStatus[i].cardState,
- simSlotStatus[i].slotState);
-#endif
- psimSlotStatus += 1;
- }
-
- Return<void> retStatus = radioConfigService->mRadioConfigIndication->simSlotsStatusChanged(
- convertIntToRadioIndicationType(indicationType), simSlotStatus);
- radioConfigService->checkReturnStatus_config(retStatus);
- } else if (radioConfigService->mRadioConfigIndicationV1_2) {
- hidl_vec<V1_2::SimSlotStatus> simSlotStatus;
- simSlotStatus.resize(num);
- for (int i = 0; i < num; i++) {
- simSlotStatus[i].base.cardState = (CardState)(psimSlotStatus->base.cardState);
- simSlotStatus[i].base.slotState = (SlotState) psimSlotStatus->base.slotState;
- simSlotStatus[i].base.atr = convertCharPtrToHidlString(psimSlotStatus->base.atr);
- simSlotStatus[i].base.logicalSlotId = psimSlotStatus->base.logicalSlotId;
- simSlotStatus[i].base.iccid = convertCharPtrToHidlString(psimSlotStatus->base.iccid);
- simSlotStatus[i].eid = convertCharPtrToHidlString(psimSlotStatus->eid);
- psimSlotStatus += 1;
-#if VDBG
- RLOGD("simSlotsStatusChanged_1_2: cardState %d slotState %d",
- simSlotStatus[i].base.cardState, simSlotStatus[i].base.slotState);
-#endif
- }
-
- Return<void> retStatus = radioConfigService->mRadioConfigIndicationV1_2->simSlotsStatusChanged_1_2(
- convertIntToRadioIndicationType(indicationType), simSlotStatus);
- radioConfigService->checkReturnStatus_config(retStatus);
- }
- } else {
- RLOGE("simSlotsStatusChanged: radioService->mRadioIndication == NULL");
- }
-
- return 0;
-}
diff --git a/guest/hals/ril/reference-libril/ril_config_commands.h b/guest/hals/ril/reference-libril/ril_config_commands.h
deleted file mode 100644
index 960639006..000000000
--- a/guest/hals/ril/reference-libril/ril_config_commands.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
-**
-** Copyright 2020, 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.
-*/
- {0, NULL}, // none
- {RIL_REQUEST_CONFIG_GET_SLOT_STATUS, radio_1_6::getSimSlotsStatusResponse},
- {RIL_REQUEST_CONFIG_SET_SLOT_MAPPING, radio_1_6::setSimSlotsMappingResponse},
- {RIL_REQUEST_CONFIG_GET_PHONE_CAPABILITY, radio_1_6::getPhoneCapabilityResponse},
- {RIL_REQUEST_CONFIG_SET_PREFER_DATA_MODEM, radio_1_6::setPreferredDataModemResponse},
- {RIL_REQUEST_CONFIG_SET_MODEM_CONFIG, radio_1_6::setModemsConfigResponse},
- {RIL_REQUEST_CONFIG_GET_MODEM_CONFIG, radio_1_6::getModemsConfigResponse},
- {RIL_REQUEST_CONFIG_GET_HAL_DEVICE_CAPABILITIES, radio_1_6::getHalDeviceCapabilitiesResponse},
diff --git a/guest/hals/ril/reference-libril/ril_config_unsol_commands.h b/guest/hals/ril/reference-libril/ril_config_unsol_commands.h
deleted file mode 100644
index 1aee12f0d..000000000
--- a/guest/hals/ril/reference-libril/ril_config_unsol_commands.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
-**
-** Copyright 2020, 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.
-*/
- {RIL_UNSOL_CONFIG_ICC_SLOT_STATUS, radio_1_6::simSlotsStatusChanged, WAKE_PARTIAL},
diff --git a/guest/hals/ril/reference-libril/ril_event.h b/guest/hals/ril/reference-libril/ril_event.h
deleted file mode 100644
index 7ba231b76..000000000
--- a/guest/hals/ril/reference-libril/ril_event.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/* //device/libs/telephony/ril_event.h
-**
-** Copyright 2008, 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.
-*/
-
-// Max number of fd's we watch at any one time. Increase if necessary.
-#define MAX_FD_EVENTS 8
-
-typedef void (*ril_event_cb)(int fd, short events, void *userdata);
-
-struct ril_event {
- struct ril_event *next;
- struct ril_event *prev;
-
- int fd;
- int index;
- bool persist;
- struct timeval timeout;
- ril_event_cb func;
- void *param;
-};
-
-// Initialize internal data structs
-void ril_event_init();
-
-// Initialize an event
-void ril_event_set(struct ril_event * ev, int fd, bool persist, ril_event_cb func, void * param);
-
-// Add event to watch list
-void ril_event_add(struct ril_event * ev);
-
-// Add timer event
-void ril_timer_add(struct ril_event * ev, struct timeval * tv);
-
-// Remove event from watch list
-void ril_event_del(struct ril_event * ev);
-
-// Event loop
-void ril_event_loop();
-
diff --git a/guest/hals/ril/reference-libril/ril_internal.h b/guest/hals/ril/reference-libril/ril_internal.h
deleted file mode 100644
index 350791b26..000000000
--- a/guest/hals/ril/reference-libril/ril_internal.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (c) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_RIL_INTERNAL_H
-#define ANDROID_RIL_INTERNAL_H
-
-namespace android {
-
-#define RIL_SERVICE_NAME_BASE "slot"
-#define RIL1_SERVICE_NAME "slot1"
-#define RIL2_SERVICE_NAME "slot2"
-#define RIL3_SERVICE_NAME "slot3"
-#define RIL4_SERVICE_NAME "slot4"
-
-/* Constants for response types */
-#define RESPONSE_SOLICITED 0
-#define RESPONSE_UNSOLICITED 1
-#define RESPONSE_SOLICITED_ACK 2
-#define RESPONSE_SOLICITED_ACK_EXP 3
-#define RESPONSE_UNSOLICITED_ACK_EXP 4
-
-// Enable verbose logging
-#define VDBG 0
-
-#define MIN(a,b) ((a)<(b) ? (a) : (b))
-
-// Enable RILC log
-#define RILC_LOG 0
-
-#if RILC_LOG
- #define startRequest sprintf(printBuf, "(")
- #define closeRequest sprintf(printBuf, "%s)", printBuf)
- #define printRequest(token, req) \
- RLOGD("[%04d]> %s %s", token, requestToString(req), printBuf)
-
- #define startResponse sprintf(printBuf, "%s {", printBuf)
- #define closeResponse sprintf(printBuf, "%s}", printBuf)
- #define printResponse RLOGD("%s", printBuf)
-
- #define clearPrintBuf printBuf[0] = 0
- #define removeLastChar printBuf[strlen(printBuf)-1] = 0
- #define appendPrintBuf(x...) snprintf(printBuf, PRINTBUF_SIZE, x)
-#else
- #define startRequest
- #define closeRequest
- #define printRequest(token, req)
- #define startResponse
- #define closeResponse
- #define printResponse
- #define clearPrintBuf
- #define removeLastChar
- #define appendPrintBuf(x...)
-#endif
-
-typedef struct CommandInfo CommandInfo;
-
-extern "C" const char * requestToString(int request);
-
-typedef struct RequestInfo {
- int32_t token; //this is not RIL_Token
- CommandInfo *pCI;
- struct RequestInfo *p_next;
- char cancelled;
- char local; // responses to local commands do not go back to command process
- RIL_SOCKET_ID socket_id;
- int wasAckSent; // Indicates whether an ack was sent earlier
-} RequestInfo;
-
-typedef struct CommandInfo {
- int requestNumber;
- int(*responseFunction) (int slotId, int responseType, int token,
- RIL_Errno e, void *response, size_t responselen);
-} CommandInfo;
-
-RequestInfo * addRequestToList(int serial, int slotId, int request);
-
-char * RIL_getServiceName();
-
-void releaseWakeLock();
-
-void onNewCommandConnect(RIL_SOCKET_ID socket_id);
-
-} // namespace android
-
-#endif //ANDROID_RIL_INTERNAL_H
diff --git a/guest/hals/ril/reference-libril/ril_unsol_commands.h b/guest/hals/ril/reference-libril/ril_unsol_commands.h
deleted file mode 100644
index 62dd40c66..000000000
--- a/guest/hals/ril/reference-libril/ril_unsol_commands.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/* ///guest/hals/ril/reference-libril/ril_unsol_commands.h
-**
-** Copyright 2006, 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.
-*/
- {RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED, radio_1_6::radioStateChangedInd, WAKE_PARTIAL},
- {RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED, radio_1_6::callStateChangedInd, WAKE_PARTIAL},
- {RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED, radio_1_6::networkStateChangedInd, WAKE_PARTIAL},
- {RIL_UNSOL_RESPONSE_NEW_SMS, radio_1_6::newSmsInd, WAKE_PARTIAL},
- {RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT, radio_1_6::newSmsStatusReportInd, WAKE_PARTIAL},
- {RIL_UNSOL_RESPONSE_NEW_SMS_ON_SIM, radio_1_6::newSmsOnSimInd, WAKE_PARTIAL},
- {RIL_UNSOL_ON_USSD, radio_1_6::onUssdInd, WAKE_PARTIAL},
- {RIL_UNSOL_ON_USSD_REQUEST, radio_1_6::onUssdInd, DONT_WAKE},
- {RIL_UNSOL_NITZ_TIME_RECEIVED, radio_1_6::nitzTimeReceivedInd, WAKE_PARTIAL},
- {RIL_UNSOL_SIGNAL_STRENGTH, radio_1_6::currentSignalStrengthInd, DONT_WAKE},
- {RIL_UNSOL_DATA_CALL_LIST_CHANGED, radio_1_6::dataCallListChangedInd, WAKE_PARTIAL},
- {RIL_UNSOL_SUPP_SVC_NOTIFICATION, radio_1_6::suppSvcNotifyInd, WAKE_PARTIAL},
- {RIL_UNSOL_STK_SESSION_END, radio_1_6::stkSessionEndInd, WAKE_PARTIAL},
- {RIL_UNSOL_STK_PROACTIVE_COMMAND, radio_1_6::stkProactiveCommandInd, WAKE_PARTIAL},
- {RIL_UNSOL_STK_EVENT_NOTIFY, radio_1_6::stkEventNotifyInd, WAKE_PARTIAL},
- {RIL_UNSOL_STK_CALL_SETUP, radio_1_6::stkCallSetupInd, WAKE_PARTIAL},
- {RIL_UNSOL_SIM_SMS_STORAGE_FULL, radio_1_6::simSmsStorageFullInd, WAKE_PARTIAL},
- {RIL_UNSOL_SIM_REFRESH, radio_1_6::simRefreshInd, WAKE_PARTIAL},
- {RIL_UNSOL_CALL_RING, radio_1_6::callRingInd, WAKE_PARTIAL},
- {RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED, radio_1_6::simStatusChangedInd, WAKE_PARTIAL},
- {RIL_UNSOL_RESPONSE_CDMA_NEW_SMS, radio_1_6::cdmaNewSmsInd, WAKE_PARTIAL},
- {RIL_UNSOL_RESPONSE_NEW_BROADCAST_SMS, radio_1_6::newBroadcastSmsInd, WAKE_PARTIAL},
- {RIL_UNSOL_CDMA_RUIM_SMS_STORAGE_FULL, radio_1_6::cdmaRuimSmsStorageFullInd, WAKE_PARTIAL},
- {RIL_UNSOL_RESTRICTED_STATE_CHANGED, radio_1_6::restrictedStateChangedInd, WAKE_PARTIAL},
- {RIL_UNSOL_ENTER_EMERGENCY_CALLBACK_MODE, radio_1_6::enterEmergencyCallbackModeInd, WAKE_PARTIAL},
- {RIL_UNSOL_CDMA_CALL_WAITING, radio_1_6::cdmaCallWaitingInd, WAKE_PARTIAL},
- {RIL_UNSOL_CDMA_OTA_PROVISION_STATUS, radio_1_6::cdmaOtaProvisionStatusInd, WAKE_PARTIAL},
- {RIL_UNSOL_CDMA_INFO_REC, radio_1_6::cdmaInfoRecInd, WAKE_PARTIAL},
- {RIL_UNSOL_OEM_HOOK_RAW, radio_1_6::oemHookRawInd, WAKE_PARTIAL},
- {RIL_UNSOL_RINGBACK_TONE, radio_1_6::indicateRingbackToneInd, WAKE_PARTIAL},
- {RIL_UNSOL_RESEND_INCALL_MUTE, radio_1_6::resendIncallMuteInd, WAKE_PARTIAL},
- {RIL_UNSOL_CDMA_SUBSCRIPTION_SOURCE_CHANGED, radio_1_6::cdmaSubscriptionSourceChangedInd, WAKE_PARTIAL},
- {RIL_UNSOL_CDMA_PRL_CHANGED, radio_1_6::cdmaPrlChangedInd, WAKE_PARTIAL},
- {RIL_UNSOL_EXIT_EMERGENCY_CALLBACK_MODE, radio_1_6::exitEmergencyCallbackModeInd, WAKE_PARTIAL},
- {RIL_UNSOL_RIL_CONNECTED, radio_1_6::rilConnectedInd, WAKE_PARTIAL},
- {RIL_UNSOL_VOICE_RADIO_TECH_CHANGED, radio_1_6::voiceRadioTechChangedInd, WAKE_PARTIAL},
- {RIL_UNSOL_CELL_INFO_LIST, radio_1_6::cellInfoListInd, WAKE_PARTIAL},
- {RIL_UNSOL_RESPONSE_IMS_NETWORK_STATE_CHANGED, radio_1_6::imsNetworkStateChangedInd, WAKE_PARTIAL},
- {RIL_UNSOL_UICC_SUBSCRIPTION_STATUS_CHANGED, radio_1_6::subscriptionStatusChangedInd, WAKE_PARTIAL},
- {RIL_UNSOL_SRVCC_STATE_NOTIFY, radio_1_6::srvccStateNotifyInd, WAKE_PARTIAL},
- {RIL_UNSOL_HARDWARE_CONFIG_CHANGED, radio_1_6::hardwareConfigChangedInd, WAKE_PARTIAL},
- {RIL_UNSOL_DC_RT_INFO_CHANGED, NULL, WAKE_PARTIAL},
- {RIL_UNSOL_RADIO_CAPABILITY, radio_1_6::radioCapabilityIndicationInd, WAKE_PARTIAL},
- {RIL_UNSOL_ON_SS, radio_1_6::onSupplementaryServiceIndicationInd, WAKE_PARTIAL},
- {RIL_UNSOL_STK_CC_ALPHA_NOTIFY, radio_1_6::stkCallControlAlphaNotifyInd, WAKE_PARTIAL},
- {RIL_UNSOL_LCEDATA_RECV, radio_1_6::lceDataInd, WAKE_PARTIAL},
- {RIL_UNSOL_PCO_DATA, radio_1_6::pcoDataInd, WAKE_PARTIAL},
- {RIL_UNSOL_MODEM_RESTART, radio_1_6::modemResetInd, WAKE_PARTIAL},
- {RIL_UNSOL_CARRIER_INFO_IMSI_ENCRYPTION, radio_1_6::carrierInfoForImsiEncryption, WAKE_PARTIAL},
- {RIL_UNSOL_NETWORK_SCAN_RESULT, radio_1_6::networkScanResultInd, WAKE_PARTIAL},
- {RIL_UNSOL_KEEPALIVE_STATUS, radio_1_6::keepaliveStatusInd, WAKE_PARTIAL},
- {RIL_UNSOL_PHYSICAL_CHANNEL_CONFIGS, radio_1_6::reportPhysicalChannelConfigs, WAKE_PARTIAL},
diff --git a/guest/hals/ril/reference-libril/sap_service.h b/guest/hals/ril/reference-libril/sap_service.h
deleted file mode 100644
index cb5ae1047..000000000
--- a/guest/hals/ril/reference-libril/sap_service.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef SAP_SERVICE_H
-#define SAP_SERVICE_H
-
-#include <telephony/ril.h>
-#include <ril_internal.h>
-#include <RilSapSocket.h>
-#include <hardware/ril/librilutils/proto/sap-api.pb.h>
-
-namespace sap {
-
-void registerService(const RIL_RadioFunctions *callbacks);
-void processResponse(MsgHeader *rsp, RilSapSocket *sapSocket);
-void processUnsolResponse(MsgHeader *rsp, RilSapSocket *sapSocket);
-
-} // namespace android
-
-#endif // RIL_SERVICE_H
diff --git a/guest/hals/ril/reference-ril/Android.bp b/guest/hals/ril/reference-ril/Android.bp
deleted file mode 100644
index de01ae131..000000000
--- a/guest/hals/ril/reference-ril/Android.bp
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package {
- default_applicable_licenses: [
- "device_google_cuttlefish_guest_hals_ril_reference-ril_license",
- ],
-}
-
-// Added automatically by a large-scale-change
-// See: http://go/android-license-faq
-license {
- name: "device_google_cuttlefish_guest_hals_ril_reference-ril_license",
- visibility: [":__subpackages__"],
- license_kinds: [
- "SPDX-license-identifier-Apache-2.0",
- ],
- license_text: [
- "NOTICE",
- ],
-}
-
-cc_library {
- name: "libcuttlefish-ril-2",
- vendor: true,
- cflags: [
- "-D_GNU_SOURCE",
- "-DCUTTLEFISH_ENABLE",
- "-DRIL_SHLIB",
- "-Wall",
- "-Wextra",
- "-Wno-unused-variable",
- "-Wno-unused-function",
- "-Werror",
- ],
- srcs: [
- "atchannel.c",
- "at_tok.c",
- "base64util.cpp",
- "misc.c",
- "reference-ril.c",
- ],
- include_dirs: [
- "device/google/cuttlefish",
- ],
- shared_libs: [
- "libbase",
- "libcutils",
- "libcuttlefish_fs",
- "libcuttlefish_utils",
- "liblog",
- "librilutils",
- "libril-modem-lib",
- "libutils",
- ],
-}
diff --git a/guest/hals/ril/reference-ril/MODULE_LICENSE_APACHE2 b/guest/hals/ril/reference-ril/MODULE_LICENSE_APACHE2
deleted file mode 100644
index e69de29bb..000000000
--- a/guest/hals/ril/reference-ril/MODULE_LICENSE_APACHE2
+++ /dev/null
diff --git a/guest/hals/ril/reference-ril/NOTICE b/guest/hals/ril/reference-ril/NOTICE
deleted file mode 100644
index c5b1efa7a..000000000
--- a/guest/hals/ril/reference-ril/NOTICE
+++ /dev/null
@@ -1,190 +0,0 @@
-
- Copyright (c) 2005-2008, 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.
-
- 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.
-
-
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
diff --git a/guest/hals/ril/reference-ril/OWNERS b/guest/hals/ril/reference-ril/OWNERS
deleted file mode 100644
index 98dba3e41..000000000
--- a/guest/hals/ril/reference-ril/OWNERS
+++ /dev/null
@@ -1,9 +0,0 @@
-amitmahajan@google.com
-jackyu@google.com
-rgreenwalt@google.com
-fionaxu@google.com
-jminjie@google.com
-mpq@google.com
-shuoq@google.com
-refuhoo@google.com
-bohu@google.com
diff --git a/guest/hals/ril/reference-ril/at_tok.c b/guest/hals/ril/reference-ril/at_tok.c
deleted file mode 100644
index 7dec7d14f..000000000
--- a/guest/hals/ril/reference-ril/at_tok.c
+++ /dev/null
@@ -1,190 +0,0 @@
-/* //device/system/reference-ril/at_tok.c
-**
-** Copyright 2006, 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 "at_tok.h"
-#include <string.h>
-#include <ctype.h>
-#include <stdlib.h>
-
-/**
- * Starts tokenizing an AT response string
- * returns -1 if this is not a valid response string, 0 on success.
- * updates *p_cur with current position
- */
-int at_tok_start(char **p_cur)
-{
- if (*p_cur == NULL) {
- return -1;
- }
-
- // skip prefix
- // consume "^[^:]:"
-
- *p_cur = strchr(*p_cur, ':');
-
- if (*p_cur == NULL) {
- return -1;
- }
-
- (*p_cur)++;
-
- return 0;
-}
-
-static void skipWhiteSpace(char **p_cur)
-{
- if (*p_cur == NULL) return;
-
- while (**p_cur != '\0' && isspace(**p_cur)) {
- (*p_cur)++;
- }
-}
-
-void skipNextComma(char **p_cur)
-{
- if (*p_cur == NULL) return;
-
- while (**p_cur != '\0' && **p_cur != ',') {
- (*p_cur)++;
- }
-
- if (**p_cur == ',') {
- (*p_cur)++;
- }
-}
-
-static char * nextTok(char **p_cur)
-{
- char *ret = NULL;
-
- skipWhiteSpace(p_cur);
-
- if (*p_cur == NULL) {
- ret = NULL;
- } else if (**p_cur == '"') {
- (*p_cur)++;
- ret = strsep(p_cur, "\"");
- skipNextComma(p_cur);
- } else {
- ret = strsep(p_cur, ",");
- }
-
- return ret;
-}
-
-
-/**
- * Parses the next integer in the AT response line and places it in *p_out
- * returns 0 on success and -1 on fail
- * updates *p_cur
- * "base" is the same as the base param in strtol
- */
-
-static int at_tok_nextint_base(char **p_cur, int *p_out, int base, int uns)
-{
- char *ret;
-
- if (*p_cur == NULL) {
- return -1;
- }
-
- ret = nextTok(p_cur);
-
- if (ret == NULL) {
- return -1;
- } else {
- long l;
- char *end;
-
- if (uns)
- l = strtoul(ret, &end, base);
- else
- l = strtol(ret, &end, base);
-
- *p_out = (int)l;
-
- if (end == ret) {
- return -1;
- }
- }
-
- return 0;
-}
-
-/**
- * Parses the next base 10 integer in the AT response line
- * and places it in *p_out
- * returns 0 on success and -1 on fail
- * updates *p_cur
- */
-int at_tok_nextint(char **p_cur, int *p_out)
-{
- return at_tok_nextint_base(p_cur, p_out, 10, 0);
-}
-
-/**
- * Parses the next base 16 integer in the AT response line
- * and places it in *p_out
- * returns 0 on success and -1 on fail
- * updates *p_cur
- */
-int at_tok_nexthexint(char **p_cur, int *p_out)
-{
- return at_tok_nextint_base(p_cur, p_out, 16, 1);
-}
-
-int at_tok_nextbool(char **p_cur, char *p_out)
-{
- int ret;
- int result;
-
- ret = at_tok_nextint(p_cur, &result);
-
- if (ret < 0) {
- return -1;
- }
-
- // booleans should be 0 or 1
- if (!(result == 0 || result == 1)) {
- return -1;
- }
-
- if (p_out != NULL) {
- *p_out = (char)result;
- }
-
- return ret;
-}
-
-int at_tok_nextstr(char **p_cur, char **p_out)
-{
- if (*p_cur == NULL) {
- return -1;
- }
-
- *p_out = nextTok(p_cur);
-
- return 0;
-}
-
-/** returns 1 on "has more tokens" and 0 if no */
-int at_tok_hasmore(char **p_cur)
-{
- return ! (*p_cur == NULL || **p_cur == '\0');
-}
-
-
diff --git a/guest/hals/ril/reference-ril/at_tok.h b/guest/hals/ril/reference-ril/at_tok.h
deleted file mode 100644
index b6a0aade3..000000000
--- a/guest/hals/ril/reference-ril/at_tok.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/* //device/system/reference-ril/at_tok.h
-**
-** Copyright 2006, 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 AT_TOK_H
-#define AT_TOK_H 1
-
-int at_tok_start(char **p_cur);
-int at_tok_nextint(char **p_cur, int *p_out);
-int at_tok_nexthexint(char **p_cur, int *p_out);
-
-int at_tok_nextbool(char **p_cur, char *p_out);
-int at_tok_nextstr(char **p_cur, char **out);
-
-int at_tok_hasmore(char **p_cur);
-
-void skipNextComma(char **p_cur);
-
-#endif /*AT_TOK_H */
diff --git a/guest/hals/ril/reference-ril/atchannel.c b/guest/hals/ril/reference-ril/atchannel.c
deleted file mode 100644
index 6ea051fff..000000000
--- a/guest/hals/ril/reference-ril/atchannel.c
+++ /dev/null
@@ -1,972 +0,0 @@
-/* //device/system/reference-ril/atchannel.c
-**
-** Copyright 2006, 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 "atchannel.h"
-#include "at_tok.h"
-
-#include <stdio.h>
-#include <string.h>
-#include <pthread.h>
-#include <ctype.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <sys/time.h>
-#include <time.h>
-#include <unistd.h>
-
-#define LOG_NDEBUG 0
-#define LOG_TAG "AT"
-#include <utils/Log.h>
-
-#include "misc.h"
-
-
-#define NUM_ELEMS(x) (sizeof(x)/sizeof((x)[0]))
-
-#define MAX_AT_RESPONSE (8 * 1024)
-#define HANDSHAKE_RETRY_COUNT 8
-#define HANDSHAKE_TIMEOUT_MSEC 250
-
-static pthread_t s_tid_reader;
-static int s_fd = -1; /* fd of the AT channel */
-static ATUnsolHandler s_unsolHandler;
-
-/* for input buffering */
-
-static char s_ATBuffer[MAX_AT_RESPONSE+1];
-static char *s_ATBufferCur = s_ATBuffer;
-
-#if AT_DEBUG
-void AT_DUMP(const char* prefix __unused, const char* buff, int len)
-{
- if (len < 0)
- len = strlen(buff);
- RLOGD("%.*s", len, buff);
-}
-#endif
-
-/*
- * There is one reader thread |s_tid_reader| and potentially multiple writer
- * threads. |s_commandmutex| and |s_commandcond| are used to maintain the
- * condition that the writer thread will not read from |sp_response| until the
- * reader thread has signaled itself is finished, etc. |s_writeMutex| is used to
- * prevent multiple writer threads from calling at_send_command_full_nolock
- * function at the same time.
- */
-
-static pthread_mutex_t s_commandmutex = PTHREAD_MUTEX_INITIALIZER;
-static pthread_cond_t s_commandcond = PTHREAD_COND_INITIALIZER;
-static pthread_mutex_t s_writeMutex = PTHREAD_MUTEX_INITIALIZER;
-
-static ATCommandType s_type;
-static const char *s_responsePrefix = NULL;
-static const char *s_smsPDU = NULL;
-static ATResponse *sp_response = NULL;
-
-static void (*s_onTimeout)(void) = NULL;
-static void (*s_onReaderClosed)(void) = NULL;
-static int s_readerClosed;
-
-static void onReaderClosed();
-static int writeCtrlZ (const char *s);
-static int writeline (const char *s);
-
-#define NS_PER_S 1000000000
-static void setTimespecRelative(struct timespec *p_ts, long long msec)
-{
- struct timeval tv;
-
- gettimeofday(&tv, (struct timezone *) NULL);
-
- p_ts->tv_sec = tv.tv_sec + (msec / 1000);
- p_ts->tv_nsec = (tv.tv_usec + (msec % 1000) * 1000L ) * 1000L;
- /* assuming tv.tv_usec < 10^6 */
- if (p_ts->tv_nsec >= NS_PER_S) {
- p_ts->tv_sec++;
- p_ts->tv_nsec -= NS_PER_S;
- }
-}
-
-static void sleepMsec(long long msec)
-{
- struct timespec ts;
- int err;
-
- ts.tv_sec = (msec / 1000);
- ts.tv_nsec = (msec % 1000) * 1000 * 1000;
-
- do {
- err = nanosleep (&ts, &ts);
- } while (err < 0 && errno == EINTR);
-}
-
-
-
-/** add an intermediate response to sp_response*/
-static void addIntermediate(const char *line)
-{
- ATLine *p_new;
-
- p_new = (ATLine *) malloc(sizeof(ATLine));
-
- p_new->line = strdup(line);
-
- /* note: this adds to the head of the list, so the list
- will be in reverse order of lines received. the order is flipped
- again before passing on to the command issuer */
- p_new->p_next = sp_response->p_intermediates;
- sp_response->p_intermediates = p_new;
-}
-
-
-/**
- * returns 1 if line is a final response indicating error
- * See 27.007 annex B
- * WARNING: NO CARRIER and others are sometimes unsolicited
- */
-static const char * s_finalResponsesError[] = {
- "ERROR",
- "+CMS ERROR:",
- "+CME ERROR:",
- "NO CARRIER", /* sometimes! */
- "NO ANSWER",
- "NO DIALTONE",
-};
-static int isFinalResponseError(const char *line)
-{
- size_t i;
-
- for (i = 0 ; i < NUM_ELEMS(s_finalResponsesError) ; i++) {
- if (strStartsWith(line, s_finalResponsesError[i])) {
- return 1;
- }
- }
-
- return 0;
-}
-
-/**
- * returns 1 if line is a final response indicating success
- * See 27.007 annex B
- * WARNING: NO CARRIER and others are sometimes unsolicited
- */
-static const char * s_finalResponsesSuccess[] = {
- "OK",
- "CONNECT" /* some stacks start up data on another channel */
-};
-static int isFinalResponseSuccess(const char *line)
-{
- size_t i;
-
- for (i = 0 ; i < NUM_ELEMS(s_finalResponsesSuccess) ; i++) {
- if (strStartsWith(line, s_finalResponsesSuccess[i])) {
- return 1;
- }
- }
-
- return 0;
-}
-
-/**
- * returns 1 if line is a final response, either error or success
- * See 27.007 annex B
- * WARNING: NO CARRIER and others are sometimes unsolicited
- */
-static int isFinalResponse(const char *line)
-{
- return isFinalResponseSuccess(line) || isFinalResponseError(line);
-}
-
-
-/**
- * returns 1 if line is the first line in (what will be) a two-line
- * SMS unsolicited response
- */
-static const char * s_smsUnsoliciteds[] = {
- "+CMT:",
- "+CDS:",
- "+CBM:"
-};
-static int isSMSUnsolicited(const char *line)
-{
- size_t i;
-
- for (i = 0 ; i < NUM_ELEMS(s_smsUnsoliciteds) ; i++) {
- if (strStartsWith(line, s_smsUnsoliciteds[i])) {
- return 1;
- }
- }
-
- return 0;
-}
-
-
-/** assumes s_commandmutex is held */
-static void handleFinalResponse(const char *line)
-{
- sp_response->finalResponse = strdup(line);
-
- pthread_cond_signal(&s_commandcond);
-}
-
-static void handleUnsolicited(const char *line)
-{
- if (s_unsolHandler != NULL) {
- s_unsolHandler(line, NULL);
- }
-}
-
-static void processLine(const char *line)
-{
- pthread_mutex_lock(&s_commandmutex);
-
- if (sp_response == NULL) {
- /* no command pending */
- handleUnsolicited(line);
- } else if (isFinalResponseSuccess(line)) {
- sp_response->success = 1;
- handleFinalResponse(line);
- } else if (isFinalResponseError(line)) {
- sp_response->success = 0;
- handleFinalResponse(line);
- } else if (s_smsPDU != NULL && 0 == strcmp(line, "> ")) {
- // See eg. TS 27.005 4.3
- // Commands like AT+CMGS have a "> " prompt
- writeCtrlZ(s_smsPDU);
- s_smsPDU = NULL;
- } else switch (s_type) {
- case NO_RESULT:
- handleUnsolicited(line);
- break;
- case NUMERIC:
- if (sp_response->p_intermediates == NULL
- && isdigit(line[0])
- ) {
- addIntermediate(line);
- } else {
- /* either we already have an intermediate response or
- the line doesn't begin with a digit */
- handleUnsolicited(line);
- }
- break;
- case SINGLELINE:
- if (sp_response->p_intermediates == NULL
- && strStartsWith (line, s_responsePrefix)
- ) {
- addIntermediate(line);
- } else {
- /* we already have an intermediate response */
- handleUnsolicited(line);
- }
- break;
- case MULTILINE:
- if (strStartsWith (line, s_responsePrefix)) {
- addIntermediate(line);
- } else {
- handleUnsolicited(line);
- }
- break;
-
- default: /* this should never be reached */
- RLOGE("Unsupported AT command type %d\n", s_type);
- handleUnsolicited(line);
- break;
- }
-
- pthread_mutex_unlock(&s_commandmutex);
-}
-
-
-/**
- * Returns a pointer to the end of the next line
- * special-cases the "> " SMS prompt
- *
- * returns NULL if there is no complete line
- */
-static char * findNextEOL(char *cur)
-{
- if (cur[0] == '>' && cur[1] == ' ' && cur[2] == '\0') {
- /* SMS prompt character...not \r terminated */
- return cur+2;
- }
-
- // Find next newline
- while (*cur != '\0' && *cur != '\r' && *cur != '\n') cur++;
-
- return *cur == '\0' ? NULL : cur;
-}
-
-
-/**
- * Reads a line from the AT channel, returns NULL on timeout.
- * Assumes it has exclusive read access to the FD
- *
- * This line is valid only until the next call to readline
- *
- * This function exists because as of writing, android libc does not
- * have buffered stdio.
- */
-
-static const char *readline()
-{
- ssize_t count;
-
- char *p_read = NULL;
- char *p_eol = NULL;
- char *ret;
-
- /* this is a little odd. I use *s_ATBufferCur == 0 to
- * mean "buffer consumed completely". If it points to a character, than
- * the buffer continues until a \0
- */
- if (*s_ATBufferCur == '\0') {
- /* empty buffer */
- s_ATBufferCur = s_ATBuffer;
- *s_ATBufferCur = '\0';
- p_read = s_ATBuffer;
- } else { /* *s_ATBufferCur != '\0' */
- /* there's data in the buffer from the last read */
-
- // skip over leading newlines
- while (*s_ATBufferCur == '\r' || *s_ATBufferCur == '\n')
- s_ATBufferCur++;
-
- p_eol = findNextEOL(s_ATBufferCur);
-
- if (p_eol == NULL) {
- /* a partial line. move it up and prepare to read more */
- size_t len;
-
- len = strlen(s_ATBufferCur);
-
- memmove(s_ATBuffer, s_ATBufferCur, len + 1);
- p_read = s_ATBuffer + len;
- s_ATBufferCur = s_ATBuffer;
- }
- /* Otherwise, (p_eol !- NULL) there is a complete line */
- /* that will be returned the while () loop below */
- }
-
- while (p_eol == NULL) {
- if (0 == MAX_AT_RESPONSE - (p_read - s_ATBuffer)) {
- RLOGE("ERROR: Input line exceeded buffer\n");
- /* ditch buffer and start over again */
- s_ATBufferCur = s_ATBuffer;
- *s_ATBufferCur = '\0';
- p_read = s_ATBuffer;
- }
-
- do {
- count = read(s_fd, p_read,
- MAX_AT_RESPONSE - (p_read - s_ATBuffer));
- } while (count < 0 && errno == EINTR);
-
- if (count > 0) {
- AT_DUMP( "<< ", p_read, count );
-
- p_read[count] = '\0';
-
- // skip over leading newlines
- while (*s_ATBufferCur == '\r' || *s_ATBufferCur == '\n')
- s_ATBufferCur++;
-
- p_eol = findNextEOL(s_ATBufferCur);
- p_read += count;
- } else if (count <= 0) {
- /* read error encountered or EOF reached */
- if(count == 0) {
- RLOGD("atchannel: EOF reached");
- } else {
- RLOGD("atchannel: read error %s", strerror(errno));
- }
- return NULL;
- }
- }
-
- /* a full line in the buffer. Place a \0 over the \r and return */
-
- ret = s_ATBufferCur;
- *p_eol = '\0';
- s_ATBufferCur = p_eol + 1; /* this will always be <= p_read, */
- /* and there will be a \0 at *p_read */
-
- RLOGD("AT< %s\n", ret);
- return ret;
-}
-
-
-static void onReaderClosed()
-{
- if (s_onReaderClosed != NULL && s_readerClosed == 0) {
-
- pthread_mutex_lock(&s_commandmutex);
-
- s_readerClosed = 1;
-
- pthread_cond_signal(&s_commandcond);
-
- pthread_mutex_unlock(&s_commandmutex);
-
- s_onReaderClosed();
- }
-}
-
-
-static void *readerLoop(void *arg __unused)
-{
- for (;;) {
- const char * line;
-
- line = readline();
-
- if (line == NULL) {
- break;
- }
-
- if(isSMSUnsolicited(line)) {
- char *line1;
- const char *line2;
-
- // The scope of string returned by 'readline()' is valid only
- // till next call to 'readline()' hence making a copy of line
- // before calling readline again.
- line1 = strdup(line);
- line2 = readline();
-
- if (line2 == NULL) {
- free(line1);
- break;
- }
-
- if (s_unsolHandler != NULL) {
- s_unsolHandler (line1, line2);
- }
- free(line1);
- } else {
- processLine(line);
- }
- }
-
- onReaderClosed();
-
- return NULL;
-}
-
-/**
- * Sends string s to the radio with a \r appended.
- * Returns AT_ERROR_* on error, 0 on success
- *
- * This function exists because as of writing, android libc does not
- * have buffered stdio.
- */
-static int writeline (const char *s)
-{
- size_t cur = 0;
- size_t len = strlen(s);
- ssize_t written;
-
- if (s_fd < 0 || s_readerClosed > 0) {
- return AT_ERROR_CHANNEL_CLOSED;
- }
-
- RLOGD("AT> %s\n", s);
-
- AT_DUMP( ">> ", s, strlen(s) );
-
- /* the main string */
- while (cur < len) {
- do {
- written = write (s_fd, s + cur, len - cur);
- } while (written < 0 && errno == EINTR);
-
- if (written < 0) {
- return AT_ERROR_GENERIC;
- }
-
- cur += written;
- }
-
- /* the \r */
-
- do {
- written = write (s_fd, "\r" , 1);
- } while ((written < 0 && errno == EINTR) || (written == 0));
-
- if (written < 0) {
- return AT_ERROR_GENERIC;
- }
-
- return 0;
-}
-static int writeCtrlZ (const char *s)
-{
- size_t cur = 0;
- size_t len = strlen(s);
- ssize_t written;
-
- if (s_fd < 0 || s_readerClosed > 0) {
- return AT_ERROR_CHANNEL_CLOSED;
- }
-
- RLOGD("AT> %s^Z\n", s);
-
- AT_DUMP( ">* ", s, strlen(s) );
-
- /* the main string */
- while (cur < len) {
- do {
- written = write (s_fd, s + cur, len - cur);
- } while (written < 0 && errno == EINTR);
-
- if (written < 0) {
- return AT_ERROR_GENERIC;
- }
-
- cur += written;
- }
-
- /* the ^Z */
-
- do {
- written = write (s_fd, "\032" , 1);
- } while ((written < 0 && errno == EINTR) || (written == 0));
-
- if (written < 0) {
- return AT_ERROR_GENERIC;
- }
-
- return 0;
-}
-
-static void clearPendingCommand()
-{
- if (sp_response != NULL) {
- at_response_free(sp_response);
- }
-
- sp_response = NULL;
- s_responsePrefix = NULL;
- s_smsPDU = NULL;
-}
-
-
-/**
- * Starts AT handler on stream "fd'
- * returns 0 on success, -1 on error
- */
-int at_open(int fd, ATUnsolHandler h)
-{
- int ret;
- pthread_t tid;
- pthread_attr_t attr;
-
- s_fd = fd;
- s_unsolHandler = h;
- s_readerClosed = 0;
-
- s_responsePrefix = NULL;
- s_smsPDU = NULL;
- sp_response = NULL;
-
- pthread_attr_init (&attr);
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
-
- ret = pthread_create(&s_tid_reader, &attr, readerLoop, &attr);
-
- if (ret < 0) {
- perror ("pthread_create");
- return -1;
- }
-
-
- return 0;
-}
-
-/* FIXME is it ok to call this from the reader and the command thread? */
-void at_close()
-{
- if (s_fd >= 0) {
- close(s_fd);
- }
- s_fd = -1;
-
- pthread_mutex_lock(&s_commandmutex);
-
- s_readerClosed = 1;
-
- pthread_cond_signal(&s_commandcond);
-
- pthread_mutex_unlock(&s_commandmutex);
-
- /* the reader thread should eventually die */
-}
-
-static ATResponse * at_response_new()
-{
- return (ATResponse *) calloc(1, sizeof(ATResponse));
-}
-
-void at_response_free(ATResponse *p_response)
-{
- ATLine *p_line;
-
- if (p_response == NULL) return;
-
- p_line = p_response->p_intermediates;
-
- while (p_line != NULL) {
- ATLine *p_toFree;
-
- p_toFree = p_line;
- p_line = p_line->p_next;
-
- free(p_toFree->line);
- free(p_toFree);
- }
-
- free (p_response->finalResponse);
- free (p_response);
-}
-
-/**
- * The line reader places the intermediate responses in reverse order
- * here we flip them back
- */
-static void reverseIntermediates(ATResponse *p_response)
-{
- ATLine *pcur,*pnext;
-
- pcur = p_response->p_intermediates;
- p_response->p_intermediates = NULL;
-
- while (pcur != NULL) {
- pnext = pcur->p_next;
- pcur->p_next = p_response->p_intermediates;
- p_response->p_intermediates = pcur;
- pcur = pnext;
- }
-}
-
-/**
- * Internal send_command implementation
- * Doesn't lock or call the timeout callback
- *
- * timeoutMsec == 0 means infinite timeout
- */
-
-static int at_send_command_full_nolock (const char *command, ATCommandType type,
- const char *responsePrefix, const char *smspdu,
- long long timeoutMsec, ATResponse **pp_outResponse)
-{
- int err = 0;
- struct timespec ts;
-
- if(sp_response != NULL) {
- err = AT_ERROR_COMMAND_PENDING;
- goto error;
- }
-
- err = writeline (command);
-
- if (err < 0) {
- goto error;
- }
-
- s_type = type;
- s_responsePrefix = responsePrefix;
- s_smsPDU = smspdu;
- sp_response = at_response_new();
-
- if (timeoutMsec != 0) {
- setTimespecRelative(&ts, timeoutMsec);
- }
-
- while (sp_response->finalResponse == NULL && s_readerClosed == 0) {
- if (timeoutMsec != 0) {
- err = pthread_cond_timedwait(&s_commandcond, &s_commandmutex, &ts);
- } else {
- err = pthread_cond_wait(&s_commandcond, &s_commandmutex);
- }
-
- if (err == ETIMEDOUT) {
- err = AT_ERROR_TIMEOUT;
- goto error;
- }
- }
-
- if (pp_outResponse == NULL) {
- at_response_free(sp_response);
- } else {
- /* line reader stores intermediate responses in reverse order */
- reverseIntermediates(sp_response);
- *pp_outResponse = sp_response;
- }
-
- sp_response = NULL;
-
- if(s_readerClosed > 0) {
- err = AT_ERROR_CHANNEL_CLOSED;
- goto error;
- }
-
- err = 0;
-error:
- clearPendingCommand();
-
- return err;
-}
-
-/**
- * Internal send_command implementation
- *
- * timeoutMsec == 0 means infinite timeout
- */
-static int at_send_command_full (const char *command, ATCommandType type,
- const char *responsePrefix, const char *smspdu,
- long long timeoutMsec, ATResponse **pp_outResponse)
-{
- int err;
- bool inEmulator;
-
- if (0 != pthread_equal(s_tid_reader, pthread_self())) {
- /* cannot be called from reader thread */
- return AT_ERROR_INVALID_THREAD;
- }
-
- pthread_mutex_lock(&s_writeMutex);
- pthread_mutex_lock(&s_commandmutex);
-
- err = at_send_command_full_nolock(command, type,
- responsePrefix, smspdu,
- timeoutMsec, pp_outResponse);
-
- pthread_mutex_unlock(&s_commandmutex);
- pthread_mutex_unlock(&s_writeMutex);
-
-
- if (err == AT_ERROR_TIMEOUT && s_onTimeout != NULL) {
- s_onTimeout();
- }
-
- return err;
-}
-
-
-/**
- * Issue a single normal AT command with no intermediate response expected
- *
- * "command" should not include \r
- * pp_outResponse can be NULL
- *
- * if non-NULL, the resulting ATResponse * must be eventually freed with
- * at_response_free
- */
-int at_send_command (const char *command, ATResponse **pp_outResponse)
-{
- int err;
-
- err = at_send_command_full (command, NO_RESULT, NULL,
- NULL, 0, pp_outResponse);
-
- return err;
-}
-
-
-int at_send_command_singleline (const char *command,
- const char *responsePrefix,
- ATResponse **pp_outResponse)
-{
- int err;
-
- err = at_send_command_full (command, SINGLELINE, responsePrefix,
- NULL, 0, pp_outResponse);
-
- if (err == 0 && pp_outResponse != NULL
- && (*pp_outResponse)->success > 0
- && (*pp_outResponse)->p_intermediates == NULL
- ) {
- /* successful command must have an intermediate response */
- at_response_free(*pp_outResponse);
- *pp_outResponse = NULL;
- return AT_ERROR_INVALID_RESPONSE;
- }
-
- return err;
-}
-
-
-int at_send_command_numeric (const char *command,
- ATResponse **pp_outResponse)
-{
- int err;
-
- err = at_send_command_full (command, NUMERIC, NULL,
- NULL, 0, pp_outResponse);
-
- if (err == 0 && pp_outResponse != NULL
- && (*pp_outResponse)->success > 0
- && (*pp_outResponse)->p_intermediates == NULL
- ) {
- /* successful command must have an intermediate response */
- at_response_free(*pp_outResponse);
- *pp_outResponse = NULL;
- return AT_ERROR_INVALID_RESPONSE;
- }
-
- return err;
-}
-
-
-int at_send_command_sms (const char *command,
- const char *pdu,
- const char *responsePrefix,
- ATResponse **pp_outResponse)
-{
- int err;
-
- err = at_send_command_full (command, SINGLELINE, responsePrefix,
- pdu, 0, pp_outResponse);
-
- if (err == 0 && pp_outResponse != NULL
- && (*pp_outResponse)->success > 0
- && (*pp_outResponse)->p_intermediates == NULL
- ) {
- /* successful command must have an intermediate response */
- at_response_free(*pp_outResponse);
- *pp_outResponse = NULL;
- return AT_ERROR_INVALID_RESPONSE;
- }
-
- return err;
-}
-
-
-int at_send_command_multiline (const char *command,
- const char *responsePrefix,
- ATResponse **pp_outResponse)
-{
- int err;
-
- err = at_send_command_full (command, MULTILINE, responsePrefix,
- NULL, 0, pp_outResponse);
-
- return err;
-}
-
-
-/** This callback is invoked on the command thread */
-void at_set_on_timeout(void (*onTimeout)(void))
-{
- s_onTimeout = onTimeout;
-}
-
-/**
- * This callback is invoked on the reader thread (like ATUnsolHandler)
- * when the input stream closes before you call at_close
- * (not when you call at_close())
- * You should still call at_close()
- */
-
-void at_set_on_reader_closed(void (*onClose)(void))
-{
- s_onReaderClosed = onClose;
-}
-
-
-/**
- * Periodically issue an AT command and wait for a response.
- * Used to ensure channel has start up and is active
- */
-
-int at_handshake()
-{
- int i;
- int err = 0;
- bool inEmulator;
-
- if (0 != pthread_equal(s_tid_reader, pthread_self())) {
- /* cannot be called from reader thread */
- return AT_ERROR_INVALID_THREAD;
- }
- inEmulator = isInEmulator();
- if (inEmulator) {
- pthread_mutex_lock(&s_writeMutex);
- }
- pthread_mutex_lock(&s_commandmutex);
-
- for (i = 0 ; i < HANDSHAKE_RETRY_COUNT ; i++) {
- /* some stacks start with verbose off */
- err = at_send_command_full_nolock ("ATE0Q0V1", NO_RESULT,
- NULL, NULL, HANDSHAKE_TIMEOUT_MSEC, NULL);
-
- if (err == 0) {
- break;
- }
- }
-
- if (err == 0) {
- /* pause for a bit to let the input buffer drain any unmatched OK's
- (they will appear as extraneous unsolicited responses) */
-
- sleepMsec(HANDSHAKE_TIMEOUT_MSEC);
- }
-
- pthread_mutex_unlock(&s_commandmutex);
- if (inEmulator) {
- pthread_mutex_unlock(&s_writeMutex);
- }
-
- return err;
-}
-
-/**
- * Returns error code from response
- * Assumes AT+CMEE=1 (numeric) mode
- */
-AT_CME_Error at_get_cme_error(const ATResponse *p_response)
-{
- int ret;
- int err;
- char *p_cur;
-
- if (p_response->success > 0) {
- return CME_SUCCESS;
- }
-
- if (p_response->finalResponse == NULL
- || !strStartsWith(p_response->finalResponse, "+CME ERROR:")
- ) {
- return CME_ERROR_NON_CME;
- }
-
- p_cur = p_response->finalResponse;
- err = at_tok_start(&p_cur);
-
- if (err < 0) {
- return CME_ERROR_NON_CME;
- }
-
- err = at_tok_nextint(&p_cur, &ret);
-
- if (err < 0) {
- return CME_ERROR_NON_CME;
- }
-
- return (AT_CME_Error) ret;
-}
-
diff --git a/guest/hals/ril/reference-ril/atchannel.h b/guest/hals/ril/reference-ril/atchannel.h
deleted file mode 100644
index 928291539..000000000
--- a/guest/hals/ril/reference-ril/atchannel.h
+++ /dev/null
@@ -1,124 +0,0 @@
-/* //device/system/reference-ril/atchannel.h
-**
-** Copyright 2006, 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 ATCHANNEL_H
-#define ATCHANNEL_H 1
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* define AT_DEBUG to send AT traffic to /tmp/radio-at.log" */
-#define AT_DEBUG 0
-
-#if AT_DEBUG
-extern void AT_DUMP(const char* prefix, const char* buff, int len);
-#else
-#define AT_DUMP(prefix,buff,len) do{}while(0)
-#endif
-
-#define AT_ERROR_GENERIC (-1)
-#define AT_ERROR_COMMAND_PENDING (-2)
-#define AT_ERROR_CHANNEL_CLOSED (-3)
-#define AT_ERROR_TIMEOUT (-4)
-#define AT_ERROR_INVALID_THREAD (-5) /* AT commands may not be issued from
- reader thread (or unsolicited response
- callback */
-#define AT_ERROR_INVALID_RESPONSE (-6) /* eg an at_send_command_singleline that
- did not get back an intermediate
- response */
-
-
-typedef enum {
- NO_RESULT, /* no intermediate response expected */
- NUMERIC, /* a single intermediate response starting with a 0-9 */
- SINGLELINE, /* a single intermediate response starting with a prefix */
- MULTILINE /* multiple line intermediate response
- starting with a prefix */
-} ATCommandType;
-
-/** a singly-lined list of intermediate responses */
-typedef struct ATLine {
- struct ATLine *p_next;
- char *line;
-} ATLine;
-
-/** Free this with at_response_free() */
-typedef struct {
- int success; /* true if final response indicates
- success (eg "OK") */
- char *finalResponse; /* eg OK, ERROR */
- ATLine *p_intermediates; /* any intermediate responses */
-} ATResponse;
-
-/**
- * a user-provided unsolicited response handler function
- * this will be called from the reader thread, so do not block
- * "s" is the line, and "sms_pdu" is either NULL or the PDU response
- * for multi-line TS 27.005 SMS PDU responses (eg +CMT:)
- */
-typedef void (*ATUnsolHandler)(const char *s, const char *sms_pdu);
-
-int at_open(int fd, ATUnsolHandler h);
-void at_close();
-
-/* This callback is invoked on the command thread.
- You should reset or handshake here to avoid getting out of sync */
-void at_set_on_timeout(void (*onTimeout)(void));
-/* This callback is invoked on the reader thread (like ATUnsolHandler)
- when the input stream closes before you call at_close
- (not when you call at_close())
- You should still call at_close()
- It may also be invoked immediately from the current thread if the read
- channel is already closed */
-void at_set_on_reader_closed(void (*onClose)(void));
-
-int at_send_command_singleline (const char *command,
- const char *responsePrefix,
- ATResponse **pp_outResponse);
-
-int at_send_command_numeric (const char *command,
- ATResponse **pp_outResponse);
-
-int at_send_command_multiline (const char *command,
- const char *responsePrefix,
- ATResponse **pp_outResponse);
-
-
-int at_handshake();
-
-int at_send_command (const char *command, ATResponse **pp_outResponse);
-
-int at_send_command_sms (const char *command, const char *pdu,
- const char *responsePrefix,
- ATResponse **pp_outResponse);
-
-void at_response_free(ATResponse *p_response);
-
-typedef enum {
- CME_ERROR_NON_CME = -1,
- CME_SUCCESS = 0,
- CME_SIM_NOT_INSERTED = 10
-} AT_CME_Error;
-
-AT_CME_Error at_get_cme_error(const ATResponse *p_response);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /*ATCHANNEL_H*/
diff --git a/guest/hals/ril/reference-ril/base64util.cpp b/guest/hals/ril/reference-ril/base64util.cpp
deleted file mode 100644
index c75e80e29..000000000
--- a/guest/hals/ril/reference-ril/base64util.cpp
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
-**
-** Copyright 2020, 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 "base64util.h"
-
-#include <vector>
-
-#include "common/libs/utils/base64.h"
-
-extern "C" {
-
-int base64_decode(const char *base64input, unsigned char *bindata) {
- if (!base64input || !bindata) {
- return 0;
- }
-
- std::vector<uint8_t> output;
- std::string input(base64input);
- bool success = cuttlefish::DecodeBase64(input, &output);
- if (!success) {
- return 0;
- }
- memcpy(bindata, reinterpret_cast<unsigned char *>(output.data()),
- output.size());
- return output.size();
-}
-
-char *base64_encode(const unsigned char *bindata, char *base64output,
- int binlength) {
- if (!base64output || !bindata || binlength <= 0) {
- return NULL;
- }
-
- std::string output;
- bool success = cuttlefish::EncodeBase64(
- bindata, static_cast<size_t>(binlength), &output);
-
- if (!success) {
- return NULL;
- }
-
- memcpy(base64output, output.data(), output.size());
- return base64output;
-}
-}
diff --git a/guest/hals/ril/reference-ril/base64util.h b/guest/hals/ril/reference-ril/base64util.h
deleted file mode 100644
index a448fe0c1..000000000
--- a/guest/hals/ril/reference-ril/base64util.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
-**
-** Copyright 2020, 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 __cplusplus
-extern "C" {
-#endif
-
-/** decode base64, returns the encoded output */
-int base64_decode(const char *base64, unsigned char *bindata);
-/** encode base64, returns the number of bytes decoded */
-char *base64_encode(const unsigned char *bindata, char *base64, int binlength);
-#ifdef __cplusplus
-}
-#endif
diff --git a/guest/hals/ril/reference-ril/misc.c b/guest/hals/ril/reference-ril/misc.c
deleted file mode 100644
index 25fdc2f60..000000000
--- a/guest/hals/ril/reference-ril/misc.c
+++ /dev/null
@@ -1,50 +0,0 @@
-/* //device/system/reference-ril/misc.c
-**
-** Copyright 2006, 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 <sys/system_properties.h>
-
-#include <fcntl.h>
-#include "misc.h"
-/** returns 1 if line starts with prefix, 0 if it does not */
-int strStartsWith(const char *line, const char *prefix)
-{
- for ( ; *line != '\0' && *prefix != '\0' ; line++, prefix++) {
- if (*line != *prefix) {
- return 0;
- }
- }
-
- return *prefix == '\0';
-}
-
-// Returns true iff running this process in an emulator VM
-bool isInEmulator(void) {
- static int inQemu = -1;
- if (inQemu < 0) {
- char propValue[PROP_VALUE_MAX];
- inQemu = (__system_property_get("ro.boot.qemu", propValue) != 0);
- }
- return inQemu == 1;
-}
-
-int qemu_open_modem_port() {
- char propValue[PROP_VALUE_MAX];
- if (__system_property_get("vendor.qemu.vport.modem", propValue) <= 0) {
- return -1;
- }
- int fd = open(propValue, O_RDWR);
- return fd;
-}
diff --git a/guest/hals/ril/reference-ril/misc.h b/guest/hals/ril/reference-ril/misc.h
deleted file mode 100644
index ed62c69e7..000000000
--- a/guest/hals/ril/reference-ril/misc.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/* //device/system/reference-ril/misc.h
-**
-** Copyright 2006, 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 <stdbool.h>
-
-/** returns 1 if line starts with prefix, 0 if it does not */
-int strStartsWith(const char *line, const char *prefix);
-/** Returns true iff running this process in an emulator VM */
-bool isInEmulator(void);
-/** open the modem port inside emulator VM; -1 if fails */
-int qemu_open_modem_port();
diff --git a/guest/hals/ril/reference-ril/reference-ril.c b/guest/hals/ril/reference-ril/reference-ril.c
deleted file mode 100644
index 784069f5b..000000000
--- a/guest/hals/ril/reference-ril/reference-ril.c
+++ /dev/null
@@ -1,6257 +0,0 @@
-/* //device/system/reference-ril/reference-ril.c
-**
-** Copyright 2006, 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 <telephony/ril_cdma_sms.h>
-#include <telephony/librilutils.h>
-#include <stdio.h>
-#include <assert.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <sys/cdefs.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <inttypes.h>
-#include <fcntl.h>
-#include <pthread.h>
-#include <alloca.h>
-#include "atchannel.h"
-#include "at_tok.h"
-#include "base64util.h"
-#include "misc.h"
-#include <getopt.h>
-#include <sys/socket.h>
-#include <cutils/properties.h>
-#include <cutils/sockets.h>
-#include <termios.h>
-#include <sys/wait.h>
-#include <stdbool.h>
-#include <net/if.h>
-#include <netinet/in.h>
-#include <linux/vm_sockets.h>
-#include <arpa/inet.h>
-
-#include "guest/hals/ril/reference-libril/ril.h"
-#define LOG_TAG "RIL"
-#include <utils/Log.h>
-
-static void *noopRemoveWarning( void *a ) { return a; }
-#define RIL_UNUSED_PARM(a) noopRemoveWarning((void *)&(a));
-
-#define MAX_AT_RESPONSE 0x1000
-
-#define MAX_PDP 3
-
-/* pathname returned from RIL_REQUEST_SETUP_DATA_CALL / RIL_REQUEST_SETUP_DEFAULT_PDP */
-// This is used if Wifi is not supported, plain old eth0
-#ifdef CUTTLEFISH_ENABLE
-#define PPP_TTY_PATH_ETH0 "rmnet0"
-#else
-#define PPP_TTY_PATH_ETH0 "eth0"
-#endif
-// This is used for emulator
-#define EMULATOR_RADIO_INTERFACE "eth0"
-
-// for sim
-#define AUTH_CONTEXT_EAP_SIM 128
-#define AUTH_CONTEXT_EAP_AKA 129
-#define SIM_AUTH_RESPONSE_SUCCESS 0
-#define SIM_AUTH_RESPONSE_SYNC_FAILURE 3
-
-// Default MTU value
-#define DEFAULT_MTU 1500
-
-#ifdef USE_TI_COMMANDS
-
-// Enable a workaround
-// 1) Make incoming call, do not answer
-// 2) Hangup remote end
-// Expected: call should disappear from CLCC line
-// Actual: Call shows as "ACTIVE" before disappearing
-#define WORKAROUND_ERRONEOUS_ANSWER 1
-
-// Some variants of the TI stack do not support the +CGEV unsolicited
-// response. However, they seem to send an unsolicited +CME ERROR: 150
-#define WORKAROUND_FAKE_CGEV 1
-#endif
-
-/* Modem Technology bits */
-#define MDM_GSM 0x01
-#define MDM_WCDMA 0x02
-#define MDM_CDMA 0x04
-#define MDM_EVDO 0x08
-#define MDM_TDSCDMA 0x10
-#define MDM_LTE 0x20
-#define MDM_NR 0x40
-
-typedef struct {
- int supportedTechs; // Bitmask of supported Modem Technology bits
- int currentTech; // Technology the modem is currently using (in the format used by modem)
- int isMultimode;
-
- // Preferred mode bitmask. This is actually 4 byte-sized bitmasks with different priority values,
- // in which the byte number from LSB to MSB give the priority.
- //
- // |MSB| | |LSB
- // value: |00 |00 |00 |00
- // byte #: |3 |2 |1 |0
- //
- // Higher byte order give higher priority. Thus, a value of 0x0000000f represents
- // a preferred mode of GSM, WCDMA, CDMA, and EvDo in which all are equally preferrable, whereas
- // 0x00000201 represents a mode with GSM and WCDMA, in which WCDMA is preferred over GSM
- int32_t preferredNetworkMode;
- int subscription_source;
-
-} ModemInfo;
-
-static ModemInfo *sMdmInfo;
-// TECH returns the current technology in the format used by the modem.
-// It can be used as an l-value
-#define TECH(mdminfo) ((mdminfo)->currentTech)
-// TECH_BIT returns the bitmask equivalent of the current tech
-#define TECH_BIT(mdminfo) (1 << ((mdminfo)->currentTech))
-#define IS_MULTIMODE(mdminfo) ((mdminfo)->isMultimode)
-#define TECH_SUPPORTED(mdminfo, tech) ((mdminfo)->supportedTechs & (tech))
-#define PREFERRED_NETWORK(mdminfo) ((mdminfo)->preferredNetworkMode)
-// CDMA Subscription Source
-#define SSOURCE(mdminfo) ((mdminfo)->subscription_source)
-
-static int net2modem[] = {
- MDM_GSM | MDM_WCDMA, // 0 - GSM / WCDMA Pref
- MDM_GSM, // 1 - GSM only
- MDM_WCDMA, // 2 - WCDMA only
- MDM_GSM | MDM_WCDMA, // 3 - GSM / WCDMA Auto
- MDM_CDMA | MDM_EVDO, // 4 - CDMA / EvDo Auto
- MDM_CDMA, // 5 - CDMA only
- MDM_EVDO, // 6 - EvDo only
- MDM_GSM | MDM_WCDMA | MDM_CDMA | MDM_EVDO, // 7 - GSM/WCDMA, CDMA, EvDo
- MDM_LTE | MDM_CDMA | MDM_EVDO, // 8 - LTE, CDMA and EvDo
- MDM_LTE | MDM_GSM | MDM_WCDMA, // 9 - LTE, GSM/WCDMA
- MDM_LTE | MDM_CDMA | MDM_EVDO | MDM_GSM | MDM_WCDMA, // 10 - LTE, CDMA, EvDo, GSM/WCDMA
- MDM_LTE, // 11 - LTE only
- MDM_LTE | MDM_WCDMA, // 12 - LTE and WCDMA
- MDM_TDSCDMA, // 13 - TD-SCDMA only
- MDM_WCDMA | MDM_TDSCDMA, // 14 - TD-SCDMA and WCDMA
- MDM_LTE | MDM_TDSCDMA, // 15 - LTE and TD-SCDMA
- MDM_TDSCDMA | MDM_GSM, // 16 - TD-SCDMA and GSM
- MDM_LTE | MDM_TDSCDMA | MDM_GSM, // 17 - TD-SCDMA, GSM and LTE
- MDM_WCDMA | MDM_TDSCDMA | MDM_GSM, // 18 - TD-SCDMA, GSM and WCDMA
- MDM_LTE | MDM_WCDMA | MDM_TDSCDMA, // 19 - LTE, TD-SCDMA and WCDMA
- MDM_LTE | MDM_WCDMA | MDM_TDSCDMA | MDM_GSM, // 20 - LTE, TD-SCDMA, GSM, and WCDMA
- MDM_EVDO | MDM_CDMA | MDM_WCDMA | MDM_TDSCDMA | MDM_GSM, // 21 - TD-SCDMA, CDMA, EVDO, GSM and WCDMA
- MDM_LTE | MDM_TDSCDMA | MDM_CDMA | MDM_EVDO | MDM_WCDMA | MDM_GSM, // 22 - LTE, TDCSDMA, CDMA, EVDO, GSM and WCDMA
- MDM_NR, // 23 - NR 5G only mode
- MDM_NR | MDM_LTE, // 24 - NR 5G, LTE
- MDM_NR | MDM_LTE | MDM_CDMA | MDM_EVDO, // 25 - NR 5G, LTE, CDMA and EvDo
- MDM_NR | MDM_LTE | MDM_WCDMA | MDM_GSM, // 26 - NR 5G, LTE, GSM and WCDMA
- MDM_NR | MDM_LTE | MDM_CDMA | MDM_EVDO | MDM_WCDMA | MDM_GSM, // 27 - NR 5G, LTE, CDMA, EvDo, GSM and WCDMA
- MDM_NR | MDM_LTE | MDM_WCDMA, // 28 - NR 5G, LTE and WCDMA
- MDM_NR | MDM_LTE | MDM_TDSCDMA, // 29 - NR 5G, LTE and TDSCDMA
- MDM_NR | MDM_LTE | MDM_TDSCDMA | MDM_GSM, // 30 - NR 5G, LTE, TD-SCDMA and GSM
- MDM_NR | MDM_LTE | MDM_TDSCDMA | MDM_WCDMA, // 31 - NR 5G, LTE, TD-SCDMA, WCDMA
- MDM_NR | MDM_LTE | MDM_TDSCDMA | MDM_WCDMA | MDM_GSM, // 32 - NR 5G, LTE, TD-SCDMA, GSM and WCDMA
- MDM_NR | MDM_LTE | MDM_TDSCDMA | MDM_CDMA | MDM_EVDO | MDM_WCDMA | MDM_GSM, // 33 - NR 5G, LTE, TD-SCDMA, CDMA, EVDO, GSM and WCDMA
-};
-
-static int32_t net2pmask[] = {
- MDM_GSM | (MDM_WCDMA << 8), // 0 - GSM / WCDMA Pref
- MDM_GSM, // 1 - GSM only
- MDM_WCDMA, // 2 - WCDMA only
- MDM_GSM | MDM_WCDMA, // 3 - GSM / WCDMA Auto
- MDM_CDMA | MDM_EVDO, // 4 - CDMA / EvDo Auto
- MDM_CDMA, // 5 - CDMA only
- MDM_EVDO, // 6 - EvDo only
- MDM_GSM | MDM_WCDMA | MDM_CDMA | MDM_EVDO, // 7 - GSM/WCDMA, CDMA, EvDo
- MDM_LTE | MDM_CDMA | MDM_EVDO, // 8 - LTE, CDMA and EvDo
- MDM_LTE | MDM_GSM | MDM_WCDMA, // 9 - LTE, GSM/WCDMA
- MDM_LTE | MDM_CDMA | MDM_EVDO | MDM_GSM | MDM_WCDMA, // 10 - LTE, CDMA, EvDo, GSM/WCDMA
- MDM_LTE, // 11 - LTE only
- MDM_LTE | MDM_WCDMA, // 12 - LTE and WCDMA
- MDM_TDSCDMA, // 13 - TD-SCDMA only
- MDM_WCDMA | MDM_TDSCDMA, // 14 - TD-SCDMA and WCDMA
- MDM_LTE | MDM_TDSCDMA, // 15 - LTE and TD-SCDMA
- MDM_TDSCDMA | MDM_GSM, // 16 - TD-SCDMA and GSM
- MDM_LTE | MDM_TDSCDMA | MDM_GSM, // 17 - TD-SCDMA, GSM and LTE
- MDM_WCDMA | MDM_TDSCDMA | MDM_GSM, // 18 - TD-SCDMA, GSM and WCDMA
- MDM_LTE | MDM_WCDMA | MDM_TDSCDMA, // 19 - LTE, TD-SCDMA and WCDMA
- MDM_LTE | MDM_WCDMA | MDM_TDSCDMA | MDM_GSM, // 20 - LTE, TD-SCDMA, GSM, and WCDMA
- MDM_EVDO | MDM_CDMA | MDM_WCDMA | MDM_TDSCDMA | MDM_GSM, // 21 - TD-SCDMA, CDMA, EVDO, GSM and WCDMA
- MDM_LTE | MDM_TDSCDMA | MDM_CDMA | MDM_EVDO | MDM_WCDMA | MDM_GSM, // 22 - LTE, TDCSDMA, CDMA, EVDO, GSM and WCDMA
- MDM_NR, // 23 - NR 5G only mode
- MDM_NR | MDM_LTE, // 24 - NR 5G, LTE
- MDM_NR | MDM_LTE | MDM_CDMA | MDM_EVDO, // 25 - NR 5G, LTE, CDMA and EvDo
- MDM_NR | MDM_LTE | MDM_WCDMA | MDM_GSM, // 26 - NR 5G, LTE, GSM and WCDMA
- MDM_NR | MDM_LTE | MDM_CDMA | MDM_EVDO | MDM_WCDMA | MDM_GSM, // 27 - NR 5G, LTE, CDMA, EvDo, GSM and WCDMA
- MDM_NR | MDM_LTE | MDM_WCDMA, // 28 - NR 5G, LTE and WCDMA
- MDM_NR | MDM_LTE | MDM_TDSCDMA, // 29 - NR 5G, LTE and TDSCDMA
- MDM_NR | MDM_LTE | MDM_TDSCDMA | MDM_GSM, // 30 - NR 5G, LTE, TD-SCDMA and GSM
- MDM_NR | MDM_LTE | MDM_TDSCDMA | MDM_WCDMA, // 31 - NR 5G, LTE, TD-SCDMA, WCDMA
- MDM_NR | MDM_LTE | MDM_TDSCDMA | MDM_WCDMA | MDM_GSM, // 32 - NR 5G, LTE, TD-SCDMA, GSM and WCDMA
- MDM_NR | MDM_LTE | MDM_TDSCDMA | MDM_CDMA | MDM_EVDO | MDM_WCDMA | MDM_GSM, // 33 - NR 5G, LTE, TD-SCDMA, CDMA, EVDO, GSM and WCDMA
-};
-
-#define GSM (RAF_GSM | RAF_GPRS | RAF_EDGE)
-#define CDMA (RAF_IS95A | RAF_IS95B | RAF_1xRTT)
-#define EVDO (RAF_EVDO_0 | RAF_EVDO_A | RAF_EVDO_B | RAF_EHRPD)
-#define WCDMA (RAF_HSUPA | RAF_HSDPA | RAF_HSPA | RAF_HSPAP | RAF_UMTS)
-#define LTE (RAF_LTE | RAF_LTE_CA)
-#define NR (RAF_NR)
-
-typedef struct {
- int bitmap;
- int type;
-} NetworkTypeBitmap;
-
-static NetworkTypeBitmap s_networkMask[] = {
- {WCDMA | GSM, MDM_GSM | (MDM_WCDMA << 8)}, // 0 - GSM / WCDMA Pref
- {GSM, MDM_GSM}, // 1 - GSM only
- {WCDMA, MDM_WCDMA}, // 2 - WCDMA only
- {WCDMA | GSM, MDM_GSM | MDM_WCDMA}, // 3 - GSM / WCDMA Auto
- {CDMA | EVDO, MDM_CDMA | MDM_EVDO}, // 4 - CDMA / EvDo Auto
- {CDMA, MDM_CDMA}, // 5 - CDMA only
- {EVDO, MDM_EVDO}, // 6 - EvDo only
- {GSM | WCDMA | CDMA | EVDO, MDM_GSM | MDM_WCDMA | MDM_CDMA | MDM_EVDO}, // 7 - GSM/WCDMA, CDMA, EvDo
- {LTE | CDMA | EVDO, MDM_LTE | MDM_CDMA | MDM_EVDO}, // 8 - LTE, CDMA and EvDo
- {LTE | GSM | WCDMA, MDM_LTE | MDM_GSM | MDM_WCDMA}, // 9 - LTE, GSM/WCDMA
- {LTE | CDMA | EVDO | GSM | WCDMA, MDM_LTE | MDM_CDMA | MDM_EVDO | MDM_GSM | MDM_WCDMA}, // 10 - LTE, CDMA, EvDo, GSM/WCDMA
- {LTE, MDM_LTE}, // 11 - LTE only
- {LTE | WCDMA, MDM_LTE | MDM_WCDMA}, // 12 - LTE and WCDMA
- {RAF_TD_SCDMA, MDM_TDSCDMA}, // 13 - TD-SCDMA only
- {RAF_TD_SCDMA | WCDMA, MDM_WCDMA | MDM_TDSCDMA}, // 14 - TD-SCDMA and WCDMA
- {LTE | RAF_TD_SCDMA, MDM_LTE | MDM_TDSCDMA}, // 15 - LTE and TD-SCDMA
- {RAF_TD_SCDMA | GSM, MDM_TDSCDMA | MDM_GSM}, // 16 - TD-SCDMA and GSM
- {LTE | RAF_TD_SCDMA | GSM, MDM_LTE | MDM_TDSCDMA | MDM_GSM}, // 17 - TD-SCDMA, GSM and LTE
- {RAF_TD_SCDMA | GSM | WCDMA, MDM_WCDMA | MDM_TDSCDMA | MDM_GSM}, // 18 - TD-SCDMA, GSM and WCDMA
- {LTE | RAF_TD_SCDMA | WCDMA, MDM_LTE | MDM_WCDMA | MDM_TDSCDMA}, // 19 - LTE, TD-SCDMA and WCDMA
- {LTE | RAF_TD_SCDMA | GSM | WCDMA,MDM_LTE | MDM_WCDMA | MDM_TDSCDMA | MDM_GSM}, // 20 - LTE, TD-SCDMA, GSM, and WCDMA
- {RAF_TD_SCDMA | CDMA | EVDO | GSM | WCDMA, MDM_EVDO | MDM_CDMA | MDM_WCDMA | MDM_TDSCDMA | MDM_GSM}, // 21 - TD-SCDMA, CDMA, EVDO, GSM and WCDMA
- {LTE | RAF_TD_SCDMA | CDMA | EVDO | GSM | WCDMA, MDM_LTE | MDM_TDSCDMA | MDM_CDMA | MDM_EVDO | MDM_WCDMA | MDM_GSM}, // 22 - LTE, TDCSDMA, CDMA, EVDO, GSM and WCDMA
- {NR, MDM_NR}, // 23 - NR 5G only mode
- {NR | LTE, MDM_NR | MDM_LTE}, // 24 - NR 5G, LTE
- {NR | LTE | CDMA | EVDO, MDM_NR | MDM_LTE | MDM_CDMA | MDM_EVDO}, // 25 - NR 5G, LTE, CDMA and EvDo
- {NR | LTE | GSM | WCDMA, MDM_NR | MDM_LTE | MDM_WCDMA | MDM_GSM}, // 26 - NR 5G, LTE, GSM and WCDMA
- {NR | LTE | CDMA | EVDO | GSM | WCDMA, MDM_NR | MDM_LTE | MDM_CDMA | MDM_EVDO | MDM_WCDMA | MDM_GSM}, // 27 - NR 5G, LTE, CDMA, EvDo, GSM and WCDMA
- {NR | LTE | WCDMA, MDM_NR | MDM_LTE | MDM_WCDMA}, // 28 - NR 5G, LTE and WCDMA
- {NR | LTE | RAF_TD_SCDMA, MDM_NR | MDM_LTE | MDM_TDSCDMA}, // 29 - NR 5G, LTE and TDSCDMA
- {NR | LTE | RAF_TD_SCDMA | GSM, MDM_NR | MDM_LTE | MDM_TDSCDMA | MDM_GSM}, // 30 - NR 5G, LTE, TD-SCDMA and GSM
- {NR | LTE | RAF_TD_SCDMA | WCDMA, MDM_NR | MDM_LTE | MDM_TDSCDMA | MDM_WCDMA}, // 31 - NR 5G, LTE, TD-SCDMA, WCDMA
- {NR | LTE | RAF_TD_SCDMA | GSM | WCDMA, MDM_NR | MDM_LTE | MDM_TDSCDMA | MDM_WCDMA | MDM_GSM}, // 32 - NR 5G, LTE, TD-SCDMA, GSM and WCDMA
- {NR | LTE | RAF_TD_SCDMA | CDMA | EVDO | GSM | WCDMA, MDM_NR | MDM_LTE | MDM_TDSCDMA | MDM_CDMA | MDM_EVDO | MDM_WCDMA | MDM_GSM}, // 33 - NR 5G, LTE, TD-SCDMA, CDMA, EVDO, GSM and WCDMA
-};
-
-static int is3gpp2(int radioTech) {
- switch (radioTech) {
- case RADIO_TECH_IS95A:
- case RADIO_TECH_IS95B:
- case RADIO_TECH_1xRTT:
- case RADIO_TECH_EVDO_0:
- case RADIO_TECH_EVDO_A:
- case RADIO_TECH_EVDO_B:
- case RADIO_TECH_EHRPD:
- return 1;
- default:
- return 0;
- }
-}
-
-typedef enum {
- SIM_ABSENT = 0,
- SIM_NOT_READY = 1,
- SIM_READY = 2,
- SIM_PIN = 3,
- SIM_PUK = 4,
- SIM_NETWORK_PERSONALIZATION = 5,
- RUIM_ABSENT = 6,
- RUIM_NOT_READY = 7,
- RUIM_READY = 8,
- RUIM_PIN = 9,
- RUIM_PUK = 10,
- RUIM_NETWORK_PERSONALIZATION = 11,
- ISIM_ABSENT = 12,
- ISIM_NOT_READY = 13,
- ISIM_READY = 14,
- ISIM_PIN = 15,
- ISIM_PUK = 16,
- ISIM_NETWORK_PERSONALIZATION = 17,
-} SIM_Status;
-
-static void onRequest (int request, void *data, size_t datalen, RIL_Token t);
-static RIL_RadioState currentState();
-static int onSupports (int requestCode);
-static void onCancel (RIL_Token t);
-static const char *getVersion();
-static int isRadioOn();
-static SIM_Status getSIMStatus();
-static int getCardStatus(RIL_CardStatus_v1_5 **pp_card_status);
-static void freeCardStatus(RIL_CardStatus_v1_5 *p_card_status);
-static void onDataCallListChanged(void *param);
-bool areUiccApplicationsEnabled = true;
-
-extern const char * requestToString(int request);
-extern uint8_t hexCharToInt(uint8_t c);
-extern uint8_t * convertHexStringToBytes(void *response, size_t responseLen);
-
-/*** Static Variables ***/
-static const RIL_RadioFunctions s_callbacks = {
- RIL_VERSION,
- onRequest,
- currentState,
- onSupports,
- onCancel,
- getVersion
-};
-
-#ifdef RIL_SHLIB
-static const struct RIL_Env *s_rilenv;
-
-#define RIL_onRequestComplete(t, e, response, responselen) s_rilenv->OnRequestComplete(t,e, response, responselen)
-#define RIL_onUnsolicitedResponse(a,b,c) s_rilenv->OnUnsolicitedResponse(a,b,c)
-#define RIL_requestTimedCallback(a,b,c) s_rilenv->RequestTimedCallback(a,b,c)
-#endif
-
-static RIL_RadioState sState = RADIO_STATE_UNAVAILABLE;
-static bool isNrDualConnectivityEnabled = true;
-
-static pthread_mutex_t s_state_mutex = PTHREAD_MUTEX_INITIALIZER;
-static pthread_cond_t s_state_cond = PTHREAD_COND_INITIALIZER;
-
-static int s_port = -1;
-static const char * s_device_path = NULL;
-static int s_device_socket = 0;
-static uint32_t s_modem_simulator_port = -1;
-
-/* trigger change to this with s_state_cond */
-static int s_closed = 0;
-
-static int sFD; /* file desc of AT channel */
-static char sATBuffer[MAX_AT_RESPONSE+1];
-static char *sATBufferCur = NULL;
-
-static const struct timeval TIMEVAL_SIMPOLL = {1,0};
-static const struct timeval TIMEVAL_CALLSTATEPOLL = {0,500000};
-static const struct timeval TIMEVAL_0 = {0,0};
-
-static int s_ims_registered = 0; // 0==unregistered
-static int s_ims_services = 1; // & 0x1 == sms over ims supported
-static int s_ims_format = 1; // FORMAT_3GPP(1) vs FORMAT_3GPP2(2);
-static int s_ims_cause_retry = 0; // 1==causes sms over ims to temp fail
-static int s_ims_cause_perm_failure = 0; // 1==causes sms over ims to permanent fail
-static int s_ims_gsm_retry = 0; // 1==causes sms over gsm to temp fail
-static int s_ims_gsm_fail = 0; // 1==causes sms over gsm to permanent fail
-
-#ifdef WORKAROUND_ERRONEOUS_ANSWER
-// Max number of times we'll try to repoll when we think
-// we have a AT+CLCC race condition
-#define REPOLL_CALLS_COUNT_MAX 4
-
-// Line index that was incoming or waiting at last poll, or -1 for none
-static int s_incomingOrWaitingLine = -1;
-// Number of times we've asked for a repoll of AT+CLCC
-static int s_repollCallsCount = 0;
-// Should we expect a call to be answered in the next CLCC?
-static int s_expectAnswer = 0;
-#endif /* WORKAROUND_ERRONEOUS_ANSWER */
-
-
-static int s_cell_info_rate_ms = INT_MAX;
-static int s_mcc = 0;
-static int s_mnc = 0;
-static int s_mncLength = 2;
-static int s_lac = 0;
-static int s_cid = 0;
-
-// STK
-static bool s_stkServiceRunning = false;
-static char *s_stkUnsolResponse = NULL;
-
-typedef enum {
- STK_UNSOL_EVENT_UNKNOWN,
- STK_UNSOL_EVENT_NOTIFY,
- STK_UNSOL_PROACTIVE_CMD,
-} StkUnsolEvent;
-
-typedef enum {
- STK_RUN_AT = 0x34,
- STK_SEND_DTMF = 0x14,
- STK_SEND_SMS = 0x13,
- STK_SEND_SS = 0x11,
- STK_SEND_USSD = 0x12,
- STK_PLAY_TONE = 0x20,
- STK_OPEN_CHANNEL = 0x40,
- STK_CLOSE_CHANNEL = 0x41,
- STK_RECEIVE_DATA = 0x42,
- STK_SEND_DATA = 0x43,
- STK_GET_CHANNEL_STATUS = 0x44,
- STK_REFRESH = 0x01,
-} StkCmdType;
-
-enum PDPState {
- PDP_IDLE,
- PDP_BUSY,
-};
-
-struct PDPInfo {
- int cid;
- enum PDPState state;
-};
-
-struct PDPInfo s_PDP[] = {
- {1, PDP_IDLE},
- {2, PDP_IDLE},
- {3, PDP_IDLE},
-};
-
-static void pollSIMState (void *param);
-static void setRadioState(RIL_RadioState newState);
-static void setRadioTechnology(ModemInfo *mdm, int newtech);
-static int query_ctec(ModemInfo *mdm, int *current, int32_t *preferred);
-static int parse_technology_response(const char *response, int *current, int32_t *preferred);
-static int techFromModemType(int mdmtype);
-static void getIccId(char *iccid, int size);
-
-static int clccStateToRILState(int state, RIL_CallState *p_state)
-{
- switch(state) {
- case 0: *p_state = RIL_CALL_ACTIVE; return 0;
- case 1: *p_state = RIL_CALL_HOLDING; return 0;
- case 2: *p_state = RIL_CALL_DIALING; return 0;
- case 3: *p_state = RIL_CALL_ALERTING; return 0;
- case 4: *p_state = RIL_CALL_INCOMING; return 0;
- case 5: *p_state = RIL_CALL_WAITING; return 0;
- default: return -1;
- }
-}
-
-void convertBytesToHexString(char *bin_ptr, int length, unsigned char *hex_ptr) {
- int i;
- unsigned char tmp;
-
- if (bin_ptr == NULL || hex_ptr == NULL) {
- return;
- }
- for (i = 0; i < length; i++) {
- tmp = (unsigned char)((bin_ptr[i] & 0xf0) >> 4);
- if (tmp <= 9) {
- *hex_ptr = (unsigned char)(tmp + '0');
- } else {
- *hex_ptr = (unsigned char)(tmp + 'A' - 10);
- }
- hex_ptr++;
- tmp = (unsigned char)(bin_ptr[i] & 0x0f);
- if (tmp <= 9) {
- *hex_ptr = (unsigned char)(tmp + '0');
- } else {
- *hex_ptr = (unsigned char)(tmp + 'A' - 10);
- }
- hex_ptr++;
- }
-}
-
-/**
- * Note: directly modified line and has *p_call point directly into
- * modified line
- */
-static int callFromCLCCLine(char *line, RIL_Call *p_call)
-{
- //+CLCC: 1,0,2,0,0,\"+18005551212\",145
- // index,isMT,state,mode,isMpty(,number,TOA)?
-
- int err;
- int state;
- int mode;
-
- err = at_tok_start(&line);
- if (err < 0) goto error;
-
- err = at_tok_nextint(&line, &(p_call->index));
- if (err < 0) goto error;
-
- err = at_tok_nextbool(&line, &(p_call->isMT));
- if (err < 0) goto error;
-
- err = at_tok_nextint(&line, &state);
- if (err < 0) goto error;
-
- err = clccStateToRILState(state, &(p_call->state));
- if (err < 0) goto error;
-
- err = at_tok_nextint(&line, &mode);
- if (err < 0) goto error;
-
- p_call->isVoice = (mode == 0);
-
- err = at_tok_nextbool(&line, &(p_call->isMpty));
- if (err < 0) goto error;
-
- if (at_tok_hasmore(&line)) {
- err = at_tok_nextstr(&line, &(p_call->number));
-
- /* tolerate null here */
- if (err < 0) return 0;
-
- // Some lame implementations return strings
- // like "NOT AVAILABLE" in the CLCC line
- if (p_call->number != NULL
- && 0 == strspn(p_call->number, "+0123456789")
- ) {
- p_call->number = NULL;
- }
-
- err = at_tok_nextint(&line, &p_call->toa);
- if (err < 0) goto error;
- }
-
- p_call->uusInfo = NULL;
-
- return 0;
-
-error:
- RLOGE("invalid CLCC line\n");
- return -1;
-}
-
-static int parseSimResponseLine(char* line, RIL_SIM_IO_Response* response) {
- int err;
-
- err = at_tok_start(&line);
- if (err < 0) return err;
- err = at_tok_nextint(&line, &response->sw1);
- if (err < 0) return err;
- err = at_tok_nextint(&line, &response->sw2);
- if (err < 0) return err;
-
- if (at_tok_hasmore(&line)) {
- err = at_tok_nextstr(&line, &response->simResponse);
- if (err < 0) return err;
- }
- return 0;
-}
-
-#ifdef CUTTLEFISH_ENABLE
-static void set_Ip_Addr(const char *addr, const char* radioInterfaceName) {
- RLOGD("%s %d setting ip addr %s on interface %s", __func__, __LINE__, addr,
- radioInterfaceName);
- struct ifreq request;
- int status = 0;
- int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
- if (sock == -1) {
- RLOGE("Failed to open interface socket: %s (%d)", strerror(errno), errno);
- return;
- }
-
- memset(&request, 0, sizeof(request));
- strncpy(request.ifr_name, radioInterfaceName, sizeof(request.ifr_name));
- request.ifr_name[sizeof(request.ifr_name) - 1] = '\0';
-
- char *myaddr = strdup(addr);
- char *pch = NULL;
- pch = strchr(myaddr, '/');
- if (pch) {
- *pch = '\0';
- }
-
- struct sockaddr_in *sin = (struct sockaddr_in *)&request.ifr_addr;
- sin->sin_family = AF_INET;
- sin->sin_addr.s_addr = inet_addr(myaddr);
- if (ioctl(sock, SIOCSIFADDR, &request) < 0) {
- RLOGE("%s: failed.", __func__);
- }
-
- close(sock);
- free(myaddr);
- RLOGD("%s %d done.", __func__, __LINE__);
-}
-#endif
-
-enum InterfaceState {
- kInterfaceUp,
- kInterfaceDown,
-};
-
-static RIL_Errno setInterfaceState(const char* interfaceName,
- enum InterfaceState state) {
- struct ifreq request;
- int status = 0;
- int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
- if (sock == -1) {
- RLOGE("Failed to open interface socket: %s (%d)",
- strerror(errno), errno);
- return RIL_E_GENERIC_FAILURE;
- }
-
- memset(&request, 0, sizeof(request));
- strncpy(request.ifr_name, interfaceName, sizeof(request.ifr_name));
- request.ifr_name[sizeof(request.ifr_name) - 1] = '\0';
- status = ioctl(sock, SIOCGIFFLAGS, &request);
- if (status != 0) {
- RLOGE("Failed to get interface flags for %s: %s (%d)",
- interfaceName, strerror(errno), errno);
- close(sock);
- return RIL_E_RADIO_NOT_AVAILABLE;
- }
-
- bool isUp = (request.ifr_flags & IFF_UP);
- if ((state == kInterfaceUp && isUp) || (state == kInterfaceDown && !isUp)) {
- // Interface already in desired state
- close(sock);
- return RIL_E_SUCCESS;
- }
-
- // Simply toggle the flag since we know it's the opposite of what we want
- request.ifr_flags ^= IFF_UP;
-
- status = ioctl(sock, SIOCSIFFLAGS, &request);
- if (status != 0) {
- RLOGE("Failed to set interface flags for %s: %s (%d)",
- interfaceName, strerror(errno), errno);
- close(sock);
- return RIL_E_GENERIC_FAILURE;
- }
-
- close(sock);
- return RIL_E_SUCCESS;
-}
-
-/** do post-AT+CFUN=1 initialization */
-static void onRadioPowerOn()
-{
-#ifdef USE_TI_COMMANDS
- /* Must be after CFUN=1 */
- /* TI specific -- notifications for CPHS things such */
- /* as CPHS message waiting indicator */
-
- at_send_command("AT%CPHS=1", NULL);
-
- /* TI specific -- enable NITZ unsol notifs */
- at_send_command("AT%CTZV=1", NULL);
-#endif
-
- pollSIMState(NULL);
-}
-
-/** do post- SIM ready initialization */
-static void onSIMReady()
-{
- at_send_command_singleline("AT+CSMS=1", "+CSMS:", NULL);
- /*
- * Always send SMS messages directly to the TE
- *
- * mode = 1 // discard when link is reserved (link should never be
- * reserved)
- * mt = 2 // most messages routed to TE
- * bm = 2 // new cell BM's routed to TE
- * ds = 1 // Status reports routed to TE
- * bfr = 1 // flush buffer
- */
- at_send_command("AT+CNMI=1,2,2,1,1", NULL);
-}
-
-static void requestRadioPower(void *data, size_t datalen __unused, RIL_Token t)
-{
- int onOff;
-
- int err;
- ATResponse *p_response = NULL;
-
- assert (datalen >= sizeof(int *));
- onOff = ((int *)data)[0];
-
- if (onOff == 0 && sState != RADIO_STATE_OFF) {
- err = at_send_command("AT+CFUN=0", &p_response);
- if (err < 0 || p_response->success == 0) goto error;
- setRadioState(RADIO_STATE_OFF);
- } else if (onOff > 0 && sState == RADIO_STATE_OFF) {
- err = at_send_command("AT+CFUN=1", &p_response);
- if (err < 0|| p_response->success == 0) {
- // Some stacks return an error when there is no SIM,
- // but they really turn the RF portion on
- // So, if we get an error, let's check to see if it
- // turned on anyway
-
- if (isRadioOn() != 1) {
- goto error;
- }
- }
- setRadioState(RADIO_STATE_ON);
- }
-
- at_response_free(p_response);
- RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
- return;
-error:
- at_response_free(p_response);
- RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
-}
-
-static void requestShutdown(RIL_Token t)
-{
- int onOff;
-
- int err;
- ATResponse *p_response = NULL;
-
- if (sState != RADIO_STATE_OFF) {
- err = at_send_command("AT+CFUN=0", &p_response);
- setRadioState(RADIO_STATE_UNAVAILABLE);
- }
-
- at_response_free(p_response);
- RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
- return;
-}
-
-static void requestOrSendDataCallList(int cid, RIL_Token *t);
-
-static void onDataCallListChanged(void *param __unused)
-{
- requestOrSendDataCallList(-1, NULL);
-}
-
-static void requestDataCallList(void *data __unused, size_t datalen __unused, RIL_Token t)
-{
- requestOrSendDataCallList(-1, &t);
-}
-
-// Hang up, reject, conference, call waiting
-static void requestCallSelection(
- void *data __unused, size_t datalen __unused, RIL_Token t, int request)
-{
- // 3GPP 22.030 6.5.5
- static char hangupWaiting[] = "AT+CHLD=0";
- static char hangupForeground[] = "AT+CHLD=1";
- static char switchWaiting[] = "AT+CHLD=2";
- static char conference[] = "AT+CHLD=3";
- static char reject[] = "ATH";
-
- char* atCommand;
-
- if (getSIMStatus() == SIM_ABSENT) {
- RIL_onRequestComplete(t, RIL_E_RADIO_NOT_AVAILABLE, NULL, 0);
- return;
- }
-
- switch(request) {
- case RIL_REQUEST_HANGUP_WAITING_OR_BACKGROUND:
- // "Releases all held calls or sets User Determined User Busy
- // (UDUB) for a waiting call."
- atCommand = hangupWaiting;
- break;
- case RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND:
- // "Releases all active calls (if any exist) and accepts
- // the other (held or waiting) call."
- atCommand = hangupForeground;
- break;
- case RIL_REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE:
- // "Places all active calls (if any exist) on hold and accepts
- // the other (held or waiting) call."
- atCommand = switchWaiting;
-#ifdef WORKAROUND_ERRONEOUS_ANSWER
- s_expectAnswer = 1;
-#endif /* WORKAROUND_ERRONEOUS_ANSWER */
- break;
- case RIL_REQUEST_CONFERENCE:
- // "Adds a held call to the conversation"
- atCommand = conference;
- break;
- case RIL_REQUEST_UDUB:
- // User determined user busy (reject)
- atCommand = reject;
- break;
- default:
- assert(0);
- }
- at_send_command(atCommand, NULL);
- // Success or failure is ignored by the upper layer here.
- // It will call GET_CURRENT_CALLS and determine success that way.
- RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
-}
-
-static const char* getRadioInterfaceName()
-{
- if (isInEmulator()) {
- return EMULATOR_RADIO_INTERFACE;
- }
- return PPP_TTY_PATH_ETH0;
-}
-
-static void requestOrSendDataCallList(int cid, RIL_Token *t)
-{
- ATResponse *p_response = NULL;
- ATLine *p_cur = NULL;
- int err = -1;
- int n = 0;
- char *out = NULL;
- char propValue[PROP_VALUE_MAX] = {0};
- const char* radioInterfaceName = getRadioInterfaceName();
-
- err = at_send_command_multiline ("AT+CGACT?", "+CGACT:", &p_response);
- if (err != 0 || p_response->success == 0) {
- if (t != NULL)
- RIL_onRequestComplete(*t, RIL_E_GENERIC_FAILURE, NULL, 0);
- else
- RIL_onUnsolicitedResponse(RIL_UNSOL_DATA_CALL_LIST_CHANGED,
- NULL, 0);
- return;
- }
-
- for (p_cur = p_response->p_intermediates; p_cur != NULL;
- p_cur = p_cur->p_next)
- n++;
-
- RIL_Data_Call_Response_v11 *responses =
- alloca(n * sizeof(RIL_Data_Call_Response_v11));
-
- int i;
- for (i = 0; i < n; i++) {
- responses[i].status = -1;
- responses[i].suggestedRetryTime = -1;
- responses[i].cid = -1;
- responses[i].active = -1;
- responses[i].type = "";
- responses[i].ifname = "";
- responses[i].addresses = "";
- responses[i].dnses = "";
- responses[i].gateways = "";
- responses[i].pcscf = "";
- responses[i].mtu = 0;
- }
-
- RIL_Data_Call_Response_v11 *response = responses;
- for (p_cur = p_response->p_intermediates; p_cur != NULL;
- p_cur = p_cur->p_next) {
- char *line = p_cur->line;
-
- err = at_tok_start(&line);
- if (err < 0)
- goto error;
-
- err = at_tok_nextint(&line, &response->cid);
- if (err < 0)
- goto error;
-
- err = at_tok_nextint(&line, &response->active);
- if (err < 0)
- goto error;
-
- response++;
- }
-
- at_response_free(p_response);
-
- err = at_send_command_multiline ("AT+CGDCONT?", "+CGDCONT:", &p_response);
- if (err != 0 || p_response->success == 0) {
- if (t != NULL)
- RIL_onRequestComplete(*t, RIL_E_GENERIC_FAILURE, NULL, 0);
- else
- RIL_onUnsolicitedResponse(RIL_UNSOL_DATA_CALL_LIST_CHANGED,
- NULL, 0);
- return;
- }
-
- for (p_cur = p_response->p_intermediates; p_cur != NULL;
- p_cur = p_cur->p_next) {
- char *line = p_cur->line;
- int ncid;
-
- err = at_tok_start(&line);
- if (err < 0)
- goto error;
-
- err = at_tok_nextint(&line, &ncid);
- if (err < 0)
- goto error;
-
- if (cid != ncid)
- continue;
-
- i = ncid - 1;
- // Assume no error
- responses[i].status = 0;
-
- // type
- err = at_tok_nextstr(&line, &out);
- if (err < 0)
- goto error;
-
- int type_size = strlen(out) + 1;
- responses[i].type = alloca(type_size);
- strlcpy(responses[i].type, out, type_size);
-
- // APN ignored for v5
- err = at_tok_nextstr(&line, &out);
- if (err < 0)
- goto error;
-
- int ifname_size = strlen(radioInterfaceName) + 1;
- responses[i].ifname = alloca(ifname_size);
- strlcpy(responses[i].ifname, radioInterfaceName, ifname_size);
-
- err = at_tok_nextstr(&line, &out);
- if (err < 0)
- goto error;
-
- int addresses_size = strlen(out) + 1;
- responses[i].addresses = alloca(addresses_size);
- strlcpy(responses[i].addresses, out, addresses_size);
-#ifdef CUTTLEFISH_ENABLE
- set_Ip_Addr(responses[i].addresses, radioInterfaceName);
-#endif
-
- if (isInEmulator()) {
- /* We are in the emulator - the dns servers are listed
- * by the following system properties, setup in
- * /system/etc/init.goldfish.sh:
- * - vendor.net.eth0.dns1
- * - vendor.net.eth0.dns2
- * - vendor.net.eth0.dns3
- * - vendor.net.eth0.dns4
- */
- const int dnslist_sz = 128;
- char* dnslist = alloca(dnslist_sz);
- const char* separator = "";
- int nn;
-
- dnslist[0] = 0;
- for (nn = 1; nn <= 4; nn++) {
- /* Probe vendor.net.eth0.dns<n> */
- char propName[PROP_NAME_MAX];
- char propValue[PROP_VALUE_MAX];
-
- snprintf(propName, sizeof propName, "vendor.net.eth0.dns%d", nn);
-
- /* Ignore if undefined */
- if (property_get(propName, propValue, "") <= 0) {
- continue;
- }
-
- /* Append the DNS IP address */
- strlcat(dnslist, separator, dnslist_sz);
- strlcat(dnslist, propValue, dnslist_sz);
- separator = " ";
- }
- responses[i].dnses = dnslist;
-
- if (property_get("vendor.net.eth0.gw", propValue, "") > 0) {
- responses[i].gateways = propValue;
- } else {
- responses[i].gateways = "";
- }
- responses[i].mtu = DEFAULT_MTU;
- } else {
- /* I don't know where we are, so use the public Google DNS
- * servers by default and no gateway.
- */
- responses[i].dnses = "8.8.8.8 8.8.4.4";
- responses[i].gateways = "";
- }
- }
-
- at_response_free(p_response);
- p_response = NULL;
-
- char cmd[64] = {0};
- snprintf(cmd, sizeof(cmd), "AT+CGCONTRDP=%d", cid);
- err = at_send_command_singleline(cmd, "+CGCONTRDP:", &p_response);
- if (err < 0 || p_response->success == 0) {
- goto error;
- }
-
- int skip = 0;
- char *sskip = NULL;
- char *input = p_response->p_intermediates->line;
-
- int ncid = -1;
- err = at_tok_start(&input);
- if (err < 0) goto error;
-
- err = at_tok_nextint(&input, &ncid); // cid
- if (err < 0) goto error;
-
- if (cid != ncid) goto error;
-
- i = ncid - 1;
-
- err = at_tok_nextint(&input, &skip); // bearer_id
- if (err < 0) goto error;
-
- err = at_tok_nextstr(&input, &sskip); // apn
- if (err < 0) goto error;
-
- err = at_tok_nextstr(&input, &sskip); // local_addr_and_subnet_mask
- if (err < 0) goto error;
-
- err = at_tok_nextstr(&input, &responses[i].gateways); // gw_addr
- if (err < 0) goto error;
-
- err = at_tok_nextstr(&input, &responses[i].dnses); // dns_prim_addr
- if (err < 0) goto error;
-
- if (t != NULL)
- RIL_onRequestComplete(*t, RIL_E_SUCCESS, &responses[i],
- sizeof(RIL_Data_Call_Response_v11));
- else
- RIL_onUnsolicitedResponse(RIL_UNSOL_DATA_CALL_LIST_CHANGED,
- responses,
- n * sizeof(RIL_Data_Call_Response_v11));
-
- at_response_free(p_response);
- return;
-
-error:
- if (t != NULL)
- RIL_onRequestComplete(*t, RIL_E_GENERIC_FAILURE, NULL, 0);
- else
- RIL_onUnsolicitedResponse(RIL_UNSOL_DATA_CALL_LIST_CHANGED,
- NULL, 0);
- at_response_free(p_response);
-}
-
-static void requestQueryNetworkSelectionMode(
- void *data __unused, size_t datalen __unused, RIL_Token t)
-{
- int err;
- ATResponse *p_response = NULL;
- int response = 0;
- char *line;
-
- err = at_send_command_singleline("AT+COPS?", "+COPS:", &p_response);
-
- if (err < 0 || p_response->success == 0) {
- goto error;
- }
-
- line = p_response->p_intermediates->line;
-
- err = at_tok_start(&line);
-
- if (err < 0) {
- goto error;
- }
-
- err = at_tok_nextint(&line, &response);
-
- if (err < 0) {
- goto error;
- }
-
- RIL_onRequestComplete(t, RIL_E_SUCCESS, &response, sizeof(int));
- at_response_free(p_response);
- return;
-error:
- at_response_free(p_response);
- RLOGE("requestQueryNetworkSelectionMode must never return error when radio is on");
- RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
-}
-
-static void sendCallStateChanged(void *param __unused)
-{
- RIL_onUnsolicitedResponse (
- RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED,
- NULL, 0);
-}
-
-static void requestGetCurrentCalls(void *data __unused, size_t datalen __unused, RIL_Token t)
-{
- int err;
- ATResponse *p_response;
- ATLine *p_cur;
- int countCalls;
- int countValidCalls;
- RIL_Call *p_calls;
- RIL_Call **pp_calls;
- int i;
- int needRepoll = 0;
-
-#ifdef WORKAROUND_ERRONEOUS_ANSWER
- int prevIncomingOrWaitingLine;
-
- prevIncomingOrWaitingLine = s_incomingOrWaitingLine;
- s_incomingOrWaitingLine = -1;
-#endif /*WORKAROUND_ERRONEOUS_ANSWER*/
-
- err = at_send_command_multiline ("AT+CLCC", "+CLCC:", &p_response);
-
- if (err != 0 || p_response->success == 0) {
- RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
- return;
- }
-
- /* count the calls */
- for (countCalls = 0, p_cur = p_response->p_intermediates
- ; p_cur != NULL
- ; p_cur = p_cur->p_next
- ) {
- countCalls++;
- }
-
- /* yes, there's an array of pointers and then an array of structures */
-
- pp_calls = (RIL_Call **)alloca(countCalls * sizeof(RIL_Call *));
- p_calls = (RIL_Call *)alloca(countCalls * sizeof(RIL_Call));
- memset (p_calls, 0, countCalls * sizeof(RIL_Call));
-
- /* init the pointer array */
- for(i = 0; i < countCalls ; i++) {
- pp_calls[i] = &(p_calls[i]);
- }
-
- for (countValidCalls = 0, p_cur = p_response->p_intermediates
- ; p_cur != NULL
- ; p_cur = p_cur->p_next
- ) {
- err = callFromCLCCLine(p_cur->line, p_calls + countValidCalls);
-
- if (err != 0) {
- continue;
- }
-
-#ifdef WORKAROUND_ERRONEOUS_ANSWER
- if (p_calls[countValidCalls].state == RIL_CALL_INCOMING
- || p_calls[countValidCalls].state == RIL_CALL_WAITING
- ) {
- s_incomingOrWaitingLine = p_calls[countValidCalls].index;
- }
-#endif /*WORKAROUND_ERRONEOUS_ANSWER*/
-
- if (p_calls[countValidCalls].state != RIL_CALL_ACTIVE
- && p_calls[countValidCalls].state != RIL_CALL_HOLDING
- ) {
- needRepoll = 1;
- }
-
- countValidCalls++;
- }
-
-#ifdef WORKAROUND_ERRONEOUS_ANSWER
- // Basically:
- // A call was incoming or waiting
- // Now it's marked as active
- // But we never answered it
- //
- // This is probably a bug, and the call will probably
- // disappear from the call list in the next poll
- if (prevIncomingOrWaitingLine >= 0
- && s_incomingOrWaitingLine < 0
- && s_expectAnswer == 0
- ) {
- for (i = 0; i < countValidCalls ; i++) {
-
- if (p_calls[i].index == prevIncomingOrWaitingLine
- && p_calls[i].state == RIL_CALL_ACTIVE
- && s_repollCallsCount < REPOLL_CALLS_COUNT_MAX
- ) {
- RLOGI(
- "Hit WORKAROUND_ERRONOUS_ANSWER case."
- " Repoll count: %d\n", s_repollCallsCount);
- s_repollCallsCount++;
- goto error;
- }
- }
- }
-
- s_expectAnswer = 0;
- s_repollCallsCount = 0;
-#endif /*WORKAROUND_ERRONEOUS_ANSWER*/
-
- RIL_onRequestComplete(t, RIL_E_SUCCESS, pp_calls,
- countValidCalls * sizeof (RIL_Call *));
-
- at_response_free(p_response);
-
-#ifdef POLL_CALL_STATE
- if (countValidCalls) { // We don't seem to get a "NO CARRIER" message from
- // smd, so we're forced to poll until the call ends.
-#else
- if (needRepoll) {
-#endif
- RIL_requestTimedCallback (sendCallStateChanged, NULL, &TIMEVAL_CALLSTATEPOLL);
- }
-
- return;
-#ifdef WORKAROUND_ERRONEOUS_ANSWER
-error:
- RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
- at_response_free(p_response);
-#endif
-}
-
-static void requestDial(void *data, size_t datalen __unused, RIL_Token t)
-{
- RIL_Dial *p_dial;
- char *cmd;
- const char *clir;
- int ret;
-
- p_dial = (RIL_Dial *)data;
-
- switch (p_dial->clir) {
- case 1: clir = "I"; break; /*invocation*/
- case 2: clir = "i"; break; /*suppression*/
- default:
- case 0: clir = ""; break; /*subscription default*/
- }
-
- asprintf(&cmd, "ATD%s%s;", p_dial->address, clir);
-
- ret = at_send_command(cmd, NULL);
-
- free(cmd);
-
- /* success or failure is ignored by the upper layer here.
- it will call GET_CURRENT_CALLS and determine success that way */
- RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
-}
-
-static void requestWriteSmsToSim(void *data, size_t datalen __unused, RIL_Token t)
-{
- RIL_SMS_WriteArgs *p_args;
- char *cmd;
- int length;
- int err;
- ATResponse *p_response = NULL;
-
- if (getSIMStatus() == SIM_ABSENT) {
- RIL_onRequestComplete(t, RIL_E_SIM_ABSENT, NULL, 0);
- return;
- }
-
- p_args = (RIL_SMS_WriteArgs *)data;
-
- length = strlen(p_args->pdu)/2;
- asprintf(&cmd, "AT+CMGW=%d,%d", length, p_args->status);
-
- err = at_send_command_sms(cmd, p_args->pdu, "+CMGW:", &p_response);
-
- if (err != 0 || p_response->success == 0) goto error;
-
- RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
- at_response_free(p_response);
-
- return;
-error:
- RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
- at_response_free(p_response);
-}
-
-static void requestHangup(void *data, size_t datalen __unused, RIL_Token t)
-{
- int *p_line;
-
- int ret;
- char *cmd;
-
- if (getSIMStatus() == SIM_ABSENT) {
- RIL_onRequestComplete(t, RIL_E_MODEM_ERR, NULL, 0);
- return;
- }
- p_line = (int *)data;
-
- // 3GPP 22.030 6.5.5
- // "Releases a specific active call X"
- asprintf(&cmd, "AT+CHLD=1%d", p_line[0]);
-
- ret = at_send_command(cmd, NULL);
-
- free(cmd);
-
- /* success or failure is ignored by the upper layer here.
- it will call GET_CURRENT_CALLS and determine success that way */
- RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
-}
-
-static void requestSignalStrength(void *data __unused, size_t datalen __unused, RIL_Token t)
-{
- ATResponse *p_response = NULL;
- int err;
- char *line;
- int count = 0;
- // Accept a response that is at least v6, and up to v12
- int minNumOfElements=sizeof(RIL_SignalStrength_v6)/sizeof(int);
- int maxNumOfElements=sizeof(RIL_SignalStrength_v12)/sizeof(int);
- int response[maxNumOfElements];
-
- memset(response, 0, sizeof(response));
-
- err = at_send_command_singleline("AT+CSQ", "+CSQ:", &p_response);
-
- if (err < 0 || p_response->success == 0) {
- RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
- goto error;
- }
-
- line = p_response->p_intermediates->line;
-
- err = at_tok_start(&line);
- if (err < 0) goto error;
-
- for (count = 0; count < maxNumOfElements; count++) {
- err = at_tok_nextint(&line, &(response[count]));
- if (err < 0 && count < minNumOfElements) goto error;
- }
-
- RIL_onRequestComplete(t, RIL_E_SUCCESS, response, sizeof(response));
-
- at_response_free(p_response);
- return;
-
-error:
- RLOGE("requestSignalStrength must never return an error when radio is on");
- RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
- at_response_free(p_response);
-}
-
-/**
- * networkModePossible. Decides whether the network mode is appropriate for the
- * specified modem
- */
-static int networkModePossible(ModemInfo *mdm, int nm)
-{
- const int asize = sizeof(net2modem) / sizeof(net2modem[0]);
- if (nm >= asize || nm < 0) {
- RLOGW("%s %d: invalid net2modem index: %d", __func__, __LINE__, nm);
- return 0;
- }
- if ((net2modem[nm] & mdm->supportedTechs) == net2modem[nm]) {
- return 1;
- }
- return 0;
-}
-
-int getPreferredFromBitmap(int value, int *index) {
- for (unsigned int i = 0; i < sizeof(s_networkMask) / sizeof(NetworkTypeBitmap); i++) {
- if (s_networkMask[i].bitmap == value) {
- if (index) *index = i;
- return s_networkMask[i].type;
- }
- }
- // set default value here, since there is no match found
- // ref.
- //{LTE | GSM | WCDMA, MDM_LTE | MDM_GSM | MDM_WCDMA}, // 9 - LTE, GSM/WCDMA
- //
- const int DEFAULT_PREFERRED_INDEX = 9;
- const int DEFAULT_PREFERRED_BITMAP = MDM_LTE | MDM_GSM | MDM_WCDMA;
- assert(s_networkMask[DEFAULT_PREFERRED_INDEX] == DEFAULT_PREFERRED_BITMAP);
- if (index) {
- *index = DEFAULT_PREFERRED_INDEX;
- }
- RLOGD("getPreferredFromBitmap %d not match", value);
- return DEFAULT_PREFERRED_BITMAP;
-}
-
-unsigned getBitmapFromPreferred(int value) {
- for (unsigned int i = 0; i < sizeof(s_networkMask) / sizeof(NetworkTypeBitmap); i++) {
- if (s_networkMask[i].type == value) {
- return s_networkMask[i].bitmap;
- }
- }
- RLOGD("getBitmapFromPreferred %d not match", value);
- return LTE | GSM | WCDMA;
-}
-
-static void requestSetPreferredNetworkType(int request, void *data,
- size_t datalen __unused, RIL_Token t )
-{
- ATResponse *p_response = NULL;
- char *cmd = NULL;
- int value = *(int *)data;
- int index = value;
- int current, old;
- int err;
- int32_t preferred;
-
- if (request == RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE) {
- preferred = net2pmask[value];
- } else {
- preferred = getPreferredFromBitmap(value, &index);
- }
- RLOGD("requestSetPreferredNetworkType: current: %x. New: %x", PREFERRED_NETWORK(sMdmInfo), preferred);
-
- if (!networkModePossible(sMdmInfo, index)) {
- RIL_onRequestComplete(t, RIL_E_MODE_NOT_SUPPORTED, NULL, 0);
- return;
- }
-
- if (query_ctec(sMdmInfo, &current, NULL) < 0) {
- RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
- return;
- }
- old = PREFERRED_NETWORK(sMdmInfo);
- RLOGD("old != preferred: %d", old != preferred);
- if (old != preferred) {
- asprintf(&cmd, "AT+CTEC=%d,\"%x\"", current, preferred);
- RLOGD("Sending command: <%s>", cmd);
- err = at_send_command_singleline(cmd, "+CTEC:", &p_response);
- free(cmd);
- if (err || !p_response->success) {
- RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
- return;
- }
- PREFERRED_NETWORK(sMdmInfo) = value;
- if (!strstr( p_response->p_intermediates->line, "DONE") ) {
- int current;
- int res = parse_technology_response(p_response->p_intermediates->line, &current, NULL);
- switch (res) {
- case -1: // Error or unable to parse
- break;
- case 1: // Only able to parse current
- case 0: // Both current and preferred were parsed
- setRadioTechnology(sMdmInfo, current);
- break;
- }
- }
- }
- RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
-}
-
-static void requestGetPreferredNetworkType(int request __unused, void *data __unused,
- size_t datalen __unused, RIL_Token t)
-{
- int preferred;
- unsigned i;
-
- switch ( query_ctec(sMdmInfo, NULL, &preferred) ) {
- case -1: // Error or unable to parse
- case 1: // Only able to parse current
- RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
- break;
- case 0: // Both current and preferred were parsed
- for ( i = 0 ; i < sizeof(net2pmask) / sizeof(int32_t) ; i++ ) {
- if (preferred == net2pmask[i]) {
- goto done;
- }
- }
- RLOGE("Unknown preferred mode received from modem: %d", preferred);
- RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
- return;
- }
-done:
- if (request == RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE_BITMAP ||
- request == RIL_REQUEST_GET_ALLOWED_NETWORK_TYPES_BITMAP) {
- i = getBitmapFromPreferred(preferred);
- }
- RIL_onRequestComplete(t, RIL_E_SUCCESS, &i, sizeof(i));
-}
-
-static void requestCdmaPrlVersion(int request __unused, void *data __unused,
- size_t datalen __unused, RIL_Token t)
-{
- int err;
- char * responseStr;
- ATResponse *p_response = NULL;
- const char *cmd;
- char *line;
-
- err = at_send_command_singleline("AT+WPRL?", "+WPRL:", &p_response);
- if (err < 0 || !p_response->success) goto error;
- line = p_response->p_intermediates->line;
- err = at_tok_start(&line);
- if (err < 0) goto error;
- err = at_tok_nextstr(&line, &responseStr);
- if (err < 0 || !responseStr) goto error;
- RIL_onRequestComplete(t, RIL_E_SUCCESS, responseStr, strlen(responseStr));
- at_response_free(p_response);
- return;
-error:
- at_response_free(p_response);
- RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
-}
-
-static void requestCdmaBaseBandVersion(int request __unused, void *data __unused,
- size_t datalen __unused, RIL_Token t)
-{
- int err;
- char * responseStr;
- ATResponse *p_response = NULL;
- const char *cmd;
- const char *prefix;
- char *line, *p;
- int commas;
- int skip;
- int count = 4;
-
- // Fixed values. TODO: query modem
- responseStr = strdup("1.0.0.0");
- RIL_onRequestComplete(t, RIL_E_SUCCESS, responseStr, sizeof(responseStr));
- free(responseStr);
-}
-
-static void requestDeviceIdentity(int request __unused, void *data __unused,
- size_t datalen __unused, RIL_Token t)
-{
- int err;
- int response[4];
- char * responseStr[4];
- ATResponse *p_response = NULL;
- const char *cmd;
- const char *prefix;
- char *line, *p;
- int commas;
- int skip;
- int count = 4;
-
- // Fixed values. TODO: Query modem
- responseStr[0] = "----";
- responseStr[1] = "----";
- responseStr[2] = "77777777";
- responseStr[3] = ""; // default empty for non-CDMA
-
- err = at_send_command_numeric("AT+CGSN", &p_response);
- if (err < 0 || p_response->success == 0) {
- RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
- return;
- } else {
- if (TECH_BIT(sMdmInfo) == MDM_CDMA) {
- responseStr[3] = p_response->p_intermediates->line;
- } else {
- responseStr[0] = p_response->p_intermediates->line;
- }
- }
-
- RIL_onRequestComplete(t, RIL_E_SUCCESS, responseStr, count*sizeof(char*));
- at_response_free(p_response);
-}
-
-static void requestCdmaGetSubscriptionSource(int request __unused, void *data,
- size_t datalen __unused, RIL_Token t)
-{
- int err;
- int *ss = (int *)data;
- ATResponse *p_response = NULL;
- char *cmd = NULL;
- char *line = NULL;
- int response;
-
- asprintf(&cmd, "AT+CCSS?");
- if (!cmd) goto error;
-
- err = at_send_command_singleline(cmd, "+CCSS:", &p_response);
- if (err < 0 || !p_response->success)
- goto error;
-
- line = p_response->p_intermediates->line;
- err = at_tok_start(&line);
- if (err < 0) goto error;
-
- err = at_tok_nextint(&line, &response);
- free(cmd);
- cmd = NULL;
-
- RIL_onRequestComplete(t, RIL_E_SUCCESS, &response, sizeof(response));
-
- return;
-error:
- free(cmd);
- RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
-}
-
-static void requestCdmaSetSubscriptionSource(int request __unused, void *data,
- size_t datalen, RIL_Token t)
-{
- int err;
- int *ss = (int *)data;
- ATResponse *p_response = NULL;
- char *cmd = NULL;
-
- if (!ss || !datalen) {
- RLOGE("RIL_REQUEST_CDMA_SET_SUBSCRIPTION without data!");
- RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
- return;
- }
- asprintf(&cmd, "AT+CCSS=%d", ss[0]);
- if (!cmd) goto error;
-
- err = at_send_command(cmd, &p_response);
- if (err < 0 || !p_response->success)
- goto error;
- free(cmd);
- cmd = NULL;
-
- RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
-
- RIL_onUnsolicitedResponse(RIL_UNSOL_CDMA_SUBSCRIPTION_SOURCE_CHANGED, ss, sizeof(ss[0]));
-
- return;
-error:
- free(cmd);
- RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
-}
-
-static void requestCdmaSubscription(int request __unused, void *data __unused,
- size_t datalen __unused, RIL_Token t)
-{
- int err;
- int response[5];
- char * responseStr[5];
- ATResponse *p_response = NULL;
- const char *cmd;
- const char *prefix;
- char *line, *p;
- int commas;
- int skip;
- int count = 5;
-
- // Fixed values. TODO: Query modem
- responseStr[0] = "8587777777"; // MDN
- responseStr[1] = "1"; // SID
- responseStr[2] = "1"; // NID
- responseStr[3] = "8587777777"; // MIN
- responseStr[4] = "1"; // PRL Version
- RIL_onRequestComplete(t, RIL_E_SUCCESS, responseStr, count*sizeof(char*));
-}
-
-static void requestCdmaGetRoamingPreference(int request __unused, void *data __unused,
- size_t datalen __unused, RIL_Token t)
-{
- int roaming_pref = -1;
- ATResponse *p_response = NULL;
- char *line;
- int res;
-
- res = at_send_command_singleline("AT+WRMP?", "+WRMP:", &p_response);
- if (res < 0 || !p_response->success) {
- goto error;
- }
- line = p_response->p_intermediates->line;
-
- res = at_tok_start(&line);
- if (res < 0) goto error;
-
- res = at_tok_nextint(&line, &roaming_pref);
- if (res < 0) goto error;
-
- RIL_onRequestComplete(t, RIL_E_SUCCESS, &roaming_pref, sizeof(roaming_pref));
- return;
-error:
- RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
-}
-
-static void requestCdmaSetRoamingPreference(int request __unused, void *data,
- size_t datalen __unused, RIL_Token t)
-{
- int *pref = (int *)data;
- ATResponse *p_response = NULL;
- char *line;
- int res;
- char *cmd = NULL;
-
- asprintf(&cmd, "AT+WRMP=%d", *pref);
- if (cmd == NULL) goto error;
-
- res = at_send_command(cmd, &p_response);
- if (res < 0 || !p_response->success)
- goto error;
-
- RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
- free(cmd);
- return;
-error:
- free(cmd);
- RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
-}
-
-static int parseRegistrationState(char *str, int *type, int *items, int **response)
-{
- int err;
- char *line = str, *p;
- int *resp = NULL;
- int skip;
- int count = 3;
- int commas;
-
- RLOGD("parseRegistrationState. Parsing: %s",str);
- err = at_tok_start(&line);
- if (err < 0) goto error;
-
- /* Ok you have to be careful here
- * The solicited version of the CREG response is
- * +CREG: n, stat, [lac, cid]
- * and the unsolicited version is
- * +CREG: stat, [lac, cid]
- * The <n> parameter is basically "is unsolicited creg on?"
- * which it should always be
- *
- * Now we should normally get the solicited version here,
- * but the unsolicited version could have snuck in
- * so we have to handle both
- *
- * Also since the LAC and CID are only reported when registered,
- * we can have 1, 2, 3, or 4 arguments here
- *
- * finally, a +CGREG: answer may have a fifth value that corresponds
- * to the network type, as in;
- *
- * +CGREG: n, stat [,lac, cid [,networkType]]
- */
-
- /* count number of commas */
- commas = 0;
- for (p = line ; *p != '\0' ;p++) {
- if (*p == ',') commas++;
- }
-
- resp = (int *)calloc(commas + 1, sizeof(int));
- if (!resp) goto error;
- switch (commas) {
- case 0: /* +CREG: <stat> */
- err = at_tok_nextint(&line, &resp[0]);
- if (err < 0) goto error;
- resp[1] = -1;
- resp[2] = -1;
- break;
-
- case 1: /* +CREG: <n>, <stat> */
- err = at_tok_nextint(&line, &skip);
- if (err < 0) goto error;
- err = at_tok_nextint(&line, &resp[0]);
- if (err < 0) goto error;
- resp[1] = -1;
- resp[2] = -1;
- if (err < 0) goto error;
- break;
-
- case 2: /* +CREG: <stat>, <lac>, <cid> */
- err = at_tok_nextint(&line, &resp[0]);
- if (err < 0) goto error;
- err = at_tok_nexthexint(&line, &resp[1]);
- if (err < 0) goto error;
- err = at_tok_nexthexint(&line, &resp[2]);
- if (err < 0) goto error;
- break;
- case 3: /* +CREG: <n>, <stat>, <lac>, <cid> */
- err = at_tok_nextint(&line, &skip);
- if (err < 0) goto error;
- err = at_tok_nextint(&line, &resp[0]);
- if (err < 0) goto error;
- err = at_tok_nexthexint(&line, &resp[1]);
- if (err < 0) goto error;
- err = at_tok_nexthexint(&line, &resp[2]);
- if (err < 0) goto error;
- break;
- /* special case for CGREG, there is a fourth parameter
- * that is the network type (unknown/gprs/edge/umts)
- */
- case 4: /* +CGREG: <n>, <stat>, <lac>, <cid>, <networkType> */
- err = at_tok_nextint(&line, &skip);
- if (err < 0) goto error;
- err = at_tok_nextint(&line, &resp[0]);
- if (err < 0) goto error;
- err = at_tok_nexthexint(&line, &resp[1]);
- if (err < 0) goto error;
- err = at_tok_nexthexint(&line, &resp[2]);
- if (err < 0) goto error;
- err = at_tok_nextint(&line, &resp[3]);
- if (err < 0) goto error;
- count = 4;
- break;
- default:
- goto error;
- }
- s_lac = resp[1];
- s_cid = resp[2];
- if (response)
- *response = resp;
- if (items)
- *items = commas + 1;
- if (type)
- *type = techFromModemType(TECH(sMdmInfo));
- return 0;
-error:
- free(resp);
- return -1;
-}
-
-static int mapNetworkRegistrationResponse(int in_response) {
- int out_response = 0;
-
- switch (in_response) {
- case 0:
- out_response = RADIO_TECH_GPRS; /* GPRS */
- break;
- case 3:
- out_response = RADIO_TECH_EDGE; /* EDGE */
- break;
- case 2:
- out_response = RADIO_TECH_UMTS; /* TD */
- break;
- case 4:
- out_response = RADIO_TECH_HSDPA; /* HSDPA */
- break;
- case 5:
- out_response = RADIO_TECH_HSUPA; /* HSUPA */
- break;
- case 6:
- out_response = RADIO_TECH_HSPA; /* HSPA */
- break;
- case 15:
- out_response = RADIO_TECH_HSPAP; /* HSPA+ */
- break;
- case 7:
- out_response = RADIO_TECH_LTE; /* LTE */
- break;
- case 16:
- out_response = RADIO_TECH_LTE_CA; /* LTE_CA */
- break;
- case 11: // NR connected to a 5GCN
- case 12: // NG-RAN
- case 13: // E-UTRA-NR dual connectivity
- out_response = RADIO_TECH_NR; /* NR */
- break;
- default:
- out_response = RADIO_TECH_UNKNOWN; /* UNKNOWN */
- break;
- }
- return out_response;
-}
-
-#define REG_STATE_LEN 18
-#define REG_DATA_STATE_LEN 14
-static void requestRegistrationState(int request, void *data __unused,
- size_t datalen __unused, RIL_Token t)
-{
- int err;
- int *registration;
- char **responseStr = NULL;
- ATResponse *p_response = NULL;
- const char *cmd;
- const char *prefix;
- char *line;
- int i = 0, j, numElements = 0;
- int count = 3;
- int type, startfrom;
-
- RLOGD("requestRegistrationState");
- if (request == RIL_REQUEST_VOICE_REGISTRATION_STATE) {
- cmd = "AT+CREG?";
- prefix = "+CREG:";
- numElements = REG_STATE_LEN;
- } else if (request == RIL_REQUEST_DATA_REGISTRATION_STATE) {
- cmd = "AT+CGREG?";
- prefix = "+CGREG:";
- numElements = REG_DATA_STATE_LEN;
- if (TECH_BIT(sMdmInfo) == MDM_LTE) {
- cmd = "AT+CEREG?";
- prefix = "+CEREG:";
- }
- } else {
- assert(0);
- goto error;
- }
-
- err = at_send_command_singleline(cmd, prefix, &p_response);
-
- if (err < 0 || !p_response->success) goto error;
-
- line = p_response->p_intermediates->line;
-
- if (parseRegistrationState(line, &type, &count, &registration)) goto error;
-
- responseStr = malloc(numElements * sizeof(char *));
- if (!responseStr) goto error;
- memset(responseStr, 0, numElements * sizeof(char *));
- /**
- * The first '4' bytes for both registration states remain the same.
- * But if the request is 'DATA_REGISTRATION_STATE',
- * the 5th and 6th byte(s) are optional.
- */
- if (is3gpp2(type) == 1) {
- RLOGD("registration state type: 3GPP2");
- // TODO: Query modem
- startfrom = 3;
- if(request == RIL_REQUEST_VOICE_REGISTRATION_STATE) {
- asprintf(&responseStr[3], "8"); // EvDo revA
- asprintf(&responseStr[4], "1"); // BSID
- asprintf(&responseStr[5], "123"); // Latitude
- asprintf(&responseStr[6], "222"); // Longitude
- asprintf(&responseStr[7], "0"); // CSS Indicator
- asprintf(&responseStr[8], "4"); // SID
- asprintf(&responseStr[9], "65535"); // NID
- asprintf(&responseStr[10], "0"); // Roaming indicator
- asprintf(&responseStr[11], "1"); // System is in PRL
- asprintf(&responseStr[12], "0"); // Default Roaming indicator
- asprintf(&responseStr[13], "0"); // Reason for denial
- asprintf(&responseStr[14], "0"); // Primary Scrambling Code of Current cell
- } else if (request == RIL_REQUEST_DATA_REGISTRATION_STATE) {
- asprintf(&responseStr[3], "8"); // Available data radio technology
- }
- } else { // type == RADIO_TECH_3GPP
- RLOGD("registration state type: 3GPP");
- startfrom = 0;
- asprintf(&responseStr[1], "%x", registration[1]);
- asprintf(&responseStr[2], "%x", registration[2]);
- if (count > 3) {
- asprintf(&responseStr[3], "%d", mapNetworkRegistrationResponse(registration[3]));
- }
- }
- asprintf(&responseStr[0], "%d", registration[0]);
-
- /**
- * Optional bytes for DATA_REGISTRATION_STATE request
- * 4th byte : Registration denial code
- * 5th byte : The max. number of simultaneous Data Calls
- */
- if (request == RIL_REQUEST_DATA_REGISTRATION_STATE) {
- // asprintf(&responseStr[4], "3");
- // asprintf(&responseStr[5], "1");
- asprintf(&responseStr[11], "%d", s_mcc);
- asprintf(&responseStr[12], "%d", s_mnc);
- if (s_mncLength == 2) {
- asprintf(&responseStr[13], "%03d%02d", s_mcc, s_mnc);
- } else {
- asprintf(&responseStr[13], "%03d%03d", s_mcc, s_mnc);
- }
- } else { // Voice
- asprintf(&responseStr[15], "%d", s_mcc);
- asprintf(&responseStr[16], "%d", s_mnc);
- if (s_mncLength == 2) {
- asprintf(&responseStr[17], "%03d%02d", s_mcc, s_mnc);
- } else {
- asprintf(&responseStr[17], "%03d%03d", s_mcc, s_mnc);
- }
- }
-
-
- for (j = startfrom; j < numElements; j++) {
- if (!responseStr[i]) goto error;
- }
- free(registration);
- registration = NULL;
- RIL_onRequestComplete(t, RIL_E_SUCCESS, responseStr, numElements*sizeof(responseStr));
- for (j = 0; j < numElements; j++ ) {
- free(responseStr[j]);
- responseStr[j] = NULL;
- }
- free(responseStr);
- responseStr = NULL;
- at_response_free(p_response);
-
- return;
-error:
- if (responseStr) {
- for (j = 0; j < numElements; j++) {
- free(responseStr[j]);
- responseStr[j] = NULL;
- }
- free(responseStr);
- responseStr = NULL;
- }
- RLOGE("requestRegistrationState must never return an error when radio is on");
- RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
- at_response_free(p_response);
-}
-
-static void requestOperator(void *data __unused, size_t datalen __unused, RIL_Token t)
-{
- int err;
- int i;
- int skip;
- ATLine *p_cur;
- char *response[3];
-
- memset(response, 0, sizeof(response));
-
- ATResponse *p_response = NULL;
-
- err = at_send_command_multiline(
- "AT+COPS=3,0;+COPS?;+COPS=3,1;+COPS?;+COPS=3,2;+COPS?",
- "+COPS:", &p_response);
-
- /* we expect 3 lines here:
- * +COPS: 0,0,"T - Mobile"
- * +COPS: 0,1,"TMO"
- * +COPS: 0,2,"310170"
- */
-
- if (err != 0) goto error;
-
- for (i = 0, p_cur = p_response->p_intermediates
- ; p_cur != NULL
- ; p_cur = p_cur->p_next, i++
- ) {
- char *line = p_cur->line;
-
- err = at_tok_start(&line);
- if (err < 0) goto error;
-
- err = at_tok_nextint(&line, &skip);
- if (err < 0) goto error;
-
- // If we're unregistered, we may just get
- // a "+COPS: 0" response
- if (!at_tok_hasmore(&line)) {
- response[i] = NULL;
- continue;
- }
-
- err = at_tok_nextint(&line, &skip);
- if (err < 0) goto error;
-
- // a "+COPS: 0, n" response is also possible
- if (!at_tok_hasmore(&line)) {
- response[i] = NULL;
- continue;
- }
-
- err = at_tok_nextstr(&line, &(response[i]));
- if (err < 0) goto error;
- // Simple assumption that mcc and mnc are 3 digits each
- int length = strlen(response[i]);
- if (length == 6) {
- s_mncLength = 3;
- if (sscanf(response[i], "%3d%3d", &s_mcc, &s_mnc) != 2) {
- RLOGE("requestOperator expected mccmnc to be 6 decimal digits");
- }
- } else if (length == 5) {
- s_mncLength = 2;
- if (sscanf(response[i], "%3d%2d", &s_mcc, &s_mnc) != 2) {
- RLOGE("requestOperator expected mccmnc to be 5 decimal digits");
- }
- }
- }
-
- if (i != 3) {
- /* expect 3 lines exactly */
- goto error;
- }
-
- RIL_onRequestComplete(t, RIL_E_SUCCESS, response, sizeof(response));
- at_response_free(p_response);
-
- return;
-error:
- RLOGE("requestOperator must not return error when radio is on");
- s_mncLength = 0;
- s_mcc = 0;
- s_mnc = 0;
- RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
- at_response_free(p_response);
-}
-
-static void requestCdmaSendSMS(void *data, size_t datalen, RIL_Token t)
-{
- int err = 1; // Set to go to error:
- RIL_SMS_Response response;
- RIL_CDMA_SMS_Message* rcsm;
-
- memset(&response, 0, sizeof(response));
-
- if (getSIMStatus() == SIM_ABSENT) {
- RIL_onRequestComplete(t, RIL_E_SIM_ABSENT, NULL, 0);
- return;
- }
-
- RLOGD("requestCdmaSendSMS datalen=%zu, sizeof(RIL_CDMA_SMS_Message)=%zu",
- datalen, sizeof(RIL_CDMA_SMS_Message));
-
- // verify data content to test marshalling/unmarshalling:
- rcsm = (RIL_CDMA_SMS_Message*)data;
- RLOGD("TeleserviceID=%d, bIsServicePresent=%d, \
- uServicecategory=%d, sAddress.digit_mode=%d, \
- sAddress.Number_mode=%d, sAddress.number_type=%d, ",
- rcsm->uTeleserviceID, rcsm->bIsServicePresent,
- rcsm->uServicecategory,rcsm->sAddress.digit_mode,
- rcsm->sAddress.number_mode,rcsm->sAddress.number_type);
-
- if (err != 0) goto error;
-
- // Cdma Send SMS implementation will go here:
- // But it is not implemented yet.
-
- response.messageRef = 1;
- RIL_onRequestComplete(t, RIL_E_SUCCESS, &response, sizeof(response));
- return;
-
-error:
- // Cdma Send SMS will always cause send retry error.
- response.messageRef = -1;
- RIL_onRequestComplete(t, RIL_E_SMS_SEND_FAIL_RETRY, &response, sizeof(response));
-}
-
-static void requestSendSMS(void *data, size_t datalen, RIL_Token t)
-{
- int err;
- const char *smsc;
- const char *pdu;
- int tpLayerLength;
- char *cmd1, *cmd2;
- RIL_SMS_Response response;
- ATResponse *p_response = NULL;
-
- if (getSIMStatus() == SIM_ABSENT) {
- RIL_onRequestComplete(t, RIL_E_SIM_ABSENT, NULL, 0);
- return;
- }
-
- memset(&response, 0, sizeof(response));
- RLOGD("requestSendSMS datalen =%zu", datalen);
-
- if (s_ims_gsm_fail != 0) goto error;
- if (s_ims_gsm_retry != 0) goto error2;
-
- smsc = ((const char **)data)[0];
- pdu = ((const char **)data)[1];
-
- tpLayerLength = strlen(pdu)/2;
-
- // "NULL for default SMSC"
- if (smsc == NULL) {
- smsc= "00";
- }
-
- asprintf(&cmd1, "AT+CMGS=%d", tpLayerLength);
- asprintf(&cmd2, "%s%s", smsc, pdu);
-
- err = at_send_command_sms(cmd1, cmd2, "+CMGS:", &p_response);
-
- free(cmd1);
- free(cmd2);
-
- if (err != 0 || p_response->success == 0) goto error;
-
- int messageRef = 1;
- char *line = p_response->p_intermediates->line;
-
- err = at_tok_start(&line);
- if (err < 0) goto error;
-
- err = at_tok_nextint(&line, &messageRef);
- if (err < 0) goto error;
-
- /* FIXME fill in ackPDU */
- response.messageRef = messageRef;
- RIL_onRequestComplete(t, RIL_E_SUCCESS, &response, sizeof(response));
- at_response_free(p_response);
-
- return;
-error:
- response.messageRef = -2;
- RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, &response, sizeof(response));
- at_response_free(p_response);
- return;
-error2:
- // send retry error.
- response.messageRef = -1;
- RIL_onRequestComplete(t, RIL_E_SMS_SEND_FAIL_RETRY, &response, sizeof(response));
- at_response_free(p_response);
- return;
-}
-
-static void requestImsSendSMS(void *data, size_t datalen, RIL_Token t)
-{
- RIL_IMS_SMS_Message *p_args;
- RIL_SMS_Response response;
-
- memset(&response, 0, sizeof(response));
-
- RLOGD("requestImsSendSMS: datalen=%zu, "
- "registered=%d, service=%d, format=%d, ims_perm_fail=%d, "
- "ims_retry=%d, gsm_fail=%d, gsm_retry=%d",
- datalen, s_ims_registered, s_ims_services, s_ims_format,
- s_ims_cause_perm_failure, s_ims_cause_retry, s_ims_gsm_fail,
- s_ims_gsm_retry);
-
- // figure out if this is gsm/cdma format
- // then route it to requestSendSMS vs requestCdmaSendSMS respectively
- p_args = (RIL_IMS_SMS_Message *)data;
-
- if (0 != s_ims_cause_perm_failure ) goto error;
-
- // want to fail over ims and this is first request over ims
- if (0 != s_ims_cause_retry && 0 == p_args->retry) goto error2;
-
- if (RADIO_TECH_3GPP == p_args->tech) {
- return requestSendSMS(p_args->message.gsmMessage,
- datalen - sizeof(RIL_RadioTechnologyFamily),
- t);
- } else if (RADIO_TECH_3GPP2 == p_args->tech) {
- return requestCdmaSendSMS(p_args->message.cdmaMessage,
- datalen - sizeof(RIL_RadioTechnologyFamily),
- t);
- } else {
- RLOGE("requestImsSendSMS invalid format value =%d", p_args->tech);
- }
-
-error:
- response.messageRef = -2;
- RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, &response, sizeof(response));
- return;
-
-error2:
- response.messageRef = -1;
- RIL_onRequestComplete(t, RIL_E_SMS_SEND_FAIL_RETRY, &response, sizeof(response));
-}
-
-/**
- * Add for CTS test
- * If open logical channel with AID NULL, this means open logical channel to MF.
- * If there is P2 value, this P2 value is used for SELECT command.
- * In addition, if SELECT command returns 61xx, GET RESPONSE command needs to send to get data.
- */
-static int sendCmdAgainForOpenChannelWithP2( char *data,
- int p2, int *response, int *rspLen) {
- int len = 0;
- int err = -1;
- char *line = NULL;
- char cmd[64] = {0};
- RIL_Errno errType = RIL_E_GENERIC_FAILURE;
- ATResponse *p_response = NULL;
- RIL_SIM_IO_Response sr;
-
- memset(&sr, 0, sizeof(sr));
- sscanf(data, "%2x", &(response[0])); // response[0] is channel number
-
- // Send SELECT command to MF
- snprintf(cmd, sizeof(cmd), "AT+CGLA=%d,14,00A400%02X023F00", response[0],
- p2);
-
- err = at_send_command_singleline(cmd, "+CGLA:", &p_response);
- if (err < 0) goto done;
- if (p_response->success == 0) {
- if (!strcmp(p_response->finalResponse, "+CME ERROR: 21") ||
- !strcmp(p_response->finalResponse, "+CME ERROR: 50")) {
- errType = RIL_E_GENERIC_FAILURE;
- }
- goto done;
- }
-
- line = p_response->p_intermediates->line;
-
- if (at_tok_start(&line) < 0 || at_tok_nextint(&line, &len) < 0 ||
- at_tok_nextstr(&line, &(sr.simResponse)) < 0) {
- goto done;
- }
-
- sscanf(&(sr.simResponse[len - 4]), "%02x%02x", &(sr.sw1), &(sr.sw2));
-
- if (sr.sw1 == 0x90 && sr.sw2 == 0x00) { // 9000 is successful
- int length = len / 2;
- for (*rspLen = 1; *rspLen <= length; (*rspLen)++) {
- sscanf(sr.simResponse, "%02x", &(response[*rspLen]));
- sr.simResponse += 2;
- }
- errType = RIL_E_SUCCESS;
- } else { // close channel
- snprintf(cmd, sizeof(cmd), "AT+CCHC=%d", response[0]);
- at_send_command( cmd, NULL);
- }
-
-done:
- at_response_free(p_response);
- return errType;
-}
-
-static void requestSimOpenChannel(void *data, size_t datalen, RIL_Token t)
-{
- RIL_UNUSED_PARM(datalen);
-
- ATResponse *p_response = NULL;
- int response[260] = {0};
- int responseLen = 1;
- int32_t session_id;
- int err;
- char cmd[64] = {0};
- char complex;
- char *line = NULL;
- int skip = 0;
- char *statusWord = NULL;
- int err_no = RIL_E_GENERIC_FAILURE;
-
- RIL_OpenChannelParams *params = (RIL_OpenChannelParams *)data;
-
- // Max length is 16 bytes according to 3GPP spec 27.007 section 8.45
- if (params->aidPtr == NULL) {
- err = at_send_command_singleline("AT+CSIM=10,\"0070000001\"", "+CSIM:", &p_response);
- } else {
- snprintf(cmd, sizeof(cmd), "AT+CCHO=%s", params->aidPtr);
- err = at_send_command_numeric(cmd, &p_response);
- }
-
- if (err < 0 || p_response == NULL || p_response->success == 0) {
- ALOGE("Error %d opening logical channel: %d",
- err, p_response ? p_response->success : 0);
- goto error;
- }
-
- // Ensure integer only by scanning for an extra char but expect one result
- line = p_response->p_intermediates->line;
- if (params->aidPtr == NULL) {
-
- err = at_tok_start(&line);
- if (err < 0) goto error;
-
- err = at_tok_nextint(&line, &skip);
- if (err < 0) goto error;
-
- err = at_tok_nextstr(&line, &statusWord);
- if (err < 0) goto error;
-
- if (params->p2 < 0) {
- int length = strlen(statusWord) / 2;
- for (responseLen = 0; responseLen < length; responseLen++) {
- sscanf(statusWord, "%02x", &(response[responseLen]));
- statusWord += 2;
- }
- err_no = RIL_E_SUCCESS;
- } else {
- response[0] = 1;
- err_no = sendCmdAgainForOpenChannelWithP2(statusWord,
- params->p2, response, &responseLen);
- if (err_no != RIL_E_SUCCESS) {
- goto error;
- }
- }
- RIL_onRequestComplete(t, err_no, response, responseLen * sizeof(int));
- at_response_free(p_response);
- return;
- } else {
- if (sscanf(line, "%" SCNd32 "%c", &session_id, &complex) != 1) {
- ALOGE("Invalid AT response, expected integer, was '%s'", line);
- goto error;
- }
- }
-
- RIL_onRequestComplete(t, RIL_E_SUCCESS, &session_id, sizeof(session_id));
- at_response_free(p_response);
- return;
-
-error:
- RIL_onRequestComplete(t, err_no, NULL, 0);
- at_response_free(p_response);
- return;
-}
-
-static void requestSimCloseChannel(void *data, size_t datalen, RIL_Token t)
-{
- ATResponse *p_response = NULL;
- int32_t session_id;
- int err;
- char cmd[32];
-
- if (data == NULL || datalen != sizeof(session_id)) {
- ALOGE("Invalid data passed to requestSimCloseChannel");
- RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
- return;
- }
- session_id = ((int32_t *)data)[0];
- if (session_id == 0) {
- RIL_onRequestComplete(t, RIL_E_INVALID_ARGUMENTS, NULL, 0);
- return;
- }
-
- snprintf(cmd, sizeof(cmd), "AT+CCHC=%" PRId32, session_id);
- err = at_send_command_singleline(cmd, "+CCHC", &p_response);
-
- if (err < 0 || p_response == NULL || p_response->success == 0) {
- ALOGE("Error %d closing logical channel %d: %d",
- err, session_id, p_response ? p_response->success : 0);
- RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
- at_response_free(p_response);
- return;
- }
-
- RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
-
- at_response_free(p_response);
-}
-
-static void requestSimTransmitApduChannel(void *data,
- size_t datalen,
- RIL_Token t)
-{
- ATResponse *p_response = NULL;
- int err;
- int len = 0;
- char *cmd;
- char *line = NULL;
- size_t cmd_size;
- RIL_SIM_IO_Response sr = {0};
- RIL_SIM_APDU *apdu = (RIL_SIM_APDU *)data;
-
- if (apdu == NULL || datalen != sizeof(RIL_SIM_APDU)) {
- RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
- return;
- }
-
- cmd_size = 10 + (apdu->data ? strlen(apdu->data) : 0);
- asprintf(&cmd, "AT+CGLA=%d,%zu,%02x%02x%02x%02x%02x%s",
- apdu->sessionid, cmd_size, apdu->cla, apdu->instruction,
- apdu->p1, apdu->p2, apdu->p3, apdu->data ? apdu->data : "");
-
- err = at_send_command_singleline(cmd, "+CGLA:", &p_response);
- free(cmd);
- if (err < 0 || p_response == NULL || p_response->success == 0) {
- ALOGE("Error %d transmitting APDU: %d",
- err, p_response ? p_response->success : 0);
- goto error;
- }
-
- line = p_response->p_intermediates->line;
- err = at_tok_start(&line);
- if (err < 0) goto error;
-
- err = at_tok_nextint(&line, &len);
- if (err < 0) goto error;
-
- err = at_tok_nextstr(&line, &(sr.simResponse));
- if (err < 0) goto error;
-
- len = strlen(sr.simResponse);
- if (len < 4) goto error;
-
- sscanf(&(sr.simResponse[len - 4]), "%02x%02x", &(sr.sw1), &(sr.sw2));
- sr.simResponse[len - 4] = '\0';
-
- RIL_onRequestComplete(t, RIL_E_SUCCESS, &sr, sizeof(sr));
- at_response_free(p_response);
- return;
-
-error:
- RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
- at_response_free(p_response);
-}
-
-static void requestSimAuthentication(int authContext, char* authData, RIL_Token t) {
- int err = -1, ret = 0;
- int status = 0;
- int binSimResponseLen = 0;
- char *cmd = NULL;
- char *line = NULL;
- // Input data
- int randLen = 0, autnLen = 0;
- char *rand = NULL, *autn = NULL;
- // EAP-SIM response data
- int kcLen = 0, sresLen = 0;
- char *kc = NULL, *sres = NULL;
- // EAP-AKA response data
- int ckLen = 0, ikLen = 0, resAutsLen = 0;
- char *ck = NULL, *ik = NULL, *resAuts = NULL;
- unsigned char *binSimResponse = NULL;
- unsigned char *binAuthData = NULL;
- unsigned char *hexAuthData = NULL;
- ATResponse *p_response = NULL;
- RIL_SIM_IO_Response response;
-
- memset(&response, 0, sizeof(response));
- response.sw1 = 0x90;
- response.sw2 = 0;
-
- binAuthData =
- (unsigned char *)malloc(sizeof(*binAuthData) * strlen(authData));
- if (binAuthData == NULL) {
- goto error;
- }
- if(base64_decode(authData, binAuthData) <= 0) {
- RLOGE("base64_decode failed %s %d", __func__, __LINE__);
- goto error;
- }
- hexAuthData =
- (unsigned char *)malloc(strlen(authData) * 2 + sizeof(char));
- if (hexAuthData == NULL) {
- goto error;
- }
- memset(hexAuthData, 0, strlen(authData) * 2 + sizeof(char));
- convertBytesToHexString((char *)binAuthData, strlen(authData), hexAuthData);
-
- randLen = binAuthData[0];
- rand = (char *)malloc(sizeof(char) * (randLen * 2 + sizeof(char)));
- if (rand == NULL) {
- goto error;
- }
- memcpy(rand, hexAuthData + 2, randLen * 2);
- memcpy(rand + randLen * 2, "\0", 1);
-
- if (authContext == AUTH_CONTEXT_EAP_AKA) {
- // There's the autn value to parse as well.
- autnLen = binAuthData[1 + randLen];
- autn = (char*)malloc(sizeof(char) * (autnLen * 2 + sizeof(char)));
- if (autn == NULL) {
- goto error;
- }
- memcpy(autn, hexAuthData + 2 + randLen * 2 + 2, autnLen * 2);
- memcpy(autn + autnLen * 2, "\0", 1);
- }
-
- if (authContext == AUTH_CONTEXT_EAP_SIM) {
- ret = asprintf(&cmd, "AT^MBAU=\"%s\"", rand);
- } else {
- ret = asprintf(&cmd, "AT^MBAU=\"%s,%s\"", rand, autn);
- }
- if (ret < 0) {
- RLOGE("Failed to asprintf");
- goto error;
- }
- err = at_send_command_singleline( cmd, "^MBAU:", &p_response);
- free(cmd);
-
- if (err < 0 || p_response->success == 0) {
- goto error;
- }
- line = p_response->p_intermediates->line;
- err = at_tok_start(&line);
- if (err < 0) goto error;
-
- err = at_tok_nextint(&line, &status);
- if (err < 0) goto error;
- if (status != SIM_AUTH_RESPONSE_SUCCESS) {
- goto error;
- }
-
- if (authContext == AUTH_CONTEXT_EAP_SIM) {
- err = at_tok_nextstr(&line, &kc);
- if (err < 0) goto error;
- kcLen = strlen(kc);
-
- err = at_tok_nextstr(&line, &sres);
- if (err < 0) goto error;
- sresLen = strlen(sres);
-
- // sresLen + sres + kcLen + kc + '\0'
- binSimResponseLen = (kcLen + sresLen) / 2 + 3 * sizeof(char);
- binSimResponse = (unsigned char*)malloc(binSimResponseLen + sizeof(char));
- if (binSimResponse == NULL) goto error;
- memset(binSimResponse, 0, binSimResponseLen);
- // set sresLen and sres
- binSimResponse[0] = (sresLen / 2) & 0xFF;
- uint8_t* tmpBinSimResponse = convertHexStringToBytes(sres, sresLen);
- snprintf((char*)(binSimResponse + 1), sresLen / 2, "%s", tmpBinSimResponse);
- free(tmpBinSimResponse);
- tmpBinSimResponse = NULL;
- // set kcLen and kc
- binSimResponse[1 + sresLen / 2] = (kcLen / 2) & 0xFF;
- tmpBinSimResponse = convertHexStringToBytes(kc, kcLen);
- snprintf((char*)(binSimResponse + 1 + sresLen / 2 + 1), kcLen / 2, "%s", tmpBinSimResponse);
- free(tmpBinSimResponse);
- tmpBinSimResponse = NULL;
- } else { // AUTH_CONTEXT_EAP_AKA
- err = at_tok_nextstr(&line, &ck);
- if (err < 0) goto error;
- ckLen = strlen(ck);
-
- err = at_tok_nextstr(&line, &ik);
- if (err < 0) goto error;
- ikLen = strlen(ik);
-
- err = at_tok_nextstr(&line, &resAuts);
- if (err < 0) goto error;
- resAutsLen = strlen(resAuts);
-
- // 0xDB + ckLen + ck + ikLen + ik + resAutsLen + resAuts + '\0'
- binSimResponseLen = (ckLen + ikLen + resAutsLen) / 2 + 5 * sizeof(char);
- binSimResponse = (unsigned char*)malloc(binSimResponseLen + sizeof(char));
- if (binSimResponse == NULL) goto error;
- memset(binSimResponse, 0, binSimResponseLen);
- // The DB prefix indicates successful auth. Not produced by the SIM.
- binSimResponse[0] = 0xDB;
- // Set ckLen and ck
- binSimResponse[1] = (ckLen / 2) & 0xFF;
- uint8_t* tmpBinSimResponse = convertHexStringToBytes(ck, ckLen);
- snprintf((char*)(binSimResponse + 2), ckLen / 2 + 1, "%s", tmpBinSimResponse);
- free(tmpBinSimResponse);
- tmpBinSimResponse = NULL;
- // Set ikLen and ik
- binSimResponse[2 + ckLen / 2] = (ikLen / 2) & 0xFF;
- tmpBinSimResponse = convertHexStringToBytes(ik, ikLen);
- snprintf((char*)(binSimResponse + 2 + ckLen / 2 + 1), ikLen / 2 + 1, "%s",
- tmpBinSimResponse);
- free(tmpBinSimResponse);
- tmpBinSimResponse = NULL;
- // Set resAutsLen and resAuts
- binSimResponse[2 + ckLen / 2 + 1 + ikLen / 2] = (resAutsLen / 2) & 0xFF;
- tmpBinSimResponse = convertHexStringToBytes(resAuts, resAutsLen);
- snprintf((char*)(binSimResponse + 2 + ckLen / 2 + 1 + ikLen / 2 + 1), resAutsLen / 2 + 1,
- "%s", tmpBinSimResponse);
- free(tmpBinSimResponse);
- tmpBinSimResponse = NULL;
- }
-
- response.simResponse = (char*)malloc(2 * binSimResponseLen + sizeof(char));
- if (response.simResponse == NULL) goto error;
- if (NULL == base64_encode(binSimResponse, response.simResponse, binSimResponseLen - 1)) {
- RLOGE("Failed to call base64_encode %s %d", __func__, __LINE__);
- goto error;
- }
-
- RIL_onRequestComplete(t, RIL_E_SUCCESS, &response, sizeof(response));
- at_response_free(p_response);
-
- free(binAuthData);
- free(hexAuthData);
- free(rand);
- free(autn);
- free(response.simResponse);
- free(binSimResponse);
- return;
-
-error:
- free(binAuthData);
- free(hexAuthData);
- free(rand);
- free(autn);
- free(response.simResponse);
- free(binSimResponse);
-
- RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
- at_response_free(p_response);
-}
-
-static void requestTransmitApduBasic( void *data, size_t datalen,
- RIL_Token t) {
- RIL_UNUSED_PARM(datalen);
-
- int err, len;
- int instruction = 0;
- char *cmd = NULL;
- char *line = NULL;
- RIL_SIM_APDU *p_args = NULL;
- ATResponse *p_response = NULL;
- RIL_SIM_IO_Response sr;
-
- memset(&sr, 0, sizeof(sr));
-
- p_args = (RIL_SIM_APDU *)data;
-
- if ((p_args->data == NULL) || (strlen(p_args->data) == 0)) {
- if (p_args->p3 < 0) {
- asprintf(&cmd, "AT+CSIM=%d,\"%02x%02x%02x%02x\"", 8, p_args->cla,
- p_args->instruction, p_args->p1, p_args->p2);
- } else {
- asprintf(&cmd, "AT+CSIM=%d,\"%02x%02x%02x%02x%02x\"", 10,
- p_args->cla, p_args->instruction, p_args->p1, p_args->p2,
- p_args->p3);
- }
- } else {
- asprintf(&cmd, "AT+CSIM=%d,\"%02x%02x%02x%02x%02x%s\"",
- 10 + (int)strlen(p_args->data), p_args->cla,
- p_args->instruction, p_args->p1, p_args->p2, p_args->p3,
- p_args->data);
- }
- err = at_send_command_singleline(cmd, "+CSIM:", &p_response);
- free(cmd);
- if (err < 0 || p_response->success == 0) {
- goto error;
- }
-
- line = p_response->p_intermediates->line;
- err = at_tok_start(&line);
- if (err < 0) goto error;
-
- err = at_tok_nextint(&line, &len);
- if (err < 0) goto error;
-
- err = at_tok_nextstr(&line, &(sr.simResponse));
- if (err < 0) goto error;
-
- sscanf(&(sr.simResponse[len - 4]), "%02x%02x", &(sr.sw1), &(sr.sw2));
- sr.simResponse[len - 4] = '\0';
-
- instruction = p_args->instruction;
- RIL_onRequestComplete(t, RIL_E_SUCCESS, &sr, sizeof(sr));
- at_response_free(p_response);
- return;
-
-error:
- RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
- at_response_free(p_response);
-}
-
-static int getPDP() {
- int ret = -1;
-
- for (int i = 0; i < MAX_PDP; i++) {
- if (s_PDP[i].state == PDP_IDLE) {
- s_PDP[i].state = PDP_BUSY;
- ret = s_PDP[i].cid;
- break;
- }
- }
- return ret;
-}
-
-static void putPDP(int cid) {
- if (cid < 1 || cid > MAX_PDP ) {
- return;
- }
-
- s_PDP[cid - 1].state = PDP_IDLE;
-}
-
-static void requestSetupDataCall(void *data, size_t datalen, RIL_Token t)
-{
- const char *apn = NULL;
- char *cmd = NULL;
- int err = -1;
- int cid = -1;
- ATResponse *p_response = NULL;
-
- apn = ((const char **)data)[2];
-
-#ifdef USE_TI_COMMANDS
- // Config for multislot class 10 (probably default anyway eh?)
- err = at_send_command("AT%CPRIM=\"GMM\",\"CONFIG MULTISLOT_CLASS=<10>\"",
- NULL);
-
- err = at_send_command("AT%DATA=2,\"UART\",1,,\"SER\",\"UART\",0", NULL);
-#endif /* USE_TI_COMMANDS */
-
- int fd, qmistatus;
- size_t cur = 0;
- size_t len;
- ssize_t written, rlen;
- char status[32] = {0};
- int retry = 10;
- const char *pdp_type;
-
- RLOGD("requesting data connection to APN '%s'", apn);
-
- fd = open ("/dev/qmi", O_RDWR);
- if (fd >= 0) { /* the device doesn't exist on the emulator */
-
- RLOGD("opened the qmi device\n");
- asprintf(&cmd, "up:%s", apn);
- len = strlen(cmd);
-
- while (cur < len) {
- do {
- written = write (fd, cmd + cur, len - cur);
- } while (written < 0 && errno == EINTR);
-
- if (written < 0) {
- RLOGE("### ERROR writing to /dev/qmi");
- close(fd);
- goto error;
- }
-
- cur += written;
- }
-
- // wait for interface to come online
-
- do {
- sleep(1);
- do {
- rlen = read(fd, status, 31);
- } while (rlen < 0 && errno == EINTR);
-
- if (rlen < 0) {
- RLOGE("### ERROR reading from /dev/qmi");
- close(fd);
- goto error;
- } else {
- status[rlen] = '\0';
- RLOGD("### status: %s", status);
- }
- } while (strncmp(status, "STATE=up", 8) && strcmp(status, "online") && --retry);
-
- close(fd);
-
- if (retry == 0) {
- RLOGE("### Failed to get data connection up\n");
- goto error;
- }
-
- qmistatus = system("netcfg rmnet0 dhcp");
-
- RLOGD("netcfg rmnet0 dhcp: status %d\n", qmistatus);
-
- if (qmistatus < 0) goto error;
-
- } else {
- const char* radioInterfaceName = getRadioInterfaceName();
- if (setInterfaceState(radioInterfaceName, kInterfaceUp) != RIL_E_SUCCESS) {
- goto error;
- }
-
- if (datalen > 6 * sizeof(char *)) {
- pdp_type = ((const char **)data)[6];
- } else {
- pdp_type = "IP";
- }
-
- cid = getPDP();
- if (cid < 1 ) goto error;
-
- asprintf(&cmd, "AT+CGDCONT=%d,\"%s\",\"%s\",,0,0", cid, pdp_type, apn);
- //FIXME check for error here
- err = at_send_command(cmd, NULL);
- free(cmd);
-
- // Set required QoS params to default
- err = at_send_command("AT+CGQREQ=1", NULL);
-
- // Set minimum QoS params to default
- err = at_send_command("AT+CGQMIN=1", NULL);
-
- // packet-domain event reporting
- err = at_send_command("AT+CGEREP=1,0", NULL);
-
- // Hangup anything that's happening there now
- err = at_send_command("AT+CGACT=1,0", NULL);
-
- // Start data on PDP context 1
- err = at_send_command("ATD*99***1#", &p_response);
-
- if (err < 0 || p_response->success == 0) {
- goto error;
- }
- }
-
- requestOrSendDataCallList(cid, &t);
-
- at_response_free(p_response);
-
- return;
-error:
- RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
- at_response_free(p_response);
-}
-
-static void requestDeactivateDataCall(void *data, RIL_Token t)
-{
- const char *p_cid = ((const char **)data)[0];
- int cid = p_cid ? atoi(p_cid) : -1;
- RIL_Errno rilErrno = RIL_E_GENERIC_FAILURE;
- if (cid < 1 || cid > MAX_PDP) {
- RIL_onRequestComplete(t, rilErrno, NULL, 0);
- return;
- }
-
- const char* radioInterfaceName = getRadioInterfaceName();
- rilErrno = setInterfaceState(radioInterfaceName, kInterfaceDown);
- RIL_onRequestComplete(t, rilErrno, NULL, 0);
- putPDP(cid);
-}
-
-static void requestSMSAcknowledge(void *data, size_t datalen __unused, RIL_Token t)
-{
- int ackSuccess;
- int err;
-
- if (getSIMStatus() == SIM_ABSENT) {
- RIL_onRequestComplete(t, RIL_E_RADIO_NOT_AVAILABLE, NULL, 0);
- return;
- }
-
- ackSuccess = ((int *)data)[0];
-
- if (ackSuccess == 1) {
- err = at_send_command("AT+CNMA=1", NULL);
- } else if (ackSuccess == 0) {
- err = at_send_command("AT+CNMA=2", NULL);
- } else {
- RLOGE("unsupported arg to RIL_REQUEST_SMS_ACKNOWLEDGE\n");
- goto error;
- }
-
- RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
-error:
- RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
-}
-
-void convertBytesToHex(uint8_t *bytes, int length, uint8_t *hex_str) {
- int i;
- unsigned char tmp;
-
- if (bytes == NULL || hex_str == NULL) {
- return;
- }
- for (i = 0; i < length; i++) {
- tmp = (unsigned char)((bytes[i] & 0xf0) >> 4);
- if (tmp <= 9) {
- *hex_str = (unsigned char)(tmp + '0');
- } else {
- *hex_str = (unsigned char)(tmp + 'A' - 10);
- }
- hex_str++;
- tmp = (unsigned char)(bytes[i] & 0x0f);
- if (tmp <= 9) {
- *hex_str = (unsigned char)(tmp + '0');
- } else {
- *hex_str = (unsigned char)(tmp + 'A' - 10);
- }
- hex_str++;
- }
-}
-
-#define TYPE_EF 4
-#define RESPONSE_EF_SIZE 15
-#define TYPE_FILE_DES_LEN 5
-#define RESPONSE_DATA_FILE_DES_FLAG 2
-#define RESPONSE_DATA_FILE_DES_LEN_FLAG 3
-#define RESPONSE_DATA_FILE_TYPE 6
-#define RESPONSE_DATA_FILE_SIZE_1 2
-#define RESPONSE_DATA_FILE_SIZE_2 3
-#define RESPONSE_DATA_STRUCTURE 13
-#define RESPONSE_DATA_RECORD_LENGTH 14
-#define RESPONSE_DATA_FILE_RECORD_LEN_1 6
-#define RESPONSE_DATA_FILE_RECORD_LEN_2 7
-#define EF_TYPE_TRANSPARENT 0x01
-#define EF_TYPE_LINEAR_FIXED 0x02
-#define EF_TYPE_CYCLIC 0x06
-#define USIM_DATA_OFFSET_2 2
-#define USIM_DATA_OFFSET_3 3
-#define USIM_FILE_DES_TAG 0x82
-#define USIM_FILE_SIZE_TAG 0x80
-
-bool convertUsimToSim(uint8_t *byteUSIM, int len, uint8_t *hexSIM) {
- int desIndex = 0;
- int sizeIndex = 0;
- int i = 0;
- uint8_t byteSIM[RESPONSE_EF_SIZE] = {0};
- for (i = 0; i < len; i++) {
- if (byteUSIM[i] == USIM_FILE_DES_TAG) {
- desIndex = i;
- break;
- }
- }
- for (i = desIndex; i < len;) {
- if (byteUSIM[i] == USIM_FILE_SIZE_TAG) {
- sizeIndex = i;
- break;
- } else {
- i += (byteUSIM[i + 1] + 2);
- }
- }
- byteSIM[RESPONSE_DATA_FILE_SIZE_1] =
- byteUSIM[sizeIndex + USIM_DATA_OFFSET_2];
- byteSIM[RESPONSE_DATA_FILE_SIZE_2] =
- byteUSIM[sizeIndex + USIM_DATA_OFFSET_3];
- byteSIM[RESPONSE_DATA_FILE_TYPE] = TYPE_EF;
- if ((byteUSIM[desIndex + RESPONSE_DATA_FILE_DES_FLAG] & 0x07) ==
- EF_TYPE_TRANSPARENT) {
- byteSIM[RESPONSE_DATA_STRUCTURE] = 0;
- } else if ((byteUSIM[desIndex + RESPONSE_DATA_FILE_DES_FLAG] & 0x07) ==
- EF_TYPE_LINEAR_FIXED) {
- if (USIM_FILE_DES_TAG != byteUSIM[RESPONSE_DATA_FILE_DES_FLAG]) {
- RLOGE("USIM_FILE_DES_TAG != ...");
- goto error;
- }
- if (TYPE_FILE_DES_LEN != byteUSIM[RESPONSE_DATA_FILE_DES_LEN_FLAG]) {
- goto error;
- }
- byteSIM[RESPONSE_DATA_STRUCTURE] = 1;
- byteSIM[RESPONSE_DATA_RECORD_LENGTH] =
- ((byteUSIM[RESPONSE_DATA_FILE_RECORD_LEN_1] & 0xff) << 8) +
- (byteUSIM[RESPONSE_DATA_FILE_RECORD_LEN_2] & 0xff);
- } else if ((byteUSIM[desIndex + RESPONSE_DATA_FILE_DES_FLAG] & 0x07) ==
- EF_TYPE_CYCLIC) {
- byteSIM[RESPONSE_DATA_STRUCTURE] = 3;
- byteSIM[RESPONSE_DATA_RECORD_LENGTH] =
- ((byteUSIM[RESPONSE_DATA_FILE_RECORD_LEN_1] & 0xff) << 8) +
- (byteUSIM[RESPONSE_DATA_FILE_RECORD_LEN_2] & 0xff);
- }
-
- convertBytesToHex(byteSIM, RESPONSE_EF_SIZE, hexSIM);
- return true;
-
-error:
- return false;
-}
-
-static void requestSIM_IO(void *data, size_t datalen __unused, RIL_Token t)
-{
- ATResponse *p_response = NULL;
- RIL_SIM_IO_Response sr;
- int err;
- char *cmd = NULL;
- RIL_SIM_IO_v6 *p_args;
- char *line;
-
- /* For Convert USIM to SIM */
- uint8_t hexSIM[RESPONSE_EF_SIZE * 2 + sizeof(char)] = {0};
-
- memset(&sr, 0, sizeof(sr));
-
- p_args = (RIL_SIM_IO_v6 *)data;
-
- /* FIXME handle pin2 */
-
- if (p_args->data == NULL) {
- asprintf(&cmd, "AT+CRSM=%d,%d,%d,%d,%d",
- p_args->command, p_args->fileid,
- p_args->p1, p_args->p2, p_args->p3);
- } else {
- asprintf(&cmd, "AT+CRSM=%d,%d,%d,%d,%d,%s",
- p_args->command, p_args->fileid,
- p_args->p1, p_args->p2, p_args->p3, p_args->data);
- }
-
- err = at_send_command_singleline(cmd, "+CRSM:", &p_response);
-
- if (err < 0 || p_response->success == 0) {
- goto error;
- }
-
- line = p_response->p_intermediates->line;
-
- err = parseSimResponseLine(line, &sr);
- if (err < 0) {
- goto error;
- }
- if (sr.simResponse != NULL && // Default to be USIM card
- p_args->command == 192) { // Get response
- uint8_t *bytes = convertHexStringToBytes(sr.simResponse, strlen(sr.simResponse));
- if (bytes == NULL) {
- RLOGE("Failed to convert sim response to bytes");
- goto error;
- }
- if (bytes[0] != 0x62) {
- RLOGE("Wrong FCP flag, unable to convert to sim ");
- free(bytes);
- goto error;
- }
- if (convertUsimToSim(bytes, strlen(sr.simResponse) / 2, hexSIM)) {
- sr.simResponse = (char *)hexSIM;
- }
- free(bytes);
- }
-
- RIL_onRequestComplete(t, RIL_E_SUCCESS, &sr, sizeof(sr));
- at_response_free(p_response);
- free(cmd);
- return;
-
-error:
- RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
- at_response_free(p_response);
- free(cmd);
-}
-
-static int getSimlockRemainTimes(const char* type) {
- int err = -1;
- int remain_times = -1;
- char cmd[32] = {0};
- char *line = NULL;
- char *lock_type = NULL;
- ATResponse *p_response = NULL;
-
- snprintf(cmd, sizeof(cmd), "AT+CPINR=\"%s\"", type);
- err = at_send_command_multiline(cmd, "+CPINR:", &p_response);
- if (err < 0 || p_response->success == 0) {
- goto error;
- }
-
- line = p_response->p_intermediates->line;
- err = at_tok_start(&line);
- if (err < 0) goto error;
-
- err = at_tok_nextstr(&line, &lock_type);
- if (err < 0) goto error;
-
- err = at_tok_nextint(&line, &remain_times);
- if (err < 0) goto error;
-
-error:
- at_response_free(p_response);
- return remain_times;
-}
-
-static void requestEnterSimPin(int request, void* data, size_t datalen, RIL_Token t)
-{
- ATResponse *p_response = NULL;
- int err;
- int remaintimes = -1;
- char* cmd = NULL;
- const char** strings = (const char**)data;;
-
- if (datalen == sizeof(char*) || datalen == 2 * sizeof(char*)) {
- asprintf(&cmd, "AT+CPIN=%s", strings[0]);
- } else
- goto error;
-
- err = at_send_command_singleline(cmd, "+CPIN:", &p_response);
- free(cmd);
-
- if (err < 0 || p_response->success == 0) {
-error:
- if (request == RIL_REQUEST_ENTER_SIM_PIN) {
- remaintimes = getSimlockRemainTimes("SIM PIN");
- } else if (request == RIL_REQUEST_ENTER_SIM_PIN2) {
- remaintimes = getSimlockRemainTimes("SIM PIN2");
- }
- RIL_onRequestComplete(t, RIL_E_PASSWORD_INCORRECT, &remaintimes,
- sizeof(remaintimes));
- } else {
- RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
- }
- at_response_free(p_response);
-}
-
-static void requestChangeSimPin(int request, void* data, size_t datalen, RIL_Token t)
-{
- ATResponse *p_response = NULL;
- int err;
- int remaintimes = -1;
- char* cmd = NULL;
- const char** strings = (const char**)data;;
-
- if (datalen == 2 * sizeof(char*) || datalen == 3 * sizeof(char*)) {
- asprintf(&cmd, "AT+CPIN=%s,%s", strings[0], strings[1]);
- } else
- goto error;
-
- err = at_send_command_singleline(cmd, "+CPIN:", &p_response);
- free(cmd);
-
- if (err < 0 || p_response->success == 0) {
-error:
- if (request == RIL_REQUEST_CHANGE_SIM_PIN) {
- remaintimes = getSimlockRemainTimes("SIM PIN");
- } else if (request == RIL_REQUEST_ENTER_SIM_PUK) {
- remaintimes = getSimlockRemainTimes("SIM PUK");
- } else if (request == RIL_REQUEST_ENTER_SIM_PUK2) {
- remaintimes = getSimlockRemainTimes("SIM PUK2");
- }
- RIL_onRequestComplete(t, RIL_E_PASSWORD_INCORRECT, &remaintimes,
- sizeof(remaintimes));
- } else {
- RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
- }
- at_response_free(p_response);
-}
-
-static void requestChangeSimPin2(void *data, size_t datalen, RIL_Token t) {
- int err, ret;
- int remaintime = -1;
- char cmd[64] = {0};
- const char **strings = (const char **)data;
- ATResponse *p_response = NULL;
-
- if (datalen != 3 * sizeof(char *)) {
- goto error;
- }
-
- snprintf(cmd, sizeof(cmd), "AT+CPWD=\"P2\",\"%s\",\"%s\"", strings[0],
- strings[1]);
- err = at_send_command(cmd, &p_response);
- if (err < 0 || p_response->success == 0) {
- remaintime = getSimlockRemainTimes("SIM PIN2");
- goto error;
- }
-
- RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
- at_response_free(p_response);
- return;
-
-error:
- RIL_onRequestComplete(t, RIL_E_PASSWORD_INCORRECT, &remaintime,
- sizeof(remaintime));
- at_response_free(p_response);
-}
-
-static void requestSendUSSD(void *data, size_t datalen, RIL_Token t)
-{
- RIL_UNUSED_PARM(datalen);
-
- int err = -1;
- char cmd[128] = {0};
- const char *ussdRequest = (char *)(data);
- ATResponse *p_response = NULL;
-
- snprintf(cmd, sizeof(cmd), "AT+CUSD=1,\"%s\"", ussdRequest);
- err = at_send_command(cmd, &p_response);
- if (err < 0 || p_response->success == 0) {
- RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
- } else {
- RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
- }
- at_response_free(p_response);
-}
-
-static void requestExitEmergencyMode(void *data __unused, size_t datalen __unused, RIL_Token t)
-{
- int err;
- ATResponse *p_response = NULL;
-
- err = at_send_command("AT+WSOS=0", &p_response);
-
- if (err < 0 || p_response->success == 0) {
- RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
- return;
- }
-
- RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
-}
-
-static uint64_t s_last_activity_info_query = 0;
-
-static void requestGetActivityInfo(void *data __unused, size_t datalen __unused, RIL_Token t)
-{
- uint64_t curTime = ril_nano_time();
- RIL_ActivityStatsInfo stats =
- {
- 0, // sleep_mode_time_ms
- ((curTime - s_last_activity_info_query) / 1000000) - 1, // idle_mode_time_ms
- {0, 0, 0, 0, 0}, // tx_mode_time_ms
- 0 // rx_mode_time_ms
- };
- s_last_activity_info_query = curTime;
-
- RIL_onRequestComplete(t, RIL_E_SUCCESS, &stats, sizeof(stats));
-}
-
-// TODO: Use all radio types
-static int techFromModemType(int mdmtype)
-{
- int ret = -1;
- switch (mdmtype) {
- case MDM_CDMA:
- ret = RADIO_TECH_1xRTT;
- break;
- case MDM_EVDO:
- ret = RADIO_TECH_EVDO_A;
- break;
- case MDM_GSM:
- ret = RADIO_TECH_GPRS;
- break;
- case MDM_WCDMA:
- ret = RADIO_TECH_HSPA;
- break;
- case MDM_LTE:
- ret = RADIO_TECH_LTE;
- case MDM_NR:
- ret = RADIO_TECH_NR;
- break;
- }
- return ret;
-}
-
-static void requestGetCellInfoList(void *data __unused, size_t datalen __unused, RIL_Token t)
-{
- uint64_t curTime = ril_nano_time();
- RIL_CellInfo_v12 ci[1] =
- {
- { // ci[0]
- 1, // cellInfoType
- 1, // registered
- RIL_TIMESTAMP_TYPE_MODEM,
- curTime - 1000, // Fake some time in the past
- { // union CellInfo
- { // RIL_CellInfoGsm gsm
- { // gsm.cellIdneityGsm
- s_mcc, // mcc
- s_mnc, // mnc
- s_lac, // lac
- s_cid, // cid
- 0, //arfcn unknown
- 0x1, // Base Station Identity Code set to arbitrarily 1
- },
- { // gsm.signalStrengthGsm
- 10, // signalStrength
- 0 // bitErrorRate
- , INT_MAX // timingAdvance invalid value
- }
- }
- }
- }
- };
-
- RIL_onRequestComplete(t, RIL_E_SUCCESS, ci, sizeof(ci));
-}
-
-
-static void requestSetCellInfoListRate(void *data, size_t datalen __unused, RIL_Token t)
-{
- // For now we'll save the rate but no RIL_UNSOL_CELL_INFO_LIST messages
- // will be sent.
- assert (datalen == sizeof(int));
- s_cell_info_rate_ms = ((int *)data)[0];
-
- RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
-}
-
-static void requestGetHardwareConfig(void *data, size_t datalen, RIL_Token t)
-{
- // TODO - hook this up with real query/info from radio.
-
- RIL_HardwareConfig hwCfg;
-
- RIL_UNUSED_PARM(data);
- RIL_UNUSED_PARM(datalen);
-
- hwCfg.type = -1;
-
- RIL_onRequestComplete(t, RIL_E_SUCCESS, &hwCfg, sizeof(hwCfg));
-}
-
-static void requestGetTtyMode(void *data, size_t datalen, RIL_Token t)
-{
- int ttyModeResponse;
-
- RIL_UNUSED_PARM(data);
- RIL_UNUSED_PARM(datalen);
-
- ttyModeResponse = (getSIMStatus() == SIM_READY) ? 1 // TTY Full
- : 0; // TTY Off
-
- RIL_onRequestComplete(t, RIL_E_SUCCESS, &ttyModeResponse, sizeof(ttyModeResponse));
-}
-
-static void requestGetRadioCapability(void *data, size_t datalen, RIL_Token t)
-{
- RIL_RadioCapability radioCapability;
-
- RIL_UNUSED_PARM(data);
- RIL_UNUSED_PARM(datalen);
-
- radioCapability.version = RIL_RADIO_CAPABILITY_VERSION;
- radioCapability.session = 0;
- radioCapability.phase = 0;
- radioCapability.rat = NR | LTE | WCDMA | GSM;
- strncpy(radioCapability.logicalModemUuid, "com.android.modem.simulator", MAX_UUID_LENGTH);
- radioCapability.status = RC_STATUS_SUCCESS;
-
- RIL_onRequestComplete(t, RIL_E_SUCCESS, &radioCapability, sizeof(radioCapability));
-}
-
-static void requestSetRadioCapability(void *data, size_t datalen, RIL_Token t)
-{
- RIL_RadioCapability* rc = (RIL_RadioCapability*)data;
- RLOGV(
- "RadioCapability version %d session %d phase %d rat %d "
- "logicalModemUuid %s status %d",
- rc->version, rc->session, rc->phase, rc->rat, rc->logicalModemUuid,
- rc->status);
- // TODO(ender): do something about these numbers.
- RIL_onRequestComplete(t, RIL_E_SUCCESS, rc, datalen);
-}
-
-static void requestGetMute(void *data, size_t datalen, RIL_Token t)
-{
- RIL_UNUSED_PARM(data);
- RIL_UNUSED_PARM(datalen);
-
- int err = -1;
- int muteResponse = 0; // Mute disabled
- char *line = NULL;
- ATResponse *p_response = NULL;
-
- err = at_send_command_singleline("AT+CMUT?", "+CMUT:", &p_response);
- if (err < 0 || p_response->success) {
- goto done;
- }
-
- line = p_response->p_intermediates->line;
- err = at_tok_start(&line);
- if (err < 0) goto done;
-
- at_tok_nextint(&line, &muteResponse);
-
-done:
- RIL_onRequestComplete(t, RIL_E_SUCCESS, &muteResponse, sizeof(muteResponse));
- at_response_free(p_response);
-}
-
-static void requestSetMute(void *data, size_t datalen, RIL_Token t)
-{
- RIL_UNUSED_PARM(datalen);
-
- int err = -1;
- char cmd[64] = {0};
- ATResponse *p_response = NULL;
-
- snprintf(cmd, sizeof(cmd), "AT+CMUT=%d", ((int *)data)[0]);
- err = at_send_command(cmd, &p_response);
- if (err < 0 || p_response->success) {
- RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
- } else {
- RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
- }
- at_response_free(p_response);
-}
-
-static void requestScreenState(void *data, RIL_Token t)
-{
- int status = *((int *)data);
-
- if (!status) {
- /* Suspend */
- at_send_command("AT+CEREG=1", NULL);
- at_send_command("AT+CREG=1", NULL);
- at_send_command("AT+CGREG=1", NULL);
- } else {
- /* Resume */
- at_send_command("AT+CEREG=2", NULL);
- at_send_command("AT+CREG=2", NULL);
- at_send_command("AT+CGREG=2", NULL);
- }
-
- RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
-}
-
-static void requestQueryClip(void *data, size_t datalen, RIL_Token t)
-{
- RIL_UNUSED_PARM(datalen);
- RIL_UNUSED_PARM(data);
-
- int err = -1;
- int skip = 0;
- int response = 0;
- char *line = NULL;
- ATResponse *p_response = NULL;
-
- if (getSIMStatus() == SIM_ABSENT) {
- RIL_onRequestComplete(t, RIL_E_MODEM_ERR, NULL, 0);
- return;
- }
-
- err = at_send_command_singleline("AT+CLIP?", "+CLIP:", &p_response);
- if (err < 0 || p_response->success == 0) {
- goto error;
- }
-
- line = p_response->p_intermediates->line;
- err = at_tok_start(&line);
- if (err < 0) goto error;
-
- err = at_tok_nextint(&line, &skip);
- if (err < 0) goto error;
-
- err = at_tok_nextint(&line, &response);
- if (err < 0) goto error;
-
- RIL_onRequestComplete(t, RIL_E_SUCCESS, &response, sizeof(response));
- at_response_free(p_response);
- return;
-
-error:
- RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
- at_response_free(p_response);
-}
-
-static void requestQueryClir(void *data, size_t datalen, RIL_Token t)
-{
- RIL_UNUSED_PARM(datalen);
- RIL_UNUSED_PARM(data);
-
- int err = -1;
- int response[2] = {1, 1};
- char *line = NULL;
- ATResponse *p_response = NULL;
-
- if (getSIMStatus() == SIM_ABSENT) {
- RIL_onRequestComplete(t, RIL_E_MODEM_ERR, NULL, 0);
- return;
- }
-
- err = at_send_command_singleline("AT+CLIR?", "+CLIR:", &p_response);
- if (err < 0 || p_response->success == 0) {
- goto error;
- }
-
- line = p_response->p_intermediates->line;
- err = at_tok_start(&line);
- if (err < 0) goto error;
-
- err = at_tok_nextint(&line, &response[0]);
- if (err < 0) goto error;
-
- err = at_tok_nextint(&line, &response[1]);
- if (err < 0) goto error;
-
- RIL_onRequestComplete(t, RIL_E_SUCCESS, response, sizeof(response));
- at_response_free(p_response);
- return;
-
-error:
- RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
- at_response_free(p_response);
-}
-
-static void requestSetClir(void *data, size_t datalen, RIL_Token t)
-{
- RIL_UNUSED_PARM(datalen);
-
- int err = -1;
- int n = ((int *)data)[0];
- char cmd[64] = {0};
- ATResponse *p_response = NULL;
-
- snprintf(cmd, sizeof(cmd), "AT+CLIR=%d", n);
- err = at_send_command(cmd, &p_response);
- if (err < 0 || p_response->success == 0) {
- RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
- } else {
- RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
- }
- at_response_free(p_response);
-}
-
-static int forwardFromCCFCULine(char *line, RIL_CallForwardInfo *p_forward) {
- int err = -1;
- int i = 0;
-
- if (line == NULL || p_forward == NULL) {
- goto error;
- }
-
- err = at_tok_start(&line);
- if (err < 0) goto error;
-
- err = at_tok_nextint(&line, &(p_forward->status));
- if (err < 0) goto error;
-
- err = at_tok_nextint(&line, &(p_forward->serviceClass));
- if (err < 0) goto error;
-
- if (at_tok_hasmore(&line)) {
- int numberType = 0;
- err = at_tok_nextint(&line, &numberType);
- if (err < 0) goto error;
-
- err = at_tok_nextint(&line, &p_forward->toa);
- if (err < 0) goto error;
-
- err = at_tok_nextstr(&line, &(p_forward->number));
-
- /* tolerate null here */
- if (err < 0) return 0;
-
- if (at_tok_hasmore(&line)) {
- for (i = 0; i < 2; i++) {
- skipNextComma(&line);
- }
-
- if (at_tok_hasmore(&line)) {
- err = at_tok_nextint(&line, &p_forward->timeSeconds);
- if (err < 0) {
- p_forward->timeSeconds = 0;
- }
- }
- }
- }
-
- return 0;
-
-error:
- return -1;
-}
-
-static void requestSetCallForward(RIL_CallForwardInfo *data,
- size_t datalen, RIL_Token t) {
- int err = -1;
- char cmd[128] = {0};
- size_t offset = 0;
- ATResponse *p_response = NULL;
-
- if (datalen != sizeof(*data) ||
- (data->status == 3 && data->number == NULL)) {
- goto error;
- }
-
- snprintf(cmd, sizeof(cmd), "AT+CCFCU=%d,%d,%d,%d,\"%s\",%d",
- data->reason,
- data->status,
- 2,
- data->toa,
- data->number ? data->number : "",
- data->serviceClass);
- offset += strlen(cmd);
-
- if (data->serviceClass == 0) {
- if (data->timeSeconds != 0 && data->status == 3) {
- snprintf(cmd + offset, sizeof(cmd) - offset, ",\"\",\"\",,%d",
- data->timeSeconds);
- }
- } else {
- if (data->timeSeconds != 0 && data->status == 3) {
- snprintf(cmd + offset, sizeof(cmd) - offset, ",\"\",\"\",,%d",
- data->timeSeconds);
- } else {
- strlcat(cmd, ",\"\"", sizeof(cmd) - offset);
- }
- }
-
- err = at_send_command_multiline(cmd, "+CCFCU:", &p_response);
- if (err < 0 || p_response->success == 0) {
- goto error;
- }
-
- RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
- at_response_free(p_response);
- return;
-
-error:
- RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
- at_response_free(p_response);
-}
-
-static void requestQueryCallForward(RIL_CallForwardInfo *data,
- size_t datalen, RIL_Token t) {
- int err = -1;
- char cmd[128] = {0};
- ATResponse *p_response = NULL;
- ATLine *p_cur = NULL;
-
- if (datalen != sizeof(*data)) {
- goto error;
- }
-
- snprintf(cmd, sizeof(cmd), "AT+CCFCU=%d,2,%d,%d,\"%s\",%d", data->reason, 2,
- data->toa, data->number ? data->number : "", data->serviceClass);
-
- err = at_send_command_multiline(cmd, "+CCFCU:", &p_response);
- if (err < 0 || p_response->success == 0) {
- goto error;
- }
-
- RIL_CallForwardInfo **forwardList = NULL, *forwardPool = NULL;
- int forwardCount = 0;
- int validCount = 0;
- int i = 0;
-
- for (p_cur = p_response->p_intermediates; p_cur != NULL;
- p_cur = p_cur->p_next, forwardCount++) {
- }
-
- forwardList = (RIL_CallForwardInfo **)
- alloca(forwardCount * sizeof(RIL_CallForwardInfo *));
-
- forwardPool = (RIL_CallForwardInfo *)
- alloca(forwardCount * sizeof(RIL_CallForwardInfo));
-
- memset(forwardPool, 0, forwardCount * sizeof(RIL_CallForwardInfo));
-
- /* init the pointer array */
- for (i = 0; i < forwardCount; i++) {
- forwardList[i] = &(forwardPool[i]);
- }
-
- for (p_cur = p_response->p_intermediates; p_cur != NULL;
- p_cur = p_cur->p_next) {
- err = forwardFromCCFCULine(p_cur->line, forwardList[validCount]);
- forwardList[validCount]->reason = data->reason;
- if (err == 0) validCount++;
- }
-
- RIL_onRequestComplete(t, RIL_E_SUCCESS, validCount ? forwardList : NULL,
- validCount * sizeof (RIL_CallForwardInfo *));
- at_response_free(p_response);
- return;
-
-error:
- RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
- at_response_free(p_response);
-}
-
-static void requestQueryCallWaiting(void *data, size_t datalen, RIL_Token t) {
- RIL_UNUSED_PARM(datalen);
-
- int err = -1, mode = 0;
- int serviceClass = ((int *)data)[0];
- int response[2] = {0, 0};
- char cmd[32] = {0};
- char *line;
- ATLine *p_cur;
- ATResponse *p_response = NULL;
-
- if (serviceClass == 0) {
- snprintf(cmd, sizeof(cmd), "AT+CCWA=1,2");
- } else {
- snprintf(cmd, sizeof(cmd), "AT+CCWA=1,2,%d", serviceClass);
- }
- err = at_send_command_multiline(cmd, "+CCWA:", &p_response);
- if (err < 0 || p_response->success == 0) {
- goto error;
- }
-
- for (p_cur = p_response->p_intermediates; p_cur != NULL;
- p_cur = p_cur->p_next) {
- line = p_cur->line;
- err = at_tok_start(&line);
- if (err < 0) goto error;
-
- err = at_tok_nextint(&line, &mode);
- if (err < 0) goto error;
-
- err = at_tok_nextint(&line, &serviceClass);
- if (err < 0) goto error;
-
- response[0] = mode;
- response[1] |= serviceClass;
- }
- RIL_onRequestComplete(t, RIL_E_SUCCESS, response, sizeof(response));
- at_response_free(p_response);
- return;
-
-error:
- RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
- at_response_free(p_response);
-}
-
-static void requestSetCallWaiting(void *data, size_t datalen, RIL_Token t) {
- RIL_UNUSED_PARM(datalen);
-
- ATResponse *p_response = NULL;
- int err = -1;
- char cmd[32] = {0};
- int enable = ((int *)data)[0];
- int serviceClass = ((int *)data)[1];
-
- if (serviceClass == 0) {
- snprintf(cmd, sizeof(cmd), "AT+CCWA=1,%d", enable);
- } else {
- snprintf(cmd, sizeof(cmd), "AT+CCWA=1,%d,%d", enable, serviceClass);
- }
-
- err = at_send_command(cmd, &p_response);
- if (err < 0 || p_response->success == 0) {
- RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
- } else {
- RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
- }
- at_response_free(p_response);
-}
-
-static void requestSetSuppServiceNotifications(void *data, size_t datalen,
- RIL_Token t) {
- RIL_UNUSED_PARM(datalen);
-
- int err = 0;
- ATResponse *p_response = NULL;
- int mode = ((int *)data)[0];
- char cmd[32] = {0};
-
- snprintf(cmd, sizeof(cmd), "AT+CSSN=%d,%d", mode, mode);
- err = at_send_command(cmd, &p_response);
- if (err < 0 || p_response->success == 0) {
- RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
- } else {
- RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
- }
- at_response_free(p_response);
-}
-
-static void requestChangeBarringPassword(char **data, size_t datalen, RIL_Token t) {
- int err = -1;
- int result;
- char cmd[64] = {0};
- ATResponse *p_response = NULL;
-
- if (datalen != 3 * sizeof(char *) || data[0] == NULL || data[1] == NULL ||
- data[2] == NULL || strlen(data[0]) == 0 || strlen(data[1]) == 0 ||
- strlen(data[2]) == 0) {
- RIL_onRequestComplete(t, RIL_E_INVALID_ARGUMENTS, NULL, 0);
- return;
- }
-
- snprintf(cmd, sizeof(cmd), "AT+CPWD=\"%s\",\"%s\",\"%s\"", data[0], data[1],
- data[2]);
-
- err = at_send_command(cmd, &p_response);
- if (err < 0 || p_response->success == 0) {
- goto error;
- }
- RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
- at_response_free(p_response);
- return;
-
-error:
- RIL_onRequestComplete(t, RIL_E_PASSWORD_INCORRECT, NULL, 0);
- at_response_free(p_response);
-}
-
-static void requestFacilityLock(int request, char **data,
- size_t datalen, RIL_Token t) {
- int err = -1;
- int status = 0;
- int serviceClass = 0;
- int remainTimes = 10;
- char cmd[128] = {0};
- char *line = NULL;
- ATLine *p_cur = NULL;
- ATResponse *p_response = NULL;
- RIL_Errno errnoType = RIL_E_GENERIC_FAILURE;
-
- char *type = data[0];
-
- if (datalen != 5 * sizeof(char *)) {
- goto error;
- }
- if (data[0] == NULL || data[1] == NULL ||
- (data[2] == NULL && request == RIL_REQUEST_SET_FACILITY_LOCK) ||
- strlen(data[0]) == 0 || strlen(data[1]) == 0 ||
- (request == RIL_REQUEST_SET_FACILITY_LOCK && strlen(data[2]) == 0 )) {
- errnoType = RIL_E_INVALID_ARGUMENTS;
- RLOGE("FacilityLock invalid arguments");
- goto error;
- }
-
- serviceClass = atoi(data[3]);
- if (serviceClass == 0) {
- snprintf(cmd, sizeof(cmd), "AT+CLCK=\"%s\",%c,\"%s\"", data[0], *data[1],
- data[2]);
- } else {
- snprintf(cmd, sizeof(cmd), "AT+CLCK=\"%s\",%c,\"%s\",%s", data[0],
- *data[1], data[2], data[3]);
- }
-
- if (*data[1] == '2') { // query status
- err = at_send_command_multiline(cmd, "+CLCK: ", &p_response);
- if (err < 0 || p_response->success == 0) {
- goto error;
- }
- line = p_response->p_intermediates->line;
-
- err = at_tok_start(&line);
- if (err < 0) goto error;
-
- err = at_tok_nextint(&line, &status);
- if (err < 0) goto error;
-
- RIL_onRequestComplete(t, RIL_E_SUCCESS, &status, sizeof(int));
- at_response_free(p_response);
- return;
- } else { // unlock/lock this facility
- err = at_send_command(cmd, &p_response);
- if (err < 0 || p_response->success == 0) {
- errnoType = RIL_E_PASSWORD_INCORRECT;
- goto error;
- }
- errnoType = RIL_E_SUCCESS;
- }
-
-error:
- if (!strcmp(data[0], "SC")) {
- remainTimes = getSimlockRemainTimes("SIM PIN");
- } else if (!strcmp(data[0], "FD")) {
- remainTimes = getSimlockRemainTimes("SIM PIN2");
- } else {
- remainTimes = 1;
- }
-
- RIL_onRequestComplete(t, errnoType, &remainTimes, sizeof(remainTimes));
- at_response_free(p_response);
-}
-
-static void requestSetSmscAddress(void *data, size_t datalen, RIL_Token t)
-{
- ATResponse *p_response = NULL;
- char cmd[64] = {0};
- int err = -1;
-
- if (getSIMStatus() != SIM_READY) {
- RIL_onRequestComplete(t, RIL_E_SIM_ABSENT, NULL, 0);
- return;
- }
-
- if (data == NULL || strlen(data) == 0) {
- RLOGE("SET_SMSC_ADDRESS invalid address: %s", (char *)data);
- RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
- return;
- }
-
- snprintf(cmd, sizeof(cmd), "AT+CSCA=%s,%d", (char *)data, (int)datalen);
-
- err = at_send_command_singleline(cmd, "+CSCA:", &p_response);
- if (err < 0 || p_response->success == 0) {
- RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
- } else {
- RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
- }
- at_response_free(p_response);
-}
-
-static void requestGetSmscAddress(void *data, size_t datalen, RIL_Token t)
-{
- RIL_UNUSED_PARM(data);
- RIL_UNUSED_PARM(datalen);
-
- ATResponse *p_response = NULL;
- int err = -1;
- char *decidata = NULL;
-
- err = at_send_command_singleline( "AT+CSCA?", "+CSCA:", &p_response);
- if (err < 0 || p_response->success == 0) {
- goto error;
- }
-
- char *line = p_response->p_intermediates->line;
- err = at_tok_start(&line);
- if (err < 0) goto error;
-
- err = at_tok_nextstr(&line, &decidata);
- if (err < 0) goto error;
-
- RIL_onRequestComplete(t, RIL_E_SUCCESS, decidata, strlen(decidata) + 1);
- at_response_free(p_response);
- return;
-
-error:
- RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
- at_response_free(p_response);
-}
-
-static void setGsmBroadcastConfigData(int from, int to, int id, int outStrSize, char *outStr) {
- if (from < 0 || from > 0xffff || to < 0 || to > 0xffff) {
- RLOGE("setGsmBroadcastConfig data is invalid, [%d, %d]", from, to);
- return;
- }
-
- if (id != 0) {
- strlcat(outStr, ",", outStrSize);
- }
-
- int len = strlen(outStr);
- if (from == to) {
- snprintf(outStr + len, outStrSize - len, "%d", from);
- } else {
- snprintf(outStr + len, outStrSize - len, "%d-%d", from, to);
- }
-}
-
-static void requestSetSmsBroadcastConfig(void *data, size_t datalen,
- RIL_Token t) {
- int i = 0;
- int count = datalen / sizeof(RIL_GSM_BroadcastSmsConfigInfo *);
- int size = count * 16;
- char cmd[256] = {0};
- char *channel = (char *)alloca(size);
- char *languageId = (char *)alloca(size);
- ATResponse *p_response = NULL;
- RIL_GSM_BroadcastSmsConfigInfo **pGsmBci =
- (RIL_GSM_BroadcastSmsConfigInfo **)data;
- RIL_GSM_BroadcastSmsConfigInfo gsmBci = {0};
-
- memset(channel, 0, size);
- memset(languageId, 0, size);
- RLOGD("requestSetGsmBroadcastConfig %zu, count %d", datalen, count);
-
- for (i = 0; i < count; i++) {
- gsmBci = *(pGsmBci[i]);
- setGsmBroadcastConfigData(gsmBci.fromServiceId, gsmBci.toServiceId, i,
- size, channel);
- setGsmBroadcastConfigData(gsmBci.fromCodeScheme, gsmBci.toCodeScheme, i,
- size, languageId);
- }
-
- snprintf(cmd, sizeof(cmd), "AT+CSCB=%d,\"%s\",\"%s\"",
- (*pGsmBci[0]).selected ? 0 : 1, channel, languageId);
- int err = at_send_command_singleline( cmd, "+CSCB:", &p_response);
-
- if (err < 0 || p_response->success == 0) {
- RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
- } else {
- RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
- }
- at_response_free(p_response);
-}
-
-static void requestGetSmsBroadcastConfig(void *data, size_t datalen,
- RIL_Token t) {
- RIL_UNUSED_PARM(data);
- RIL_UNUSED_PARM(datalen);
-
- ATResponse *p_response = NULL;
- int err = -1, mode, commas = 0, i = 0;
- char *line = NULL;
- char *serviceIds = NULL, *codeSchemes = NULL, *p = NULL;
- char *serviceId = NULL, *codeScheme = NULL;
-
- err = at_send_command_singleline("AT+CSCB?", "+CSCB:", &p_response);
- if (err < 0 || p_response->success == 0) {
- goto error;
- }
-
- line = p_response->p_intermediates->line;
- err = at_tok_start(&line);
- if (err < 0) goto error;
-
- err = at_tok_nextint(&line, &mode);
- if (err < 0) goto error;
-
- err = at_tok_nextstr(&line, &serviceIds);
- if (err < 0) goto error;
-
- err = at_tok_nextstr(&line, &codeSchemes);
- if (err < 0) goto error;
-
- for (p = serviceIds; *p != '\0'; p++) {
- if (*p == ',') {
- commas++;
- }
- }
- RIL_GSM_BroadcastSmsConfigInfo **pGsmBci =
- (RIL_GSM_BroadcastSmsConfigInfo **)alloca((commas + 1) *
- sizeof(RIL_GSM_BroadcastSmsConfigInfo *));
- memset(pGsmBci, 0, (commas + 1) * sizeof(RIL_GSM_BroadcastSmsConfigInfo *));
-
- for (i = 0; i < commas + 1; i++) {
- pGsmBci[i] = (RIL_GSM_BroadcastSmsConfigInfo *)alloca(
- sizeof(RIL_GSM_BroadcastSmsConfigInfo));
- memset(pGsmBci[i], 0, sizeof(RIL_GSM_BroadcastSmsConfigInfo));
-
- err = at_tok_nextstr(&serviceIds, &serviceId);
- if (err < 0) goto error;
- pGsmBci[i]->toServiceId = pGsmBci[i]->fromServiceId = 0;
- if (strstr(serviceId, "-")) {
- sscanf(serviceId,"%d-%d", &pGsmBci[i]->fromServiceId,
- &pGsmBci[i]->toServiceId);
- }
-
- err = at_tok_nextstr(&codeSchemes, &codeScheme);
- if (err < 0) goto error;
- pGsmBci[i]->toCodeScheme = pGsmBci[i]->fromCodeScheme = 0;
- if (strstr(codeScheme, "-")) {
- sscanf(codeScheme, "%d-%d", &pGsmBci[i]->fromCodeScheme,
- &pGsmBci[i]->toCodeScheme);
- }
-
- pGsmBci[i]->selected = (mode == 0 ? false : true);
- }
- RIL_onRequestComplete(t, RIL_E_SUCCESS, pGsmBci,
- (commas + 1) * sizeof(RIL_GSM_BroadcastSmsConfigInfo *));
- at_response_free(p_response);
- return;
-
-error:
- at_response_free(p_response);
- RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
-}
-
-/**
- * <AcT>: integer type; access technology selected
- * 0 GSM
- * 1 GSM Compact
- * 2 UTRAN
- * 3 GSM w/EGPRS (see NOTE 1)
- * 4 UTRAN w/HSDPA (see NOTE 2)
- * 5 UTRAN w/HSUPA (see NOTE 2)
- * 6 UTRAN w/HSDPA and HSUPA (see NOTE 2)
- * 7 E-UTRAN
- * 8 EC-GSM-IoT (A/Gb mode) (see NOTE 3)
- * 9 E-UTRAN (NB-S1 mode) (see NOTE 4)
- * 10 E-UTRA connected to a 5GCN (see NOTE 5)
- * 11 NR connected to a 5GCN (see NOTE 5)
- * 12 NG-RAN
- * 13 E-UTRA-NR dual connectivity (see NOTE 6)
- */
-int mapRadioAccessNetworkToTech(RIL_RadioAccessNetworks network) {
- switch (network) {
- case GERAN: // GSM EDGE
- return 3;
- case UTRAN:
- return 6;
- case EUTRAN:
- return 7;
- case NGRAN:
- return 11;
- default:
- return 7; // LTE
- }
-}
-
-static void requestSetNetworlSelectionManual(void *data, RIL_Token t) {
- int err = -1;
- char cmd[64] = {0};
- ATResponse *p_response = NULL;
- RIL_NetworkOperator *operator = (RIL_NetworkOperator *)data;
-
- if (operator->act != UNKNOWN) {
- snprintf(cmd, sizeof(cmd), "AT+COPS=1,2,\"%s\"", operator->operatorNumeric);
- } else {
- snprintf(cmd, sizeof(cmd), "AT+COPS=1,2,\"%s\",%d",
- operator->operatorNumeric, operator->act);
- }
- err = at_send_command(cmd, &p_response);
- if (err < 0 || p_response->success == 0) {
- goto error;
- }
-
- RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
- at_response_free(p_response);
- return;
-
-error:
- if (p_response != NULL &&
- !strcmp(p_response->finalResponse, "+CME ERROR: 30")) {
- RIL_onRequestComplete(t, RIL_E_RADIO_NOT_AVAILABLE, NULL, 0);
- } else {
- RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
- }
- at_response_free(p_response);
-}
-
-static void requestStkServiceIsRunning(RIL_Token t)
-{
- int err = -1;
- ATResponse *p_response = NULL;
-
- s_stkServiceRunning = true;
- if (NULL != s_stkUnsolResponse) {
- RIL_onUnsolicitedResponse(RIL_UNSOL_STK_PROACTIVE_COMMAND,
- s_stkUnsolResponse, strlen(s_stkUnsolResponse) + 1);
- free(s_stkUnsolResponse);
- s_stkUnsolResponse = NULL;
- RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
- return;
- }
-
- err = at_send_command_singleline("AT+CUSATD?", "+CUSATD:", &p_response);
-
- if (err < 0 || p_response->success == 0) {
- RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
- } else {
- RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
- }
- at_response_free(p_response);
-}
-
-static void requestStkSendEnvelope(void *data, RIL_Token t)
-{
- int ret = -1, err = -1;
- char cmd[128] = {0};
- ATResponse *p_response = NULL;
-
- if (data == NULL || strlen((char *)data) == 0) {
- RLOGE("STK sendEnvelope data is invalid");
- RIL_onRequestComplete(t, RIL_E_INVALID_ARGUMENTS, NULL, 0);
- return;
- }
-
- snprintf(cmd, sizeof(cmd), "AT+CUSATE=\"%s\"", (char *)data);
- err = at_send_command_singleline(cmd, "+CUSATE:", &p_response);
- if (err < 0 || p_response->success == 0) {
- RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
- } else {
- RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
-
- // type of alpha data is 85, such as 850C546F6F6C6B6974204D656E75
- char *p = strstr(p_response->p_intermediates->line, "85");
- if (p != NULL) {
- char alphaStrHexLen[3] = {0};
- char alphaStr[1024] = {0};
- uint8_t *alphaBytes = NULL;
- int len = 0;
-
- p = p + strlen("85");
- strncpy(alphaStrHexLen, p, 2);
- len = strtoul(alphaStrHexLen, NULL, 16);
- strncpy(alphaStr, p + 2, len * 2);
- alphaBytes = convertHexStringToBytes(alphaStr, strlen(alphaStr));
- RIL_onUnsolicitedResponse(RIL_UNSOL_STK_CC_ALPHA_NOTIFY, alphaBytes,
- strlen((char *)alphaBytes));
- free(alphaBytes);
- }
- }
- at_response_free(p_response);
-}
-
-static void requestStksendTerminalResponse(void *data, RIL_Token t)
-{
- int ret = -1, err = -1;
- char cmd[128] = {0};
- ATResponse *p_response = NULL;
-
- if (data == NULL || strlen((char *)data) == 0) {
- RLOGE("STK sendTerminalResponse data is invalid");
- RIL_onRequestComplete(t, RIL_E_INVALID_ARGUMENTS, NULL, 0);
- return;
- }
-
- snprintf(cmd, sizeof(cmd), "AT+CUSATT=\"%s\"", (char *)data);
- err = at_send_command_singleline( cmd, "+CUSATT:", &p_response);
- if (err < 0 || p_response->success == 0) {
- RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
- } else {
- RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
- }
- at_response_free(p_response);
-}
-
-static void requestEccDial(void *data, RIL_Token t) {
- char cmd[64] = {0};
- const char *clir = NULL;
- int err = -1;
- RIL_EmergencyDial *p_eccDial = (RIL_EmergencyDial *)data;
-
- switch (p_eccDial->dialInfo.clir) {
- case 0: /* subscription default */
- clir = "";
- break;
- case 1: /* invocation */
- clir = "I";
- break;
- case 2: /* suppression */
- clir = "i";
- break;
- default:
- break;
- }
-
- if (p_eccDial->routing == ROUTING_MERGENCY ||
- p_eccDial->routing == ROUTING_UNKNOWN) {
- if (p_eccDial->categories == CATEGORY_UNSPECIFIED) {
- snprintf(cmd, sizeof(cmd), "ATD%s@,#%s;", p_eccDial->dialInfo.address, clir);
- } else {
- snprintf(cmd, sizeof(cmd), "ATD%s@%d,#%s;", p_eccDial->dialInfo.address,
- p_eccDial->categories, clir);
- }
- } else { // ROUTING_NORMAL
- snprintf(cmd, sizeof(cmd), "ATD%s%s;", p_eccDial->dialInfo.address, clir);
- }
-
- err = at_send_command(cmd, NULL);
- if (err != 0) goto error;
-
- RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
- return;
-
-error:
- RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
-}
-
-void getConfigSlotStatus(RIL_SimSlotStatus_V1_2 *pSimSlotStatus) {
- if (pSimSlotStatus == NULL) {
- return;
- }
- if (getSIMStatus() == SIM_ABSENT) {
- pSimSlotStatus->base.cardState = RIL_CARDSTATE_ABSENT;
- } else {
- pSimSlotStatus->base.cardState = RIL_CARDSTATE_PRESENT;
- }
- // TODO: slot state is always active now
- pSimSlotStatus->base.slotState = SLOT_STATE_ACTIVE;
-
- if (pSimSlotStatus->base.cardState != RIL_CARDSTATE_ABSENT) {
- pSimSlotStatus->base.atr = "";
- pSimSlotStatus->base.iccid = (char *)calloc(64, sizeof(char));
- getIccId(pSimSlotStatus->base.iccid, 64);
- }
-
- pSimSlotStatus->base.logicalSlotId = 0;
- pSimSlotStatus->eid = "";
-}
-
-void onIccSlotStatus(RIL_Token t) {
- RIL_SimSlotStatus_V1_2 *pSimSlotStatusList =
- (RIL_SimSlotStatus_V1_2 *)calloc(SIM_COUNT, sizeof(RIL_SimSlotStatus_V1_2));
-
- getConfigSlotStatus(pSimSlotStatusList);
-
- if (t == NULL) {
- RIL_onUnsolicitedResponse(RIL_UNSOL_CONFIG_ICC_SLOT_STATUS, pSimSlotStatusList,
- SIM_COUNT * sizeof(RIL_SimSlotStatus_V1_2));
- } else {
- RIL_onRequestComplete(t, RIL_E_SUCCESS, pSimSlotStatusList,
- SIM_COUNT * sizeof(RIL_SimSlotStatus_V1_2));
- }
-
- if (pSimSlotStatusList != NULL) {
- free(pSimSlotStatusList->base.iccid);
- free(pSimSlotStatusList);
- }
-}
-
-/*** Callback methods from the RIL library to us ***/
-
-/**
- * Call from RIL to us to make a RIL_REQUEST
- *
- * Must be completed with a call to RIL_onRequestComplete()
- *
- * RIL_onRequestComplete() may be called from any thread, before or after
- * this function returns.
- *
- * Because onRequest function could be called from multiple different thread,
- * we must ensure that the underlying at_send_command_* function
- * is atomic.
- */
-static void
-onRequest (int request, void *data, size_t datalen, RIL_Token t)
-{
- ATResponse *p_response;
- int err;
-
- RLOGD("onRequest: %s, sState: %d", requestToString(request), sState);
-
- /* Ignore all requests except RIL_REQUEST_GET_SIM_STATUS
- * when RADIO_STATE_UNAVAILABLE.
- */
- if (sState == RADIO_STATE_UNAVAILABLE
- && request != RIL_REQUEST_GET_SIM_STATUS
- ) {
- RIL_onRequestComplete(t, RIL_E_RADIO_NOT_AVAILABLE, NULL, 0);
- return;
- }
-
- /* Ignore all non-power requests when RADIO_STATE_OFF
- * (except RIL_REQUEST_GET_SIM_STATUS)
- */
- if (sState == RADIO_STATE_OFF) {
- switch(request) {
- case RIL_REQUEST_BASEBAND_VERSION:
- case RIL_REQUEST_CDMA_GET_SUBSCRIPTION_SOURCE:
- case RIL_REQUEST_CDMA_QUERY_PREFERRED_VOICE_PRIVACY_MODE:
- case RIL_REQUEST_CDMA_SET_PREFERRED_VOICE_PRIVACY_MODE:
- case RIL_REQUEST_CDMA_SET_ROAMING_PREFERENCE:
- case RIL_REQUEST_CDMA_SET_SUBSCRIPTION_SOURCE:
- case RIL_REQUEST_CDMA_SUBSCRIPTION:
- case RIL_REQUEST_DEVICE_IDENTITY:
- case RIL_REQUEST_EXIT_EMERGENCY_CALLBACK_MODE:
- case RIL_REQUEST_GET_ACTIVITY_INFO:
- case RIL_REQUEST_GET_CARRIER_RESTRICTIONS:
- case RIL_REQUEST_GET_CURRENT_CALLS:
- case RIL_REQUEST_GET_IMEI:
- case RIL_REQUEST_GET_MUTE:
- case RIL_REQUEST_SET_MUTE:
- case RIL_REQUEST_GET_NEIGHBORING_CELL_IDS:
- case RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE:
- case RIL_REQUEST_GET_RADIO_CAPABILITY:
- case RIL_REQUEST_GET_SIM_STATUS:
- case RIL_REQUEST_NV_RESET_CONFIG:
- case RIL_REQUEST_QUERY_AVAILABLE_BAND_MODE:
- case RIL_REQUEST_QUERY_NETWORK_SELECTION_MODE:
- case RIL_REQUEST_QUERY_TTY_MODE:
- case RIL_REQUEST_RADIO_POWER:
- case RIL_REQUEST_SET_BAND_MODE:
- case RIL_REQUEST_SET_CARRIER_RESTRICTIONS:
- case RIL_REQUEST_SET_LOCATION_UPDATES:
- case RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE:
- case RIL_REQUEST_SET_TTY_MODE:
- case RIL_REQUEST_SET_UNSOL_CELL_INFO_LIST_RATE:
- case RIL_REQUEST_STOP_LCE:
- case RIL_REQUEST_VOICE_RADIO_TECH:
- case RIL_REQUEST_SCREEN_STATE:
- // Process all the above, even though the radio is off
- break;
-
- default:
- // For all others, say NOT_AVAILABLE because the radio is off
- RIL_onRequestComplete(t, RIL_E_RADIO_NOT_AVAILABLE, NULL, 0);
- return;
- }
- }
-
- switch (request) {
- case RIL_REQUEST_GET_SIM_STATUS: {
- RIL_CardStatus_v1_5 *p_card_status;
- char *p_buffer;
- int buffer_size;
-
- int result = getCardStatus(&p_card_status);
- if (result == RIL_E_SUCCESS) {
- p_buffer = (char *)p_card_status;
- buffer_size = sizeof(*p_card_status);
- } else {
- p_buffer = NULL;
- buffer_size = 0;
- }
- RIL_onRequestComplete(t, result, p_buffer, buffer_size);
- freeCardStatus(p_card_status);
- break;
- }
- case RIL_REQUEST_GET_CURRENT_CALLS:
- requestGetCurrentCalls(data, datalen, t);
- break;
- case RIL_REQUEST_DIAL:
- requestDial(data, datalen, t);
- break;
- case RIL_REQUEST_HANGUP:
- requestHangup(data, datalen, t);
- break;
- case RIL_REQUEST_HANGUP_WAITING_OR_BACKGROUND:
- case RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND:
- case RIL_REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE:
- case RIL_REQUEST_CONFERENCE:
- case RIL_REQUEST_UDUB:
- requestCallSelection(data, datalen, t, request);
- break;
- case RIL_REQUEST_ANSWER:
- at_send_command("ATA", NULL);
-
-#ifdef WORKAROUND_ERRONEOUS_ANSWER
- s_expectAnswer = 1;
-#endif /* WORKAROUND_ERRONEOUS_ANSWER */
-
- if (getSIMStatus() != SIM_READY) {
- RIL_onRequestComplete(t, RIL_E_MODEM_ERR, NULL, 0);
- } else {
- // Success or failure is ignored by the upper layer here.
- // It will call GET_CURRENT_CALLS and determine success that way.
- RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
- }
- break;
-
- case RIL_REQUEST_SEPARATE_CONNECTION:
- {
- char cmd[12];
- int party = ((int*)data)[0];
-
- if (getSIMStatus() == SIM_ABSENT) {
- RIL_onRequestComplete(t, RIL_E_RADIO_NOT_AVAILABLE, NULL, 0);
- return;
- }
- // Make sure that party is in a valid range.
- // (Note: The Telephony middle layer imposes a range of 1 to 7.
- // It's sufficient for us to just make sure it's single digit.)
- if (party > 0 && party < 10) {
- sprintf(cmd, "AT+CHLD=2%d", party);
- at_send_command(cmd, NULL);
- RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
- } else {
- RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
- }
- }
- break;
-
- case RIL_REQUEST_SIGNAL_STRENGTH:
- requestSignalStrength(data, datalen, t);
- break;
- case RIL_REQUEST_VOICE_REGISTRATION_STATE:
- case RIL_REQUEST_DATA_REGISTRATION_STATE:
- requestRegistrationState(request, data, datalen, t);
- break;
- case RIL_REQUEST_OPERATOR:
- requestOperator(data, datalen, t);
- break;
- case RIL_REQUEST_RADIO_POWER:
- requestRadioPower(data, datalen, t);
- break;
- case RIL_REQUEST_DTMF: {
- char c = ((char *)data)[0];
- char *cmd;
- asprintf(&cmd, "AT+VTS=%c", (int)c);
- at_send_command(cmd, NULL);
- free(cmd);
- RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
- break;
- }
- case RIL_REQUEST_SEND_SMS:
- case RIL_REQUEST_SEND_SMS_EXPECT_MORE:
- requestSendSMS(data, datalen, t);
- break;
- case RIL_REQUEST_CDMA_SEND_SMS:
- requestCdmaSendSMS(data, datalen, t);
- break;
- case RIL_REQUEST_IMS_SEND_SMS:
- requestImsSendSMS(data, datalen, t);
- break;
- case RIL_REQUEST_SIM_OPEN_CHANNEL:
- requestSimOpenChannel(data, datalen, t);
- break;
- case RIL_REQUEST_SIM_CLOSE_CHANNEL:
- requestSimCloseChannel(data, datalen, t);
- break;
- case RIL_REQUEST_SIM_TRANSMIT_APDU_CHANNEL:
- requestSimTransmitApduChannel(data, datalen, t);
- break;
- case RIL_REQUEST_SIM_AUTHENTICATION: {
- RIL_SimAuthentication *sim_auth = (RIL_SimAuthentication *)data;
- if ((sim_auth->authContext == AUTH_CONTEXT_EAP_SIM ||
- sim_auth->authContext == AUTH_CONTEXT_EAP_AKA) &&
- sim_auth->authData != NULL) {
- requestSimAuthentication(sim_auth->authContext, sim_auth->authData, t);
- } else {
- RIL_onRequestComplete(t, RIL_E_INVALID_ARGUMENTS, NULL, 0);
- }
- break;
- }
- case RIL_REQUEST_SIM_TRANSMIT_APDU_BASIC:
- requestTransmitApduBasic(data, datalen, t);
- break;
- case RIL_REQUEST_SETUP_DATA_CALL:
- requestSetupDataCall(data, datalen, t);
- break;
- case RIL_REQUEST_DEACTIVATE_DATA_CALL:
- requestDeactivateDataCall(data, t);
- break;
- case RIL_REQUEST_SMS_ACKNOWLEDGE:
- requestSMSAcknowledge(data, datalen, t);
- break;
-
- case RIL_REQUEST_GET_IMSI:
- p_response = NULL;
- err = at_send_command_numeric("AT+CIMI", &p_response);
-
- if (err < 0 || p_response->success == 0) {
- RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
- } else {
- RIL_onRequestComplete(t, RIL_E_SUCCESS,
- p_response->p_intermediates->line, sizeof(char *));
- }
- at_response_free(p_response);
- break;
-
- case RIL_REQUEST_GET_IMEI:
- p_response = NULL;
- err = at_send_command_numeric("AT+CGSN", &p_response);
-
- if (err < 0 || p_response->success == 0) {
- RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
- } else {
- RIL_onRequestComplete(t, RIL_E_SUCCESS,
- p_response->p_intermediates->line, sizeof(char *));
- }
- at_response_free(p_response);
- break;
-
-
- case RIL_REQUEST_SIM_IO:
- requestSIM_IO(data,datalen,t);
- break;
-
- case RIL_REQUEST_SEND_USSD:
- requestSendUSSD(data, datalen, t);
- break;
-
- case RIL_REQUEST_CANCEL_USSD:
- if (getSIMStatus() == SIM_ABSENT) {
- RIL_onRequestComplete(t, RIL_E_RADIO_NOT_AVAILABLE, NULL, 0);
- break;
- }
- p_response = NULL;
- err = at_send_command_numeric("AT+CUSD=2", &p_response);
-
- if (err < 0 || p_response->success == 0) {
- RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
- } else {
- RIL_onRequestComplete(t, RIL_E_SUCCESS,
- p_response->p_intermediates->line, sizeof(char *));
- }
- at_response_free(p_response);
- break;
-
- case RIL_REQUEST_SET_NETWORK_SELECTION_AUTOMATIC:
- if (getSIMStatus() == SIM_ABSENT) {
- RIL_onRequestComplete(t, RIL_E_RADIO_NOT_AVAILABLE, NULL, 0);
- break;
- }
- p_response = NULL;
- err = at_send_command("AT+COPS=0", &p_response);
- if (err < 0 || p_response->success == 0) {
- RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
- } else {
- RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
- }
- at_response_free(p_response);
- break;
-
- case RIL_REQUEST_SET_NETWORK_SELECTION_MANUAL:
- requestSetNetworlSelectionManual(data, t);
- break;
-
- case RIL_REQUEST_DATA_CALL_LIST:
- requestDataCallList(data, datalen, t);
- break;
-
- case RIL_REQUEST_QUERY_NETWORK_SELECTION_MODE:
- requestQueryNetworkSelectionMode(data, datalen, t);
- break;
-
- case RIL_REQUEST_OEM_HOOK_RAW:
- // echo back data
- RIL_onRequestComplete(t, RIL_E_SUCCESS, data, datalen);
- break;
-
-
- case RIL_REQUEST_OEM_HOOK_STRINGS: {
- int i;
- const char ** cur;
-
- RLOGD("got OEM_HOOK_STRINGS: 0x%8p %lu", data, (long)datalen);
-
-
- for (i = (datalen / sizeof (char *)), cur = (const char **)data ;
- i > 0 ; cur++, i --) {
- RLOGD("> '%s'", *cur);
- }
-
- // echo back strings
- RIL_onRequestComplete(t, RIL_E_SUCCESS, data, datalen);
- break;
- }
-
- case RIL_REQUEST_WRITE_SMS_TO_SIM:
- requestWriteSmsToSim(data, datalen, t);
- break;
-
- case RIL_REQUEST_DELETE_SMS_ON_SIM: {
- char * cmd;
- p_response = NULL;
- asprintf(&cmd, "AT+CMGD=%d", ((int *)data)[0]);
- err = at_send_command(cmd, &p_response);
- free(cmd);
- if (err < 0 || p_response->success == 0) {
- RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
- } else {
- RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
- }
- at_response_free(p_response);
- break;
- }
-
- case RIL_REQUEST_ENTER_SIM_PIN:
- case RIL_REQUEST_ENTER_SIM_PIN2:
- requestEnterSimPin(request, data, datalen, t);
- break;
-
- case RIL_REQUEST_ENTER_SIM_PUK:
- case RIL_REQUEST_ENTER_SIM_PUK2:
- case RIL_REQUEST_CHANGE_SIM_PIN:
- requestChangeSimPin(request, data, datalen, t);
- break;
-
- case RIL_REQUEST_CHANGE_SIM_PIN2:
- requestChangeSimPin2(data, datalen, t);
- break;
-
- case RIL_REQUEST_IMS_REGISTRATION_STATE: {
- int reply[2];
- //0==unregistered, 1==registered
- reply[0] = s_ims_registered;
-
- //to be used when changed to include service supporated info
- //reply[1] = s_ims_services;
-
- // FORMAT_3GPP(1) vs FORMAT_3GPP2(2);
- reply[1] = s_ims_format;
-
- RLOGD("IMS_REGISTRATION=%d, format=%d ",
- reply[0], reply[1]);
- if (reply[1] != -1) {
- RIL_onRequestComplete(t, RIL_E_SUCCESS, reply, sizeof(reply));
- } else {
- RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
- }
- break;
- }
-
- case RIL_REQUEST_VOICE_RADIO_TECH:
- {
- int tech = techFromModemType(TECH(sMdmInfo));
- if (tech < 0 )
- RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
- else
- RIL_onRequestComplete(t, RIL_E_SUCCESS, &tech, sizeof(tech));
- }
- break;
- case RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE:
- requestSetPreferredNetworkType(request, data, datalen, t);
- break;
-
- case RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE:
- requestGetPreferredNetworkType(request, data, datalen, t);
- break;
-
- case RIL_REQUEST_GET_CELL_INFO_LIST:
- requestGetCellInfoList(data, datalen, t);
- break;
-
- case RIL_REQUEST_SET_UNSOL_CELL_INFO_LIST_RATE:
- requestSetCellInfoListRate(data, datalen, t);
- break;
-
- case RIL_REQUEST_GET_HARDWARE_CONFIG:
- requestGetHardwareConfig(data, datalen, t);
- break;
-
- case RIL_REQUEST_SHUTDOWN:
- requestShutdown(t);
- break;
-
- case RIL_REQUEST_QUERY_TTY_MODE:
- requestGetTtyMode(data, datalen, t);
- break;
-
- case RIL_REQUEST_GET_RADIO_CAPABILITY:
- requestGetRadioCapability(data, datalen, t);
- break;
-
- case RIL_REQUEST_SET_RADIO_CAPABILITY:
- requestSetRadioCapability(data, datalen, t);
- break;
-
- case RIL_REQUEST_GET_MUTE:
- requestGetMute(data, datalen, t);
- break;
-
- case RIL_REQUEST_SET_MUTE:
- requestSetMute(data, datalen, t);
- break;
-
- case RIL_REQUEST_QUERY_AVAILABLE_BAND_MODE: {
- int size = 5;
- int response[20] = {0};
- for (int i = 1; i <= size; i++) {
- response[i] = i - 1;
- }
- RIL_onRequestComplete(t, RIL_E_SUCCESS, response, (size + 1) * sizeof(int));
- break;
- }
-
- case RIL_REQUEST_SET_INITIAL_ATTACH_APN:
- case RIL_REQUEST_ALLOW_DATA:
- case RIL_REQUEST_ENTER_NETWORK_DEPERSONALIZATION:
- case RIL_REQUEST_SET_BAND_MODE:
- case RIL_REQUEST_GET_NEIGHBORING_CELL_IDS:
- case RIL_REQUEST_SET_LOCATION_UPDATES:
- case RIL_REQUEST_SET_TTY_MODE:
- case RIL_REQUEST_CDMA_SET_PREFERRED_VOICE_PRIVACY_MODE:
- RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
- break;
-
- case RIL_REQUEST_BASEBAND_VERSION:
- requestCdmaBaseBandVersion(request, data, datalen, t);
- break;
-
- case RIL_REQUEST_DEVICE_IDENTITY:
- requestDeviceIdentity(request, data, datalen, t);
- break;
-
- case RIL_REQUEST_CDMA_SUBSCRIPTION:
- requestCdmaSubscription(request, data, datalen, t);
- break;
-
- case RIL_REQUEST_CDMA_GET_SUBSCRIPTION_SOURCE:
- requestCdmaGetSubscriptionSource(request, data, datalen, t);
- break;
-
- case RIL_REQUEST_START_LCE:
- case RIL_REQUEST_STOP_LCE:
- case RIL_REQUEST_PULL_LCEDATA:
- if (getSIMStatus() == SIM_ABSENT) {
- RIL_onRequestComplete(t, RIL_E_SIM_ABSENT, NULL, 0);
- } else {
- RIL_onRequestComplete(t, RIL_E_LCE_NOT_SUPPORTED, NULL, 0);
- }
- break;
-
- case RIL_REQUEST_CDMA_QUERY_ROAMING_PREFERENCE:
- if (TECH_BIT(sMdmInfo) == MDM_CDMA) {
- requestCdmaGetRoamingPreference(request, data, datalen, t);
- } else {
- RIL_onRequestComplete(t, RIL_E_REQUEST_NOT_SUPPORTED, NULL, 0);
- }
- break;
-
- case RIL_REQUEST_CDMA_SET_SUBSCRIPTION_SOURCE:
- if (TECH_BIT(sMdmInfo) == MDM_CDMA) {
- requestCdmaSetSubscriptionSource(request, data, datalen, t);
- } else {
- // VTS tests expect us to silently do nothing
- RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
- }
- break;
-
- case RIL_REQUEST_CDMA_SET_ROAMING_PREFERENCE:
- if (TECH_BIT(sMdmInfo) == MDM_CDMA) {
- requestCdmaSetRoamingPreference(request, data, datalen, t);
- } else {
- // VTS tests expect us to silently do nothing
- RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
- }
- break;
-
- case RIL_REQUEST_EXIT_EMERGENCY_CALLBACK_MODE:
- if (TECH_BIT(sMdmInfo) == MDM_CDMA) {
- requestExitEmergencyMode(data, datalen, t);
- } else {
- // VTS tests expect us to silently do nothing
- RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
- }
- break;
-
- case RIL_REQUEST_GET_ACTIVITY_INFO:
- requestGetActivityInfo(data, datalen, t);
- break;
-
- case RIL_REQUEST_SCREEN_STATE:
- requestScreenState(data, t);
- break;
-
- case RIL_REQUEST_SET_DATA_PROFILE:
- RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
- break;
-
- case RIL_REQUEST_QUERY_CALL_FORWARD_STATUS:
- requestQueryCallForward(data, datalen, t);
- break;
-
- case RIL_REQUEST_SET_CALL_FORWARD:
- requestSetCallForward(data, datalen, t);
- break;
-
- case RIL_REQUEST_QUERY_CLIP:
- requestQueryClip(data, datalen, t);
- break;
-
- case RIL_REQUEST_GET_CLIR:
- requestQueryClir(data, datalen, t);
- break;
-
- case RIL_REQUEST_SET_CLIR:
- requestSetClir(data, datalen, t);
- break;
-
- case RIL_REQUEST_QUERY_CALL_WAITING:
- requestQueryCallWaiting(data, datalen, t);
- break;
-
- case RIL_REQUEST_SET_CALL_WAITING:
- requestSetCallWaiting(data, datalen, t);
- break;
-
- case RIL_REQUEST_SET_SUPP_SVC_NOTIFICATION:
- requestSetSuppServiceNotifications(data, datalen, t);
- break;
-
- case RIL_REQUEST_CHANGE_BARRING_PASSWORD:
- requestChangeBarringPassword(data, datalen, t);
- break;
-
- case RIL_REQUEST_QUERY_FACILITY_LOCK: {
- char *lockData[4];
- lockData[0] = ((char **)data)[0];
- lockData[1] = "2";
- lockData[2] = ((char **)data)[1];
- lockData[3] = ((char **)data)[2];
- requestFacilityLock(request, lockData, datalen + sizeof(char *), t);
- break;
- }
-
- case RIL_REQUEST_SET_FACILITY_LOCK:
- requestFacilityLock(request, data, datalen, t);
- break;
-
- case RIL_REQUEST_GET_SMSC_ADDRESS:
- requestGetSmscAddress(data, datalen, t);
- break;
-
- case RIL_REQUEST_SET_SMSC_ADDRESS:
- requestSetSmscAddress(data, datalen, t);
- break;
-
- case RIL_REQUEST_GSM_SET_BROADCAST_SMS_CONFIG:
- requestSetSmsBroadcastConfig(data, datalen, t);
- break;
-
- case RIL_REQUEST_GSM_GET_BROADCAST_SMS_CONFIG:
- requestGetSmsBroadcastConfig(data, datalen, t);
- break;
-
- case RIL_REQUEST_REPORT_STK_SERVICE_IS_RUNNING:
- requestStkServiceIsRunning(t);
- break;
-
- case RIL_REQUEST_STK_SEND_ENVELOPE_COMMAND:
- requestStkSendEnvelope(data, t);
- break;
-
- case RIL_REQUEST_STK_SEND_TERMINAL_RESPONSE:
- requestStksendTerminalResponse(data, t);
- break;
-
- // New requests after P.
- case RIL_REQUEST_START_NETWORK_SCAN:
- RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
- break;
- case RIL_REQUEST_GET_MODEM_STACK_STATUS:
- RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
- break;
- case RIL_REQUEST_ENABLE_MODEM:
- RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
- break;
- case RIL_REQUEST_EMERGENCY_DIAL:
- requestEccDial(data, t);
- break;
- case RIL_REQUEST_SET_SIM_CARD_POWER:
- RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
- break;
- case RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE_BITMAP:
- requestSetPreferredNetworkType(request, data, datalen, t);
- break;
- case RIL_REQUEST_SET_ALLOWED_NETWORK_TYPES_BITMAP:
- requestSetPreferredNetworkType(request, data, datalen, t);
- break;
- case RIL_REQUEST_GET_ALLOWED_NETWORK_TYPES_BITMAP:
- requestGetPreferredNetworkType(request, data, datalen, t);
- case RIL_REQUEST_ENABLE_NR_DUAL_CONNECTIVITY:
- if (data == NULL || datalen != sizeof(int)) {
- RIL_onRequestComplete(t, RIL_E_INTERNAL_ERR, NULL, 0);
- break;
- }
- int nrDualConnectivityState = *(int *)(data);
- isNrDualConnectivityEnabled = (nrDualConnectivityState == 1) ? true : false;
- RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
- break;
- case RIL_REQUEST_IS_NR_DUAL_CONNECTIVITY_ENABLED:
- RIL_onRequestComplete(t, RIL_E_SUCCESS, &isNrDualConnectivityEnabled,
- sizeof(isNrDualConnectivityEnabled));
- break;
- case RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE_BITMAP:
- requestGetPreferredNetworkType(request, data, datalen, t);
- break;
- case RIL_REQUEST_SET_SYSTEM_SELECTION_CHANNELS:
- RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
- break;
- case RIL_REQUEST_GET_SLICING_CONFIG:
- RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
- break;
-
- // Radio config requests
- case RIL_REQUEST_CONFIG_GET_SLOT_STATUS:
- RIL_requestTimedCallback(onIccSlotStatus, (void *)t, NULL);
- break;
- case RIL_REQUEST_CONFIG_SET_SLOT_MAPPING:
- RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
- break;
- case RIL_REQUEST_CONFIG_GET_PHONE_CAPABILITY: {
- RIL_PhoneCapability *phoneCapability =
- (RIL_PhoneCapability *)alloca(sizeof(RIL_PhoneCapability));
- phoneCapability->maxActiveData = 1;
- // DSDS is 1, and DSDA is 2, now only support DSDS
- phoneCapability->maxActiveInternetData = 1;
- // DSDA can support internet lingering
- phoneCapability->isInternetLingeringSupported = false;
- for (int num = 0; num < SIM_COUNT; num++) {
- phoneCapability->logicalModemList[num].modemId = num;
- }
- RIL_onRequestComplete(t, RIL_E_SUCCESS,
- phoneCapability, sizeof(RIL_PhoneCapability));
- break;
- }
- case RIL_REQUEST_CONFIG_SET_MODEM_CONFIG: {
- RIL_ModemConfig *mdConfig = (RIL_ModemConfig*)(data);
- if (mdConfig == NULL || mdConfig->numOfLiveModems != 1) {
- RIL_onRequestComplete(t, RIL_E_INVALID_ARGUMENTS, NULL, 0);
- } else {
- RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
- }
- break;
- }
- case RIL_REQUEST_CONFIG_GET_MODEM_CONFIG: {
- RIL_ModemConfig mdConfig;
- mdConfig.numOfLiveModems = 1;
-
- RIL_onRequestComplete(t, RIL_E_SUCCESS, &mdConfig, sizeof(RIL_ModemConfig));
- break;
- }
- case RIL_REQUEST_CONFIG_SET_PREFER_DATA_MODEM: {
- int *modemId = (int*)(data);
- if (modemId == NULL || *modemId != 0) {
- RIL_onRequestComplete(t, RIL_E_INVALID_ARGUMENTS, NULL, 0);
- } else {
- RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
- }
- break;
- }
- case RIL_REQUEST_SET_SIGNAL_STRENGTH_REPORTING_CRITERIA:
- RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
- break;
- case RIL_REQUEST_SET_LINK_CAPACITY_REPORTING_CRITERIA:
- RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
- break;
- case RIL_REQUEST_ENABLE_UICC_APPLICATIONS: {
- if (data == NULL || datalen != sizeof(int)) {
- RIL_onRequestComplete(t, RIL_E_INTERNAL_ERR, NULL, 0);
- break;
- }
- areUiccApplicationsEnabled = *(int *)(data);
- RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
- break;
- }
- case RIL_REQUEST_ARE_UICC_APPLICATIONS_ENABLED:
- RIL_onRequestComplete(t, RIL_E_SUCCESS, &areUiccApplicationsEnabled,
- sizeof(areUiccApplicationsEnabled));
- break;
- case RIL_REQUEST_CDMA_SEND_SMS_EXPECT_MORE:
- RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
- break;
- case RIL_REQUEST_GET_BARRING_INFO:
- RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
- break;
- case RIL_REQUEST_SET_DATA_THROTTLING:
- RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
- break;
- default:
- RLOGD("Request not supported. Tech: %d",TECH(sMdmInfo));
- RIL_onRequestComplete(t, RIL_E_REQUEST_NOT_SUPPORTED, NULL, 0);
- break;
- }
-}
-
-/**
- * Synchronous call from the RIL to us to return current radio state.
- * RADIO_STATE_UNAVAILABLE should be the initial state.
- */
-static RIL_RadioState
-currentState()
-{
- return sState;
-}
-/**
- * Call from RIL to us to find out whether a specific request code
- * is supported by this implementation.
- *
- * Return 1 for "supported" and 0 for "unsupported"
- */
-
-static int
-onSupports (int requestCode __unused)
-{
- //@@@ todo
-
- return 1;
-}
-
-static void onCancel (RIL_Token t __unused)
-{
- //@@@todo
-
-}
-
-static const char * getVersion(void)
-{
- return "android reference-ril 1.0";
-}
-
-static void
-setRadioTechnology(ModemInfo *mdm, int newtech)
-{
- RLOGD("setRadioTechnology(%d)", newtech);
-
- int oldtech = TECH(mdm);
-
- if (newtech != oldtech) {
- RLOGD("Tech change (%d => %d)", oldtech, newtech);
- TECH(mdm) = newtech;
- if (techFromModemType(newtech) != techFromModemType(oldtech)) {
- int tech = techFromModemType(TECH(sMdmInfo));
- if (tech > 0 ) {
- RIL_onUnsolicitedResponse(RIL_UNSOL_VOICE_RADIO_TECH_CHANGED,
- &tech, sizeof(tech));
- }
- }
- }
-}
-
-static void
-setRadioState(RIL_RadioState newState)
-{
- RLOGD("setRadioState(%d)", newState);
- RIL_RadioState oldState;
-
- pthread_mutex_lock(&s_state_mutex);
-
- oldState = sState;
-
- if (s_closed > 0) {
- // If we're closed, the only reasonable state is
- // RADIO_STATE_UNAVAILABLE
- // This is here because things on the main thread
- // may attempt to change the radio state after the closed
- // event happened in another thread
- newState = RADIO_STATE_UNAVAILABLE;
- }
-
- if (sState != newState || s_closed > 0) {
- sState = newState;
-
- pthread_cond_broadcast (&s_state_cond);
- }
-
- pthread_mutex_unlock(&s_state_mutex);
-
-
- /* do these outside of the mutex */
- if (sState != oldState) {
- RIL_onUnsolicitedResponse (RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED,
- NULL, 0);
- // Sim state can change as result of radio state change
- RIL_onUnsolicitedResponse (RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED,
- NULL, 0);
-
- /* FIXME onSimReady() and onRadioPowerOn() cannot be called
- * from the AT reader thread
- * Currently, this doesn't happen, but if that changes then these
- * will need to be dispatched on the request thread
- */
- if (sState == RADIO_STATE_ON) {
- onRadioPowerOn();
- }
- }
-}
-
-/** Returns RUIM_NOT_READY on error */
-static SIM_Status
-getRUIMStatus()
-{
- ATResponse *p_response = NULL;
- int err;
- int ret;
- char *cpinLine;
- char *cpinResult;
-
- if (sState == RADIO_STATE_OFF || sState == RADIO_STATE_UNAVAILABLE) {
- ret = SIM_NOT_READY;
- goto done;
- }
-
- err = at_send_command_singleline("AT+CPIN?", "+CPIN:", &p_response);
-
- if (err != 0) {
- ret = SIM_NOT_READY;
- goto done;
- }
-
- switch (at_get_cme_error(p_response)) {
- case CME_SUCCESS:
- break;
-
- case CME_SIM_NOT_INSERTED:
- ret = SIM_ABSENT;
- goto done;
-
- default:
- ret = SIM_NOT_READY;
- goto done;
- }
-
- /* CPIN? has succeeded, now look at the result */
-
- cpinLine = p_response->p_intermediates->line;
- err = at_tok_start (&cpinLine);
-
- if (err < 0) {
- ret = SIM_NOT_READY;
- goto done;
- }
-
- err = at_tok_nextstr(&cpinLine, &cpinResult);
-
- if (err < 0) {
- ret = SIM_NOT_READY;
- goto done;
- }
-
- if (0 == strcmp (cpinResult, "SIM PIN")) {
- ret = SIM_PIN;
- goto done;
- } else if (0 == strcmp (cpinResult, "SIM PUK")) {
- ret = SIM_PUK;
- goto done;
- } else if (0 == strcmp (cpinResult, "PH-NET PIN")) {
- return SIM_NETWORK_PERSONALIZATION;
- } else if (0 != strcmp (cpinResult, "READY")) {
- /* we're treating unsupported lock types as "sim absent" */
- ret = SIM_ABSENT;
- goto done;
- }
-
- at_response_free(p_response);
- p_response = NULL;
- cpinResult = NULL;
-
- ret = SIM_READY;
-
-done:
- at_response_free(p_response);
- return ret;
-}
-
-/** Returns SIM_NOT_READY on error */
-static SIM_Status
-getSIMStatus()
-{
- ATResponse *p_response = NULL;
- int err;
- int ret;
- char *cpinLine;
- char *cpinResult;
-
- RLOGD("getSIMStatus(). sState: %d",sState);
- err = at_send_command_singleline("AT+CPIN?", "+CPIN:", &p_response);
-
- if (err != 0) {
- ret = SIM_NOT_READY;
- goto done;
- }
-
- switch (at_get_cme_error(p_response)) {
- case CME_SUCCESS:
- break;
-
- case CME_SIM_NOT_INSERTED:
- ret = SIM_ABSENT;
- goto done;
-
- default:
- ret = SIM_NOT_READY;
- goto done;
- }
-
- /* CPIN? has succeeded, now look at the result */
-
- cpinLine = p_response->p_intermediates->line;
- err = at_tok_start (&cpinLine);
-
- if (err < 0) {
- ret = SIM_NOT_READY;
- goto done;
- }
-
- err = at_tok_nextstr(&cpinLine, &cpinResult);
-
- if (err < 0) {
- ret = SIM_NOT_READY;
- goto done;
- }
-
- if (0 == strcmp (cpinResult, "SIM PIN")) {
- ret = SIM_PIN;
- goto done;
- } else if (0 == strcmp (cpinResult, "SIM PUK")) {
- ret = SIM_PUK;
- goto done;
- } else if (0 == strcmp (cpinResult, "PH-NET PIN")) {
- return SIM_NETWORK_PERSONALIZATION;
- } else if (0 != strcmp (cpinResult, "READY")) {
- /* we're treating unsupported lock types as "sim absent" */
- ret = SIM_ABSENT;
- goto done;
- }
-
- at_response_free(p_response);
- p_response = NULL;
- cpinResult = NULL;
-
- ret = (sState == RADIO_STATE_ON) ? SIM_READY : SIM_NOT_READY;
-
-done:
- at_response_free(p_response);
- return ret;
-}
-
-static void getIccId(char *iccid, int size) {
- int err = 0;
- ATResponse *p_response = NULL;
-
- if (iccid == NULL) {
- RLOGE("iccid buffer is null");
- return;
- }
- err = at_send_command_numeric("AT+CICCID", &p_response);
- if (err < 0 || p_response->success == 0) {
- goto error;
- }
-
- snprintf(iccid, size, "%s", p_response->p_intermediates->line);
-
-error:
- at_response_free(p_response);
-}
-
-/**
- * Get the current card status.
- *
- * This must be freed using freeCardStatus.
- * @return: On success returns RIL_E_SUCCESS
- */
-static int getCardStatus(RIL_CardStatus_v1_5 **pp_card_status) {
- static RIL_AppStatus app_status_array[] = {
- // SIM_ABSENT = 0
- { RIL_APPTYPE_UNKNOWN, RIL_APPSTATE_UNKNOWN, RIL_PERSOSUBSTATE_UNKNOWN,
- NULL, NULL, 0, RIL_PINSTATE_UNKNOWN, RIL_PINSTATE_UNKNOWN },
- // SIM_NOT_READY = 1
- { RIL_APPTYPE_USIM, RIL_APPSTATE_DETECTED, RIL_PERSOSUBSTATE_UNKNOWN,
- NULL, NULL, 0, RIL_PINSTATE_UNKNOWN, RIL_PINSTATE_UNKNOWN },
- // SIM_READY = 2
- { RIL_APPTYPE_USIM, RIL_APPSTATE_READY, RIL_PERSOSUBSTATE_READY,
- NULL, NULL, 0, RIL_PINSTATE_UNKNOWN, RIL_PINSTATE_UNKNOWN },
- // SIM_PIN = 3
- { RIL_APPTYPE_USIM, RIL_APPSTATE_PIN, RIL_PERSOSUBSTATE_UNKNOWN,
- NULL, NULL, 0, RIL_PINSTATE_ENABLED_NOT_VERIFIED, RIL_PINSTATE_UNKNOWN },
- // SIM_PUK = 4
- { RIL_APPTYPE_USIM, RIL_APPSTATE_PUK, RIL_PERSOSUBSTATE_UNKNOWN,
- NULL, NULL, 0, RIL_PINSTATE_ENABLED_BLOCKED, RIL_PINSTATE_UNKNOWN },
- // SIM_NETWORK_PERSONALIZATION = 5
- { RIL_APPTYPE_USIM, RIL_APPSTATE_SUBSCRIPTION_PERSO, RIL_PERSOSUBSTATE_SIM_NETWORK,
- NULL, NULL, 0, RIL_PINSTATE_ENABLED_NOT_VERIFIED, RIL_PINSTATE_UNKNOWN },
- // RUIM_ABSENT = 6
- { RIL_APPTYPE_UNKNOWN, RIL_APPSTATE_UNKNOWN, RIL_PERSOSUBSTATE_UNKNOWN,
- NULL, NULL, 0, RIL_PINSTATE_UNKNOWN, RIL_PINSTATE_UNKNOWN },
- // RUIM_NOT_READY = 7
- { RIL_APPTYPE_RUIM, RIL_APPSTATE_DETECTED, RIL_PERSOSUBSTATE_UNKNOWN,
- NULL, NULL, 0, RIL_PINSTATE_UNKNOWN, RIL_PINSTATE_UNKNOWN },
- // RUIM_READY = 8
- { RIL_APPTYPE_RUIM, RIL_APPSTATE_READY, RIL_PERSOSUBSTATE_READY,
- NULL, NULL, 0, RIL_PINSTATE_UNKNOWN, RIL_PINSTATE_UNKNOWN },
- // RUIM_PIN = 9
- { RIL_APPTYPE_RUIM, RIL_APPSTATE_PIN, RIL_PERSOSUBSTATE_UNKNOWN,
- NULL, NULL, 0, RIL_PINSTATE_ENABLED_NOT_VERIFIED, RIL_PINSTATE_UNKNOWN },
- // RUIM_PUK = 10
- { RIL_APPTYPE_RUIM, RIL_APPSTATE_PUK, RIL_PERSOSUBSTATE_UNKNOWN,
- NULL, NULL, 0, RIL_PINSTATE_ENABLED_BLOCKED, RIL_PINSTATE_UNKNOWN },
- // RUIM_NETWORK_PERSONALIZATION = 11
- { RIL_APPTYPE_RUIM, RIL_APPSTATE_SUBSCRIPTION_PERSO, RIL_PERSOSUBSTATE_SIM_NETWORK,
- NULL, NULL, 0, RIL_PINSTATE_ENABLED_NOT_VERIFIED, RIL_PINSTATE_UNKNOWN },
- // ISIM_ABSENT = 12
- { RIL_APPTYPE_UNKNOWN, RIL_APPSTATE_UNKNOWN, RIL_PERSOSUBSTATE_UNKNOWN,
- NULL, NULL, 0, RIL_PINSTATE_UNKNOWN, RIL_PINSTATE_UNKNOWN },
- // ISIM_NOT_READY = 13
- { RIL_APPTYPE_ISIM, RIL_APPSTATE_DETECTED, RIL_PERSOSUBSTATE_UNKNOWN,
- NULL, NULL, 0, RIL_PINSTATE_UNKNOWN, RIL_PINSTATE_UNKNOWN },
- // ISIM_READY = 14
- { RIL_APPTYPE_ISIM, RIL_APPSTATE_READY, RIL_PERSOSUBSTATE_READY,
- NULL, NULL, 0, RIL_PINSTATE_UNKNOWN, RIL_PINSTATE_UNKNOWN },
- // ISIM_PIN = 15
- { RIL_APPTYPE_ISIM, RIL_APPSTATE_PIN, RIL_PERSOSUBSTATE_UNKNOWN,
- NULL, NULL, 0, RIL_PINSTATE_ENABLED_NOT_VERIFIED, RIL_PINSTATE_UNKNOWN },
- // ISIM_PUK = 16
- { RIL_APPTYPE_ISIM, RIL_APPSTATE_PUK, RIL_PERSOSUBSTATE_UNKNOWN,
- NULL, NULL, 0, RIL_PINSTATE_ENABLED_BLOCKED, RIL_PINSTATE_UNKNOWN },
- // ISIM_NETWORK_PERSONALIZATION = 17
- { RIL_APPTYPE_ISIM, RIL_APPSTATE_SUBSCRIPTION_PERSO, RIL_PERSOSUBSTATE_SIM_NETWORK,
- NULL, NULL, 0, RIL_PINSTATE_ENABLED_NOT_VERIFIED, RIL_PINSTATE_UNKNOWN },
-
- };
- RIL_CardState card_state;
- int num_apps;
-
- int sim_status = getSIMStatus();
- if (sim_status == SIM_ABSENT) {
- card_state = RIL_CARDSTATE_ABSENT;
- num_apps = 0;
- } else {
- card_state = RIL_CARDSTATE_PRESENT;
- num_apps = 3;
- }
-
- // Allocate and initialize base card status.
- RIL_CardStatus_v1_5 *p_card_status = calloc(1, sizeof(RIL_CardStatus_v1_5));
- p_card_status->base.base.base.card_state = card_state;
- p_card_status->base.base.base.universal_pin_state = RIL_PINSTATE_UNKNOWN;
- p_card_status->base.base.base.gsm_umts_subscription_app_index = -1;
- p_card_status->base.base.base.cdma_subscription_app_index = -1;
- p_card_status->base.base.base.ims_subscription_app_index = -1;
- p_card_status->base.base.base.num_applications = num_apps;
- p_card_status->base.base.physicalSlotId = 0;
- p_card_status->base.base.atr = NULL;
- p_card_status->base.base.iccid = NULL;
- p_card_status->base.eid = "";
- if (sim_status != SIM_ABSENT) {
- p_card_status->base.base.iccid = (char *)calloc(64, sizeof(char));
- getIccId(p_card_status->base.base.iccid, 64);
- }
-
- // Initialize application status
- int i;
- for (i = 0; i < RIL_CARD_MAX_APPS; i++) {
- p_card_status->base.base.base.applications[i] = app_status_array[SIM_ABSENT];
- }
- RLOGD("enter getCardStatus module, num_apps= %d",num_apps);
- // Pickup the appropriate application status
- // that reflects sim_status for gsm.
- if (num_apps != 0) {
- p_card_status->base.base.base.num_applications = 3;
- p_card_status->base.base.base.gsm_umts_subscription_app_index = 0;
- p_card_status->base.base.base.cdma_subscription_app_index = 1;
- p_card_status->base.base.base.ims_subscription_app_index = 2;
-
- // Get the correct app status
- p_card_status->base.base.base.applications[0] = app_status_array[sim_status];
- p_card_status->base.base.base.applications[1] = app_status_array[sim_status + RUIM_ABSENT];
- p_card_status->base.base.base.applications[2] = app_status_array[sim_status + ISIM_ABSENT];
- }
-
- *pp_card_status = p_card_status;
- return RIL_E_SUCCESS;
-}
-
-/**
- * Free the card status returned by getCardStatus
- */
-static void freeCardStatus(RIL_CardStatus_v1_5 *p_card_status) {
- if (p_card_status == NULL) {
- return;
- }
- free(p_card_status->base.base.iccid);
- free(p_card_status);
-}
-
-/**
- * SIM ready means any commands that access the SIM will work, including:
- * AT+CPIN, AT+CSMS, AT+CNMI, AT+CRSM
- * (all SMS-related commands)
- */
-
-static void pollSIMState (void *param __unused)
-{
- ATResponse *p_response;
- int ret;
-
- if (sState != RADIO_STATE_UNAVAILABLE) {
- // no longer valid to poll
- return;
- }
-
- switch(getSIMStatus()) {
- case SIM_ABSENT:
- case SIM_PIN:
- case SIM_PUK:
- case SIM_NETWORK_PERSONALIZATION:
- default:
- RLOGI("SIM ABSENT or LOCKED");
- RIL_onUnsolicitedResponse(RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED, NULL, 0);
- return;
-
- case SIM_NOT_READY:
- RIL_requestTimedCallback (pollSIMState, NULL, &TIMEVAL_SIMPOLL);
- return;
-
- case SIM_READY:
- RLOGI("SIM_READY");
- onSIMReady();
- RIL_onUnsolicitedResponse(RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED, NULL, 0);
- return;
- }
-}
-
-/** returns 1 if on, 0 if off, and -1 on error */
-static int isRadioOn()
-{
- ATResponse *p_response = NULL;
- int err;
- char *line;
- char ret;
-
- err = at_send_command_singleline("AT+CFUN?", "+CFUN:", &p_response);
-
- if (err < 0 || p_response->success == 0) {
- // assume radio is off
- goto error;
- }
-
- line = p_response->p_intermediates->line;
-
- err = at_tok_start(&line);
- if (err < 0) goto error;
-
- err = at_tok_nextbool(&line, &ret);
- if (err < 0) goto error;
-
- at_response_free(p_response);
-
- return (int)ret;
-
-error:
-
- at_response_free(p_response);
- return -1;
-}
-
-/**
- * Parse the response generated by a +CTEC AT command
- * The values read from the response are stored in current and preferred.
- * Both current and preferred may be null. The corresponding value is ignored in that case.
- *
- * @return: -1 if some error occurs (or if the modem doesn't understand the +CTEC command)
- * 1 if the response includes the current technology only
- * 0 if the response includes both current technology and preferred mode
- */
-int parse_technology_response( const char *response, int *current, int32_t *preferred )
-{
- int err;
- char *line, *p;
- int ct;
- int32_t pt = 0;
- char *str_pt;
-
- line = p = strdup(response);
- RLOGD("Response: %s", line);
- err = at_tok_start(&p);
- if (err || !at_tok_hasmore(&p)) {
- RLOGD("err: %d. p: %s", err, p);
- free(line);
- return -1;
- }
-
- err = at_tok_nextint(&p, &ct);
- if (err) {
- free(line);
- return -1;
- }
- if (current) *current = ct;
-
- RLOGD("line remaining after int: %s", p);
-
- err = at_tok_nexthexint(&p, &pt);
- if (err) {
- free(line);
- return 1;
- }
- if (preferred) {
- *preferred = pt;
- }
- free(line);
-
- return 0;
-}
-
-int query_supported_techs( ModemInfo *mdm __unused, int *supported )
-{
- ATResponse *p_response;
- int err, val, techs = 0;
- char *tok;
- char *line;
-
- RLOGD("query_supported_techs");
- err = at_send_command_singleline("AT+CTEC=?", "+CTEC:", &p_response);
- if (err || !p_response->success)
- goto error;
- line = p_response->p_intermediates->line;
- err = at_tok_start(&line);
- if (err || !at_tok_hasmore(&line))
- goto error;
- while (!at_tok_nextint(&line, &val)) {
- techs |= ( 1 << val );
- }
- if (supported) *supported = techs;
- return 0;
-error:
- at_response_free(p_response);
- return -1;
-}
-
-/**
- * query_ctec. Send the +CTEC AT command to the modem to query the current
- * and preferred modes. It leaves values in the addresses pointed to by
- * current and preferred. If any of those pointers are NULL, the corresponding value
- * is ignored, but the return value will still reflect if retrieving and parsing of the
- * values succeeded.
- *
- * @mdm Currently unused
- * @current A pointer to store the current mode returned by the modem. May be null.
- * @preferred A pointer to store the preferred mode returned by the modem. May be null.
- * @return -1 on error (or failure to parse)
- * 1 if only the current mode was returned by modem (or failed to parse preferred)
- * 0 if both current and preferred were returned correctly
- */
-int query_ctec(ModemInfo *mdm __unused, int *current, int32_t *preferred)
-{
- ATResponse *response = NULL;
- int err;
- int res;
-
- RLOGD("query_ctec. current: %p, preferred: %p", current, preferred);
- err = at_send_command_singleline("AT+CTEC?", "+CTEC:", &response);
- if (!err && response->success) {
- res = parse_technology_response(response->p_intermediates->line, current, preferred);
- at_response_free(response);
- return res;
- }
- RLOGE("Error executing command: %d. response: %p. status: %d", err, response, response? response->success : -1);
- at_response_free(response);
- return -1;
-}
-
-int is_multimode_modem(ModemInfo *mdm)
-{
- ATResponse *response;
- int err;
- char *line;
- int tech;
- int32_t preferred;
-
- if (query_ctec(mdm, &tech, &preferred) == 0) {
- mdm->currentTech = tech;
- mdm->preferredNetworkMode = preferred;
- if (query_supported_techs(mdm, &mdm->supportedTechs)) {
- return 0;
- }
- return 1;
- }
- return 0;
-}
-
-/**
- * Find out if our modem is GSM, CDMA or both (Multimode)
- */
-static void probeForModemMode(ModemInfo *info)
-{
- ATResponse *response;
- int err;
- assert (info);
- // Currently, our only known multimode modem is qemu's android modem,
- // which implements the AT+CTEC command to query and set mode.
- // Try that first
-
- if (is_multimode_modem(info)) {
- RLOGI("Found Multimode Modem. Supported techs mask: %8.8x. Current tech: %d",
- info->supportedTechs, info->currentTech);
- return;
- }
-
- /* Being here means that our modem is not multimode */
- info->isMultimode = 0;
-
- /* CDMA Modems implement the AT+WNAM command */
- err = at_send_command_singleline("AT+WNAM","+WNAM:", &response);
- if (!err && response->success) {
- at_response_free(response);
- // TODO: find out if we really support EvDo
- info->supportedTechs = MDM_CDMA | MDM_EVDO;
- info->currentTech = MDM_CDMA;
- RLOGI("Found CDMA Modem");
- return;
- }
- if (!err) at_response_free(response);
- // TODO: find out if modem really supports WCDMA/LTE
- info->supportedTechs = MDM_GSM | MDM_WCDMA | MDM_LTE;
- info->currentTech = MDM_GSM;
- RLOGI("Found GSM Modem");
-}
-
-/**
- * Initialize everything that can be configured while we're still in
- * AT+CFUN=0
- */
-static void initializeCallback(void *param __unused)
-{
- ATResponse *p_response = NULL;
- int err;
-
- setRadioState (RADIO_STATE_OFF);
-
- at_handshake();
-
- probeForModemMode(sMdmInfo);
- /* note: we don't check errors here. Everything important will
- be handled in onATTimeout and onATReaderClosed */
-
- /* atchannel is tolerant of echo but it must */
- /* have verbose result codes */
- at_send_command("ATE0Q0V1", NULL);
-
- /* No auto-answer */
- at_send_command("ATS0=0", NULL);
-
- /* Extended errors */
- at_send_command("AT+CMEE=1", NULL);
-
- /* Network registration events */
- err = at_send_command("AT+CREG=2", &p_response);
-
- /* some handsets -- in tethered mode -- don't support CREG=2 */
- if (err < 0 || p_response->success == 0) {
- at_send_command("AT+CREG=1", NULL);
- }
-
- at_response_free(p_response);
-
- /* GPRS registration events */
- at_send_command("AT+CGREG=1", NULL);
-
- /* Call Waiting notifications */
- at_send_command("AT+CCWA=1", NULL);
-
- /* Alternating voice/data off */
- at_send_command("AT+CMOD=0", NULL);
-
- /* Not muted */
- at_send_command("AT+CMUT=0", NULL);
-
- /* +CSSU unsolicited supp service notifications */
- at_send_command("AT+CSSN=0,1", NULL);
-
- /* no connected line identification */
- at_send_command("AT+COLP=0", NULL);
-
- /* HEX character set */
- at_send_command("AT+CSCS=\"HEX\"", NULL);
-
- /* USSD unsolicited */
- at_send_command("AT+CUSD=1", NULL);
-
- /* Enable +CGEV GPRS event notifications, but don't buffer */
- at_send_command("AT+CGEREP=1,0", NULL);
-
- /* SMS PDU mode */
- at_send_command("AT+CMGF=0", NULL);
-
-#ifdef USE_TI_COMMANDS
-
- at_send_command("AT%CPI=3", NULL);
-
- /* TI specific -- notifications when SMS is ready (currently ignored) */
- at_send_command("AT%CSTAT=1", NULL);
-
-#endif /* USE_TI_COMMANDS */
-
-
- /* assume radio is off on error */
- if (isRadioOn() > 0) {
- setRadioState (RADIO_STATE_ON);
- }
-}
-
-static void waitForClose()
-{
- pthread_mutex_lock(&s_state_mutex);
-
- while (s_closed == 0) {
- pthread_cond_wait(&s_state_cond, &s_state_mutex);
- }
-
- pthread_mutex_unlock(&s_state_mutex);
-}
-
-static void sendUnsolImsNetworkStateChanged()
-{
-#if 0 // to be used when unsol is changed to return data.
- int reply[2];
- reply[0] = s_ims_registered;
- reply[1] = s_ims_services;
- reply[1] = s_ims_format;
-#endif
- RIL_onUnsolicitedResponse(RIL_UNSOL_RESPONSE_IMS_NETWORK_STATE_CHANGED,
- NULL, 0);
-}
-
-static int parseProactiveCmdInd(char *response) {
- int typePos = 0;
- int cmdType = 0;
- char tempStr[3] = {0};
- char *end = NULL;
- StkUnsolEvent ret = STK_UNSOL_EVENT_UNKNOWN;
-
- if (response == NULL || strlen(response) < 3) {
- return ret;
- }
-
- if (response[2] <= '7') {
- typePos = 10;
- } else {
- typePos = 12;
- }
-
- if ((int)strlen(response) < typePos + 1) {
- return ret;
- }
-
- memcpy(tempStr, &(response[typePos]), 2);
- cmdType = strtoul(tempStr, &end, 16);
- cmdType = 0xFF & cmdType;
- RLOGD("cmdType: %d",cmdType);
-
- switch (cmdType) {
- case STK_RUN_AT:
- case STK_SEND_DTMF:
- case STK_SEND_SMS:
- case STK_SEND_SS:
- case STK_SEND_USSD:
- case STK_PLAY_TONE:
- case STK_CLOSE_CHANNEL:
- ret = STK_UNSOL_EVENT_NOTIFY;
- break;
- case STK_REFRESH:
- if (strncasecmp(&(response[typePos + 2]), "04", 2) == 0) { // SIM_RESET
- RLOGD("Type of Refresh is SIM_RESET");
- s_stkServiceRunning = false;
- ret = STK_UNSOL_PROACTIVE_CMD;
- } else {
- ret = STK_UNSOL_EVENT_NOTIFY;
- }
- break;
- default:
- ret = STK_UNSOL_PROACTIVE_CMD;
- break;
- }
-
- if (getSIMStatus() == SIM_ABSENT && s_stkServiceRunning) {
- s_stkServiceRunning = false;
- }
-
- if (false == s_stkServiceRunning) {
- ret = STK_UNSOL_EVENT_UNKNOWN;
- s_stkUnsolResponse = (char *)calloc((strlen(response) + 1), sizeof(char));
- snprintf(s_stkUnsolResponse, strlen(response) + 1, "%s", response);
- RLOGD("STK service is not running [%s]", s_stkUnsolResponse);
- }
-
- return ret;
-}
-
-/**
- * Called by atchannel when an unsolicited line appears
- * This is called on atchannel's reader thread. AT commands may
- * not be issued here
- */
-static void onUnsolicited (const char *s, const char *sms_pdu)
-{
- char *line = NULL, *p;
- int err;
-
- /* Ignore unsolicited responses until we're initialized.
- * This is OK because the RIL library will poll for initial state
- */
- if (sState == RADIO_STATE_UNAVAILABLE) {
- return;
- }
-
-#define CGFPCCFG "%CGFPCCFG:"
- if (strStartsWith(s, CGFPCCFG)) {
- /* cuttlefish/goldfish specific
- */
- char *response;
- line = p = strdup(s);
- RLOGD("got CGFPCCFG line %s and %s\n", s, p);
- err = at_tok_start(&line);
- if(err) {
- RLOGE("invalid CGFPCCFG line %s and %s\n", s, p);
- }
-#define kSize 5
- int configs[kSize];
- for (int i=0; i < kSize && !err; ++i) {
- err = at_tok_nextint(&line, &(configs[i]));
- RLOGD("got i %d, val = %d", i, configs[i]);
- }
- if(err) {
- RLOGE("invalid CGFPCCFG line %s and %s\n", s, p);
- } else {
- int modem_tech = configs[2];
- configs[2] = techFromModemType(modem_tech);
- RIL_onUnsolicitedResponse (
- RIL_UNSOL_PHYSICAL_CHANNEL_CONFIGS,
- configs, kSize);
- }
- free(p);
- } else if (strStartsWith(s, "%CTZV:")) {
- /* TI specific -- NITZ time */
- char *response;
-
- line = p = strdup(s);
- at_tok_start(&p);
-
- err = at_tok_nextstr(&p, &response);
-
- if (err != 0) {
- RLOGE("invalid NITZ line %s\n", s);
- } else {
- RIL_onUnsolicitedResponse (
- RIL_UNSOL_NITZ_TIME_RECEIVED,
- response, strlen(response) + 1);
- }
- free(line);
- } else if (strStartsWith(s,"+CRING:")
- || strStartsWith(s,"RING")
- || strStartsWith(s,"NO CARRIER")
- || strStartsWith(s,"+CCWA")
- ) {
- RIL_onUnsolicitedResponse (
- RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED,
- NULL, 0);
-#ifdef WORKAROUND_FAKE_CGEV
- RIL_requestTimedCallback (onDataCallListChanged, NULL, NULL); //TODO use new function
-#endif /* WORKAROUND_FAKE_CGEV */
- } else if (strStartsWith(s,"+CREG:")
- || strStartsWith(s,"+CGREG:")
- ) {
- RIL_onUnsolicitedResponse (
- RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED,
- NULL, 0);
-#ifdef WORKAROUND_FAKE_CGEV
- RIL_requestTimedCallback (onDataCallListChanged, NULL, NULL);
-#endif /* WORKAROUND_FAKE_CGEV */
- } else if (strStartsWith(s, "+CMT:")) {
- RIL_onUnsolicitedResponse (
- RIL_UNSOL_RESPONSE_NEW_SMS,
- sms_pdu, strlen(sms_pdu));
- } else if (strStartsWith(s, "+CDS:")) {
- RIL_onUnsolicitedResponse (
- RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT,
- sms_pdu, strlen(sms_pdu));
- } else if (strStartsWith(s, "+CGEV:")) {
- /* Really, we can ignore NW CLASS and ME CLASS events here,
- * but right now we don't since extranous
- * RIL_UNSOL_DATA_CALL_LIST_CHANGED calls are tolerated
- */
- /* can't issue AT commands here -- call on main thread */
- RIL_requestTimedCallback (onDataCallListChanged, NULL, NULL);
-#ifdef WORKAROUND_FAKE_CGEV
- } else if (strStartsWith(s, "+CME ERROR: 150")) {
- RIL_requestTimedCallback (onDataCallListChanged, NULL, NULL);
-#endif /* WORKAROUND_FAKE_CGEV */
- } else if (strStartsWith(s, "+CTEC: ")) {
- int tech, mask;
- switch (parse_technology_response(s, &tech, NULL))
- {
- case -1: // no argument could be parsed.
- RLOGE("invalid CTEC line %s\n", s);
- break;
- case 1: // current mode correctly parsed
- case 0: // preferred mode correctly parsed
- mask = 1 << tech;
- if (mask != MDM_GSM && mask != MDM_CDMA &&
- mask != MDM_WCDMA && mask != MDM_LTE) {
- RLOGE("Unknown technology %d\n", tech);
- } else {
- setRadioTechnology(sMdmInfo, tech);
- }
- break;
- }
- } else if (strStartsWith(s, "+CCSS: ")) {
- int source = 0;
- line = p = strdup(s);
- if (!line) {
- RLOGE("+CCSS: Unable to allocate memory");
- return;
- }
- if (at_tok_start(&p) < 0) {
- free(line);
- return;
- }
- if (at_tok_nextint(&p, &source) < 0) {
- RLOGE("invalid +CCSS response: %s", line);
- free(line);
- return;
- }
- SSOURCE(sMdmInfo) = source;
- RIL_onUnsolicitedResponse(RIL_UNSOL_CDMA_SUBSCRIPTION_SOURCE_CHANGED,
- &source, sizeof(source));
- free(line);
- } else if (strStartsWith(s, "+WSOS: ")) {
- char state = 0;
- int unsol;
- line = p = strdup(s);
- if (!line) {
- RLOGE("+WSOS: Unable to allocate memory");
- return;
- }
- if (at_tok_start(&p) < 0) {
- free(line);
- return;
- }
- if (at_tok_nextbool(&p, &state) < 0) {
- RLOGE("invalid +WSOS response: %s", line);
- free(line);
- return;
- }
- free(line);
-
- unsol = state ?
- RIL_UNSOL_ENTER_EMERGENCY_CALLBACK_MODE : RIL_UNSOL_EXIT_EMERGENCY_CALLBACK_MODE;
-
- RIL_onUnsolicitedResponse(unsol, NULL, 0);
-
- } else if (strStartsWith(s, "+WPRL: ")) {
- int version = -1;
- line = p = strdup(s);
- if (!line) {
- RLOGE("+WPRL: Unable to allocate memory");
- return;
- }
- if (at_tok_start(&p) < 0) {
- RLOGE("invalid +WPRL response: %s", s);
- free(line);
- return;
- }
- if (at_tok_nextint(&p, &version) < 0) {
- RLOGE("invalid +WPRL response: %s", s);
- free(line);
- return;
- }
- free(line);
- RIL_onUnsolicitedResponse(RIL_UNSOL_CDMA_PRL_CHANGED, &version, sizeof(version));
- } else if (strStartsWith(s, "+CFUN: 0")) {
- setRadioState(RADIO_STATE_OFF);
- } else if (strStartsWith(s, "+CSQ: ")) {
- // Accept a response that is at least v6, and up to v12
- int minNumOfElements=sizeof(RIL_SignalStrength_v6)/sizeof(int);
- int maxNumOfElements=sizeof(RIL_SignalStrength_v12)/sizeof(int);
- int response[maxNumOfElements];
- memset(response, 0, sizeof(response));
-
- line = p = strdup(s);
- at_tok_start(&p);
-
- for (int count = 0; count < maxNumOfElements; count++) {
- err = at_tok_nextint(&p, &(response[count]));
- if (err < 0 && count < minNumOfElements) {
- free(line);
- return;
- }
- }
-
- RIL_onUnsolicitedResponse(RIL_UNSOL_SIGNAL_STRENGTH,
- response, sizeof(response));
- free(line);
- } else if (strStartsWith(s, "+CUSATEND")) { // session end
- RIL_onUnsolicitedResponse(RIL_UNSOL_STK_SESSION_END, NULL, 0);
- } else if (strStartsWith(s, "+CUSATP:")) {
- line = p = strdup(s);
- if (!line) {
- RLOGE("+CUSATP: Unable to allocate memory");
- return;
- }
- if (at_tok_start(&p) < 0) {
- RLOGE("invalid +CUSATP response: %s", s);
- free(line);
- return;
- }
-
- char *response = NULL;
- if (at_tok_nextstr(&p, &response) < 0) {
- RLOGE("%s fail", s);
- free(line);
- return;
- }
-
- StkUnsolEvent ret = parseProactiveCmdInd(response);
- if (ret == STK_UNSOL_EVENT_NOTIFY) {
- RIL_onUnsolicitedResponse(RIL_UNSOL_STK_EVENT_NOTIFY, response,
- strlen(response) + 1);
- } else if (ret == STK_UNSOL_PROACTIVE_CMD) {
- RIL_onUnsolicitedResponse(RIL_UNSOL_STK_PROACTIVE_COMMAND, response,
- strlen(response) + 1);
- }
-
- free(line);
- }
-}
-
-/* Called on command or reader thread */
-static void onATReaderClosed()
-{
- RLOGI("AT channel closed\n");
- at_close();
- s_closed = 1;
-
- setRadioState (RADIO_STATE_UNAVAILABLE);
-}
-
-/* Called on command thread */
-static void onATTimeout()
-{
- RLOGI("AT channel timeout; closing\n");
- at_close();
-
- s_closed = 1;
-
- /* FIXME cause a radio reset here */
-
- setRadioState (RADIO_STATE_UNAVAILABLE);
-}
-
-/* Called to pass hardware configuration information to telephony
- * framework.
- */
-static void setHardwareConfiguration(int num, RIL_HardwareConfig *cfg)
-{
- RIL_onUnsolicitedResponse(RIL_UNSOL_HARDWARE_CONFIG_CHANGED, cfg, num*sizeof(*cfg));
-}
-
-static void usage(char *s __unused)
-{
-#ifdef RIL_SHLIB
- fprintf(stderr, "reference-ril requires: -p <tcp port> or -d /dev/tty_device\n");
-#else
- fprintf(stderr, "usage: %s [-p <tcp port>] [-d /dev/tty_device]\n", s);
- exit(-1);
-#endif
-}
-
-static void *
-mainLoop(void *param __unused)
-{
- int fd;
- int ret;
-
- AT_DUMP("== ", "entering mainLoop()", -1 );
- at_set_on_reader_closed(onATReaderClosed);
- at_set_on_timeout(onATTimeout);
-
- for (;;) {
- fd = -1;
- while (fd < 0) {
- if (isInEmulator()) {
- fd = qemu_open_modem_port();
- RLOGD("opening qemu_modem_port %d!", fd);
- } else if (s_port > 0) {
- fd = socket_network_client("localhost", s_port, SOCK_STREAM);
- } else if (s_modem_simulator_port >= 0) {
- fd = socket(AF_VSOCK, SOCK_STREAM, 0);
- if (fd < 0) {
- RLOGD("Can't create AF_VSOCK socket!");
- continue;
- }
- struct sockaddr_vm sa;
- memset(&sa, 0, sizeof(struct sockaddr_vm));
- sa.svm_family = AF_VSOCK;
- sa.svm_cid = VMADDR_CID_HOST;
- sa.svm_port = s_modem_simulator_port;
-
- if (connect(fd, (struct sockaddr *)(&sa), sizeof(sa)) < 0) {
- RLOGD("Can't connect to port:%ud, errno: %s",
- s_modem_simulator_port, strerror(errno));
- close(fd);
- fd = -1;
- continue;
- }
- } else if (s_device_socket) {
- fd = socket_local_client(s_device_path,
- ANDROID_SOCKET_NAMESPACE_FILESYSTEM,
- SOCK_STREAM);
- } else if (s_device_path != NULL) {
- fd = open (s_device_path, O_RDWR);
- if ( fd >= 0 && !memcmp( s_device_path, "/dev/ttyS", 9 ) ) {
- /* disable echo on serial ports */
- struct termios ios;
- tcgetattr( fd, &ios );
- ios.c_lflag = 0; /* disable ECHO, ICANON, etc... */
- tcsetattr( fd, TCSANOW, &ios );
- }
- }
-
- if (fd < 0) {
- perror ("opening AT interface. retrying...");
- sleep(10);
- /* never returns */
- }
- }
-
- s_closed = 0;
- ret = at_open(fd, onUnsolicited);
-
- if (ret < 0) {
- RLOGE ("AT error %d on at_open\n", ret);
- return 0;
- }
-
- RIL_requestTimedCallback(initializeCallback, NULL, &TIMEVAL_0);
-
- // Give initializeCallback a chance to dispatched, since
- // we don't presently have a cancellation mechanism
- sleep(1);
-
- waitForClose();
- RLOGI("Re-opening after close");
- }
-}
-
-#ifdef RIL_SHLIB
-
-pthread_t s_tid_mainloop;
-
-const RIL_RadioFunctions *RIL_Init(const struct RIL_Env *env, int argc, char **argv)
-{
- int ret;
- int fd = -1;
- int opt;
- pthread_attr_t attr;
-
- s_rilenv = env;
-
- RLOGD("RIL_Init");
- while ( -1 != (opt = getopt(argc, argv, "p:d:s:c:m:"))) {
- switch (opt) {
- case 'p':
- s_port = atoi(optarg);
- if (s_port == 0) {
- usage(argv[0]);
- return NULL;
- }
- RLOGI("Opening loopback port %d\n", s_port);
- break;
-
- case 'd':
- s_device_path = optarg;
- RLOGI("Opening tty device %s\n", s_device_path);
- break;
-
- case 's':
- s_device_path = optarg;
- s_device_socket = 1;
- RLOGI("Opening socket %s\n", s_device_path);
- break;
-
- case 'c':
- RLOGI("Client id received %s\n", optarg);
- break;
-
- case 'm':
- s_modem_simulator_port = strtoul(optarg, NULL, 10);
- RLOGI("Opening modem simulator port %ud\n", s_modem_simulator_port);
- break;
-
- default:
- usage(argv[0]);
- return NULL;
- }
- }
-
- if (s_port < 0 && s_device_path == NULL && !isInEmulator() &&
- s_modem_simulator_port < 0) {
- usage(argv[0]);
- return NULL;
- }
-
- sMdmInfo = calloc(1, sizeof(ModemInfo));
- if (!sMdmInfo) {
- RLOGE("Unable to alloc memory for ModemInfo");
- return NULL;
- }
- pthread_attr_init (&attr);
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
- ret = pthread_create(&s_tid_mainloop, &attr, mainLoop, NULL);
-
- return &s_callbacks;
-}
-#else /* RIL_SHLIB */
-int main (int argc, char **argv)
-{
- int ret;
- int fd = -1;
- int opt;
-
- while ( -1 != (opt = getopt(argc, argv, "p:d:"))) {
- switch (opt) {
- case 'p':
- s_port = atoi(optarg);
- if (s_port == 0) {
- usage(argv[0]);
- }
- RLOGI("Opening loopback port %d\n", s_port);
- break;
-
- case 'd':
- s_device_path = optarg;
- RLOGI("Opening tty device %s\n", s_device_path);
- break;
-
- case 's':
- s_device_path = optarg;
- s_device_socket = 1;
- RLOGI("Opening socket %s\n", s_device_path);
- break;
-
- default:
- usage(argv[0]);
- }
- }
-
- if (s_port < 0 && s_device_path == NULL && !isInEmulator()) {
- usage(argv[0]);
- }
-
- RIL_register(&s_callbacks);
-
- mainLoop(NULL);
-
- return 0;
-}
-
-#endif /* RIL_SHLIB */
diff --git a/guest/hals/rild/Android.mk b/guest/hals/rild/Android.mk
new file mode 100644
index 000000000..40e6b1000
--- /dev/null
+++ b/guest/hals/rild/Android.mk
@@ -0,0 +1,47 @@
+# Copyright (C) 2006 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.
+
+# only for PLATFORM_VERSION greater or equal to Q
+ifeq (true,$(ENABLE_CUTTLEFISH_RILD))
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ rild_cuttlefish.c
+
+LOCAL_SHARED_LIBRARIES := \
+ libcutils \
+ libdl \
+ liblog \
+ libril-cuttlefish-fork
+
+LOCAL_C_INCLUDES += \
+ device/google/cuttlefish
+
+# Temporary hack for broken vendor RILs.
+LOCAL_WHOLE_STATIC_LIBRARIES := \
+ librilutils
+
+LOCAL_CFLAGS := -DRIL_SHLIB
+LOCAL_CFLAGS += -Wall -Wextra -Werror
+
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_PROPRIETARY_MODULE := true
+LOCAL_MODULE:= libcuttlefish-rild
+LOCAL_OVERRIDES_PACKAGES := rild
+PACKAGES.$(LOCAL_MODULE).OVERRIDES := rild
+LOCAL_INIT_RC := rild_cuttlefish.rc
+
+include $(BUILD_EXECUTABLE)
+endif
diff --git a/guest/hals/rild/rild_cuttlefish.c b/guest/hals/rild/rild_cuttlefish.c
index 49f34eccf..cfd74fa33 100644
--- a/guest/hals/rild/rild_cuttlefish.c
+++ b/guest/hals/rild/rild_cuttlefish.c
@@ -24,7 +24,7 @@
#include <fcntl.h>
#include <errno.h>
-#include <guest/hals/ril/reference-libril/ril.h>
+#include <guest/hals/ril/libril/ril.h>
#define LOG_TAG "RILD"
#include <log/log.h>
@@ -34,8 +34,9 @@
#include <sys/prctl.h>
#include <sys/stat.h>
#include <sys/types.h>
-#include <guest/hals/ril/reference-libril/ril_ex.h>
+#include <guest/hals/ril/libril/ril_ex.h>
+#define LIB_PATH_PROPERTY "vendor.rild.libpath"
#define LIB_ARGS_PROPERTY "vendor.rild.libargs"
#define MAX_LIB_ARGS 16
@@ -108,9 +109,10 @@ int main(int argc, char **argv) {
// functions returned by ril init function in vendor ril
const RIL_RadioFunctions *funcs;
+ // lib path from rild.libpath property (if it's read)
+ char libPath[PROPERTY_VALUE_MAX];
// flat to indicate if -- parameters are present
unsigned char hasLibArgs = 0;
- char port[PROPERTY_VALUE_MAX] = {0};
int i;
// ril/socket id received as -c parameter, otherwise set to 0
@@ -147,12 +149,14 @@ int main(int argc, char **argv) {
clientId);
}
- property_get("ro.boot.modem_simulator_ports", port, "");
- if (strcmp(port, "") == 0) {
- // Assume "no-ril" case.
- goto done;
- } else {
- rilLibPath = "libcuttlefish-ril-2.so";
+ if (rilLibPath == NULL) {
+ if ( 0 == property_get(LIB_PATH_PROPERTY, libPath, NULL)) {
+ // No lib sepcified on the command line, and nothing set in props.
+ // Assume "no-ril" case.
+ goto done;
+ } else {
+ rilLibPath = libPath;
+ }
}
dlHandle = dlopen(rilLibPath, RTLD_NOW);
@@ -199,11 +203,6 @@ int main(int argc, char **argv) {
rilArgv[argc++] = (char*)clientId;
RLOGD("RIL_Init argc = %d clientId = %s", argc, rilArgv[argc-1]);
- if (strcmp(port, "")) {
- rilArgv[argc++] = "-m";
- rilArgv[argc++] = port;
- }
-
// Make sure there's a reasonable argv[0]
rilArgv[0] = argv[0];
diff --git a/guest/hals/rild/rild_cuttlefish.legacy.rc b/guest/hals/rild/rild_cuttlefish.legacy.rc
new file mode 100644
index 000000000..e9c2d0717
--- /dev/null
+++ b/guest/hals/rild/rild_cuttlefish.legacy.rc
@@ -0,0 +1,5 @@
+service ril-daemon /vendor/bin/hw/libcuttlefish-rild
+ class main
+ user radio
+ group radio cache inet misc audio log readproc wakelock
+ capabilities BLOCK_SUSPEND NET_ADMIN NET_RAW
diff --git a/guest/hals/rild/rild_cuttlefish.rc b/guest/hals/rild/rild_cuttlefish.rc
index 5757e9af9..9990a7a8a 100644
--- a/guest/hals/rild/rild_cuttlefish.rc
+++ b/guest/hals/rild/rild_cuttlefish.rc
@@ -1,5 +1,5 @@
service vendor.ril-daemon /vendor/bin/hw/libcuttlefish-rild
class main
user radio
- group radio inet misc audio log readproc wakelock
+ group radio cache inet misc audio log readproc wakelock
capabilities BLOCK_SUSPEND NET_ADMIN NET_RAW
diff --git a/guest/libs/wpa_supplicant_8_lib/Android.mk b/guest/libs/wpa_supplicant_8_lib/Android.mk
deleted file mode 100644
index 31179f5cc..000000000
--- a/guest/libs/wpa_supplicant_8_lib/Android.mk
+++ /dev/null
@@ -1,82 +0,0 @@
-# Copyright (C) 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-
-ifeq ($(WPA_SUPPLICANT_VERSION),VER_0_8_X)
-
-ifneq ($(BOARD_WPA_SUPPLICANT_DRIVER),)
- CONFIG_DRIVER_$(BOARD_WPA_SUPPLICANT_DRIVER) := y
-endif
-
-# Use a custom libnl on releases before N
-ifeq (0, $(shell test $(PLATFORM_SDK_VERSION) -lt 24; echo $$?))
-EXTERNAL_VSOC_LIBNL_INCLUDE := external/gce/libnl/include
-else
-EXTERNAL_VSOC_LIBNL_INCLUDE :=
-endif
-
-
-WPA_SUPPL_DIR = external/wpa_supplicant_8
-WPA_SRC_FILE :=
-
-include $(WPA_SUPPL_DIR)/wpa_supplicant/android.config
-
-WPA_SUPPL_DIR_INCLUDE = $(WPA_SUPPL_DIR)/src \
- $(WPA_SUPPL_DIR)/src/common \
- $(WPA_SUPPL_DIR)/src/drivers \
- $(WPA_SUPPL_DIR)/src/l2_packet \
- $(WPA_SUPPL_DIR)/src/utils \
- $(WPA_SUPPL_DIR)/src/wps \
- $(WPA_SUPPL_DIR)/wpa_supplicant \
- $(EXTERNAL_VSOC_LIBNL_INCLUDE)
-
-WPA_SUPPL_DIR_INCLUDE += external/libnl/include
-
-ifdef CONFIG_DRIVER_NL80211
-WPA_SRC_FILE += driver_cmd_nl80211.c
-endif
-
-ifeq ($(TARGET_ARCH),arm)
-# To force sizeof(enum) = 4
-L_CFLAGS += -mabi=aapcs-linux
-endif
-
-ifdef CONFIG_ANDROID_LOG
-L_CFLAGS += -DCONFIG_ANDROID_LOG
-endif
-
-########################
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := lib_driver_cmd_simulated_cf
-LOCAL_VENDOR_MODULE := true
-LOCAL_SHARED_LIBRARIES := libc libcutils
-
-LOCAL_CFLAGS := $(L_CFLAGS) \
- $(VSOC_VERSION_CFLAGS)
-
-LOCAL_SRC_FILES := $(WPA_SRC_FILE)
-
-LOCAL_C_INCLUDES := \
- device/google/cuttlefish_common \
- $(WPA_SUPPL_DIR_INCLUDE)\
-
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-include $(BUILD_STATIC_LIBRARY)
-
-########################
-
-endif
diff --git a/guest/libs/wpa_supplicant_8_lib/driver_cmd_nl80211.c b/guest/libs/wpa_supplicant_8_lib/driver_cmd_nl80211.c
deleted file mode 100644
index 71814989a..000000000
--- a/guest/libs/wpa_supplicant_8_lib/driver_cmd_nl80211.c
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*
- * Driver interaction with extended Linux CFG8021
- */
-
-#include "driver_cmd_nl80211.h"
-
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <linux/if.h>
-#include <linux/if_ether.h>
-#include <netinet/in.h>
-#include "driver_nl80211.h"
-
-#include "android_drv.h"
-#include "common.h"
-#include "config.h"
-#include "wpa_supplicant_i.h"
-
-int wpa_driver_nl80211_driver_cmd(void* priv, char* cmd, char* buf,
- size_t buf_len) {
- struct i802_bss* bss = priv;
- struct wpa_driver_nl80211_data* drv = bss->drv;
- struct ifreq ifr;
- android_wifi_priv_cmd priv_cmd;
- int ret = 0;
-
- D("%s: called", __FUNCTION__);
- if (os_strcasecmp(cmd, "STOP") == 0) {
- linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 0);
- wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "STOPPED");
- } else if (os_strcasecmp(cmd, "START") == 0) {
- linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 1);
- wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "STARTED");
- } else if (os_strcasecmp(cmd, "MACADDR") == 0) {
- u8 macaddr[ETH_ALEN] = {};
-
- ret = linux_get_ifhwaddr(drv->global->ioctl_sock, bss->ifname, macaddr);
- if (!ret)
- ret =
- os_snprintf(buf, buf_len, "Macaddr = " MACSTR "\n", MAC2STR(macaddr));
- } else if (os_strcasecmp(cmd, "RELOAD") == 0) {
- wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "HANGED");
- } else { // Use private command
- return 0;
- }
- return ret;
-}
-
-int wpa_driver_set_p2p_noa(void* priv, u8 count, int start, int duration) {
- D("%s: called", __FUNCTION__);
- return 0;
-}
-
-int wpa_driver_get_p2p_noa(void* priv, u8* buf, size_t len) {
- D("%s: called", __FUNCTION__);
- return 0;
-}
-
-int wpa_driver_set_p2p_ps(void* priv, int legacy_ps, int opp_ps, int ctwindow) {
- D("%s: called", __FUNCTION__);
- return -1;
-}
-
-int wpa_driver_set_ap_wps_p2p_ie(void* priv, const struct wpabuf* beacon,
- const struct wpabuf* proberesp,
- const struct wpabuf* assocresp) {
- D("%s: called", __FUNCTION__);
- return 0;
-}
diff --git a/guest/monitoring/Android.bp b/guest/monitoring/Android.bp
new file mode 100644
index 000000000..a7f69c0a1
--- /dev/null
+++ b/guest/monitoring/Android.bp
@@ -0,0 +1,19 @@
+//
+// 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.
+
+subdirs = [
+ "dumpstate_ext",
+ "tombstone_transmit",
+]
diff --git a/guest/monitoring/cuttlefish_service/Android.bp b/guest/monitoring/cuttlefish_service/Android.bp
deleted file mode 100644
index 133d233c2..000000000
--- a/guest/monitoring/cuttlefish_service/Android.bp
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2020 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-android_app {
- name: "CuttlefishService",
- vendor: true,
- srcs: ["java/**/*.java"],
- static_libs: ["guava"],
- sdk_version: "28",
- privileged: true,
- optimize: {
- proguard_flags_files: ["proguard.flags"],
- enabled: true,
- }
-}
diff --git a/vsoc_x86_only/BoardConfig.mk b/guest/monitoring/cuttlefish_service/Android.mk
index 8703a10ee..b08adaf8d 100644
--- a/vsoc_x86_only/BoardConfig.mk
+++ b/guest/monitoring/cuttlefish_service/Android.mk
@@ -1,5 +1,4 @@
-#
-# Copyright 2020 The Android Open-Source Project
+# Copyright (C) 2016 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -12,17 +11,19 @@
# 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.
-#
-
-#
-# x86 (32-bit kernel) target for Cuttlefish
-#
--include device/google/cuttlefish/shared/BoardConfig.mk
+LOCAL_PATH:= $(call my-dir)
-TARGET_BOARD_PLATFORM := vsoc_x86
-TARGET_ARCH := x86
-TARGET_ARCH_VARIANT := x86
-TARGET_CPU_ABI := x86
+include $(CLEAR_VARS)
+LOCAL_MODULE_TAGS := optional
+LOCAL_SRC_FILES := $(call all-java-files-under, java)
+LOCAL_STATIC_JAVA_LIBRARIES := guava
+LOCAL_PACKAGE_NAME := CuttlefishService
+LOCAL_SDK_VERSION := 28
+LOCAL_PRIVILEGED_MODULE := true
+LOCAL_PROGUARD_FLAGS := -include build/core/proguard.flags
+LOCAL_PROGUARD_FLAG_FILES := proguard.flags
+LOCAL_PROGUARD_ENABLED := obfuscation
+LOCAL_VENDOR_MODULE := true
-BOARD_VENDOR_RAMDISK_KERNEL_MODULES += $(wildcard device/google/cuttlefish_prebuilts/kernel/$(TARGET_KERNEL_USE)-i686/*.ko)
+include $(BUILD_PACKAGE)
diff --git a/guest/monitoring/cuttlefish_service/java/com/android/google/gce/gceservice/EventReporter.java b/guest/monitoring/cuttlefish_service/java/com/android/google/gce/gceservice/BootReporter.java
index 5d9b02f34..b866b356e 100644
--- a/guest/monitoring/cuttlefish_service/java/com/android/google/gce/gceservice/EventReporter.java
+++ b/guest/monitoring/cuttlefish_service/java/com/android/google/gce/gceservice/BootReporter.java
@@ -27,13 +27,13 @@ import java.util.Calendar;
import java.util.List;
/**
- * Report virtual device boot status and other messages to console.
+ * Report boot status to console.
*
* This class sends messages to kernel log (and serial console) directly by
* writing to /dev/kmsg.
*/
-public class EventReporter extends JobBase {
- private static final String LOG_TAG = "GceEventReporter";
+public class BootReporter extends JobBase {
+ private static final String LOG_TAG = "GceBootReporter";
private static final int KLOG_NOTICE = 5;
private static final String KLOG_OUTPUT = "/dev/kmsg";
private static final String KLOG_FORMAT = "<%d>%s: %s\n";
@@ -41,14 +41,13 @@ public class EventReporter extends JobBase {
private static final String VIRTUAL_DEVICE_BOOT_PENDING = "VIRTUAL_DEVICE_BOOT_PENDING";
private static final String VIRTUAL_DEVICE_BOOT_COMPLETED = "VIRTUAL_DEVICE_BOOT_COMPLETED";
private static final String VIRTUAL_DEVICE_BOOT_FAILED = "VIRTUAL_DEVICE_BOOT_FAILED";
- private static final String VIRTUAL_DEVICE_SCREEN_CHANGED = "VIRTUAL_DEVICE_SCREEN_CHANGED";
private FileOutputStream mKmsgStream = null;
private PrintWriter mKmsgWriter = null;
private List<String> mMessageList = new ArrayList<String>();
/** Constructor. */
- public EventReporter() {
+ public BootReporter() {
super(LOG_TAG);
try {
@@ -123,12 +122,6 @@ public class EventReporter extends JobBase {
reportMessage(VIRTUAL_DEVICE_BOOT_STARTED);
}
- public void reportScreenChanged(int width, int height, int dpi, int rotation) {
- reportMessage(String.format("%s width=%d height=%d dpi=%d rotation=%d",
- VIRTUAL_DEVICE_SCREEN_CHANGED,
- width, height, dpi, rotation));
- }
-
/** Get the list of reported messages so far.
*/
public List<String> getMessageList() {
diff --git a/guest/monitoring/cuttlefish_service/java/com/android/google/gce/gceservice/ConnectivityChecker.java b/guest/monitoring/cuttlefish_service/java/com/android/google/gce/gceservice/ConnectivityChecker.java
index 43f4e3b7b..1354021bc 100644
--- a/guest/monitoring/cuttlefish_service/java/com/android/google/gce/gceservice/ConnectivityChecker.java
+++ b/guest/monitoring/cuttlefish_service/java/com/android/google/gce/gceservice/ConnectivityChecker.java
@@ -28,20 +28,17 @@ public class ConnectivityChecker extends JobBase {
private static final String LOG_TAG = "GceConnChecker";
private static final String MOBILE_NETWORK_CONNECTED_MESSAGE =
"VIRTUAL_DEVICE_NETWORK_MOBILE_CONNECTED";
- private static final String ETHERNET_NETWORK_CONNECTED_MESSAGE =
- "VIRTUAL_DEVICE_NETWORK_ETHERNET_CONNECTED";
private final Context mContext;
- private final EventReporter mEventReporter;
+ private final BootReporter mBootReporter;
private final GceFuture<Boolean> mConnected = new GceFuture<Boolean>("Connectivity");
// TODO(schuffelen): Figure out why this has to be static in order to not report 3 times.
private static boolean reportedMobileConnectivity = false;
- private static boolean reportedEthernetConnectivity = false;
- public ConnectivityChecker(Context context, EventReporter eventReporter) {
+ public ConnectivityChecker(Context context, BootReporter bootReporter) {
super(LOG_TAG);
mContext = context;
- mEventReporter = eventReporter;
+ mBootReporter = bootReporter;
}
@@ -57,16 +54,11 @@ public class ConnectivityChecker extends JobBase {
NetworkInfo info = connManager.getNetworkInfo(network);
if (info.isConnected()) {
NetworkCapabilities capabilities = connManager.getNetworkCapabilities(network);
- if (capabilities != null) {
- if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)
- && !reportedMobileConnectivity) {
- mEventReporter.reportMessage(MOBILE_NETWORK_CONNECTED_MESSAGE);
- reportedMobileConnectivity = true;
- } else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)
- && !reportedEthernetConnectivity) {
- mEventReporter.reportMessage(ETHERNET_NETWORK_CONNECTED_MESSAGE);
- reportedEthernetConnectivity = true;
- }
+ if (capabilities != null
+ && capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)
+ && !reportedMobileConnectivity) {
+ mBootReporter.reportMessage(MOBILE_NETWORK_CONNECTED_MESSAGE);
+ reportedMobileConnectivity = true;
}
}
}
diff --git a/guest/monitoring/cuttlefish_service/java/com/android/google/gce/gceservice/GceService.java b/guest/monitoring/cuttlefish_service/java/com/android/google/gce/gceservice/GceService.java
index 80d497a10..8e7bcc55d 100644
--- a/guest/monitoring/cuttlefish_service/java/com/android/google/gce/gceservice/GceService.java
+++ b/guest/monitoring/cuttlefish_service/java/com/android/google/gce/gceservice/GceService.java
@@ -23,20 +23,16 @@ import android.bluetooth.BluetoothAdapter;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.content.res.Configuration;
-import android.graphics.Point;
import android.net.ConnectivityManager;
import android.util.Log;
import android.os.IBinder;
-import android.view.Display;
-import android.view.WindowManager;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.List;
/**
* Service is started by the BootCompletedReceiver at the end of Android Boot process.
- * Responsible for emitting final BOOT_COMPLETED message and continued configuration changes.
+ * Responsible for final configuration changes and emitting final BOOT_COMPLETED message.
*/
public class GceService extends Service {
private static final String LOG_TAG = "GceService";
@@ -49,19 +45,13 @@ public class GceService extends Service {
private static final int NOTIFICATION_ID = 1;
private final JobExecutor mExecutor = new JobExecutor();
- private final EventReporter mEventReporter = new EventReporter();
+ private final BootReporter mBootReporter = new BootReporter();
private final GceBroadcastReceiver mBroadcastReceiver = new GceBroadcastReceiver();
private final BluetoothChecker mBluetoothChecker = new BluetoothChecker();
private ConnectivityChecker mConnChecker;
private GceWifiManager mWifiManager = null;
private String mMostRecentAction = null;
- private WindowManager mWindowManager;
-
- private int mPreviousRotation;
- private Point mPreviousScreenBounds;
- private int mPreviousDpi;
-
public GceService() {}
@@ -70,22 +60,17 @@ public class GceService extends Service {
public void onCreate() {
try {
super.onCreate();
- mEventReporter.reportBootStarted();
+ mBootReporter.reportBootStarted();
registerBroadcastReceivers();
- mWindowManager = getSystemService(WindowManager.class);
- mConnChecker = new ConnectivityChecker(this, mEventReporter);
- mWifiManager = new GceWifiManager(this, mEventReporter, mExecutor);
-
- mPreviousRotation = getRotation();
- mPreviousScreenBounds = getScreenBounds();
- mPreviousDpi = getResources().getConfiguration().densityDpi;
+ mConnChecker = new ConnectivityChecker(this, mBootReporter);
+ mWifiManager = new GceWifiManager(this, mBootReporter, mExecutor);
mExecutor.schedule(mWifiManager);
mExecutor.schedule(mBluetoothChecker);
mExecutor.schedule(mConnChecker);
- mExecutor.schedule(mEventReporter, mBluetoothChecker.getEnabled());
+ mExecutor.schedule(mBootReporter, mBluetoothChecker.getEnabled());
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
@@ -120,42 +105,6 @@ public class GceService extends Service {
this.registerReceiver(mBroadcastReceiver, filter);
}
- private Point getScreenBounds() {
- Display display = mWindowManager.getDefaultDisplay();
- Point screenBounds = new Point();
- display.getRealSize(screenBounds);
- return screenBounds;
- }
-
- private int getRotation() {
- return mWindowManager.getDefaultDisplay().getRotation();
- }
-
- @Override
- public void onConfigurationChanged(Configuration config) {
- super.onConfigurationChanged(config);
-
- int rotation = getRotation();
- Point screenBounds = getScreenBounds();
- int dpi = config.densityDpi;
- // NOTE: We cannot rely on config.diff(previous config) here because
- // diff shows CONFIG_SCREEN_SIZE changes when changing between 3-button
- // and gesture navigation. We only care about the display bounds.
- if (rotation == mPreviousRotation &&
- screenBounds.equals(mPreviousScreenBounds) &&
- dpi == mPreviousDpi) {
- return;
- }
-
- int width = screenBounds.x;
- int height = screenBounds.y;
- mEventReporter.reportScreenChanged(width, height, dpi, rotation);
-
- mPreviousRotation = rotation;
- mPreviousScreenBounds = screenBounds;
- mPreviousDpi = dpi;
- }
-
/** StartService entry point.
*/
@@ -178,8 +127,6 @@ public class GceService extends Service {
.setSmallIcon(android.R.drawable.ic_dialog_info)
.setTimeoutAfter(10000)
.build();
- // Start in the Foreground (and do not stop) so that this service
- // continues running and reporting events without being killed.
startForeground(NOTIFICATION_ID, notification);
if (INTENT_ACTION_CONFIGURE.equals(mMostRecentAction)) {
@@ -190,6 +137,8 @@ public class GceService extends Service {
mExecutor.schedule(mBluetoothChecker);
}
+ stopForeground(Service.STOP_FOREGROUND_DETACH);
+
/* If anything goes wrong, make sure we receive intent again. */
return Service.START_STICKY;
}
@@ -203,8 +152,8 @@ public class GceService extends Service {
*/
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- pw.println("Virtual Device reporter:");
- List<String> messageList = mEventReporter.getMessageList();
+ pw.println("Boot reporter:");
+ List<String> messageList = mBootReporter.getMessageList();
for (int i = 0; i < messageList.size(); i++) {
pw.println(" " + messageList.get(i));
}
diff --git a/guest/monitoring/cuttlefish_service/java/com/android/google/gce/gceservice/GceWifiManager.java b/guest/monitoring/cuttlefish_service/java/com/android/google/gce/gceservice/GceWifiManager.java
index a0dbd403f..1b07c04f6 100644
--- a/guest/monitoring/cuttlefish_service/java/com/android/google/gce/gceservice/GceWifiManager.java
+++ b/guest/monitoring/cuttlefish_service/java/com/android/google/gce/gceservice/GceWifiManager.java
@@ -41,18 +41,18 @@ public class GceWifiManager extends JobBase {
private final Context mContext;
private final WifiManager mWifiManager;
private final ConnectivityManager mConnManager;
- private final EventReporter mEventReporter;
+ private final BootReporter mBootReporter;
private final MonitorWifiJob mMonitorWifiJob;
- public GceWifiManager(Context context, EventReporter eventReporter, JobExecutor executor) {
+ public GceWifiManager(Context context, BootReporter bootReporter, JobExecutor executor) {
super(LOG_TAG);
mContext = context;
mWifiManager = (WifiManager)context.getSystemService(Context.WIFI_SERVICE);
mConnManager = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
- mEventReporter = eventReporter;
+ mBootReporter = bootReporter;
mJobExecutor = executor;
mMonitorWifiJob = new MonitorWifiJob();
}
@@ -108,7 +108,7 @@ public class GceWifiManager extends JobBase {
}
return WIFI_RECONNECTION_TIMEOUT_S;
} else {
- mEventReporter.reportMessage(WIFI_CONNECTED_MESSAGE);
+ mBootReporter.reportMessage(WIFI_CONNECTED_MESSAGE);
Log.i(LOG_TAG, "Wifi connected.");
mWifiReady.set(true);
return 0;
diff --git a/guest/monitoring/tombstone_transmit/Android.bp b/guest/monitoring/tombstone_transmit/Android.bp
index d24985a25..a4739e4ec 100644
--- a/guest/monitoring/tombstone_transmit/Android.bp
+++ b/guest/monitoring/tombstone_transmit/Android.bp
@@ -13,10 +13,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
cc_binary {
name: "tombstone_transmit",
srcs: [
diff --git a/guest/monitoring/tombstone_transmit/tombstone_transmit.cpp b/guest/monitoring/tombstone_transmit/tombstone_transmit.cpp
index 3d08780dd..c2e07eeda 100644
--- a/guest/monitoring/tombstone_transmit/tombstone_transmit.cpp
+++ b/guest/monitoring/tombstone_transmit/tombstone_transmit.cpp
@@ -108,7 +108,7 @@ int main(int argc, char** argv) {
if(ts_path.empty()) {continue;}
- auto log_fd = cuttlefish::SharedFD::VsockClient(FLAGS_cid, FLAGS_port,
+ auto log_fd = cvd::SharedFD::VsockClient(FLAGS_cid, FLAGS_port,
SOCK_STREAM);
std::ifstream ifs(ts_path);
diff --git a/guest/services/suspend_blocker/Android.bp b/guest/services/suspend_blocker/Android.bp
index 6412632cc..c87c4da92 100644
--- a/guest/services/suspend_blocker/Android.bp
+++ b/guest/services/suspend_blocker/Android.bp
@@ -12,13 +12,9 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
cc_binary {
name: "suspend_blocker",
srcs: ["suspend_blocker.cpp"],
shared_libs: ["libpower"],
- defaults: ["cuttlefish_guest_only"],
+ defaults: ["cuttlefish_guest_product_only"],
}
diff --git a/guest/services/suspend_blocker/suspend_blocker.cpp b/guest/services/suspend_blocker/suspend_blocker.cpp
index 2228b8a44..120a01b8d 100644
--- a/guest/services/suspend_blocker/suspend_blocker.cpp
+++ b/guest/services/suspend_blocker/suspend_blocker.cpp
@@ -18,10 +18,7 @@
#include <wakelock/wakelock.h>
int main() {
- auto wl = android::wakelock::WakeLock::tryGet("suspend_blocker"); // RAII object
- if (!wl.has_value()) {
- return EXIT_FAILURE;
- }
+ android::wakelock::WakeLock wl{"suspend_blocker"}; // RAII object
sigset_t mask;
sigemptyset(&mask);
diff --git a/host/Android.bp b/host/Android.bp
new file mode 100644
index 000000000..2280c23eb
--- /dev/null
+++ b/host/Android.bp
@@ -0,0 +1,20 @@
+//
+// 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.
+
+subdirs = [
+ "commands",
+ "frontend",
+ "libs",
+]
diff --git a/host/commands/Android.bp b/host/commands/Android.bp
new file mode 100644
index 000000000..c200611eb
--- /dev/null
+++ b/host/commands/Android.bp
@@ -0,0 +1,28 @@
+//
+// 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.
+
+subdirs = [
+ "adbshell",
+ "fetch_cvd",
+ "launch",
+ "stop_cvd",
+ "ivserver",
+ "virtual_usb_manager",
+ "kernel_log_monitor",
+ "config_server",
+ "console_forwarder",
+ "run_cvd",
+ "assemble_cvd",
+]
diff --git a/host/commands/adbshell/Android.bp b/host/commands/adbshell/Android.bp
index 883503eb7..ea84dd406 100644
--- a/host/commands/adbshell/Android.bp
+++ b/host/commands/adbshell/Android.bp
@@ -13,10 +13,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
cc_binary_host {
name: "adbshell",
srcs: [
@@ -33,5 +29,5 @@ cc_binary_host {
"libcuttlefish_host_config",
"libjsoncpp",
],
- defaults: ["cuttlefish_buildhost_only"],
+ defaults: ["cuttlefish_host_only"],
}
diff --git a/host/commands/adbshell/main.cpp b/host/commands/adbshell/main.cpp
index 7263f4c34..95f5fefe3 100644
--- a/host/commands/adbshell/main.cpp
+++ b/host/commands/adbshell/main.cpp
@@ -16,6 +16,8 @@
/* Utility that uses an adb connection as the login shell. */
+#include "host/libs/config/cuttlefish_config.h"
+
#include <array>
#include <cassert>
#include <cstdio>
@@ -27,9 +29,6 @@
#include <errno.h>
#include <unistd.h>
-#include "common/libs/utils/environment.h"
-#include "host/libs/config/cuttlefish_config.h"
-
// Many of our users interact with CVDs via ssh. They expect to be able to
// get an Android shell (as opposed to the host shell) with a single command.
//
@@ -52,12 +51,13 @@
namespace {
std::string VsocUser() {
- std::string user = cuttlefish::StringFromEnv("USER", "");
- assert(!user_cstring.empty());
+ const char* user_cstring = std::getenv("USER");
+ assert(user_cstring != nullptr);
+ std::string user(user_cstring);
std::string cvd_prefix = "cvd-";
if (user.find(cvd_prefix) == 0) {
- user.replace(0, cvd_prefix.size(), cuttlefish::kVsocUserPrefix);
+ user.replace(0, cvd_prefix.size(), vsoc::kVsocUserPrefix);
}
return user;
}
@@ -76,14 +76,14 @@ std::string CuttlefishFindAdb() {
}
void SetCuttlefishConfigEnv() {
- setenv(cuttlefish::kCuttlefishConfigEnvVarName, CuttlefishConfigLocation().c_str(),
+ setenv(vsoc::kCuttlefishConfigEnvVarName, CuttlefishConfigLocation().c_str(),
true);
}
} // namespace
int main(int argc, char* argv[]) {
SetCuttlefishConfigEnv();
- auto instance = cuttlefish::CuttlefishConfig::Get()
+ auto instance = vsoc::CuttlefishConfig::Get()
->ForDefaultInstance().adb_device_name();
std::string adb_path = CuttlefishFindAdb();
diff --git a/host/commands/assemble_cvd/Android.bp b/host/commands/assemble_cvd/Android.bp
index 4ed4452ae..0d5a1d740 100644
--- a/host/commands/assemble_cvd/Android.bp
+++ b/host/commands/assemble_cvd/Android.bp
@@ -13,20 +13,29 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
+cc_library_host_shared {
+ name: "cdisk_spec",
+ srcs: [
+ "cdisk_spec.proto",
+ ],
+ proto: {
+ type: "full",
+ export_proto_headers: true,
+ include_dirs: [
+ "external/protobuf/src",
+ ],
+ },
+ defaults: ["cuttlefish_host_only"],
}
-cc_binary {
+cc_binary_host {
name: "assemble_cvd",
srcs: [
- "alloc.cc",
"assemble_cvd.cc",
- "boot_config.cc",
- "boot_image_utils.cc",
- "clean.cc",
- "disk_flags.cc",
+ "boot_image_unpacker.cc",
+ "data_image.cc",
"flags.cc",
+ "image_aggregator.cc",
"misc_info.cc",
"super_image_mixer.cc",
],
@@ -34,28 +43,28 @@ cc_binary {
"bootimg_headers",
],
shared_libs: [
+ "cdisk_spec",
"libcuttlefish_fs",
"libcuttlefish_utils",
"libbase",
- "libjsoncpp",
"libnl",
"libprotobuf-cpp-full",
"libziparchive",
"libz",
- "libcuttlefish_allocd_utils",
],
static_libs: [
- "libcdisk_spec",
- "libext2_uuid",
- "libimage_aggregator",
"libsparse",
- "libcuttlefish_graphics_detector",
"libcuttlefish_host_config",
"libcuttlefish_vm_manager",
"libgflags",
+ "libxml2",
+ "libjsoncpp",
],
- required: [
- "lz4",
- ],
- defaults: ["cuttlefish_host", "cuttlefish_libicuuc"],
+ defaults: ["cuttlefish_host_only", "cuttlefish_libicuuc"],
+}
+
+python_binary_host {
+ name: "cf_bpttool",
+ srcs: [ "cf_bpttool.py" ],
+ defaults: ["py2_only"],
}
diff --git a/host/commands/assemble_cvd/alloc.cc b/host/commands/assemble_cvd/alloc.cc
deleted file mode 100644
index 62b1b7884..000000000
--- a/host/commands/assemble_cvd/alloc.cc
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * Copyright (C) 2020 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 "host/commands/assemble_cvd/alloc.h"
-
-#include <iomanip>
-#include <sstream>
-
-#include "common/libs/fs/shared_fd.h"
-#include "host/libs/allocd/request.h"
-#include "host/libs/allocd/utils.h"
-
-namespace cuttlefish {
-
-static std::string StrForInstance(const std::string& prefix, int num) {
- std::ostringstream stream;
- stream << prefix << std::setfill('0') << std::setw(2) << num;
- return stream.str();
-}
-
-IfaceConfig DefaultNetworkInterfaces(int num) {
- IfaceConfig config{};
- config.mobile_tap.name = StrForInstance("cvd-mtap-", num);
- config.mobile_tap.resource_id = 0;
- config.mobile_tap.session_id = 0;
-
- config.wireless_tap.name = StrForInstance("cvd-wtap-", num);
- config.wireless_tap.resource_id = 0;
- config.wireless_tap.session_id = 0;
-
- config.ethernet_tap.name = StrForInstance("cvd-etap-", num);
- config.ethernet_tap.resource_id = 0;
- config.ethernet_tap.session_id = 0;
-
- return config;
-}
-
-std::optional<IfaceConfig> AllocateNetworkInterfaces() {
- IfaceConfig config{};
-
- SharedFD allocd_sock = SharedFD::SocketLocalClient(
- kDefaultLocation, false, SOCK_STREAM);
- CHECK(allocd_sock->IsOpen())
- << "Unable to connect to allocd on " << kDefaultLocation
- << ": " << allocd_sock->StrError();
-
- Json::Value resource_config;
- Json::Value request_list;
- Json::Value req;
- req["request_type"] = "create_interface";
- req["uid"] = geteuid();
- req["iface_type"] = "mtap";
- request_list.append(req);
- req["iface_type"] = "wtap";
- request_list.append(req);
- req["iface_type"] = "etap";
- request_list.append(req);
-
- resource_config["config_request"]["request_list"] = request_list;
-
- CHECK(SendJsonMsg(allocd_sock, resource_config))
- << "Failed to send JSON to allocd";
-
- auto resp_opt = RecvJsonMsg(allocd_sock);
- CHECK(resp_opt.has_value()) << "Bad response from allocd";
- auto resp = resp_opt.value();
-
- CHECK(resp.isMember("config_status") && !resp["config_status"].isString())
- << "Bad response from allocd: " << resp;
-
- CHECK_EQ(
- resp["config_status"].asString(),
- StatusToStr(RequestStatus::Success))
- <<"Failed to allocate interfaces " << resp;
-
- CHECK(resp.isMember("session_id") && resp["session_id"].isUInt())
- << "Bad response from allocd: " << resp;
- auto session_id = resp["session_id"].asUInt();
-
- CHECK(resp.isMember("response_list") && resp["response_list"].isArray())
- << "Bad response from allocd: " << resp;
-
- Json::Value resp_list = resp["response_list"];
- Json::Value mtap_resp;
- Json::Value wtap_resp;
- Json::Value etap_resp;
- for (Json::Value::ArrayIndex i = 0; i != resp_list.size(); ++i) {
- auto ty = StrToIfaceTy(resp_list[i]["iface_type"].asString());
-
- switch (ty) {
- case IfaceType::mtap: {
- mtap_resp = resp_list[i];
- break;
- }
- case IfaceType::wtap: {
- wtap_resp = resp_list[i];
- break;
- }
- case IfaceType::etap: {
- etap_resp = resp_list[i];
- break;
- }
- default: {
- break;
- }
- }
- }
-
- if (!mtap_resp.isMember("iface_type")) {
- LOG(ERROR) << "Missing mtap response from allocd";
- return std::nullopt;
- }
- if (!wtap_resp.isMember("iface_type")) {
- LOG(ERROR) << "Missing wtap response from allocd";
- return std::nullopt;
- }
- if (!etap_resp.isMember("iface_type")) {
- LOG(ERROR) << "Missing etap response from allocd";
- return std::nullopt;
- }
-
- config.mobile_tap.name = mtap_resp["iface_name"].asString();
- config.mobile_tap.resource_id = mtap_resp["resource_id"].asUInt();
- config.mobile_tap.session_id = session_id;
-
- config.wireless_tap.name = wtap_resp["iface_name"].asString();
- config.wireless_tap.resource_id = wtap_resp["resource_id"].asUInt();
- config.wireless_tap.session_id = session_id;
-
- config.ethernet_tap.name = etap_resp["iface_name"].asString();
- config.ethernet_tap.resource_id = etap_resp["resource_id"].asUInt();
- config.ethernet_tap.session_id = session_id;
-
- return config;
-}
-
-} // namespace cuttlefish
diff --git a/host/commands/assemble_cvd/alloc.h b/host/commands/assemble_cvd/alloc.h
deleted file mode 100644
index d74c2b2ba..000000000
--- a/host/commands/assemble_cvd/alloc.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2020 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 <optional>
-#include <string>
-
-namespace cuttlefish {
-
-struct IfaceData {
- std::string name;
- uint32_t session_id;
- uint32_t resource_id;
-};
-
-struct IfaceConfig {
- IfaceData mobile_tap;
- IfaceData wireless_tap;
- IfaceData ethernet_tap;
-};
-
-IfaceConfig DefaultNetworkInterfaces(int num);
-
-// Acquires interfaces from the resource allocator daemon.
-std::optional<IfaceConfig> AllocateNetworkInterfaces();
-
-} // namespace cuttlefish
diff --git a/host/commands/assemble_cvd/assemble_cvd.cc b/host/commands/assemble_cvd/assemble_cvd.cc
index 27eadb520..63bc4f745 100644
--- a/host/commands/assemble_cvd/assemble_cvd.cc
+++ b/host/commands/assemble_cvd/assemble_cvd.cc
@@ -17,41 +17,22 @@
#include <android-base/strings.h>
#include <android-base/logging.h>
-#include <gflags/gflags.h>
#include "common/libs/fs/shared_buf.h"
#include "common/libs/fs/shared_fd.h"
-#include "common/libs/utils/environment.h"
-#include "common/libs/utils/files.h"
-#include "common/libs/utils/tee_logging.h"
-#include "host/commands/assemble_cvd/clean.h"
-#include "host/commands/assemble_cvd/disk_flags.h"
+#include "host/commands/assemble_cvd/assembler_defs.h"
#include "host/commands/assemble_cvd/flags.h"
#include "host/libs/config/fetcher_config.h"
-using cuttlefish::StringFromEnv;
-
-DEFINE_string(assembly_dir, StringFromEnv("HOME", ".") + "/cuttlefish_assembly",
- "A directory to put generated files common between instances");
-DEFINE_string(instance_dir, StringFromEnv("HOME", ".") + "/cuttlefish_runtime",
- "A directory to put all instance specific files");
-DEFINE_bool(resume, true, "Resume using the disk from the last session, if "
- "possible. i.e., if --noresume is passed, the disk "
- "will be reset to the state it was initially launched "
- "in. This flag is ignored if the underlying partition "
- "images have been updated since the first launch.");
-DEFINE_int32(modem_simulator_count, 1,
- "Modem simulator count corresponding to maximum sim number");
-
-namespace cuttlefish {
namespace {
std::string kFetcherConfigFile = "fetcher_config.json";
-FetcherConfig FindFetcherConfig(const std::vector<std::string>& files) {
- FetcherConfig fetcher_config;
+cvd::FetcherConfig FindFetcherConfig(const std::vector<std::string>& files) {
+ cvd::FetcherConfig fetcher_config;
for (const auto& file : files) {
- if (android::base::EndsWith(file, kFetcherConfigFile)) {
+ auto expected_pos = file.size() - kFetcherConfigFile.size();
+ if (file.rfind(kFetcherConfigFile) == expected_pos) {
if (fetcher_config.LoadFromFile(file)) {
return fetcher_config;
}
@@ -61,205 +42,39 @@ FetcherConfig FindFetcherConfig(const std::vector<std::string>& files) {
return fetcher_config;
}
-std::string GetLegacyConfigFilePath(const CuttlefishConfig& config) {
- return config.ForDefaultInstance().PerInstancePath("cuttlefish_config.json");
-}
-
-bool SaveConfig(const CuttlefishConfig& tmp_config_obj) {
- auto config_file = GetConfigFilePath(tmp_config_obj);
- auto config_link = GetGlobalConfigFileLink();
- // Save the config object before starting any host process
- if (!tmp_config_obj.SaveToFile(config_file)) {
- LOG(ERROR) << "Unable to save config object";
- return false;
- }
- auto legacy_config_file = GetLegacyConfigFilePath(tmp_config_obj);
- if (!tmp_config_obj.SaveToFile(legacy_config_file)) {
- LOG(ERROR) << "Unable to save legacy config object";
- return false;
- }
- setenv(kCuttlefishConfigEnvVarName, config_file.c_str(), true);
- if (symlink(config_file.c_str(), config_link.c_str()) != 0) {
- LOG(ERROR) << "Failed to create symlink to config file at " << config_link
- << ": " << strerror(errno);
- return false;
- }
-
- return true;
-}
-
-void ValidateAdbModeFlag(const CuttlefishConfig& config) {
- auto adb_modes = config.adb_mode();
- adb_modes.erase(AdbMode::Unknown);
- if (adb_modes.size() < 1) {
- LOG(INFO) << "ADB not enabled";
- }
-}
-
-#ifndef O_TMPFILE
-# define O_TMPFILE (020000000 | O_DIRECTORY)
-#endif
-
-const CuttlefishConfig* InitFilesystemAndCreateConfig(
- FetcherConfig fetcher_config, KernelConfig kernel_config) {
- std::string assembly_dir_parent = AbsolutePath(FLAGS_assembly_dir);
- while (assembly_dir_parent[assembly_dir_parent.size() - 1] == '/') {
- assembly_dir_parent =
- assembly_dir_parent.substr(0, FLAGS_assembly_dir.rfind('/'));
- }
- assembly_dir_parent =
- assembly_dir_parent.substr(0, FLAGS_assembly_dir.rfind('/'));
- auto log =
- SharedFD::Open(
- assembly_dir_parent,
- O_WRONLY | O_TMPFILE,
- S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
- if (!log->IsOpen()) {
- LOG(ERROR) << "Could not open O_TMPFILE precursor to assemble_cvd.log: "
- << log->StrError();
- } else {
- android::base::SetLogger(TeeLogger({
- {ConsoleSeverity(), SharedFD::Dup(2), MetadataLevel::ONLY_MESSAGE},
- {LogFileSeverity(), log, MetadataLevel::FULL},
- }));
- }
-
- {
- // The config object is created here, but only exists in memory until the
- // SaveConfig line below. Don't launch cuttlefish subprocesses between these
- // two operations, as those will assume they can read the config object from
- // disk.
- auto config = InitializeCuttlefishConfiguration(
- FLAGS_instance_dir, FLAGS_modem_simulator_count, kernel_config);
- std::set<std::string> preserving;
- if (FLAGS_resume && ShouldCreateAllCompositeDisks(config)) {
- LOG(INFO) << "Requested resuming a previous session (the default behavior) "
- << "but the base images have changed under the overlay, making the "
- << "overlay incompatible. Wiping the overlay files.";
- } else if (FLAGS_resume && !ShouldCreateAllCompositeDisks(config)) {
- preserving.insert("overlay.img");
- preserving.insert("os_composite_disk_config.txt");
- preserving.insert("os_composite_gpt_header.img");
- preserving.insert("os_composite_gpt_footer.img");
- preserving.insert("os_composite.img");
- preserving.insert("sdcard.img");
- preserving.insert("boot_repacked.img");
- preserving.insert("vendor_boot_repacked.img");
- preserving.insert("access-kregistry");
- preserving.insert("NVChip");
- preserving.insert("gatekeeper_secure");
- preserving.insert("gatekeeper_insecure");
- preserving.insert("modem_nvram.json");
- preserving.insert("recording");
- preserving.insert("persistent_composite_disk_config.txt");
- preserving.insert("persistent_composite_gpt_header.img");
- preserving.insert("persistent_composite_gpt_footer.img");
- preserving.insert("persistent_composite.img");
- preserving.insert("uboot_env.img");
- preserving.insert("factory_reset_protected.img");
- std::stringstream ss;
- for (int i = 0; i < FLAGS_modem_simulator_count; i++) {
- ss.clear();
- ss << "iccprofile_for_sim" << i << ".xml";
- preserving.insert(ss.str());
- ss.str("");
- }
- }
- CHECK(CleanPriorFiles(preserving, FLAGS_assembly_dir, FLAGS_instance_dir))
- << "Failed to clean prior files";
-
- // Create assembly directory if it doesn't exist.
- CHECK(EnsureDirectoryExists(FLAGS_assembly_dir));
- if (log->LinkAtCwd(config.AssemblyPath("assemble_cvd.log"))) {
- LOG(ERROR) << "Unable to persist assemble_cvd log at "
- << config.AssemblyPath("assemble_cvd.log")
- << ": " << log->StrError();
- }
- for (const auto& instance : config.Instances()) {
- // Create instance directory if it doesn't exist.
- CHECK(EnsureDirectoryExists(instance.instance_dir()));
- auto internal_dir = instance.instance_dir() + "/" + kInternalDirName;
- CHECK(EnsureDirectoryExists(internal_dir));
- auto shared_dir = instance.instance_dir() + "/" + kSharedDirName;
- CHECK(EnsureDirectoryExists(shared_dir));
- auto recording_dir = instance.instance_dir() + "/recording";
- CHECK(EnsureDirectoryExists(recording_dir));
- }
- CHECK(SaveConfig(config)) << "Failed to initialize configuration";
- }
-
- std::string first_instance = FLAGS_instance_dir + "." + std::to_string(GetInstance());
- CHECK_EQ(symlink(first_instance.c_str(), FLAGS_instance_dir.c_str()), 0)
- << "Could not symlink \"" << first_instance << "\" to \"" << FLAGS_instance_dir << "\"";
-
- // Do this early so that the config object is ready for anything that needs it
- auto config = CuttlefishConfig::Get();
- CHECK(config) << "Failed to obtain config singleton";
-
- ValidateAdbModeFlag(*config);
-
- CreateDynamicDiskFiles(fetcher_config, config);
-
- return config;
-}
-
-const std::string kKernelDefaultPath = "kernel";
-const std::string kInitramfsImg = "initramfs.img";
-static void ExtractKernelParamsFromFetcherConfig(
- const FetcherConfig& fetcher_config) {
- std::string discovered_kernel =
- fetcher_config.FindCvdFileWithSuffix(kKernelDefaultPath);
- std::string discovered_ramdisk =
- fetcher_config.FindCvdFileWithSuffix(kInitramfsImg);
-
- SetCommandLineOptionWithMode("kernel_path", discovered_kernel.c_str(),
- google::FlagSettingMode::SET_FLAGS_DEFAULT);
-
- SetCommandLineOptionWithMode("initramfs_path", discovered_ramdisk.c_str(),
- google::FlagSettingMode::SET_FLAGS_DEFAULT);
-}
} // namespace
-int AssembleCvdMain(int argc, char** argv) {
+int main(int argc, char** argv) {
setenv("ANDROID_LOG_TAGS", "*:v", /* overwrite */ 0);
::android::base::InitLogging(argv, android::base::StderrLogger);
- int tty = isatty(0);
- int error_num = errno;
- CHECK_EQ(tty, 0)
- << "stdin was a tty, expected to be passed the output of a previous stage. "
- << "Did you mean to run launch_cvd?";
- CHECK(error_num != EBADF)
- << "stdin was not a valid file descriptor, expected to be passed the output "
- << "of launch_cvd. Did you mean to run launch_cvd?";
+ if (isatty(0)) {
+ LOG(FATAL) << "stdin was a tty, expected to be passed the output of a previous stage. "
+ << "Did you mean to run launch_cvd?";
+ return cvd::AssemblerExitCodes::kInvalidHostConfiguration;
+ } else {
+ int error_num = errno;
+ if (error_num == EBADF) {
+ LOG(FATAL) << "stdin was not a valid file descriptor, expected to be passed the output "
+ << "of launch_cvd. Did you mean to run launch_cvd?";
+ return cvd::AssemblerExitCodes::kInvalidHostConfiguration;
+ }
+ }
std::string input_files_str;
{
- auto input_fd = SharedFD::Dup(0);
- auto bytes_read = ReadAll(input_fd, &input_files_str);
- CHECK(bytes_read >= 0)
- << "Failed to read input files. Error was \"" << input_fd->StrError() << "\"";
+ auto input_fd = cvd::SharedFD::Dup(0);
+ auto bytes_read = cvd::ReadAll(input_fd, &input_files_str);
+ if (bytes_read < 0) {
+ LOG(FATAL) << "Failed to read input files. Error was \"" << input_fd->StrError() << "\"";
+ }
}
std::vector<std::string> input_files = android::base::Split(input_files_str, "\n");
- FetcherConfig fetcher_config = FindFetcherConfig(input_files);
- // set gflags defaults to point to kernel/RD from fetcher config
- ExtractKernelParamsFromFetcherConfig(fetcher_config);
-
- KernelConfig kernel_config;
- CHECK(ParseCommandLineFlags(&argc, &argv, &kernel_config)) << "Failed to parse arguments";
-
- auto config =
- InitFilesystemAndCreateConfig(std::move(fetcher_config), kernel_config);
+ auto config = InitFilesystemAndCreateConfig(&argc, &argv, FindFetcherConfig(input_files));
std::cout << GetConfigFilePath(*config) << "\n";
std::cout << std::flush;
- return 0;
-}
-
-} // namespace cuttlefish
-
-int main(int argc, char** argv) {
- return cuttlefish::AssembleCvdMain(argc, argv);
+ return cvd::AssemblerExitCodes::kSuccess;
}
diff --git a/host/commands/assemble_cvd/assembler_defs.h b/host/commands/assemble_cvd/assembler_defs.h
new file mode 100644
index 000000000..b890ca08e
--- /dev/null
+++ b/host/commands/assemble_cvd/assembler_defs.h
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+#pragma once
+
+namespace cvd {
+
+constexpr char kLogcatSerialMode[] = "serial";
+constexpr char kLogcatVsockMode[] = "vsock";
+
+enum AssemblerExitCodes : int {
+ kSuccess = 0,
+ kArgumentParsingError = 1,
+ kInvalidHostConfiguration = 2,
+ kCuttlefishConfigurationInitError = 3,
+ kInstanceDirCreationError = 4,
+ kPrioFilesCleanupError = 5,
+ kBootImageUnpackError = 6,
+ kCuttlefishConfigurationSaveError = 7,
+ kDaemonizationError = 8,
+ kVMCreationError = 9,
+ kPipeIOError = 10,
+ kVirtualDeviceBootFailed = 11,
+ kProcessGroupError = 12,
+ kMonitorCreationFailed = 13,
+ kServerError = 14,
+ kUsbV1SocketError = 15,
+ kE2eTestFailed = 16,
+ kKernelDecompressError = 17,
+ kLogcatServerError = 18,
+ kConfigServerError = 19,
+ kTombstoneServerError = 20,
+ kTombstoneDirCreationError = 21,
+ kInitRamFsConcatError = 22,
+ kAssemblyDirCreationError = 23,
+ kDiskSpaceError = 24,
+};
+
+} // namespace cvd
diff --git a/host/commands/assemble_cvd/boot_config.cc b/host/commands/assemble_cvd/boot_config.cc
deleted file mode 100644
index b4339406e..000000000
--- a/host/commands/assemble_cvd/boot_config.cc
+++ /dev/null
@@ -1,120 +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.
- */
-
-#include "host/commands/assemble_cvd/boot_config.h"
-
-#include <fstream>
-#include <sstream>
-#include <string>
-
-#include <sys/stat.h>
-
-#include <android-base/logging.h>
-#include <android-base/strings.h>
-#include <gflags/gflags.h>
-
-#include "common/libs/utils/environment.h"
-#include "common/libs/utils/files.h"
-#include "common/libs/utils/subprocess.h"
-#include "host/libs/config/cuttlefish_config.h"
-#include "host/libs/config/kernel_args.h"
-#include "host/libs/vm_manager/crosvm_manager.h"
-#include "host/libs/vm_manager/vm_manager.h"
-
-using cuttlefish::vm_manager::CrosvmManager;
-
-DECLARE_bool(pause_in_bootloader);
-DECLARE_string(vm_manager);
-
-namespace cuttlefish {
-namespace {
-
-size_t WriteEnvironment(const CuttlefishConfig& config,
- const std::vector<std::string>& kernel_args,
- const std::string& env_path) {
- std::ostringstream env;
- env << "bootargs=" << android::base::Join(kernel_args, " ") << '\0';
- if (!config.boot_slot().empty()) {
- env << "android_slot_suffix=_" << config.boot_slot() << '\0';
- }
-
- if(FLAGS_pause_in_bootloader) {
- env << "bootdelay=-1" << '\0';
- } else {
- env << "bootdelay=0" << '\0';
- }
-
- // Note that the 0 index points to the GPT table.
- env << "bootcmd=boot_android virtio 0#misc" << '\0';
- if (FLAGS_vm_manager == CrosvmManager::name() &&
- config.target_arch() == Arch::Arm64) {
- env << "fdtaddr=0x80000000" << '\0';
- } else {
- env << "fdtaddr=0x40000000" << '\0';
- }
- env << '\0';
- std::string env_str = env.str();
- std::ofstream file_out(env_path.c_str(), std::ios::binary);
- file_out << env_str;
-
- if(!file_out.good()) {
- return 0;
- }
-
- return env_str.length();
-}
-
-} // namespace
-
-
-bool InitBootloaderEnvPartition(const CuttlefishConfig& config,
- const CuttlefishConfig::InstanceSpecific& instance) {
- auto boot_env_image_path = instance.uboot_env_image_path();
- auto tmp_boot_env_image_path = boot_env_image_path + ".tmp";
- auto uboot_env_path = instance.PerInstancePath("mkenvimg_input");
- auto kernel_args = KernelCommandLineFromConfig(config);
- if(!WriteEnvironment(config, kernel_args, uboot_env_path)) {
- LOG(ERROR) << "Unable to write out plaintext env '" << uboot_env_path << ".'";
- return false;
- }
-
- auto mkimage_path = HostBinaryPath("mkenvimage");
- Command cmd(mkimage_path);
- cmd.AddParameter("-s");
- cmd.AddParameter("4096");
- cmd.AddParameter("-o");
- cmd.AddParameter(tmp_boot_env_image_path);
- cmd.AddParameter(uboot_env_path);
- int success = cmd.Start().Wait();
- if (success != 0) {
- LOG(ERROR) << "Unable to run mkenvimage. Exited with status " << success;
- return false;
- }
-
- if(!FileExists(boot_env_image_path) || ReadFile(boot_env_image_path) != ReadFile(tmp_boot_env_image_path)) {
- if(!RenameFile(tmp_boot_env_image_path, boot_env_image_path)) {
- LOG(ERROR) << "Unable to delete the old env image.";
- return false;
- }
- LOG(DEBUG) << "Updated bootloader environment image.";
- } else {
- RemoveFile(tmp_boot_env_image_path);
- }
-
- return true;
-}
-
-} // namespace cuttlefish
diff --git a/host/commands/assemble_cvd/boot_image_unpacker.cc b/host/commands/assemble_cvd/boot_image_unpacker.cc
new file mode 100644
index 000000000..9ea407abe
--- /dev/null
+++ b/host/commands/assemble_cvd/boot_image_unpacker.cc
@@ -0,0 +1,156 @@
+/*
+ * 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.
+ */
+
+#include "host/commands/assemble_cvd/boot_image_unpacker.h"
+
+#include <string.h>
+#include <unistd.h>
+
+#include <sstream>
+
+#include <bootimg.h>
+#include <android-base/logging.h>
+
+#include "common/libs/utils/subprocess.h"
+
+namespace cvd {
+
+namespace {
+
+// Extracts size bytes from file, starting at offset bytes from the beginning to
+// path.
+bool ExtractFile(SharedFD source, off_t offset, size_t size,
+ const std::string& path) {
+ auto dest = SharedFD::Open(path.c_str(), O_CREAT | O_RDWR, 0755);
+ if (!dest->IsOpen()) {
+ LOG(ERROR) << "Unable to open " << path;
+ return false;
+ }
+ auto off = source->LSeek(offset, SEEK_SET);
+ if (off != offset) {
+ LOG(ERROR) << "Failed to lseek: " << source->StrError();
+ return false;
+ }
+ return dest->CopyFrom(*source, size);
+}
+} // namespace
+
+std::unique_ptr<BootImageUnpacker> BootImageUnpacker::FromImages(
+ const std::string& boot_image_path,
+ const std::string& vendor_boot_image_path) {
+ auto boot_img = SharedFD::Open(boot_image_path.c_str(), O_RDONLY);
+ if (!boot_img->IsOpen()) {
+ LOG(ERROR) << "Unable to open boot image (" << boot_image_path
+ << "): " << boot_img->StrError();
+ return nullptr;
+ }
+ boot_img_hdr_v3 header;
+ auto bytes_read = boot_img->Read(&header, sizeof(header));
+ if (bytes_read != sizeof(header)) {
+ LOG(ERROR) << "Error reading boot image header";
+ return nullptr;
+ }
+
+ auto vendor_boot_img = SharedFD::Open(vendor_boot_image_path.c_str(),
+ O_RDONLY);
+ if (!vendor_boot_img->IsOpen()) {
+ LOG(ERROR) << "Unable to open vendor boot image (" << vendor_boot_image_path
+ << "): " << vendor_boot_img->StrError();
+ return nullptr;
+ }
+ vendor_boot_img_hdr_v3 vboot_header;
+ bytes_read = vendor_boot_img->Read(&vboot_header, sizeof(vboot_header));
+ if (bytes_read != sizeof(vboot_header)) {
+ LOG(ERROR) << "Error reading vendor boot image header";
+ return nullptr;
+ }
+
+ std::ostringstream cmdline;
+ cmdline << reinterpret_cast<char*>(&header.cmdline[0]);
+ if (vboot_header.cmdline[0] != '\0') {
+ cmdline << " ";
+ cmdline << reinterpret_cast<char*>(&vboot_header.cmdline[0]);
+ }
+
+ uint32_t page_size = 4096;
+ // See system/tools/mkbootimg/include/bootimg/bootimg.h for the origin of
+ // these offset calculations
+ uint32_t kernel_offset = page_size;
+ uint32_t ramdisk_offset =
+ kernel_offset +
+ ((header.kernel_size + page_size - 1) / page_size) * page_size;
+ uint32_t vendor_ramdisk_offset =
+ ((vboot_header.header_size + vboot_header.page_size - 1) / vboot_header.page_size) *
+ vboot_header.page_size;
+
+ std::unique_ptr<BootImageUnpacker> ret(new BootImageUnpacker(
+ boot_img, cmdline.str(), header.kernel_size, kernel_offset,
+ header.ramdisk_size, ramdisk_offset, vendor_boot_img,
+ vboot_header.vendor_ramdisk_size, vendor_ramdisk_offset));
+
+ return ret;
+}
+
+std::string BootImageUnpacker::kernel_cmdline() const {
+ return kernel_cmdline_;
+}
+
+bool BootImageUnpacker::ExtractKernelImage(const std::string& path) const {
+ if (kernel_image_size_ == 0) return false;
+ return ExtractFile(boot_image_, kernel_image_offset_, kernel_image_size_,
+ path);
+}
+bool BootImageUnpacker::ExtractRamdiskImage(const std::string& path) const {
+ if (ramdisk_image_size_ == 0) return false;
+ return ExtractFile(boot_image_, ramdisk_image_offset_, ramdisk_image_size_,
+ path);
+}
+bool BootImageUnpacker::ExtractVendorRamdiskImage(const std::string& path) const {
+ if (vendor_ramdisk_image_size_ == 0) return false;
+ return ExtractFile(vendor_boot_image_, vendor_ramdisk_image_offset_,
+ vendor_ramdisk_image_size_, path);
+}
+
+bool BootImageUnpacker::Unpack(const std::string& ramdisk_image_path,
+ const std::string& vendor_ramdisk_image_path,
+ const std::string& kernel_image_path) {
+ if (HasRamdiskImage()) {
+ if (!ExtractRamdiskImage(ramdisk_image_path)) {
+ LOG(ERROR) << "Error extracting ramdisk from boot image";
+ return false;
+ }
+ }
+ if (HasVendorRamdiskImage()) {
+ if (!ExtractVendorRamdiskImage(vendor_ramdisk_image_path)) {
+ LOG(ERROR) << "Error extracting vendor ramdisk from venodr boot image";
+ return false;
+ }
+ }
+ if (!kernel_image_path.empty()) {
+ if (HasKernelImage()) {
+ if (!ExtractKernelImage(kernel_image_path)) {
+ LOG(ERROR) << "Error extracting kernel from boot image";
+ return false;
+ }
+ } else {
+ LOG(ERROR) << "No kernel found on boot image";
+ return false;
+ }
+ }
+ return true;
+}
+
+} // namespace cvd
diff --git a/host/commands/assemble_cvd/boot_image_unpacker.h b/host/commands/assemble_cvd/boot_image_unpacker.h
new file mode 100644
index 000000000..a331f0ca9
--- /dev/null
+++ b/host/commands/assemble_cvd/boot_image_unpacker.h
@@ -0,0 +1,88 @@
+/*
+ * 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.
+ */
+#pragma once
+
+#include <stdint.h>
+
+#include <memory>
+#include <string>
+
+#include "common/libs/fs/shared_fd.h"
+
+namespace cvd {
+
+// Unpacks the boot image and extracts kernel, ramdisk and kernel arguments
+class BootImageUnpacker {
+ public:
+ // Reads header section of boot image at path and returns a BootImageUnpacker
+ // preloaded with all the metadata.
+ static std::unique_ptr<BootImageUnpacker> FromImages(
+ const std::string& boot_image_path,
+ const std::string& vendor_boot_image_path);
+
+ ~BootImageUnpacker() = default;
+
+ std::string kernel_cmdline() const;
+
+ bool HasKernelImage() const { return kernel_image_size_ > 0; }
+ bool HasRamdiskImage() const { return ramdisk_image_size_ > 0; }
+ bool HasVendorRamdiskImage() const { return vendor_ramdisk_image_size_ > 0; }
+
+ bool Unpack(const std::string& ramdisk_image_path,
+ const std::string& vendor_ramdisk_image_path,
+ const std::string& kernel_image_path);
+
+ private:
+ BootImageUnpacker(SharedFD boot_image, const std::string& cmdline,
+ uint32_t kernel_image_size, uint32_t kernel_image_offset,
+ uint32_t ramdisk_image_size, uint32_t ramdisk_image_offset,
+ SharedFD vendor_boot_image,
+ uint32_t vendor_ramdisk_image_size,
+ uint32_t vendor_ramdisk_image_offset)
+ : boot_image_(boot_image),
+ vendor_boot_image_(vendor_boot_image),
+ kernel_cmdline_(cmdline),
+ kernel_image_size_(kernel_image_size),
+ kernel_image_offset_(kernel_image_offset),
+ ramdisk_image_size_(ramdisk_image_size),
+ ramdisk_image_offset_(ramdisk_image_offset),
+ vendor_ramdisk_image_size_(vendor_ramdisk_image_size),
+ vendor_ramdisk_image_offset_(vendor_ramdisk_image_offset) {}
+
+ // Mutable because we only read from the fd, but do not modify its contents
+ mutable SharedFD boot_image_;
+ mutable SharedFD vendor_boot_image_;
+ std::string kernel_cmdline_;
+ // When buidling the boot image a particular page size is assumed, which may
+ // not match the actual page size of the system.
+ uint32_t kernel_image_size_;
+ uint32_t kernel_image_offset_;
+ uint32_t ramdisk_image_size_;
+ uint32_t ramdisk_image_offset_;
+ uint32_t vendor_ramdisk_image_size_;
+ uint32_t vendor_ramdisk_image_offset_;
+
+ // Extracts the kernel image to the given path
+ bool ExtractKernelImage(const std::string& path) const;
+ // Extracts the ramdisk image to the given path. It may return false if the
+ // boot image does not contain a ramdisk, which is the case when having system
+ // as root.
+ bool ExtractRamdiskImage(const std::string& path) const;
+ // Extracts the vendor ramdisk image to the given path
+ bool ExtractVendorRamdiskImage(const std::string& path) const;
+};
+
+} // namespace cvd
diff --git a/host/commands/assemble_cvd/boot_image_utils.cc b/host/commands/assemble_cvd/boot_image_utils.cc
deleted file mode 100644
index cfad23f6a..000000000
--- a/host/commands/assemble_cvd/boot_image_utils.cc
+++ /dev/null
@@ -1,332 +0,0 @@
-/*
- * Copyright (C) 2020 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 "host/commands/assemble_cvd/boot_image_utils.h"
-#include "host/libs/config/cuttlefish_config.h"
-
-#include <string.h>
-#include <unistd.h>
-
-#include <fstream>
-#include <sstream>
-
-#include <android-base/logging.h>
-#include <android-base/strings.h>
-
-#include "common/libs/utils/files.h"
-#include "common/libs/utils/subprocess.h"
-
-const char TMP_EXTENSION[] = ".tmp";
-const char CPIO_EXT[] = ".cpio";
-const char TMP_RD_DIR[] = "stripped_ramdisk_dir";
-const char STRIPPED_RD[] = "stripped_ramdisk";
-const char CONCATENATED_VENDOR_RAMDISK[] = "concatenated_vendor_ramdisk";
-namespace cuttlefish {
-namespace {
-std::string ExtractValue(const std::string& dictionary, const std::string& key) {
- std::size_t index = dictionary.find(key);
- if (index != std::string::npos) {
- std::size_t end_index = dictionary.find('\n', index + key.length());
- if (end_index != std::string::npos) {
- return dictionary.substr(index + key.length(),
- end_index - index - key.length());
- }
- }
- return "";
-}
-
-// Though it is just as fast to overwrite the existing boot images with the newly generated ones,
-// the cuttlefish composite disk generator checks the age of each of the components and
-// regenerates the disk outright IF any one of the components is younger/newer than the current
-// composite disk. If this file overwrite occurs, that condition is fulfilled. This action then
-// causes data in the userdata partition from previous boots to be lost (which is not expected by
-// the user if they've been booting the same kernel/ramdisk combination repeatedly).
-// Consequently, the file is checked for differences and ONLY overwritten if there is a diff.
-bool DeleteTmpFileIfNotChanged(const std::string& tmp_file, const std::string& current_file) {
- if (!FileExists(current_file) ||
- ReadFile(current_file) != ReadFile(tmp_file)) {
- if (!RenameFile(tmp_file, current_file)) {
- LOG(ERROR) << "Unable to delete " << current_file;
- return false;
- }
- LOG(DEBUG) << "Updated " << current_file;
- } else {
- LOG(DEBUG) << "Didn't update " << current_file;
- RemoveFile(tmp_file);
- }
-
- return true;
-}
-
-bool UnpackBootImage(const std::string& boot_image_path,
- const std::string& unpack_dir) {
- auto unpack_path = HostBinaryPath("unpack_bootimg");
- Command unpack_cmd(unpack_path);
- unpack_cmd.AddParameter("--boot_img");
- unpack_cmd.AddParameter(boot_image_path);
- unpack_cmd.AddParameter("--out");
- unpack_cmd.AddParameter(unpack_dir);
-
- auto output_file = SharedFD::Creat(unpack_dir + "/boot_params", 0666);
- if (!output_file->IsOpen()) {
- LOG(ERROR) << "Unable to create intermediate boot params file: "
- << output_file->StrError();
- return false;
- }
- unpack_cmd.RedirectStdIO(Subprocess::StdIOChannel::kStdOut, output_file);
-
- int success = unpack_cmd.Start().Wait();
- if (success != 0) {
- LOG(ERROR) << "Unable to run unpack_bootimg. Exited with status "
- << success;
- return false;
- }
- return true;
-}
-
-void RepackVendorRamdisk(const std::string& kernel_modules_ramdisk_path,
- const std::string& original_ramdisk_path,
- const std::string& new_ramdisk_path,
- const std::string& build_dir) {
- int success = execute({"/bin/bash", "-c", HostBinaryPath("lz4") + " -c -d -l " +
- original_ramdisk_path + " > " + original_ramdisk_path + CPIO_EXT});
- CHECK(success == 0) << "Unable to run lz4. Exited with status " << success;
-
- const std::string ramdisk_stage_dir = build_dir + "/" + TMP_RD_DIR;
- success =
- mkdir(ramdisk_stage_dir.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
- CHECK(success == 0) << "Could not mkdir \"" << ramdisk_stage_dir
- << "\", error was " << strerror(errno);
-
- success = execute(
- {"/bin/bash", "-c",
- "(cd " + ramdisk_stage_dir + " && while " + HostBinaryPath("toybox") +
- " cpio -idu; do :; done) < " + original_ramdisk_path + CPIO_EXT});
- CHECK(success == 0) << "Unable to run cd or cpio. Exited with status "
- << success;
-
- success = execute({"rm", "-rf", ramdisk_stage_dir + "/lib/modules"});
- CHECK(success == 0) << "Could not rmdir \"lib/modules\" in TMP_RD_DIR. "
- << "Exited with status " << success;
-
- const std::string stripped_ramdisk_path = build_dir + "/" + STRIPPED_RD;
- success = execute({"/bin/bash", "-c",
- HostBinaryPath("mkbootfs") + " " + ramdisk_stage_dir +
- " > " + stripped_ramdisk_path + CPIO_EXT});
- CHECK(success == 0) << "Unable to run cd or cpio. Exited with status "
- << success;
-
- success = execute({"/bin/bash", "-c", HostBinaryPath("lz4") +
- " -c -l -12 --favor-decSpeed " + stripped_ramdisk_path + CPIO_EXT + " > " +
- stripped_ramdisk_path});
- CHECK(success == 0) << "Unable to run lz4. Exited with status " << success;
-
- // Concatenates the stripped ramdisk and input ramdisk and places the result at new_ramdisk_path
- std::ofstream final_rd(new_ramdisk_path, std::ios_base::binary | std::ios_base::trunc);
- std::ifstream ramdisk_a(stripped_ramdisk_path, std::ios_base::binary);
- std::ifstream ramdisk_b(kernel_modules_ramdisk_path, std::ios_base::binary);
- final_rd << ramdisk_a.rdbuf() << ramdisk_b.rdbuf();
-}
-
-bool UnpackVendorBootImageIfNotUnpacked(
- const std::string& vendor_boot_image_path, const std::string& unpack_dir) {
- // the vendor boot params file is created during the first unpack. If it's
- // already there, a unpack has occurred and there's no need to repeat the
- // process.
- if (FileExists(unpack_dir + "/vendor_boot_params")) {
- return true;
- }
-
- auto unpack_path = HostBinaryPath("unpack_bootimg");
- Command unpack_cmd(unpack_path);
- unpack_cmd.AddParameter("--boot_img");
- unpack_cmd.AddParameter(vendor_boot_image_path);
- unpack_cmd.AddParameter("--out");
- unpack_cmd.AddParameter(unpack_dir);
- auto output_file = SharedFD::Creat(unpack_dir + "/vendor_boot_params", 0666);
- if (!output_file->IsOpen()) {
- LOG(ERROR) << "Unable to create intermediate vendor boot params file: "
- << output_file->StrError();
- return false;
- }
- unpack_cmd.RedirectStdIO(Subprocess::StdIOChannel::kStdOut, output_file);
- int success = unpack_cmd.Start().Wait();
- if (success != 0) {
- LOG(ERROR) << "Unable to run unpack_bootimg. Exited with status " << success;
- return false;
- }
-
- // Concatenates all vendor ramdisk into one single ramdisk.
- Command concat_cmd("/bin/bash");
- concat_cmd.AddParameter("-c");
- concat_cmd.AddParameter("cat " + unpack_dir + "/vendor_ramdisk*");
- auto concat_file =
- SharedFD::Creat(unpack_dir + "/" + CONCATENATED_VENDOR_RAMDISK, 0666);
- if (!concat_file->IsOpen()) {
- LOG(ERROR) << "Unable to create concatenated vendor ramdisk file: "
- << concat_file->StrError();
- return false;
- }
- concat_cmd.RedirectStdIO(Subprocess::StdIOChannel::kStdOut, concat_file);
- success = concat_cmd.Start().Wait();
- if (success != 0) {
- LOG(ERROR) << "Unable to run cat. Exited with status " << success;
- return false;
- }
- return true;
-}
-
-} // namespace
-
-bool RepackBootImage(const std::string& new_kernel_path,
- const std::string& boot_image_path,
- const std::string& new_boot_image_path,
- const std::string& build_dir) {
- if (UnpackBootImage(boot_image_path, build_dir) == false) {
- return false;
- }
-
- std::string boot_params = ReadFile(build_dir + "/boot_params");
- auto kernel_cmdline = ExtractValue(boot_params, "command line args: ");
- LOG(DEBUG) << "Cmdline from boot image is " << kernel_cmdline;
-
- auto tmp_boot_image_path = new_boot_image_path + TMP_EXTENSION;
- auto repack_path = HostBinaryPath("mkbootimg");
- Command repack_cmd(repack_path);
- repack_cmd.AddParameter("--kernel");
- repack_cmd.AddParameter(new_kernel_path);
- repack_cmd.AddParameter("--ramdisk");
- repack_cmd.AddParameter(build_dir + "/ramdisk");
- repack_cmd.AddParameter("--header_version");
- repack_cmd.AddParameter("4");
- repack_cmd.AddParameter("--cmdline");
- repack_cmd.AddParameter(kernel_cmdline);
- repack_cmd.AddParameter("-o");
- repack_cmd.AddParameter(tmp_boot_image_path);
- int success = repack_cmd.Start().Wait();
- if (success != 0) {
- LOG(ERROR) << "Unable to run mkbootimg. Exited with status " << success;
- return false;
- }
-
- auto fd = SharedFD::Open(tmp_boot_image_path, O_RDWR);
- auto original_size = FileSize(boot_image_path);
- CHECK(fd->Truncate(original_size) == 0)
- << "`truncate --size=" << original_size << " " << tmp_boot_image_path << "` "
- << "failed: " << fd->StrError();
-
- return DeleteTmpFileIfNotChanged(tmp_boot_image_path, new_boot_image_path);
-}
-
-bool RepackVendorBootImage(const std::string& new_ramdisk,
- const std::string& vendor_boot_image_path,
- const std::string& new_vendor_boot_image_path,
- const std::string& unpack_dir,
- const std::string& repack_dir,
- const std::vector<std::string>& bootconfig_args,
- bool bootconfig_supported) {
- if (UnpackVendorBootImageIfNotUnpacked(vendor_boot_image_path, unpack_dir) ==
- false) {
- return false;
- }
-
- std::string ramdisk_path;
- if (new_ramdisk.size()) {
- ramdisk_path = unpack_dir + "/vendor_ramdisk_repacked";
- if (!FileExists(ramdisk_path)) {
- RepackVendorRamdisk(new_ramdisk,
- unpack_dir + "/" + CONCATENATED_VENDOR_RAMDISK,
- ramdisk_path, unpack_dir);
- }
- } else {
- ramdisk_path = unpack_dir + "/" + CONCATENATED_VENDOR_RAMDISK;
- }
-
- auto bootconfig_fd = SharedFD::Creat(repack_dir + "/bootconfig", 0666);
- if (!bootconfig_fd->IsOpen()) {
- LOG(ERROR) << "Unable to create intermediate bootconfig file: "
- << bootconfig_fd->StrError();
- return false;
- }
- std::string bootconfig = ReadFile(unpack_dir + "/bootconfig");
- bootconfig_fd->Write(bootconfig.c_str(), bootconfig.size());
- LOG(DEBUG) << "Bootconfig parameters from vendor boot image are "
- << ReadFile(repack_dir + "/bootconfig");
- std::string vendor_boot_params = ReadFile(unpack_dir + "/vendor_boot_params");
- auto kernel_cmdline =
- ExtractValue(vendor_boot_params, "vendor command line args: ") +
- (bootconfig_supported
- ? ""
- : " " + android::base::StringReplace(bootconfig, "\n", " ", true) +
- " " + android::base::Join(bootconfig_args, " "));
- if (!bootconfig_supported) {
- // TODO(b/182417593): Until we pass the module parameters through
- // modules.options, we pass them through bootconfig using
- // 'kernel.<key>=<value>' But if we don't support bootconfig, we need to
- // rename them back to the old cmdline version
- kernel_cmdline = android::base::StringReplace(
- kernel_cmdline, " kernel.", " ", true);
- }
- LOG(DEBUG) << "Cmdline from vendor boot image and config is "
- << kernel_cmdline;
-
- auto tmp_vendor_boot_image_path = new_vendor_boot_image_path + TMP_EXTENSION;
- auto repack_path = HostBinaryPath("mkbootimg");
- Command repack_cmd(repack_path);
- repack_cmd.AddParameter("--vendor_ramdisk");
- repack_cmd.AddParameter(ramdisk_path);
- repack_cmd.AddParameter("--header_version");
- repack_cmd.AddParameter("4");
- repack_cmd.AddParameter("--vendor_cmdline");
- repack_cmd.AddParameter(kernel_cmdline);
- repack_cmd.AddParameter("--vendor_boot");
- repack_cmd.AddParameter(tmp_vendor_boot_image_path);
- repack_cmd.AddParameter("--dtb");
- repack_cmd.AddParameter(unpack_dir + "/dtb");
- if (bootconfig_supported) {
- repack_cmd.AddParameter("--vendor_bootconfig");
- repack_cmd.AddParameter(repack_dir + "/bootconfig");
- }
-
- int success = repack_cmd.Start().Wait();
- if (success != 0) {
- LOG(ERROR) << "Unable to run mkbootimg. Exited with status " << success;
- return false;
- }
-
- auto fd = SharedFD::Open(tmp_vendor_boot_image_path, O_RDWR);
- auto original_size = FileSize(vendor_boot_image_path);
- CHECK(fd->Truncate(original_size) == 0)
- << "`truncate --size=" << original_size << " " << tmp_vendor_boot_image_path << "` "
- << "failed: " << fd->StrError();
-
- return DeleteTmpFileIfNotChanged(tmp_vendor_boot_image_path, new_vendor_boot_image_path);
-}
-
-bool RepackVendorBootImageWithEmptyRamdisk(
- const std::string& vendor_boot_image_path,
- const std::string& new_vendor_boot_image_path,
- const std::string& unpack_dir, const std::string& repack_dir,
- const std::vector<std::string>& bootconfig_args,
- bool bootconfig_supported) {
- auto empty_ramdisk_file =
- SharedFD::Creat(unpack_dir + "/empty_ramdisk", 0666);
- return RepackVendorBootImage(
- unpack_dir + "/empty_ramdisk", vendor_boot_image_path,
- new_vendor_boot_image_path, unpack_dir, repack_dir, bootconfig_args,
- bootconfig_supported);
-}
-} // namespace cuttlefish
diff --git a/host/commands/assemble_cvd/boot_image_utils.h b/host/commands/assemble_cvd/boot_image_utils.h
deleted file mode 100644
index fafb51426..000000000
--- a/host/commands/assemble_cvd/boot_image_utils.h
+++ /dev/null
@@ -1,38 +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.
- */
-#pragma once
-
-#include <string>
-#include <vector>
-
-namespace cuttlefish {
-bool RepackBootImage(const std::string& new_kernel_path,
- const std::string& boot_image_path,
- const std::string& new_boot_image_path,
- const std::string& tmp_artifact_dir);
-bool RepackVendorBootImage(const std::string& new_ramdisk_path,
- const std::string& vendor_boot_image_path,
- const std::string& new_vendor_boot_image_path,
- const std::string& unpack_dir,
- const std::string& repack_dir,
- const std::vector<std::string>& bootconfig_args,
- bool bootconfig_supported);
-bool RepackVendorBootImageWithEmptyRamdisk(
- const std::string& vendor_boot_image_path,
- const std::string& new_vendor_boot_image_path,
- const std::string& unpack_dir, const std::string& repack_dir,
- const std::vector<std::string>& bootconfig_args, bool bootconfig_supported);
-}
diff --git a/host/libs/image_aggregator/cdisk_spec.proto b/host/commands/assemble_cvd/cdisk_spec.proto
index 771c7ceaa..771c7ceaa 100644
--- a/host/libs/image_aggregator/cdisk_spec.proto
+++ b/host/commands/assemble_cvd/cdisk_spec.proto
diff --git a/host/commands/assemble_cvd/cf_bpttool.py b/host/commands/assemble_cvd/cf_bpttool.py
new file mode 100755
index 000000000..a29d737bc
--- /dev/null
+++ b/host/commands/assemble_cvd/cf_bpttool.py
@@ -0,0 +1,1649 @@
+#!/usr/bin/env python
+
+# Copyright 2016, The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+"""Command-line tool for partitioning Brillo images."""
+
+
+import argparse
+import bisect
+import copy
+import json
+import math
+import numbers
+import os
+import struct
+import sys
+import uuid
+import zlib
+
+# Python 2.6 required for modern exception syntax
+if sys.hexversion < 0x02060000:
+ print >> sys.stderr, "Python 2.6 or newer is required."
+ sys.exit(1)
+
+# Keywords used in JSON files.
+JSON_KEYWORD_SETTINGS = 'settings'
+JSON_KEYWORD_SETTINGS_AB_SUFFIXES = 'ab_suffixes'
+JSON_KEYWORD_SETTINGS_DISK_SIZE = 'disk_size'
+JSON_KEYWORD_SETTINGS_DISK_ALIGNMENT = 'disk_alignment'
+JSON_KEYWORD_SETTINGS_DISK_GUID = 'disk_guid'
+JSON_KEYWORD_SETTINGS_PARTITIONS_OFFSET_BEGIN = 'partitions_offset_begin'
+JSON_KEYWORD_PARTITIONS = 'partitions'
+JSON_KEYWORD_PARTITIONS_LABEL = 'label'
+JSON_KEYWORD_PARTITIONS_OFFSET = 'offset'
+JSON_KEYWORD_PARTITIONS_SIZE = 'size'
+JSON_KEYWORD_PARTITIONS_GROW = 'grow'
+JSON_KEYWORD_PARTITIONS_GUID = 'guid'
+JSON_KEYWORD_PARTITIONS_TYPE_GUID = 'type_guid'
+JSON_KEYWORD_PARTITIONS_FLAGS = 'flags'
+JSON_KEYWORD_PARTITIONS_PERSIST = 'persist'
+JSON_KEYWORD_PARTITIONS_IGNORE = 'ignore'
+JSON_KEYWORD_PARTITIONS_AB = 'ab'
+JSON_KEYWORD_PARTITIONS_AB_EXPANDED = 'ab_expanded'
+JSON_KEYWORD_PARTITIONS_POSITION = 'position'
+JSON_KEYWORD_AUTO = 'auto'
+
+# Possible values for the --type option of the query_partition
+# sub-command.
+QUERY_PARTITION_TYPES = ['size',
+ 'offset',
+ 'guid',
+ 'type_guid',
+ 'flags',
+ 'persist']
+
+BPT_VERSION_MAJOR = 1
+BPT_VERSION_MINOR = 0
+
+DISK_SECTOR_SIZE = 512
+
+GPT_NUM_LBAS = 33
+
+GPT_MIN_PART_NUM = 1
+GPT_MAX_PART_NUM = 128
+
+KNOWN_TYPE_GUIDS = {
+ 'brillo_boot': 'bb499290-b57e-49f6-bf41-190386693794',
+ 'brillo_bootloader': '4892aeb3-a45f-4c5f-875f-da3303c0795c',
+ 'brillo_system': '0f2778c4-5cc1-4300-8670-6c88b7e57ed6',
+ 'brillo_odm': 'e99d84d7-2c1b-44cf-8c58-effae2dc2558',
+ 'brillo_oem': 'aa3434b2-ddc3-4065-8b1a-18e99ea15cb7',
+ 'brillo_userdata': '0bb7e6ed-4424-49c0-9372-7fbab465ab4c',
+ 'brillo_misc': '6b2378b0-0fbc-4aa9-a4f6-4d6e17281c47',
+ 'brillo_vbmeta': 'b598858a-5fe3-418e-b8c4-824b41f4adfc',
+ 'brillo_vendor_specific': '314f99d5-b2bf-4883-8d03-e2f2ce507d6a',
+ 'linux_fs': '0fc63daf-8483-4772-8e79-3d69d8477de4',
+ 'ms_basic_data': 'ebd0a0a2-b9e5-4433-87c0-68b6b72699c7',
+ 'efi_system': 'c12a7328-f81f-11d2-ba4b-00a0c93ec93b'
+}
+
+
+def RoundToMultiple(number, size, round_down=False):
+ """Rounds a number up (or down) to nearest multiple of another number.
+
+ Args:
+ number: The number to round up.
+ size: The multiple to round up to.
+ round_down: If True, the number will be rounded down.
+
+ Returns:
+ If |number| is a multiple of |size|, returns |number|, otherwise
+ returns |number| + |size| - |remainder| (if |round_down| is False) or
+ |number| - |remainder| (if |round_down| is True). Always returns
+ an integer.
+ """
+ remainder = number % size
+ if remainder == 0:
+ return int(number)
+ if round_down:
+ return int(number - remainder)
+ return int(number + size - remainder)
+
+
+def ParseNumber(arg):
+ """Number parser.
+
+ If |arg| is an integer, that value is returned. Otherwise int(arg, 0)
+ is returned.
+
+ This function is suitable for use in the |type| parameter of
+ |ArgumentParser|'s add_argument() function. An improvement to just
+ using type=int is that this function supports numbers in other
+ bases, e.g. "0x1234".
+
+ Arguments:
+ arg: Argument (int or string) to parse.
+
+ Returns:
+ The parsed value, as an integer.
+
+ Raises:
+ ValueError: If the argument could not be parsed.
+ """
+ if isinstance(arg, numbers.Integral):
+ return arg
+ return int(arg, 0)
+
+
+def ParseGuid(arg):
+ """Parser for RFC 4122 GUIDs.
+
+ Arguments:
+ arg: The argument, as a string.
+
+ Returns:
+ UUID in hyphenated format.
+
+ Raises:
+ ValueError: If the given string cannot be parsed.
+ """
+ return str(uuid.UUID(arg))
+
+
+def ParseSize(arg):
+ """Parser for size strings with decimal and binary unit support.
+
+ This supports both integers and strings.
+
+ Arguments:
+ arg: The string to parse.
+
+ Returns:
+ The parsed size in bytes as an integer.
+
+ Raises:
+ ValueError: If the given string cannot be parsed.
+ """
+ if isinstance(arg, numbers.Integral):
+ return arg
+
+ ws_index = arg.find(' ')
+ if ws_index != -1:
+ num = float(arg[0:ws_index])
+ factor = 1
+ if arg.endswith('KiB'):
+ factor = 1024
+ elif arg.endswith('MiB'):
+ factor = 1024*1024
+ elif arg.endswith('GiB'):
+ factor = 1024*1024*1024
+ elif arg.endswith('TiB'):
+ factor = 1024*1024*1024*1024
+ elif arg.endswith('PiB'):
+ factor = 1024*1024*1024*1024*1024
+ elif arg.endswith('kB'):
+ factor = 1000
+ elif arg.endswith('MB'):
+ factor = 1000*1000
+ elif arg.endswith('GB'):
+ factor = 1000*1000*1000
+ elif arg.endswith('TB'):
+ factor = 1000*1000*1000*1000
+ elif arg.endswith('PB'):
+ factor = 1000*1000*1000*1000*1000
+ else:
+ raise ValueError('Cannot parse string "{}"'.format(arg))
+ value = num*factor
+ # If the resulting value isn't an integer, round up.
+ if not value.is_integer():
+ value = int(math.ceil(value))
+ else:
+ value = int(arg, 0)
+ return value
+
+
+class ImageChunk(object):
+ """Data structure used for representing chunks in Android sparse files.
+
+ Attributes:
+ chunk_type: One of TYPE_RAW, TYPE_FILL, or TYPE_DONT_CARE.
+ chunk_offset: Offset in the sparse file where this chunk begins.
+ output_offset: Offset in de-sparsified file where output begins.
+ output_size: Number of bytes in output.
+ input_offset: Offset in sparse file for data if TYPE_RAW otherwise None.
+ fill_data: Blob with data to fill if TYPE_FILL otherwise None.
+ """
+
+ FORMAT = '<2H2I'
+ TYPE_RAW = 0xcac1
+ TYPE_FILL = 0xcac2
+ TYPE_DONT_CARE = 0xcac3
+ TYPE_CRC32 = 0xcac4
+
+ def __init__(self, chunk_type, chunk_offset, output_offset, output_size,
+ input_offset, fill_data):
+ """Initializes an ImageChunk object.
+
+ Arguments:
+ chunk_type: One of TYPE_RAW, TYPE_FILL, or TYPE_DONT_CARE.
+ chunk_offset: Offset in the sparse file where this chunk begins.
+ output_offset: Offset in de-sparsified file.
+ output_size: Number of bytes in output.
+ input_offset: Offset in sparse file if TYPE_RAW otherwise None.
+ fill_data: Blob with data to fill if TYPE_FILL otherwise None.
+
+ Raises:
+ ValueError: If data is not well-formed.
+ """
+ self.chunk_type = chunk_type
+ self.chunk_offset = chunk_offset
+ self.output_offset = output_offset
+ self.output_size = output_size
+ self.input_offset = input_offset
+ self.fill_data = fill_data
+ # Check invariants.
+ if self.chunk_type == self.TYPE_RAW:
+ if self.fill_data is not None:
+ raise ValueError('RAW chunk cannot have fill_data set.')
+ if not self.input_offset:
+ raise ValueError('RAW chunk must have input_offset set.')
+ elif self.chunk_type == self.TYPE_FILL:
+ if self.fill_data is None:
+ raise ValueError('FILL chunk must have fill_data set.')
+ if self.input_offset:
+ raise ValueError('FILL chunk cannot have input_offset set.')
+ elif self.chunk_type == self.TYPE_DONT_CARE:
+ if self.fill_data is not None:
+ raise ValueError('DONT_CARE chunk cannot have fill_data set.')
+ if self.input_offset:
+ raise ValueError('DONT_CARE chunk cannot have input_offset set.')
+ else:
+ raise ValueError('Invalid chunk type')
+
+
+class ImageHandler(object):
+ """Abstraction for image I/O with support for Android sparse images.
+
+ This class provides an interface for working with image files that
+ may be using the Android Sparse Image format. When an instance is
+ constructed, we test whether it's an Android sparse file. If so,
+ operations will be on the sparse file by interpreting the sparse
+ format, otherwise they will be directly on the file. Either way the
+ operations do the same.
+
+ For reading, this interface mimics a file object - it has seek(),
+ tell(), and read() methods. For writing, only truncation
+ (truncate()) and appending is supported (append_raw(),
+ append_fill(), and append_dont_care()). Additionally, data can only
+ be written in units of the block size.
+
+ Attributes:
+ is_sparse: Whether the file being operated on is sparse.
+ block_size: The block size, typically 4096.
+ image_size: The size of the unsparsified file.
+
+ """
+ # See system/core/libsparse/sparse_format.h for details.
+ MAGIC = 0xed26ff3a
+ HEADER_FORMAT = '<I4H4I'
+
+ # These are formats and offset of just the |total_chunks| and
+ # |total_blocks| fields.
+ NUM_CHUNKS_AND_BLOCKS_FORMAT = '<II'
+ NUM_CHUNKS_AND_BLOCKS_OFFSET = 16
+
+ def __init__(self, image_filename):
+ """Initializes an image handler.
+
+ Arguments:
+ image_filename: The name of the file to operate on.
+
+ Raises:
+ ValueError: If data in the file is invalid.
+ """
+ self._image_filename = image_filename
+ self._read_header()
+
+ def _read_header(self):
+ """Initializes internal data structures used for reading file.
+
+ This may be called multiple times and is typically called after
+ modifying the file (e.g. appending, truncation).
+
+ Raises:
+ ValueError: If data in the file is invalid.
+ """
+ self.is_sparse = False
+ self.block_size = 4096
+ self._file_pos = 0
+ self._image = open(self._image_filename, 'r+b')
+ self._image.seek(0, os.SEEK_END)
+ self.image_size = self._image.tell()
+
+ self._image.seek(0, os.SEEK_SET)
+ header_bin = self._image.read(struct.calcsize(self.HEADER_FORMAT))
+ if len(header_bin) < struct.calcsize(self.HEADER_FORMAT):
+ # Not a sparse image, our job here is done.
+ return
+ (magic, major_version, minor_version, file_hdr_sz, chunk_hdr_sz,
+ block_size, self._num_total_blocks, self._num_total_chunks,
+ _) = struct.unpack(self.HEADER_FORMAT, header_bin)
+ if magic != self.MAGIC:
+ # Not a sparse image, our job here is done.
+ return
+ if not (major_version == 1 and minor_version == 0):
+ raise ValueError('Encountered sparse image format version {}.{} but '
+ 'only 1.0 is supported'.format(major_version,
+ minor_version))
+ if file_hdr_sz != struct.calcsize(self.HEADER_FORMAT):
+ raise ValueError('Unexpected file_hdr_sz value {}.'.
+ format(file_hdr_sz))
+ if chunk_hdr_sz != struct.calcsize(ImageChunk.FORMAT):
+ raise ValueError('Unexpected chunk_hdr_sz value {}.'.
+ format(chunk_hdr_sz))
+
+ self.block_size = block_size
+
+ # Build an list of chunks by parsing the file.
+ self._chunks = []
+
+ # Find the smallest offset where only "Don't care" chunks
+ # follow. This will be the size of the content in the sparse
+ # image.
+ offset = 0
+ output_offset = 0
+ for _ in xrange(1, self._num_total_chunks + 1):
+ chunk_offset = self._image.tell()
+
+ header_bin = self._image.read(struct.calcsize(ImageChunk.FORMAT))
+ (chunk_type, _, chunk_sz, total_sz) = struct.unpack(ImageChunk.FORMAT,
+ header_bin)
+ data_sz = total_sz - struct.calcsize(ImageChunk.FORMAT)
+
+ if chunk_type == ImageChunk.TYPE_RAW:
+ if data_sz != (chunk_sz * self.block_size):
+ raise ValueError('Raw chunk input size ({}) does not match output '
+ 'size ({})'.
+ format(data_sz, chunk_sz*self.block_size))
+ self._chunks.append(ImageChunk(ImageChunk.TYPE_RAW,
+ chunk_offset,
+ output_offset,
+ chunk_sz*self.block_size,
+ self._image.tell(),
+ None))
+ self._image.read(data_sz)
+
+ elif chunk_type == ImageChunk.TYPE_FILL:
+ if data_sz != 4:
+ raise ValueError('Fill chunk should have 4 bytes of fill, but this '
+ 'has {}'.format(data_sz))
+ fill_data = self._image.read(4)
+ self._chunks.append(ImageChunk(ImageChunk.TYPE_FILL,
+ chunk_offset,
+ output_offset,
+ chunk_sz*self.block_size,
+ None,
+ fill_data))
+ elif chunk_type == ImageChunk.TYPE_DONT_CARE:
+ if data_sz != 0:
+ raise ValueError('Don\'t care chunk input size is non-zero ({})'.
+ format(data_sz))
+ self._chunks.append(ImageChunk(ImageChunk.TYPE_DONT_CARE,
+ chunk_offset,
+ output_offset,
+ chunk_sz*self.block_size,
+ None,
+ None))
+ elif chunk_type == ImageChunk.TYPE_CRC32:
+ if data_sz != 4:
+ raise ValueError('CRC32 chunk should have 4 bytes of CRC, but '
+ 'this has {}'.format(data_sz))
+ self._image.read(4)
+ else:
+ raise ValueError('Unknown chunk type {}'.format(chunk_type))
+
+ offset += chunk_sz
+ output_offset += chunk_sz * self.block_size
+
+ # Record where sparse data end.
+ self._sparse_end = self._image.tell()
+
+ # Now that we've traversed all chunks, sanity check.
+ if self._num_total_blocks != offset:
+ raise ValueError('The header said we should have {} output blocks, '
+ 'but we saw {}'.format(self._num_total_blocks, offset))
+ junk_len = len(self._image.read())
+ if junk_len > 0:
+ raise ValueError('There were {} bytes of extra data at the end of the '
+ 'file.'.format(junk_len))
+
+ # Assign |image_size|.
+ self.image_size = output_offset
+
+ # This is used when bisecting in read() to find the initial slice.
+ self._chunk_output_offsets = [i.output_offset for i in self._chunks]
+
+ self.is_sparse = True
+
+ def _update_chunks_and_blocks(self):
+ """Helper function to update the image header.
+
+ The the |total_chunks| and |total_blocks| fields in the header
+ will be set to value of the |_num_total_blocks| and
+ |_num_total_chunks| attributes.
+
+ """
+ self._image.seek(self.NUM_CHUNKS_AND_BLOCKS_OFFSET, os.SEEK_SET)
+ self._image.write(struct.pack(self.NUM_CHUNKS_AND_BLOCKS_FORMAT,
+ self._num_total_blocks,
+ self._num_total_chunks))
+
+ def append_dont_care(self, num_bytes):
+ """Appends a DONT_CARE chunk to the sparse file.
+
+ The given number of bytes must be a multiple of the block size.
+
+ Arguments:
+ num_bytes: Size in number of bytes of the DONT_CARE chunk.
+ """
+ assert num_bytes % self.block_size == 0
+
+ if not self.is_sparse:
+ self._image.seek(0, os.SEEK_END)
+ # This is more efficient that writing NUL bytes since it'll add
+ # a hole on file systems that support sparse files (native
+ # sparse, not Android sparse).
+ self._image.truncate(self._image.tell() + num_bytes)
+ self._read_header()
+ return
+
+ self._num_total_chunks += 1
+ self._num_total_blocks += num_bytes / self.block_size
+ self._update_chunks_and_blocks()
+
+ self._image.seek(self._sparse_end, os.SEEK_SET)
+ self._image.write(struct.pack(ImageChunk.FORMAT,
+ ImageChunk.TYPE_DONT_CARE,
+ 0, # Reserved
+ num_bytes / self.block_size,
+ struct.calcsize(ImageChunk.FORMAT)))
+ self._read_header()
+
+ def append_raw(self, data):
+ """Appends a RAW chunk to the sparse file.
+
+ The length of the given data must be a multiple of the block size.
+
+ Arguments:
+ data: Data to append.
+ """
+ assert len(data) % self.block_size == 0
+
+ if not self.is_sparse:
+ self._image.seek(0, os.SEEK_END)
+ self._image.write(data)
+ self._read_header()
+ return
+
+ self._num_total_chunks += 1
+ self._num_total_blocks += len(data) / self.block_size
+ self._update_chunks_and_blocks()
+
+ self._image.seek(self._sparse_end, os.SEEK_SET)
+ self._image.write(struct.pack(ImageChunk.FORMAT,
+ ImageChunk.TYPE_RAW,
+ 0, # Reserved
+ len(data) / self.block_size,
+ len(data) +
+ struct.calcsize(ImageChunk.FORMAT)))
+ self._image.write(data)
+ self._read_header()
+
+ def append_fill(self, fill_data, size):
+ """Appends a fill chunk to the sparse file.
+
+ The total length of the fill data must be a multiple of the block size.
+
+ Arguments:
+ fill_data: Fill data to append - must be four bytes.
+ size: Number of chunk - must be a multiple of four and the block size.
+ """
+ assert len(fill_data) == 4
+ assert size % 4 == 0
+ assert size % self.block_size == 0
+
+ if not self.is_sparse:
+ self._image.seek(0, os.SEEK_END)
+ self._image.write(fill_data * (size/4))
+ self._read_header()
+ return
+
+ self._num_total_chunks += 1
+ self._num_total_blocks += size / self.block_size
+ self._update_chunks_and_blocks()
+
+ self._image.seek(self._sparse_end, os.SEEK_SET)
+ self._image.write(struct.pack(ImageChunk.FORMAT,
+ ImageChunk.TYPE_FILL,
+ 0, # Reserved
+ size / self.block_size,
+ 4 + struct.calcsize(ImageChunk.FORMAT)))
+ self._image.write(fill_data)
+ self._read_header()
+
+ def seek(self, offset):
+ """Sets the cursor position for reading from unsparsified file.
+
+ Arguments:
+ offset: Offset to seek to from the beginning of the file.
+ """
+ self._file_pos = offset
+
+ def read(self, size):
+ """Reads data from the unsparsified file.
+
+ This method may return fewer than |size| bytes of data if the end
+ of the file was encountered.
+
+ The file cursor for reading is advanced by the number of bytes
+ read.
+
+ Arguments:
+ size: Number of bytes to read.
+
+ Returns:
+ The data.
+
+ """
+ if not self.is_sparse:
+ self._image.seek(self._file_pos)
+ data = self._image.read(size)
+ self._file_pos += len(data)
+ return data
+
+ # Iterate over all chunks.
+ chunk_idx = bisect.bisect_right(self._chunk_output_offsets,
+ self._file_pos) - 1
+ data = bytearray()
+ to_go = size
+ while to_go > 0:
+ chunk = self._chunks[chunk_idx]
+ chunk_pos_offset = self._file_pos - chunk.output_offset
+ chunk_pos_to_go = min(chunk.output_size - chunk_pos_offset, to_go)
+
+ if chunk.chunk_type == ImageChunk.TYPE_RAW:
+ self._image.seek(chunk.input_offset + chunk_pos_offset)
+ data.extend(self._image.read(chunk_pos_to_go))
+ elif chunk.chunk_type == ImageChunk.TYPE_FILL:
+ all_data = chunk.fill_data*(chunk_pos_to_go/len(chunk.fill_data) + 2)
+ offset_mod = chunk_pos_offset % len(chunk.fill_data)
+ data.extend(all_data[offset_mod:(offset_mod + chunk_pos_to_go)])
+ else:
+ assert chunk.chunk_type == ImageChunk.TYPE_DONT_CARE
+ data.extend('\0' * chunk_pos_to_go)
+
+ to_go -= chunk_pos_to_go
+ self._file_pos += chunk_pos_to_go
+ chunk_idx += 1
+ # Generate partial read in case of EOF.
+ if chunk_idx >= len(self._chunks):
+ break
+
+ return data
+
+ def tell(self):
+ """Returns the file cursor position for reading from unsparsified file.
+
+ Returns:
+ The file cursor position for reading.
+ """
+ return self._file_pos
+
+ def truncate(self, size):
+ """Truncates the unsparsified file.
+
+ Arguments:
+ size: Desired size of unsparsified file.
+
+ Raises:
+ ValueError: If desired size isn't a multiple of the block size.
+ """
+ if not self.is_sparse:
+ self._image.truncate(size)
+ self._read_header()
+ return
+
+ if size % self.block_size != 0:
+ raise ValueError('Cannot truncate to a size which is not a multiple '
+ 'of the block size')
+
+ if size == self.image_size:
+ # Trivial where there's nothing to do.
+ return
+ elif size < self.image_size:
+ chunk_idx = bisect.bisect_right(self._chunk_output_offsets, size) - 1
+ chunk = self._chunks[chunk_idx]
+ if chunk.output_offset != size:
+ # Truncation in the middle of a trunk - need to keep the chunk
+ # and modify it.
+ chunk_idx_for_update = chunk_idx + 1
+ num_to_keep = size - chunk.output_offset
+ assert num_to_keep % self.block_size == 0
+ if chunk.chunk_type == ImageChunk.TYPE_RAW:
+ truncate_at = (chunk.chunk_offset +
+ struct.calcsize(ImageChunk.FORMAT) + num_to_keep)
+ data_sz = num_to_keep
+ elif chunk.chunk_type == ImageChunk.TYPE_FILL:
+ truncate_at = (chunk.chunk_offset +
+ struct.calcsize(ImageChunk.FORMAT) + 4)
+ data_sz = 4
+ else:
+ assert chunk.chunk_type == ImageChunk.TYPE_DONT_CARE
+ truncate_at = chunk.chunk_offset + struct.calcsize(ImageChunk.FORMAT)
+ data_sz = 0
+ chunk_sz = num_to_keep/self.block_size
+ total_sz = data_sz + struct.calcsize(ImageChunk.FORMAT)
+ self._image.seek(chunk.chunk_offset)
+ self._image.write(struct.pack(ImageChunk.FORMAT,
+ chunk.chunk_type,
+ 0, # Reserved
+ chunk_sz,
+ total_sz))
+ chunk.output_size = num_to_keep
+ else:
+ # Truncation at trunk boundary.
+ truncate_at = chunk.chunk_offset
+ chunk_idx_for_update = chunk_idx
+
+ self._num_total_chunks = chunk_idx_for_update
+ self._num_total_blocks = 0
+ for i in range(0, chunk_idx_for_update):
+ self._num_total_blocks += self._chunks[i].output_size / self.block_size
+ self._update_chunks_and_blocks()
+ self._image.truncate(truncate_at)
+
+ # We've modified the file so re-read all data.
+ self._read_header()
+ else:
+ # Truncating to grow - just add a DONT_CARE section.
+ self.append_dont_care(size - self.image_size)
+
+
+class GuidGenerator(object):
+ """An interface for obtaining strings that are GUIDs.
+
+ To facilitate unit testing, this abstraction is used instead of the
+ directly using the uuid module.
+ """
+
+ def dispense_guid(self, partition_number):
+ """Dispenses a GUID.
+
+ Arguments:
+ partition_number: The partition number or 0 if requesting a GUID
+ for the whole disk.
+
+ Returns:
+ A RFC 4122 compliant GUID, as a string.
+ """
+ return str(uuid.uuid4())
+
+
+class Partition(object):
+ """Object representing a partition.
+
+ Attributes:
+ label: The partition label.
+ offset: Offset of the partition on the disk, or None.
+ size: Size of the partition or None if not specified.
+ grow: True if partition has been requested to use all remaining space.
+ guid: Instance GUID (RFC 4122 compliant) as a string or None or 'auto'
+ if it should be automatically generated.
+ type_guid: Type GUID (RFC 4122 compliant) as a string or a known type
+ from the |KNOWN_TYPE_GUIDS| map.
+ flags: GUID flags.
+ persist: If true, sets bit 0 of flags indicating that this partition should
+ not be deleted by the bootloader.
+ ab: If True, the partition is an A/B partition.
+ ab_expanded: If True, the A/B partitions have been generated.
+ ignore: If True, the partition should not be included in the final output.
+ position: The requested position of the partition or 0 if it doesn't matter.
+ """
+
+ def __init__(self):
+ """Initializer method."""
+ self.label = ''
+ self.offset = None
+ self.size = None
+ self.grow = False
+ self.guid = None
+ self.type_guid = None
+ self.flags = 0
+ self.persist = False
+ self.ab = False
+ self.ab_expanded = False
+ self.ignore = False
+ self.position = 0
+
+ def add_info(self, pobj):
+ """Add information to partition.
+
+ Arguments:
+ pobj: A JSON object with information about the partition.
+ """
+ self.label = pobj[JSON_KEYWORD_PARTITIONS_LABEL]
+ value = pobj.get(JSON_KEYWORD_PARTITIONS_OFFSET)
+ if value is not None:
+ self.offset = ParseSize(value)
+ value = pobj.get(JSON_KEYWORD_PARTITIONS_SIZE)
+ if value is not None:
+ self.size = ParseSize(value)
+ value = pobj.get(JSON_KEYWORD_PARTITIONS_GROW)
+ if value is not None:
+ self.grow = value
+ value = pobj.get(JSON_KEYWORD_PARTITIONS_AB)
+ if value is not None:
+ self.ab = value
+ value = pobj.get(JSON_KEYWORD_PARTITIONS_AB_EXPANDED)
+ if value is not None:
+ self.ab_expanded = value
+ value = pobj.get(JSON_KEYWORD_PARTITIONS_GUID)
+ if value is not None:
+ self.guid = value
+ value = pobj.get(JSON_KEYWORD_PARTITIONS_IGNORE)
+ if value is not None:
+ self.ignore = value
+ value = pobj.get(JSON_KEYWORD_PARTITIONS_TYPE_GUID)
+ if value is not None:
+ self.type_guid = str.lower(str(value))
+ if self.type_guid in KNOWN_TYPE_GUIDS:
+ self.type_guid = KNOWN_TYPE_GUIDS[self.type_guid]
+ value = pobj.get(JSON_KEYWORD_PARTITIONS_FLAGS)
+ if value is not None:
+ self.flags = ParseNumber(value)
+ value = pobj.get(JSON_KEYWORD_PARTITIONS_PERSIST)
+ if value is not None:
+ self.persist = value
+ if value:
+ self.flags = self.flags | 0x1
+ value = pobj.get(JSON_KEYWORD_PARTITIONS_POSITION)
+ if value is not None:
+ self.position = ParseNumber(value)
+
+ def expand_guid(self, guid_generator, partition_number):
+ """Assign instance GUID and type GUID if required.
+
+ Arguments:
+ guid_generator: A GuidGenerator object.
+ partition_number: The partition number, starting from 1.
+ """
+ if not self.guid or self.guid == JSON_KEYWORD_AUTO:
+ self.guid = guid_generator.dispense_guid(partition_number)
+ if not self.type_guid:
+ self.type_guid = KNOWN_TYPE_GUIDS['brillo_vendor_specific']
+
+ def validate(self):
+ """Sanity checks data in object."""
+
+ try:
+ _ = uuid.UUID(str(self.guid))
+ except ValueError:
+ raise ValueError('The string "{}" is not a valid GPT instance GUID on '
+ 'partition with label "{}".'.format(
+ str(self.guid), self.label))
+
+ try:
+ _ = uuid.UUID(str(self.type_guid))
+ except ValueError:
+ raise ValueError('The string "{}" is not a valid GPT type GUID on '
+ 'partition with label "{}".'.format(
+ str(self.type_guid), self.label))
+
+ if not self.size:
+ if not self.grow:
+ raise ValueError('Size can only be unset if "grow" is True.')
+
+ def cmp(self, other):
+ """Comparison method."""
+ self_position = self.position
+ if self_position == 0:
+ self_position = GPT_MAX_PART_NUM
+ other_position = other.position
+ if other_position == 0:
+ other_position = GPT_MAX_PART_NUM
+ return cmp(self_position, other_position)
+
+
+class Settings(object):
+ """An object for holding settings.
+
+ Attributes:
+ ab_suffixes: A list of A/B suffixes to use.
+ disk_size: An integer with the disk size in bytes.
+ partitions_offset_begin: An integer with the disk partitions
+ offset begin size in bytes.
+ disk_alignment: The alignment to use for partitions.
+ disk_guid: The GUID to use for the disk or None or 'auto' if
+ automatically generated.
+ """
+
+ def __init__(self):
+ """Initializer with defaults."""
+ self.ab_suffixes = ['_a', '_b']
+ self.disk_size = None
+ self.partitions_offset_begin = 0
+ self.disk_alignment = 4096
+ self.disk_guid = JSON_KEYWORD_AUTO
+
+
+class BptError(Exception):
+ """Application-specific errors.
+
+ These errors represent issues for which a stack-trace should not be
+ presented.
+
+ Attributes:
+ message: Error message.
+ """
+
+ def __init__(self, message):
+ Exception.__init__(self, message)
+
+
+class BptParsingError(BptError):
+ """Represents an error with an input file.
+
+ Attributes:
+ message: Error message.
+ filename: Name of the file that caused an error.
+ """
+
+ def __init__(self, filename, message):
+ self.filename = filename
+ BptError.__init__(self, message)
+
+
+class Bpt(object):
+ """Business logic for bpttool command-line tool."""
+
+ def _read_json(self, input_files, ab_collapse=True):
+ """Parses a stack of JSON files into suitable data structures.
+
+ The order of files matters as later files can modify partitions
+ declared in earlier files.
+
+ Arguments:
+ input_files: An ordered list of open files.
+ ab_collapse: If True, collapse A/B partitions.
+
+ Returns:
+ A tuple where the first element is a list of Partition objects
+ and the second element is a Settings object.
+
+ Raises:
+ BptParsingError: If an input file has an error.
+ """
+ partitions = []
+ settings = Settings()
+
+ # Read all input file and merge partitions and settings.
+ for f in input_files:
+ try:
+ obj = json.loads(f.read())
+ except ValueError as e:
+ # Unfortunately we can't easily get the line number where the
+ # error occurred.
+ raise BptParsingError(f.name, e.message)
+
+ sobj = obj.get(JSON_KEYWORD_SETTINGS)
+ if sobj:
+ ab_suffixes = sobj.get(JSON_KEYWORD_SETTINGS_AB_SUFFIXES)
+ if ab_suffixes:
+ settings.ab_suffixes = ab_suffixes
+ disk_size = sobj.get(JSON_KEYWORD_SETTINGS_DISK_SIZE)
+ if disk_size:
+ settings.disk_size = ParseSize(disk_size)
+ partitions_offset_begin = sobj.get(
+ JSON_KEYWORD_SETTINGS_PARTITIONS_OFFSET_BEGIN)
+ if partitions_offset_begin:
+ settings.partitions_offset_begin = ParseSize(partitions_offset_begin)
+ disk_alignment = sobj.get(JSON_KEYWORD_SETTINGS_DISK_ALIGNMENT)
+ if disk_alignment:
+ settings.disk_alignment = ParseSize(disk_alignment)
+ disk_guid = sobj.get(JSON_KEYWORD_SETTINGS_DISK_GUID)
+ if disk_guid:
+ settings.disk_guid = disk_guid
+
+ pobjs = obj.get(JSON_KEYWORD_PARTITIONS)
+ if pobjs:
+ for pobj in pobjs:
+ if ab_collapse and pobj.get(JSON_KEYWORD_PARTITIONS_AB_EXPANDED):
+ # If we encounter an expanded partition, unexpand it. This
+ # is to make it possible to use output-JSON (from this tool)
+ # and stack it with an input-JSON file that e.g. specifies
+ # size='256 GiB' for the 'system' partition.
+ label = pobj[JSON_KEYWORD_PARTITIONS_LABEL]
+ if label.endswith(settings.ab_suffixes[0]):
+ # Modify first A/B copy so it doesn't have the trailing suffix.
+ new_len = len(label) - len(settings.ab_suffixes[0])
+ pobj[JSON_KEYWORD_PARTITIONS_LABEL] = label[0:new_len]
+ pobj[JSON_KEYWORD_PARTITIONS_AB_EXPANDED] = False
+ pobj[JSON_KEYWORD_PARTITIONS_GUID] = JSON_KEYWORD_AUTO
+ else:
+ # Skip other A/B copies.
+ continue
+ # Find or create a partition.
+ p = None
+ for candidate in partitions:
+ if candidate.label == pobj[JSON_KEYWORD_PARTITIONS_LABEL]:
+ p = candidate
+ break
+ if not p:
+ p = Partition()
+ partitions.append(p)
+ p.add_info(pobj)
+
+ return partitions, settings
+
+ def _generate_json(self, partitions, settings):
+ """Generate a string with JSON representing partitions and settings.
+
+ Arguments:
+ partitions: A list of Partition objects.
+ settings: A Settings object.
+
+ Returns:
+ A JSON string.
+ """
+ suffixes_str = '['
+ for n in range(0, len(settings.ab_suffixes)):
+ if n != 0:
+ suffixes_str += ', '
+ suffixes_str += '"{}"'.format(settings.ab_suffixes[n])
+ suffixes_str += ']'
+
+ ret = ('{{\n'
+ ' "' + JSON_KEYWORD_SETTINGS + '": {{\n'
+ ' "' + JSON_KEYWORD_SETTINGS_AB_SUFFIXES + '": {},\n'
+ ' "' + JSON_KEYWORD_SETTINGS_PARTITIONS_OFFSET_BEGIN + '": {},\n'
+ ' "' + JSON_KEYWORD_SETTINGS_DISK_SIZE + '": {},\n'
+ ' "' + JSON_KEYWORD_SETTINGS_DISK_ALIGNMENT + '": {},\n'
+ ' "' + JSON_KEYWORD_SETTINGS_DISK_GUID + '": "{}"\n'
+ ' }},\n'
+ ' "' + JSON_KEYWORD_PARTITIONS + '": [\n').format(
+ suffixes_str,
+ settings.partitions_offset_begin,
+ settings.disk_size,
+ settings.disk_alignment,
+ settings.disk_guid)
+
+ for n in range(0, len(partitions)):
+ p = partitions[n]
+ ret += (' {{\n'
+ ' "' + JSON_KEYWORD_PARTITIONS_LABEL + '": "{}",\n'
+ ' "' + JSON_KEYWORD_PARTITIONS_OFFSET + '": {},\n'
+ ' "' + JSON_KEYWORD_PARTITIONS_SIZE + '": {},\n'
+ ' "' + JSON_KEYWORD_PARTITIONS_GROW + '": {},\n'
+ ' "' + JSON_KEYWORD_PARTITIONS_GUID + '": "{}",\n'
+ ' "' + JSON_KEYWORD_PARTITIONS_TYPE_GUID + '": "{}",\n'
+ ' "' + JSON_KEYWORD_PARTITIONS_FLAGS + '": "{:#018x}",\n'
+ ' "' + JSON_KEYWORD_PARTITIONS_PERSIST + '": {},\n'
+ ' "' + JSON_KEYWORD_PARTITIONS_IGNORE + '": {},\n'
+ ' "' + JSON_KEYWORD_PARTITIONS_AB + '": {},\n'
+ ' "' + JSON_KEYWORD_PARTITIONS_AB_EXPANDED + '": {},\n'
+ ' "' + JSON_KEYWORD_PARTITIONS_POSITION + '": {}\n'
+ ' }}{}\n').format(p.label,
+ p.offset,
+ p.size,
+ 'true' if p.grow else 'false',
+ p.guid,
+ p.type_guid,
+ p.flags,
+ 'true' if p.persist else 'false',
+ 'true' if p.ignore else 'false',
+ 'true' if p.ab else 'false',
+ 'true' if p.ab_expanded else 'false',
+ p.position,
+ '' if n == len(partitions) - 1 else ',')
+ ret += (' ]\n'
+ '}\n')
+ return ret
+
+ def _lba_to_chs(self, lba):
+ """Converts LBA to CHS.
+
+ Arguments:
+ lba: The sector number to convert.
+
+ Returns:
+ An array containing the CHS encoded the way it's expected in a
+ MBR partition table.
+ """
+ # See https://en.wikipedia.org/wiki/Cylinder-head-sector
+ num_heads = 255
+ num_sectors = 63
+ # If LBA isn't going to fit in CHS, return maximum CHS values.
+ max_lba = 255*num_heads*num_sectors
+ if lba > max_lba:
+ return [255, 255, 255]
+ c = lba / (num_heads*num_sectors)
+ h = (lba / num_sectors) % num_heads
+ s = lba % num_sectors
+ return [h, (((c>>8) & 0x03)<<6) | (s & 0x3f), c & 0xff]
+
+ def _generate_protective_mbr(self, settings):
+ """Generate Protective MBR.
+
+ Arguments:
+ settings: A Settings object.
+
+ Returns:
+ A string with the binary protective MBR (512 bytes).
+ """
+ # See https://en.wikipedia.org/wiki/Master_boot_record for MBR layout.
+ #
+ # The first partition starts at offset 446 (0x1be).
+ lba_start = 1
+ lba_end = settings.disk_size/DISK_SECTOR_SIZE - 1
+ start_chs = self._lba_to_chs(lba_start)
+ end_chs = self._lba_to_chs(lba_end)
+ pmbr = struct.pack('<446s' # Bootloader code
+ 'B' # Status.
+ 'BBB' # CHS start.
+ 'B' # Partition type.
+ 'BBB' # CHS end.
+ 'I' # LBA of partition start.
+ 'I' # Number of sectors in partition.
+ '48x' # Padding to get to offset 510 (0x1fe).
+ 'BB', # Boot signature.
+ '\xfa\xeb\xfe', # cli ; jmp $ (x86)
+ 0x00,
+ start_chs[0], start_chs[1], start_chs[2],
+ 0xee, # MBR Partition Type: GPT protective MBR.
+ end_chs[0], end_chs[1], end_chs[2],
+ 1, # LBA start
+ lba_end,
+ 0x55, 0xaa)
+ return pmbr
+
+ def _generate_gpt(self, partitions, settings, primary=True):
+ """Generate GUID Partition Table.
+
+ Arguments:
+ partitions: A list of Partition objects.
+ settings: A Settings object.
+ primary: True to generate primary GPT, False to generate secondary.
+
+ Returns:
+ A string with the binary GUID Partition Table (33*512 bytes).
+ """
+ # See https://en.wikipedia.org/wiki/Master_boot_record for MBR layout.
+ #
+ # The first partition starts at offset 446 (0x1be).
+
+ disk_num_lbas = settings.disk_size/DISK_SECTOR_SIZE
+ if primary:
+ current_lba = 1
+ other_lba = disk_num_lbas - 1
+ partitions_lba = 2
+ else:
+ current_lba = disk_num_lbas - 1
+ other_lba = 1
+ partitions_lba = disk_num_lbas - GPT_NUM_LBAS
+ first_usable_lba = GPT_NUM_LBAS + 1
+ last_usable_lba = disk_num_lbas - GPT_NUM_LBAS - 1
+
+ part_array = []
+ for p in partitions:
+ part_array.append(struct.pack(
+ '<16s' # Partition type GUID.
+ '16s' # Partition instance GUID.
+ 'QQ' # First and last LBA.
+ 'Q' # Flags.
+ '72s', # Name (36 UTF-16LE code units).
+ uuid.UUID(p.type_guid).get_bytes_le(),
+ uuid.UUID(p.guid).get_bytes_le(),
+ p.offset/DISK_SECTOR_SIZE,
+ (p.offset + p.size)/DISK_SECTOR_SIZE - 1,
+ p.flags,
+ p.label.encode(encoding='utf-16le')))
+
+ part_array.append(((128 - len(partitions))*128) * '\0')
+ part_array_str = ''.join(part_array)
+
+ partitions_crc32 = zlib.crc32(part_array_str) % (1<<32)
+
+ header_crc32 = 0
+ while True:
+ header = struct.pack(
+ '<8s' # Signature.
+ '4B' # Version.
+ 'I' # Header size.
+ 'I' # CRC32 (must be zero during calculation).
+ 'I' # Reserved (must be zero).
+ 'QQ' # Current and Other LBA.
+ 'QQ' # First and last usable LBA.
+ '16s' # Disk GUID.
+ 'Q' # Starting LBA of array of partitions.
+ 'I' # Number of partitions.
+ 'I' # Partition entry size, in bytes.
+ 'I' # CRC32 of partition array
+ '420x', # Padding to get to 512 bytes.
+ 'EFI PART',
+ 0x00, 0x00, 0x01, 0x00,
+ 92,
+ header_crc32,
+ 0x00000000,
+ current_lba, other_lba,
+ first_usable_lba, last_usable_lba,
+ uuid.UUID(settings.disk_guid).get_bytes_le(),
+ partitions_lba,
+ 128,
+ 128,
+ partitions_crc32)
+ if header_crc32 != 0:
+ break
+ header_crc32 = zlib.crc32(header[0:92]) % (1<<32)
+
+ if primary:
+ return header + part_array_str
+ else:
+ return part_array_str + header
+
+ def _generate_gpt_bin(self, partitions, settings):
+ """Generate a bytearray representing partitions and settings.
+
+ The blob will have three partition tables, laid out one after
+ another: 1) Protective MBR (512 bytes); 2) Primary GPT (33*512
+ bytes); and 3) Secondary GPT (33*512 bytes).
+
+ The total size will be 34,304 bytes.
+
+ Arguments:
+ partitions: A list of Partition objects.
+ settings: A Settings object.
+
+ Returns:
+ A bytearray() object.
+ """
+ protective_mbr = self._generate_protective_mbr(settings)
+ primary_gpt = self._generate_gpt(partitions, settings)
+ secondary_gpt = self._generate_gpt(partitions, settings, primary=False)
+ ret = protective_mbr + primary_gpt + secondary_gpt
+ return ret
+
+ def _validate_disk_partitions(self, partitions, disk_size):
+ """Check that a list of partitions have assigned offsets and fits on a
+ disk of a given size.
+
+ This function checks partition offsets and sizes to see if they may fit on
+ a disk image.
+
+ Arguments:
+ partitions: A list of Partition objects.
+ settings: Integer size of disk image.
+
+ Raises:
+ BptError: If checked condition is not satisfied.
+ """
+ for p in partitions:
+ if not p.offset or p.offset < (GPT_NUM_LBAS + 1)*DISK_SECTOR_SIZE:
+ raise BptError('Partition with label "{}" has no offset.'
+ .format(p.label))
+ if not p.size or p.size < 0:
+ raise BptError('Partition with label "{}" has no size.'
+ .format(p.label))
+ if (p.offset + p.size) > (disk_size - GPT_NUM_LBAS*DISK_SECTOR_SIZE):
+ raise BptError('Partition with label "{}" exceeds the disk '
+ 'image size.'.format(p.label))
+
+ def make_table(self,
+ inputs,
+ ab_suffixes=None,
+ partitions_offset_begin=None,
+ disk_size=None,
+ disk_alignment=None,
+ disk_guid=None,
+ guid_generator=None):
+ """Implementation of the 'make_table' command.
+
+ This function takes a list of input partition definition files,
+ flattens them, expands A/B partitions, grows partitions, and lays
+ out partitions according to alignment constraints.
+
+ Arguments:
+ inputs: List of JSON files to parse.
+ ab_suffixes: List of the A/B suffixes (as a comma-separated string)
+ to use or None to not override.
+ partitions_offset_begin: Size of disk partitions offset
+ begin or None to not override.
+ disk_size: Size of disk or None to not override.
+ disk_alignment: Disk alignment or None to not override.
+ disk_guid: Disk GUID as a string or None to not override.
+ guid_generator: A GuidGenerator or None to use the default.
+
+ Returns:
+ A tuple where the first argument is a JSON string for the resulting
+ partitions and the second argument is the binary partition tables.
+
+ Raises:
+ BptParsingError: If an input file has an error.
+ BptError: If another application-specific error occurs
+ """
+ partitions, settings = self._read_json(inputs)
+
+ # Command-line arguments override anything specified in input
+ # files.
+ if disk_size:
+ settings.disk_size = int(math.ceil(disk_size))
+ if disk_alignment:
+ settings.disk_alignment = int(disk_alignment)
+ if partitions_offset_begin:
+ settings.partitions_offset_begin = int(partitions_offset_begin)
+ if ab_suffixes:
+ settings.ab_suffixes = ab_suffixes.split(',')
+ if disk_guid:
+ settings.disk_guid = disk_guid
+
+ if not guid_generator:
+ guid_generator = GuidGenerator()
+
+ # We need to know the disk size. Also round it down to ensure it's
+ # a multiple of the sector size.
+ if not settings.disk_size:
+ raise BptError('Disk size not specified. Use --disk_size option '
+ 'or specify it in an input file.\n')
+ settings.disk_size = RoundToMultiple(settings.disk_size,
+ DISK_SECTOR_SIZE,
+ round_down=True)
+
+ # Alignment must be divisible by disk sector size.
+ if settings.disk_alignment % DISK_SECTOR_SIZE != 0:
+ raise BptError(
+ 'Disk alignment size of {} is not divisible by {}.\n'.format(
+ settings.disk_alignment, DISK_SECTOR_SIZE))
+
+ if settings.partitions_offset_begin != 0:
+ # Disk partitions offset begin size must be
+ # divisible by disk sector size.
+ if settings.partitions_offset_begin % settings.disk_alignment != 0:
+ raise BptError(
+ 'Disk Partitions offset begin size of {} '
+ 'is not divisible by {}.\n'.format(
+ settings.partitions_offset_begin, settings.disk_alignment))
+ settings.partitions_offset_begin = max(settings.partitions_offset_begin,
+ DISK_SECTOR_SIZE*(1 + GPT_NUM_LBAS))
+ settings.partitions_offset_begin = RoundToMultiple(
+ settings.partitions_offset_begin, settings.disk_alignment)
+
+ # Expand A/B partitions and skip ignored partitions.
+ expanded_partitions = []
+ for p in partitions:
+ if p.ignore:
+ continue
+ if p.ab and not p.ab_expanded:
+ p.ab_expanded = True
+ for suffix in settings.ab_suffixes:
+ new_p = copy.deepcopy(p)
+ new_p.label += suffix
+ expanded_partitions.append(new_p)
+ else:
+ expanded_partitions.append(p)
+ partitions = expanded_partitions
+
+ # Expand Disk GUID if needed.
+ if not settings.disk_guid or settings.disk_guid == JSON_KEYWORD_AUTO:
+ settings.disk_guid = guid_generator.dispense_guid(0)
+
+ # Sort according to 'position' attribute.
+ partitions = sorted(partitions, cmp=lambda x, y: x.cmp(y))
+
+ # Automatically generate GUIDs if the GUID is unset or set to
+ # 'auto'. Also validate the rest of the fields.
+ part_no = 1
+ for p in partitions:
+ p.expand_guid(guid_generator, part_no)
+ p.validate()
+ part_no += 1
+
+ # Idenfify partition to grow and lay out partitions, ignoring the
+ # one to grow. This way we can figure out how much space is left.
+ #
+ # Right now we only support a single 'grow' partition but we could
+ # support more in the future by splitting up the available bytes
+ # between them.
+ grow_part = None
+ # offset minimal size: DISK_SECTOR_SIZE*(1 + GPT_NUM_LBAS)
+ offset = max(settings.partitions_offset_begin,
+ DISK_SECTOR_SIZE*(1 + GPT_NUM_LBAS))
+ for p in partitions:
+ if p.grow:
+ if grow_part:
+ raise BptError('Only a single partition can be automatically '
+ 'grown.\n')
+ grow_part = p
+ else:
+ # Ensure size is a multiple of DISK_SECTOR_SIZE by rounding up
+ # (user may specify it as e.g. "1.5 GB" which is not divisible
+ # by 512).
+ p.size = RoundToMultiple(p.size, DISK_SECTOR_SIZE)
+ # Align offset to disk alignment.
+ offset = RoundToMultiple(offset, settings.disk_alignment)
+ offset += p.size
+
+ # After laying out (respecting alignment) all non-grow
+ # partitions, check that the given disk size is big enough.
+ if offset > settings.disk_size - DISK_SECTOR_SIZE*GPT_NUM_LBAS:
+ raise BptError('Disk size of {} bytes is too small for partitions '
+ 'totaling {} bytes.\n'.format(
+ settings.disk_size, offset))
+
+ # If we have a grow partition, it'll starts at the next
+ # available alignment offset and we can calculate its size as
+ # follows.
+ if grow_part:
+ offset = RoundToMultiple(offset, settings.disk_alignment)
+ grow_part.size = RoundToMultiple(
+ settings.disk_size - DISK_SECTOR_SIZE*GPT_NUM_LBAS - offset,
+ settings.disk_alignment,
+ round_down=True)
+ if grow_part.size < DISK_SECTOR_SIZE:
+ raise BptError('Not enough space for partition "{}" to be '
+ 'automatically grown.\n'.format(grow_part.label))
+
+ # Now we can assign partition start offsets for all partitions,
+ # including the grow partition.
+ # offset minimal size: DISK_SECTOR_SIZE*(1 + GPT_NUM_LBAS)
+ offset = max(settings.partitions_offset_begin,
+ DISK_SECTOR_SIZE*(1 + GPT_NUM_LBAS))
+ for p in partitions:
+ # Align offset.
+ offset = RoundToMultiple(offset, settings.disk_alignment)
+ p.offset = offset
+ offset += p.size
+ assert offset <= settings.disk_size - DISK_SECTOR_SIZE*GPT_NUM_LBAS
+
+ json_str = self._generate_json(partitions, settings)
+
+ gpt_bin = self._generate_gpt_bin(partitions, settings)
+
+ return json_str, gpt_bin
+
+ def make_disk_image(self, output, bpt, images, allow_empty_partitions=False):
+ """Implementation of the 'make_disk_image' command.
+
+ This function takes in a list of partitions images and a bpt file
+ for the purpose of creating a raw disk image with a protective MBR,
+ primary and secondary GPT, and content for each partition as specified.
+
+ Arguments:
+ output: Output file where disk image is to be written to.
+ bpt: BPT JSON file to parse.
+ images: List of partition image paths to be combined (as specified by
+ bpt). Each element is of the form.
+ 'PARTITION_NAME:/PATH/TO/PARTITION_IMAGE'
+ allow_empty_partitions: If True, partitions defined in |bpt| need not to
+ be present in |images|. Otherwise an exception is
+ thrown if a partition is referenced in |bpt| but
+ not in |images|.
+
+ Raises:
+ BptParsingError: If an image file has an error.
+ BptError: If another application-specific error occurs.
+ """
+ # Generate partition list and settings.
+ partitions, settings = self._read_json([bpt], ab_collapse=False)
+
+ # Validated partition sizes and offsets.
+ self._validate_disk_partitions(partitions, settings.disk_size)
+
+ # Sort according to 'offset' attribute.
+ partitions = sorted(partitions, cmp=lambda x, y: cmp(x.offset, y.offset))
+
+ # Create necessary tables.
+ protective_mbr = self._generate_protective_mbr(settings)
+ primary_gpt = self._generate_gpt(partitions, settings)
+ secondary_gpt = self._generate_gpt(partitions, settings, primary=False)
+
+ # Start at 0 offset for mbr and primary gpt.
+ output.seek(0)
+ output.write(protective_mbr)
+ output.write(primary_gpt)
+
+ # Create mapping of partition name to partition image file.
+ image_file_names = {}
+ try:
+ for name_path in images:
+ name, path = name_path.split(":")
+ image_file_names[name] = path
+ except ValueError as e:
+ raise BptParsingError(name_path, 'Bad image argument {}.'.format(
+ images[i]))
+
+ # Read image and insert in correct offset.
+ for p in partitions:
+ if p.label not in image_file_names:
+ if allow_empty_partitions:
+ continue
+ else:
+ raise BptParsingError(bpt.name, 'No content specified for partition'
+ ' with label {}'.format(p.label))
+
+ input_image = ImageHandler(image_file_names[p.label])
+ output.seek(p.offset)
+ partition_blob = input_image.read(p.size)
+ output.write(partition_blob)
+
+ # Put secondary GPT and end of disk.
+ output.seek(settings.disk_size - len(secondary_gpt))
+ output.write(secondary_gpt)
+
+ def query_partition(self, input_file, part_label, query_type, ab_collapse):
+ """Implementation of the 'query_partition' command.
+
+ This reads the partition definition file given by |input_file| and
+ returns information of type |query_type| for the partition with
+ label |part_label|.
+
+ Arguments:
+ input_file: A JSON file to parse.
+ part_label: Label of partition to query information about.
+ query_type: The information to query, see |QUERY_PARTITION_TYPES|.
+ ab_collapse: If True, collapse A/B partitions.
+
+ Returns:
+ The requested information as a string or None if there is no
+ partition with the given label.
+
+ Raises:
+ BptParsingError: If an input file has an error.
+ BptError: If another application-specific error occurs
+ """
+
+ partitions, _ = self._read_json([input_file], ab_collapse)
+
+ part = None
+ for p in partitions:
+ if p.label == part_label:
+ part = p
+ break
+
+ if not part:
+ return None
+
+ value = part.__dict__.get(query_type)
+ # Print out flags as a hex-value.
+ if query_type == 'flags':
+ return '{:#018x}'.format(value)
+ return str(value)
+
+
+class BptTool(object):
+ """Object for bpttool command-line tool."""
+
+ def __init__(self):
+ """Initializer method."""
+ self.bpt = Bpt()
+
+ def run(self, argv):
+ """Command-line processor.
+
+ Arguments:
+ argv: Pass sys.argv from main.
+ """
+ parser = argparse.ArgumentParser()
+ subparsers = parser.add_subparsers(title='subcommands')
+
+ sub_parser = subparsers.add_parser(
+ 'version',
+ help='Prints version of bpttool.')
+ sub_parser.set_defaults(func=self.version)
+
+ sub_parser = subparsers.add_parser(
+ 'make_table',
+ help='Lays out partitions and creates partition table.')
+ sub_parser.add_argument('--input',
+ help='Path to partition definition file.',
+ type=argparse.FileType('r'),
+ action='append')
+ sub_parser.add_argument('--ab_suffixes',
+ help='Set or override A/B suffixes.')
+ sub_parser.add_argument('--partitions_offset_begin',
+ help='Set or override disk partitions '
+ 'offset begin size.',
+ type=ParseSize)
+ sub_parser.add_argument('--disk_size',
+ help='Set or override disk size.',
+ type=ParseSize)
+ sub_parser.add_argument('--disk_alignment',
+ help='Set or override disk alignment.',
+ type=ParseSize)
+ sub_parser.add_argument('--disk_guid',
+ help='Set or override disk GUID.',
+ type=ParseGuid)
+ sub_parser.add_argument('--output_json',
+ help='JSON output file name.',
+ type=argparse.FileType('w'))
+ sub_parser.add_argument('--output_gpt',
+ help='Output file name for MBR/GPT/GPT file.',
+ type=argparse.FileType('w'))
+ sub_parser.set_defaults(func=self.make_table)
+
+ sub_parser = subparsers.add_parser(
+ 'make_disk_image',
+ help='Creates disk image for loaded with partitions.')
+ sub_parser.add_argument('--output',
+ help='Path to image output.',
+ type=argparse.FileType('w'),
+ required=True)
+ sub_parser.add_argument('--input',
+ help='Path to bpt file input.',
+ type=argparse.FileType('r'),
+ required=True)
+ sub_parser.add_argument('--image',
+ help='Partition name and path to image file.',
+ metavar='PARTITION_NAME:PATH',
+ action='append')
+ sub_parser.add_argument('--allow_empty_partitions',
+ help='Allow skipping partitions in bpt file.',
+ action='store_true')
+ sub_parser.set_defaults(func=self.make_disk_image)
+
+ sub_parser = subparsers.add_parser(
+ 'query_partition',
+ help='Looks up informtion about a partition.')
+ sub_parser.add_argument('--input',
+ help='Path to partition definition file.',
+ type=argparse.FileType('r'),
+ required=True)
+ sub_parser.add_argument('--label',
+ help='Label of partition to look up.',
+ required=True)
+ sub_parser.add_argument('--ab_collapse',
+ help='Collapse A/B partitions.',
+ action='store_true')
+ sub_parser.add_argument('--type',
+ help='Type of information to look up.',
+ choices=QUERY_PARTITION_TYPES,
+ required=True)
+ sub_parser.set_defaults(func=self.query_partition)
+
+ args = parser.parse_args(argv[1:])
+ args.func(args)
+
+ def version(self, _):
+ """Implements the 'version' sub-command."""
+ print '{}.{}'.format(BPT_VERSION_MAJOR, BPT_VERSION_MINOR)
+
+ def query_partition(self, args):
+ """Implements the 'query_partition' sub-command."""
+ try:
+ result = self.bpt.query_partition(args.input,
+ args.label,
+ args.type,
+ args.ab_collapse)
+ except BptParsingError as e:
+ sys.stderr.write('{}: Error parsing: {}\n'.format(e.filename, e.message))
+ sys.exit(1)
+ except BptError as e:
+ sys.stderr.write('{}\n'.format(e.message))
+ sys.exit(1)
+
+ if not result:
+ sys.stderr.write('No partition with label "{}".\n'.format(args.label))
+ sys.exit(1)
+
+ print result
+
+ def make_table(self, args):
+ """Implements the 'make_table' sub-command."""
+ if not args.input:
+ sys.stderr.write('Option --input is required one or more times.\n')
+ sys.exit(1)
+
+ try:
+ (json_str, gpt_bin) = self.bpt.make_table(args.input, args.ab_suffixes,
+ args.partitions_offset_begin,
+ args.disk_size,
+ args.disk_alignment,
+ args.disk_guid)
+ except BptParsingError as e:
+ sys.stderr.write('{}: Error parsing: {}\n'.format(e.filename, e.message))
+ sys.exit(1)
+ except BptError as e:
+ sys.stderr.write('{}\n'.format(e.message))
+ sys.exit(1)
+
+ if args.output_json:
+ args.output_json.write(json_str)
+ if args.output_gpt:
+ args.output_gpt.write(gpt_bin)
+
+ def make_disk_image(self, args):
+ """Implements the 'make_disk_image' sub-command."""
+ if not args.input:
+ sys.stderr.write('Option --input is required.\n')
+ sys.exit(1)
+ if not args.output:
+ sys.stderr.write('Option --ouptut is required.\n')
+ sys.exit(1)
+
+ try:
+ self.bpt.make_disk_image(args.output,
+ args.input,
+ args.image,
+ args.allow_empty_partitions)
+ except BptParsingError as e:
+ sys.stderr.write('{}: Error parsing: {}\n'.format(e.filename, e.message))
+ sys.exit(1)
+ except 'BptError' as e:
+ sys.stderr.write('{}\n'.format(e.message))
+ sys.exit(1)
+
+if __name__ == '__main__':
+ tool = BptTool()
+ tool.run(sys.argv)
diff --git a/host/commands/assemble_cvd/clean.cc b/host/commands/assemble_cvd/clean.cc
deleted file mode 100644
index 6197a8f26..000000000
--- a/host/commands/assemble_cvd/clean.cc
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Copyright (C) 2020 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 "host/commands/assemble_cvd/clean.h"
-
-#include <dirent.h>
-#include <errno.h>
-#include <sys/stat.h>
-
-#include <regex>
-#include <vector>
-
-#include <android-base/logging.h>
-
-#include "host/commands/assemble_cvd/flags.h"
-#include "common/libs/utils/files.h"
-
-namespace cuttlefish {
-namespace {
-
-bool CleanPriorFiles(const std::string& path, const std::set<std::string>& preserving) {
- if (preserving.count(cpp_basename(path))) {
- LOG(DEBUG) << "Preserving: " << path;
- return true;
- }
- struct stat statbuf;
- if (lstat(path.c_str(), &statbuf) < 0) {
- int error_num = errno;
- if (error_num == ENOENT) {
- return true;
- } else {
- LOG(ERROR) << "Could not stat \"" << path << "\": " << strerror(error_num);
- return false;
- }
- }
- if ((statbuf.st_mode & S_IFMT) != S_IFDIR) {
- LOG(DEBUG) << "Deleting: " << path;
- if (unlink(path.c_str()) < 0) {
- int error_num = errno;
- LOG(ERROR) << "Could not unlink \"" << path << "\", error was " << strerror(error_num);
- return false;
- }
- return true;
- }
- std::unique_ptr<DIR, int(*)(DIR*)> dir(opendir(path.c_str()), closedir);
- if (!dir) {
- int error_num = errno;
- LOG(ERROR) << "Could not clean \"" << path << "\": error was " << strerror(error_num);
- return false;
- }
- for (auto entity = readdir(dir.get()); entity != nullptr; entity = readdir(dir.get())) {
- std::string entity_name(entity->d_name);
- if (entity_name == "." || entity_name == "..") {
- continue;
- }
- std::string entity_path = path + "/" + entity_name;
- if (!CleanPriorFiles(entity_path.c_str(), preserving)) {
- return false;
- }
- }
- if (rmdir(path.c_str()) < 0) {
- if (!(errno == EEXIST || errno == ENOTEMPTY)) {
- // If EEXIST or ENOTEMPTY, probably because a file was preserved
- int error_num = errno;
- LOG(ERROR) << "Could not rmdir \"" << path << "\", error was " << strerror(error_num);
- return false;
- }
- }
- return true;
-}
-
-bool CleanPriorFiles(const std::vector<std::string>& paths, const std::set<std::string>& preserving) {
- std::string prior_files;
- for (auto path : paths) {
- struct stat statbuf;
- if (stat(path.c_str(), &statbuf) < 0 && errno != ENOENT) {
- // If ENOENT, it doesn't exist yet, so there is no work to do'
- int error_num = errno;
- LOG(ERROR) << "Could not stat \"" << path << "\": " << strerror(error_num);
- return false;
- }
- bool is_directory = (statbuf.st_mode & S_IFMT) == S_IFDIR;
- prior_files += (is_directory ? (path + "/*") : path) + " ";
- }
- LOG(DEBUG) << "Assuming prior files of " << prior_files;
- std::string lsof_cmd = "lsof -t " + prior_files + " >/dev/null 2>&1";
- int rval = std::system(lsof_cmd.c_str());
- // lsof returns 0 if any of the files are open
- if (WEXITSTATUS(rval) == 0) {
- LOG(ERROR) << "Clean aborted: files are in use";
- return false;
- }
- for (const auto& path : paths) {
- if (!CleanPriorFiles(path, preserving)) {
- LOG(ERROR) << "Remove of file under \"" << path << "\" failed";
- return false;
- }
- }
- return true;
-}
-
-} // namespace
-
-bool CleanPriorFiles(
- const std::set<std::string>& preserving,
- const std::string& assembly_dir,
- const std::string& instance_dir) {
- std::vector<std::string> paths = {
- // Everything in the assembly directory
- assembly_dir,
- // The environment file
- GetCuttlefishEnvPath(),
- // The global link to the config file
- GetGlobalConfigFileLink(),
- };
-
- std::string runtime_dir_parent = cpp_dirname(AbsolutePath(instance_dir));
- std::string runtime_dirs_basename = cpp_basename(AbsolutePath(instance_dir));
-
- std::regex instance_dir_regex("^.+\\.[1-9]\\d*$");
- for (const auto& path : DirectoryContents(runtime_dir_parent)) {
- std::string absl_path = runtime_dir_parent + "/" + path;
- if((path.rfind(runtime_dirs_basename, 0) == 0) && std::regex_match(path, instance_dir_regex) &&
- DirectoryExists(absl_path)) {
- paths.push_back(absl_path);
- }
- }
- paths.push_back(instance_dir);
- return CleanPriorFiles(paths, preserving);
-}
-
-bool EnsureDirectoryExists(const std::string& directory_path) {
- if (!DirectoryExists(directory_path)) {
- LOG(DEBUG) << "Setting up " << directory_path;
- if (mkdir(directory_path.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) < 0
- && errno != EEXIST) {
- PLOG(ERROR) << "Failed to create dir: \"" << directory_path << "\" ";
- return false;
- }
- }
- return true;
-}
-
-} // namespace cuttlefish
diff --git a/host/commands/assemble_cvd/clean.h b/host/commands/assemble_cvd/clean.h
deleted file mode 100644
index 1f336851b..000000000
--- a/host/commands/assemble_cvd/clean.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2020 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 <set>
-#include <string>
-
-namespace cuttlefish {
-
-bool CleanPriorFiles(
- const std::set<std::string>& preserving,
- const std::string& assembly_dir,
- const std::string& instance_dir);
-
-bool EnsureDirectoryExists(const std::string& directory_path);
-
-} // namespace cuttlefish
diff --git a/host/libs/config/data_image.cpp b/host/commands/assemble_cvd/data_image.cc
index 044dadbfa..1e6e46d92 100644
--- a/host/libs/config/data_image.cpp
+++ b/host/commands/assemble_cvd/data_image.cc
@@ -1,4 +1,4 @@
-#include "host/libs/config/data_image.h"
+#include "host/commands/assemble_cvd/data_image.h"
#include <android-base/logging.h>
@@ -7,9 +7,7 @@
#include "common/libs/utils/files.h"
#include "common/libs/utils/subprocess.h"
-#include "host/libs/config/mbr.h"
-
-namespace cuttlefish {
+#include "host/commands/assemble_cvd/mbr.h"
namespace {
const std::string kDataPolicyUseExisting = "use_existing";
@@ -21,8 +19,8 @@ const int FSCK_ERROR_CORRECTED = 1;
const int FSCK_ERROR_CORRECTED_REQUIRES_REBOOT = 2;
bool ForceFsckImage(const char* data_image) {
- auto fsck_path = HostBinaryPath("fsck.f2fs");
- int fsck_status = execute({fsck_path, "-y", "-f", data_image});
+ auto fsck_path = vsoc::DefaultHostArtifactsPath("bin/fsck.f2fs");
+ int fsck_status = cvd::execute({fsck_path, "-y", "-f", data_image});
if (fsck_status & ~(FSCK_ERROR_CORRECTED|FSCK_ERROR_CORRECTED_REQUIRES_REBOOT)) {
LOG(ERROR) << "`fsck.f2fs -y -f " << data_image << "` failed with code "
<< fsck_status;
@@ -32,7 +30,7 @@ bool ForceFsckImage(const char* data_image) {
}
bool ResizeImage(const char* data_image, int data_image_mb) {
- auto file_mb = FileSize(data_image) >> 20;
+ auto file_mb = cvd::FileSize(data_image) >> 20;
if (file_mb > data_image_mb) {
LOG(ERROR) << data_image << " is already " << file_mb << " MB, will not "
<< "resize down.";
@@ -42,7 +40,7 @@ bool ResizeImage(const char* data_image, int data_image_mb) {
return true;
} else {
off_t raw_target = static_cast<off_t>(data_image_mb) << 20;
- auto fd = SharedFD::Open(data_image, O_RDWR);
+ auto fd = cvd::SharedFD::Open(data_image, O_RDWR);
if (fd->Truncate(raw_target) != 0) {
LOG(ERROR) << "`truncate --size=" << data_image_mb << "M "
<< data_image << "` failed:" << fd->StrError();
@@ -52,8 +50,8 @@ bool ResizeImage(const char* data_image, int data_image_mb) {
if (!fsck_success) {
return false;
}
- auto resize_path = HostBinaryPath("resize.f2fs");
- int resize_status = execute({resize_path, data_image});
+ auto resize_path = vsoc::DefaultHostArtifactsPath("bin/resize.f2fs");
+ int resize_status = cvd::execute({resize_path, data_image});
if (resize_status != 0) {
LOG(ERROR) << "`resize.f2fs " << data_image << "` failed with code "
<< resize_status;
@@ -70,13 +68,13 @@ bool ResizeImage(const char* data_image, int data_image_mb) {
void CreateBlankImage(
const std::string& image, int num_mb, const std::string& image_fmt) {
- LOG(DEBUG) << "Creating " << image;
+ LOG(INFO) << "Creating " << image;
off_t image_size_bytes = static_cast<off_t>(num_mb) << 20;
// The newfs_msdos tool with the mandatory -C option will do the same
// as below to zero the image file, so we don't need to do it here
if (image_fmt != "sdcard") {
- auto fd = SharedFD::Open(image, O_CREAT | O_TRUNC | O_RDWR, 0666);
+ auto fd = cvd::SharedFD::Open(image, O_CREAT | O_TRUNC | O_RDWR, 0666);
if (fd->Truncate(image_size_bytes) != 0) {
LOG(ERROR) << "`truncate --size=" << num_mb << "M " << image
<< "` failed:" << fd->StrError();
@@ -85,25 +83,24 @@ void CreateBlankImage(
}
if (image_fmt == "ext4") {
- execute({"/sbin/mkfs.ext4", image});
+ cvd::execute({"/sbin/mkfs.ext4", image});
} else if (image_fmt == "f2fs") {
- auto make_f2fs_path = cuttlefish::HostBinaryPath("make_f2fs");
- execute({make_f2fs_path, "-t", image_fmt, image, "-C", "utf8", "-O",
- "compression,extra_attr,prjquota", "-g", "android"});
+ auto make_f2fs_path = vsoc::DefaultHostArtifactsPath("bin/make_f2fs");
+ cvd::execute({make_f2fs_path, "-t", image_fmt, image, "-g", "android"});
} else if (image_fmt == "sdcard") {
// Reserve 1MB in the image for the MBR and padding, to simulate what
// other OSes do by default when partitioning a drive
off_t offset_size_bytes = 1 << 20;
image_size_bytes -= offset_size_bytes;
off_t image_size_sectors = image_size_bytes / 512;
- auto newfs_msdos_path = HostBinaryPath("newfs_msdos");
- execute({newfs_msdos_path, "-F", "32", "-m", "0xf8", "-a", "4088",
- "-o", "0", "-c", "8", "-h", "255",
- "-u", "63", "-S", "512",
- "-s", std::to_string(image_size_sectors),
- "-C", std::to_string(num_mb) + "M",
- "-@", std::to_string(offset_size_bytes),
- image});
+ auto newfs_msdos_path = vsoc::DefaultHostArtifactsPath("bin/newfs_msdos");
+ cvd::execute({newfs_msdos_path, "-F", "32", "-m", "0xf8", "-a", "4088",
+ "-o", "0", "-c", "8", "-h", "255",
+ "-u", "63", "-S", "512",
+ "-s", std::to_string(image_size_sectors),
+ "-C", std::to_string(num_mb) + "M",
+ "-@", std::to_string(offset_size_bytes),
+ image});
// Write the MBR after the filesystem is formatted, as the formatting tools
// don't consistently preserve the image contents
MasterBootRecord mbr = {
@@ -114,8 +111,8 @@ void CreateBlankImage(
}},
.boot_signature = { 0x55, 0xAA },
};
- auto fd = SharedFD::Open(image, O_RDWR);
- if (WriteAllBinary(fd, &mbr) != sizeof(MasterBootRecord)) {
+ auto fd = cvd::SharedFD::Open(image, O_RDWR);
+ if (cvd::WriteAllBinary(fd, &mbr) != sizeof(MasterBootRecord)) {
LOG(ERROR) << "Writing MBR to " << image << " failed:" << fd->StrError();
return;
}
@@ -125,9 +122,9 @@ void CreateBlankImage(
}
}
-DataImageResult ApplyDataImagePolicy(const CuttlefishConfig& config,
- const std::string& data_image) {
- bool data_exists = FileHasContent(data_image.c_str());
+bool ApplyDataImagePolicy(const vsoc::CuttlefishConfig& config,
+ const std::string& data_image) {
+ bool data_exists = cvd::FileHasContent(data_image.c_str());
bool remove{};
bool create{};
bool resize{};
@@ -135,12 +132,12 @@ DataImageResult ApplyDataImagePolicy(const CuttlefishConfig& config,
if (config.data_policy() == kDataPolicyUseExisting) {
if (!data_exists) {
LOG(ERROR) << "Specified data image file does not exists: " << data_image;
- return DataImageResult::Error;
+ return false;
}
if (config.blank_data_image_mb() > 0) {
LOG(ERROR) << "You should NOT use -blank_data_image_mb with -data_policy="
<< kDataPolicyUseExisting;
- return DataImageResult::Error;
+ return false;
}
create = false;
remove = false;
@@ -159,45 +156,42 @@ DataImageResult ApplyDataImagePolicy(const CuttlefishConfig& config,
resize = true;
} else {
LOG(ERROR) << "Invalid data_policy: " << config.data_policy();
- return DataImageResult::Error;
+ return false;
}
if (remove) {
- RemoveFile(data_image.c_str());
+ cvd::RemoveFile(data_image.c_str());
}
if (create) {
if (config.blank_data_image_mb() <= 0) {
LOG(ERROR) << "-blank_data_image_mb is required to create data image";
- return DataImageResult::Error;
+ return false;
}
CreateBlankImage(data_image.c_str(), config.blank_data_image_mb(),
config.blank_data_image_fmt());
- return DataImageResult::FileUpdated;
} else if (resize) {
if (!data_exists) {
LOG(ERROR) << data_image << " does not exist, but resizing was requested";
- return DataImageResult::Error;
+ return false;
}
- bool success = ResizeImage(data_image.c_str(), config.blank_data_image_mb());
- return success ? DataImageResult::FileUpdated : DataImageResult::Error;
+ return ResizeImage(data_image.c_str(), config.blank_data_image_mb());
} else {
- LOG(DEBUG) << data_image << " exists. Not creating it.";
- return DataImageResult::NoChange;
+ LOG(INFO) << data_image << " exists. Not creating it.";
}
+
+ return true;
}
bool InitializeMiscImage(const std::string& misc_image) {
- bool misc_exists = FileHasContent(misc_image.c_str());
+ bool misc_exists = cvd::FileHasContent(misc_image.c_str());
if (misc_exists) {
- LOG(DEBUG) << "misc partition image: use existing";
+ LOG(INFO) << "misc partition image: use existing";
return true;
}
- LOG(DEBUG) << "misc partition image: creating empty";
+ LOG(INFO) << "misc partition image: creating empty";
CreateBlankImage(misc_image, 1 /* mb */, "none");
return true;
}
-
-} // namespace cuttlefish
diff --git a/host/commands/assemble_cvd/data_image.h b/host/commands/assemble_cvd/data_image.h
new file mode 100644
index 000000000..4c4022f36
--- /dev/null
+++ b/host/commands/assemble_cvd/data_image.h
@@ -0,0 +1,11 @@
+#pragma once
+
+#include <string>
+
+#include "host/libs/config/cuttlefish_config.h"
+
+bool ApplyDataImagePolicy(const vsoc::CuttlefishConfig& config,
+ const std::string& path);
+bool InitializeMiscImage(const std::string& misc_image);
+void CreateBlankImage(
+ const std::string& image, int num_mb, const std::string& image_fmt);
diff --git a/host/commands/assemble_cvd/disk_flags.cc b/host/commands/assemble_cvd/disk_flags.cc
deleted file mode 100644
index e5ccac958..000000000
--- a/host/commands/assemble_cvd/disk_flags.cc
+++ /dev/null
@@ -1,596 +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.
- */
-
-#include "host/commands/assemble_cvd/disk_flags.h"
-
-#include <sys/statvfs.h>
-
-#include <fstream>
-
-#include <android-base/logging.h>
-#include <android-base/strings.h>
-#include <gflags/gflags.h>
-
-#include "common/libs/fs/shared_buf.h"
-#include "common/libs/utils/environment.h"
-#include "common/libs/utils/files.h"
-#include "common/libs/utils/size_utils.h"
-#include "common/libs/utils/subprocess.h"
-#include "host/commands/assemble_cvd/boot_config.h"
-#include "host/commands/assemble_cvd/boot_image_utils.h"
-#include "host/commands/assemble_cvd/super_image_mixer.h"
-#include "host/libs/config/bootconfig_args.h"
-#include "host/libs/config/cuttlefish_config.h"
-#include "host/libs/config/data_image.h"
-#include "host/libs/image_aggregator/image_aggregator.h"
-#include "host/libs/vm_manager/crosvm_manager.h"
-
-// Taken from external/avb/libavb/avb_slot_verify.c; this define is not in the headers
-#define VBMETA_MAX_SIZE 65536ul
-
-DEFINE_string(system_image_dir, cuttlefish::DefaultGuestImagePath(""),
- "Location of the system partition images.");
-
-DEFINE_string(boot_image, "",
- "Location of cuttlefish boot image. If empty it is assumed to be "
- "boot.img in the directory specified by -system_image_dir.");
-DEFINE_string(data_image, "", "Location of the data partition image.");
-DEFINE_string(super_image, "", "Location of the super partition image.");
-DEFINE_string(misc_image, "",
- "Location of the misc partition image. If the image does not "
- "exist, a blank new misc partition image is created.");
-DEFINE_string(metadata_image, "", "Location of the metadata partition image "
- "to be generated.");
-DEFINE_string(vendor_boot_image, "",
- "Location of cuttlefish vendor boot image. If empty it is assumed to "
- "be vendor_boot.img in the directory specified by -system_image_dir.");
-DEFINE_string(vbmeta_image, "",
- "Location of cuttlefish vbmeta image. If empty it is assumed to "
- "be vbmeta.img in the directory specified by -system_image_dir.");
-DEFINE_string(vbmeta_system_image, "",
- "Location of cuttlefish vbmeta_system image. If empty it is assumed to "
- "be vbmeta_system.img in the directory specified by -system_image_dir.");
-DEFINE_string(esp, "", "Path to ESP partition image (FAT formatted)");
-
-DEFINE_int32(blank_metadata_image_mb, 16,
- "The size of the blank metadata image to generate, MB.");
-DEFINE_int32(blank_sdcard_image_mb, 2048,
- "If enabled, the size of the blank sdcard image to generate, MB.");
-
-DECLARE_string(bootloader);
-DECLARE_bool(use_sdcard);
-DECLARE_string(initramfs_path);
-DECLARE_string(kernel_path);
-DECLARE_bool(resume);
-DECLARE_bool(protected_vm);
-
-namespace cuttlefish {
-
-using vm_manager::CrosvmManager;
-
-bool ResolveInstanceFiles() {
- if (FLAGS_system_image_dir.empty()) {
- LOG(ERROR) << "--system_image_dir must be specified.";
- return false;
- }
-
- // If user did not specify location of either of these files, expect them to
- // be placed in --system_image_dir location.
- std::string default_boot_image = FLAGS_system_image_dir + "/boot.img";
- SetCommandLineOptionWithMode("boot_image", default_boot_image.c_str(),
- google::FlagSettingMode::SET_FLAGS_DEFAULT);
- std::string default_data_image = FLAGS_system_image_dir + "/userdata.img";
- SetCommandLineOptionWithMode("data_image", default_data_image.c_str(),
- google::FlagSettingMode::SET_FLAGS_DEFAULT);
- std::string default_metadata_image = FLAGS_system_image_dir + "/metadata.img";
- SetCommandLineOptionWithMode("metadata_image", default_metadata_image.c_str(),
- google::FlagSettingMode::SET_FLAGS_DEFAULT);
- std::string default_super_image = FLAGS_system_image_dir + "/super.img";
- SetCommandLineOptionWithMode("super_image", default_super_image.c_str(),
- google::FlagSettingMode::SET_FLAGS_DEFAULT);
- std::string default_misc_image = FLAGS_system_image_dir + "/misc.img";
- SetCommandLineOptionWithMode("misc_image", default_misc_image.c_str(),
- google::FlagSettingMode::SET_FLAGS_DEFAULT);
- std::string default_vendor_boot_image = FLAGS_system_image_dir
- + "/vendor_boot.img";
- SetCommandLineOptionWithMode("vendor_boot_image",
- default_vendor_boot_image.c_str(),
- google::FlagSettingMode::SET_FLAGS_DEFAULT);
- std::string default_vbmeta_image = FLAGS_system_image_dir + "/vbmeta.img";
- SetCommandLineOptionWithMode("vbmeta_image", default_vbmeta_image.c_str(),
- google::FlagSettingMode::SET_FLAGS_DEFAULT);
- std::string default_vbmeta_system_image = FLAGS_system_image_dir
- + "/vbmeta_system.img";
- SetCommandLineOptionWithMode("vbmeta_system_image",
- default_vbmeta_system_image.c_str(),
- google::FlagSettingMode::SET_FLAGS_DEFAULT);
-
- return true;
-}
-
-std::vector<ImagePartition> os_composite_disk_config(
- const CuttlefishConfig::InstanceSpecific& instance) {
- std::vector<ImagePartition> partitions;
- partitions.push_back(ImagePartition {
- .label = "misc",
- .image_file_path = FLAGS_misc_image,
- });
- if (!FLAGS_esp.empty()) {
- partitions.push_back(ImagePartition {
- .label = "esp",
- .image_file_path = FLAGS_esp,
- .type = kEfiSystemPartition,
- });
- }
- partitions.push_back(ImagePartition {
- .label = "boot_a",
- .image_file_path = FLAGS_boot_image,
- });
- partitions.push_back(ImagePartition {
- .label = "boot_b",
- .image_file_path = FLAGS_boot_image,
- });
- // Boot image repacking is not supported on protected VMs. Repacking requires
- // resigning the image and keys on android hosts aren't trusted.
- if (!FLAGS_protected_vm) {
- partitions.push_back(ImagePartition{
- .label = "vendor_boot_a",
- .image_file_path = instance.vendor_boot_image_path(),
- });
- partitions.push_back(ImagePartition{
- .label = "vendor_boot_b",
- .image_file_path = instance.vendor_boot_image_path(),
- });
- } else {
- partitions.push_back(ImagePartition{
- .label = "vendor_boot_a",
- .image_file_path = FLAGS_vendor_boot_image,
- });
- partitions.push_back(ImagePartition{
- .label = "vendor_boot_b",
- .image_file_path = FLAGS_vendor_boot_image,
- });
- }
- partitions.push_back(ImagePartition {
- .label = "vbmeta_a",
- .image_file_path = FLAGS_vbmeta_image,
- });
- partitions.push_back(ImagePartition {
- .label = "vbmeta_b",
- .image_file_path = FLAGS_vbmeta_image,
- });
- partitions.push_back(ImagePartition {
- .label = "vbmeta_system_a",
- .image_file_path = FLAGS_vbmeta_system_image,
- });
- partitions.push_back(ImagePartition {
- .label = "vbmeta_system_b",
- .image_file_path = FLAGS_vbmeta_system_image,
- });
- partitions.push_back(ImagePartition {
- .label = "super",
- .image_file_path = FLAGS_super_image,
- });
- partitions.push_back(ImagePartition {
- .label = "userdata",
- .image_file_path = FLAGS_data_image,
- });
- partitions.push_back(ImagePartition {
- .label = "metadata",
- .image_file_path = FLAGS_metadata_image,
- });
- return partitions;
-}
-
-std::vector<ImagePartition> persistent_composite_disk_config(
- const CuttlefishConfig::InstanceSpecific& instance) {
- std::vector<ImagePartition> partitions;
-
- // Note that if the position of uboot_env changes, the environment for
- // u-boot must be updated as well (see boot_config.cc and
- // cuttlefish.fragment in external/u-boot).
- partitions.push_back(ImagePartition{
- .label = "uboot_env",
- .image_file_path = instance.uboot_env_image_path(),
- });
- if (!FLAGS_protected_vm) {
- partitions.push_back(ImagePartition{
- .label = "frp",
- .image_file_path = instance.factory_reset_protected_path(),
- });
- }
- partitions.push_back(ImagePartition{
- .label = "bootconfig",
- .image_file_path = instance.persistent_bootconfig_path(),
- });
- return partitions;
-}
-
-static std::chrono::system_clock::time_point LastUpdatedInputDisk(
- const std::vector<ImagePartition>& partitions) {
- std::chrono::system_clock::time_point ret;
- for (auto& partition : partitions) {
- if (partition.label == "frp") {
- continue;
- }
-
- auto partition_mod_time = FileModificationTime(partition.image_file_path);
- if (partition_mod_time > ret) {
- ret = partition_mod_time;
- }
- }
- return ret;
-}
-
-bool ShouldCreateAllCompositeDisks(const CuttlefishConfig& config) {
- std::chrono::system_clock::time_point youngest_disk_img;
- for (auto& partition :
- os_composite_disk_config(config.ForDefaultInstance())) {
- auto partition_mod_time = FileModificationTime(partition.image_file_path);
- if (partition_mod_time > youngest_disk_img) {
- youngest_disk_img = partition_mod_time;
- }
- }
-
- // If the youngest partition img is younger than any composite disk, this fact implies that
- // the composite disks are all out of date and need to be reinitialized.
- for (auto& instance : config.Instances()) {
- if (!FileExists(instance.os_composite_disk_path())) {
- continue;
- }
- if (youngest_disk_img >
- FileModificationTime(instance.os_composite_disk_path())) {
- return true;
- }
- }
-
- return false;
-}
-
-bool DoesCompositeMatchCurrentDiskConfig(
- const std::string& prior_disk_config_path,
- const std::vector<ImagePartition>& partitions) {
- std::string current_disk_config_path = prior_disk_config_path + ".tmp";
- std::ostringstream disk_conf;
- for (auto& partition : partitions) {
- disk_conf << partition.image_file_path << "\n";
- }
-
- {
- // This file acts as a descriptor of the cuttlefish disk contents in a VMM agnostic way (VMMs
- // used are QEMU and CrosVM at the time of writing). This file is used to determine if the
- // disk config for the pending boot matches the disk from the past boot.
- std::ofstream file_out(current_disk_config_path.c_str(), std::ios::binary);
- file_out << disk_conf.str();
- CHECK(file_out.good()) << "Disk config verification failed.";
- }
-
- if (!FileExists(prior_disk_config_path) ||
- ReadFile(prior_disk_config_path) != ReadFile(current_disk_config_path)) {
- CHECK(cuttlefish::RenameFile(current_disk_config_path, prior_disk_config_path))
- << "Unable to delete the old disk config descriptor";
- LOG(DEBUG) << "Disk Config has changed since last boot. Regenerating composite disk.";
- return false;
- } else {
- RemoveFile(current_disk_config_path);
- return true;
- }
-}
-
-bool ShouldCreateCompositeDisk(const std::string& composite_disk_path,
- const std::vector<ImagePartition>& partitions) {
- if (!FileExists(composite_disk_path)) {
- return true;
- }
-
- auto composite_age = FileModificationTime(composite_disk_path);
- return composite_age < LastUpdatedInputDisk(partitions);
-}
-
-static uint64_t AvailableSpaceAtPath(const std::string& path) {
- struct statvfs vfs;
- if (statvfs(path.c_str(), &vfs) != 0) {
- int error_num = errno;
- LOG(ERROR) << "Could not find space available at " << path << ", error was "
- << strerror(error_num);
- return 0;
- }
- // f_frsize (block size) * f_bavail (free blocks) for unprivileged users.
- return static_cast<uint64_t>(vfs.f_frsize) * vfs.f_bavail;
-}
-
-bool CreateCompositeDisk(const CuttlefishConfig& config,
- const CuttlefishConfig::InstanceSpecific& instance) {
- if (!SharedFD::Open(instance.os_composite_disk_path().c_str(),
- O_WRONLY | O_CREAT, 0644)
- ->IsOpen()) {
- LOG(ERROR) << "Could not ensure " << instance.os_composite_disk_path()
- << " exists";
- return false;
- }
- if (config.vm_manager() == CrosvmManager::name()) {
- // Check if filling in the sparse image would run out of disk space.
- auto existing_sizes = SparseFileSizes(FLAGS_data_image);
- if (existing_sizes.sparse_size == 0 && existing_sizes.disk_size == 0) {
- LOG(ERROR) << "Unable to determine size of \"" << FLAGS_data_image
- << "\". Does this file exist?";
- }
- auto available_space = AvailableSpaceAtPath(FLAGS_data_image);
- if (available_space < existing_sizes.sparse_size - existing_sizes.disk_size) {
- // TODO(schuffelen): Duplicate this check in run_cvd when it can run on a separate machine
- LOG(ERROR) << "Not enough space remaining in fs containing " << FLAGS_data_image;
- LOG(ERROR) << "Wanted " << (existing_sizes.sparse_size - existing_sizes.disk_size);
- LOG(ERROR) << "Got " << available_space;
- return false;
- } else {
- LOG(DEBUG) << "Available space: " << available_space;
- LOG(DEBUG) << "Sparse size of \"" << FLAGS_data_image << "\": "
- << existing_sizes.sparse_size;
- LOG(DEBUG) << "Disk size of \"" << FLAGS_data_image << "\": "
- << existing_sizes.disk_size;
- }
- std::string header_path =
- instance.PerInstancePath("os_composite_gpt_header.img");
- std::string footer_path =
- instance.PerInstancePath("os_composite_gpt_footer.img");
- CreateCompositeDisk(os_composite_disk_config(instance), header_path,
- footer_path, instance.os_composite_disk_path());
- } else {
- // If this doesn't fit into the disk, it will fail while aggregating. The
- // aggregator doesn't maintain any sparse attributes.
- AggregateImage(os_composite_disk_config(instance),
- instance.os_composite_disk_path());
- }
- return true;
-}
-
-bool CreatePersistentCompositeDisk(
- const CuttlefishConfig& config,
- const CuttlefishConfig::InstanceSpecific& instance) {
- if (!SharedFD::Open(instance.persistent_composite_disk_path().c_str(),
- O_WRONLY | O_CREAT, 0644)
- ->IsOpen()) {
- LOG(ERROR) << "Could not ensure "
- << instance.persistent_composite_disk_path() << " exists";
- return false;
- }
- if (config.vm_manager() == CrosvmManager::name()) {
- std::string header_path =
- instance.PerInstancePath("persistent_composite_gpt_header.img");
- std::string footer_path =
- instance.PerInstancePath("persistent_composite_gpt_footer.img");
- CreateCompositeDisk(persistent_composite_disk_config(instance), header_path,
- footer_path, instance.persistent_composite_disk_path());
- } else {
- AggregateImage(persistent_composite_disk_config(instance),
- instance.persistent_composite_disk_path());
- }
- return true;
-}
-
-static void RepackAllBootImages(const CuttlefishConfig* config) {
- CHECK(FileHasContent(FLAGS_boot_image))
- << "File not found: " << FLAGS_boot_image;
-
- CHECK(FileHasContent(FLAGS_vendor_boot_image))
- << "File not found: " << FLAGS_vendor_boot_image;
-
- if (FLAGS_kernel_path.size()) {
- const std::string new_boot_image_path =
- config->AssemblyPath("boot_repacked.img");
- bool success = RepackBootImage(FLAGS_kernel_path, FLAGS_boot_image,
- new_boot_image_path, config->assembly_dir());
- CHECK(success) << "Failed to regenerate the boot image with the new kernel";
- SetCommandLineOptionWithMode("boot_image", new_boot_image_path.c_str(),
- google::FlagSettingMode::SET_FLAGS_DEFAULT);
- }
-
- for (auto instance : config->Instances()) {
- const std::string new_vendor_boot_image_path =
- instance.vendor_boot_image_path();
- const std::vector<std::string> boot_config_vector =
- BootconfigArgsFromConfig(*config, instance);
- if (FLAGS_kernel_path.size() || FLAGS_initramfs_path.size()) {
- // Repack the vendor boot images if kernels and/or ramdisks are passed in.
- if (FLAGS_initramfs_path.size()) {
- bool success = RepackVendorBootImage(
- FLAGS_initramfs_path, FLAGS_vendor_boot_image,
- new_vendor_boot_image_path, config->assembly_dir(),
- instance.instance_dir(), boot_config_vector,
- config->bootconfig_supported());
- CHECK(success) << "Failed to regenerate the vendor boot image with the "
- "new ramdisk";
- } else {
- // This control flow implies a kernel with all configs built in.
- // If it's just the kernel, repack the vendor boot image without a
- // ramdisk.
- bool success = RepackVendorBootImageWithEmptyRamdisk(
- FLAGS_vendor_boot_image, new_vendor_boot_image_path,
- config->assembly_dir(), instance.instance_dir(), boot_config_vector,
- config->bootconfig_supported());
- CHECK(success)
- << "Failed to regenerate the vendor boot image without a ramdisk";
- }
- } else {
- // Repack the vendor boot image to add the instance specific bootconfig
- // parameters
- bool success = RepackVendorBootImage(
- std::string(), FLAGS_vendor_boot_image, new_vendor_boot_image_path,
- config->assembly_dir(), instance.instance_dir(), boot_config_vector,
- config->bootconfig_supported());
- CHECK(success) << "Failed to regenerate the vendor boot image";
- }
- }
-}
-
-void CreateDynamicDiskFiles(const FetcherConfig& fetcher_config,
- const CuttlefishConfig* config) {
- // Create misc if necessary
- CHECK(InitializeMiscImage(FLAGS_misc_image)) << "Failed to create misc image";
-
- // Create data if necessary
- DataImageResult dataImageResult = ApplyDataImagePolicy(*config, FLAGS_data_image);
- CHECK(dataImageResult != DataImageResult::Error) << "Failed to set up userdata";
-
- if (!FileExists(FLAGS_metadata_image)) {
- CreateBlankImage(FLAGS_metadata_image, FLAGS_blank_metadata_image_mb, "none");
- }
-
- // If we are booting a protected VM, for now, assume we want a super minimal
- // environment with no userdata encryption, limited debug, no FRP emulation, a
- // static env for the bootloader, no SD-Card and no resume-on-reboot HAL
- // support. We can also assume that image repacking isn't trusted. Repacking
- // requires resigning the image and keys from an android host aren't trusted.
- if (!FLAGS_protected_vm) {
- RepackAllBootImages(config);
-
- for (const auto& instance : config->Instances()) {
- if (!FileExists(instance.access_kregistry_path())) {
- CreateBlankImage(instance.access_kregistry_path(), 2 /* mb */, "none");
- }
-
- if (!FileExists(instance.pstore_path())) {
- CreateBlankImage(instance.pstore_path(), 2 /* mb */, "none");
- }
-
- if (FLAGS_use_sdcard && !FileExists(instance.sdcard_path())) {
- CreateBlankImage(instance.sdcard_path(),
- FLAGS_blank_sdcard_image_mb, "sdcard");
- }
-
- CHECK(InitBootloaderEnvPartition(*config, instance))
- << "Failed to create bootloader environment partition";
-
- const auto frp = instance.factory_reset_protected_path();
- if (!FileExists(frp)) {
- CreateBlankImage(frp, 1 /* mb */, "none");
- }
-
- const auto bootconfig_path = instance.persistent_bootconfig_path();
- if (!FileExists(bootconfig_path)) {
- CreateBlankImage(bootconfig_path, 1 /* mb */, "none");
- }
-
- auto bootconfig_fd = SharedFD::Open(bootconfig_path, O_RDWR);
- CHECK(bootconfig_fd->IsOpen())
- << "Unable to open bootconfig file: " << bootconfig_fd->StrError();
-
- const std::string bootconfig =
- android::base::Join(BootconfigArgsFromConfig(*config, instance),
- "\n") +
- "\n";
- ssize_t bytesWritten = WriteAll(bootconfig_fd, bootconfig);
- CHECK(bytesWritten == bootconfig.size());
- LOG(DEBUG)
- << "Bootconfig parameters from vendor boot image and config are "
- << ReadFile(bootconfig_path);
-
- const off_t bootconfig_size_bytes =
- AlignToPowerOf2(bootconfig.size(), PARTITION_SIZE_SHIFT);
- CHECK(bootconfig_fd->Truncate(bootconfig_size_bytes) == 0)
- << "`truncate --size=" << bootconfig_size_bytes << " bytes "
- << bootconfig_path << "` failed:" << bootconfig_fd->StrError();
- }
- }
-
- for (const auto& instance : config->Instances()) {
- bool compositeMatchesDiskConfig = DoesCompositeMatchCurrentDiskConfig(
- instance.PerInstancePath("persistent_composite_disk_config.txt"),
- persistent_composite_disk_config(instance));
- bool oldCompositeDisk =
- ShouldCreateCompositeDisk(instance.persistent_composite_disk_path(),
- persistent_composite_disk_config(instance));
-
- if (!compositeMatchesDiskConfig || oldCompositeDisk) {
- CHECK(CreatePersistentCompositeDisk(*config, instance))
- << "Failed to create persistent composite disk";
- }
- }
-
- // libavb expects to be able to read the maximum vbmeta size, so we must
- // provide a partition which matches this or the read will fail
- for (const auto& vbmeta_image : { FLAGS_vbmeta_image, FLAGS_vbmeta_system_image }) {
- if (FileSize(vbmeta_image) != VBMETA_MAX_SIZE) {
- auto fd = SharedFD::Open(vbmeta_image, O_RDWR);
- CHECK(fd->Truncate(VBMETA_MAX_SIZE) == 0)
- << "`truncate --size=" << VBMETA_MAX_SIZE << " " << vbmeta_image << "` "
- << "failed: " << fd->StrError();
- }
- }
-
- CHECK(FileHasContent(FLAGS_bootloader))
- << "File not found: " << FLAGS_bootloader;
-
- if (!FLAGS_esp.empty()) {
- CHECK(FileHasContent(FLAGS_esp))
- << "File not found: " << FLAGS_esp;
- }
-
- if (SuperImageNeedsRebuilding(fetcher_config, *config)) {
- bool success = RebuildSuperImage(fetcher_config, *config, FLAGS_super_image);
- CHECK(success) << "Super image rebuilding requested but could not be completed.";
- }
-
- bool newDataImage = dataImageResult == DataImageResult::FileUpdated;
-
- for (auto instance : config->Instances()) {
- bool compositeMatchesDiskConfig = DoesCompositeMatchCurrentDiskConfig(
- instance.PerInstancePath("os_composite_disk_config.txt"),
- os_composite_disk_config(instance));
- bool oldCompositeDisk = ShouldCreateCompositeDisk(
- instance.os_composite_disk_path(), os_composite_disk_config(instance));
- if (!compositeMatchesDiskConfig || oldCompositeDisk || !FLAGS_resume || newDataImage) {
- if (FLAGS_resume) {
- LOG(INFO) << "Requested to continue an existing session, (the default) "
- << "but the disk files have become out of date. Wiping the "
- << "old session files and starting a new session for device "
- << instance.serial_number();
- }
- CHECK(CreateCompositeDisk(*config, instance))
- << "Failed to create composite disk";
- if (FileExists(instance.access_kregistry_path())) {
- CreateBlankImage(instance.access_kregistry_path(), 2 /* mb */, "none");
- }
- if (FileExists(instance.pstore_path())) {
- CreateBlankImage(instance.pstore_path(), 2 /* mb */, "none");
- }
- }
- }
-
- if (!FLAGS_protected_vm) {
- for (auto instance : config->Instances()) {
- auto overlay_path = instance.PerInstancePath("overlay.img");
- bool missingOverlay = !FileExists(overlay_path);
- bool newOverlay = FileModificationTime(overlay_path) <
- FileModificationTime(instance.os_composite_disk_path());
- if (missingOverlay || !FLAGS_resume || newOverlay) {
- CreateQcowOverlay(config->crosvm_binary(),
- instance.os_composite_disk_path(), overlay_path);
- }
- }
- }
-
- for (auto instance : config->Instances()) {
- // Check that the files exist
- for (const auto& file : instance.virtual_disk_paths()) {
- if (!file.empty()) {
- CHECK(FileHasContent(file)) << "File not found: " << file;
- }
- }
- }
-}
-
-} // namespace cuttlefish
diff --git a/host/commands/assemble_cvd/flags.cc b/host/commands/assemble_cvd/flags.cc
index a1ce5eb6d..27e93e3cf 100644
--- a/host/commands/assemble_cvd/flags.cc
+++ b/host/commands/assemble_cvd/flags.cc
@@ -1,47 +1,50 @@
#include "host/commands/assemble_cvd/flags.h"
-#include <android-base/logging.h>
-#include <android-base/strings.h>
-#include <gflags/gflags.h>
-#include <json/json.h>
-#include <json/writer.h>
+#include <dirent.h>
#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/statvfs.h>
#include <unistd.h>
+#include <fcntl.h>
#include <algorithm>
#include <array>
-#include <fstream>
#include <iostream>
-#include <optional>
-#include <regex>
-#include <set>
-#include <sstream>
+#include <fstream>
+
+#include <android-base/strings.h>
+#include <gflags/gflags.h>
+#include <android-base/logging.h>
#include "common/libs/utils/environment.h"
#include "common/libs/utils/files.h"
-#include "host/commands/assemble_cvd/alloc.h"
-#include "host/commands/assemble_cvd/boot_config.h"
-#include "host/commands/assemble_cvd/clean.h"
-#include "host/commands/assemble_cvd/disk_flags.h"
-#include "host/libs/config/host_tools_version.h"
-#include "host/libs/graphics_detector/graphics_detector.h"
+#include "common/libs/utils/tee_logging.h"
+#include "host/commands/assemble_cvd/boot_image_unpacker.h"
+#include "host/commands/assemble_cvd/data_image.h"
+#include "host/commands/assemble_cvd/image_aggregator.h"
+#include "host/commands/assemble_cvd/assembler_defs.h"
+#include "host/commands/assemble_cvd/super_image_mixer.h"
+#include "host/libs/config/fetcher_config.h"
#include "host/libs/vm_manager/crosvm_manager.h"
#include "host/libs/vm_manager/qemu_manager.h"
#include "host/libs/vm_manager/vm_manager.h"
-using cuttlefish::DefaultHostArtifactsPath;
-using cuttlefish::HostBinaryPath;
-using cuttlefish::StringFromEnv;
-using cuttlefish::vm_manager::CrosvmManager;
-using google::FlagSettingMode::SET_FLAGS_DEFAULT;
+// Taken from external/avb/libavb/avb_slot_verify.c; this define is not in the headers
+#define VBMETA_MAX_SIZE 65536ul
-DEFINE_string(config, "phone",
- "Config preset name. Will automatically set flag fields "
- "using the values from this file of presets. See "
- "device/google/cuttlefish/shared/config/config_*.json "
- "for possible values.");
+using vsoc::ForCurrentInstance;
+using vsoc::RandomSerialNumber;
+using cvd::AssemblerExitCodes;
+DEFINE_string(cache_image, "", "Location of the cache partition image.");
+DEFINE_string(metadata_image, "", "Location of the metadata partition image "
+ "to be generated.");
+DEFINE_int32(blank_metadata_image_mb, 16,
+ "The size of the blank metadata image to generate, MB.");
+DEFINE_int32(blank_sdcard_image_mb, 2048,
+ "The size of the blank sdcard image to generate, MB.");
DEFINE_int32(cpus, 2, "Virtual CPU count.");
+DEFINE_string(data_image, "", "Location of the data partition image.");
DEFINE_string(data_policy, "use_existing", "How to handle userdata partition."
" Either 'use_existing', 'create_if_missing', 'resize_up_to', or "
"'always_create'.");
@@ -49,34 +52,64 @@ DEFINE_int32(blank_data_image_mb, 0,
"The size of the blank data image to generate, MB.");
DEFINE_string(blank_data_image_fmt, "f2fs",
"The fs format for the blank data image. Used with mkfs.");
-DEFINE_int32(gdb_port, 0,
- "Port number to spawn kernel gdb on e.g. -gdb_port=1234. The"
- "kernel must have been built with CONFIG_RANDOMIZE_BASE "
- "disabled.");
-
-DEFINE_int32(x_res, 0, "Width of the screen in pixels");
-DEFINE_int32(y_res, 0, "Height of the screen in pixels");
-DEFINE_int32(dpi, 0, "Pixels per inch for the screen");
+DEFINE_string(qemu_gdb, "",
+ "Debug flag to pass to qemu. e.g. -qemu_gdb=tcp::1234");
+
+DEFINE_int32(x_res, 720, "Width of the screen in pixels");
+DEFINE_int32(y_res, 1280, "Height of the screen in pixels");
+DEFINE_int32(dpi, 160, "Pixels per inch for the screen");
DEFINE_int32(refresh_rate_hz, 60, "Screen refresh rate in Hertz");
DEFINE_string(kernel_path, "",
"Path to the kernel. Overrides the one from the boot image");
DEFINE_string(initramfs_path, "", "Path to the initramfs");
+DEFINE_bool(decompress_kernel, false,
+ "Whether to decompress the kernel image.");
DEFINE_string(extra_kernel_cmdline, "",
"Additional flags to put on the kernel command line");
+DEFINE_int32(loop_max_part, 7, "Maximum number of loop partitions");
DEFINE_bool(guest_enforce_security, true,
"Whether to run in enforcing mode (non permissive).");
DEFINE_bool(guest_audit_security, true,
"Whether to log security audits.");
-DEFINE_int32(memory_mb, 0, "Total amount of memory available for guest, MB.");
-DEFINE_string(serial_number, cuttlefish::ForCurrentInstance("CUTTLEFISHCVD"),
+DEFINE_bool(guest_force_normal_boot, true,
+ "Whether to force the boot sequence to skip recovery.");
+DEFINE_string(boot_image, "",
+ "Location of cuttlefish boot image. If empty it is assumed to be "
+ "boot.img in the directory specified by -system_image_dir.");
+DEFINE_string(vendor_boot_image, "",
+ "Location of cuttlefish vendor boot image. If empty it is assumed to "
+ "be vendor_boot.img in the directory specified by -system_image_dir.");
+DEFINE_string(vbmeta_image, "",
+ "Location of cuttlefish vbmeta image. If empty it is assumed to "
+ "be vbmeta.img in the directory specified by -system_image_dir.");
+DEFINE_string(vbmeta_system_image, "",
+ "Location of cuttlefish vbmeta_system image. If empty it is assumed to "
+ "be vbmeta_system.img in the directory specified by -system_image_dir.");
+DEFINE_int32(memory_mb, 2048,
+ "Total amount of memory available for guest, MB.");
+DEFINE_string(serial_number, ForCurrentInstance("CUTTLEFISHCVD"),
"Serial number to use for the device");
DEFINE_bool(use_random_serial, false,
"Whether to use random serial for the device.");
-DEFINE_string(vm_manager, "",
- "What virtual machine manager to use, one of {qemu_cli, crosvm}");
-DEFINE_string(gpu_mode, cuttlefish::kGpuModeAuto,
- "What gpu configuration to use, one of {auto, drm_virgl, "
- "gfxstream, guest_swiftshader}");
+DEFINE_string(assembly_dir,
+ cvd::StringFromEnv("HOME", ".") + "/cuttlefish_assembly",
+ "A directory to put generated files common between instances");
+DEFINE_string(instance_dir,
+ cvd::StringFromEnv("HOME", ".") + "/cuttlefish_runtime",
+ "A directory to put all instance specific files");
+DEFINE_string(
+ vm_manager, vm_manager::CrosvmManager::name(),
+ "What virtual machine manager to use, one of {qemu_cli, crosvm}");
+DEFINE_string(
+ gpu_mode, vsoc::kGpuModeGuestSwiftshader,
+ "What gpu configuration to use, one of {guest_swiftshader, drm_virgl}");
+
+DEFINE_string(system_image_dir, vsoc::DefaultGuestImagePath(""),
+ "Location of the system partition images.");
+DEFINE_string(super_image, "", "Location of the super partition image.");
+DEFINE_string(misc_image, "",
+ "Location of the misc partition image. If the image does not "
+ "exist, a blank new misc partition image is created.");
DEFINE_bool(deprecated_boot_completed, false, "Log boot completed message to"
" host kernel. This is only used during transition of our clients."
@@ -85,116 +118,29 @@ DEFINE_bool(start_vnc_server, false, "Whether to start the vnc server process. "
"The VNC server runs at port 6443 + i for "
"the vsoc-i user or CUTTLEFISH_INSTANCE=i, "
"starting from 1.");
-DEFINE_bool(use_allocd, false,
- "Acquire static resources from the resource allocator daemon.");
-DEFINE_bool(enable_minimal_mode, false,
- "Only enable the minimum features to boot a cuttlefish device and "
- "support minimal UI interactions.\nNote: Currently only supports "
- "handheld/phone targets");
-DEFINE_bool(pause_in_bootloader, false,
- "Stop the bootflow in u-boot. You can continue the boot by connecting "
- "to the device console and typing in \"boot\".");
-DEFINE_bool(enable_host_bluetooth, true,
- "Enable the root-canal which is Bluetooth emulator in the host.");
-
-DEFINE_string(bluetooth_controller_properties_file,
- "etc/rootcanal/data/controller_properties.json",
- "The configuartion file path for root-canal which is a Bluetooth "
- "emulator.");
-DEFINE_string(
- bluetooth_default_commands_file, "etc/rootcanal/data/default_commands",
- "The default commands which root-canal executes when it launches.");
-
-/**
- *
- * crosvm sandbox feature requires /var/empty and seccomp directory
- *
- * --enable-sandbox: will enforce the sandbox feature
- * failing to meet the requirements result in assembly_cvd termination
- *
- * --enable-sandbox=no, etc: will disable sandbox
- *
- * no option given: it is enabled if /var/empty exists and an empty directory
- * or if it does not exist and can be created
- *
- * if seccomp dir doesn't exist, assembly_cvd will terminate
- *
- * See SetDefaultFlagsForCrosvm()
- *
- */
-DEFINE_bool(enable_sandbox,
- false,
- "Enable crosvm sandbox. Use this when you are sure about what you are doing.");
-
-static const std::string kSeccompDir =
- std::string("usr/share/crosvm/") + cuttlefish::HostArchStr() + "-linux-gnu/seccomp";
-DEFINE_string(seccomp_policy_dir, DefaultHostArtifactsPath(kSeccompDir),
- "With sandbox'ed crosvm, overrieds the security comp policy directory");
-
-DEFINE_bool(start_webrtc, false, "Whether to start the webrtc process.");
+
+DEFINE_bool(start_webrtc, false, "[Experimental] Whether to start the webrtc process.");
DEFINE_string(
- webrtc_assets_dir, DefaultHostArtifactsPath("usr/share/webrtc/assets"),
+ webrtc_assets_dir,
+ vsoc::DefaultHostArtifactsPath("usr/share/webrtc/assets"),
"[Experimental] Path to WebRTC webpage assets.");
DEFINE_string(
- webrtc_certs_dir, DefaultHostArtifactsPath("usr/share/webrtc/certs"),
+ webrtc_certs_dir,
+ vsoc::DefaultHostArtifactsPath("usr/share/webrtc/certs"),
"[Experimental] Path to WebRTC certificates directory.");
DEFINE_string(
webrtc_public_ip,
- "0.0.0.0",
- "[Deprecated] Ignored, webrtc can figure out its IP address");
+ "127.0.0.1",
+ "[Experimental] Public IPv4 address of your server, a.b.c.d format");
DEFINE_bool(
webrtc_enable_adb_websocket,
false,
"[Experimental] If enabled, exposes local adb service through a websocket.");
-DEFINE_bool(
- start_webrtc_sig_server, false,
- "Whether to start the webrtc signaling server. This option only applies to "
- "the first instance, if multiple instances are launched they'll share the "
- "same signaling server, which is owned by the first one.");
-
-DEFINE_string(webrtc_sig_server_addr, "0.0.0.0",
- "The address of the webrtc signaling server.");
-
-DEFINE_int32(
- webrtc_sig_server_port, 443,
- "The port of the signaling server if started outside of this launch. If "
- "-start_webrtc_sig_server is given it will choose 8443+instance_num1-1 and "
- "this parameter is ignored.");
-
-// TODO (jemoreira): We need a much bigger range to reliably support several
-// simultaneous connections.
-DEFINE_string(tcp_port_range, "15550:15558",
- "The minimum and maximum TCP port numbers to allocate for ICE "
- "candidates as 'min:max'. To use any port just specify '0:0'");
-
-DEFINE_string(udp_port_range, "15550:15558",
- "The minimum and maximum UDP port numbers to allocate for ICE "
- "candidates as 'min:max'. To use any port just specify '0:0'");
-
-DEFINE_string(webrtc_sig_server_path, "/register_device",
- "The path section of the URL where the device should be "
- "registered with the signaling server.");
-
-DEFINE_bool(verify_sig_server_certificate, false,
- "Whether to verify the signaling server's certificate with a "
- "trusted signing authority (Disallow self signed certificates).");
-
-DEFINE_string(sig_server_headers_file, "",
- "Path to a file containing HTTP headers to be included in the "
- "connection to the signaling server. Each header should be on a "
- "line by itself in the form <name>: <value>");
-
-DEFINE_string(
- webrtc_device_id, "cvd-{num}",
- "The for the device to register with the signaling server. Every "
- "appearance of the substring '{num}' in the device id will be substituted "
- "with the instance number to support multiple instances");
-
DEFINE_string(adb_mode, "vsock_half_tunnel",
"Mode for ADB connection."
"'vsock_tunnel' for a TCP connection tunneled through vsock, "
@@ -202,11 +148,11 @@ DEFINE_string(adb_mode, "vsock_half_tunnel",
"vsock, 'vsock_half_tunnel' for a TCP connection forwarded to "
"the guest ADB server, or a comma separated list of types as in "
"'native_vsock,vsock_half_tunnel'");
-DEFINE_bool(run_adb_connector, !cuttlefish::IsRunningInContainer(),
+DEFINE_bool(run_adb_connector, true,
"Maintain adb connection by sending 'adb connect' commands to the "
"server. Only relevant with -adb_mode=tunnel or vsock_tunnel");
-DEFINE_string(uuid, cuttlefish::ForCurrentInstance(cuttlefish::kDefaultUuidPrefix),
+DEFINE_string(uuid, vsoc::ForCurrentInstance(vsoc::kDefaultUuidPrefix),
"UUID to use for the device. Random if not specified");
DEFINE_bool(daemon, false,
"Run cuttlefish in background, the launcher exits on boot "
@@ -217,113 +163,87 @@ DEFINE_string(device_title, "", "Human readable name for the instance, "
DEFINE_string(setupwizard_mode, "DISABLED",
"One of DISABLED,OPTIONAL,REQUIRED");
-DEFINE_string(qemu_binary_dir, "/usr/bin",
- "Path to the directory containing the qemu binary to use");
-DEFINE_string(crosvm_binary, HostBinaryPath("crosvm"),
+DEFINE_string(qemu_binary,
+ "/usr/bin/qemu-system-x86_64",
+ "The qemu binary to use");
+DEFINE_string(crosvm_binary,
+ vsoc::DefaultHostArtifactsPath("bin/crosvm"),
"The Crosvm binary to use");
-DEFINE_string(tpm_device, "", "A host TPM device to pass through commands to.");
DEFINE_bool(restart_subprocesses, true, "Restart any crashed host process");
+DEFINE_string(logcat_mode, "", "How to send android's log messages from "
+ "guest to host. One of [serial, vsock]");
+DEFINE_bool(enable_tombstone_receiver, true, "Enables the tombstone logger on "
+ "both the guest and the host");
DEFINE_bool(enable_vehicle_hal_grpc_server, true, "Enables the vehicle HAL "
"emulation gRPC server on the host");
-DEFINE_string(custom_action_config, "",
- "Path to a custom action config JSON. Defaults to the file provided by "
- "build variable CVD_CUSTOM_ACTION_CONFIG. If this build variable "
- "is empty then the custom action config will be empty as well.");
-DEFINE_string(custom_actions, "",
- "Serialized JSON of an array of custom action objects (in the "
- "same format as custom action config JSON files). For use "
- "within --config preset config files; prefer "
- "--custom_action_config to specify a custom config file on the "
- "command line. Actions in this flag are combined with actions "
- "in --custom_action_config.");
+DEFINE_bool(use_bootloader, false, "Boots the device using a bootloader");
DEFINE_string(bootloader, "", "Bootloader binary path");
DEFINE_string(boot_slot, "", "Force booting into the given slot. If empty, "
"the slot will be chosen based on the misc partition if using a "
"bootloader. It will default to 'a' if empty and not using a "
"bootloader.");
DEFINE_int32(num_instances, 1, "Number of Android guests to launch");
-DEFINE_string(report_anonymous_usage_stats, "", "Report anonymous usage "
- "statistics for metrics collection and analysis.");
-DEFINE_string(ril_dns, "8.8.8.8", "DNS address of mobile network (RIL)");
-DEFINE_bool(kgdb, false, "Configure the virtual device for debugging the kernel "
- "with kgdb/kdb. The kernel must have been built with "
- "kgdb support, and serial console must be enabled.");
-
-DEFINE_bool(start_gnss_proxy, false, "Whether to start the gnss proxy.");
-
-DEFINE_string(gnss_file_path, "",
- "Local gnss file path for the gnss proxy");
-
-// by default, this modem-simulator is disabled
-DEFINE_bool(enable_modem_simulator, true,
- "Enable the modem simulator to process RILD AT commands");
-// modem_simulator_sim_type=2 for test CtsCarrierApiTestCases
-DEFINE_int32(modem_simulator_sim_type, 1,
- "Sim type: 1 for normal, 2 for CtsCarrierApiTestCases");
-
-DEFINE_bool(console, false, "Enable the serial console");
-
-DEFINE_bool(vhost_net, false, "Enable vhost acceleration of networking");
-
-DEFINE_bool(record_screen, false, "Enable screen recording. "
- "Requires --start_webrtc");
-
-DEFINE_bool(ethernet, false, "Enable Ethernet network interface");
-
-DEFINE_bool(smt, false, "Enable simultaneous multithreading (SMT/HT)");
+DEFINE_bool(resume, true, "Resume using the disk from the last session, if "
+ "possible. i.e., if --noresume is passed, the disk "
+ "will be reset to the state it was initially launched "
+ "in. This flag is ignored if the underlying partition "
+ "images have been updated since the first launch.");
-DEFINE_int32(vsock_guest_cid,
- cuttlefish::GetDefaultVsockCid(),
- "vsock_guest_cid is used to determine the guest vsock cid as well as all the ports"
- "of all vsock servers such as tombstone or modem simulator(s)."
- "The vsock ports and guest vsock cid are a function of vsock_guest_cid and instance number."
- "An instance number of i th instance is determined by --num_instances=N and --base_instance_num=B"
- "The instance number of i th instance is B + i where i in [0, N-1] and B >= 1."
- "See --num_instances, and --base_instance_num for more information"
- "If --vsock_guest_cid=C is given and C >= 3, the guest vsock cid is C + i. Otherwise,"
- "the guest vsock cid is 2 + instance number, which is 2 + (B + i)."
- "If --vsock_guest_cid is not given, each vsock server port number for i th instance is"
- "base + instance number - 1. vsock_guest_cid is by default B + i + 2."
- "Thus, by default, each port is base + vsock_guest_cid - 3."
- "The same formula holds when --vsock_guest_cid=C is given, for algorithm's sake."
- "Each vsock server port number is base + C - 3.");
-
-DEFINE_string(secure_hals, "keymint,gatekeeper",
- "Which HALs to use enable host security features for. Supports "
- "keymint and gatekeeper at the moment.");
-
-DEFINE_bool(use_sdcard, true, "Create blank SD-Card image and expose to guest");
-
-DEFINE_bool(protected_vm, false, "Boot in Protected VM mode");
+namespace {
-DEFINE_bool(enable_audio, cuttlefish::HostArch() != cuttlefish::Arch::Arm64,
- "Whether to play or capture audio");
+const std::string kKernelDefaultPath = "kernel";
+const std::string kInitramfsImg = "initramfs.img";
+const std::string kRamdiskConcatExt = ".concat";
-DECLARE_string(assembly_dir);
-DECLARE_string(boot_image);
-DECLARE_string(system_image_dir);
+bool ResolveInstanceFiles() {
+ if (FLAGS_system_image_dir.empty()) {
+ LOG(ERROR) << "--system_image_dir must be specified.";
+ return false;
+ }
-namespace cuttlefish {
-using vm_manager::QemuManager;
-using vm_manager::GetVmManager;
+ // If user did not specify location of either of these files, expect them to
+ // be placed in --system_image_dir location.
+ std::string default_boot_image = FLAGS_system_image_dir + "/boot.img";
+ SetCommandLineOptionWithMode("boot_image", default_boot_image.c_str(),
+ google::FlagSettingMode::SET_FLAGS_DEFAULT);
+ std::string default_cache_image = FLAGS_system_image_dir + "/cache.img";
+ SetCommandLineOptionWithMode("cache_image", default_cache_image.c_str(),
+ google::FlagSettingMode::SET_FLAGS_DEFAULT);
+ std::string default_data_image = FLAGS_system_image_dir + "/userdata.img";
+ SetCommandLineOptionWithMode("data_image", default_data_image.c_str(),
+ google::FlagSettingMode::SET_FLAGS_DEFAULT);
+ std::string default_metadata_image = FLAGS_system_image_dir + "/metadata.img";
+ SetCommandLineOptionWithMode("metadata_image", default_metadata_image.c_str(),
+ google::FlagSettingMode::SET_FLAGS_DEFAULT);
+ std::string default_super_image = FLAGS_system_image_dir + "/super.img";
+ SetCommandLineOptionWithMode("super_image", default_super_image.c_str(),
+ google::FlagSettingMode::SET_FLAGS_DEFAULT);
+ std::string default_misc_image = FLAGS_system_image_dir + "/misc.img";
+ SetCommandLineOptionWithMode("misc_image", default_misc_image.c_str(),
+ google::FlagSettingMode::SET_FLAGS_DEFAULT);
+ std::string default_vendor_boot_image = FLAGS_system_image_dir
+ + "/vendor_boot.img";
+ SetCommandLineOptionWithMode("vendor_boot_image",
+ default_vendor_boot_image.c_str(),
+ google::FlagSettingMode::SET_FLAGS_DEFAULT);
+ std::string default_vbmeta_image = FLAGS_system_image_dir + "/vbmeta.img";
+ SetCommandLineOptionWithMode("vbmeta_image", default_vbmeta_image.c_str(),
+ google::FlagSettingMode::SET_FLAGS_DEFAULT);
+ std::string default_vbmeta_system_image = FLAGS_system_image_dir
+ + "/vbmeta_system.img";
+ SetCommandLineOptionWithMode("vbmeta_system_image",
+ default_vbmeta_system_image.c_str(),
+ google::FlagSettingMode::SET_FLAGS_DEFAULT);
-namespace {
+ return true;
+}
-bool IsFlagSet(const std::string& flag) {
- return !gflags::GetCommandLineFlagInfoOrDie(flag.c_str()).is_default;
+std::string GetCuttlefishEnvPath() {
+ return cvd::StringFromEnv("HOME", ".") + "/.cuttlefish.sh";
}
-std::pair<uint16_t, uint16_t> ParsePortRange(const std::string& flag) {
- static const std::regex rgx("[0-9]+:[0-9]+");
- CHECK(std::regex_match(flag, rgx))
- << "Port range flag has invalid value: " << flag;
- std::pair<uint16_t, uint16_t> port_range;
- std::stringstream ss(flag);
- char c;
- ss >> port_range.first;
- ss.read(&c, 1);
- ss >> port_range.second;
- return port_range;
+std::string GetLegacyConfigFilePath(const vsoc::CuttlefishConfig& config) {
+ return config.ForDefaultInstance().PerInstancePath("cuttlefish_config.json");
}
int NumStreamers() {
@@ -337,385 +257,186 @@ std::string StrForInstance(const std::string& prefix, int num) {
return stream.str();
}
-#ifdef __ANDROID__
-void ReadKernelConfig(KernelConfig* kernel_config) {
- // QEMU isn't on Android, so always follow host arch
- kernel_config->target_arch = HostArch();
- kernel_config->bootconfig_supported = true;
-}
-#else
-void ReadKernelConfig(KernelConfig* kernel_config) {
- // extract-ikconfig can be called directly on the boot image since it looks
- // for the ikconfig header in the image before extracting the config list.
- // This code is liable to break if the boot image ever includes the
- // ikconfig header outside the kernel.
- const std::string kernel_image_path =
- FLAGS_kernel_path.size() ? FLAGS_kernel_path : FLAGS_boot_image;
-
- Command ikconfig_cmd(HostBinaryPath("extract-ikconfig"));
- ikconfig_cmd.AddParameter(kernel_image_path);
-
- std::string current_path = StringFromEnv("PATH", "");
- std::string bin_folder = DefaultHostArtifactsPath("bin");
- ikconfig_cmd.SetEnvironment({"PATH=" + current_path + ":" + bin_folder});
-
- std::string ikconfig_path =
- StringFromEnv("TEMP", "/tmp") + "/ikconfig.XXXXXX";
- auto ikconfig_fd = SharedFD::Mkstemp(&ikconfig_path);
- CHECK(ikconfig_fd->IsOpen())
- << "Unable to create ikconfig file: " << ikconfig_fd->StrError();
- ikconfig_cmd.RedirectStdIO(Subprocess::StdIOChannel::kStdOut, ikconfig_fd);
-
- auto ikconfig_proc = ikconfig_cmd.Start();
- CHECK(ikconfig_proc.Started() && ikconfig_proc.Wait() == 0)
- << "Failed to extract ikconfig from " << kernel_image_path;
-
- std::string config = ReadFile(ikconfig_path);
-
- if (config.find("\nCONFIG_ARM=y") != std::string::npos) {
- kernel_config->target_arch = Arch::Arm;
- } else if (config.find("\nCONFIG_ARM64=y") != std::string::npos) {
- kernel_config->target_arch = Arch::Arm64;
- } else if (config.find("\nCONFIG_X86_64=y") != std::string::npos) {
- kernel_config->target_arch = Arch::X86_64;
- } else if (config.find("\nCONFIG_X86=y") != std::string::npos) {
- kernel_config->target_arch = Arch::X86;
- } else {
- LOG(FATAL) << "Unknown target architecture";
- }
- kernel_config->bootconfig_supported =
- config.find("\nCONFIG_BOOT_CONFIG=y") != std::string::npos;
-
- unlink(ikconfig_path.c_str());
-}
-#endif // #ifdef __ANDROID__
-
-} // namespace
-
-CuttlefishConfig InitializeCuttlefishConfiguration(
- const std::string& instance_dir, int modem_simulator_count,
- KernelConfig kernel_config) {
+// Initializes the config object and saves it to file. It doesn't return it, all
+// further uses of the config should happen through the singleton
+vsoc::CuttlefishConfig InitializeCuttlefishConfiguration(
+ const cvd::BootImageUnpacker& boot_image_unpacker,
+ const cvd::FetcherConfig& fetcher_config) {
// At most one streamer can be started.
CHECK(NumStreamers() <= 1);
- CuttlefishConfig tmp_config_obj;
+ vsoc::CuttlefishConfig tmp_config_obj;
tmp_config_obj.set_assembly_dir(FLAGS_assembly_dir);
- tmp_config_obj.set_target_arch(kernel_config.target_arch);
- tmp_config_obj.set_bootconfig_supported(kernel_config.bootconfig_supported);
- auto vmm = GetVmManager(FLAGS_vm_manager, kernel_config.target_arch);
- if (!vmm) {
+ if (!vm_manager::VmManager::IsValidName(FLAGS_vm_manager)) {
+ LOG(FATAL) << "Invalid vm_manager: " << FLAGS_vm_manager;
+ }
+ if (!vm_manager::VmManager::IsValidName(FLAGS_vm_manager)) {
LOG(FATAL) << "Invalid vm_manager: " << FLAGS_vm_manager;
}
tmp_config_obj.set_vm_manager(FLAGS_vm_manager);
-
- const GraphicsAvailability graphics_availability =
- GetGraphicsAvailabilityWithSubprocessCheck();
-
- LOG(VERBOSE) << graphics_availability;
-
tmp_config_obj.set_gpu_mode(FLAGS_gpu_mode);
-
- if (tmp_config_obj.gpu_mode() != kGpuModeAuto &&
- tmp_config_obj.gpu_mode() != kGpuModeDrmVirgl &&
- tmp_config_obj.gpu_mode() != kGpuModeGfxStream &&
- tmp_config_obj.gpu_mode() != kGpuModeGuestSwiftshader) {
- LOG(FATAL) << "Invalid gpu_mode: " << FLAGS_gpu_mode;
- }
- if (tmp_config_obj.gpu_mode() == kGpuModeAuto) {
- if (ShouldEnableAcceleratedRendering(graphics_availability)) {
- LOG(INFO) << "GPU auto mode: detected prerequisites for accelerated "
- "rendering support.";
- if (FLAGS_vm_manager == QemuManager::name()) {
- LOG(INFO) << "Enabling --gpu_mode=drm_virgl.";
- tmp_config_obj.set_gpu_mode(kGpuModeDrmVirgl);
- } else {
- LOG(INFO) << "Enabling --gpu_mode=gfxstream.";
- tmp_config_obj.set_gpu_mode(kGpuModeGfxStream);
- }
- } else {
- LOG(INFO) << "GPU auto mode: did not detect prerequisites for "
- "accelerated rendering support, enabling "
- "--gpu_mode=guest_swiftshader.";
- tmp_config_obj.set_gpu_mode(kGpuModeGuestSwiftshader);
- }
- } else if (tmp_config_obj.gpu_mode() == kGpuModeGfxStream ||
- tmp_config_obj.gpu_mode() == kGpuModeDrmVirgl) {
- if (!ShouldEnableAcceleratedRendering(graphics_availability)) {
- LOG(ERROR) << "--gpu_mode="
- << tmp_config_obj.gpu_mode()
- << " was requested but the prerequisites for accelerated "
- "rendering were not detected so the device may not "
- "function correctly. Please consider switching to "
- "--gpu_mode=auto or --gpu_mode=guest_swiftshader.";
- }
- }
- // Sepolicy rules need to be updated to support gpu mode. Temporarily disable
- // auto-enabling sandbox when gpu is enabled (b/152323505).
- if (tmp_config_obj.gpu_mode() != kGpuModeGuestSwiftshader) {
- SetCommandLineOptionWithMode("enable_sandbox", "false", SET_FLAGS_DEFAULT);
- }
-
- if (vmm->ConfigureGpuMode(tmp_config_obj.gpu_mode()).empty()) {
+ if (vm_manager::VmManager::ConfigureGpuMode(tmp_config_obj.vm_manager(),
+ tmp_config_obj.gpu_mode()).empty()) {
LOG(FATAL) << "Invalid gpu_mode=" << FLAGS_gpu_mode <<
" does not work with vm_manager=" << FLAGS_vm_manager;
}
- CHECK(!FLAGS_smt || FLAGS_cpus % 2 == 0)
- << "CPUs must be a multiple of 2 in SMT mode";
tmp_config_obj.set_cpus(FLAGS_cpus);
- tmp_config_obj.set_smt(FLAGS_smt);
-
tmp_config_obj.set_memory_mb(FLAGS_memory_mb);
- tmp_config_obj.set_setupwizard_mode(FLAGS_setupwizard_mode);
-
- std::vector<cuttlefish::CuttlefishConfig::DisplayConfig> display_configs = {{
- .width = FLAGS_x_res,
- .height = FLAGS_y_res,
- }};
- tmp_config_obj.set_display_configs(display_configs);
tmp_config_obj.set_dpi(FLAGS_dpi);
+ tmp_config_obj.set_setupwizard_mode(FLAGS_setupwizard_mode);
+ tmp_config_obj.set_x_res(FLAGS_x_res);
+ tmp_config_obj.set_y_res(FLAGS_y_res);
tmp_config_obj.set_refresh_rate_hz(FLAGS_refresh_rate_hz);
-
- auto secure_hals = android::base::Split(FLAGS_secure_hals, ",");
- tmp_config_obj.set_secure_hals(
- std::set<std::string>(secure_hals.begin(), secure_hals.end()));
-
- tmp_config_obj.set_gdb_port(FLAGS_gdb_port);
-
+ tmp_config_obj.set_gdb_flag(FLAGS_qemu_gdb);
std::vector<std::string> adb = android::base::Split(FLAGS_adb_mode, ",");
tmp_config_obj.set_adb_mode(std::set<std::string>(adb.begin(), adb.end()));
+ std::string discovered_kernel = fetcher_config.FindCvdFileWithSuffix(kKernelDefaultPath);
+ std::string foreign_kernel = FLAGS_kernel_path.size() ? FLAGS_kernel_path : discovered_kernel;
+ if (foreign_kernel.size()) {
+ tmp_config_obj.set_kernel_image_path(foreign_kernel);
+ tmp_config_obj.set_use_unpacked_kernel(false);
+ } else {
+ tmp_config_obj.set_kernel_image_path(
+ tmp_config_obj.AssemblyPath(kKernelDefaultPath.c_str()));
+ tmp_config_obj.set_use_unpacked_kernel(true);
+ }
+ tmp_config_obj.set_decompress_kernel(FLAGS_decompress_kernel);
+ if (tmp_config_obj.decompress_kernel()) {
+ tmp_config_obj.set_decompressed_kernel_image_path(
+ tmp_config_obj.AssemblyPath("vmlinux"));
+ }
+
+ auto ramdisk_path = tmp_config_obj.AssemblyPath("ramdisk.img");
+ auto vendor_ramdisk_path = tmp_config_obj.AssemblyPath("vendor_ramdisk.img");
+ if (!boot_image_unpacker.HasRamdiskImage()) {
+ LOG(FATAL) << "A ramdisk is required, but the boot image did not have one.";
+ }
+
+ tmp_config_obj.set_boot_image_kernel_cmdline(boot_image_unpacker.kernel_cmdline());
+ tmp_config_obj.set_loop_max_part(FLAGS_loop_max_part);
tmp_config_obj.set_guest_enforce_security(FLAGS_guest_enforce_security);
tmp_config_obj.set_guest_audit_security(FLAGS_guest_audit_security);
+ tmp_config_obj.set_guest_force_normal_boot(FLAGS_guest_force_normal_boot);
tmp_config_obj.set_extra_kernel_cmdline(FLAGS_extra_kernel_cmdline);
- if (FLAGS_console) {
- SetCommandLineOptionWithMode("enable_sandbox", "false", SET_FLAGS_DEFAULT);
+ tmp_config_obj.set_ramdisk_image_path(ramdisk_path);
+ tmp_config_obj.set_vendor_ramdisk_image_path(vendor_ramdisk_path);
+
+ std::string discovered_ramdisk = fetcher_config.FindCvdFileWithSuffix(kInitramfsImg);
+ std::string foreign_ramdisk = FLAGS_initramfs_path.size () ? FLAGS_initramfs_path : discovered_ramdisk;
+ if (foreign_kernel.size() && !foreign_ramdisk.size()) {
+ // If there's a kernel that's passed in without an initramfs, that implies
+ // user error or a kernel built with no modules. In either case, let's
+ // choose to avoid loading the modules from the vendor ramdisk which are
+ // built for the default cf kernel. Once boot occurs, user error will
+ // become obvious.
+ tmp_config_obj.set_final_ramdisk_path(ramdisk_path);
+ } else {
+ tmp_config_obj.set_final_ramdisk_path(ramdisk_path + kRamdiskConcatExt);
+ if(foreign_ramdisk.size()) {
+ tmp_config_obj.set_initramfs_path(foreign_ramdisk);
+ }
}
- tmp_config_obj.set_console(FLAGS_console);
- tmp_config_obj.set_kgdb(FLAGS_console && FLAGS_kgdb);
-
- tmp_config_obj.set_host_tools_version(HostToolsCrc());
-
tmp_config_obj.set_deprecated_boot_completed(FLAGS_deprecated_boot_completed);
+ tmp_config_obj.set_logcat_receiver_binary(
+ vsoc::DefaultHostArtifactsPath("bin/logcat_receiver"));
+ tmp_config_obj.set_config_server_binary(
+ vsoc::DefaultHostArtifactsPath("bin/config_server"));
- tmp_config_obj.set_qemu_binary_dir(FLAGS_qemu_binary_dir);
+ tmp_config_obj.set_qemu_binary(FLAGS_qemu_binary);
tmp_config_obj.set_crosvm_binary(FLAGS_crosvm_binary);
- tmp_config_obj.set_tpm_device(FLAGS_tpm_device);
+ tmp_config_obj.set_console_forwarder_binary(
+ vsoc::DefaultHostArtifactsPath("bin/console_forwarder"));
+ tmp_config_obj.set_kernel_log_monitor_binary(
+ vsoc::DefaultHostArtifactsPath("bin/kernel_log_monitor"));
tmp_config_obj.set_enable_vnc_server(FLAGS_start_vnc_server);
-
- tmp_config_obj.set_seccomp_policy_dir(FLAGS_seccomp_policy_dir);
+ tmp_config_obj.set_vnc_server_binary(
+ vsoc::DefaultHostArtifactsPath("bin/vnc_server"));
tmp_config_obj.set_enable_webrtc(FLAGS_start_webrtc);
+ tmp_config_obj.set_webrtc_binary(
+ vsoc::DefaultHostArtifactsPath("bin/webRTC"));
tmp_config_obj.set_webrtc_assets_dir(FLAGS_webrtc_assets_dir);
+ tmp_config_obj.set_webrtc_public_ip(FLAGS_webrtc_public_ip);
tmp_config_obj.set_webrtc_certs_dir(FLAGS_webrtc_certs_dir);
- // Note: This will be overridden if the sig server is started by us
- tmp_config_obj.set_sig_server_port(FLAGS_webrtc_sig_server_port);
- tmp_config_obj.set_sig_server_address(FLAGS_webrtc_sig_server_addr);
- tmp_config_obj.set_sig_server_path(FLAGS_webrtc_sig_server_path);
- tmp_config_obj.set_sig_server_strict(FLAGS_verify_sig_server_certificate);
- tmp_config_obj.set_sig_server_headers_path(FLAGS_sig_server_headers_file);
-
- auto tcp_range = ParsePortRange(FLAGS_tcp_port_range);
- tmp_config_obj.set_webrtc_tcp_port_range(tcp_range);
- auto udp_range = ParsePortRange(FLAGS_udp_port_range);
- tmp_config_obj.set_webrtc_udp_port_range(udp_range);
-
- tmp_config_obj.set_enable_modem_simulator(FLAGS_enable_modem_simulator &&
- !FLAGS_enable_minimal_mode);
- tmp_config_obj.set_modem_simulator_instance_number(modem_simulator_count);
- tmp_config_obj.set_modem_simulator_sim_type(FLAGS_modem_simulator_sim_type);
tmp_config_obj.set_webrtc_enable_adb_websocket(
FLAGS_webrtc_enable_adb_websocket);
tmp_config_obj.set_restart_subprocesses(FLAGS_restart_subprocesses);
tmp_config_obj.set_run_adb_connector(FLAGS_run_adb_connector);
+ tmp_config_obj.set_adb_connector_binary(
+ vsoc::DefaultHostArtifactsPath("bin/adb_connector"));
+ tmp_config_obj.set_socket_vsock_proxy_binary(
+ vsoc::DefaultHostArtifactsPath("bin/socket_vsock_proxy"));
tmp_config_obj.set_run_as_daemon(FLAGS_daemon);
tmp_config_obj.set_data_policy(FLAGS_data_policy);
tmp_config_obj.set_blank_data_image_mb(FLAGS_blank_data_image_mb);
tmp_config_obj.set_blank_data_image_fmt(FLAGS_blank_data_image_fmt);
- tmp_config_obj.set_enable_gnss_grpc_proxy(FLAGS_start_gnss_proxy);
+ tmp_config_obj.set_logcat_mode(FLAGS_logcat_mode);
+
+ tmp_config_obj.set_enable_tombstone_receiver(FLAGS_enable_tombstone_receiver);
+ tmp_config_obj.set_tombstone_receiver_binary(
+ vsoc::DefaultHostArtifactsPath("bin/tombstone_receiver"));
tmp_config_obj.set_enable_vehicle_hal_grpc_server(FLAGS_enable_vehicle_hal_grpc_server);
tmp_config_obj.set_vehicle_hal_grpc_server_binary(
- HostBinaryPath("android.hardware.automotive.vehicle@2.0-virtualization-grpc-server"));
-
- std::string custom_action_config;
- if (!FLAGS_custom_action_config.empty()) {
- custom_action_config = FLAGS_custom_action_config;
- } else {
- std::string custom_action_config_dir =
- DefaultHostArtifactsPath("etc/cvd_custom_action_config");
- if (DirectoryExists(custom_action_config_dir)) {
- auto custom_action_configs = DirectoryContents(custom_action_config_dir);
- // Two entries are always . and ..
- if (custom_action_configs.size() > 3) {
- LOG(ERROR) << "Expected at most one custom action config in "
- << custom_action_config_dir << ". Please delete extras.";
- } else if (custom_action_configs.size() == 3) {
- for (const auto& config : custom_action_configs) {
- if (android::base::EndsWithIgnoreCase(config, ".json")) {
- custom_action_config = custom_action_config_dir + "/" + config;
- }
- }
- }
- }
- }
- std::vector<CustomActionConfig> custom_actions;
- Json::CharReaderBuilder builder;
- Json::Value custom_action_array(Json::arrayValue);
- if (custom_action_config != "") {
- // Load the custom action config JSON.
- std::ifstream ifs(custom_action_config);
- std::string errorMessage;
- if (!Json::parseFromStream(builder, ifs, &custom_action_array, &errorMessage)) {
- LOG(FATAL) << "Could not read custom actions config file "
- << custom_action_config << ": "
- << errorMessage;
- }
- for (const auto& custom_action : custom_action_array) {
- custom_actions.push_back(CustomActionConfig(custom_action));
- }
- }
- if (FLAGS_custom_actions != "") {
- // Load the custom action from the --config preset file.
- std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
- std::string errorMessage;
- if (!reader->parse(&*FLAGS_custom_actions.begin(), &*FLAGS_custom_actions.end(),
- &custom_action_array, &errorMessage)) {
- LOG(FATAL) << "Could not read custom actions config flag: "
- << errorMessage;
- }
- for (const auto& custom_action : custom_action_array) {
- custom_actions.push_back(CustomActionConfig(custom_action));
- }
- }
- tmp_config_obj.set_custom_actions(custom_actions);
+ vsoc::DefaultHostArtifactsPath("bin/android.hardware.automotive.vehicle@2.0-virtualization-grpc-server"));
+ tmp_config_obj.set_use_bootloader(FLAGS_use_bootloader);
tmp_config_obj.set_bootloader(FLAGS_bootloader);
- tmp_config_obj.set_enable_metrics(FLAGS_report_anonymous_usage_stats);
-
if (!FLAGS_boot_slot.empty()) {
tmp_config_obj.set_boot_slot(FLAGS_boot_slot);
}
tmp_config_obj.set_cuttlefish_env_path(GetCuttlefishEnvPath());
- tmp_config_obj.set_ril_dns(FLAGS_ril_dns);
-
- tmp_config_obj.set_enable_minimal_mode(FLAGS_enable_minimal_mode);
-
- tmp_config_obj.set_vhost_net(FLAGS_vhost_net);
-
- tmp_config_obj.set_record_screen(FLAGS_record_screen);
-
- tmp_config_obj.set_ethernet(FLAGS_ethernet);
-
- tmp_config_obj.set_enable_host_bluetooth(FLAGS_enable_host_bluetooth);
-
- tmp_config_obj.set_protected_vm(FLAGS_protected_vm);
-
- std::vector<int> num_instances;
+ std::vector<int> instance_nums;
for (int i = 0; i < FLAGS_num_instances; i++) {
- num_instances.push_back(GetInstance() + i);
+ instance_nums.push_back(vsoc::GetInstance() + i);
}
- std::vector<std::string> gnss_file_paths = android::base::Split(FLAGS_gnss_file_path, ",");
-
- bool is_first_instance = true;
- for (const auto& num : num_instances) {
- IfaceConfig iface_config;
- if (FLAGS_use_allocd) {
- auto iface_opt = AllocateNetworkInterfaces();
- if (!iface_opt.has_value()) {
- LOG(FATAL) << "Failed to acquire network interfaces";
- }
- iface_config = iface_opt.value();
- } else {
- iface_config = DefaultNetworkInterfaces(num);
- }
+ for (const auto& num : instance_nums) {
auto instance = tmp_config_obj.ForInstance(num);
- auto const_instance =
- const_cast<const CuttlefishConfig&>(tmp_config_obj)
- .ForInstance(num);
+ auto const_instance = const_cast<const vsoc::CuttlefishConfig&>(tmp_config_obj)
+ .ForInstance(num);
// Set this first so that calls to PerInstancePath below are correct
- instance.set_instance_dir(instance_dir + "." + std::to_string(num));
- instance.set_use_allocd(FLAGS_use_allocd);
- if (FLAGS_use_random_serial) {
- instance.set_serial_number(
- RandomSerialNumber("CFCVD" + std::to_string(num)));
+ instance.set_instance_dir(FLAGS_instance_dir + "." + std::to_string(num));
+ if(FLAGS_use_random_serial){
+ instance.set_serial_number(RandomSerialNumber("CFCVD" + std::to_string(num)));
} else {
instance.set_serial_number(FLAGS_serial_number + std::to_string(num));
}
- // call this before all stuff that has vsock server: e.g. touchpad, keyboard, etc
- const auto vsock_guest_cid = FLAGS_vsock_guest_cid + num - GetInstance();
- instance.set_vsock_guest_cid(vsock_guest_cid);
- auto calc_vsock_port = [vsock_guest_cid](const int base_port) {
- // a base (vsock) port is like 9200 for modem_simulator, etc
- return cuttlefish::GetVsockServerPort(base_port, vsock_guest_cid);
- };
- instance.set_session_id(iface_config.mobile_tap.session_id);
instance.set_mobile_bridge_name(StrForInstance("cvd-mbr-", num));
- instance.set_mobile_tap_name(iface_config.mobile_tap.name);
- instance.set_wifi_tap_name(iface_config.wireless_tap.name);
- instance.set_ethernet_tap_name(iface_config.ethernet_tap.name);
+ instance.set_mobile_tap_name(StrForInstance("cvd-mtap-", num));
+
+ instance.set_wifi_tap_name(StrForInstance("cvd-wtap-", num));
+
+ instance.set_vsock_guest_cid(3 + num - 1);
instance.set_uuid(FLAGS_uuid);
instance.set_vnc_server_port(6444 + num - 1);
instance.set_host_port(6520 + num - 1);
- instance.set_adb_ip_and_port("0.0.0.0:" + std::to_string(6520 + num - 1));
- instance.set_tombstone_receiver_port(calc_vsock_port(6600));
- instance.set_vehicle_hal_server_port(9210 + num - 1);
- instance.set_audiocontrol_server_port(9410); /* OK to use the same port number across instances */
- instance.set_config_server_port(calc_vsock_port(6800));
-
- if (tmp_config_obj.gpu_mode() != kGpuModeDrmVirgl &&
- tmp_config_obj.gpu_mode() != kGpuModeGfxStream) {
- instance.set_frames_server_port(calc_vsock_port(6900));
- if (FLAGS_vm_manager == QemuManager::name()) {
- instance.set_keyboard_server_port(calc_vsock_port(7000));
- instance.set_touch_server_port(calc_vsock_port(7100));
- }
- }
-
- instance.set_gnss_grpc_proxy_server_port(7200 + num -1);
-
- if (num <= gnss_file_paths.size()) {
- instance.set_gnss_file_path(gnss_file_paths[num-1]);
- }
+ instance.set_adb_ip_and_port("127.0.0.1:" + std::to_string(6520 + num - 1));
- instance.set_rootcanal_hci_port(7300 + num - 1);
- instance.set_rootcanal_link_port(7400 + num - 1);
- instance.set_rootcanal_test_port(7500 + num - 1);
- instance.set_rootcanal_config_file(
- FLAGS_bluetooth_controller_properties_file);
- instance.set_rootcanal_default_commands_file(
- FLAGS_bluetooth_default_commands_file);
+ instance.set_vehicle_hal_server_port(9210 + num - 1);
instance.set_device_title(FLAGS_device_title);
- if (FLAGS_protected_vm) {
- instance.set_virtual_disk_paths(
- {const_instance.PerInstancePath("os_composite.img")});
- } else {
- std::vector<std::string> virtual_disk_paths = {
- const_instance.PerInstancePath("overlay.img"),
- const_instance.PerInstancePath("persistent_composite.img"),
- };
- if (FLAGS_use_sdcard) {
- virtual_disk_paths.push_back(const_instance.sdcard_path());
- }
- instance.set_virtual_disk_paths(virtual_disk_paths);
- }
+ instance.set_virtual_disk_paths({
+ const_instance.PerInstancePath("overlay.img"),
+ const_instance.sdcard_path(),
+ });
std::array<unsigned char, 6> mac_address;
mac_address[0] = 1 << 6; // locally administered
@@ -725,209 +446,601 @@ CuttlefishConfig InitializeCuttlefishConfiguration(
}
mac_address[5] = num;
instance.set_wifi_mac_address(mac_address);
+ }
+
+ return tmp_config_obj;
+}
+
+bool SaveConfig(const vsoc::CuttlefishConfig& tmp_config_obj) {
+ auto config_file = GetConfigFilePath(tmp_config_obj);
+ auto config_link = vsoc::GetGlobalConfigFileLink();
+ // Save the config object before starting any host process
+ if (!tmp_config_obj.SaveToFile(config_file)) {
+ LOG(ERROR) << "Unable to save config object";
+ return false;
+ }
+ auto legacy_config_file = GetLegacyConfigFilePath(tmp_config_obj);
+ if (!tmp_config_obj.SaveToFile(legacy_config_file)) {
+ LOG(ERROR) << "Unable to save legacy config object";
+ return false;
+ }
+ setenv(vsoc::kCuttlefishConfigEnvVarName, config_file.c_str(), true);
+ if (symlink(config_file.c_str(), config_link.c_str()) != 0) {
+ LOG(ERROR) << "Failed to create symlink to config file at " << config_link
+ << ": " << strerror(errno);
+ return false;
+ }
+
+ return true;
+}
- instance.set_start_webrtc_signaling_server(false);
+void SetDefaultFlagsForQemu() {
+ // TODO(b/144119457) Use the serial port.
+ SetCommandLineOptionWithMode("logcat_mode", cvd::kLogcatVsockMode,
+ google::FlagSettingMode::SET_FLAGS_DEFAULT);
+}
- if (FLAGS_webrtc_device_id.empty()) {
- // Use the instance's name as a default
- instance.set_webrtc_device_id(const_instance.instance_name());
+void SetDefaultFlagsForCrosvm() {
+ SetCommandLineOptionWithMode("logcat_mode", cvd::kLogcatVsockMode,
+ google::FlagSettingMode::SET_FLAGS_DEFAULT);
+
+ // Crosvm requires a specific setting for kernel decompression; it must be
+ // on for aarch64 and off for x86, no other mode is supported.
+ bool decompress_kernel = false;
+ if (cvd::HostArch() == "aarch64") {
+ decompress_kernel = true;
+ }
+ SetCommandLineOptionWithMode("decompress_kernel",
+ (decompress_kernel ? "true" : "false"),
+ google::FlagSettingMode::SET_FLAGS_DEFAULT);
+}
+
+bool ParseCommandLineFlags(int* argc, char*** argv) {
+ google::ParseCommandLineNonHelpFlags(argc, argv, true);
+ bool invalid_manager = false;
+ if (FLAGS_vm_manager == vm_manager::QemuManager::name()) {
+ SetDefaultFlagsForQemu();
+ } else if (FLAGS_vm_manager == vm_manager::CrosvmManager::name()) {
+ SetDefaultFlagsForCrosvm();
+ } else {
+ std::cerr << "Unknown Virtual Machine Manager: " << FLAGS_vm_manager
+ << std::endl;
+ invalid_manager = true;
+ }
+ if (NumStreamers() == 0) {
+ // This makes the vnc server the default streamer unless the user requests
+ // another via a --star_<streamer> flag, while at the same time it's
+ // possible to run without any streamer by setting --start_vnc_server=false.
+ SetCommandLineOptionWithMode("start_vnc_server", "true",
+ google::FlagSettingMode::SET_FLAGS_DEFAULT);
+ }
+ google::HandleCommandLineHelpFlags();
+ if (invalid_manager) {
+ return false;
+ }
+ // Set the env variable to empty (in case the caller passed a value for it).
+ unsetenv(vsoc::kCuttlefishConfigEnvVarName);
+
+ return ResolveInstanceFiles();
+}
+
+std::string cpp_basename(const std::string& str) {
+ char* copy = strdup(str.c_str()); // basename may modify its argument
+ std::string ret(basename(copy));
+ free(copy);
+ return ret;
+}
+
+bool CleanPriorFiles(const std::string& path, const std::set<std::string>& preserving) {
+ if (preserving.count(cpp_basename(path))) {
+ LOG(INFO) << "Preserving: " << path;
+ return true;
+ }
+ struct stat statbuf;
+ if (lstat(path.c_str(), &statbuf) < 0) {
+ int error_num = errno;
+ if (error_num == ENOENT) {
+ return true;
} else {
- std::string device_id = FLAGS_webrtc_device_id;
- size_t pos;
- while ((pos = device_id.find("{num}")) != std::string::npos) {
- device_id.replace(pos, strlen("{num}"), std::to_string(num));
- }
- instance.set_webrtc_device_id(device_id);
+ LOG(ERROR) << "Could not stat \"" << path << "\": " << strerror(error_num);
+ return false;
}
- if (FLAGS_start_webrtc_sig_server && is_first_instance) {
- auto port = 8443 + num - 1;
- // Change the signaling server port for all instances
- tmp_config_obj.set_sig_server_port(port);
- instance.set_start_webrtc_signaling_server(true);
- } else {
- instance.set_start_webrtc_signaling_server(false);
+ }
+ if ((statbuf.st_mode & S_IFMT) != S_IFDIR) {
+ LOG(INFO) << "Deleting: " << path;
+ if (unlink(path.c_str()) < 0) {
+ int error_num = errno;
+ LOG(ERROR) << "Could not unlink \"" << path << "\", error was " << strerror(error_num);
+ return false;
}
- is_first_instance = false;
-
- // instance.modem_simulator_ports := "" or "[port,]*port"
- if (modem_simulator_count > 0) {
- std::stringstream modem_ports;
- for (auto index {0}; index < modem_simulator_count - 1; index++) {
- auto port = 9200 + (modem_simulator_count * (num - 1)) + index;
- modem_ports << calc_vsock_port(port) << ",";
- }
- auto port = 9200 + (modem_simulator_count * (num - 1)) +
- modem_simulator_count - 1;
- modem_ports << calc_vsock_port(port);
- instance.set_modem_simulator_ports(modem_ports.str());
- } else {
- instance.set_modem_simulator_ports("");
+ return true;
+ }
+ std::unique_ptr<DIR, int(*)(DIR*)> dir(opendir(path.c_str()), closedir);
+ if (!dir) {
+ int error_num = errno;
+ LOG(ERROR) << "Could not clean \"" << path << "\": error was " << strerror(error_num);
+ return false;
+ }
+ for (auto entity = readdir(dir.get()); entity != nullptr; entity = readdir(dir.get())) {
+ std::string entity_name(entity->d_name);
+ if (entity_name == "." || entity_name == "..") {
+ continue;
+ }
+ std::string entity_path = path + "/" + entity_name;
+ if (!CleanPriorFiles(entity_path.c_str(), preserving)) {
+ return false;
+ }
+ }
+ if (rmdir(path.c_str()) < 0) {
+ if (!(errno == EEXIST || errno == ENOTEMPTY)) {
+ // If EEXIST or ENOTEMPTY, probably because a file was preserved
+ int error_num = errno;
+ LOG(ERROR) << "Could not rmdir \"" << path << "\", error was " << strerror(error_num);
+ return false;
+ }
+ }
+ return true;
+}
+
+bool CleanPriorFiles(const std::vector<std::string>& paths, const std::set<std::string>& preserving) {
+ std::string prior_files;
+ for (auto path : paths) {
+ struct stat statbuf;
+ if (stat(path.c_str(), &statbuf) < 0 && errno != ENOENT) {
+ // If ENOENT, it doesn't exist yet, so there is no work to do'
+ int error_num = errno;
+ LOG(ERROR) << "Could not stat \"" << path << "\": " << strerror(error_num);
+ return false;
+ }
+ bool is_directory = (statbuf.st_mode & S_IFMT) == S_IFDIR;
+ prior_files += (is_directory ? (path + "/*") : path) + " ";
+ }
+ LOG(INFO) << "Assuming prior files of " << prior_files;
+ std::string lsof_cmd = "lsof -t " + prior_files + " >/dev/null 2>&1";
+ int rval = std::system(lsof_cmd.c_str());
+ // lsof returns 0 if any of the files are open
+ if (WEXITSTATUS(rval) == 0) {
+ LOG(ERROR) << "Clean aborted: files are in use";
+ return false;
+ }
+ for (const auto& path : paths) {
+ if (!CleanPriorFiles(path, preserving)) {
+ LOG(ERROR) << "Remove of file under \"" << path << "\" failed";
+ return false;
}
- } // end of num_instances loop
+ }
+ return true;
+}
+
+bool CleanPriorFiles(const vsoc::CuttlefishConfig& config, const std::set<std::string>& preserving) {
+ std::vector<std::string> paths = {
+ // Everything in the assembly directory
+ FLAGS_assembly_dir,
+ // The environment file
+ GetCuttlefishEnvPath(),
+ // The global link to the config file
+ vsoc::GetGlobalConfigFileLink(),
+ };
+ for (const auto& instance : config.Instances()) {
+ paths.push_back(instance.instance_dir());
+ }
+ paths.push_back(FLAGS_instance_dir);
+ return CleanPriorFiles(paths, preserving);
+}
- tmp_config_obj.set_enable_sandbox(FLAGS_enable_sandbox);
+bool DecompressKernel(const std::string& src, const std::string& dst) {
+ cvd::Command decomp_cmd(vsoc::DefaultHostArtifactsPath("bin/extract-vmlinux"));
+ decomp_cmd.AddParameter(src);
+ auto output_file = cvd::SharedFD::Creat(dst.c_str(), 0666);
+ if (!output_file->IsOpen()) {
+ LOG(ERROR) << "Unable to create decompressed image file: "
+ << output_file->StrError();
+ return false;
+ }
+ decomp_cmd.RedirectStdIO(cvd::Subprocess::StdIOChannel::kStdOut, output_file);
+ auto decomp_proc = decomp_cmd.Start();
+ return decomp_proc.Started() && decomp_proc.Wait() == 0;
+}
- // Audio is not available for VNC server
- SetCommandLineOptionWithMode(
- "enable_audio",
- (FLAGS_start_vnc_server || (cuttlefish::HostArch() == cuttlefish::Arch::Arm64))
- ? "false"
- : "true",
- SET_FLAGS_DEFAULT);
- tmp_config_obj.set_enable_audio(FLAGS_enable_audio);
+void ValidateAdbModeFlag(const vsoc::CuttlefishConfig& config) {
+ auto adb_modes = config.adb_mode();
+ adb_modes.erase(vsoc::AdbMode::Unknown);
+ if (adb_modes.size() < 1) {
+ LOG(INFO) << "ADB not enabled";
+ }
+}
- return tmp_config_obj;
+} // namespace
+
+namespace {
+
+std::vector<ImagePartition> disk_config() {
+ std::vector<ImagePartition> partitions;
+ partitions.push_back(ImagePartition {
+ .label = "misc",
+ .image_file_path = FLAGS_misc_image,
+ });
+ partitions.push_back(ImagePartition {
+ .label = "boot_a",
+ .image_file_path = FLAGS_boot_image,
+ });
+ partitions.push_back(ImagePartition {
+ .label = "boot_b",
+ .image_file_path = FLAGS_boot_image,
+ });
+ partitions.push_back(ImagePartition {
+ .label = "vendor_boot_a",
+ .image_file_path = FLAGS_vendor_boot_image,
+ });
+ partitions.push_back(ImagePartition {
+ .label = "vendor_boot_b",
+ .image_file_path = FLAGS_vendor_boot_image,
+ });
+ partitions.push_back(ImagePartition {
+ .label = "vbmeta_a",
+ .image_file_path = FLAGS_vbmeta_image,
+ });
+ partitions.push_back(ImagePartition {
+ .label = "vbmeta_b",
+ .image_file_path = FLAGS_vbmeta_image,
+ });
+ partitions.push_back(ImagePartition {
+ .label = "vbmeta_system_a",
+ .image_file_path = FLAGS_vbmeta_system_image,
+ });
+ partitions.push_back(ImagePartition {
+ .label = "vbmeta_system_b",
+ .image_file_path = FLAGS_vbmeta_system_image,
+ });
+ partitions.push_back(ImagePartition {
+ .label = "super",
+ .image_file_path = FLAGS_super_image,
+ });
+ partitions.push_back(ImagePartition {
+ .label = "userdata",
+ .image_file_path = FLAGS_data_image,
+ });
+ partitions.push_back(ImagePartition {
+ .label = "cache",
+ .image_file_path = FLAGS_cache_image,
+ });
+ partitions.push_back(ImagePartition {
+ .label = "metadata",
+ .image_file_path = FLAGS_metadata_image,
+ });
+ return partitions;
}
-void SetDefaultFlagsFromConfigPreset() {
- std::string config_preset = FLAGS_config; // The name of the preset config.
- std::string config_file_path; // The path to the preset config JSON.
- std::set<std::string> allowed_config_presets;
- for (const std::string& file :
- DirectoryContents(DefaultHostArtifactsPath("etc/cvd_config"))) {
- std::string_view local_file(file);
- if (android::base::ConsumePrefix(&local_file, "cvd_config_") &&
- android::base::ConsumeSuffix(&local_file, ".json")) {
- allowed_config_presets.emplace(local_file);
+std::chrono::system_clock::time_point LastUpdatedInputDisk() {
+ std::chrono::system_clock::time_point ret;
+ for (auto& partition : disk_config()) {
+ auto partition_mod_time = cvd::FileModificationTime(partition.image_file_path);
+ if (partition_mod_time > ret) {
+ ret = partition_mod_time;
}
}
+ return ret;
+}
+
+bool ShouldCreateCompositeDisk(const vsoc::CuttlefishConfig& config) {
+ if (!cvd::FileExists(config.composite_disk_path())) {
+ return true;
+ }
+ auto composite_age = cvd::FileModificationTime(config.composite_disk_path());
+ return composite_age < LastUpdatedInputDisk();
+}
+
+bool ConcatRamdisks(const std::string& new_ramdisk_path, const std::string& ramdisk_a_path,
+ const std::string& ramdisk_b_path) {
+ // clear out file of any pre-existing content
+ std::ofstream new_ramdisk(new_ramdisk_path, std::ios_base::binary | std::ios_base::trunc);
+ std::ifstream ramdisk_a(ramdisk_a_path, std::ios_base::binary);
+ std::ifstream ramdisk_b(ramdisk_b_path, std::ios_base::binary);
+
+ if(!new_ramdisk.is_open() || !ramdisk_a.is_open() || !ramdisk_b.is_open()) {
+ return false;
+ }
+
+ new_ramdisk << ramdisk_a.rdbuf() << ramdisk_b.rdbuf();
+ return true;
+}
+
+off_t AvailableSpaceAtPath(const std::string& path) {
+ struct statvfs vfs;
+ if (statvfs(path.c_str(), &vfs) != 0) {
+ int error_num = errno;
+ LOG(ERROR) << "Could not find space available at " << path << ", error was "
+ << strerror(error_num);
+ return 0;
+ }
+ return vfs.f_bsize * vfs.f_bavail; // block size * free blocks for unprivileged users
+}
+
+off_t USERDATA_IMAGE_RESERVED = 4l * (1l << 30l); // 4 GiB
+off_t AGGREGATE_IMAGE_RESERVED = 12l * (1l << 30l); // 12 GiB
- // If the user specifies a --config name, then use that config
- // preset option.
- std::string android_info_path = FLAGS_system_image_dir + "/android-info.txt";
- if (IsFlagSet("config")) {
- if (!allowed_config_presets.count(config_preset)) {
- LOG(FATAL) << "Invalid --config option '" << config_preset
- << "'. Valid options: "
- << android::base::Join(allowed_config_presets, ",");
+bool CreateCompositeDisk(const vsoc::CuttlefishConfig& config) {
+ if (!cvd::SharedFD::Open(config.composite_disk_path().c_str(), O_WRONLY | O_CREAT, 0644)->IsOpen()) {
+ LOG(ERROR) << "Could not ensure " << config.composite_disk_path() << " exists";
+ return false;
+ }
+ if (FLAGS_vm_manager == vm_manager::CrosvmManager::name()) {
+ auto existing_size = cvd::FileSize(FLAGS_data_image);
+ auto available_space = AvailableSpaceAtPath(FLAGS_data_image);
+ if (available_space < USERDATA_IMAGE_RESERVED - existing_size) {
+ // TODO(schuffelen): Duplicate this check in run_cvd when it can run on a separate machine
+ LOG(ERROR) << "Not enough space in fs containing " << FLAGS_data_image;
+ LOG(ERROR) << "Wanted " << (USERDATA_IMAGE_RESERVED - existing_size);
+ LOG(ERROR) << "Got " << available_space;
+ return false;
}
- } else if (FileExists(android_info_path)) {
- // Otherwise try to load the correct preset using android-info.txt.
- std::ifstream ifs(android_info_path);
- if (ifs.is_open()) {
- std::string android_info;
- ifs >> android_info;
- std::string_view local_android_info(android_info);
- if (android::base::ConsumePrefix(&local_android_info, "config=")) {
- config_preset = local_android_info;
+ std::string header_path = config.AssemblyPath("gpt_header.img");
+ std::string footer_path = config.AssemblyPath("gpt_footer.img");
+ CreateCompositeDisk(disk_config(), header_path, footer_path, config.composite_disk_path());
+ } else {
+ auto existing_size = cvd::FileSize(config.composite_disk_path());
+ auto available_space = AvailableSpaceAtPath(config.composite_disk_path());
+ if (available_space < AGGREGATE_IMAGE_RESERVED - existing_size) {
+ LOG(ERROR) << "Not enough space to create " << config.composite_disk_path();
+ LOG(ERROR) << "Wanted " << (AGGREGATE_IMAGE_RESERVED - existing_size);
+ LOG(ERROR) << "Got " << available_space;
+ return false;
+ }
+ AggregateImage(disk_config(), config.composite_disk_path());
+ }
+ return true;
+}
+
+} // namespace
+
+#ifndef O_TMPFILE
+# define O_TMPFILE (020000000 | O_DIRECTORY)
+#endif
+
+const vsoc::CuttlefishConfig* InitFilesystemAndCreateConfig(
+ int* argc, char*** argv, cvd::FetcherConfig fetcher_config) {
+ if (!ParseCommandLineFlags(argc, argv)) {
+ LOG(ERROR) << "Failed to parse command arguments";
+ exit(AssemblerExitCodes::kArgumentParsingError);
+ }
+
+ std::string assembly_dir_parent = cvd::AbsolutePath(FLAGS_assembly_dir);
+ while (assembly_dir_parent[assembly_dir_parent.size() - 1] == '/') {
+ assembly_dir_parent =
+ assembly_dir_parent.substr(0, FLAGS_assembly_dir.rfind('/'));
+ }
+ assembly_dir_parent =
+ assembly_dir_parent.substr(0, FLAGS_assembly_dir.rfind('/'));
+ auto log =
+ cvd::SharedFD::Open(
+ assembly_dir_parent,
+ O_WRONLY | O_TMPFILE,
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
+ if (!log->IsOpen()) {
+ LOG(ERROR) << "Could not open O_TMPFILE precursor to assemble_cvd.log: "
+ << log->StrError();
+ } else {
+ android::base::SetLogger(cvd::TeeLogger({
+ {cvd::ConsoleSeverity(), cvd::SharedFD::Dup(2)},
+ {cvd::LogFileSeverity(), log},
+ }));
+ }
+
+ auto boot_img_unpacker =
+ cvd::BootImageUnpacker::FromImages(FLAGS_boot_image,
+ FLAGS_vendor_boot_image);
+ {
+ // The config object is created here, but only exists in memory until the
+ // SaveConfig line below. Don't launch cuttlefish subprocesses between these
+ // two operations, as those will assume they can read the config object from
+ // disk.
+ auto config = InitializeCuttlefishConfiguration(*boot_img_unpacker, fetcher_config);
+ std::set<std::string> preserving;
+ if (FLAGS_resume && ShouldCreateCompositeDisk(config)) {
+ LOG(WARNING) << "Requested resuming a previous session (the default behavior) "
+ << "but the base images have changed under the overlay, making the "
+ << "overlay incompatible. Wiping the overlay files.";
+ } else if (FLAGS_resume && !ShouldCreateCompositeDisk(config)) {
+ preserving.insert("overlay.img");
+ preserving.insert("gpt_header.img");
+ preserving.insert("gpt_footer.img");
+ preserving.insert("composite.img");
+ preserving.insert("sdcard.img");
+ preserving.insert("access-kregistry");
+ }
+ if (!CleanPriorFiles(config, preserving)) {
+ LOG(ERROR) << "Failed to clean prior files";
+ exit(AssemblerExitCodes::kPrioFilesCleanupError);
+ }
+ // Create assembly directory if it doesn't exist.
+ if (!cvd::DirectoryExists(FLAGS_assembly_dir.c_str())) {
+ LOG(INFO) << "Setting up " << FLAGS_assembly_dir;
+ if (mkdir(FLAGS_assembly_dir.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) < 0
+ && errno != EEXIST) {
+ LOG(ERROR) << "Failed to create assembly directory: "
+ << FLAGS_assembly_dir << ". Error: " << errno;
+ exit(AssemblerExitCodes::kAssemblyDirCreationError);
}
- if (!allowed_config_presets.count(config_preset)) {
- LOG(WARNING) << android_info_path
- << " contains invalid config preset: '"
- << local_android_info << "'. Defaulting to 'phone'.";
- config_preset = "phone";
+ }
+ if (log->LinkAtCwd(config.AssemblyPath("assemble_cvd.log"))) {
+ LOG(ERROR) << "Unable to persist assemble_cvd log at "
+ << config.AssemblyPath("assemble_cvd.log")
+ << ": " << log->StrError();
+ }
+ for (const auto& instance : config.Instances()) {
+ // Create instance directory if it doesn't exist.
+ if (!cvd::DirectoryExists(instance.instance_dir().c_str())) {
+ LOG(INFO) << "Setting up " << FLAGS_instance_dir << ".N";
+ if (mkdir(instance.instance_dir().c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) < 0
+ && errno != EEXIST) {
+ LOG(ERROR) << "Failed to create instance directory: "
+ << FLAGS_instance_dir << ". Error: " << errno;
+ exit(AssemblerExitCodes::kInstanceDirCreationError);
+ }
}
+ auto internal_dir = instance.instance_dir() + "/" + vsoc::kInternalDirName;
+ if (!cvd::DirectoryExists(internal_dir)) {
+ if (mkdir(internal_dir.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) < 0
+ && errno != EEXIST) {
+ LOG(ERROR) << "Failed to create internal instance directory: "
+ << internal_dir << ". Error: " << errno;
+ exit(AssemblerExitCodes::kInstanceDirCreationError);
+ }
+ }
+ }
+ if (!SaveConfig(config)) {
+ LOG(ERROR) << "Failed to initialize configuration";
+ exit(AssemblerExitCodes::kCuttlefishConfigurationInitError);
}
}
- LOG(INFO) << "Launching CVD using --config='" << config_preset << "'.";
-
- config_file_path = DefaultHostArtifactsPath("etc/cvd_config/cvd_config_" +
- config_preset + ".json");
- Json::Value config;
- Json::CharReaderBuilder builder;
- std::ifstream ifs(config_file_path);
- std::string errorMessage;
- if (!Json::parseFromStream(builder, ifs, &config, &errorMessage)) {
- LOG(FATAL) << "Could not read config file " << config_file_path << ": "
- << errorMessage;
- }
- for (const std::string& flag : config.getMemberNames()) {
- std::string value;
- if (flag == "custom_actions") {
- Json::StreamWriterBuilder factory;
- value = Json::writeString(factory, config[flag]);
- } else {
- value = config[flag].asString();
+
+ std::string first_instance = FLAGS_instance_dir + "." + std::to_string(vsoc::GetInstance());
+ if (symlink(first_instance.c_str(), FLAGS_instance_dir.c_str()) < 0) {
+ LOG(ERROR) << "Could not symlink \"" << first_instance << "\" to \"" << FLAGS_instance_dir << "\"";
+ exit(cvd::kCuttlefishConfigurationInitError);
+ }
+
+ if (!cvd::FileHasContent(FLAGS_boot_image)) {
+ LOG(ERROR) << "File not found: " << FLAGS_boot_image;
+ exit(cvd::kCuttlefishConfigurationInitError);
+ }
+
+ if (!cvd::FileHasContent(FLAGS_vendor_boot_image)) {
+ LOG(ERROR) << "File not found: " << FLAGS_vendor_boot_image;
+ exit(cvd::kCuttlefishConfigurationInitError);
+ }
+
+ // Do this early so that the config object is ready for anything that needs it
+ auto config = vsoc::CuttlefishConfig::Get();
+ if (!config) {
+ LOG(ERROR) << "Failed to obtain config singleton";
+ exit(AssemblerExitCodes::kCuttlefishConfigurationInitError);
+ }
+
+ if (!boot_img_unpacker->Unpack(config->ramdisk_image_path(),
+ config->vendor_ramdisk_image_path(),
+ config->use_unpacked_kernel()
+ ? config->kernel_image_path()
+ : "")) {
+ LOG(ERROR) << "Failed to unpack boot image";
+ exit(AssemblerExitCodes::kBootImageUnpackError);
+ }
+
+ // TODO(134522463) as part of the bootloader refactor, repack the vendor boot
+ // image and use the bootloader to load both the boot and vendor ramdisk.
+ // Until then, this hack to get gki modules into cuttlefish will suffice.
+
+ // If a vendor ramdisk comes in via this mechanism, let it supercede the one
+ // in the vendor boot image. This flag is what kernel presubmit testing uses
+ // to pass in the kernel ramdisk.
+
+ // If no kernel is passed in or an initramfs is made available, the default
+ // vendor boot ramdisk or the initramfs provided should be appended to the
+ // boot ramdisk. If a kernel IS provided with no initramfs, it is safe to
+ // safe to assume that the kernel was built with no modules and expects no
+ // modules for cf to run properly.
+ std::string discovered_kernel = fetcher_config.FindCvdFileWithSuffix(kKernelDefaultPath);
+ std::string foreign_kernel = FLAGS_kernel_path.size() ? FLAGS_kernel_path : discovered_kernel;
+ std::string discovered_ramdisk = fetcher_config.FindCvdFileWithSuffix(kInitramfsImg);
+ std::string foreign_ramdisk = FLAGS_initramfs_path.size () ? FLAGS_initramfs_path : discovered_ramdisk;
+ if(!foreign_kernel.size() || foreign_ramdisk.size()) {
+ const std::string& vendor_ramdisk_path =
+ config->initramfs_path().size() ? config->initramfs_path()
+ : config->vendor_ramdisk_image_path();
+ if(!ConcatRamdisks(config->final_ramdisk_path(),
+ config->ramdisk_image_path(), vendor_ramdisk_path)) {
+ LOG(ERROR) << "Failed to concatenate ramdisk and vendor ramdisk";
+ exit(AssemblerExitCodes::kInitRamFsConcatError);
}
- if (gflags::SetCommandLineOptionWithMode(flag.c_str(), value.c_str(),
- SET_FLAGS_DEFAULT)
- .empty()) {
- LOG(FATAL) << "Error setting flag '" << flag << "'.";
+ }
+
+ if (config->decompress_kernel()) {
+ if (!DecompressKernel(config->kernel_image_path(),
+ config->decompressed_kernel_image_path())) {
+ LOG(ERROR) << "Failed to decompress kernel";
+ exit(AssemblerExitCodes::kKernelDecompressError);
}
}
-}
-void SetDefaultFlagsForQemu() {
- // for now, we don't set non-default options for QEMU
- if (FLAGS_gpu_mode == kGpuModeGuestSwiftshader && NumStreamers() == 0) {
- // This makes WebRTC the default streamer unless the user requests
- // another via a --star_<streamer> flag, while at the same time it's
- // possible to run without any streamer by setting --start_webrtc=false.
- SetCommandLineOptionWithMode("start_webrtc", "true", SET_FLAGS_DEFAULT);
+ ValidateAdbModeFlag(*config);
+
+ // Create misc if necessary
+ if (!InitializeMiscImage(FLAGS_misc_image)) {
+ exit(cvd::kCuttlefishConfigurationInitError);
}
- std::string default_bootloader = FLAGS_system_image_dir + "/bootloader.qemu";
- SetCommandLineOptionWithMode("bootloader", default_bootloader.c_str(),
- SET_FLAGS_DEFAULT);
-}
-void SetDefaultFlagsForCrosvm() {
- if (NumStreamers() == 0) {
- // This makes WebRTC the default streamer unless the user requests
- // another via a --star_<streamer> flag, while at the same time it's
- // possible to run without any streamer by setting --start_webrtc=false.
- SetCommandLineOptionWithMode("start_webrtc", "true", SET_FLAGS_DEFAULT);
+ // Create data if necessary
+ if (!ApplyDataImagePolicy(*config, FLAGS_data_image)) {
+ exit(cvd::kCuttlefishConfigurationInitError);
}
- // TODO(b/182484563): Re-enable autodetection when we fix the crosvm crashes
- bool default_enable_sandbox = false;
+ if (!cvd::FileExists(FLAGS_metadata_image)) {
+ CreateBlankImage(FLAGS_metadata_image, FLAGS_blank_metadata_image_mb, "none");
+ }
- SetCommandLineOptionWithMode("enable_sandbox",
- (default_enable_sandbox ? "true" : "false"),
- SET_FLAGS_DEFAULT);
+ for (const auto& instance : config->Instances()) {
+ if (!cvd::FileExists(instance.access_kregistry_path())) {
+ CreateBlankImage(instance.access_kregistry_path(), 2 /* mb */, "none");
+ }
- std::string default_bootloader = FLAGS_system_image_dir + "/bootloader";
- SetCommandLineOptionWithMode("bootloader", default_bootloader.c_str(),
- SET_FLAGS_DEFAULT);
-}
+ if (!cvd::FileExists(instance.sdcard_path())) {
+ CreateBlankImage(instance.sdcard_path(),
+ FLAGS_blank_sdcard_image_mb, "sdcard");
+ }
+ }
-bool ParseCommandLineFlags(int* argc, char*** argv, KernelConfig* kernel_config) {
- google::ParseCommandLineNonHelpFlags(argc, argv, true);
- SetDefaultFlagsFromConfigPreset();
- google::HandleCommandLineHelpFlags();
- bool invalid_manager = false;
+ // libavb expects to be able to read the maximum vbmeta size, so we must
+ // provide a partition which matches this or the read will fail
+ for (const auto& vbmeta_image : { FLAGS_vbmeta_image, FLAGS_vbmeta_system_image }) {
+ if (cvd::FileSize(vbmeta_image) != VBMETA_MAX_SIZE) {
+ auto fd = cvd::SharedFD::Open(vbmeta_image, O_RDWR);
+ if (fd->Truncate(VBMETA_MAX_SIZE) != 0) {
+ LOG(ERROR) << "`truncate --size=" << VBMETA_MAX_SIZE << " "
+ << vbmeta_image << "` failed: " << fd->StrError();
+ exit(cvd::kCuttlefishConfigurationInitError);
+ }
+ }
+ }
- if (!ResolveInstanceFiles()) {
- return false;
+ if (SuperImageNeedsRebuilding(fetcher_config, *config)) {
+ if (!RebuildSuperImage(fetcher_config, *config, FLAGS_super_image)) {
+ LOG(ERROR) << "Super image rebuilding requested but could not be completed.";
+ exit(cvd::kCuttlefishConfigurationInitError);
+ }
}
- ReadKernelConfig(kernel_config);
- if (FLAGS_vm_manager == "") {
- if (IsHostCompatible(kernel_config->target_arch)) {
- FLAGS_vm_manager = CrosvmManager::name();
- } else {
- FLAGS_vm_manager = QemuManager::name();
+ if (ShouldCreateCompositeDisk(*config)) {
+ if (!CreateCompositeDisk(*config)) {
+ exit(cvd::kDiskSpaceError);
}
}
- if (FLAGS_vm_manager == QemuManager::name()) {
- SetDefaultFlagsForQemu();
- } else if (FLAGS_vm_manager == CrosvmManager::name()) {
- SetDefaultFlagsForCrosvm();
- } else {
- std::cerr << "Unknown Virtual Machine Manager: " << FLAGS_vm_manager
- << std::endl;
- invalid_manager = true;
+ for (auto instance : config->Instances()) {
+ auto overlay_path = instance.PerInstancePath("overlay.img");
+ if (!cvd::FileExists(overlay_path) || ShouldCreateCompositeDisk(*config) || !FLAGS_resume
+ || cvd::FileModificationTime(overlay_path) < cvd::FileModificationTime(config->composite_disk_path())) {
+ if (FLAGS_resume) {
+ LOG(WARNING) << "Requested to continue an existing session, but the overlay was "
+ << "newer than its underlying composite disk. Wiping the overlay.";
+ }
+ CreateQcowOverlay(config->crosvm_binary(), config->composite_disk_path(), overlay_path);
+ CreateBlankImage(instance.access_kregistry_path(), 2 /* mb */, "none");
+ }
}
- // The default for starting signaling server is whether or not webrt is to be
- // started.
- SetCommandLineOptionWithMode("start_webrtc_sig_server",
- FLAGS_start_webrtc ? "true" : "false",
- SET_FLAGS_DEFAULT);
- if (invalid_manager) {
- return false;
+
+ for (auto instance : config->Instances()) {
+ // Check that the files exist
+ for (const auto& file : instance.virtual_disk_paths()) {
+ if (!file.empty() && !cvd::FileHasContent(file.c_str())) {
+ LOG(ERROR) << "File not found: " << file;
+ exit(cvd::kCuttlefishConfigurationInitError);
+ }
+ }
}
- // Set the env variable to empty (in case the caller passed a value for it).
- unsetenv(kCuttlefishConfigEnvVarName);
- return true;
+ return config;
}
-std::string GetConfigFilePath(const CuttlefishConfig& config) {
+std::string GetConfigFilePath(const vsoc::CuttlefishConfig& config) {
return config.AssemblyPath("cuttlefish_config.json");
}
-
-std::string GetCuttlefishEnvPath() {
- return StringFromEnv("HOME", ".") + "/.cuttlefish.sh";
-}
-
-} // namespace cuttlefish
diff --git a/host/commands/assemble_cvd/flags.h b/host/commands/assemble_cvd/flags.h
index 3c02d9258..03733881e 100644
--- a/host/commands/assemble_cvd/flags.h
+++ b/host/commands/assemble_cvd/flags.h
@@ -1,27 +1,8 @@
#pragma once
-#include <cstdint>
-#include <optional>
-
-#include "common/libs/utils/environment.h"
#include "host/libs/config/cuttlefish_config.h"
#include "host/libs/config/fetcher_config.h"
-namespace cuttlefish {
-
-struct KernelConfig {
- Arch target_arch;
- bool bootconfig_supported;
-};
-
-bool ParseCommandLineFlags(int* argc, char*** argv,
- KernelConfig* kernel_config);
-// Must be called after ParseCommandLineFlags.
-CuttlefishConfig InitializeCuttlefishConfiguration(
- const std::string& instance_dir, int modem_simulator_count,
- KernelConfig kernel_config);
-
-std::string GetConfigFilePath(const CuttlefishConfig& config);
-std::string GetCuttlefishEnvPath();
-
-} // namespace cuttlefish
+const vsoc::CuttlefishConfig* InitFilesystemAndCreateConfig(
+ int* argc, char*** argv, cvd::FetcherConfig config);
+std::string GetConfigFilePath(const vsoc::CuttlefishConfig& config);
diff --git a/host/commands/assemble_cvd/image_aggregator.cc b/host/commands/assemble_cvd/image_aggregator.cc
new file mode 100644
index 000000000..5f1c36070
--- /dev/null
+++ b/host/commands/assemble_cvd/image_aggregator.cc
@@ -0,0 +1,325 @@
+/*
+ * 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.
+ */
+
+#include "host/commands/assemble_cvd/image_aggregator.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdio.h>
+
+#include <fstream>
+#include <string>
+#include <vector>
+
+#include <android-base/logging.h>
+#include <json/json.h>
+#include <google/protobuf/text_format.h>
+#include <sparse/sparse.h>
+
+#include "common/libs/fs/shared_buf.h"
+#include "common/libs/fs/shared_fd.h"
+#include "common/libs/utils/files.h"
+#include "common/libs/utils/subprocess.h"
+#include "host/commands/assemble_cvd/mbr.h"
+#include "host/libs/config/cuttlefish_config.h"
+#include "device/google/cuttlefish/host/commands/assemble_cvd/cdisk_spec.pb.h"
+
+namespace {
+
+const int GPT_HEADER_SIZE = 512 * 34;
+const int GPT_FOOTER_SIZE = 512 * 33;
+
+const std::string BPTTOOL_FILE_PATH = "bin/cf_bpttool";
+
+Json::Value BpttoolInput(const std::vector<ImagePartition>& partitions) {
+ std::vector<off_t> file_sizes;
+ off_t total_size = 20 << 20; // 20 MB for padding
+ for (auto& partition : partitions) {
+ LOG(INFO) << "Examining " << partition.label;
+ auto file = cvd::SharedFD::Open(partition.image_file_path.c_str(), O_RDONLY);
+ if (!file->IsOpen()) {
+ LOG(FATAL) << "Could not open \"" << partition.image_file_path
+ << "\": " << file->StrError();
+ break;
+ }
+ int fd = file->UNMANAGED_Dup();
+ auto sparse = sparse_file_import(fd, /* verbose */ false, /* crc */ false);
+ off_t partition_file_size = 0;
+ if (sparse) {
+ partition_file_size = sparse_file_len(sparse, /* sparse */ false,
+ /* crc */ true);
+ sparse_file_destroy(sparse);
+ close(fd);
+ LOG(INFO) << "was sparse";
+ } else {
+ partition_file_size = cvd::FileSize(partition.image_file_path);
+ if (partition_file_size == 0) {
+ LOG(FATAL) << "Could not get file size of \"" << partition.image_file_path
+ << "\"";
+ break;
+ }
+ LOG(INFO) << "was not sparse";
+ }
+ LOG(INFO) << "size was " << partition_file_size;
+ total_size += partition_file_size;
+ file_sizes.push_back(partition_file_size);
+ }
+ Json::Value bpttool_input_json;
+ bpttool_input_json["settings"] = Json::Value();
+ bpttool_input_json["settings"]["disk_size"] = (Json::Int64) total_size;
+ bpttool_input_json["partitions"] = Json::Value(Json::arrayValue);
+ for (size_t i = 0; i < partitions.size(); i++) {
+ Json::Value partition_json;
+ partition_json["label"] = partitions[i].label;
+ partition_json["size"] = (Json::Int64) file_sizes[i];
+ partition_json["guid"] = "auto";
+ partition_json["type_guid"] = "linux_fs";
+ bpttool_input_json["partitions"].append(partition_json);
+ }
+ return bpttool_input_json;
+}
+
+std::string CreateFile(size_t len) {
+ char file_template[] = "/tmp/diskXXXXXX";
+ int fd = mkstemp(file_template);
+ if (fd < 0) {
+ LOG(FATAL) << "not able to create disk hole temp file";
+ }
+ char data[4096];
+ for (size_t i = 0; i < sizeof(data); i++) {
+ data[i] = '\0';
+ }
+ for (size_t i = 0; i < len + 2 * sizeof(data); i+= sizeof(data)) {
+ if (write(fd, data, sizeof(data)) < (ssize_t) sizeof(data)) {
+ LOG(FATAL) << "not able to write to disk hole temp file";
+ }
+ }
+ close(fd);
+ return std::string(file_template);
+}
+
+CompositeDisk MakeCompositeDiskSpec(const Json::Value& bpt_file,
+ const std::vector<ImagePartition>& partitions,
+ const std::string& header_file,
+ const std::string& footer_file) {
+ CompositeDisk disk;
+ disk.set_version(1);
+ ComponentDisk* header = disk.add_component_disks();
+ header->set_file_path(header_file);
+ header->set_offset(0);
+ size_t previous_end = GPT_HEADER_SIZE;
+ for (auto& bpt_partition: bpt_file["partitions"]) {
+ if (bpt_partition["offset"].asUInt64() != previous_end) {
+ ComponentDisk* component = disk.add_component_disks();
+ component->set_file_path(CreateFile(bpt_partition["offset"].asUInt64() - previous_end));
+ component->set_offset(previous_end);
+ }
+ ComponentDisk* component = disk.add_component_disks();
+ for (auto& partition : partitions) {
+ if (bpt_partition["label"] == partition.label) {
+ component->set_file_path(partition.image_file_path);
+ }
+ }
+ component->set_offset(bpt_partition["offset"].asUInt64());
+ component->set_read_write_capability(ReadWriteCapability::READ_WRITE);
+ previous_end = bpt_partition["offset"].asUInt64() + bpt_partition["size"].asUInt64();
+ }
+ size_t footer_start = bpt_file["settings"]["disk_size"].asUInt64() - GPT_FOOTER_SIZE;
+ if (footer_start != previous_end) {
+ ComponentDisk* component = disk.add_component_disks();
+ component->set_file_path(CreateFile(footer_start - previous_end));
+ component->set_offset(previous_end);
+ }
+ ComponentDisk* footer = disk.add_component_disks();
+ footer->set_file_path(footer_file);
+ footer->set_offset(bpt_file["settings"]["disk_size"].asUInt64() - GPT_FOOTER_SIZE);
+ disk.set_length(bpt_file["settings"]["disk_size"].asUInt64());
+ return disk;
+}
+
+cvd::SharedFD JsonToFd(const Json::Value& json) {
+ Json::FastWriter json_writer;
+ std::string json_string = json_writer.write(json);
+ cvd::SharedFD pipe[2];
+ cvd::SharedFD::Pipe(&pipe[0], &pipe[1]);
+ int written = pipe[1]->Write(json_string.c_str(), json_string.size());
+ if (written < 0) {
+ LOG(FATAL) << "Failed to write to pipe, errno is " << pipe[0]->GetErrno();
+ } else if (written < (int) json_string.size()) {
+ LOG(FATAL) << "Failed to write full json to pipe, only did " << written;
+ }
+ return pipe[0];
+}
+
+Json::Value FdToJson(cvd::SharedFD fd) {
+ std::string contents;
+ cvd::ReadAll(fd, &contents);
+ Json::Reader reader;
+ Json::Value json;
+ if (!reader.parse(contents, json)) {
+ LOG(FATAL) << "Could not parse json: " << reader.getFormattedErrorMessages();
+ }
+ return json;
+}
+
+cvd::SharedFD BpttoolMakeTable(const cvd::SharedFD& input) {
+ auto bpttool_path = vsoc::DefaultHostArtifactsPath(BPTTOOL_FILE_PATH);
+ cvd::Command bpttool_cmd(bpttool_path);
+ bpttool_cmd.AddParameter("make_table");
+ bpttool_cmd.AddParameter("--input=/dev/stdin");
+ bpttool_cmd.RedirectStdIO(cvd::Subprocess::StdIOChannel::kStdIn, input);
+ bpttool_cmd.AddParameter("--output_json=/dev/stdout");
+ cvd::SharedFD output_pipe[2];
+ cvd::SharedFD::Pipe(&output_pipe[0], &output_pipe[1]);
+ bpttool_cmd.RedirectStdIO(cvd::Subprocess::StdIOChannel::kStdOut, output_pipe[1]);
+ int success = bpttool_cmd.Start().Wait();
+ if (success != 0) {
+ LOG(FATAL) << "Unable to run bpttool. Exited with status " << success;
+ }
+ return output_pipe[0];
+}
+
+cvd::SharedFD BpttoolMakePartitionTable(cvd::SharedFD input) {
+ auto bpttool_path = vsoc::DefaultHostArtifactsPath(BPTTOOL_FILE_PATH);
+ cvd::Command bpttool_cmd(bpttool_path);
+ bpttool_cmd.AddParameter("make_table");
+ bpttool_cmd.AddParameter("--input=/dev/stdin");
+ bpttool_cmd.RedirectStdIO(cvd::Subprocess::StdIOChannel::kStdIn, input);
+ bpttool_cmd.AddParameter("--output_gpt=/dev/stdout");
+ cvd::SharedFD output_pipe[2];
+ cvd::SharedFD::Pipe(&output_pipe[0], &output_pipe[1]);
+ bpttool_cmd.RedirectStdIO(cvd::Subprocess::StdIOChannel::kStdOut, output_pipe[1]);
+ int success = bpttool_cmd.Start().Wait();
+ if (success != 0) {
+ LOG(FATAL) << "Unable to run bpttool. Exited with status " << success;
+ }
+ return output_pipe[0];
+}
+
+void CreateGptFiles(cvd::SharedFD gpt, const std::string& header_file,
+ const std::string& footer_file) {
+ std::string content;
+ content.resize(GPT_HEADER_SIZE);
+ if (cvd::ReadExact(gpt, &content) < GPT_HEADER_SIZE) {
+ LOG(FATAL) << "Unable to run read full gpt. Errno is " << gpt->GetErrno();
+ }
+ auto header_fd = cvd::SharedFD::Open(header_file.c_str(), O_CREAT | O_RDWR, 0755);
+ if (cvd::WriteAll(header_fd, content) < GPT_HEADER_SIZE) {
+ LOG(FATAL) << "Unable to run write full gpt. Errno is " << gpt->GetErrno();
+ }
+ content.resize(GPT_FOOTER_SIZE);
+ if (cvd::ReadExact(gpt, &content) < GPT_FOOTER_SIZE) {
+ LOG(FATAL) << "Unable to run read full gpt. Errno is " << gpt->GetErrno();
+ }
+ auto footer_fd = cvd::SharedFD::Open(footer_file.c_str(), O_CREAT | O_RDWR, 0755);
+ if (cvd::WriteAll(footer_fd, content) < GPT_FOOTER_SIZE) {
+ LOG(FATAL) << "Unable to run write full gpt. Errno is " << gpt->GetErrno();
+ }
+}
+
+void BptToolMakeDiskImage(const std::vector<ImagePartition>& partitions,
+ cvd::SharedFD table, const std::string& output) {
+ auto bpttool_path = vsoc::DefaultHostArtifactsPath(BPTTOOL_FILE_PATH);
+ cvd::Command bpttool_cmd(bpttool_path);
+ bpttool_cmd.AddParameter("make_disk_image");
+ bpttool_cmd.AddParameter("--input=/dev/stdin");
+ bpttool_cmd.AddParameter("--output=", cvd::AbsolutePath(output));
+ bpttool_cmd.RedirectStdIO(cvd::Subprocess::StdIOChannel::kStdIn, table);
+ for (auto& partition : partitions) {
+ auto abs_path = cvd::AbsolutePath(partition.image_file_path);
+ bpttool_cmd.AddParameter("--image=" + partition.label + ":" + abs_path);
+ }
+ int success = bpttool_cmd.Start().Wait();
+ if (success != 0) {
+ LOG(FATAL) << "Unable to run bpttool. Exited with status " << success;
+ }
+}
+
+void DeAndroidSparse(const std::vector<ImagePartition>& partitions) {
+ for (const auto& partition : partitions) {
+ auto file = cvd::SharedFD::Open(partition.image_file_path.c_str(), O_RDONLY);
+ if (!file->IsOpen()) {
+ LOG(FATAL) << "Could not open \"" << partition.image_file_path
+ << "\": " << file->StrError();
+ break;
+ }
+ int fd = file->UNMANAGED_Dup();
+ auto sparse = sparse_file_import(fd, /* verbose */ false, /* crc */ false);
+ if (!sparse) {
+ close(fd);
+ continue;
+ }
+ LOG(INFO) << "Desparsing " << partition.image_file_path;
+ std::string out_file_name = partition.image_file_path + ".desparse";
+ auto out_file = cvd::SharedFD::Open(out_file_name.c_str(), O_RDWR | O_CREAT | O_TRUNC,
+ S_IRUSR | S_IWUSR | S_IRGRP);
+ int write_fd = out_file->UNMANAGED_Dup();
+ int write_status = sparse_file_write(sparse, write_fd, /* gz */ false,
+ /* sparse */ false, /* crc */ false);
+ if (write_status < 0) {
+ LOG(FATAL) << "Failed to desparse \"" << partition.image_file_path << "\": " << write_status;
+ }
+ close(write_fd);
+ if (rename(out_file_name.c_str(), partition.image_file_path.c_str()) < 0) {
+ int error_num = errno;
+ LOG(FATAL) << "Could not move \"" << out_file_name << "\" to \""
+ << partition.image_file_path << "\": " << strerror(error_num);
+ }
+ sparse_file_destroy(sparse);
+ close(fd);
+ }
+}
+
+} // namespace
+
+void AggregateImage(const std::vector<ImagePartition>& partitions,
+ const std::string& output_path) {
+ DeAndroidSparse(partitions);
+ auto bpttool_input_json = BpttoolInput(partitions);
+ auto input_json_fd = JsonToFd(bpttool_input_json);
+ auto table_fd = BpttoolMakeTable(input_json_fd);
+ BptToolMakeDiskImage(partitions, table_fd, output_path);
+};
+
+void CreateCompositeDisk(std::vector<ImagePartition> partitions,
+ const std::string& header_file,
+ const std::string& footer_file,
+ const std::string& output_composite_path) {
+ auto bpttool_input_json = BpttoolInput(partitions);
+ auto table_fd = BpttoolMakeTable(JsonToFd(bpttool_input_json));
+ auto table = FdToJson(table_fd);
+ auto partition_table_fd = BpttoolMakePartitionTable(JsonToFd(bpttool_input_json));
+ CreateGptFiles(partition_table_fd, header_file, footer_file);
+ auto composite_proto = MakeCompositeDiskSpec(table, partitions, header_file, footer_file);
+ std::ofstream composite(output_composite_path.c_str(), std::ios::binary | std::ios::trunc);
+ composite << "composite_disk\x1d";
+ composite_proto.SerializeToOstream(&composite);
+ composite.flush();
+}
+
+void CreateQcowOverlay(const std::string& crosvm_path,
+ const std::string& backing_file,
+ const std::string& output_overlay_path) {
+ cvd::Command crosvm_qcow2_cmd(crosvm_path);
+ crosvm_qcow2_cmd.AddParameter("create_qcow2");
+ crosvm_qcow2_cmd.AddParameter("--backing_file=", backing_file);
+ crosvm_qcow2_cmd.AddParameter(output_overlay_path);
+ int success = crosvm_qcow2_cmd.Start().Wait();
+ if (success != 0) {
+ LOG(FATAL) << "Unable to run crosvm create_qcow2. Exited with status " << success;
+ }
+}
diff --git a/host/commands/assemble_cvd/image_aggregator.h b/host/commands/assemble_cvd/image_aggregator.h
new file mode 100644
index 000000000..d27931b33
--- /dev/null
+++ b/host/commands/assemble_cvd/image_aggregator.h
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <string>
+#include <vector>
+
+struct ImagePartition {
+ std::string label;
+ std::string image_file_path;
+};
+
+void AggregateImage(const std::vector<ImagePartition>& partitions,
+ const std::string& output_path);
+void CreateCompositeDisk(std::vector<ImagePartition> partitions,
+ const std::string& header_file,
+ const std::string& footer_file,
+ const std::string& output_composite_path);
+void CreateQcowOverlay(const std::string& crosvm_path,
+ const std::string& backing_file,
+ const std::string& output_overlay_path);
diff --git a/host/libs/config/mbr.h b/host/commands/assemble_cvd/mbr.h
index 3388237bc..b06a5e3f5 100644
--- a/host/libs/config/mbr.h
+++ b/host/commands/assemble_cvd/mbr.h
@@ -15,8 +15,7 @@
*/
#pragma once
-constexpr int SECTOR_SIZE_SHIFT = 9;
-constexpr int SECTOR_SIZE = 1 << SECTOR_SIZE_SHIFT;
+constexpr int SECTOR_SIZE = 512;
struct __attribute__((packed)) MbrPartitionEntry {
std::uint8_t status;
diff --git a/host/commands/assemble_cvd/misc_info.cc b/host/commands/assemble_cvd/misc_info.cc
index e96099c4d..4d5ecd58f 100644
--- a/host/commands/assemble_cvd/misc_info.cc
+++ b/host/commands/assemble_cvd/misc_info.cc
@@ -18,11 +18,8 @@
#include <algorithm>
#include <android-base/logging.h>
-#include <android-base/stringprintf.h>
#include <android-base/strings.h>
-namespace cuttlefish {
-
MiscInfo ParseMiscInfo(const std::string& misc_info_contents) {
auto lines = android::base::Split(misc_info_contents, "\n");
MiscInfo misc_info;
@@ -73,55 +70,11 @@ std::vector<std::string> SuperPartitionComponents(const MiscInfo& info) {
return components;
}
-static constexpr const char* kGoogleDynamicPartitions =
- "google_dynamic_partitions";
-static constexpr const char* kSuperPartitionGroups = "super_partition_groups";
+static const std::string kGoogleDynamicPartitions =
+ "super_google_dynamic_partitions_partition_list";
-bool SetSuperPartitionComponents(const std::vector<std::string>& components,
+void SetSuperPartitionComponents(const std::vector<std::string>& components,
MiscInfo* misc_info) {
- auto super_partition_groups = misc_info->find(kSuperPartitionGroups);
- if (super_partition_groups == misc_info->end()) {
- LOG(ERROR) << "Failed to find super partition groups in misc_info";
- return false;
- }
-
- // Remove all existing update groups in misc_info
- auto update_groups =
- android::base::Split(super_partition_groups->second, " ");
- for (const auto& group_name : update_groups) {
- auto partition_list = android::base::StringPrintf("super_%s_partition_list",
- group_name.c_str());
- auto partition_size =
- android::base::StringPrintf("super_%s_group_size", group_name.c_str());
- for (const auto& key : {partition_list, partition_size}) {
- auto it = misc_info->find(key);
- if (it == misc_info->end()) {
- LOG(ERROR) << "Failed to find " << key << " in misc_info";
- return false;
- }
- misc_info->erase(it);
- }
- }
-
- // For merged target-file, put all dynamic partitions under the
- // google_dynamic_partitions update group.
- // TODO(xunchang) use different update groups for system and vendor images.
(*misc_info)[kDynamicPartitions] = android::base::Join(components, " ");
- (*misc_info)[kSuperPartitionGroups] = kGoogleDynamicPartitions;
- std::string partitions_list_key = android::base::StringPrintf(
- "super_%s_partition_list", kGoogleDynamicPartitions);
- (*misc_info)[partitions_list_key] = android::base::Join(components, " ");
-
- // Use the entire super partition as the group size
- std::string group_size_key = android::base::StringPrintf(
- "super_%s_group_size", kGoogleDynamicPartitions);
- auto super_size_it = misc_info->find("super_partition_size");
- if (super_size_it == misc_info->end()) {
- LOG(ERROR) << "Failed to find super partition size";
- return false;
- }
- (*misc_info)[group_size_key] = super_size_it->second;
- return true;
+ (*misc_info)[kGoogleDynamicPartitions] = android::base::Join(components, " ");
}
-
-} // namespace cuttlefish
diff --git a/host/commands/assemble_cvd/misc_info.h b/host/commands/assemble_cvd/misc_info.h
index aa130bcc9..7c32e3bb2 100644
--- a/host/commands/assemble_cvd/misc_info.h
+++ b/host/commands/assemble_cvd/misc_info.h
@@ -17,9 +17,6 @@
#include <map>
#include <string>
-#include <vector>
-
-namespace cuttlefish {
using MiscInfo = std::map<std::string, std::string>;
@@ -27,7 +24,5 @@ MiscInfo ParseMiscInfo(const std::string& file_contents);
std::string WriteMiscInfo(const MiscInfo& info);
std::vector<std::string> SuperPartitionComponents(const MiscInfo&);
-bool SetSuperPartitionComponents(const std::vector<std::string>& components,
+void SetSuperPartitionComponents(const std::vector<std::string>& components,
MiscInfo* misc_info);
-
-} // namespace cuttlefish
diff --git a/host/commands/assemble_cvd/super_image_mixer.cc b/host/commands/assemble_cvd/super_image_mixer.cc
index c1e7eac0e..de6d94cd9 100644
--- a/host/commands/assemble_cvd/super_image_mixer.cc
+++ b/host/commands/assemble_cvd/super_image_mixer.cc
@@ -34,11 +34,13 @@
#include "host/libs/config/cuttlefish_config.h"
#include "host/libs/config/fetcher_config.h"
-namespace cuttlefish {
namespace {
-std::string TargetFilesZip(const FetcherConfig& fetcher_config,
- FileSource source) {
+using cvd::FileExists;
+using vsoc::DefaultHostArtifactsPath;
+
+std::string TargetFilesZip(const cvd::FetcherConfig& fetcher_config,
+ cvd::FileSource source) {
for (const auto& file_iter : fetcher_config.get_cvd_files()) {
const auto& file_path = file_iter.first;
const auto& file_info = file_iter.second;
@@ -56,13 +58,12 @@ std::string TargetFilesZip(const FetcherConfig& fetcher_config,
const std::string kMiscInfoPath = "META/misc_info.txt";
const std::set<std::string> kDefaultTargetImages = {
"IMAGES/boot.img",
+ "IMAGES/cache.img",
"IMAGES/odm.img",
- "IMAGES/odm_dlkm.img",
"IMAGES/recovery.img",
"IMAGES/userdata.img",
"IMAGES/vbmeta.img",
"IMAGES/vendor.img",
- "IMAGES/vendor_dlkm.img",
};
const std::set<std::string> kDefaultTargetBuildProp = {
"ODM/build.prop",
@@ -71,7 +72,7 @@ const std::set<std::string> kDefaultTargetBuildProp = {
"VENDOR/etc/build.prop",
};
-void FindImports(Archive* archive, const std::string& build_prop_file) {
+void FindImports(cvd::Archive* archive, const std::string& build_prop_file) {
auto contents = archive->ExtractToMemory(build_prop_file);
auto lines = android::base::Split(contents, "\n");
for (const auto& line : lines) {
@@ -85,8 +86,8 @@ void FindImports(Archive* archive, const std::string& build_prop_file) {
bool CombineTargetZipFiles(const std::string& default_target_zip,
const std::string& system_target_zip,
const std::string& output_path) {
- Archive default_target_archive(default_target_zip);
- Archive system_target_archive(system_target_zip);
+ cvd::Archive default_target_archive(default_target_zip);
+ cvd::Archive system_target_archive(system_target_zip);
auto default_target_contents = default_target_archive.Contents();
if (default_target_contents.size() == 0) {
@@ -132,27 +133,21 @@ bool CombineTargetZipFiles(const std::string& default_target_zip,
}
auto output_misc = default_misc;
auto system_super_partitions = SuperPartitionComponents(system_misc);
- // Ensure specific skipped partitions end up in the misc_info.txt
- for (auto partition : {"odm", "odm_dlkm", "vendor", "vendor_dlkm"}) {
- if (std::find(system_super_partitions.begin(), system_super_partitions.end(),
- partition) == system_super_partitions.end()) {
- system_super_partitions.push_back(partition);
- }
- }
- if (!SetSuperPartitionComponents(system_super_partitions, &output_misc)) {
- LOG(ERROR) << "Failed to update super partitions components for misc_info";
- return false;
+ if (std::find(system_super_partitions.begin(), system_super_partitions.end(),
+ "odm") == system_super_partitions.end()) {
+ // odm is not one of the partitions skipped by the system check
+ system_super_partitions.push_back("odm");
}
-
+ SetSuperPartitionComponents(system_super_partitions, &output_misc);
auto misc_output_path = output_path + "/" + kMiscInfoPath;
- SharedFD misc_output_file =
- SharedFD::Creat(misc_output_path.c_str(), 0644);
+ cvd::SharedFD misc_output_file =
+ cvd::SharedFD::Creat(misc_output_path.c_str(), 0644);
if (!misc_output_file->IsOpen()) {
LOG(ERROR) << "Failed to open output misc file: "
<< misc_output_file->StrError();
return false;
}
- if (WriteAll(misc_output_file, WriteMiscInfo(output_misc)) < 0) {
+ if (cvd::WriteAll(misc_output_file, WriteMiscInfo(output_misc)) < 0) {
LOG(ERROR) << "Failed to write output misc file contents: "
<< misc_output_file->StrError();
return false;
@@ -225,15 +220,15 @@ bool BuildSuperImage(const std::string& combined_target_zip,
build_super_image_binary =
DefaultHostArtifactsPath("otatools/bin/build_super_image");
otatools_path = DefaultHostArtifactsPath("otatools");
- } else if (FileExists(HostBinaryPath("build_super_image"))) {
+ } else if (FileExists(DefaultHostArtifactsPath("bin/build_super_image"))) {
build_super_image_binary =
- HostBinaryPath("build_super_image");
+ DefaultHostArtifactsPath("bin/build_super_image");
otatools_path = DefaultHostArtifactsPath("");
} else {
LOG(ERROR) << "Could not find otatools";
return false;
}
- return execute({
+ return cvd::execute({
build_super_image_binary,
"--path=" + otatools_path,
combined_target_zip,
@@ -243,31 +238,31 @@ bool BuildSuperImage(const std::string& combined_target_zip,
} // namespace
-bool SuperImageNeedsRebuilding(const FetcherConfig& fetcher_config,
- const CuttlefishConfig&) {
+bool SuperImageNeedsRebuilding(const cvd::FetcherConfig& fetcher_config,
+ const vsoc::CuttlefishConfig&) {
bool has_default_build = false;
bool has_system_build = false;
for (const auto& file_iter : fetcher_config.get_cvd_files()) {
- if (file_iter.second.source == FileSource::DEFAULT_BUILD) {
+ if (file_iter.second.source == cvd::FileSource::DEFAULT_BUILD) {
has_default_build = true;
- } else if (file_iter.second.source == FileSource::SYSTEM_BUILD) {
+ } else if (file_iter.second.source == cvd::FileSource::SYSTEM_BUILD) {
has_system_build = true;
}
}
return has_default_build && has_system_build;
}
-bool RebuildSuperImage(const FetcherConfig& fetcher_config,
- const CuttlefishConfig& config,
+bool RebuildSuperImage(const cvd::FetcherConfig& fetcher_config,
+ const vsoc::CuttlefishConfig& config,
const std::string& output_path) {
std::string default_target_zip =
- TargetFilesZip(fetcher_config, FileSource::DEFAULT_BUILD);
+ TargetFilesZip(fetcher_config, cvd::FileSource::DEFAULT_BUILD);
if (default_target_zip == "") {
LOG(ERROR) << "Unable to find default target zip file.";
return false;
}
std::string system_target_zip =
- TargetFilesZip(fetcher_config, FileSource::SYSTEM_BUILD);
+ TargetFilesZip(fetcher_config, cvd::FileSource::SYSTEM_BUILD);
if (system_target_zip == "") {
LOG(ERROR) << "Unable to find system target zip file.";
return false;
@@ -287,5 +282,3 @@ bool RebuildSuperImage(const FetcherConfig& fetcher_config,
}
return success;
}
-
-} // namespace cuttlefish
diff --git a/host/commands/assemble_cvd/super_image_mixer.h b/host/commands/assemble_cvd/super_image_mixer.h
index 91f2c1356..1b8c4201f 100644
--- a/host/commands/assemble_cvd/super_image_mixer.h
+++ b/host/commands/assemble_cvd/super_image_mixer.h
@@ -16,12 +16,8 @@
#include "host/libs/config/cuttlefish_config.h"
#include "host/libs/config/fetcher_config.h"
-namespace cuttlefish {
-
-bool SuperImageNeedsRebuilding(const FetcherConfig& fetcher_config,
- const CuttlefishConfig& config);
-bool RebuildSuperImage(const FetcherConfig& fetcher_config,
- const CuttlefishConfig& config,
+bool SuperImageNeedsRebuilding(const cvd::FetcherConfig& fetcher_config,
+ const vsoc::CuttlefishConfig& config);
+bool RebuildSuperImage(const cvd::FetcherConfig& fetcher_config,
+ const vsoc::CuttlefishConfig& config,
const std::string& output_path);
-
-} // namespace cuttlefish
diff --git a/host/commands/bt_connector/OWNERS b/host/commands/bt_connector/OWNERS
deleted file mode 100644
index e8a4a0030..000000000
--- a/host/commands/bt_connector/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-include platform/system/bt:/OWNERS
-jeongik@google.com \ No newline at end of file
diff --git a/host/commands/bt_connector/main.cpp b/host/commands/bt_connector/main.cpp
deleted file mode 100644
index fc17b31c2..000000000
--- a/host/commands/bt_connector/main.cpp
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (C) 2021 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 <fcntl.h>
-#include <sys/poll.h>
-#include <unistd.h>
-#include <ios>
-#include <mutex>
-
-#include <android-base/logging.h>
-#include <gflags/gflags.h>
-#include <thread>
-
-#include "common/libs/fs/shared_buf.h"
-#include "common/libs/fs/shared_fd.h"
-#include "host/libs/config/cuttlefish_config.h"
-#include "host/libs/config/logging.h"
-
-// Copied from net/bluetooth/hci.h
-#define HCI_MAX_ACL_SIZE 1024
-#define HCI_MAX_FRAME_SIZE (HCI_MAX_ACL_SIZE + 4)
-
-// Include H4 header byte, and reserve more buffer size in the case of excess
-// packet.
-constexpr const size_t kBufferSize = (HCI_MAX_FRAME_SIZE + 1) * 2;
-
-DEFINE_int32(bt_in, -1, "A pipe for bt communication");
-DEFINE_int32(bt_out, -1, "A pipe for bt communication");
-DEFINE_int32(hci_port, -1, "A port for bt hci command");
-DEFINE_int32(link_port, -1, "A pipe for bt link layer command");
-DEFINE_int32(test_port, -1, "A pipe for rootcanal test channel");
-
-void openSocket(cuttlefish::SharedFD* fd, int port) {
- static std::mutex mutex;
- std::unique_lock<std::mutex> lock(mutex);
- *fd = cuttlefish::SharedFD::SocketLocalClient(port, SOCK_STREAM);
-}
-
-int main(int argc, char** argv) {
- cuttlefish::DefaultSubprocessLogging(argv);
- gflags::ParseCommandLineFlags(&argc, &argv, true);
- auto bt_in = cuttlefish::SharedFD::Dup(FLAGS_bt_in);
- if (!bt_in->IsOpen()) {
- LOG(ERROR) << "Error dupping fd " << FLAGS_bt_in << ": "
- << bt_in->StrError();
- return 1;
- }
- close(FLAGS_bt_in);
-
- auto bt_out = cuttlefish::SharedFD::Dup(FLAGS_bt_out);
- if (!bt_out->IsOpen()) {
- LOG(ERROR) << "Error dupping fd " << FLAGS_bt_out << ": "
- << bt_out->StrError();
- return 1;
- }
- close(FLAGS_bt_out);
- cuttlefish::SharedFD sock;
- openSocket(&sock, FLAGS_hci_port);
-
- auto guest_to_host = std::thread([&]() {
- while (true) {
- char buf[kBufferSize];
- auto read = bt_in->Read(buf, sizeof(buf));
- while (cuttlefish::WriteAll(sock, buf, read) == -1) {
- LOG(ERROR) << "failed to write to socket, retry.";
- // Wait for the host process to be ready
- sleep(1);
- openSocket(&sock, FLAGS_hci_port);
- }
- }
- });
-
- auto host_to_guest = std::thread([&]() {
- while (true) {
- char buf[kBufferSize];
- auto read = sock->Read(buf, sizeof(buf));
- if (read == -1) {
- LOG(ERROR) << "failed to read from socket, retry.";
- // Wait for the host process to be ready
- sleep(1);
- openSocket(&sock, FLAGS_hci_port);
- continue;
- }
- cuttlefish::WriteAll(bt_out, buf, read);
- }
- });
- guest_to_host.join();
- host_to_guest.join();
-}
diff --git a/host/commands/config_server/Android.bp b/host/commands/config_server/Android.bp
index b567bd902..08dc1fd35 100644
--- a/host/commands/config_server/Android.bp
+++ b/host/commands/config_server/Android.bp
@@ -13,11 +13,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-cc_binary {
+cc_binary_host {
name: "config_server",
srcs: [
"main.cpp",
@@ -25,16 +21,14 @@ cc_binary {
shared_libs: [
"libbase",
"libcuttlefish_fs",
- "libjsoncpp",
"liblog",
"libcuttlefish_utils",
"libcuttlefish_device_config",
- "libcuttlefish_device_config_proto",
- "libprotobuf-cpp-full"
],
static_libs: [
"libcuttlefish_host_config",
"libgflags",
+ "libjsoncpp",
],
- defaults: ["cuttlefish_host"],
+ defaults: ["cuttlefish_host_only"],
}
diff --git a/host/commands/config_server/main.cpp b/host/commands/config_server/main.cpp
index 921084235..6db7605f2 100644
--- a/host/commands/config_server/main.cpp
+++ b/host/commands/config_server/main.cpp
@@ -27,26 +27,26 @@ DEFINE_int32(
"File descriptor to an already created vsock server. Must be specified.");
int main(int argc, char** argv) {
- cuttlefish::DefaultSubprocessLogging(argv);
+ cvd::DefaultSubprocessLogging(argv);
google::ParseCommandLineFlags(&argc, &argv, true);
- auto device_config_helper = cuttlefish::DeviceConfigHelper::Get();
+ auto device_config = cvd::DeviceConfig::Get();
- CHECK(device_config_helper) << "Could not open device config";
+ CHECK(device_config) << "Could not open device config";
- cuttlefish::SharedFD server_fd = cuttlefish::SharedFD::Dup(FLAGS_server_fd);
+ cvd::SharedFD server_fd = cvd::SharedFD::Dup(FLAGS_server_fd);
CHECK(server_fd->IsOpen()) << "Inheriting logcat server: "
<< server_fd->StrError();
// Server loop
while (true) {
- auto conn = cuttlefish::SharedFD::Accept(*server_fd);
- LOG(DEBUG) << "Connection received on configuration server";
+ auto conn = cvd::SharedFD::Accept(*server_fd);
+ LOG(INFO) << "Connection received on configuration server";
- bool succeeded = device_config_helper->SendDeviceConfig(conn);
+ bool succeeded = device_config->SendRawData(conn);
if (succeeded) {
- LOG(DEBUG) << "Successfully sent device configuration";
+ LOG(INFO) << "Successfully sent device configuration";
} else {
LOG(ERROR) << "Failed to send the device configuration: "
<< conn->StrError();
diff --git a/host/commands/console_forwarder/Android.bp b/host/commands/console_forwarder/Android.bp
index 230a0f75f..1a89e2a68 100644
--- a/host/commands/console_forwarder/Android.bp
+++ b/host/commands/console_forwarder/Android.bp
@@ -13,24 +13,20 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-cc_binary {
+cc_binary_host {
name: "console_forwarder",
srcs: [
"main.cpp",
],
shared_libs: [
"libbase",
- "libjsoncpp",
"libcuttlefish_fs",
"libcuttlefish_utils",
],
static_libs: [
"libcuttlefish_host_config",
+ "libjsoncpp",
"libgflags",
],
- defaults: ["cuttlefish_host"],
+ defaults: ["cuttlefish_host_only"],
}
diff --git a/host/commands/console_forwarder/main.cpp b/host/commands/console_forwarder/main.cpp
index df5c9f7cf..f36fd0623 100644
--- a/host/commands/console_forwarder/main.cpp
+++ b/host/commands/console_forwarder/main.cpp
@@ -14,10 +14,7 @@
* limitations under the License.
*/
-#include <termios.h>
-#include <stdlib.h>
#include <signal.h>
-#include <unistd.h>
#include <deque>
#include <thread>
@@ -38,11 +35,9 @@ DEFINE_int32(console_out_fd,
-1,
"File descriptor for the console's output channel");
-namespace cuttlefish {
-
-// Handles forwarding the serial console to a pseudo-terminal (PTY)
-// It receives a couple of fds for the console (could be the same fd twice if,
-// for example a socket_pair were used).
+// Handles forwarding the serial console to a socket.
+// It receives the socket fd along with a couple of fds for the console (could
+// be the same fd twice if, for example a socket_pair were used).
// Data available in the console's output needs to be read immediately to avoid
// the having the VMM blocked on writes to the pipe. To achieve this one thread
// takes care of (and only of) all read calls (from console output and from the
@@ -51,73 +46,35 @@ namespace cuttlefish {
// protected by a mutex.
class ConsoleForwarder {
public:
- ConsoleForwarder(std::string console_path, SharedFD console_in,
- SharedFD console_out, SharedFD console_log)
- : console_path_(console_path),
- console_in_(console_in),
- console_out_(console_out),
- console_log_(console_log) {}
+ ConsoleForwarder(cvd::SharedFD socket,
+ cvd::SharedFD console_in,
+ cvd::SharedFD console_out) : socket_(socket),
+ console_in_(console_in),
+ console_out_(console_out) {}
[[noreturn]] void StartServer() {
- // Create a new thread to handle writes to the console
+ // Create a new thread to handle writes to the console and to the any client
+ // connected to the socket.
writer_thread_ = std::thread([this]() { WriteLoop(); });
// Use the calling thread (likely the process' main thread) to handle
// reading the console's output and input from the client.
ReadLoop();
}
private:
- SharedFD OpenPTY() {
- // Remove any stale symlink to a pts device
- auto ret = unlink(console_path_.c_str());
- CHECK(!(ret < 0 && errno != ENOENT))
- << "Failed to unlink " << console_path_ << ": " << strerror(errno);
-
- auto pty = posix_openpt(O_RDWR | O_NOCTTY | O_NONBLOCK);
- CHECK(pty >= 0) << "Failed to open a PTY: " << strerror(errno);
-
- grantpt(pty);
- unlockpt(pty);
-
- // Disable all echo modes on the PTY
- struct termios termios;
- CHECK(tcgetattr(pty, &termios) >= 0)
- << "Failed to get terminal control: " << strerror(errno);
-
- termios.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
- termios.c_oflag &= ~(ONLCR);
- CHECK(tcsetattr(pty, TCSANOW, &termios) >= 0)
- << "Failed to set terminal control: " << strerror(errno);
-
- auto pty_dev_name = ptsname(pty);
- CHECK(pty_dev_name != nullptr)
- << "Failed to obtain PTY device name: " << strerror(errno);
-
- CHECK(symlink(pty_dev_name, console_path_.c_str()) >= 0)
- << "Failed to create symlink to " << pty_dev_name << " at "
- << console_path_ << ": " << strerror(errno);
-
- auto pty_shared_fd = SharedFD::Dup(pty);
- close(pty);
- CHECK(pty_shared_fd->IsOpen())
- << "Error dupping fd " << pty << ": " << pty_shared_fd->StrError();
-
- return pty_shared_fd;
- }
-
- void EnqueueWrite(std::shared_ptr<std::vector<char>> buf_ptr, SharedFD fd) {
+ void EnqueueWrite(std::vector<char> buffer, cvd::SharedFD fd) {
std::lock_guard<std::mutex> lock(write_queue_mutex_);
- write_queue_.emplace_back(fd, buf_ptr);
+ write_queue_.emplace_back(fd, std::move(buffer));
condvar_.notify_one();
}
[[noreturn]] void WriteLoop() {
while (true) {
while (!write_queue_.empty()) {
- std::shared_ptr<std::vector<char>> buf_ptr;
- SharedFD fd;
+ std::vector<char> buffer;
+ cvd::SharedFD fd;
{
std::lock_guard<std::mutex> lock(write_queue_mutex_);
auto& front = write_queue_.front();
- buf_ptr = front.second;
+ buffer = std::move(front.second);
fd = front.first;
write_queue_.pop_front();
}
@@ -125,16 +82,12 @@ class ConsoleForwarder {
// mutex lock should NOT be held while writing to avoid blocking the
// other thread.
ssize_t bytes_written = 0;
- ssize_t bytes_to_write = buf_ptr->size();
+ ssize_t bytes_to_write = buffer.size();
while (bytes_to_write > 0) {
bytes_written =
- fd->Write(buf_ptr->data() + bytes_written, bytes_to_write);
+ fd->Write(buffer.data() + bytes_written, bytes_to_write);
if (bytes_written < 0) {
- // It is expected for writes to the PTY to fail if nothing is connected
- if(fd->GetErrno() != EAGAIN) {
- LOG(ERROR) << "Error writing to fd: " << fd->StrError();
- }
-
+ LOG(ERROR) << "Error writing to fd: " << fd->StrError();
// Don't try to write from this buffer anymore, error handling will
// be done on the reading thread (failed client will be
// disconnected, on serial console failure this process will abort).
@@ -154,95 +107,116 @@ class ConsoleForwarder {
}
[[noreturn]] void ReadLoop() {
- SharedFD client_fd;
+ cvd::SharedFD client_fd;
while (true) {
- if (!client_fd->IsOpen()) {
- client_fd = OpenPTY();
+ cvd::SharedFDSet read_set;
+ if (client_fd->IsOpen()) {
+ read_set.Set(client_fd);
+ } else {
+ read_set.Set(socket_);
}
-
- SharedFDSet read_set;
read_set.Set(console_out_);
- read_set.Set(client_fd);
-
- Select(&read_set, nullptr, nullptr, nullptr);
+ cvd::Select(&read_set, nullptr, nullptr, nullptr);
if (read_set.IsSet(console_out_)) {
- std::shared_ptr<std::vector<char>> buf_ptr = std::make_shared<std::vector<char>>(4096);
- auto bytes_read = console_out_->Read(buf_ptr->data(), buf_ptr->size());
- // This is likely unrecoverable, so exit here
- CHECK(bytes_read > 0) << "Error reading from console output: "
- << console_out_->StrError();
- buf_ptr->resize(bytes_read);
- EnqueueWrite(buf_ptr, console_log_);
+ std::vector<char> buffer(4096);
+ auto bytes_read = console_out_->Read(buffer.data(), buffer.size());
+ if (bytes_read <= 0) {
+ LOG(ERROR) << "Error reading from console output: "
+ << console_out_->StrError();
+ // This is likely unrecoverable, so exit here
+ std::exit(-4);
+ }
+ buffer.resize(bytes_read);
if (client_fd->IsOpen()) {
- EnqueueWrite(buf_ptr, client_fd);
+ EnqueueWrite(std::move(buffer), client_fd);
+ }
+ }
+ if (read_set.IsSet(socket_)) {
+ // socket_ will only be included in the select call (and therefore only
+ // present in the read set) if there is no client connected, so this
+ // assignment is safe.
+ client_fd = cvd::SharedFD::Accept(*socket_);
+ if (!client_fd->IsOpen()) {
+ LOG(ERROR) << "Error accepting connection on socket: "
+ << client_fd->StrError();
}
}
if (read_set.IsSet(client_fd)) {
- std::shared_ptr<std::vector<char>> buf_ptr = std::make_shared<std::vector<char>>(4096);
- auto bytes_read = client_fd->Read(buf_ptr->data(), buf_ptr->size());
+ std::vector<char> buffer(4096);
+ auto bytes_read = client_fd->Read(buffer.data(), buffer.size());
if (bytes_read <= 0) {
- // If this happens, it's usually because the PTY controller went away
- // e.g. the user closed minicom, or killed screen, or closed kgdb. In
- // such a case, we will just re-create the PTY
LOG(ERROR) << "Error reading from client fd: "
<< client_fd->StrError();
- client_fd->Close();
+ client_fd->Close(); // ignore errors here
} else {
- buf_ptr->resize(bytes_read);
- EnqueueWrite(buf_ptr, console_in_);
+ buffer.resize(bytes_read);
+ EnqueueWrite(std::move(buffer), console_in_);
}
}
}
}
- std::string console_path_;
- SharedFD console_in_;
- SharedFD console_out_;
- SharedFD console_log_;
+ cvd::SharedFD socket_;
+ cvd::SharedFD console_in_;
+ cvd::SharedFD console_out_;
std::thread writer_thread_;
std::mutex write_queue_mutex_;
std::condition_variable condvar_;
- std::deque<std::pair<SharedFD, std::shared_ptr<std::vector<char>>>>
- write_queue_;
+ std::deque<std::pair<cvd::SharedFD, std::vector<char>>> write_queue_;
};
-int ConsoleForwarderMain(int argc, char** argv) {
- DefaultSubprocessLogging(argv);
+int main(int argc, char** argv) {
+ cvd::DefaultSubprocessLogging(argv);
::gflags::ParseCommandLineFlags(&argc, &argv, true);
- CHECK(!(FLAGS_console_in_fd < 0 || FLAGS_console_out_fd < 0))
- << "Invalid file descriptors: " << FLAGS_console_in_fd << ", "
- << FLAGS_console_out_fd;
+ if (FLAGS_console_in_fd < 0 || FLAGS_console_out_fd < 0) {
+ LOG(ERROR) << "Invalid file descriptors: " << FLAGS_console_in_fd << ", "
+ << FLAGS_console_out_fd;
+ return -1;
+ }
- auto console_in = SharedFD::Dup(FLAGS_console_in_fd);
- CHECK(console_in->IsOpen()) << "Error dupping fd " << FLAGS_console_in_fd
- << ": " << console_in->StrError();
+ auto console_in = cvd::SharedFD::Dup(FLAGS_console_in_fd);
+ close(FLAGS_console_in_fd);
+ if (!console_in->IsOpen()) {
+ LOG(ERROR) << "Error dupping fd " << FLAGS_console_in_fd << ": "
+ << console_in->StrError();
+ return -2;
+ }
close(FLAGS_console_in_fd);
- auto console_out = SharedFD::Dup(FLAGS_console_out_fd);
- CHECK(console_out->IsOpen()) << "Error dupping fd " << FLAGS_console_out_fd
- << ": " << console_out->StrError();
+ auto console_out = cvd::SharedFD::Dup(FLAGS_console_out_fd);
close(FLAGS_console_out_fd);
+ if (!console_out->IsOpen()) {
+ LOG(ERROR) << "Error dupping fd " << FLAGS_console_out_fd << ": "
+ << console_out->StrError();
+ return -2;
+ }
- auto config = CuttlefishConfig::Get();
- CHECK(config) << "Unable to get config object";
+ auto config = vsoc::CuttlefishConfig::Get();
+ if (!config) {
+ LOG(ERROR) << "Unable to get config object";
+ return -3;
+ }
auto instance = config->ForDefaultInstance();
- auto console_path = instance.console_path();
- auto console_log = instance.PerInstancePath("console_log");
- auto console_log_fd =
- SharedFD::Open(console_log.c_str(), O_CREAT | O_APPEND | O_WRONLY, 0666);
- ConsoleForwarder console_forwarder(console_path, console_in, console_out, console_log_fd);
+ auto console_socket_name = instance.console_path();
+ auto socket = cvd::SharedFD::SocketLocalServer(console_socket_name.c_str(),
+ false,
+ SOCK_STREAM,
+ 0600);
+ if (!socket->IsOpen()) {
+ LOG(ERROR) << "Failed to create console socket at " << console_socket_name
+ << ": " << socket->StrError();
+ return -5;
+ }
+
+ ConsoleForwarder console_forwarder(socket, console_in, console_out);
// Don't get a SIGPIPE from the clients
- CHECK(sigaction(SIGPIPE, nullptr, nullptr) == 0)
- << "Failed to set SIGPIPE to be ignored: " << strerror(errno);
+ if (sigaction(SIGPIPE, nullptr, nullptr) != 0) {
+ LOG(FATAL) << "Failed to set SIGPIPE to be ignored: " << strerror(errno);
+ return -6;
+ }
console_forwarder.StartServer();
}
-
-} // namespace cuttlefish
-
-int main(int argc, char** argv) {
- return cuttlefish::ConsoleForwarderMain(argc, argv);
-}
diff --git a/host/commands/cvd_host_bugreport/main.cc b/host/commands/cvd_host_bugreport/main.cc
deleted file mode 100644
index c920e7cb9..000000000
--- a/host/commands/cvd_host_bugreport/main.cc
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (C) 2021 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 <stdio.h>
-#include <fstream>
-#include <string>
-
-#include <android-base/logging.h>
-#include <android-base/strings.h>
-#include <gflags/gflags.h>
-
-#include "common/libs/fs/shared_fd.h"
-#include "common/libs/fs/shared_select.h"
-#include "common/libs/utils/files.h"
-#include "host/libs/config/cuttlefish_config.h"
-#include "ziparchive/zip_writer.h"
-
-DEFINE_string(output, "host_bugreport.zip", "Where to write the output");
-
-namespace cuttlefish {
-namespace {
-
-void SaveFile(ZipWriter& writer, const std::string& zip_path,
- const std::string& file_path) {
- writer.StartEntry(zip_path, ZipWriter::kCompress | ZipWriter::kAlign32);
- std::fstream file(file_path, std::fstream::in | std::fstream::binary);
- do {
- char data[1024 * 10];
- file.read(data, sizeof(data));
- writer.WriteBytes(data, file.gcount());
- } while (file);
- writer.FinishEntry();
- if (file.bad()) {
- LOG(ERROR) << "Error in logging " << file_path << " to " << zip_path;
- }
-}
-
-int CvdHostBugreportMain(int argc, char** argv) {
- ::android::base::InitLogging(argv, android::base::StderrLogger);
- google::ParseCommandLineFlags(&argc, &argv, true);
-
- auto config = CuttlefishConfig::Get();
- CHECK(config) << "Unable to find the config";
-
- auto out_path = FLAGS_output.c_str();
- std::unique_ptr<FILE, decltype(&fclose)> out(fopen(out_path, "wb"), &fclose);
- ZipWriter writer(out.get());
-
- auto save = [&writer, config](const std::string& path) {
- SaveFile(writer, "cuttlefish_assembly/" + path, config->AssemblyPath(path));
- };
- save("assemble_cvd.log");
- save("cuttlefish_config.json");
-
- for (const auto& instance : config->Instances()) {
- auto save = [&writer, instance](const std::string& path) {
- const auto& zip_name = instance.instance_name() + "/" + path;
- const auto& file_name = instance.PerInstancePath(path.c_str());
- SaveFile(writer, zip_name, file_name);
- };
- save("cuttlefish_config.json");
- save("disk_config.txt");
- save("kernel.log");
- save("launcher.log");
- save("logcat");
- save("metrics.log");
- auto tombstones = DirectoryContents(instance.PerInstancePath("tombstones"));
- for (const auto& tombstone : tombstones) {
- if (tombstone == "." || tombstone == "..") {
- continue;
- }
- save("tombstones/" + tombstone);
- }
- auto recordings = DirectoryContents(instance.PerInstancePath("recording"));
- for (const auto& recording : recordings) {
- if (recording == "." || recording == "..") {
- continue;
- }
- save("recording/" + recording);
- }
- }
-
- writer.Finish();
-
- LOG(INFO) << "Saved to \"" << FLAGS_output << "\"";
-
- return 0;
-}
-
-} // namespace
-} // namespace cuttlefish
-
-int main(int argc, char** argv) {
- return cuttlefish::CvdHostBugreportMain(argc, argv);
-}
diff --git a/host/commands/cvd_status/Android.bp b/host/commands/cvd_status/Android.bp
index ae48d1975..9f72e2caf 100644
--- a/host/commands/cvd_status/Android.bp
+++ b/host/commands/cvd_status/Android.bp
@@ -13,11 +13,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-cc_binary {
+cc_binary_host {
name: "cvd_status",
srcs: [
"cvd_status.cc",
@@ -26,12 +22,13 @@ cc_binary {
"libbase",
"libcuttlefish_fs",
"libcuttlefish_utils",
- "libjsoncpp",
],
static_libs: [
"libcuttlefish_host_config",
"libcuttlefish_vm_manager",
+ "libjsoncpp",
"libgflags",
+ "libxml2",
],
- defaults: ["cuttlefish_host", "cuttlefish_libicuuc"],
+ defaults: ["cuttlefish_host_only", "cuttlefish_libicuuc"],
}
diff --git a/host/commands/cvd_status/cvd_status.cc b/host/commands/cvd_status/cvd_status.cc
index 81436d474..7b2789a45 100644
--- a/host/commands/cvd_status/cvd_status.cc
+++ b/host/commands/cvd_status/cvd_status.cc
@@ -53,7 +53,7 @@ int main(int argc, char** argv) {
::android::base::InitLogging(argv, android::base::StderrLogger);
google::ParseCommandLineFlags(&argc, &argv, true);
- auto config = cuttlefish::CuttlefishConfig::Get();
+ auto config = vsoc::CuttlefishConfig::Get();
if (!config) {
LOG(ERROR) << "Failed to obtain config object";
return 1;
@@ -65,14 +65,14 @@ int main(int argc, char** argv) {
LOG(ERROR) << "No path to launcher monitor found";
return 2;
}
- auto monitor_socket = cuttlefish::SharedFD::SocketLocalClient(
- monitor_path.c_str(), false, SOCK_STREAM, FLAGS_wait_for_launcher);
+ auto monitor_socket = cvd::SharedFD::SocketLocalClient(monitor_path.c_str(),
+ false, SOCK_STREAM);
if (!monitor_socket->IsOpen()) {
LOG(ERROR) << "Unable to connect to launcher monitor at " << monitor_path
<< ": " << monitor_socket->StrError();
return 3;
}
- auto request = cuttlefish::LauncherAction::kStatus;
+ auto request = cvd::LauncherAction::kStatus;
auto bytes_sent = monitor_socket->Send(&request, sizeof(request), 0);
if (bytes_sent < 0) {
LOG(ERROR) << "Error sending launcher monitor the status command: "
@@ -80,10 +80,10 @@ int main(int argc, char** argv) {
return 4;
}
// Perform a select with a timeout to guard against launcher hanging
- cuttlefish::SharedFDSet read_set;
+ cvd::SharedFDSet read_set;
read_set.Set(monitor_socket);
struct timeval timeout = {FLAGS_wait_for_launcher, 0};
- int selected = cuttlefish::Select(&read_set, nullptr, nullptr,
+ int selected = cvd::Select(&read_set, nullptr, nullptr,
FLAGS_wait_for_launcher <= 0 ? nullptr : &timeout);
if (selected < 0){
LOG(ERROR) << "Failed communication with the launcher monitor: "
@@ -94,14 +94,14 @@ int main(int argc, char** argv) {
LOG(ERROR) << "Timeout expired waiting for launcher monitor to respond";
return 6;
}
- cuttlefish::LauncherResponse response;
+ cvd::LauncherResponse response;
auto bytes_recv = monitor_socket->Recv(&response, sizeof(response), 0);
if (bytes_recv < 0) {
LOG(ERROR) << "Error receiving response from launcher monitor: "
<< monitor_socket->StrError();
return 7;
}
- if (response != cuttlefish::LauncherResponse::kSuccess) {
+ if (response != cvd::LauncherResponse::kSuccess) {
LOG(ERROR) << "Received '" << static_cast<char>(response)
<< "' response from launcher monitor";
return 8;
diff --git a/host/commands/fetcher/Android.bp b/host/commands/fetcher/Android.bp
index fdb97ecfe..7c1e87f0a 100644
--- a/host/commands/fetcher/Android.bp
+++ b/host/commands/fetcher/Android.bp
@@ -13,11 +13,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-cc_binary {
+cc_binary_host {
name: "fetch_cvd",
srcs: [
"build_api.cc",
@@ -26,38 +22,19 @@ cc_binary {
"fetch_cvd.cc",
"install_zip.cc",
],
+ stl: "libc++_static",
static_libs: [
+ "libbase",
"libcuttlefish_host_config",
+ "libcuttlefish_fs",
+ "libcuttlefish_utils",
+ "libcurl",
+ "libcrypto",
"libgflags",
+ "liblog",
+ "libssl",
+ "libz",
+ "libjsoncpp",
],
- target: {
- host: {
- stl: "libc++_static",
- static_libs: [
- "libbase",
- "libcuttlefish_fs",
- "libcuttlefish_utils",
- "libcurl",
- "libcrypto",
- "liblog",
- "libssl",
- "libz",
- "libjsoncpp",
- ],
- },
- android: {
- shared_libs: [
- "libbase",
- "libcuttlefish_fs",
- "libcuttlefish_utils",
- "libcurl",
- "libcrypto",
- "liblog",
- "libssl",
- "libz",
- "libjsoncpp",
- ],
- },
- },
- defaults: ["cuttlefish_host"],
+ defaults: ["cuttlefish_host_only"],
}
diff --git a/host/commands/fetcher/build_api.cc b/host/commands/fetcher/build_api.cc
index 16f95db63..2722de83a 100644
--- a/host/commands/fetcher/build_api.cc
+++ b/host/commands/fetcher/build_api.cc
@@ -26,10 +26,8 @@
#include <android-base/strings.h>
#include <android-base/logging.h>
-#include "common/libs/utils/environment.h"
#include "common/libs/utils/files.h"
-namespace cuttlefish {
namespace {
const std::string BUILD_API =
@@ -74,12 +72,6 @@ std::ostream& operator<<(std::ostream& out, const Build& build) {
return out;
}
-DirectoryBuild::DirectoryBuild(const std::vector<std::string>& paths,
- const std::string& target)
- : paths(paths), target(target), id("eng") {
- product = StringFromEnv("TARGET_PRODUCT", "");
-}
-
BuildApi::BuildApi(std::unique_ptr<CredentialSource> credential_source)
: credential_source(std::move(credential_source)) {}
@@ -118,37 +110,17 @@ std::string BuildApi::BuildStatus(const DeviceBuild& build) {
return response_json["buildAttemptStatus"].asString();
}
-std::string BuildApi::ProductName(const DeviceBuild& build) {
- std::string url = BUILD_API + "/builds/" + build.id + "/" + build.target;
- auto response_json = curl.DownloadToJson(url, Headers());
- CHECK(!response_json.isMember("error")) << "Error fetching the status of "
- << "build " << build << ". Response was " << response_json;
- CHECK(response_json.isMember("target")) << "Build was missing target field.";
- return response_json["target"]["product"].asString();
-}
-
std::vector<Artifact> BuildApi::Artifacts(const DeviceBuild& build) {
- std::string page_token = "";
+ std::string url = BUILD_API + "/builds/" + build.id + "/" + build.target
+ + "/attempts/latest/artifacts?maxResults=1000";
+ auto artifacts_json = curl.DownloadToJson(url, Headers());
+ CHECK(!artifacts_json.isMember("error")) << "Error fetching the artifacts of "
+ << build << ". Response was " << artifacts_json;
+
std::vector<Artifact> artifacts;
- do {
- std::string url = BUILD_API + "/builds/" + build.id + "/" + build.target +
- "/attempts/latest/artifacts?maxResults=1000";
- if (page_token != "") {
- url += "&pageToken=" + page_token;
- }
- auto artifacts_json = curl.DownloadToJson(url, Headers());
- CHECK(!artifacts_json.isMember("error"))
- << "Error fetching the artifacts of " << build << ". Response was "
- << artifacts_json;
- if (artifacts_json.isMember("nextPageToken")) {
- page_token = artifacts_json["nextPageToken"].asString();
- } else {
- page_token = "";
- }
- for (const auto& artifact_json : artifacts_json["artifacts"]) {
- artifacts.emplace_back(artifact_json);
- }
- } while (page_token != "");
+ for (const auto& artifact_json : artifacts_json["artifacts"]) {
+ artifacts.emplace_back(artifact_json);
+ }
return artifacts;
}
@@ -175,17 +147,9 @@ std::vector<Artifact> BuildApi::Artifacts(const DirectoryBuild& build) {
bool BuildApi::ArtifactToFile(const DeviceBuild& build,
const std::string& artifact,
const std::string& path) {
- std::string download_url_endpoint =
- BUILD_API + "/builds/" + build.id + "/" + build.target +
- "/attempts/latest/artifacts/" + artifact + "/url";
- auto download_url_json =
- curl.DownloadToJson(download_url_endpoint, Headers());
- if (!download_url_json.isMember("signedUrl")) {
- LOG(ERROR) << "URL endpoint did not have json path: " << download_url_json;
- return false;
- }
- std::string url = download_url_json["signedUrl"].asString();
- return curl.DownloadToFile(url, path);
+ std::string url = BUILD_API + "/builds/" + build.id + "/" + build.target
+ + "/attempts/latest/artifacts/" + artifact + "?alt=media";
+ return curl.DownloadToFile(url, path, Headers());
}
bool BuildApi::ArtifactToFile(const DirectoryBuild& build,
@@ -193,7 +157,7 @@ bool BuildApi::ArtifactToFile(const DirectoryBuild& build,
const std::string& destination) {
for (const auto& path : build.paths) {
auto source = path + "/" + artifact;
- if (!FileExists(source)) {
+ if (!cvd::FileExists(source)) {
continue;
}
unlink(destination.c_str());
@@ -249,8 +213,5 @@ Build ArgumentToBuild(BuildApi* build_api, const std::string& arg,
status = build_api->BuildStatus(proposed_build);
}
LOG(INFO) << "Status for build " << proposed_build << " is " << status;
- proposed_build.product = build_api->ProductName(proposed_build);
return proposed_build;
}
-
-} // namespace cuttlefish
diff --git a/host/commands/fetcher/build_api.h b/host/commands/fetcher/build_api.h
index 505ad4b53..54bbd72ed 100644
--- a/host/commands/fetcher/build_api.h
+++ b/host/commands/fetcher/build_api.h
@@ -25,8 +25,6 @@
#include "credential_source.h"
#include "curl_wrapper.h"
-namespace cuttlefish {
-
class Artifact {
std::string name;
size_t size;
@@ -58,7 +56,6 @@ struct DeviceBuild {
std::string id;
std::string target;
- std::string product;
};
std::ostream& operator<<(std::ostream&, const DeviceBuild&);
@@ -66,12 +63,12 @@ std::ostream& operator<<(std::ostream&, const DeviceBuild&);
struct DirectoryBuild {
// TODO(schuffelen): Support local builds other than "eng"
DirectoryBuild(const std::vector<std::string>& paths,
- const std::string& target);
+ const std::string& target)
+ : paths(paths), target(target), id("eng") {}
std::vector<std::string> paths;
std::string target;
std::string id;
- std::string product;
};
std::ostream& operator<<(std::ostream&, const DirectoryBuild&);
@@ -94,8 +91,6 @@ public:
std::string BuildStatus(const DeviceBuild&);
- std::string ProductName(const DeviceBuild&);
-
std::vector<Artifact> Artifacts(const DeviceBuild&);
bool ArtifactToFile(const DeviceBuild& build, const std::string& artifact,
@@ -121,5 +116,3 @@ public:
Build ArgumentToBuild(BuildApi* api, const std::string& arg,
const std::string& default_build_target,
const std::chrono::seconds& retry_period);
-
-} // namespace cuttlefish
diff --git a/host/commands/fetcher/credential_source.cc b/host/commands/fetcher/credential_source.cc
index 0144e2d4b..2d2873dcb 100644
--- a/host/commands/fetcher/credential_source.cc
+++ b/host/commands/fetcher/credential_source.cc
@@ -17,7 +17,6 @@
#include <android-base/logging.h>
-namespace cuttlefish {
namespace {
std::chrono::steady_clock::duration REFRESH_WINDOW =
@@ -25,7 +24,7 @@ std::chrono::steady_clock::duration REFRESH_WINDOW =
std::string REFRESH_URL = "http://metadata.google.internal/computeMetadata/"
"v1/instance/service-accounts/default/token";
-} // namespace
+}
GceMetadataCredentialSource::GceMetadataCredentialSource() {
latest_credential = "";
@@ -73,5 +72,3 @@ std::unique_ptr<CredentialSource> FixedCredentialSource::make(
const std::string& credential) {
return std::unique_ptr<CredentialSource>(new FixedCredentialSource(credential));
}
-
-} // namespace cuttlefish
diff --git a/host/commands/fetcher/credential_source.h b/host/commands/fetcher/credential_source.h
index 78ec51ad3..fa82eab83 100644
--- a/host/commands/fetcher/credential_source.h
+++ b/host/commands/fetcher/credential_source.h
@@ -20,8 +20,6 @@
#include "curl_wrapper.h"
-namespace cuttlefish {
-
class CredentialSource {
public:
virtual ~CredentialSource() = default;
@@ -52,5 +50,3 @@ public:
static std::unique_ptr<CredentialSource> make(const std::string& credential);
};
-
-}
diff --git a/host/commands/fetcher/curl_wrapper.cc b/host/commands/fetcher/curl_wrapper.cc
index c32f4cee3..62af9126a 100644
--- a/host/commands/fetcher/curl_wrapper.cc
+++ b/host/commands/fetcher/curl_wrapper.cc
@@ -24,7 +24,6 @@
#include <curl/curl.h>
#include <json/json.h>
-namespace cuttlefish {
namespace {
size_t file_write_callback(char *ptr, size_t, size_t nmemb, void *userdata) {
@@ -146,16 +145,12 @@ Json::Value CurlWrapper::DownloadToJson(const std::string& url) {
Json::Value CurlWrapper::DownloadToJson(const std::string& url,
const std::vector<std::string>& headers) {
std::string contents = DownloadToString(url, headers);
- Json::CharReaderBuilder builder;
- std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
+ Json::Reader reader;
Json::Value json;
- std::string errorMessage;
- if (!reader->parse(&*contents.begin(), &*contents.end(), &json, &errorMessage)) {
- LOG(ERROR) << "Could not parse json: " << errorMessage;
+ if (!reader.parse(contents, json)) {
+ LOG(ERROR) << "Could not parse json: " << reader.getFormattedErrorMessages();
json["error"] = "Failed to parse json.";
json["response"] = contents;
}
return json;
}
-
-}
diff --git a/host/commands/fetcher/curl_wrapper.h b/host/commands/fetcher/curl_wrapper.h
index 6d3a2cb0f..5a5ba9c07 100644
--- a/host/commands/fetcher/curl_wrapper.h
+++ b/host/commands/fetcher/curl_wrapper.h
@@ -20,8 +20,6 @@
#include <curl/curl.h>
#include <json/json.h>
-namespace cuttlefish {
-
class CurlWrapper {
CURL* curl;
public:
@@ -41,5 +39,3 @@ public:
Json::Value DownloadToJson(const std::string& url,
const std::vector<std::string>& headers);
};
-
-}
diff --git a/host/commands/fetcher/fetch_cvd.cc b/host/commands/fetcher/fetch_cvd.cc
index b84fbbaeb..42ce8758b 100644
--- a/host/commands/fetcher/fetch_cvd.cc
+++ b/host/commands/fetcher/fetch_cvd.cc
@@ -20,9 +20,8 @@
#include <sys/stat.h>
#include <unistd.h>
-#include "android-base/logging.h"
-#include "android-base/strings.h"
#include "gflags/gflags.h"
+#include <android-base/logging.h>
#include "common/libs/fs/shared_fd.h"
#include "common/libs/utils/archive.h"
@@ -38,16 +37,14 @@
namespace {
const std::string DEFAULT_BRANCH = "aosp-master";
-const std::string DEFAULT_BUILD_TARGET = "aosp_cf_x86_64_phone-userdebug";
-}
+const std::string DEFAULT_BUILD_TARGET = "aosp_cf_x86_phone-userdebug";
-using cuttlefish::CurrentDirectory;
+}
DEFINE_string(default_build, DEFAULT_BRANCH + "/" + DEFAULT_BUILD_TARGET,
"source for the cuttlefish build to use (vendor.img + host)");
DEFINE_string(system_build, "", "source for system.img and product.img");
DEFINE_string(kernel_build, "", "source for the kernel or gki target");
-DEFINE_string(bootloader_build, "", "source for the bootloader target");
DEFINE_string(otatools_build, "", "source for the host ota tools");
DEFINE_bool(download_img_zip, true, "Whether to fetch the -img-*.zip file.");
@@ -55,13 +52,12 @@ DEFINE_bool(download_target_files_zip, false, "Whether to fetch the "
"-target_files-*.zip file.");
DEFINE_string(credential_source, "", "Build API credential source");
-DEFINE_string(directory, CurrentDirectory(), "Target directory to fetch "
- "files into");
+DEFINE_string(directory, cvd::CurrentDirectory(), "Target directory to fetch "
+ "files into");
DEFINE_bool(run_next_stage, false, "Continue running the device through the next stage.");
DEFINE_string(wait_retry_period, "20", "Retry period for pending builds given "
"in seconds. Set to 0 to not wait.");
-namespace cuttlefish {
namespace {
const std::string HOST_TOOLS = "cvd-host_package.tar.gz";
@@ -76,9 +72,13 @@ const std::string OTA_TOOLS_DIR = "/otatools/";
std::string TargetBuildZipFromArtifacts(
const Build& build, const std::string& name,
const std::vector<Artifact>& artifacts) {
- std::string product = std::visit([](auto&& arg) { return arg.product; }, build);
+ std::string target = std::visit([](auto&& arg) { return arg.target; }, build);
+ size_t dash_pos = target.find('-');
+ if (dash_pos != std::string::npos) {
+ target.replace(dash_pos, target.size() - dash_pos, "");
+ }
auto id = std::visit([](auto&& arg) { return arg.id; }, build);
- auto match = product + "-" + name + "-" + id;
+ auto match = target + "-" + name + "-" + id;
for (const auto& artifact : artifacts) {
if (artifact.Name().find(match) != std::string::npos) {
return artifact.Name();
@@ -159,7 +159,7 @@ std::vector<std::string> download_host_package(BuildApi* build_api,
return {};
}
- Archive archive(local_path);
+ cvd::Archive archive(local_path);
if (!archive.ExtractAll(target_directory)) {
LOG(ERROR) << "Could not extract " << local_path;
return {};
@@ -196,11 +196,11 @@ std::vector<std::string> download_ota_tools(BuildApi* build_api,
}
std::string otatools_dir = target_directory + OTA_TOOLS_DIR;
- if (!DirectoryExists(otatools_dir) && mkdir(otatools_dir.c_str(), 0777) != 0) {
+ if (!cvd::DirectoryExists(otatools_dir) && mkdir(otatools_dir.c_str(), 0777) != 0) {
LOG(ERROR) << "Could not create " << otatools_dir;
return {};
}
- Archive archive(local_path);
+ cvd::Archive archive(local_path);
if (!archive.ExtractAll(otatools_dir)) {
LOG(ERROR) << "Could not extract " << local_path;
return {};
@@ -213,24 +213,14 @@ std::vector<std::string> download_ota_tools(BuildApi* build_api,
return files;
}
-void AddFilesToConfig(FileSource purpose, const Build& build,
- const std::vector<std::string>& paths,
- FetcherConfig* config,
- const std::string& directory_prefix,
+void AddFilesToConfig(cvd::FileSource purpose, const Build& build,
+ const std::vector<std::string>& paths, cvd::FetcherConfig* config,
bool override_entry = false) {
for (const std::string& path : paths) {
- std::string_view local_path(path);
- if (!android::base::ConsumePrefix(&local_path, directory_prefix)) {
- LOG(ERROR) << "Failed to remove prefix " << directory_prefix << " from "
- << local_path;
- }
- while (android::base::StartsWith(local_path, "/")) {
- android::base::ConsumePrefix(&local_path, "/");
- }
// TODO(schuffelen): Do better for local builds here.
auto id = std::visit([](auto&& arg) { return arg.id; }, build);
auto target = std::visit([](auto&& arg) { return arg.target; }, build);
- CvdFile file(purpose, id, target, std::string(local_path));
+ cvd::CvdFile file(purpose, id, target, path);
bool added = config->add_cvd_file(file, override_entry);
if (!added) {
LOG(ERROR) << "Duplicate file " << file;
@@ -251,19 +241,18 @@ std::string USAGE_MESSAGE =
} // namespace
-int FetchCvdMain(int argc, char** argv) {
+int main(int argc, char** argv) {
::android::base::InitLogging(argv, android::base::StderrLogger);
gflags::SetUsageMessage(USAGE_MESSAGE);
gflags::ParseCommandLineFlags(&argc, &argv, true);
- FetcherConfig config;
+ cvd::FetcherConfig config;
config.RecordFlags();
- std::string target_dir = AbsolutePath(FLAGS_directory);
- if (!DirectoryExists(target_dir) && mkdir(target_dir.c_str(), 0777) != 0) {
+ std::string target_dir = cvd::AbsolutePath(FLAGS_directory);
+ if (!cvd::DirectoryExists(target_dir) && mkdir(target_dir.c_str(), 0777) != 0) {
LOG(FATAL) << "Could not create " << target_dir;
}
- std::string target_dir_slash = target_dir;
std::chrono::seconds retry_period(std::stoi(FLAGS_wait_retry_period));
curl_global_init(CURL_GLOBAL_DEFAULT);
@@ -285,8 +274,7 @@ int FetchCvdMain(int argc, char** argv) {
if (host_package_files.empty()) {
LOG(FATAL) << "Could not download host package for " << default_build;
}
- AddFilesToConfig(FileSource::DEFAULT_BUILD, default_build,
- host_package_files, &config, target_dir);
+ AddFilesToConfig(cvd::FileSource::DEFAULT_BUILD, default_build, host_package_files, &config);
if (FLAGS_system_build != "" || FLAGS_kernel_build != "" || FLAGS_otatools_build != "") {
auto ota_build = default_build;
@@ -299,8 +287,7 @@ int FetchCvdMain(int argc, char** argv) {
if (ota_tools_files.empty()) {
LOG(FATAL) << "Could not download ota tools for " << ota_build;
}
- AddFilesToConfig(FileSource::DEFAULT_BUILD, default_build,
- ota_tools_files, &config, target_dir);
+ AddFilesToConfig(cvd::FileSource::DEFAULT_BUILD, default_build, ota_tools_files, &config);
}
if (FLAGS_download_img_zip) {
std::vector<std::string> image_files =
@@ -312,8 +299,7 @@ int FetchCvdMain(int argc, char** argv) {
for (auto& file : image_files) {
LOG(INFO) << file;
}
- AddFilesToConfig(FileSource::DEFAULT_BUILD, default_build, image_files,
- &config, target_dir);
+ AddFilesToConfig(cvd::FileSource::DEFAULT_BUILD, default_build, image_files, &config);
}
if (FLAGS_system_build != "" || FLAGS_download_target_files_zip) {
std::string default_target_dir = target_dir + "/default";
@@ -326,8 +312,7 @@ int FetchCvdMain(int argc, char** argv) {
LOG(FATAL) << "Could not download target files for " << default_build;
}
LOG(INFO) << "Adding target files for default build";
- AddFilesToConfig(FileSource::DEFAULT_BUILD, default_build, target_files,
- &config, target_dir);
+ AddFilesToConfig(cvd::FileSource::DEFAULT_BUILD, default_build, target_files, &config);
}
if (FLAGS_system_build != "") {
@@ -337,17 +322,16 @@ int FetchCvdMain(int argc, char** argv) {
bool system_in_img_zip = true;
if (FLAGS_download_img_zip) {
std::vector<std::string> image_files =
- download_images(&build_api, system_build, target_dir,
- {"system.img", "product.img"});
+ download_images(&build_api, system_build, target_dir, {"system.img"});
if (image_files.empty()) {
LOG(INFO) << "Could not find system image for " << system_build
<< "in the img zip. Assuming a super image build, which will "
- << "get the system image from the target zip.";
+ << "get the super image from the target zip.";
system_in_img_zip = false;
} else {
LOG(INFO) << "Adding img-zip files for system build";
- AddFilesToConfig(FileSource::SYSTEM_BUILD, system_build, image_files,
- &config, target_dir, true);
+ AddFilesToConfig(cvd::FileSource::SYSTEM_BUILD, system_build, image_files,
+ &config, true);
}
}
std::string system_target_dir = target_dir + "/system";
@@ -360,55 +344,29 @@ int FetchCvdMain(int argc, char** argv) {
LOG(FATAL) << "Could not download target files for " << system_build;
return -1;
}
- AddFilesToConfig(FileSource::SYSTEM_BUILD, system_build, target_files,
- &config, target_dir);
+ AddFilesToConfig(cvd::FileSource::SYSTEM_BUILD, system_build, target_files, &config);
if (!system_in_img_zip) {
- if (ExtractImages(target_files[0], target_dir, {"IMAGES/system.img"})
- != std::vector<std::string>{}) {
- std::string extracted_system = target_dir + "/IMAGES/system.img";
- std::string target_system = target_dir + "/system.img";
- if (rename(extracted_system.c_str(), target_system.c_str())) {
- int error_num = errno;
- LOG(FATAL) << "Could not replace system.img in target directory: "
- << strerror(error_num);
- return -1;
- }
- } else {
- LOG(FATAL) << "Could not get system.img from the target zip";
+ std::vector<std::string> wanted_images = {"IMAGES/system.img", "IMAGES/product.img"};
+ auto images = ExtractImages(target_files[0], target_dir, wanted_images);
+ if (images.size() != 2) {
+ LOG(FATAL) << "Could not get system.img, product.img from target zip";
return -1;
}
- if (ExtractImages(target_files[0], target_dir, {"IMAGES/product.img"})
- != std::vector<std::string>{}) {
- std::string extracted_product = target_dir + "/IMAGES/product.img";
- std::string target_product = target_dir + "/product.img";
- if (rename(extracted_product.c_str(), target_product.c_str())) {
- int error_num = errno;
- LOG(FATAL) << "Could not replace product.img in target directory"
- << strerror(error_num);
- return -1;
- }
- }
- if (ExtractImages(target_files[0], target_dir, {"IMAGES/system_ext.img"})
- != std::vector<std::string>{}) {
- std::string extracted_system_ext = target_dir + "/IMAGES/system_ext.img";
- std::string target_system_ext = target_dir + "/system_ext.img";
- if (rename(extracted_system_ext.c_str(), target_system_ext.c_str())) {
- int error_num = errno;
- LOG(FATAL) << "Could not move system_ext.img in target directory: "
- << strerror(error_num);
- return -1;
- }
+ std::string extracted_system = target_dir + "/IMAGES/system.img";
+ std::string target_system = target_dir + "/system.img";
+ if (rename(extracted_system.c_str(), target_system.c_str())) {
+ int error_num = errno;
+ LOG(FATAL) << "Could not replace system.img in target directory: "
+ << strerror(error_num);
+ return -1;
}
- if (ExtractImages(target_files[0], target_dir, {"IMAGES/vbmeta_system.img"})
- != std::vector<std::string>{}) {
- std::string extracted_vbmeta_system = target_dir + "/IMAGES/vbmeta_system.img";
- std::string target_vbmeta_system = target_dir + "/vbmeta_system.img";
- if (rename(extracted_vbmeta_system.c_str(), target_vbmeta_system.c_str())) {
- int error_num = errno;
- LOG(FATAL) << "Could not move vbmeta_system.img in target directory: "
- << strerror(error_num);
- return -1;
- }
+ std::string extracted_product = target_dir + "/IMAGES/product.img";
+ std::string target_product = target_dir + "/product.img";
+ if (rename(extracted_product.c_str(), target_product.c_str())) {
+ int error_num = errno;
+ LOG(FATAL) << "Could not replace product.img in target directory"
+ << strerror(error_num);
+ return -1;
}
// This should technically call AddFilesToConfig with the produced files,
// but it will conflict with the ones produced from the default system image
@@ -422,14 +380,7 @@ int FetchCvdMain(int argc, char** argv) {
std::string local_path = target_dir + "/kernel";
if (build_api.ArtifactToFile(kernel_build, "bzImage", local_path)) {
- AddFilesToConfig(FileSource::KERNEL_BUILD, kernel_build, {local_path},
- &config, target_dir);
- }
- // If the kernel is from an arm/aarch64 build, the artifact will be called
- // Image.
- else if (build_api.ArtifactToFile(kernel_build, "Image", local_path)) {
- AddFilesToConfig(FileSource::KERNEL_BUILD, kernel_build, {local_path},
- &config, target_dir);
+ AddFilesToConfig(cvd::FileSource::KERNEL_BUILD, kernel_build, {local_path}, &config);
} else {
LOG(FATAL) << "Could not download " << kernel_build << ":bzImage to "
<< local_path;
@@ -445,31 +396,8 @@ int FetchCvdMain(int argc, char** argv) {
LOG(FATAL) << "Could not download " << kernel_build << ":initramfs.img to "
<< target_dir + "/initramfs.img";
}
- AddFilesToConfig(FileSource::KERNEL_BUILD, kernel_build,
- {target_dir + "/initramfs.img"}, &config, target_dir);
- }
- }
-
- if (FLAGS_bootloader_build != "") {
- auto bootloader_build = ArgumentToBuild(&build_api,
- FLAGS_bootloader_build,
- "u-boot_crosvm_x86_64",
- retry_period);
-
- std::string local_path = target_dir + "/bootloader";
- if (build_api.ArtifactToFile(bootloader_build, "u-boot.rom", local_path)) {
- AddFilesToConfig(FileSource::BOOTLOADER_BUILD, bootloader_build,
- {local_path}, &config, target_dir, true);
- }
- // If the bootloader is from an arm/aarch64 build, the artifact will be of
- // filetype bin.
- else if (build_api.ArtifactToFile(bootloader_build, "u-boot.bin",
- local_path)) {
- AddFilesToConfig(FileSource::BOOTLOADER_BUILD, bootloader_build,
- {local_path}, &config, target_dir, true);
- } else {
- LOG(FATAL) << "Could not download " << bootloader_build << ":u-boot.rom to "
- << local_path;
+ AddFilesToConfig(cvd::FileSource::KERNEL_BUILD, kernel_build,
+ {target_dir + "/initramfs.img"}, &config);
}
}
}
@@ -479,12 +407,11 @@ int FetchCvdMain(int argc, char** argv) {
// their own build id. So it's unclear which build number fetch_cvd itself was built at.
// https://android.googlesource.com/platform/build/+/979c9f3/Changes.md#build_number
std::string fetcher_path = target_dir + "/fetcher_config.json";
- AddFilesToConfig(GENERATED, DeviceBuild("", ""), {fetcher_path}, &config,
- target_dir);
+ AddFilesToConfig(cvd::GENERATED, DeviceBuild("", ""), {fetcher_path}, &config);
config.SaveToFile(fetcher_path);
for (const auto& file : config.get_cvd_files()) {
- std::cout << target_dir << "/" << file.second.file_path << "\n";
+ std::cout << file.second.file_path << "\n";
}
std::cout << std::flush;
@@ -494,15 +421,15 @@ int FetchCvdMain(int argc, char** argv) {
// Ignore return code. We want to make sure there is no running instance,
// and stop_cvd will exit with an error code if there is already no running instance.
- Command stop_cmd(target_dir + "/bin/stop_cvd");
- stop_cmd.RedirectStdIO(Subprocess::StdIOChannel::kStdOut,
- Subprocess::StdIOChannel::kStdErr);
+ cvd::Command stop_cmd(target_dir + "/bin/stop_cvd");
+ stop_cmd.RedirectStdIO(cvd::Subprocess::StdIOChannel::kStdOut,
+ cvd::Subprocess::StdIOChannel::kStdErr);
stop_cmd.Start().Wait();
// gflags::ParseCommandLineFlags will remove fetch_cvd's flags from this.
// This depends the remove_flags argument (3rd) is "true".
- auto filelist_fd = SharedFD::MemfdCreate("files_list");
+ auto filelist_fd = cvd::SharedFD::MemfdCreate("files_list");
if (!filelist_fd->IsOpen()) {
LOG(FATAL) << "Unable to create temp file to write file list. "
<< filelist_fd->StrError() << " (" << filelist_fd->GetErrno() << ")";
@@ -541,12 +468,4 @@ int FetchCvdMain(int argc, char** argv) {
execv(next_stage.c_str(), const_cast<char* const*>(next_stage_argv.data()));
int error = errno;
LOG(FATAL) << "execv returned with errno " << error << ":" << strerror(error);
-
- return -1;
-}
-
-} // namespace cuttlefish
-
-int main(int argc, char** argv) {
- return cuttlefish::FetchCvdMain(argc, argv);
}
diff --git a/host/commands/fetcher/install_zip.cc b/host/commands/fetcher/install_zip.cc
index 624c41911..7933000c8 100644
--- a/host/commands/fetcher/install_zip.cc
+++ b/host/commands/fetcher/install_zip.cc
@@ -29,7 +29,7 @@
std::vector<std::string> ExtractImages(const std::string& archive_file,
const std::string& target_directory,
const std::vector<std::string>& images) {
- cuttlefish::Archive archive(archive_file);
+ cvd::Archive archive(archive_file);
bool extracted =
images.size() > 0
? archive.ExtractFiles(images, target_directory)
diff --git a/host/commands/gnss_grpc_proxy/Android.bp b/host/commands/gnss_grpc_proxy/Android.bp
deleted file mode 100644
index e85a91942..000000000
--- a/host/commands/gnss_grpc_proxy/Android.bp
+++ /dev/null
@@ -1,91 +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.
-
-
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-cc_binary {
- name: "gnss_grpc_proxy",
- srcs: [
- "gnss_grpc_proxy.cpp",
- ],
- cflags: [
- "-Wno-unused-parameter",
- "-D_XOPEN_SOURCE",
- ],
- generated_headers: [
- "GnssGrpcProxyStub_h",
- ],
- generated_sources: [
- "GnssGrpcProxyStub_cc",
- ],
- shared_libs: [
- "libbase",
- "libcuttlefish_fs",
- "libcuttlefish_utils",
- "libjsoncpp",
- "libprotobuf-cpp-full",
- "libgrpc++_unsecure",
- ],
- static_libs: [
- "libcuttlefish_host_config",
- "libgflags",
- ],
- defaults: ["cuttlefish_host"],
- include_dirs: [
- "external/grpc-grpc/include",
- "external/protobuf/src",
- ],
-}
-
-filegroup {
- name: "GnssGrpcProxyProto",
- srcs: [
- "gnss_grpc_proxy.proto",
- ],
-}
-
-genrule {
- name: "GnssGrpcProxyStub_h",
- tools: [
- "aprotoc",
- "protoc-gen-grpc-cpp-plugin",
- ],
- cmd: "$(location aprotoc) -Idevice/google/cuttlefish/host/commands/gnss_grpc_proxy -Iexternal/protobuf/src --plugin=protoc-gen-grpc=$(location protoc-gen-grpc-cpp-plugin) $(in) --grpc_out=$(genDir) --cpp_out=$(genDir)",
- srcs: [
- ":GnssGrpcProxyProto",
- ],
- out: [
- "gnss_grpc_proxy.grpc.pb.h",
- "gnss_grpc_proxy.pb.h",
- ],
-}
-
-genrule {
- name: "GnssGrpcProxyStub_cc",
- tools: [
- "aprotoc",
- "protoc-gen-grpc-cpp-plugin",
- ],
- cmd: "$(location aprotoc) -Idevice/google/cuttlefish/host/commands/gnss_grpc_proxy -Iexternal/protobuf/src --plugin=protoc-gen-grpc=$(location protoc-gen-grpc-cpp-plugin) $(in) --grpc_out=$(genDir) --cpp_out=$(genDir)",
- srcs: [
- ":GnssGrpcProxyProto",
- ],
- out: [
- "gnss_grpc_proxy.grpc.pb.cc",
- "gnss_grpc_proxy.pb.cc",
- ],
-}
diff --git a/host/commands/gnss_grpc_proxy/gnss_grpc_proxy.cpp b/host/commands/gnss_grpc_proxy/gnss_grpc_proxy.cpp
deleted file mode 100644
index ff8e54e04..000000000
--- a/host/commands/gnss_grpc_proxy/gnss_grpc_proxy.cpp
+++ /dev/null
@@ -1,235 +0,0 @@
-/*
- * Copyright (C) 2020 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 <iostream>
-#include <fstream>
-#include <memory>
-#include <string>
-
-#include <grpcpp.h>
-
-#include "gnss_grpc_proxy.grpc.pb.h"
-
-#include <signal.h>
-
-#include <chrono>
-#include <deque>
-#include <mutex>
-#include <thread>
-#include <vector>
-
-#include <gflags/gflags.h>
-#include <android-base/logging.h>
-
-#include <common/libs/fs/shared_fd.h>
-#include <common/libs/fs/shared_buf.h>
-#include <common/libs/fs/shared_select.h>
-#include <host/libs/config/cuttlefish_config.h>
-
-using grpc::Server;
-using grpc::ServerBuilder;
-using grpc::ServerContext;
-using grpc::Status;
-using gnss_grpc_proxy::SendNmeaRequest;
-using gnss_grpc_proxy::SendNmeaReply;
-using gnss_grpc_proxy::GnssGrpcProxy;
-
-DEFINE_int32(gnss_in_fd,
- -1,
- "File descriptor for the gnss's input channel");
-DEFINE_int32(gnss_out_fd,
- -1,
- "File descriptor for the gnss's output channel");
-
-DEFINE_int32(gnss_grpc_port,
- -1,
- "Service port for gnss grpc");
-
-DEFINE_string(gnss_file_path,
- "",
- "NMEA file path for gnss grpc");
-
-constexpr char CMD_GET_LOCATION[] = "CMD_GET_LOCATION";
-constexpr uint32_t GNSS_SERIAL_BUFFER_SIZE = 4096;
-// Logic and data behind the server's behavior.
-class GnssGrpcProxyServiceImpl final : public GnssGrpcProxy::Service {
- public:
- GnssGrpcProxyServiceImpl(cuttlefish::SharedFD gnss_in,
- cuttlefish::SharedFD gnss_out) : gnss_in_(gnss_in),
- gnss_out_(gnss_out) {}
- Status SendNmea(ServerContext* context, const SendNmeaRequest* request,
- SendNmeaReply* reply) override {
- reply->set_reply("Received nmea record.");
-
- auto buffer = request->nmea();
- std::lock_guard<std::mutex> lock(cached_nmea_mutex);
- cached_nmea = request->nmea();
- return Status::OK;
- }
-
- void sendToSerial() {
- LOG(DEBUG) << "Send NMEA to serial:" << cached_nmea;
- std::lock_guard<std::mutex> lock(cached_nmea_mutex);
- ssize_t bytes_written = cuttlefish::WriteAll(gnss_in_, cached_nmea);
- if (bytes_written < 0) {
- LOG(ERROR) << "Error writing to fd: " << gnss_in_->StrError();
- }
- }
-
- void StartServer() {
- // Create a new thread to handle writes to the gnss and to the any client
- // connected to the socket.
- read_thread_ = std::thread([this]() { ReadLoop(); });
- }
-
- void StartReadFileThread() {
- // Create a new thread to handle writes to the gnss and to the any client
- // connected to the socket.
- file_read_thread_ = std::thread([this]() { ReadNmeaFromLocalFile(); });
- }
-
- void ReadNmeaFromLocalFile() {
- std::ifstream file(FLAGS_gnss_file_path);
- if (file.is_open()) {
- std::string line;
- std::string lastLine;
- int count = 0;
- while (std::getline(file, line)) {
- count++;
- /* Only support a lite version of NEMA format to make it simple.
- * Records will only contains $GPGGA, $GPRMC,
- * $GPGGA,213204.00,3725.371240,N,12205.589239,W,7,,0.38,-26.75,M,0.0,M,0.0,0000*78
- * $GPRMC,213204.00,A,3725.371240,N,12205.589239,W,000.0,000.0,290819,,,A*49
- * $GPGGA,....
- * $GPRMC,....
- * Sending at 1Hz, currently user should
- * provide a NMEA file that has one location per second. need some extra work
- * to make it more generic, i.e. align with the timestamp in the file.
- */
- if (count % 2 == 0) {
- {
- std::lock_guard<std::mutex> lock(cached_nmea_mutex);
- cached_nmea = lastLine + '\n' + line;
- }
- std::this_thread::sleep_for(std::chrono::milliseconds(1000));
- }
- lastLine = line;
- }
- file.close();
- } else {
- LOG(ERROR) << "Can not open NMEA file: " << FLAGS_gnss_file_path ;
- return;
- }
- }
- private:
- [[noreturn]] void ReadLoop() {
- cuttlefish::SharedFDSet read_set;
- read_set.Set(gnss_out_);
- std::vector<char> buffer(GNSS_SERIAL_BUFFER_SIZE);
- int total_read = 0;
- std::string gnss_cmd_str;
- int flags = gnss_out_->Fcntl(F_GETFL, 0);
- gnss_out_->Fcntl(F_SETFL, flags | O_NONBLOCK);
- while (true) {
- auto bytes_read = gnss_out_->Read(buffer.data(), buffer.size());
- if (bytes_read > 0) {
- std::string s(buffer.data(), bytes_read);
- gnss_cmd_str += s;
- // In case random string sent though /dev/gnss0, gnss_cmd_str will auto resize,
- // to get rid of first page.
- if (gnss_cmd_str.size() > GNSS_SERIAL_BUFFER_SIZE * 2) {
- gnss_cmd_str = gnss_cmd_str.substr(gnss_cmd_str.size() - GNSS_SERIAL_BUFFER_SIZE);
- }
- total_read += bytes_read;
- if (gnss_cmd_str.find(CMD_GET_LOCATION) != std::string::npos) {
- sendToSerial();
- gnss_cmd_str = "";
- total_read = 0;
- }
- } else {
- if (gnss_out_->GetErrno() == EAGAIN|| gnss_out_->GetErrno() == EWOULDBLOCK) {
- std::this_thread::sleep_for(std::chrono::milliseconds(100));
- } else {
- LOG(ERROR) << "Error reading fd " << FLAGS_gnss_out_fd << ": "
- << " Error code: " << gnss_out_->GetErrno()
- << " Error sg:" << gnss_out_->StrError();
- }
- }
- }
- }
-
- cuttlefish::SharedFD gnss_in_;
- cuttlefish::SharedFD gnss_out_;
- std::thread read_thread_;
- std::thread file_read_thread_;
- std::string cached_nmea;
- std::mutex cached_nmea_mutex;
-};
-
-void RunServer() {
- auto gnss_in = cuttlefish::SharedFD::Dup(FLAGS_gnss_in_fd);
- close(FLAGS_gnss_in_fd);
- if (!gnss_in->IsOpen()) {
- LOG(ERROR) << "Error dupping fd " << FLAGS_gnss_in_fd << ": "
- << gnss_in->StrError();
- return;
- }
- close(FLAGS_gnss_in_fd);
-
- auto gnss_out = cuttlefish::SharedFD::Dup(FLAGS_gnss_out_fd);
- close(FLAGS_gnss_out_fd);
- if (!gnss_out->IsOpen()) {
- LOG(ERROR) << "Error dupping fd " << FLAGS_gnss_out_fd << ": "
- << gnss_out->StrError();
- return;
- }
- auto server_address("0.0.0.0:" + std::to_string(FLAGS_gnss_grpc_port));
- GnssGrpcProxyServiceImpl service(gnss_in, gnss_out);
- service.StartServer();
- if (!FLAGS_gnss_file_path.empty()) {
- service.StartReadFileThread();
- // In the local mode, we are not start a grpc server, use a infinite loop instead
- while(true) {
- std::this_thread::sleep_for(std::chrono::milliseconds(2000));
- }
- } else {
- ServerBuilder builder;
- // Listen on the given address without any authentication mechanism.
- builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());
- // Register "service" as the instance through which we'll communicate with
- // clients. In this case it corresponds to an *synchronous* service.
- builder.RegisterService(&service);
- // Finally assemble the server.
- std::unique_ptr<Server> server(builder.BuildAndStart());
- std::cout << "Server listening on " << server_address << std::endl;
-
- // Wait for the server to shutdown. Note that some other thread must be
- // responsible for shutting down the server for this call to ever return.
- server->Wait();
- }
-
-}
-
-
-int main(int argc, char** argv) {
- ::android::base::InitLogging(argv, android::base::StderrLogger);
- ::gflags::ParseCommandLineFlags(&argc, &argv, true);
-
- LOG(DEBUG) << "Starting gnss grpc proxy server...";
- RunServer();
-
- return 0;
-}
diff --git a/host/commands/gnss_grpc_proxy/gnss_grpc_proxy.proto b/host/commands/gnss_grpc_proxy/gnss_grpc_proxy.proto
deleted file mode 100644
index 2a12d2d2b..000000000
--- a/host/commands/gnss_grpc_proxy/gnss_grpc_proxy.proto
+++ /dev/null
@@ -1,19 +0,0 @@
-syntax = "proto3";
-
-package gnss_grpc_proxy;
-
-// The greeting service definition.
-service GnssGrpcProxy {
- // Sends NmeaRequest
- rpc SendNmea (SendNmeaRequest) returns (SendNmeaReply) {}
-}
-
-// The request message containing nmea
-message SendNmeaRequest {
- string nmea = 1;
-}
-
-// The response message containing the return information
-message SendNmeaReply {
- string reply = 1;
-}
diff --git a/host/commands/gnss_grpc_proxy/grpcpp.h b/host/commands/gnss_grpc_proxy/grpcpp.h
deleted file mode 100644
index e95280663..000000000
--- a/host/commands/gnss_grpc_proxy/grpcpp.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- *
- * Copyright 2015 gRPC authors.
- *
- * 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.
- *
- */
-
-/// \mainpage gRPC C++ API
-///
-/// The gRPC C++ API mainly consists of the following classes:
-/// <br>
-/// - grpc::Channel, which represents the connection to an endpoint. See [the
-/// gRPC Concepts page](https://grpc.io/docs/guides/concepts.html) for more
-/// details. Channels are created by the factory function grpc::CreateChannel.
-///
-/// - grpc::CompletionQueue, the producer-consumer queue used for all
-/// asynchronous communication with the gRPC runtime.
-///
-/// - grpc::ClientContext and grpc::ServerContext, where optional configuration
-/// for an RPC can be set, such as setting custom metadata to be conveyed to the
-/// peer, compression settings, authentication, etc.
-///
-/// - grpc::Server, representing a gRPC server, created by grpc::ServerBuilder.
-///
-/// Streaming calls are handled with the streaming classes in
-/// \ref sync_stream.h and
-/// \ref async_stream.h.
-///
-/// Refer to the
-/// [examples](https://github.com/grpc/)
-/// for code putting these pieces into play.
-
-#ifndef GRPCPP_GRPCPP_H
-#define GRPCPP_GRPCPP_H
-
-// Pragma for http://include-what-you-use.org/ tool, tells that following
-// headers are not private for grpcpp.h and are part of its interface.
-// IWYU pragma: begin_exports
-#include <grpc/grpc.h>
-
-#include <grpcpp/channel.h>
-#include <grpcpp/client_context.h>
-#include <grpcpp/completion_queue.h>
-#include <grpcpp/create_channel.h>
-#include <grpcpp/create_channel_posix.h>
-#include <grpcpp/server.h>
-#include <grpcpp/server_builder.h>
-#include <grpcpp/server_context.h>
-#include <grpcpp/server_posix.h>
-// IWYU pragma: end_exports
-
-namespace grpc {
-/// Return gRPC library version.
-grpc::string Version();
-} // namespace grpc
-
-#endif // GRPCPP_GRPCPP_H \ No newline at end of file
diff --git a/host/commands/kernel_log_monitor/Android.bp b/host/commands/kernel_log_monitor/Android.bp
index 02e2be82f..9fdd11e8e 100644
--- a/host/commands/kernel_log_monitor/Android.bp
+++ b/host/commands/kernel_log_monitor/Android.bp
@@ -13,11 +13,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-cc_binary {
+cc_binary_host {
name: "kernel_log_monitor",
srcs: [
"main.cc",
@@ -26,27 +22,12 @@ cc_binary {
shared_libs: [
"libcuttlefish_fs",
"libcuttlefish_utils",
- "libcuttlefish_kernel_log_monitor_utils",
"libbase",
- "libjsoncpp",
],
static_libs: [
"libcuttlefish_host_config",
"libgflags",
- ],
- defaults: ["cuttlefish_host"],
-}
-
-cc_library {
- name: "libcuttlefish_kernel_log_monitor_utils",
- srcs: [
- "utils.cc",
- ],
- shared_libs: [
- "libcuttlefish_fs",
- "libcuttlefish_utils",
- "libbase",
"libjsoncpp",
],
- defaults: ["cuttlefish_host"],
+ defaults: ["cuttlefish_host_only"],
}
diff --git a/host/commands/kernel_log_monitor/kernel_log_server.cc b/host/commands/kernel_log_monitor/kernel_log_server.cc
index 66fafab27..2bc037bcf 100644
--- a/host/commands/kernel_log_monitor/kernel_log_server.cc
+++ b/host/commands/kernel_log_monitor/kernel_log_server.cc
@@ -20,41 +20,37 @@
#include <utility>
#include <android-base/logging.h>
-#include <android-base/strings.h>
#include <netinet/in.h>
#include "common/libs/fs/shared_select.h"
#include "host/libs/config/cuttlefish_config.h"
-using cuttlefish::SharedFD;
+using cvd::SharedFD;
namespace {
static const std::map<std::string, std::string> kInformationalPatterns = {
- {"U-Boot ", "GUEST_UBOOT_VERSION: "},
{"] Linux version ", "GUEST_KERNEL_VERSION: "},
{"GUEST_BUILD_FINGERPRINT: ", "GUEST_BUILD_FINGERPRINT: "},
};
-static const std::map<std::string, monitor::Event> kStageToEventMap = {
- {cuttlefish::kBootStartedMessage, monitor::Event::BootStarted},
- {cuttlefish::kBootCompletedMessage, monitor::Event::BootCompleted},
- {cuttlefish::kBootFailedMessage, monitor::Event::BootFailed},
- {cuttlefish::kMobileNetworkConnectedMessage,
- monitor::Event::MobileNetworkConnected},
- {cuttlefish::kWifiConnectedMessage, monitor::Event::WifiNetworkConnected},
- {cuttlefish::kEthernetConnectedMessage, monitor::Event::EthernetNetworkConnected},
+static const std::map<std::string, monitor::BootEvent> kStageToEventMap = {
+ {vsoc::kBootStartedMessage, monitor::BootEvent::BootStarted},
+ {vsoc::kBootCompletedMessage, monitor::BootEvent::BootCompleted},
+ {vsoc::kBootFailedMessage, monitor::BootEvent::BootFailed},
+ {vsoc::kMobileNetworkConnectedMessage,
+ monitor::BootEvent::MobileNetworkConnected},
+ {vsoc::kWifiConnectedMessage, monitor::BootEvent::WifiNetworkConnected},
// TODO(b/131864854): Replace this with a string less likely to change
- {"init: starting service 'adbd'...", monitor::Event::AdbdStarted},
- {cuttlefish::kScreenChangedMessage, monitor::Event::ScreenChanged},
+ {"init: starting service 'adbd'", monitor::BootEvent::AdbdStarted},
};
void ProcessSubscriptions(
- Json::Value message,
- std::vector<monitor::EventCallback>* subscribers) {
+ monitor::BootEvent evt,
+ std::vector<monitor::BootEventCallback>* subscribers) {
auto active_subscription_count = subscribers->size();
std::size_t idx = 0;
while (idx < active_subscription_count) {
// Call the callback
- auto action = (*subscribers)[idx](message);
+ auto action = (*subscribers)[idx](evt);
if (action == monitor::SubscriptionAction::ContinueSubscription) {
++idx;
} else {
@@ -70,24 +66,25 @@ void ProcessSubscriptions(
} // namespace
namespace monitor {
-KernelLogServer::KernelLogServer(cuttlefish::SharedFD pipe_fd,
+KernelLogServer::KernelLogServer(cvd::SharedFD pipe_fd,
const std::string& log_name,
bool deprecated_boot_completed)
: pipe_fd_(pipe_fd),
- log_fd_(cuttlefish::SharedFD::Open(log_name.c_str(), O_CREAT | O_RDWR | O_APPEND, 0666)),
+ log_fd_(cvd::SharedFD::Open(log_name.c_str(), O_CREAT | O_RDWR, 0666)),
deprecated_boot_completed_(deprecated_boot_completed) {}
-void KernelLogServer::BeforeSelect(cuttlefish::SharedFDSet* fd_read) const {
+void KernelLogServer::BeforeSelect(cvd::SharedFDSet* fd_read) const {
fd_read->Set(pipe_fd_);
}
-void KernelLogServer::AfterSelect(const cuttlefish::SharedFDSet& fd_read) {
+void KernelLogServer::AfterSelect(const cvd::SharedFDSet& fd_read) {
if (fd_read.IsSet(pipe_fd_)) {
HandleIncomingMessage();
}
}
-void KernelLogServer::SubscribeToEvents(monitor::EventCallback callback) {
+void KernelLogServer::SubscribeToBootEvents(
+ monitor::BootEventCallback callback) {
subscribers_.push_back(callback);
}
@@ -120,35 +117,10 @@ bool KernelLogServer::HandleIncomingMessage() {
for (auto& stage_kv : kStageToEventMap) {
auto& stage = stage_kv.first;
auto event = stage_kv.second;
- auto pos = line_.find(stage);
- if (std::string::npos != pos) {
+ if (std::string::npos != line_.find(stage)) {
// Log the stage
LOG(INFO) << stage;
-
- Json::Value message;
- message["event"] = event;
- Json::Value metadata;
- // Expect space-separated key=value pairs in the log message.
- const auto& fields = android::base::Split(
- line_.substr(pos + stage.size()), " ");
- for (std::string field : fields) {
- field = android::base::Trim(field);
- if (field.empty()) {
- // Expected; android::base::Split() always returns at least
- // one (possibly empty) string.
- LOG(DEBUG) << "Empty field for line: " << line_;
- continue;
- }
- const auto& keyvalue = android::base::Split(field, "=");
- if (keyvalue.size() != 2) {
- LOG(WARNING) << "Field is not in key=value format: " << field;
- continue;
- }
- metadata[keyvalue[0]] = keyvalue[1];
- }
- message["metadata"] = metadata;
- ProcessSubscriptions(message, &subscribers_);
-
+ ProcessSubscriptions(event, &subscribers_);
//TODO(b/69417553) Remove this when our clients have transitioned to the
// new boot completed
if (deprecated_boot_completed_) {
diff --git a/host/commands/kernel_log_monitor/kernel_log_server.h b/host/commands/kernel_log_monitor/kernel_log_server.h
index 659a3724a..f5709eec6 100644
--- a/host/commands/kernel_log_monitor/kernel_log_server.h
+++ b/host/commands/kernel_log_monitor/kernel_log_server.h
@@ -21,22 +21,18 @@
#include <string>
#include <vector>
-#include <json/json.h>
-
#include "common/libs/fs/shared_fd.h"
#include "common/libs/fs/shared_select.h"
namespace monitor {
-enum Event : int32_t {
+enum BootEvent : int32_t {
BootStarted = 0,
BootCompleted = 1,
BootFailed = 2,
WifiNetworkConnected = 3,
MobileNetworkConnected = 4,
AdbdStarted = 5,
- ScreenChanged = 6,
- EthernetNetworkConnected = 7,
};
enum class SubscriptionAction {
@@ -44,13 +40,13 @@ enum class SubscriptionAction {
CancelSubscription,
};
-using EventCallback = std::function<SubscriptionAction(Json::Value)>;
+using BootEventCallback = std::function<SubscriptionAction(BootEvent)>;
-// KernelLogServer manages an incoming kernel log connection from the VMM.
-// Only accept one connection.
+// KernelLogServer manages incoming kernel log connection from QEmu. Only accept
+// one connection.
class KernelLogServer {
public:
- KernelLogServer(cuttlefish::SharedFD pipe_fd,
+ KernelLogServer(cvd::SharedFD pipe_fd,
const std::string& log_name,
bool deprecated_boot_completed);
@@ -58,24 +54,23 @@ class KernelLogServer {
// BeforeSelect is Called right before Select() to populate interesting
// SharedFDs.
- void BeforeSelect(cuttlefish::SharedFDSet* fd_read) const;
+ void BeforeSelect(cvd::SharedFDSet* fd_read) const;
// AfterSelect is Called right after Select() to detect and respond to changes
// on affected SharedFDs.
- void AfterSelect(const cuttlefish::SharedFDSet& fd_read);
-
- void SubscribeToEvents(EventCallback callback);
+ void AfterSelect(const cvd::SharedFDSet& fd_read);
+ void SubscribeToBootEvents(BootEventCallback callback);
private:
// Respond to message from remote client.
// Returns false, if client disconnected.
bool HandleIncomingMessage();
- cuttlefish::SharedFD pipe_fd_;
- cuttlefish::SharedFD log_fd_;
+ cvd::SharedFD pipe_fd_;
+ cvd::SharedFD log_fd_;
std::string line_;
bool deprecated_boot_completed_;
- std::vector<EventCallback> subscribers_;
+ std::vector<BootEventCallback> subscribers_;
KernelLogServer(const KernelLogServer&) = delete;
KernelLogServer& operator=(const KernelLogServer&) = delete;
diff --git a/host/commands/kernel_log_monitor/main.cc b/host/commands/kernel_log_monitor/main.cc
index 3f708b791..54611a8b5 100644
--- a/host/commands/kernel_log_monitor/main.cc
+++ b/host/commands/kernel_log_monitor/main.cc
@@ -20,17 +20,15 @@
#include <string>
#include <vector>
-#include <android-base/logging.h>
#include <android-base/strings.h>
#include <gflags/gflags.h>
-#include <json/json.h>
+#include <android-base/logging.h>
#include <common/libs/fs/shared_fd.h>
#include <common/libs/fs/shared_select.h>
#include <host/libs/config/cuttlefish_config.h>
#include <host/libs/config/logging.h>
#include "host/commands/kernel_log_monitor/kernel_log_server.h"
-#include "host/commands/kernel_log_monitor/utils.h"
DEFINE_int32(log_pipe_fd, -1,
"A file descriptor representing a (UNIX) socket from which to "
@@ -38,9 +36,9 @@ DEFINE_int32(log_pipe_fd, -1,
"the instance configuration");
DEFINE_string(subscriber_fds, "",
"A comma separated list of file descriptors (most likely pipes) to"
- " send kernel log events to.");
+ " send boot events to.");
-std::vector<cuttlefish::SharedFD> SubscribersFromCmdline() {
+std::vector<cvd::SharedFD> SubscribersFromCmdline() {
// Validate the parameter
std::string fd_list = FLAGS_subscriber_fds;
for (auto c: fd_list) {
@@ -51,10 +49,10 @@ std::vector<cuttlefish::SharedFD> SubscribersFromCmdline() {
}
auto fds = android::base::Split(FLAGS_subscriber_fds, ",");
- std::vector<cuttlefish::SharedFD> shared_fds;
+ std::vector<cvd::SharedFD> shared_fds;
for (auto& fd_str: fds) {
auto fd = std::stoi(fd_str);
- auto shared_fd = cuttlefish::SharedFD::Dup(fd);
+ auto shared_fd = cvd::SharedFD::Dup(fd);
close(fd);
shared_fds.push_back(shared_fd);
}
@@ -63,10 +61,10 @@ std::vector<cuttlefish::SharedFD> SubscribersFromCmdline() {
}
int main(int argc, char** argv) {
- cuttlefish::DefaultSubprocessLogging(argv);
+ cvd::DefaultSubprocessLogging(argv);
google::ParseCommandLineFlags(&argc, &argv, true);
- auto config = cuttlefish::CuttlefishConfig::Get();
+ auto config = vsoc::CuttlefishConfig::Get();
CHECK(config) << "Could not open cuttlefish config";
@@ -80,12 +78,12 @@ int main(int argc, char** argv) {
new_action.sa_handler = SIG_IGN;
sigaction(SIGPIPE, &new_action, &old_action);
- cuttlefish::SharedFD pipe;
+ cvd::SharedFD pipe;
if (FLAGS_log_pipe_fd < 0) {
auto log_name = instance.kernel_log_pipe_name();
- pipe = cuttlefish::SharedFD::Open(log_name.c_str(), O_RDONLY);
+ pipe = cvd::SharedFD::Open(log_name.c_str(), O_RDONLY);
} else {
- pipe = cuttlefish::SharedFD::Dup(FLAGS_log_pipe_fd);
+ pipe = cvd::SharedFD::Dup(FLAGS_log_pipe_fd);
close(FLAGS_log_pipe_fd);
}
@@ -99,8 +97,9 @@ int main(int argc, char** argv) {
for (auto subscriber_fd: subscriber_fds) {
if (subscriber_fd->IsOpen()) {
- klog.SubscribeToEvents([subscriber_fd](Json::Value message) {
- if (!monitor::WriteEvent(subscriber_fd, message)) {
+ klog.SubscribeToBootEvents([subscriber_fd](monitor::BootEvent evt) {
+ int retval = subscriber_fd->Write(&evt, sizeof(evt));
+ if (retval < 0) {
if (subscriber_fd->GetErrno() != EPIPE) {
LOG(ERROR) << "Error while writing to pipe: "
<< subscriber_fd->StrError();
@@ -117,12 +116,12 @@ int main(int argc, char** argv) {
}
for (;;) {
- cuttlefish::SharedFDSet fd_read;
+ cvd::SharedFDSet fd_read;
fd_read.Zero();
klog.BeforeSelect(&fd_read);
- int ret = cuttlefish::Select(&fd_read, nullptr, nullptr, nullptr);
+ int ret = cvd::Select(&fd_read, nullptr, nullptr, nullptr);
if (ret <= 0) continue;
klog.AfterSelect(fd_read);
diff --git a/host/commands/kernel_log_monitor/utils.cc b/host/commands/kernel_log_monitor/utils.cc
deleted file mode 100644
index 96496684a..000000000
--- a/host/commands/kernel_log_monitor/utils.cc
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2020 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 "host/commands/kernel_log_monitor/utils.h"
-
-#include <android-base/logging.h>
-
-#include "common/libs/fs/shared_buf.h"
-
-namespace monitor {
-
-std::optional<ReadEventResult> ReadEvent(cuttlefish::SharedFD fd) {
- size_t length;
- ssize_t bytes_read = cuttlefish::ReadExactBinary(fd, &length);
- if (bytes_read <= 0) {
- LOG(ERROR) << "Failed to read event buffer size: " << fd->StrError();
- return std::nullopt;
- }
- std::string buf(length, ' ');
- bytes_read = cuttlefish::ReadExact(fd, &buf);
- if (bytes_read <= 0) {
- LOG(ERROR) << "Failed to read event buffer: " << fd->StrError();
- return std::nullopt;
- }
-
- Json::CharReaderBuilder builder;
- std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
- std::string errorMessage;
- Json::Value message;
- if (!reader->parse(&*buf.begin(), &*buf.end(), &message, &errorMessage)) {
- LOG(ERROR) << "Unable to parse event JSON: " << errorMessage;
- return std::nullopt;
- }
-
- ReadEventResult result = {
- static_cast<monitor::Event>(message["event"].asInt()),
- message["metadata"]
- };
- return result;
-}
-
-bool WriteEvent(cuttlefish::SharedFD fd, const Json::Value& event_message) {
- Json::StreamWriterBuilder factory;
- std::string message_string = Json::writeString(factory, event_message);
- size_t length = message_string.length();
- ssize_t retval = cuttlefish::WriteAllBinary(fd, &length);
- if (retval <= 0) {
- LOG(ERROR) << "Failed to write event buffer size: " << fd->StrError();
- return false;
- }
- retval = cuttlefish::WriteAll(fd, message_string);
- if (retval <= 0) {
- LOG(ERROR) << "Failed to write event buffer: " << fd->StrError();
- return false;
- }
- return true;
-}
-
-} // namespace monitor
diff --git a/host/commands/kernel_log_monitor/utils.h b/host/commands/kernel_log_monitor/utils.h
deleted file mode 100644
index 1293a121d..000000000
--- a/host/commands/kernel_log_monitor/utils.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2020 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 <json/json.h>
-#include <optional>
-
-#include "common/libs/fs/shared_fd.h"
-#include "host/commands/kernel_log_monitor/kernel_log_server.h"
-
-namespace monitor {
-
-struct ReadEventResult {
- Event event;
- Json::Value metadata;
-};
-
-// Read a kernel log event from fd.
-std::optional<ReadEventResult> ReadEvent(cuttlefish::SharedFD fd);
-
-// Writes a kernel log event to the fd, in a format expected by ReadEvent.
-bool WriteEvent(cuttlefish::SharedFD fd, const Json::Value& event_message);
-
-} // namespace monitor
diff --git a/host/commands/launch/Android.bp b/host/commands/launch/Android.bp
index 6adf7a204..53ed2c39c 100644
--- a/host/commands/launch/Android.bp
+++ b/host/commands/launch/Android.bp
@@ -13,11 +13,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-cc_binary {
+cc_binary_host {
name: "launch_cvd",
srcs: [
"filesystem_explorer.cc",
@@ -28,18 +24,14 @@ cc_binary {
"libcuttlefish_fs",
"libcuttlefish_utils",
"libbase",
- "libjsoncpp",
"libnl",
- "libxml2",
- "libz",
],
static_libs: [
"libcuttlefish_host_config",
"libcuttlefish_vm_manager",
"libgflags",
+ "libxml2",
+ "libjsoncpp",
],
- required: [
- "mkenvimage",
- ],
- defaults: ["cuttlefish_host", "cuttlefish_libicuuc"],
+ defaults: ["cuttlefish_host_only", "cuttlefish_libicuuc"],
}
diff --git a/host/commands/launch/filesystem_explorer.cc b/host/commands/launch/filesystem_explorer.cc
index aac8ae693..12cd1ede4 100644
--- a/host/commands/launch/filesystem_explorer.cc
+++ b/host/commands/launch/filesystem_explorer.cc
@@ -28,10 +28,10 @@
#include "common/libs/utils/environment.h"
#include "host/libs/config/fetcher_config.h"
-cuttlefish::FetcherConfig AvailableFilesReport() {
- std::string current_directory = cuttlefish::AbsolutePath(cuttlefish::CurrentDirectory());
- if (cuttlefish::FileExists(current_directory + "/fetcher_config.json")) {
- cuttlefish::FetcherConfig config;
+cvd::FetcherConfig AvailableFilesReport() {
+ std::string current_directory = cvd::AbsolutePath(cvd::CurrentDirectory());
+ if (cvd::FileExists(current_directory + "/fetcher_config.json")) {
+ cvd::FetcherConfig config;
config.LoadFromFile(current_directory + "/fetcher_config.json");
return config;
}
@@ -39,16 +39,16 @@ cuttlefish::FetcherConfig AvailableFilesReport() {
std::set<std::string> files;
std::string psuedo_fetcher_dir =
- cuttlefish::StringFromEnv("ANDROID_HOST_OUT",
- cuttlefish::StringFromEnv("HOME", current_directory));
+ cvd::StringFromEnv("ANDROID_HOST_OUT",
+ cvd::StringFromEnv("HOME", current_directory));
std::string psuedo_fetcher_config =
psuedo_fetcher_dir + "/launcher_pseudo_fetcher_config.json";
files.insert(psuedo_fetcher_config);
- cuttlefish::FetcherConfig config;
+ cvd::FetcherConfig config;
config.RecordFlags();
for (const auto& file : files) {
- config.add_cvd_file(cuttlefish::CvdFile(cuttlefish::FileSource::LOCAL_FILE, "", "", file));
+ config.add_cvd_file(cvd::CvdFile(cvd::FileSource::LOCAL_FILE, "", "", file));
}
config.SaveToFile(psuedo_fetcher_config);
return config;
diff --git a/host/commands/launch/filesystem_explorer.h b/host/commands/launch/filesystem_explorer.h
index ceae50448..3290ebd82 100644
--- a/host/commands/launch/filesystem_explorer.h
+++ b/host/commands/launch/filesystem_explorer.h
@@ -17,4 +17,4 @@
#include "host/libs/config/fetcher_config.h"
-cuttlefish::FetcherConfig AvailableFilesReport();
+cvd::FetcherConfig AvailableFilesReport();
diff --git a/host/commands/launch/flag_forwarder.cc b/host/commands/launch/flag_forwarder.cc
index 692e4539c..8dc92d06c 100644
--- a/host/commands/launch/flag_forwarder.cc
+++ b/host/commands/launch/flag_forwarder.cc
@@ -234,12 +234,12 @@ FlagForwarder::FlagForwarder(std::set<std::string> subprocesses)
std::map<std::string, std::string> flag_to_type = CurrentFlagsToTypes();
for (const auto& subprocess : subprocesses_) {
- cuttlefish::Command cmd(subprocess);
+ cvd::Command cmd(subprocess);
cmd.AddParameter("--helpxml");
std::string helpxml_input, helpxml_output, helpxml_error;
- cuttlefish::SubprocessOptions options;
+ cvd::SubprocessOptions options;
options.Verbose(false);
- int helpxml_ret = cuttlefish::RunWithManagedStdio(std::move(cmd), &helpxml_input,
+ int helpxml_ret = cvd::RunWithManagedStdio(std::move(cmd), &helpxml_input,
&helpxml_output, &helpxml_error,
options);
if (helpxml_ret != 1) {
@@ -273,7 +273,7 @@ FlagForwarder::~FlagForwarder() = default;
void FlagForwarder::UpdateFlagDefaults() const {
for (const auto& subprocess : subprocesses_) {
- cuttlefish::Command cmd(subprocess);
+ cvd::Command cmd(subprocess);
std::vector<std::string> invocation = {subprocess};
for (const auto& flag : ArgvForSubprocess(subprocess)) {
cmd.AddParameter(flag);
@@ -290,9 +290,9 @@ void FlagForwarder::UpdateFlagDefaults() const {
// Ensure this is set on by putting it at the end.
cmd.AddParameter("--helpxml");
std::string helpxml_input, helpxml_output, helpxml_error;
- cuttlefish::SubprocessOptions options;
+ cvd::SubprocessOptions options;
options.Verbose(false);
- int helpxml_ret = cuttlefish::RunWithManagedStdio(std::move(cmd), &helpxml_input,
+ int helpxml_ret = cvd::RunWithManagedStdio(std::move(cmd), &helpxml_input,
&helpxml_output, &helpxml_error,
options);
if (helpxml_ret != 1) {
diff --git a/host/commands/launch/launch_cvd.cc b/host/commands/launch/launch_cvd.cc
index f67ce48d1..f375e833e 100644
--- a/host/commands/launch/launch_cvd.cc
+++ b/host/commands/launch/launch_cvd.cc
@@ -13,9 +13,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include <iostream>
#include <sstream>
-#include <fstream>
#include <gflags/gflags.h>
#include <android-base/logging.h>
@@ -25,7 +23,6 @@
#include "common/libs/utils/subprocess.h"
#include "host/commands/launch/filesystem_explorer.h"
#include "host/libs/config/cuttlefish_config.h"
-#include "host/libs/config/host_tools_version.h"
#include "host/libs/config/fetcher_config.h"
#include "flag_forwarder.h"
@@ -43,124 +40,51 @@
DEFINE_bool(run_file_discovery, true,
"Whether to run file discovery or get input files from stdin.");
DEFINE_int32(num_instances, 1, "Number of Android guests to launch");
-DEFINE_string(report_anonymous_usage_stats, "", "Report anonymous usage "
- "statistics for metrics collection and analysis.");
-DEFINE_int32(base_instance_num,
- cuttlefish::GetInstance(),
- "The instance number of the device created. When `-num_instances N`"
- " is used, N instance numbers are claimed starting at this number.");
DEFINE_string(verbosity, "INFO", "Console logging verbosity. Options are VERBOSE,"
"DEBUG,INFO,WARNING,ERROR");
-DEFINE_string(file_verbosity, "DEBUG",
- "Log file logging verbosity. Options are VERBOSE,DEBUG,INFO,"
- "WARNING,ERROR");
namespace {
-std::string kAssemblerBin = cuttlefish::HostBinaryPath("assemble_cvd");
-std::string kRunnerBin = cuttlefish::HostBinaryPath("run_cvd");
+std::string kAssemblerBin = vsoc::DefaultHostArtifactsPath("bin/assemble_cvd");
+std::string kRunnerBin = vsoc::DefaultHostArtifactsPath("bin/run_cvd");
-cuttlefish::Subprocess StartAssembler(cuttlefish::SharedFD assembler_stdin,
- cuttlefish::SharedFD assembler_stdout,
+cvd::Subprocess StartAssembler(cvd::SharedFD assembler_stdin,
+ cvd::SharedFD assembler_stdout,
const std::vector<std::string>& argv) {
- cuttlefish::Command assemble_cmd(kAssemblerBin);
+ cvd::Command assemble_cmd(kAssemblerBin);
for (const auto& arg : argv) {
assemble_cmd.AddParameter(arg);
}
if (assembler_stdin->IsOpen()) {
- assemble_cmd.RedirectStdIO(cuttlefish::Subprocess::StdIOChannel::kStdIn, assembler_stdin);
+ assemble_cmd.RedirectStdIO(cvd::Subprocess::StdIOChannel::kStdIn, assembler_stdin);
}
- assemble_cmd.RedirectStdIO(cuttlefish::Subprocess::StdIOChannel::kStdOut, assembler_stdout);
+ assemble_cmd.RedirectStdIO(cvd::Subprocess::StdIOChannel::kStdOut, assembler_stdout);
return assemble_cmd.Start();
}
-cuttlefish::Subprocess StartRunner(cuttlefish::SharedFD runner_stdin,
+cvd::Subprocess StartRunner(cvd::SharedFD runner_stdin,
const std::vector<std::string>& argv) {
- cuttlefish::Command run_cmd(kRunnerBin);
+ cvd::Command run_cmd(kRunnerBin);
for (const auto& arg : argv) {
run_cmd.AddParameter(arg);
}
- run_cmd.RedirectStdIO(cuttlefish::Subprocess::StdIOChannel::kStdIn, runner_stdin);
+ run_cmd.RedirectStdIO(cvd::Subprocess::StdIOChannel::kStdIn, runner_stdin);
return run_cmd.Start();
}
-void WriteFiles(cuttlefish::FetcherConfig fetcher_config, cuttlefish::SharedFD out) {
+void WriteFiles(cvd::FetcherConfig fetcher_config, cvd::SharedFD out) {
std::stringstream output_streambuf;
for (const auto& file : fetcher_config.get_cvd_files()) {
output_streambuf << file.first << "\n";
}
std::string output_string = output_streambuf.str();
- int written = cuttlefish::WriteAll(out, output_string);
+ int written = cvd::WriteAll(out, output_string);
if (written < 0) {
LOG(FATAL) << "Could not write file report (" << strerror(out->GetErrno())
<< ")";
}
}
-std::string ValidateMetricsConfirmation(std::string use_metrics) {
- if (use_metrics == "") {
- if (cuttlefish::CuttlefishConfig::ConfigExists()) {
- auto config = cuttlefish::CuttlefishConfig::Get();
- if (config) {
- if (config->enable_metrics() == cuttlefish::CuttlefishConfig::kYes) {
- use_metrics = "y";
- } else if (config->enable_metrics() == cuttlefish::CuttlefishConfig::kNo) {
- use_metrics = "n";
- }
- }
- }
- }
- char ch = !use_metrics.empty() ? tolower(use_metrics.at(0)) : -1;
- if (ch != 'n') {
- std::cout << "===================================================================\n";
- std::cout << "NOTICE:\n\n";
- std::cout << "We collect usage statistics in accordance with our\n"
- "Content Licenses (https://source.android.com/setup/start/licenses),\n"
- "Contributor License Agreement (https://cla.developers.google.com/),\n"
- "Privacy Policy (https://policies.google.com/privacy) and\n"
- "Terms of Service (https://policies.google.com/terms).\n";
- std::cout << "===================================================================\n\n";
- if (use_metrics.empty()) {
- std::cout << "Do you accept anonymous usage statistics reporting (Y/n)?: ";
- }
- }
- for (;;) {
- switch (ch) {
- case 0:
- case '\r':
- case '\n':
- case 'y':
- return "y";
- case 'n':
- return "n";
- default:
- std::cout << "Must accept/reject anonymous usage statistics reporting (Y/n): ";
- FALLTHROUGH_INTENDED;
- case -1:
- std::cin.get(ch);
- // if there's no tty the EOF flag is set, in which case default to 'n'
- if (std::cin.eof()) {
- ch = 'n';
- std::cout << "n\n"; // for consistency with user input
- }
- ch = tolower(ch);
- }
- }
- return "";
-}
-
-bool HostToolsUpdated() {
- if (cuttlefish::CuttlefishConfig::ConfigExists()) {
- auto config = cuttlefish::CuttlefishConfig::Get();
- if (config) {
- auto current_tools = cuttlefish::HostToolsCrc();
- auto last_tools = config->host_tools_version();
- return current_tools != last_tools;
- }
- }
- return true;
-}
-
} // namespace
int main(int argc, char** argv) {
@@ -175,34 +99,16 @@ int main(int argc, char** argv) {
gflags::HandleCommandLineHelpFlags();
setenv("CF_CONSOLE_SEVERITY", FLAGS_verbosity.c_str(), /* replace */ false);
- setenv("CF_FILE_SEVERITY", FLAGS_file_verbosity.c_str(), /* replace */ false);
- auto use_metrics = FLAGS_report_anonymous_usage_stats;
- FLAGS_report_anonymous_usage_stats = ValidateMetricsConfirmation(use_metrics);
+ cvd::SharedFD assembler_stdout, assembler_stdout_capture;
+ cvd::SharedFD::Pipe(&assembler_stdout_capture, &assembler_stdout);
- // TODO(b/159068082) Make decisions based on this value in assemble_cvd
- LOG(INFO) << "Host changed from last run: " << HostToolsUpdated();
-
- cuttlefish::SharedFD assembler_stdout, assembler_stdout_capture;
- cuttlefish::SharedFD::Pipe(&assembler_stdout_capture, &assembler_stdout);
-
- cuttlefish::SharedFD launcher_report, assembler_stdin;
+ cvd::SharedFD launcher_report, assembler_stdin;
bool should_generate_report = FLAGS_run_file_discovery;
if (should_generate_report) {
- cuttlefish::SharedFD::Pipe(&assembler_stdin, &launcher_report);
+ cvd::SharedFD::Pipe(&assembler_stdin, &launcher_report);
}
- auto instance_num_str = std::to_string(FLAGS_base_instance_num);
- setenv("CUTTLEFISH_INSTANCE", instance_num_str.c_str(), /* overwrite */ 1);
-
-#if defined(__BIONIC__)
- // These environment variables are needed in case when Bionic is used.
- // b/171754977
- setenv("ANDROID_DATA", cuttlefish::DefaultHostArtifactsPath("").c_str(), /* overwrite */ 0);
- setenv("ANDROID_TZDATA_ROOT", cuttlefish::DefaultHostArtifactsPath("").c_str(), /* overwrite */ 0);
- setenv("ANDROID_ROOT", cuttlefish::DefaultHostArtifactsPath("").c_str(), /* overwrite */ 0);
-#endif
-
// SharedFDs are std::move-d in to avoid dangling references.
// Removing the std::move will probably make run_cvd hang as its stdin never closes.
auto assemble_proc = StartAssembler(std::move(assembler_stdin),
@@ -214,7 +120,7 @@ int main(int argc, char** argv) {
}
std::string assembler_output;
- if (cuttlefish::ReadAll(assembler_stdout_capture, &assembler_output) < 0) {
+ if (cvd::ReadAll(assembler_stdout_capture, &assembler_output) < 0) {
int error_num = errno;
LOG(ERROR) << "Read error getting output from assemble_cvd: " << strerror(error_num);
return -1;
@@ -225,20 +131,20 @@ int main(int argc, char** argv) {
LOG(ERROR) << "assemble_cvd returned " << assemble_ret;
return assemble_ret;
} else {
- LOG(DEBUG) << "assemble_cvd exited successfully.";
+ LOG(INFO) << "assemble_cvd exited successfully.";
}
- std::vector<cuttlefish::Subprocess> runners;
+ std::vector<cvd::Subprocess> runners;
for (int i = 0; i < FLAGS_num_instances; i++) {
- cuttlefish::SharedFD runner_stdin_in, runner_stdin_out;
- cuttlefish::SharedFD::Pipe(&runner_stdin_out, &runner_stdin_in);
- std::string instance_name = std::to_string(i + FLAGS_base_instance_num);
+ cvd::SharedFD runner_stdin_in, runner_stdin_out;
+ cvd::SharedFD::Pipe(&runner_stdin_out, &runner_stdin_in);
+ std::string instance_name = std::to_string(i + vsoc::GetInstance());
setenv("CUTTLEFISH_INSTANCE", instance_name.c_str(), /* overwrite */ 1);
auto run_proc = StartRunner(std::move(runner_stdin_out),
forwarder.ArgvForSubprocess(kRunnerBin));
runners.push_back(std::move(run_proc));
- if (cuttlefish::WriteAll(runner_stdin_in, assembler_output) < 0) {
+ if (cvd::WriteAll(runner_stdin_in, assembler_output) < 0) {
int error_num = errno;
LOG(ERROR) << "Could not write to run_cvd: " << strerror(error_num);
return -1;
@@ -252,7 +158,7 @@ int main(int argc, char** argv) {
run_cvd_failure = true;
LOG(ERROR) << "run_cvd returned " << run_ret;
} else {
- LOG(DEBUG) << "run_cvd exited successfully.";
+ LOG(INFO) << "run_cvd exited successfully.";
}
}
return run_cvd_failure ? -1 : 0;
diff --git a/host/commands/log_tee/Android.bp b/host/commands/log_tee/Android.bp
index 49b3e6901..567009a2c 100644
--- a/host/commands/log_tee/Android.bp
+++ b/host/commands/log_tee/Android.bp
@@ -13,11 +13,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-cc_binary {
+cc_binary_host {
name: "log_tee",
srcs: [
"log_tee.cpp",
@@ -26,13 +22,14 @@ cc_binary {
"libcuttlefish_fs",
"libcuttlefish_utils",
"libbase",
- "libjsoncpp",
"libnl",
],
static_libs: [
"libgflags",
"libcuttlefish_host_config",
"libcuttlefish_vm_manager",
+ "libxml2",
+ "libjsoncpp",
],
- defaults: ["cuttlefish_host", "cuttlefish_libicuuc"],
+ defaults: ["cuttlefish_host_only", "cuttlefish_libicuuc"],
}
diff --git a/host/commands/log_tee/log_tee.cpp b/host/commands/log_tee/log_tee.cpp
index 7021a994b..c1b3ba043 100644
--- a/host/commands/log_tee/log_tee.cpp
+++ b/host/commands/log_tee/log_tee.cpp
@@ -30,7 +30,7 @@ int main(int argc, char** argv) {
CHECK(FLAGS_log_fd_in >= 0) << "-log_fd_in is required";
- auto config = cuttlefish::CuttlefishConfig::Get();
+ auto config = vsoc::CuttlefishConfig::Get();
CHECK(config) << "Could not open cuttlefish config";
@@ -38,13 +38,13 @@ int main(int argc, char** argv) {
if (config->run_as_daemon()) {
android::base::SetLogger(
- cuttlefish::LogToFiles({instance.launcher_log_path()}));
+ cvd::LogToFiles({instance.launcher_log_path()}));
} else {
android::base::SetLogger(
- cuttlefish::LogToStderrAndFiles({instance.launcher_log_path()}));
+ cvd::LogToStderrAndFiles({instance.launcher_log_path()}));
}
- auto log_fd = cuttlefish::SharedFD::Dup(FLAGS_log_fd_in);
+ auto log_fd = cvd::SharedFD::Dup(FLAGS_log_fd_in);
CHECK(log_fd->IsOpen()) << "Failed to dup log_fd_in: " << log_fd->StrError();
close(FLAGS_log_fd_in);
@@ -60,20 +60,7 @@ int main(int argc, char** argv) {
while ((chars_read = log_fd->Read(buf, sizeof(buf))) > 0) {
auto trimmed = android::base::Trim(std::string(buf, chars_read));
// Newlines inside `trimmed` are handled by the android logging code.
- // These checks attempt to determine the log severity coming from crosvm.
- // There is no guarantee of success all the time since log line boundaries
- // could be out sync with the reads, but that's ok.
- if (android::base::StartsWith(trimmed, "[INFO")) {
- LOG(INFO) << trimmed;
- } else if (android::base::StartsWith(trimmed, "[ERROR")) {
- LOG(ERROR) << trimmed;
- } else if (android::base::StartsWith(trimmed, "[WARNING")) {
- LOG(WARNING) << trimmed;
- } else if (android::base::StartsWith(trimmed, "[VERBOSE")) {
- LOG(VERBOSE) << trimmed;
- } else {
- LOG(DEBUG) << trimmed;
- }
+ LOG(INFO) << trimmed;
}
if (chars_read < 0) {
diff --git a/host/commands/logcat_receiver/Android.bp b/host/commands/logcat_receiver/Android.bp
index 305ab7fe5..086d41e3d 100644
--- a/host/commands/logcat_receiver/Android.bp
+++ b/host/commands/logcat_receiver/Android.bp
@@ -13,11 +13,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-cc_binary {
+cc_binary_host {
name: "logcat_receiver",
srcs: [
"main.cpp",
@@ -25,13 +21,13 @@ cc_binary {
shared_libs: [
"libbase",
"libcuttlefish_fs",
- "libjsoncpp",
"liblog",
"libcuttlefish_utils",
],
static_libs: [
"libcuttlefish_host_config",
"libgflags",
+ "libjsoncpp",
],
- defaults: ["cuttlefish_host"],
+ defaults: ["cuttlefish_host_only"],
}
diff --git a/host/commands/logcat_receiver/main.cpp b/host/commands/logcat_receiver/main.cpp
index b1c4d9339..c4a0a9a6d 100644
--- a/host/commands/logcat_receiver/main.cpp
+++ b/host/commands/logcat_receiver/main.cpp
@@ -14,70 +14,55 @@
* limitations under the License.
*/
-#include <signal.h>
-
#include <gflags/gflags.h>
#include <android-base/logging.h>
-#include "common/libs/fs/shared_buf.h"
#include "common/libs/fs/shared_fd.h"
#include "host/libs/config/cuttlefish_config.h"
#include "host/libs/config/logging.h"
-DEFINE_int32(log_pipe_fd, -1,
- "A file descriptor representing a (UNIX) socket from which to "
- "read the logs. If -1 is given the socket is created according to "
- "the instance configuration");
+DEFINE_int32(
+ server_fd, -1,
+ "File descriptor to an already created vsock server. Must be specified.");
int main(int argc, char** argv) {
- cuttlefish::DefaultSubprocessLogging(argv);
+ cvd::DefaultSubprocessLogging(argv);
google::ParseCommandLineFlags(&argc, &argv, true);
- auto config = cuttlefish::CuttlefishConfig::Get();
-
- CHECK(config) << "Could not open cuttlefish config";
+ auto config = vsoc::CuttlefishConfig::Get();
auto instance = config->ForDefaultInstance();
-
- // Disable default handling of SIGPIPE
- struct sigaction new_action {
- }, old_action{};
- new_action.sa_handler = SIG_IGN;
- sigaction(SIGPIPE, &new_action, &old_action);
-
- cuttlefish::SharedFD pipe;
- if (FLAGS_log_pipe_fd < 0) {
- auto log_name = instance.logcat_pipe_name();
- pipe = cuttlefish::SharedFD::Open(log_name.c_str(), O_RDONLY);
- } else {
- pipe = cuttlefish::SharedFD::Dup(FLAGS_log_pipe_fd);
- close(FLAGS_log_pipe_fd);
- }
-
- if (!pipe->IsOpen()) {
- LOG(ERROR) << "Error opening log pipe: " << pipe->StrError();
- return 2;
- }
-
auto path = instance.logcat_path();
auto logcat_file =
- cuttlefish::SharedFD::Open(path.c_str(), O_CREAT | O_APPEND | O_WRONLY, 0666);
+ cvd::SharedFD::Open(path.c_str(), O_CREAT | O_APPEND | O_WRONLY, 0666);
+ CHECK(logcat_file->IsOpen())
+ << "Unable to open logcat file: " << logcat_file->StrError();
+
+ cvd::SharedFD server_fd = cvd::SharedFD::Dup(FLAGS_server_fd);
+ close(FLAGS_server_fd);
+
+ CHECK(server_fd->IsOpen()) << "Error creating or inheriting logcat server: "
+ << server_fd->StrError();
// Server loop
while (true) {
- char buff[1024];
- auto read = pipe->Read(buff, sizeof(buff));
- if (read < 0) {
- LOG(ERROR) << "Could not read logcat: " << pipe->StrError();
- break;
+ auto conn = cvd::SharedFD::Accept(*server_fd);
+
+ while (true) {
+ char buff[1024];
+ auto read = conn->Read(buff, sizeof(buff));
+ if (read <= 0) {
+ // Close here to ensure the other side gets reset if it's still
+ // connected
+ conn->Close();
+ LOG(WARNING) << "Detected close from the other side";
+ break;
+ }
+ auto written = logcat_file->Write(buff, read);
+ CHECK(written == read)
+ << "Error writing to log file: " << logcat_file->StrError()
+ << ". This is unrecoverable.";
}
- auto written = cuttlefish::WriteAll(logcat_file, buff, read);
- CHECK(written == read)
- << "Error writing to log file: " << logcat_file->StrError()
- << ". This is unrecoverable.";
}
-
- logcat_file->Close();
- pipe->Close();
return 0;
}
diff --git a/host/commands/metrics/Android.bp b/host/commands/metrics/Android.bp
deleted file mode 100644
index 67eb3b095..000000000
--- a/host/commands/metrics/Android.bp
+++ /dev/null
@@ -1,36 +0,0 @@
-//
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-cc_binary {
- name: "metrics",
- srcs: [
- "metrics.cc",
- ],
- shared_libs: [
- "libcuttlefish_fs",
- "libcuttlefish_utils",
- "libbase",
- "libjsoncpp",
- ],
- static_libs: [
- "libcuttlefish_host_config",
- "libgflags",
- ],
- defaults: ["cuttlefish_host"],
-}
diff --git a/host/commands/metrics/metrics.cc b/host/commands/metrics/metrics.cc
deleted file mode 100644
index 378155cf6..000000000
--- a/host/commands/metrics/metrics.cc
+++ /dev/null
@@ -1,56 +0,0 @@
-//
-// Copyright (C) 2020 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 <android-base/strings.h>
-#include <gflags/gflags.h>
-#include <android-base/logging.h>
-
-#include "common/libs/utils/tee_logging.h"
-#include "host/commands/metrics/metrics_defs.h"
-#include "host/libs/config/cuttlefish_config.h"
-
-using cuttlefish::MetricsExitCodes;
-
-int main(int argc, char** argv) {
- ::android::base::InitLogging(argv, android::base::StderrLogger);
- google::ParseCommandLineFlags(&argc, &argv, true);
-
- auto config = cuttlefish::CuttlefishConfig::Get();
-
- CHECK(config) << "Could not open cuttlefish config";
-
- auto instance = config->ForDefaultInstance();
- auto metrics_log_path = instance.PerInstancePath("metrics.log");
-
- if (config->run_as_daemon()) {
- android::base::SetLogger(
- cuttlefish::LogToFiles({metrics_log_path, instance.launcher_log_path()}));
- } else {
- android::base::SetLogger(
- cuttlefish::LogToStderrAndFiles(
- {metrics_log_path, instance.launcher_log_path()}));
- }
-
- if (config->enable_metrics() != cuttlefish::CuttlefishConfig::kYes) {
- LOG(ERROR) << "metrics not enabled, but metrics were launched.";
- return cuttlefish::MetricsExitCodes::kInvalidHostConfiguration;
- }
-
- while (true) {
- // do nothing
- sleep(std::numeric_limits<unsigned int>::max());
- }
- return cuttlefish::MetricsExitCodes::kMetricsError;
-}
diff --git a/host/commands/metrics/proto/Android.bp b/host/commands/metrics/proto/Android.bp
deleted file mode 100644
index 250abcfe0..000000000
--- a/host/commands/metrics/proto/Android.bp
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-cc_library_shared {
- name: "cf_proto",
- vendor_available: true,
-
- srcs: [
- "*.proto",
- ],
-
- shared_libs: [
- "libcuttlefish_fs",
- "libcuttlefish_utils",
- "libbase",
- "libprotobuf-cpp-lite",
- "libprotobuf-cpp-full",
- ],
-
- static_libs: [
- "libcuttlefish_host_config",
- "libgflags",
- "libjsoncpp",
- ],
-
- proto: {
- export_proto_headers: true,
- type: "full",
- canonical_path_from_root: false,
- include_dirs: ["external/protobuf/src"],
- },
-
- cppflags: [
- "-Werror",
- "-Wno-unused-parameter",
- "-Wno-format",
- "-Wno-c++98-compat-pedantic",
- "-Wno-float-conversion",
- "-Wno-disabled-macro-expansion",
- "-Wno-float-equal",
- "-Wno-sign-conversion",
- "-Wno-padded",
- "-Wno-old-style-cast",
- "-Wno-undef",
- ],
-
- defaults: ["cuttlefish_host"],
-}
diff --git a/host/commands/metrics/proto/cf_log.proto b/host/commands/metrics/proto/cf_log.proto
deleted file mode 100644
index 46659fb3d..000000000
--- a/host/commands/metrics/proto/cf_log.proto
+++ /dev/null
@@ -1,42 +0,0 @@
-syntax = "proto2";
-
-package cuttlefish;
-
-import "common.proto";
-import "cf_metrics_event.proto";
-
-// Wrapper for Cuttlefish log events
-// Next index: 7
-message CuttlefishLogEvent {
- // Defines the device class that this log was sourced from.
- // This may not be the same device which uploaded the log event.
- // Next index: 3
- enum DeviceType {
- // The log event was sourced from an unspecified device type.
- CUTTLEFISH_DEVICE_TYPE_UNSPECIFIED = 0;
-
- // A log event that was sourced from a Cuttlefish host device.
- CUTTLEFISH_DEVICE_TYPE_HOST = 1;
-
- // A log event that was sent by an Cuttlefish guest device.
- CUTTLEFISH_DEVICE_TYPE_GUEST = 2;
- }
-
- // Local time on the event source device of when this event occurred.
- optional Timestamp timestamp_ms = 1;
-
- // The type of device this log event originated from.
- optional DeviceType device_type = 2;
-
- // The identifier for this device.
- optional string device_id = 3;
-
- // The identifier for this session.
- optional string session_id = 6;
-
- // The version of Cuttlefish that's sending the log event.
- optional string cuttlefish_version = 4;
-
- // An event encompassing metrics data
- optional MetricsEvent metrics_event = 5;
-}
diff --git a/host/commands/metrics/proto/cf_metrics_event.proto b/host/commands/metrics/proto/cf_metrics_event.proto
deleted file mode 100644
index 7129c2397..000000000
--- a/host/commands/metrics/proto/cf_metrics_event.proto
+++ /dev/null
@@ -1,143 +0,0 @@
-syntax = "proto2";
-
-package cuttlefish;
-
-import "common.proto";
-
-// Wrapper for Cuttlefish Metrics log events.
-// Next index: 22
-message MetricsEvent {
- // High level event types for this message. This is the broadest
- // category identifier for MetricsEvent and should be used to indicate
- // which other fields will be populated. Only used in field event_type.
- // Next index: 6
- enum EventType {
- // An unspecified, unhandled event.
- CUTTLEFISH_EVENT_TYPE_UNSPECIFIED = 0;
-
- // The device experienced an error.
- CUTTLEFISH_EVENT_TYPE_ERROR = 1;
-
- // The event type is the time the VM instance is instantiated.
- CUTTLEFISH_EVENT_TYPE_VM_INSTANTIATION = 2;
-
- // The event type is the time the device boot process is started.
- CUTTLEFISH_EVENT_TYPE_DEVICE_BOOT = 3;
-
- // The event type is the time the device lock screen is available.
- CUTTLEFISH_EVENT_TYPE_LOCK_SCREEN_AVAILABLE = 4;
-
- // The event type is the time the virtual device was stopped.
- CUTTLEFISH_EVENT_TYPE_VM_STOP = 5;
- }
-
- // Defines the OS that this log was sourced from.
- // This may not be the same OS which uploaded the log event.
- // Next index: 5
- enum OsType {
- // The log event was sourced from an unspecified os type.
- CUTTLEFISH_OS_TYPE_UNSPECIFIED = 0;
-
- // The log event was sourced from Linux x86 os type.
- CUTTLEFISH_OS_TYPE_LINUX_X86 = 1;
-
- // The log event was sourced from Linux x86_64 os type.
- CUTTLEFISH_OS_TYPE_LINUX_X86_64 = 2;
-
- // The log event was sourced from Linux aarch32 os type.
- CUTTLEFISH_OS_TYPE_LINUX_AARCH32 = 3;
-
- // The log event was sourced from Linux aarch64 os type.
- CUTTLEFISH_OS_TYPE_LINUX_AARCH64 = 4;
- }
-
- // Defines the VMM that this log was sourced from.
- // This may not be the same VMM which uploaded the log event.
- // Next index: 3
- enum VmmType {
- // The log event was sourced from an unspecified vmm type.
- CUTTLEFISH_VMM_TYPE_UNSPECIFIED = 0;
-
- // The log event was sourced from a CrOS VM vmm type.
- CUTTLEFISH_VMM_TYPE_CROSVM = 1;
-
- // The log event was sourced from a QEMU vmm type.
- CUTTLEFISH_VMM_TYPE_QEMU = 2;
- }
-
- // High level error types for this message. Defines the error
- // the device received when it experienced an error. This field
- // should only be present when event_type is ERROR.
- // Next index: 1
- enum ErrorType {
- // An unspecified, unhandled error.
- CUTTLEFISH_ERROR_TYPE_UNSPECIFIED = 0;
- }
-
- // Defines the type of device event contained in this message.
- // This is the highest level identifier for MetricsEvent messages.
- optional EventType event_type = 1;
-
- // Defines the error the device received when it experienced an error.
- // The field should only be present when event_type is ERROR.
- optional ErrorType error_type = 2;
-
- // Time the event occurred in milliseconds since Unix epoch.
- optional Timestamp event_time_ms = 3;
-
- // Elapsed time for the event in milliseconds.
- optional Duration elapsed_time_ms = 4;
-
- // The type of OS this log event originated from.
- optional OsType os_type = 5;
-
- // OS version for the host/guest operating system.
- // Ex. Android version (9.x, 10.x, etc.) or `uname -r` output
- optional string os_version = 6;
-
- // Android guest API level
- optional int32 api_level = 7;
-
- // The type of VMM this log event originated from.
- optional VmmType vmm_type = 8;
-
- // The version of the VMM that's sending the log event.
- optional string vmm_version = 9;
-
- // The company that's sending the log event.
- optional string company = 10;
-
- // The allowlist of launch_cvd flags attached to the launch_cvd command
- // associated with this instance
- repeated string launch_cvd_flags = 11;
-
- // Exists a -system_image_dir specified in launch_cvd
- optional bool exists_system_image_spec = 12;
-
- // Exists a -boot_image specified in launch_cvd
- optional bool exists_boot_image_spec = 13;
-
- // Exists a -bootloader specified in launch_cvd
- optional bool exists_bootloader_spec = 14;
-
- // Exists a -composite_disk specified in launch_cvd
- optional bool exists_composite_disk_spec = 15;
-
- // Exists a -data_image specified in launch_cvd
- optional bool exists_data_image_spec = 16;
-
- // Exists a -metadata_image specified in launch_cvd
- optional bool exists_metadata_image_spec = 17;
-
- // Exists a -misc_image specified in launch_cvd
- optional bool exists_misc_image_spec = 18;
-
- // Exists a -qemu_binary specified in launch_cvd
- optional bool exists_qemu_binary_spec = 19;
-
- // Exists a -super_image specified in launch_cvd
- optional bool exists_super_image_spec = 20;
-
- // Exists a -vendor_boot_image specified in launch_cvd
- optional bool exists_vendor_boot_image_spec = 21;
-}
diff --git a/host/commands/metrics/proto/clientanalytics.proto b/host/commands/metrics/proto/clientanalytics.proto
deleted file mode 100644
index 955a15c0b..000000000
--- a/host/commands/metrics/proto/clientanalytics.proto
+++ /dev/null
@@ -1,21 +0,0 @@
-syntax = "proto2";
-
-message LogRequest {
- optional ClientInfo client_info = 1;
- optional int32 log_source = 2;
- optional int64 request_time_ms = 4;
- repeated LogEvent log_event = 3;
-}
-
-message ClientInfo {
- optional int32 client_type = 1;
-}
-
-message LogResponse {
- optional int64 next_request_wait_millis = 1;
-}
-
-message LogEvent {
- optional int64 event_time_ms = 1;
- optional bytes source_extension = 6;
-}
diff --git a/host/commands/metrics/proto/common.proto b/host/commands/metrics/proto/common.proto
deleted file mode 100644
index 6ad0380c4..000000000
--- a/host/commands/metrics/proto/common.proto
+++ /dev/null
@@ -1,16 +0,0 @@
-syntax = "proto2";
-
-message Duration {
- required int64 seconds = 1;
- required int32 nanos = 2;
-}
-
-message Timestamp {
- required int64 seconds = 1;
- required int32 nanos = 2;
-}
-
-enum UserType {
- GOOGLE = 0;
- EXTERNAL = 1;
-}
diff --git a/host/commands/mk_cdisk/Android.bp b/host/commands/mk_cdisk/Android.bp
deleted file mode 100644
index a0cf8bafc..000000000
--- a/host/commands/mk_cdisk/Android.bp
+++ /dev/null
@@ -1,41 +0,0 @@
-//
-// Copyright (C) 2021 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-cc_binary {
- name: "mk_cdisk",
- srcs: [
- "mk_cdisk.cc",
- ],
- shared_libs: [
- "libcuttlefish_fs",
- "libcuttlefish_utils",
- "libbase",
- "libjsoncpp",
- "liblog",
- "libz",
- ],
- static_libs: [
- "libcdisk_spec",
- "libext2_uuid",
- "libimage_aggregator",
- "libprotobuf-cpp-lite",
- "libsparse",
- ],
- defaults: ["cuttlefish_host"],
-}
diff --git a/host/commands/mk_cdisk/mk_cdisk.cc b/host/commands/mk_cdisk/mk_cdisk.cc
deleted file mode 100644
index 028547ca4..000000000
--- a/host/commands/mk_cdisk/mk_cdisk.cc
+++ /dev/null
@@ -1,146 +0,0 @@
-//
-// Copyright (C) 2021 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 <fstream>
-#include <iostream>
-
-#include <android-base/file.h>
-#include <android-base/logging.h>
-#include <android-base/result.h>
-#include <json/json.h>
-
-#include "common/libs/utils/files.h"
-#include "host/libs/image_aggregator/image_aggregator.h"
-
-using android::base::ErrnoError;
-using android::base::Error;
-using android::base::Result;
-
-using cuttlefish::CreateCompositeDisk;
-using cuttlefish::FileExists;
-using cuttlefish::ImagePartition;
-using cuttlefish::kLinuxFilesystem;
-
-// Returns `append` is appended to the end of filename preserving the extension.
-std::string AppendFileName(const std::string& filename,
- const std::string& append) {
- size_t pos = filename.find_last_of('.');
- if (pos == std::string::npos) {
- return filename + append;
- } else {
- return filename.substr(0, pos) + append + filename.substr(pos);
- }
-}
-
-// config JSON schema:
-// {
-// "partitions": [
-// {
-// "label": string,
-// "path": string,
-// "writable": bool, // optional. defaults to false.
-// }
-// ]
-// }
-
-Result<std::vector<ImagePartition>> LoadConfig(std::istream& in) {
- std::vector<ImagePartition> partitions;
-
- Json::CharReaderBuilder builder;
- Json::Value root;
- Json::String errs;
- if (!parseFromStream(builder, in, &root, &errs)) {
- return Error() << "bad config: " << errs;
- }
- for (const Json::Value& part : root["partitions"]) {
- const std::string label = part["label"].asString();
- const std::string path = part["path"].asString();
- const bool writable =
- part["writable"].asBool(); // default: false (if null)
-
- if (!FileExists(path)) {
- return Error() << "bad config: Can't find \'" << path << '\'';
- }
- partitions.push_back(
- ImagePartition{label, path, kLinuxFilesystem, .read_only = !writable});
- }
-
- if (partitions.empty()) {
- return Error() << "bad config: no partitions";
- }
- return partitions;
-}
-
-Result<std::vector<ImagePartition>> LoadConfig(const std::string& config_file) {
- if (config_file == "-") {
- return LoadConfig(std::cin);
- } else {
- std::ifstream in(config_file);
- if (!in) {
- return ErrnoError() << "Can't open file \'" << config_file << '\'';
- }
- return LoadConfig(in);
- }
-}
-
-struct CompositeDiskArgs {
- std::string config_file;
- std::string output_file;
-};
-
-Result<CompositeDiskArgs> ParseCompositeDiskArgs(int argc, char** argv) {
- if (argc != 3) {
- std::cerr << fmt::format(
- "Usage: {0} <config_file> <output_file>\n"
- " or {0} - <output_file> (read config from STDIN)\n",
- argv[0]);
- return Error() << "missing arguments.";
- }
- CompositeDiskArgs args{
- .config_file = argv[1],
- .output_file = argv[2],
- };
- return args;
-}
-
-Result<void> MakeCompositeDiskMain(int argc, char** argv) {
- setenv("ANDROID_LOG_TAGS", "*:v", /* overwrite */ 0);
- ::android::base::InitLogging(argv, android::base::StderrLogger);
-
- auto args = ParseCompositeDiskArgs(argc, argv);
- if (!args.ok()) {
- return args.error();
- }
- auto partitions = LoadConfig(args->config_file);
- if (!partitions.ok()) {
- return partitions.error();
- }
-
- // We need two implicit output paths: GPT header/footer
- // e.g. out.img will have out-header.img and out-footer.img
- std::string gpt_header = AppendFileName(args->output_file, "-header");
- std::string gpt_footer = AppendFileName(args->output_file, "-footer");
- CreateCompositeDisk(*partitions, gpt_header, gpt_footer, args->output_file);
- return {};
-}
-
-int main(int argc, char** argv) {
- auto result = MakeCompositeDiskMain(argc, argv);
- if (!result.ok()) {
- LOG(ERROR) << result.error();
- return EXIT_FAILURE;
- }
- return 0;
-}
diff --git a/host/commands/modem_simulator/Android.bp b/host/commands/modem_simulator/Android.bp
deleted file mode 100644
index c0d03718e..000000000
--- a/host/commands/modem_simulator/Android.bp
+++ /dev/null
@@ -1,126 +0,0 @@
-//
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-cc_defaults {
- name: "modem_simulator_base",
- srcs: [
- "channel_monitor.cpp",
- "thread_looper.cpp",
- "command_parser.cpp",
- "modem_simulator.cpp",
- "modem_service.cpp",
- "sim_service.cpp",
- "network_service.cpp",
- "misc_service.cpp",
- "call_service.cpp",
- "data_service.cpp",
- "sms_service.cpp",
- "sup_service.cpp",
- "stk_service.cpp",
- "pdu_parser.cpp",
- "cf_device_config.cpp",
- "nvram_config.cpp"
- ],
- shared_libs: [
- "libcuttlefish_fs",
- "libcuttlefish_utils",
- "libbase",
- "libjsoncpp",
- "libnl",
- "libcuttlefish_device_config",
- "libcuttlefish_device_config_proto",
- ],
- static_libs: [
- "libcuttlefish_host_config",
- "libgflags",
- "libtinyxml2",
- ],
- cflags: ["-Werror", "-Wall", "-fexceptions"],
- defaults: ["cuttlefish_host"],
-}
-
-cc_binary {
- name: "modem_simulator",
- srcs: [
- "main.cpp"
- ],
- defaults: ["cuttlefish_host", "modem_simulator_base"],
-}
-
-prebuilt_etc {
- name: "iccprofile_for_sim0.xml",
- vendor: true,
- src: "files/iccprofile_for_sim0.xml",
- filename: "iccprofile_for_sim0.xml",
- sub_dir: "modem_simulator/files",
-}
-
-prebuilt_etc {
- name: "iccprofile_for_sim0_for_CtsCarrierApiTestCases.xml",
- vendor: true,
- src: "files/iccprofile_for_sim0_for_CtsCarrierApiTestCases.xml",
- filename: "iccprofile_for_sim0_for_CtsCarrierApiTestCases.xml",
- sub_dir: "modem_simulator/files",
-}
-
-prebuilt_etc {
- name: "numeric_operator.xml",
- vendor: true,
- src: "files/numeric_operator.xml",
- filename: "numeric_operator.xml",
- sub_dir: "modem_simulator/files",
-}
-
-prebuilt_etc_host {
- name: "iccprofile_for_sim0.xml_host",
- src: "files/iccprofile_for_sim0.xml",
- filename: "iccprofile_for_sim0.xml",
- sub_dir: "modem_simulator/files",
-}
-
-prebuilt_etc_host {
- name: "iccprofile_for_sim0_for_CtsCarrierApiTestCases.xml_host",
- src: "files/iccprofile_for_sim0_for_CtsCarrierApiTestCases.xml",
- filename: "iccprofile_for_sim0_for_CtsCarrierApiTestCases.xml",
- sub_dir: "modem_simulator/files",
-}
-
-prebuilt_etc_host {
- name: "numeric_operator.xml_host",
- src: "files/numeric_operator.xml",
- filename: "numeric_operator.xml",
- sub_dir: "modem_simulator/files",
-}
-
-cc_test_host {
- name: "modem_simulator_test",
- srcs: [
- "unittest/main_test.cpp",
- "unittest/service_test.cpp",
- "unittest/command_parser_test.cpp",
- "unittest/pdu_parser_test.cpp",
- ],
- include_dirs: [
- "device/google/cuttlefish/host/commands",
- ],
- defaults: ["cuttlefish_host", "modem_simulator_base"],
- whole_static_libs: [
- "libc++fs"
- ],
-}
diff --git a/host/commands/modem_simulator/call_service.cpp b/host/commands/modem_simulator/call_service.cpp
deleted file mode 100644
index 678da4fd2..000000000
--- a/host/commands/modem_simulator/call_service.cpp
+++ /dev/null
@@ -1,719 +0,0 @@
-//
-// Copyright (C) 2020 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 "host/commands/modem_simulator/call_service.h"
-
-#include <android-base/logging.h>
-
-#include <chrono>
-#include <iostream>
-#include <thread>
-
-#include "host/commands/modem_simulator/nvram_config.h"
-
-namespace cuttlefish {
-
-CallService::CallService(int32_t service_id, ChannelMonitor* channel_monitor,
- ThreadLooper* thread_looper)
- : ModemService(service_id, this->InitializeCommandHandlers(),
- channel_monitor, thread_looper) {
- InitializeServiceState();
-}
-
-void CallService::InitializeServiceState() {
- auto nvram_config = NvramConfig::Get();
- auto instance = nvram_config->ForInstance(service_id_);
- in_emergency_mode_ = instance.emergency_mode();
-
- last_active_call_index_ = 1;
- mute_on_ = false;
-}
-
-void CallService::SetupDependency(SimService* sim, NetworkService* net) {
- sim_service_ = sim;
- network_service_ = net;
-}
-
-std::vector<CommandHandler> CallService::InitializeCommandHandlers() {
- std::vector<CommandHandler> command_handlers = {
- CommandHandler("D",
- [this](const Client& client, std::string& cmd) {
- this->HandleDial(client, cmd);
- }),
- CommandHandler(
- "A",
- [this](const Client& client) { this->HandleAcceptCall(client); }),
- CommandHandler(
- "H",
- [this](const Client& client) { this->HandleRejectCall(client); }),
- CommandHandler(
- "+CLCC",
- [this](const Client& client) { this->HandleCurrentCalls(client); }),
- CommandHandler("+CHLD=",
- [this](const Client& client, std::string& cmd) {
- this->HandleHangup(client, cmd);
- }),
- CommandHandler("+CMUT",
- [this](const Client& client, std::string& cmd) {
- this->HandleMute(client, cmd);
- }),
- CommandHandler("+VTS=",
- [this](const Client& client, std::string& cmd) {
- this->HandleSendDtmf(client, cmd);
- }),
- CommandHandler("+CUSD=",
- [this](const Client& client, std::string& cmd) {
- this->HandleCancelUssd(client, cmd);
- }),
- CommandHandler("+WSOS=0",
- [this](const Client& client, std::string& cmd) {
- this->HandleEmergencyMode(client, cmd);
- }),
- CommandHandler("+REMOTECALL",
- [this](const Client& client, std::string& cmd) {
- this->HandleRemoteCall(client, cmd);
- }),
- };
- return (command_handlers);
-}
-
-// This also resumes held calls
-void CallService::SimulatePendingCallsAnswered() {
- for (auto& iter : active_calls_) {
- if (iter.second.isCallDialing()) {
- iter.second.SetCallActive();
- }
- }
-}
-
-void CallService::TimerWaitingRemoteCallResponse(CallToken call_token) {
- LOG(DEBUG) << "Dialing id: " << call_token.first
- << ", number: " << call_token.second << "timeout, cancel";
- auto iter = active_calls_.find(call_token.first);
- if (iter != active_calls_.end() && iter->second.number == call_token.second) {
- if (iter->second.remote_client != std::nullopt) {
- CloseRemoteConnection(*(iter->second.remote_client));
- }
- active_calls_.erase(iter); // match
- CallStateUpdate();
- } // else not match, ignore
-}
-
-/* ATD */
-void CallService::HandleDial(const Client& client, const std::string& command) {
- // Check the network registration state
- auto registration_state = NetworkService::NET_REGISTRATION_UNKNOWN;
- if (network_service_) {
- registration_state = network_service_->GetVoiceRegistrationState();
- }
-
- bool emergency_only = false;
- if (registration_state == NetworkService::NET_REGISTRATION_HOME ||
- registration_state == NetworkService::NET_REGISTRATION_ROAMING) {
- emergency_only = false;
- } else if (registration_state == NetworkService::NET_REGISTRATION_EMERGENCY) {
- emergency_only = true;
- } else {
- client.SendCommandResponse(kCmeErrorNoNetworkService);
- return;
- }
-
- CommandParser cmd(command);
- cmd.SkipPrefixAT();
-
- std::string number;
- bool emergency_number = false;
- /**
- * Normal dial: ATDnumber[clir];
- * Emergency dial: ATDnumber@[category],#[clir];
- */
- auto pos = cmd->find_last_of('@');
- if (pos != std::string_view::npos) {
- emergency_number = true;
- number = cmd->substr(1, pos -1); // Skip 'D' and ignore category, clir
- } else { // Remove 'i' or 'I' or ';'
- pos = cmd->find_last_of('i');
- if (pos == std::string_view::npos) {
- pos = cmd->find_last_of('I');
- if (pos == std::string_view::npos) {
- pos = cmd->find_last_of(';');
- }
- }
- if (pos == std::string_view::npos) {
- number = cmd->substr(1);
- } else {
- number = cmd->substr(1, pos -1);
- }
- }
-
- // Check the number is valid digits or not
- if (strspn(number.c_str(), "1234567890") != number.size()) {
- client.SendCommandResponse(kCmeErrorInCorrectParameters);
- return;
- }
-
- if (emergency_only && !emergency_number) {
- client.SendCommandResponse(kCmeErrorNetworkNotAllowedEmergencyCallsOnly);
- return;
- }
-
- // If the number is not emergency number, FDN enabled and the number is not in
- // the fdn list, return kCmeErrorFixedDialNumberOnlyAllowed.
- if (!emergency_number && sim_service_->IsFDNEnabled() &&
- !sim_service_->IsFixedDialNumber(number)) {
- client.SendCommandResponse(kCmeErrorFixedDialNumberOnlyAllowed);
- return;
- }
-
- int port = 0;
- if (number.length() == 11) {
- port = std::stoi(number.substr(7));
- } else if (number.length() == 4) {
- port = std::stoi(number);
- }
-
- if (port >= kRemotePortRange.first &&
- port <= kRemotePortRange.second) { // May be a remote call
- std::stringstream ss;
- ss << port;
- auto remote_port = ss.str();
- auto remote_client = ConnectToRemoteCvd(remote_port);
- if (!remote_client->IsOpen()) {
- client.SendCommandResponse(kCmeErrorNoNetworkService);
- return;
- }
- auto local_host_port = GetHostPort();
- if (local_host_port == remote_port) {
- client.SendCommandResponse(kCmeErrorOperationNotAllowed);
- return;
- }
-
- if (channel_monitor_) {
- channel_monitor_->SetRemoteClient(remote_client, false);
- }
-
- ss.clear();
- ss.str("");
- ss << "AT+REMOTECALL=4,0,0,\"" << local_host_port << "\",129";
-
- SendCommandToRemote(remote_client, "REM0");
- SendCommandToRemote(remote_client, ss.str());
-
- CallStatus call_status(remote_port);
- call_status.is_remote_call = true;
- call_status.is_mobile_terminated = false;
- call_status.call_state = CallStatus::CALL_STATE_DIALING;
- call_status.remote_client = remote_client;
- int index = last_active_call_index_++;
-
- auto call_token = std::make_pair(index, call_status.number);
- call_status.timeout_serial = thread_looper_->PostWithDelay(
- std::chrono::minutes(1),
- makeSafeCallback<CallService>(this, [call_token](CallService* me) {
- me->TimerWaitingRemoteCallResponse(call_token);
- }));
-
- active_calls_[index] = call_status;
- } else {
- CallStatus call_status(number);
- call_status.is_mobile_terminated = false;
- call_status.call_state = CallStatus::CALL_STATE_DIALING;
- auto index = last_active_call_index_++;
- active_calls_[index] = call_status;
-
- if (emergency_number) {
- in_emergency_mode_ = true;
- SendUnsolicitedCommand("+WSOS: 1");
- }
- thread_looper_->PostWithDelay(std::chrono::seconds(1),
- makeSafeCallback(this, &CallService::SimulatePendingCallsAnswered));
- }
-
- client.SendCommandResponse("OK");
- std::this_thread::sleep_for(std::chrono::seconds(2));
-}
-
-void CallService::SendCallStatusToRemote(CallStatus& call,
- CallStatus::CallState state) {
- if (call.is_remote_call && call.remote_client != std::nullopt) {
- std::stringstream ss;
- ss << "AT+REMOTECALL=" << state << ","
- << call.is_voice_mode << ","
- << call.is_multi_party << ",\""
- << GetHostPort() << "\","
- << call.is_international;
-
- SendCommandToRemote(*(call.remote_client), ss.str());
- if (state == CallStatus::CALL_STATE_HANGUP) {
- CloseRemoteConnection(*(call.remote_client));
- }
- }
-}
-
-/* ATA */
-void CallService::HandleAcceptCall(const Client& client) {
- for (auto& iter : active_calls_) {
- if (iter.second.isCallIncoming()) {
- iter.second.SetCallActive();
- SendCallStatusToRemote(iter.second, CallStatus::CALL_STATE_ACTIVE);
- } else if (iter.second.isCallActive()) {
- iter.second.SetCallBackground();
- SendCallStatusToRemote(iter.second, CallStatus::CALL_STATE_HELD);
- }
- }
-
- client.SendCommandResponse("OK");
-}
-
-/* ATH */
-void CallService::HandleRejectCall(const Client& client) {
- for (auto iter = active_calls_.begin(); iter != active_calls_.end();) {
- /* ATH: hangup, since user is busy */
- if (iter->second.isCallIncoming()) {
- SendCallStatusToRemote(iter->second, CallStatus::CALL_STATE_HANGUP);
- iter = active_calls_.erase(iter);
- } else {
- ++iter;
- }
- }
-
- client.SendCommandResponse("OK");
-}
-
-/**
- * AT+CLCC
- * Returns list of current calls of MT. If command succeeds but no
- * calls are available, no information response is sent to TE.
- *
- * command Possible response(s)
- * AT+CLCC [+CLCC: <ccid1>,<dir>,<stat>,<mode>,<mpty>
- * [,<number>,<type>[,<alpha>[,<priority>
- * [,<CLI validity>]]]][<CR><LF>
- * +CLCC: <ccid2>,<dir>,<stat>,<mode>,<mpty>
- * [,<number>,<type>[,<alpha>[,<priority>[,<CLI validity>]]]]
- * +CME ERROR: <err>
- *
- * <ccidx>: integer type. This number can be used in +CHLD command
- * operations. Value range is from 1 to N. N, the maximum number of
- * simultaneous call control processes is implementation specific.
- * <dir>: integer type
- * 0 mobile originated (MO) call
- 1 mobile terminated (MT) call
- * <stat>: integer type (state of the call)
- * 0 active
- * 1 held
- * 2 dialing (MO call)
- * 3 alerting (MO call)
- * 4 incoming (MT call)
- * 5 waiting (MT call)
- * <mode>: integer type (bearer/teleservice)
- * 0 voice
- * 1 data
- * 2 fax
- * 3 voice followed by data, voice mode
- * 4 alternating voice/data, voice mode
- * 5 alternating voice/fax, voice mode
- * 6 voice followed by data, data mode
- * 7 alternating voice/data, data mode
- * 8 alternating voice/fax, fax mode
- * 9 unknown
- * <mpty>: integer type
- * 0 call is not one of multiparty (conference) call parties
- * 1 call is one of multiparty (conference) call parties
- * <number>: string type phone number in format specified by <type>.
- * <type>: type of address octet in integer format
- *
- *see RIL_REQUEST_GET_CURRENT_CALLS in RIL
- */
-void CallService::HandleCurrentCalls(const Client& client) {
- std::vector<std::string> responses;
- std::stringstream ss;
-
- // AT+CLCC
- // [+CLCC: <ccid1>,<dir>,<stat>,<mode>,<mpty>[,<number>,<type>[,<alpha>[,<priority>[,<CLI validity>]]]]
- // [+CLCC: <ccid2>,<dir>,<stat>,<mode>,<mpty>[,<number>,<type>[,<alpha>[,<priority>[,<CLI validity>]]]]
- // [...]]]
- for (auto iter = active_calls_.begin(); iter != active_calls_.end(); ++iter) {
- int index = iter->first;
- int dir = iter->second.is_mobile_terminated;
- CallStatus::CallState call_state = iter->second.call_state;
- int mode = iter->second.is_voice_mode;
- int mpty = iter->second.is_multi_party;
- int type = iter->second.is_international ? 145 : 129;
- std::string number = iter->second.number;
-
- ss.clear();
- ss << "+CLCC: " << index << "," << dir << "," << call_state << ","
- << mode << "," << mpty << "," << number<< "," << type;
- responses.push_back(ss.str());
- ss.str("");
- }
-
- responses.push_back("OK");
- client.SendCommandResponse(responses);
-}
-
-/**
- * AT+CHLD
- * This command allows the control of the following call related services:
- * 1) a call can be temporarily disconnected from the MT but the connection
- * is retained by the network;
- * 2) multiparty conversation (conference calls);
- * 3) the served subscriber who has two calls (one held and the other
- * either active or alerting) can connect the other parties and release
- * the served subscriber's own connection.
- *
- * Calls can be put on hold, recovered, released, added to conversation,
- * and transferred similarly.
- *
- * command Possible response(s)
- * +CHLD=<n> +CME ERROR: <err>
- *
- * +CHLD=? +CHLD: (list of supported <n>s)
- * e.g. +CHLD: (0,1,1x,2,2x,3,4)
- *
- *
- * see RIL_REQUEST_HANGUP_WAITING_OR_BACKGROUND
- * RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND
- * RIL_REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE
- * RIL_REQUEST_CONFERENCE
- * RIL_REQUEST_SEPARATE_CONNECTION
- * RIL_REQUEST_HANGUP
- * RIL_REQUEST_UDUB in RIL
- */
-void CallService::HandleHangup(const Client& client,
- const std::string& command) {
- std::vector<std::string> responses;
- CommandParser cmd(command);
- cmd.SkipPrefix();
-
- std::string action(*cmd);
- int n = std::stoi(action.substr(0, 1));
- int index = -1;
- if (cmd->length() > 1) {
- index = std::stoi(action.substr(1));
- }
-
- switch (n) {
- case 0: // Release all held calls or set User Determined User Busy(UDUB) for a waiting call
- for (auto iter = active_calls_.begin(); iter != active_calls_.end();) {
- if (iter->second.isCallIncoming() ||
- iter->second.isCallBackground() ||
- iter->second.isCallWaiting()) {
- SendCallStatusToRemote(iter->second, CallStatus::CALL_STATE_HANGUP);
- iter = active_calls_.erase(iter);
- } else {
- ++iter;
- }
- }
- break;
- case 1:
- if (index == -1) { // Release all active calls and accepts the other(hold or waiting) call
- for (auto iter = active_calls_.begin(); iter != active_calls_.end();) {
- if (iter->second.isCallActive()) {
- SendCallStatusToRemote(iter->second, CallStatus::CALL_STATE_HANGUP);
- iter = active_calls_.erase(iter);
- continue;
- } else if (iter->second.isCallBackground() ||
- iter->second.isCallWaiting()) {
- iter->second.SetCallActive();
- SendCallStatusToRemote(iter->second, CallStatus::CALL_STATE_ACTIVE);
- }
- ++iter;
- }
- } else { // Release a specific active call
- auto iter = active_calls_.find(index);
- if (iter != active_calls_.end()) {
- SendCallStatusToRemote(iter->second, CallStatus::CALL_STATE_HANGUP);
- active_calls_.erase(iter);
- }
- }
- break;
- case 2:
- if (index == -1) { // Place all active calls and the waiting calls, activates all held calls
- for (auto& iter : active_calls_) {
- if (iter.second.isCallActive() || iter.second.isCallWaiting()) {
- iter.second.SetCallBackground();
- SendCallStatusToRemote(iter.second, CallStatus::CALL_STATE_HELD);
- } else if (iter.second.isCallBackground()) {
- iter.second.SetCallActive();
- SendCallStatusToRemote(iter.second, CallStatus::CALL_STATE_ACTIVE);
- }
- }
- } else { // Disconnect a call from the conversation
- auto iter = active_calls_.find(index);
- if (iter != active_calls_.end()) {
- SendCallStatusToRemote(iter->second, CallStatus::CALL_STATE_HANGUP);
- active_calls_.erase(iter);
- }
- }
- break;
- case 3: // Adds an held call to the conversation
- for (auto iter = active_calls_.begin(); iter != active_calls_.end(); ++iter) {
- if (iter->second.isCallBackground()) {
- iter->second.SetCallActive();
- SendCallStatusToRemote(iter->second, CallStatus::CALL_STATE_ACTIVE);
- }
- }
- break;
- case 4: // Connect the two calls
- for (auto iter = active_calls_.begin(); iter != active_calls_.end(); ++iter) {
- if (iter->second.isCallBackground()) {
- iter->second.SetCallActive();
- SendCallStatusToRemote(iter->second, CallStatus::CALL_STATE_ACTIVE);
- }
- }
- break;
- default:
- client.SendCommandResponse(kCmeErrorOperationNotAllowed);
- return;
- }
- client.SendCommandResponse("OK");
-}
-
-/**
- * AT+CMUT
- * This command is used to enable and disable the uplink voice muting
- * during a voice call.
- * Read command returns the current value of <n>.
- *
- * Command Possible response(s)
- * +CMUT=[<n>] +CME ERROR: <err>
- * +CMUT? +CMUT: <n>
- * +CME ERROR: <err>
- *
- * <n>: integer type
- * 0 mute off
- * 1 mute on
- *
- * see RIL_REQUEST_SET_MUTE or RIL_REQUEST_GET_MUTE in RIL
- */
-void CallService::HandleMute(const Client& client, const std::string& command) {
- std::vector<std::string> responses;
- std::stringstream ss;
-
- CommandParser cmd(command);
- cmd.SkipPrefix(); // If AT+CMUT?, it remains AT+CMUT?
-
- if (cmd == "AT+CMUT?") {
- ss << "+CMUT: " << mute_on_;
- responses.push_back(ss.str());
- } else { // AT+CMUT = <n>
- int n = cmd.GetNextInt();
- switch (n) {
- case 0: // Mute off
- mute_on_ = false;
- break;
- case 1: // Mute on
- mute_on_ = true;
- break;
- default:
- client.SendCommandResponse(kCmeErrorInCorrectParameters);
- return;
- }
- }
- responses.push_back("OK");
- client.SendCommandResponse(responses);
-}
-
-/**
- * AT+VTS
- * This command transmits DTMF, after a successful call connection.
- * Setting Command is used to send one or more ASCII characters which make
- * MSC (Mobile Switching Center) send DTMF tone to remote User.
- *
- * Command Possible response(s)
- * AT+VTS=<dtmf>[,<duration>] +CME ERROR: <err>
- *
- * <dtmf>
- * A single ASCII character in the set { 0 -9, #, *, A – D}.
- * <duration>
- * Refer to duration value range of +VTD command
- *
- * see RIL_REQUEST_DTMF in RIL
- */
-void CallService::HandleSendDtmf(const Client& client,
- const std::string& /*command*/) {
- client.SendCommandResponse("OK");
-}
-
-void CallService::HandleCancelUssd(const Client& client,
- const std::string& /*command*/) {
- client.SendCommandResponse("OK");
-}
-
-/**
- * AT+WSOS
- *
- * Command Possible response(s)
- * +WSOS=[<n>] +CME ERROR: <err>
- * +WSOS? +WSOS: <n>
- * +CME ERROR: <err>
- *
- * <n>: integer type
- * 0 enter emergency mode
- * 1 exit emergency mode
- *
- * see RIL_REQUEST_EXIT_EMERGENCY_CALLBACK_MODE
- * RIL_UNSOL_ENTER_EMERGENCY_CALLBACK_MODE
- * RIL_UNSOL_EXIT_EMERGENCY_CALLBACK_MODE in RIL
- */
-void CallService::HandleEmergencyMode(const Client& client,
- const std::string& command) {
- std::vector<std::string> responses;
- CommandParser cmd(command);
- cmd.SkipPrefix();
-
- if (cmd == "AT+WSOS?") {
- std::stringstream ss;
- ss << "+WSOS: " << in_emergency_mode_;
- responses.push_back(ss.str());
- } else {
- int n = cmd.GetNextInt();
- switch (n) {
- case 0: // Exit
- in_emergency_mode_ = false;
- break;
- case 1: // Enter
- in_emergency_mode_ = true;
- break;
- default:
- client.SendCommandResponse(kCmeErrorInCorrectParameters);
- return;
- }
- auto nvram_config = NvramConfig::Get();
- auto instance = nvram_config->ForInstance(service_id_);
- instance.set_emergency_mode(in_emergency_mode_);
- NvramConfig::SaveToFile();
- }
- client.SendCommandResponse("OK");
-}
-
-void CallService::CallStateUpdate() {
- SendUnsolicitedCommand("RING");
-}
-
-/**
- * AT+REMOTECALL=<dir>,<stat>,<mode>,<mpty>,<number>,<num_type>
- * This command allows to dial a remote voice call with another cuttlefish
- * emulator. If request is successful, the remote emulator can simulate hold on,
- * hang up, reject and so on.
- *
- * e.g. AT+REMOTECALL=4,0,0,6521,129
- *
- * <stat>: integer type (state of the call)
- * 0 active
- * 1 held
- * 2 dialing (MO call)
- * 3 alerting (MO call)
- * 4 incoming (MT call)
- * 5 waiting (MT call)
- * <mode>: integer type
- * 0 voice
- * 1 data
- * 2 fax
- * 3 voice followed by data, voice mode
- * 4 alternating voice/data, voice mode
- * 5 alternating voice/fax, voice mode
- * 6 voice followed by data, data mode
- * 7 alternating voice/data, data mode
- * 8 alternating voice/fax, fax mode
- * 9 unknown
- * <mpty>: integer type
- * 0 call is not one of multiparty (conference) call parties
- * 1 call is one of multiparty (conference) call parties
- * <number>: string here maybe remote port
- * <num_type>: type of address octet in integer format
- *
- * Note: reason should be added to indicate why hang up. Since not realizing
- * RIL_LAST_CALL_FAIL_CAUSE, delay to be implemented.
- */
-void CallService::HandleRemoteCall(const Client& client,
- const std::string& command) {
- CommandParser cmd(command);
- cmd.SkipPrefix();
-
- int state = cmd.GetNextInt();
- int mode = cmd.GetNextInt();
- int mpty = cmd.GetNextInt();
- auto number = cmd.GetNextStr();
- int num_type = cmd.GetNextInt();
-
- // According to the number to determine whether it is a existing call
- auto iter = active_calls_.begin();
- for (; iter != active_calls_.end(); ++iter) {
- if (iter->second.number == number) {
- break;
- }
- }
-
- switch (state) {
- case CallStatus::CALL_STATE_ACTIVE: {
- if (iter != active_calls_.end()) {
- iter->second.SetCallActive();
- if (iter->second.timeout_serial != std::nullopt) {
- thread_looper_->CancelSerial(*(iter->second.timeout_serial));
- }
- }
- break;
- }
- case CallStatus::CALL_STATE_HELD:
- if (iter != active_calls_.end()) {
- iter->second.SetCallBackground();
- if (iter->second.timeout_serial != std::nullopt) {
- thread_looper_->CancelSerial(*(iter->second.timeout_serial));
- }
- }
- break;
- case CallStatus::CALL_STATE_HANGUP:
- if (iter != active_calls_.end()) {
- auto client = iter->second.remote_client;
- if (client != std::nullopt) {
- CloseRemoteConnection(*client);
- }
- if (iter->second.timeout_serial != std::nullopt) {
- thread_looper_->CancelSerial(*(iter->second.timeout_serial));
- }
- active_calls_.erase(iter);
- }
- break;
- case CallStatus::CALL_STATE_INCOMING: {
- if (network_service_) {
- if (network_service_->isRadioOff()) {
- LOG(DEBUG) << " radio is off, reject incoming call from: " << number;
- client.client_fd->Close();
- return;
- }
- }
- CallStatus call_status(number);
- call_status.is_remote_call = true;
- call_status.is_voice_mode = mode;
- call_status.is_multi_party = mpty;
- call_status.is_mobile_terminated = true;
- call_status.is_international = num_type;
- call_status.remote_client = client.client_fd;
- call_status.call_state = CallStatus::CALL_STATE_INCOMING;
-
- auto index = last_active_call_index_++;
- active_calls_[index] = call_status;
- break;
- }
- default: // Unsupported call state
- return;
- }
- thread_looper_->Post(makeSafeCallback(this, &CallService::CallStateUpdate));
-}
-
-} // namespace cuttlefish
diff --git a/host/commands/modem_simulator/call_service.h b/host/commands/modem_simulator/call_service.h
deleted file mode 100644
index 187037226..000000000
--- a/host/commands/modem_simulator/call_service.h
+++ /dev/null
@@ -1,150 +0,0 @@
-//
-// Copyright (C) 2020 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 "host/commands/modem_simulator/modem_service.h"
-#include "host/commands/modem_simulator/network_service.h"
-#include "host/commands/modem_simulator/sim_service.h"
-
-namespace cuttlefish {
-
-class CallService : public ModemService, public std::enable_shared_from_this<CallService> {
- public:
- CallService(int32_t service_id, ChannelMonitor* channel_monitor,
- ThreadLooper* thread_looper);
- ~CallService() = default;
-
- CallService(const CallService &) = delete;
- CallService &operator=(const CallService &) = delete;
-
- void SetupDependency(SimService* sim, NetworkService* net);
-
- void HandleDial(const Client& client, const std::string& command);
- void HandleAcceptCall(const Client& client);
- void HandleRejectCall(const Client& client);
- void HandleCurrentCalls(const Client& client);
- void HandleHangup(const Client& client, const std::string& command);
- void HandleMute(const Client& client, const std::string& command);
- void HandleSendDtmf(const Client& client, const std::string& command);
- void HandleCancelUssd(const Client& client, const std::string& command);
- void HandleEmergencyMode(const Client& client, const std::string& command);
- void HandleRemoteCall(const Client& client, const std::string& command);
-
- private:
- void InitializeServiceState();
- std::vector<CommandHandler> InitializeCommandHandlers();
- void SimulatePendingCallsAnswered();
- void CallStateUpdate();
-
- struct CallStatus {
- enum CallState {
- CALL_STATE_ACTIVE = 0,
- CALL_STATE_HELD,
- CALL_STATE_DIALING,
- CALL_STATE_ALERTING,
- CALL_STATE_INCOMING,
- CALL_STATE_WAITING,
- CALL_STATE_HANGUP
- };
-
- // ctors
- CallStatus()
- : call_state(CALL_STATE_ACTIVE),
- is_mobile_terminated(true),
- is_international(false),
- is_voice_mode(true),
- is_multi_party(false),
- can_present_number(true) {}
-
- CallStatus(const std::string_view number)
- : call_state(CALL_STATE_INCOMING),
- is_mobile_terminated(true),
- is_international(false),
- is_voice_mode(true),
- is_multi_party(false),
- number(number),
- can_present_number(true) {}
-
- bool isCallBackground() {
- return call_state == CALL_STATE_HELD;
- }
-
- bool isCallActive() {
- return call_state == CALL_STATE_ACTIVE;
- }
-
- bool isCallDialing() {
- return call_state == CALL_STATE_DIALING;
- }
-
- bool isCallIncoming() {
- return call_state == CALL_STATE_INCOMING;
- }
-
- bool isCallWaiting() {
- return call_state == CALL_STATE_WAITING;
- }
-
- bool isCallAlerting() {
- return call_state == CALL_STATE_ALERTING;
- }
-
- bool SetCallBackground() {
- if (call_state == CALL_STATE_ACTIVE) {
- call_state = CALL_STATE_HELD;
- return true;
- }
-
- return false;
- }
-
- bool SetCallActive() {
- if (call_state == CALL_STATE_INCOMING || call_state == CALL_STATE_WAITING ||
- call_state == CALL_STATE_DIALING || call_state == CALL_STATE_HELD) {
- call_state = CALL_STATE_ACTIVE;
- return true;
- }
-
- return false;
- }
-
- // date member public
- CallState call_state;
- bool is_mobile_terminated;
- bool is_international;
- bool is_voice_mode;
- bool is_multi_party;
- bool is_remote_call;
- std::optional<cuttlefish::SharedFD> remote_client;
- std::optional<int32_t> timeout_serial;
- std::string number;
- bool can_present_number;
- };
- using CallToken = std::pair<int, std::string>;
-
- void SendCallStatusToRemote(CallStatus& call, CallStatus::CallState state);
- void TimerWaitingRemoteCallResponse(CallToken token);
-
- // private data members
- SimService* sim_service_;
- NetworkService* network_service_;
- int32_t last_active_call_index_;
- std::map<int, CallStatus> active_calls_;
- bool in_emergency_mode_;
- bool mute_on_;
-};
-
-} // namespace
diff --git a/host/commands/modem_simulator/cf_device_config.cpp b/host/commands/modem_simulator/cf_device_config.cpp
deleted file mode 100644
index 559e1f8ac..000000000
--- a/host/commands/modem_simulator/cf_device_config.cpp
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2020 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 "common/libs/device_config/device_config.h"
-#include "host/commands/modem_simulator/device_config.h"
-#include "host/libs/config/cuttlefish_config.h"
-
-// this file provide cuttlefish hooks
-namespace cuttlefish {
-namespace modem {
-
-int DeviceConfig::host_port() {
- if (!cuttlefish::CuttlefishConfig::Get()) {
- return 6500;
- }
- auto config = cuttlefish::CuttlefishConfig::Get();
- auto instance = config->ForDefaultInstance();
- auto host_port = instance.host_port();
- return host_port;
-}
-
-std::string DeviceConfig::PerInstancePath(const char* file_name) {
- if (!cuttlefish::CuttlefishConfig::Get()) {
- return "";
- }
- auto config = cuttlefish::CuttlefishConfig::Get();
- auto instance = config->ForDefaultInstance();
- return instance.PerInstancePath(file_name);
-}
-
-std::string DeviceConfig::DefaultHostArtifactsPath(const std::string& file) {
- return cuttlefish::DefaultHostArtifactsPath(file);
-}
-
-std::string DeviceConfig::ril_address_and_prefix() {
- auto device_config_helper = cuttlefish::DeviceConfigHelper::Get();
- if (!device_config_helper) {
- return "10.0.2.15/24";
- }
- const auto& ril_config = device_config_helper->GetDeviceConfig().ril_config();
- return ril_config.ipaddr() + "/" + std::to_string(ril_config.prefixlen());
-};
-
-std::string DeviceConfig::ril_gateway() {
- auto device_config_helper = cuttlefish::DeviceConfigHelper::Get();
- if (!device_config_helper) {
- return "10.0.2.2";
- }
- const auto& ril_config = device_config_helper->GetDeviceConfig().ril_config();
- return ril_config.gateway();
-}
-
-std::string DeviceConfig::ril_dns() {
- auto device_config_helper = cuttlefish::DeviceConfigHelper::Get();
- if (!device_config_helper) {
- return "8.8.8.8";
- }
- const auto& ril_config = device_config_helper->GetDeviceConfig().ril_config();
- return ril_config.dns();
-}
-
-} // namespace modem
-} // namespace cuttlefish
diff --git a/host/commands/modem_simulator/channel_monitor.cpp b/host/commands/modem_simulator/channel_monitor.cpp
deleted file mode 100644
index e598f2de4..000000000
--- a/host/commands/modem_simulator/channel_monitor.cpp
+++ /dev/null
@@ -1,279 +0,0 @@
-
-//
-// Copyright (C) 2020 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 "host/commands/modem_simulator/channel_monitor.h"
-
-#include <android-base/logging.h>
-#include <android-base/strings.h>
-
-#include <algorithm>
-
-#include "host/commands/modem_simulator/modem_simulator.h"
-
-namespace cuttlefish {
-
-constexpr int32_t kMaxCommandLength = 4096;
-
-Client::Client(cuttlefish::SharedFD fd) : client_fd(fd) {}
-
-Client::Client(cuttlefish::SharedFD fd, ClientType client_type)
- : type(client_type), client_fd(fd) {}
-
-bool Client::operator==(const Client& other) const {
- return client_fd == other.client_fd;
-}
-
-void Client::SendCommandResponse(std::string response) const {
- if (response.empty()) {
- LOG(DEBUG) << "Invalid response, ignore!";
- return;
- }
-
- if (response.back() != '\r') {
- response += '\r';
- }
- LOG(VERBOSE) << " AT< " << response;
-
- std::lock_guard<std::mutex> autolock(const_cast<Client*>(this)->write_mutex);
- client_fd->Write(response.data(), response.size());
-}
-
-void Client::SendCommandResponse(
- const std::vector<std::string>& responses) const {
- for (auto& response : responses) {
- SendCommandResponse(response);
- }
-}
-
-ChannelMonitor::ChannelMonitor(ModemSimulator* modem,
- cuttlefish::SharedFD server)
- : modem_(modem), server_(server) {
- if (!cuttlefish::SharedFD::Pipe(&read_pipe_, &write_pipe_)) {
- LOG(ERROR) << "Unable to create pipe, ignore";
- }
-
- if (server_->IsOpen())
- monitor_thread_ = std::thread([this]() { MonitorLoop(); });
-}
-
-void ChannelMonitor::SetRemoteClient(cuttlefish::SharedFD client, bool is_accepted) {
- auto remote_client = std::make_unique<Client>(client, Client::REMOTE);
-
- if (is_accepted) {
- // There may be new data from remote client before select.
- remote_client->first_read_command_ = true;
- ReadCommand(*remote_client);
- }
-
- if (remote_client->client_fd->IsOpen()) {
- remote_client->first_read_command_ = false;
- remote_clients_.push_back(std::move(remote_client));
- LOG(DEBUG) << "added one remote client";
- }
-
- // Trigger monitor loop
- if (write_pipe_->IsOpen()) {
- write_pipe_->Write("OK", sizeof("OK"));
- } else {
- LOG(ERROR) << "Pipe created fail, can't trigger monitor loop";
- }
-}
-
-void ChannelMonitor::AcceptIncomingConnection() {
- auto client_fd = cuttlefish::SharedFD::Accept(*server_);
- if (!client_fd->IsOpen()) {
- LOG(ERROR) << "Error accepting connection on socket: " << client_fd->StrError();
- } else {
- auto client = std::make_unique<Client>(client_fd);
- LOG(DEBUG) << "added one RIL client";
- clients_.push_back(std::move(client));
- if (clients_.size() == 1) {
- // The first connected client default to be the unsolicited commands channel
- modem_->OnFirstClientConnected();
- }
- }
-}
-
-void ChannelMonitor::ReadCommand(Client& client) {
- std::vector<char> buffer(kMaxCommandLength);
- auto bytes_read = client.client_fd->Read(buffer.data(), buffer.size());
- if (bytes_read <= 0) {
- if (errno == EAGAIN && client.type == Client::REMOTE &&
- client.first_read_command_) {
- LOG(ERROR) << "After read 'REM' from remote client, and before select "
- "no new data come.";
- return;
- }
- LOG(DEBUG) << "Error reading from client fd: "
- << client.client_fd->StrError();
- client.client_fd->Close(); // Ignore errors here
- // Erase client from the vector clients
- auto& clients = client.type == Client::REMOTE ? remote_clients_ : clients_;
- auto iter = std::find_if(
- clients.begin(), clients.end(),
- [&](std::unique_ptr<Client>& other) { return *other == client; });
- if (iter != clients.end()) {
- clients.erase(iter);
- }
- return;
- }
-
- std::string& incomplete_command = client.incomplete_command;
-
- // Add the incomplete command from the last read
- auto commands = std::string{incomplete_command.data()};
- commands.append(buffer.data());
-
- incomplete_command.clear();
-
- // Replacing '\n' with '\r'
- commands = android::base::StringReplace(commands, "\n", "\r", true);
-
- // Split into commands and dispatch
- size_t pos = 0, r_pos = 0; // '\r' or '\n'
- while (r_pos != std::string::npos) {
- if (modem_->IsWaitingSmsPdu()) {
- r_pos = commands.find('\032', pos); // In sms, find ctrl-z
- } else {
- r_pos = commands.find('\r', pos);
- }
- if (r_pos != std::string::npos) {
- auto command = commands.substr(pos, r_pos - pos);
- if (command.size() > 0) { // "\r\r" ?
- LOG(VERBOSE) << "AT> " << command;
- modem_->DispatchCommand(client, command);
- }
- pos = r_pos + 1; // Skip '\r'
- } else if (pos < commands.length()) { // Incomplete command
- incomplete_command = commands.substr(pos);
- LOG(DEBUG) << "incomplete command: " << incomplete_command;
- }
- }
-}
-
-void ChannelMonitor::SendUnsolicitedCommand(std::string& response) {
- // The first accepted client default to be unsolicited command channel?
- auto iter = clients_.begin();
- if (iter != clients_.end()) {
- iter->get()->SendCommandResponse(response);
- } else {
- LOG(DEBUG) << "No client connected yet.";
- }
-}
-
-void ChannelMonitor::SendRemoteCommand(cuttlefish::SharedFD client, std::string& response) {
- auto iter = remote_clients_.begin();
- for (; iter != remote_clients_.end(); ++iter) {
- if (iter->get()->client_fd == client) {
- iter->get()->SendCommandResponse(response);
- return;
- }
- }
- LOG(DEBUG) << "Remote client has closed.";
-}
-
-void ChannelMonitor::CloseRemoteConnection(cuttlefish::SharedFD client) {
- auto iter = remote_clients_.begin();
- for (; iter != remote_clients_.end(); ++iter) {
- if (iter->get()->client_fd == client) {
- iter->get()->client_fd->Close();
- iter->get()->is_valid = false;
-
- // Trigger monitor loop
- if (write_pipe_->IsOpen()) {
- write_pipe_->Write("OK", sizeof("OK"));
- LOG(DEBUG) << "asking to remove clients";
- } else {
- LOG(ERROR) << "Pipe created fail, can't trigger monitor loop";
- }
- return;
- }
- }
- LOG(DEBUG) << "Remote client has been erased.";
-}
-
-ChannelMonitor::~ChannelMonitor() {
- if (write_pipe_->IsOpen()) {
- write_pipe_->Write("KO", sizeof("KO"));
- }
-
- if (monitor_thread_.joinable()) {
- LOG(DEBUG) << "waiting for monitor thread to join";
- monitor_thread_.join();
- }
-}
-
-static void removeInvalidClients(std::vector<std::unique_ptr<Client>>& clients) {
- auto iter = clients.begin();
- for (; iter != clients.end();) {
- if (iter->get()->is_valid) {
- ++iter;
- } else {
- LOG(DEBUG) << "removed 1 client";
- iter = clients.erase(iter);
- }
- }
-}
-
-void ChannelMonitor::MonitorLoop() {
- do {
- cuttlefish::SharedFDSet read_set;
- read_set.Set(server_);
- read_set.Set(read_pipe_);
- for (auto& client: clients_) {
- if (client->is_valid) read_set.Set(client->client_fd);
- }
- for (auto& client: remote_clients_) {
- if (client->is_valid) read_set.Set(client->client_fd);
- }
- int num_fds = cuttlefish::Select(&read_set, nullptr, nullptr, nullptr);
- if (num_fds < 0) {
- LOG(ERROR) << "Select call returned error : " << strerror(errno);
- // std::exit(kSelectError);
- break;
- } else if (num_fds > 0) {
- if (read_set.IsSet(server_)) {
- AcceptIncomingConnection();
- }
- if (read_set.IsSet(read_pipe_)) {
- std::string buf(2, ' ');
- read_pipe_->Read(buf.data(), buf.size()); // Empty pipe
- if (buf == std::string("KO")) {
- LOG(DEBUG) << "requested to exit now";
- break;
- }
- // clean the lists
- removeInvalidClients(clients_);
- removeInvalidClients(remote_clients_);
- }
- for (auto& client : clients_) {
- if (read_set.IsSet(client->client_fd)) {
- ReadCommand(*client);
- }
- }
- for (auto& client : remote_clients_) {
- if (read_set.IsSet(client->client_fd)) {
- ReadCommand(*client);
- }
- }
- } else {
- // Ignore errors here
- LOG(ERROR) << "Select call returned error : " << strerror(errno);
- }
- } while (true);
-}
-
-} // namespace cuttlefish
diff --git a/host/commands/modem_simulator/channel_monitor.h b/host/commands/modem_simulator/channel_monitor.h
deleted file mode 100644
index 6dc7c4a15..000000000
--- a/host/commands/modem_simulator/channel_monitor.h
+++ /dev/null
@@ -1,97 +0,0 @@
-//
-// Copyright (C) 2020 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 <mutex>
-#include <thread>
-#include <vector>
-
-#include "common/libs/fs/shared_select.h"
-
-namespace cuttlefish {
-
-class ModemSimulator;
-
-enum ModemSimulatorExitCodes : int {
- kSuccess = 0,
- kSelectError = 1,
- kServerError = 2,
-};
-
-/**
- * Client object managed by ChannelMonitor, contains two types, the RIL client
- * and the remote client of other cuttlefish instance.
- * Due to std::mutex does not implement its copy and operate= constructors, it
- * cann't be stored in standard contains (vector, map), so use the point instead.
- */
-class Client {
- public:
- enum ClientType { RIL, REMOTE };
-
- ClientType type = RIL;
- cuttlefish::SharedFD client_fd;
- std::string incomplete_command;
- std::mutex write_mutex;
- bool first_read_command_; // Only used when ClientType::REMOTE
- bool is_valid = true;
-
- Client() = default;
- ~Client() = default;
- Client(cuttlefish::SharedFD fd);
- Client(cuttlefish::SharedFD fd, ClientType client_type);
- Client(const Client& client) = delete;
- Client(Client&& client) = delete;
-
- Client& operator=(Client&& other) = delete;
-
- bool operator==(const Client& other) const;
-
- void SendCommandResponse(std::string response) const;
- void SendCommandResponse(const std::vector<std::string>& responses) const;
-};
-
-class ChannelMonitor {
- public:
- ChannelMonitor(ModemSimulator* modem, cuttlefish::SharedFD server);
- ~ChannelMonitor();
-
- ChannelMonitor(const ChannelMonitor&) = delete;
- ChannelMonitor& operator=(const ChannelMonitor&) = delete;
-
- void SetRemoteClient(cuttlefish::SharedFD client, bool is_accepted);
- void SendRemoteCommand(cuttlefish::SharedFD client, std::string& response);
- void CloseRemoteConnection(cuttlefish::SharedFD client);
-
- // For modem services to send unsolicited commands
- void SendUnsolicitedCommand(std::string& response);
-
- private:
- ModemSimulator* modem_;
- std::thread monitor_thread_;
- cuttlefish::SharedFD server_;
- cuttlefish::SharedFD read_pipe_;
- cuttlefish::SharedFD write_pipe_;
- std::vector<std::unique_ptr<Client>> clients_;
- std::vector<std::unique_ptr<Client>> remote_clients_;
-
- void AcceptIncomingConnection();
- void OnClientSocketClosed(int sock);
- void ReadCommand(Client& client);
-
- void MonitorLoop();
-};
-
-} // namespace cuttlefish
diff --git a/host/commands/modem_simulator/command_parser.cpp b/host/commands/modem_simulator/command_parser.cpp
deleted file mode 100644
index 9b95706e3..000000000
--- a/host/commands/modem_simulator/command_parser.cpp
+++ /dev/null
@@ -1,125 +0,0 @@
-//
-// Copyright (C) 2020 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 "host/commands/modem_simulator/command_parser.h"
-
-#include <sstream>
-#include <string>
-
-namespace cuttlefish {
-
-/**
- * Parses the next string between double quotes
- * returns the string on success and "" on fail
- * updates command_
- */
-std::string_view CommandParser::GetNextStr() {
- auto fpos = command_.find('\"');
- if (fpos == std::string_view::npos) {
- return {};
- }
-
- auto spos = command_.find('\"', fpos + 1);
- if (spos == std::string_view::npos) {
- command_ = command_.substr(fpos + 1);
- return {};
- }
-
- auto str = command_.substr(fpos + 1, (spos - fpos - 1));
- command_ = command_.substr(spos + 1);
- SkipComma();
- return str;
-}
-
-/**
- * Parses the next string before the flag
- * If flag not exists, returns the whole command_
- * updates command_
- */
-std::string_view CommandParser::GetNextStr(char flag) {
- auto pos = command_.find(flag);
- auto str = command_.substr(0, pos);
- if (pos != std::string_view::npos) pos += 1; // npos + 1 = 0
- command_.remove_prefix(std::min(pos, command_.size()));
- return str;
-}
-
-/**
- * Parses the next base 10 integer in the AT command and convert to upper case
- * hex string
- * returns the hex string on success and "" on fail
- * updates command_
- *
- * Specially, for AT+CRSM
- */
-std::string CommandParser::GetNextStrDeciToHex() {
- std::string str;
- int value = GetNextInt();
- if (value == -1) {
- return {};
- } else {
- std::stringstream ss;
- ss << std::hex << std::uppercase << value;
- return ss.str();
- }
-}
-
-static int parse_int(const std::string& snumber, int base) {
- if (snumber.empty()) return -1;
- const char* p = snumber.c_str();
- char* p_end = nullptr;
- errno = 0;
- const long lval = std::strtol(p, &p_end, base);
- if (p == p_end) {
- return -1;
- }
- const bool range_error = errno == ERANGE;
-
- if (range_error) return -1;
- return lval;
-}
-
-/**
- * Parses the next base 10 integer in the AT command
- * returns the value on success and -1 on fail
- * updates command_
- */
-int CommandParser::GetNextInt() {
- if (command_.empty()) {
- return -1;
- }
- std::string sub(GetNextStr(','));
-
- int value = parse_int(sub, 10);
-
- return value;
-}
-
-/**
- * Parses the next base 16 integer in the AT command
- * returns the value on success and -1 on fail
- * updates command_
- */
-int CommandParser::GetNextHexInt() {
- if (command_.empty()) {
- return -1;
- }
-
- std::string sub(GetNextStr(','));
- int value = parse_int(sub, 16);
- return value;
-}
-
-} // namespace cuttlefish
diff --git a/host/commands/modem_simulator/command_parser.h b/host/commands/modem_simulator/command_parser.h
deleted file mode 100644
index 7cde60bb1..000000000
--- a/host/commands/modem_simulator/command_parser.h
+++ /dev/null
@@ -1,98 +0,0 @@
-//
-// Copyright (C) 2020 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 <android-base/strings.h>
-
-#include <algorithm>
-#include <string>
-
-namespace cuttlefish {
-
-class CommandParser {
- public:
- explicit CommandParser(const std::string& command) : copy_command_(command) {
- command_ = copy_command_;
- };
-
- ~CommandParser() = default;
-
- CommandParser(CommandParser&&) = default;
- CommandParser& operator=(CommandParser&&) = default;
-
- inline void SkipPrefix();
- inline void SkipPrefixAT();
- inline void SkipComma();
- inline void SkipWhiteSpace();
-
- std::string_view GetNextStr();
- std::string_view GetNextStr(char flag);
- std::string GetNextStrDeciToHex(); /* for AT+CRSM */
-
- int GetNextInt();
- int GetNextHexInt();
-
- const std::string_view* operator->() const { return &command_; }
- const std::string_view& operator*() const { return command_; }
- bool operator==(const std::string &rhs) const { return command_ == rhs; }
- std::string_view::const_reference& operator[](int index) const { return command_[index]; }
-
- private:
- std::string copy_command_;
- std::string_view command_;
-};
-
-/**
- * Skip the substring before the first '=', including '='
- * updates command_
- * If '=' not exists, command_ remains unchanged
- */
-inline void CommandParser::SkipPrefix() {
- auto pos = command_.find('=');
- if (pos != std::string_view::npos) {
- command_.remove_prefix(std::min(pos + 1, command_.size()));
- }
-}
-
-/**
- * Skip the next "AT" substring
- * updates command_
- */
-inline void CommandParser::SkipPrefixAT() {
- android::base::ConsumePrefix(&command_, std::string_view("AT"));
-}
-
-/**
- * Skip the next comma
- * updates command_
- */
-inline void CommandParser::SkipComma() {
- auto pos = command_.find(',');
- if (pos != std::string_view::npos) {
- command_.remove_prefix(std::min(pos + 1, command_.size()));
- }
-}
-
-/**
- * Skip the next whitespace
- * updates command_
- */
-inline void CommandParser::SkipWhiteSpace() {
- auto pos = command_.find(' ');
- if (pos != std::string_view::npos) {
- command_.remove_prefix(std::min(pos + 1, command_.size()));
- }
-}
-
-} // namespace cuttlefish
diff --git a/host/commands/modem_simulator/data_service.cpp b/host/commands/modem_simulator/data_service.cpp
deleted file mode 100644
index b48a777fe..000000000
--- a/host/commands/modem_simulator/data_service.cpp
+++ /dev/null
@@ -1,344 +0,0 @@
-//
-// Copyright (C) 2020 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 "host/commands/modem_simulator/data_service.h"
-
-#include <android-base/strings.h>
-
-#include "host/commands/modem_simulator/device_config.h"
-
-namespace cuttlefish {
-
-DataService::DataService(int32_t service_id, ChannelMonitor* channel_monitor,
- ThreadLooper* thread_looper)
- : ModemService(service_id, this->InitializeCommandHandlers(),
- channel_monitor, thread_looper) {
- InitializeServiceState();
-}
-
-std::vector<CommandHandler> DataService::InitializeCommandHandlers() {
- std::vector<CommandHandler> command_handlers = {
- CommandHandler("+CGACT=",
- [this](const Client& client, std::string& cmd) {
- this->HandleActivateDataCall(client, cmd);
- }),
- CommandHandler("+CGACT?",
- [this](const Client& client) {
- this->HandleQueryDataCallList(client);
- }),
- CommandHandler("+CGDCONT=",
- [this](const Client& client, std::string& cmd) {
- this->HandlePDPContext(client, cmd);
- }),
- CommandHandler("+CGDCONT?",
- [this](const Client& client) {
- this->HandleQueryPDPContextList(client);
- }),
- CommandHandler("+CGQREQ=1",
- [this](const Client& client) {
- this->HandleCommandDefaultSupported(client);
- }),
- CommandHandler("+CGQMIN=1",
- [this](const Client& client) {
- this->HandleCommandDefaultSupported(client);
- }),
- CommandHandler("+CGEREP=1,0",
- [this](const Client& client) {
- this->HandleCommandDefaultSupported(client);
- }),
- CommandHandler("+CGDATA",
- [this](const Client& client, std::string& cmd) {
- this->HandleEnterDataState(client, cmd);
- }),
- CommandHandler("D*99***1#",
- [this](const Client& client) {
- this->HandleCommandDefaultSupported(client);
- }),
- CommandHandler("+CGCONTRDP",
- [this](const Client& client, std::string& cmd) {
- this->HandleReadDynamicParam(client, cmd);
- }),
- };
- return (command_handlers);
-}
-
-void DataService::InitializeServiceState() {
- // Initialize data connection config
-}
-
-/**
- * AT+CGACT
- * The execution command is used to activate or deactivate the specified PDP
- * context(s).
- *
- * Command Possible response(s)
- * +CGACT=[<state>[,<cid> OK
- * [,<cid>[,...]]]] +CME ERROR: <err>
- * +CGACT? [+CGACT: <cid>,<state>]
- * [<CR><LF>+CGACT: <cid>,<state>[...]]
- * <state>: integer type; indicates the state of PDP context activation.
- * 0: deactivated
- * 1: activated
- * <cid>: (PDP Context Identifier) integer(1~15), specifies the PDP context ID.
- *
- * see RIL_REQUEST_SETUP_DATA_CALL in RIL
- */
-void DataService::HandleActivateDataCall(const Client& client,
- const std::string& /*command*/) {
- client.SendCommandResponse("OK");
-}
-
-/**
- * see AT+CGACT
- */
-void DataService::HandleQueryDataCallList(const Client& client) {
- std::vector<std::string> responses;
-
- std::stringstream ss;
- for (auto iter = pdp_context_.begin(); iter != pdp_context_.end(); ++iter) {
- if (iter->state == PDPContext::ACTIVE) {
- ss.clear();
- ss << "+CGACT: " << iter->cid << "," << iter->state;
- responses.push_back(ss.str());
- ss.str("");
- }
- }
- responses.push_back("OK");
- client.SendCommandResponse(responses);
-}
-
-/**
- * AT+CGDCONT
- * The set command specifies PDP context parameter values for a PDP context
- * identified by the (local) context identification parameter, <cid>.
- *
- * Command Possible response(s)
- * +CGDCONT=[<cid>[,<PDP_type>[,<APN> OK
- * [,<PDP_addr>[,<d_comp> [,<h_comp>] +CME ERROR: <err>
- * ]]]]]
- * +CGDCONT? +CGDCONT: <cid>,<pdp_type>,<APN>,
- * <pdp_addr>,<d_comp>,<h_comp><CR><LF>
- * [+CGDCONT: <cid>,<pdp_type>,<APN>,
- * <pdp_addr>,<d_comp>,<h_comp><CR><LF>[...]]
- * OK
- * <cid>: see AT+CGACT
- * <PDP_type>: string type; specifies the type of packet data protocol.
- * Value: X.25, IP, IPV6, IPV4V6, OSPIH, PPP, Non-IP,Ethernet
- * <APN>: string type; a logical name that is used to select the GGSN or the
- * external packet data network.If the value is null or omitted, then
- * the subscription value will be requested
- * <PDP_addr>: string type; identifies the MT in the address space applicable
- * to the PDP
- * <d_comp>: integer type; controls PDP data compression
- * <h_comp>: integer type; controls PDP header compression
- *
- * see RIL_REQUEST_SETUP_DATA_CALL in RIL
- */
-void DataService::HandlePDPContext(const Client& client,
- const std::string& command) {
- CommandParser cmd(command);
- cmd.SkipPrefix(); /* skip +CGDCONT= */
- int cid = cmd.GetNextInt();
-
- std::string ip_type(cmd.GetNextStr(','));
- std::string apn(cmd.GetNextStr(','));
-
- auto address = cuttlefish::modem::DeviceConfig::ril_address_and_prefix();
- auto dnses = cuttlefish::modem::DeviceConfig::ril_dns();
- auto gateways = cuttlefish::modem::DeviceConfig::ril_gateway();
-
- PDPContext pdp_context = {cid,
- PDPContext::ACTIVE,
- ip_type, // IPV4 or IPV6 or IPV4V6
- apn,
- address,
- dnses,
- gateways};
-
- // check cid
- auto iter = pdp_context_.begin();
- for (; iter != pdp_context_.end(); ++iter) {
- if (pdp_context.cid == iter->cid) {
- *iter = pdp_context;
- break;
- }
- }
-
- if (iter == pdp_context_.end()) {
- pdp_context_.push_back(pdp_context);
- }
-
- client.SendCommandResponse("OK");
-}
-
-/**
- * see AT+CGDCONT above
- */
-void DataService::HandleQueryPDPContextList(const Client& client) {
- std::vector<std::string> responses;
-
- std::stringstream ss;
- for (auto it = pdp_context_.begin(); it != pdp_context_.end(); ++it) {
- std::stringstream ss;
- ss << "+CGDCONT: " << it->cid << "," << it->conn_types << ","
- << it->apn << "," << it->addresses << ",0,0";
- responses.push_back(ss.str());
- }
- responses.push_back("OK");
- client.SendCommandResponse(responses);
-}
-
-/**
- * AT+CGDATA
- * The execution command causes the MT to perform whatever actions are
- * necessary to establish communication between the TE and the network using
- * one or more Packet Domain PDP types.
- *
- * Command Possible response(s)
- * +CGDATA[=<L2P>[,[,<cid> CONNECT
- * [,...]]]] ERROR
- * +CME ERROR: <err>
- *
- * <L2P>: string type; indicates the layer 2 protocol to be used between the
- * TE and MT NULL none, for PDP type OSP:IHOSS (Obsolete)
- * value: PPP, PAD, X25, M-xxxx
- * <cid>: see AT+CGACT
- *
- * see RIL_REQUEST_SETUP_DATA_CALL in RIL
- */
-void DataService::HandleEnterDataState(const Client& client,
- const std::string& command) {
- std::string response;
-
- CommandParser cmd(command);
- cmd.SkipPrefix();
- cmd.SkipComma();
- int cid = cmd.GetNextInt();
-
- // Check cid
- auto iter = pdp_context_.begin();
- for (; iter != pdp_context_.end(); ++iter) {
- if (cid == iter->cid && iter->state == PDPContext::ACTIVE) {
- response = "CONNECT";
- break;
- }
- }
-
- if (iter == pdp_context_.end()) {
- response = "ERROR";
- }
-
- client.SendCommandResponse(response);
-}
-
-/**
- * AT+CGCONTRDP
- * The execution command returns the relevant information for an active non
- * secondary PDP context with the context identifier <cid>.
- *
- * Command Possible response(s)
- * +CGCONTRDP[=<cid>] [+CGCONTRDP: <cid>,<bearer_id>,<apn>
- * [,<local_addr and subnet_mask>[,<gw_addr>
- * [,<DNS_prim_addr>[<DNS_sec_addr>[...]]]]]]
- * [<CR><LF>+CGCONTRDP: <cid>,<bearer_id>,<apn>
- * [,<local_addr and subnet_mask>[,<gw_addr>
- * [,<DNS_prim_addr>[<DNS_sec_addr>[...]]]]]]
- *
- * <cid>: see AT+CGACT
- * <bearer_id>: integer type; identifies the bearer, i.e. the EPS bearer and
- * the NSAPI.
- * <local_addr and subnet_mask>: string type; shows the IP address and subnet
- * mask of the MT.
- * <gw_addr>: string type; shows the Gateway Address of the MT. The string is
- * given as dot-separated numeric (0-255) parameters.
- * <DNS_prim_addr>: string type; shows the IP address of the primary DNS server.
- * <DNS_sec_addr>: string type; shows the IP address of the secondary DNS server.
- *
- *
- * see RIL_REQUEST_SETUP_DATA_CALL in RIL
- */
-void DataService::HandleReadDynamicParam(const Client& client,
- const std::string& command) {
- std::vector<std::string> responses;
-
- CommandParser cmd(command);
- cmd.SkipPrefix(); /* skip prefix AT+CGCONTRDP= */
-
- int cid = cmd.GetNextInt();
- auto iter = pdp_context_.begin(); // Check cid
- for (; iter != pdp_context_.end(); ++iter) {
- if (cid == iter->cid && iter->state == PDPContext::ACTIVE) {
- break;
- }
- }
-
- if (iter == pdp_context_.end()) {
- responses.push_back(kCmeErrorInvalidIndex); // number
- } else {
- std::stringstream ss;
- ss << "+CGCONTRDP: "
- << iter->cid << ",5,"
- << iter->apn << ","
- << iter->addresses << ","
- << iter->gateways << ","
- << iter->dnses;
- responses.push_back(ss.str());
- responses.push_back("OK");
- }
-
- client.SendCommandResponse(responses);
-}
-
-void DataService::sendOnePhysChanCfgUpdate(int status, int bandwidth, int rat,
- int freq, int id) {
- std::stringstream ss;
- ss << "%CGFPCCFG: " << status << "," << bandwidth << "," << rat << "," << freq
- << "," << id;
- SendUnsolicitedCommand(ss.str());
-}
-
-void DataService::onUpdatePhysicalChannelconfigs(int modem_tech, int freq,
- int cellBandwidthDownlink) {
- updatePhysicalChannelconfigs(modem_tech, freq, cellBandwidthDownlink, 3);
-}
-
-void DataService::updatePhysicalChannelconfigs(int modem_tech, int freq,
- int cellBandwidthDownlink,
- int count) {
- if (count <= 0) {
- return;
- }
-
- const int PRIMARY_SERVING = 1;
- const int SECONDARY_SERVING = 2;
-
- for (const auto& iter : pdp_context_) {
- if (iter.state == PDPContext::ACTIVE) {
- sendOnePhysChanCfgUpdate(PRIMARY_SERVING, cellBandwidthDownlink,
- modem_tech, freq, iter.cid);
- sendOnePhysChanCfgUpdate(SECONDARY_SERVING, cellBandwidthDownlink,
- modem_tech, freq, iter.cid);
- }
- }
-
- // call again after 1 sec delay
- count--;
- thread_looper_->PostWithDelay(
- std::chrono::seconds(1),
- makeSafeCallback(this, &DataService::updatePhysicalChannelconfigs,
- modem_tech, freq, cellBandwidthDownlink, count));
-}
-
-} // namespace cuttlefish
diff --git a/host/commands/modem_simulator/data_service.h b/host/commands/modem_simulator/data_service.h
deleted file mode 100644
index 2da2d1c13..000000000
--- a/host/commands/modem_simulator/data_service.h
+++ /dev/null
@@ -1,63 +0,0 @@
-//
-// Copyright (C) 2020 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 "host/commands/modem_simulator/modem_service.h"
-
-namespace cuttlefish {
-
-class DataService : public ModemService, public std::enable_shared_from_this<DataService> {
- public:
- DataService(int32_t service_id, ChannelMonitor* channel_monitor,
- ThreadLooper* thread_looper);
- ~DataService() = default;
-
- DataService(const DataService &) = delete;
- DataService &operator=(const DataService &) = delete;
-
- void HandleActivateDataCall(const Client& client, const std::string& command);
- void HandleQueryDataCallList(const Client& client);
- void HandlePDPContext(const Client& client, const std::string& command);
- void HandleQueryPDPContextList(const Client& client);
- void HandleEnterDataState(const Client& client, const std::string& command);
- void HandleReadDynamicParam(const Client& client, const std::string& command);
-
- void onUpdatePhysicalChannelconfigs(int modem_tech, int freq,
- int cellBandwidthDownlink);
-
- private:
- std::vector<CommandHandler> InitializeCommandHandlers();
- void InitializeServiceState();
- void sendOnePhysChanCfgUpdate(int status, int bandwidth, int rat, int freq,
- int id);
- void updatePhysicalChannelconfigs(int modem_tech, int freq,
- int cellBandwidthDownlink, int count);
-
- struct PDPContext {
- enum CidState {ACTIVE, NO_ACTIVE};
-
- int cid;
- CidState state;
- std::string conn_types;
- std::string apn;
- std::string addresses;
- std::string dnses;
- std::string gateways;
- };
- std::vector<PDPContext> pdp_context_;
-};
-
-} // namespace cuttlefish
diff --git a/host/commands/modem_simulator/device_config.h b/host/commands/modem_simulator/device_config.h
deleted file mode 100644
index 05bca7785..000000000
--- a/host/commands/modem_simulator/device_config.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2020 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>
-
-// this file provide a few device (cvd or emulator) specific hooks for
-// modem-simulator
-
-namespace cuttlefish {
-namespace modem {
-
-class DeviceConfig {
- public:
- static int host_port();
- static std::string PerInstancePath(const char* file_name);
- static std::string DefaultHostArtifactsPath(const std::string& file);
- static std::string ril_address_and_prefix();
- static std::string ril_gateway();
- static std::string ril_dns();
-};
-
-} // namespace modem
-} // namespace cuttlefish
diff --git a/host/commands/modem_simulator/files/iccprofile_for_sim0.xml b/host/commands/modem_simulator/files/iccprofile_for_sim0.xml
deleted file mode 100755
index 655c37a96..000000000
--- a/host/commands/modem_simulator/files/iccprofile_for_sim0.xml
+++ /dev/null
@@ -1,181 +0,0 @@
-<IccProfile>
-<MF path="3F00">
- <EF name="EF_DIR" id="2F00" structure="linear fixed">
- <SIMIO cmd="C0" p1="0" p2="0" p3="F" data="">144,0,621A8205422100300483022F008A01058B032F0601800200C08801F0</SIMIO>
- <SIMIO cmd="B2" p1="1" p2="4" p3="30" data="">144,0,61184F10A0000003431002FF86FF0389FFFFFFFF50044353494DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="2" p2="4" p3="30" data="">144,0,61184F10A0000000871002FF86FF0389FFFFFFFF50045553494DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="3" p2="4" p3="30" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="4" p2="4" p3="30" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- </EF>
- <EF name="EF_ICCID" id="2FE2" structure="transparent">
- <SIMIO cmd="C0" p1="0" p2="0" p3="F" data="">144,0,62178202412183022FE28A01058B032F06038002000A880110</SIMIO>
- <SIMIO cmd="B0" p1="0" p2="0" p3="A" data="">144,0,98683081462002318379</SIMIO>
- <!-- Special ATC to read ICCID from modem cache -->
- <CCID>89860318640220133897</CCID>
- </EF>
- <EF name="EF_PL" id="2F05" structure="transparent">
- <SIMIO cmd="C0" p1="0" p2="0" p3="F" data="">144,0,62178202412183022F058A01058B032F060280020004880128</SIMIO>
- <SIMIO cmd="B0" p1="0" p2="0" p3="4" data="">144,0,FFFFFFFF</SIMIO>
- </EF>
-
- <DF name="TELECOM" path="7F10">
- <DF name="PHONEBOOK" path="5F3A">
- <EF name="EF_PBR" id="4F30" structure="linear fixed">
- <SIMIO cmd="C0" p1="0" p2="0" p3="F" data="">144,0,62198205422100400283024F308A01058B036F0606800200808800</SIMIO>
- <SIMIO cmd="B2" p1="1" p2="4" p3="40" data="">144,0,A81EC0034F3A01C1034F3306C5034F0902C4034F1104C6034F2503C9034F3107A905CA034F5008AA0FC2034F4A09C7034F4B0AC8034F4C0BFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="2" p2="4" p3="40" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- </EF>
- <EF name="EF_GAS" id="4F4C" structure="linear fixed">
- <SIMIO cmd="C0" p1="0" p2="0" p3="F" data="">144,0,621A8205422100140A83024F4C8A01058B036F060E800200C8880158</SIMIO>
- <SIMIO cmd="B2" p1="1" p2="4" p3="E" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="2" p2="4" p3="E" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="3" p2="4" p3="E" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="4" p2="4" p3="E" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="5" p2="4" p3="E" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="6" p2="4" p3="E" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="7" p2="4" p3="E" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="8" p2="4" p3="E" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="9" p2="4" p3="E" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="A" p2="4" p3="E" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- </EF>
- <EF name="EF_ADN" id="4F3A" structure="linear fixed">
- <SIMIO cmd="C0" p1="0" p2="0" p3="F" data="">144,0,621A82054221001C1483024F3A8A01058B036F060E80020230880108</SIMIO>
- <SIMIO cmd="B2" p1="1" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="2" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="3" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="4" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="5" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="6" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="7" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="8" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="9" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="A" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="B" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="C" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="D" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="E" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="F" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="10" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="11" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="12" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="13" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="14" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- </EF>
- <EF name="EF_IAP" id="4F33" structure="linear fixed">
- <SIMIO cmd="C0" p1="0" p2="0" p3="F" data="">144,0,621A820542210001FA83024F338A01058B036F060E800200FA880130</SIMIO>
- </EF>
- <EF name="EF_PBC" id="4F09" structure="linear fixed">
- <SIMIO cmd="C0" p1="0" p2="0" p3="F" data="">144,0,621A820542210002FA83024F098A01058B036F060E800201F4880110</SIMIO>
- </EF>
- <EF name="EF_ANR" id="4F11" structure="linear fixed">
- <SIMIO cmd="C0" p1="0" p2="0" p3="F" data="">144,0,621A82054221000FFA83024F118A01058B036F060E80020EA6880120</SIMIO>
- </EF>
- <!-- EF_SNE, EF_AAS, EF_EXT1, EF_GRP, EF_UID, EF_EMAIL, EF_CCP1, EF_PUR1 ... -->
- </DF>
- </DF>
-
- <ADF name="USIM" path="7FFF" aid="A0000000871002FF86FF0389FFFFFFFF">
- <EF name="EF_IMSI" id="6F07" structure="transparent">
- <CIMI>311740123456789</CIMI>
- </EF>
- <EF name="EF_MSISDN" id="6F40" structure="linear fixed">
- <SIMIO cmd="C0" p1="0" p2="0" p3="F" data="">144,0,621982054221001C0283026F408A01058B036F0605800200388800</SIMIO>
- <SIMIO cmd="B2" p1="1" p2="4" p3="1C" data="">144,0,000000000000000000000000000007915155214365F7FFFFFFFFFFFF</SIMIO>
- </EF>
- <EF name="EF_MBI" id="6FC9" structure="linear fixed">
- <SIMIO cmd="C0" p1="0" p2="0" p3="F" data="">144,0,62198205422100050183026FC98A01058B036F0602800200058800</SIMIO>
- <SIMIO cmd="B2" p1="1" p2="4" p3="5" data="">144,0,0100000000</SIMIO>
- </EF>
- <EF name="EF_MBDN" id="6FC7" structure="linear fixed">
- <SIMIO cmd="C0" p1="0" p2="0" p3="F" data="">144,0,621982054221001C0283026F408A01058B036F06058002003E8800</SIMIO>
- <SIMIO cmd="B2" p1="1" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF07915155674523F1FFFFFFFFFFFF</SIMIO>
- </EF>
- <EF name="EF_AD" id="6FAD" structure="transparent">
- <SIMIO cmd="C0" p1="0" p2="0" p3="F" data="">144,0,62178202412183026FAD8A01058B036F060180020004880118</SIMIO>
- <SIMIO cmd="B0" p1="0" p2="0" p3="4" data="">144,0,00000003</SIMIO>
- </EF>
- <EF name="EF_MWIS" id="6FCA" structure="linear fixed">
- <SIMIO cmd="C0" p1="0" p2="0" p3="F" data="">144,0,62198205422100050183026FCA8A01058B036F060E800200058800</SIMIO>
- <SIMIO cmd="B2" p1="1" p2="4" p3="5" data="">144,0,0000000000</SIMIO>
- </EF>
- <EF name="EF_VOICE_MAIL_INDICATOR_CPHS" id="6F11" structure="transparent">
- <SIMIO cmd="C0" p1="0" p2="0" p3="F" data="">106,130</SIMIO>
- </EF>
- <EF name="EF_FPLMN" id="6F7B" structure="transparent">
- <SIMIO cmd="C0" p1="0" p2="0" p3="F" data="">144,0,621C8202412183026F7BA5038001718A01058B036F06038002001E880168</SIMIO>
- <SIMIO cmd="B0" p1="0" p2="0" p3="1E" data="">144,0,64F00064F02064F04064F07064F080FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- </EF>
- <EF name="EF_FDN" id="6F3B" structure="linear fixed">
- <SIMIO cmd="C0" p1="0" p2="0" p3="F" data="">144,0,621982054221001C0A83026F3B8A01058B036F0605800201188800</SIMIO>
- <SIMIO cmd="B2" p1="1" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="2" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="3" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="4" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="5" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="6" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="7" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="8" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="9" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="A" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- </EF>
- <!-- Other USIM files... -->
- </ADF>
-</MF>
-
-<ADF name="PKCS15" aid="A000000063504B43532D3135">
- <CGLA cmd="A40004025031">4,6124</CGLA>
- <CGLA cmd="C0000024">76,62228202412183025031A503C001408A01058B066F0601010001800200108102002288009000 </CGLA>
- <CGLA cmd="B0000010">36,A706300404024401A5063004040244029000</CGLA>
-</ADF>
-
-<ADF name="" aid="">
- <CSIM cmd='10,"0070000001"'>6,019000</CSIM>
- <CGLA cmd='1,14,"81F2FF0000"'>4,6b00</CGLA>
- <!-- more CGLA Command -->
-</ADF>
-
-<PinProfile>
- <!-- PIN: PINSTATE_ENABLED_NOT_VERIFIED -->
- <!-- PUK: PINSTATE_ENABLED_BLOCKED -->
- <!-- Ready: PINSTATE_UNKNOWN -->
- <PINSTATE>PINSTATE_UNKNOWN</PINSTATE>
- <PINCODE>1234</PINCODE>
- <PUKCODE>12345678</PUKCODE>
- <PINREMAINTIMES>3</PINREMAINTIMES>
- <PUKREMAINTIMES>10</PUKREMAINTIMES>
- <PIN2CODE>1234</PIN2CODE>
- <PUK2CODE>12345678</PUK2CODE>
- <PIN2REMAINTIMES>3</PIN2REMAINTIMES>
- <PUK2REMAINTIMES>10</PUK2REMAINTIMES>
-</PinProfile>
-
-<FacilityLock>
- <SC>DISABLE</SC>
- <FD>DISABLE</FD>
- <AO>DISABLE</AO>
- <OI>DISABLE</OI>
- <AI>DISABLE</AI>
- <IR>DISABLE</IR>
- <AB>DISABLE</AB>
- <AG>DISABLE</AG>
- <AC>DISABLE</AC>
-</FacilityLock>
-
-<SETUPMENU cmd="25" text="D0388103012500820281820509804E2D56FD79FB52A88F10508000530049004D5FEB6377786E8BA48F104E80005500530049004D53614FE1606F">
- <SELECTITEM id="1" cmd="24" menuId="50" text="D02D8103012400820281828F0A018053E34EE48BBE7F6E8F0A02804E1A52A14ECB7ECD8F0A0380724867434FE1606F">
- <SELECTITEM id="1" cmd="24" menuId="01" text="D0218103012400820281828F0A01806DFB52A083DC53558F0A02805220966483DC5355">
- <DISPLAYTEXT id="1" cmd="21" menuId="01" text="D0228103012181820281028D1708662F542666F465B04E0B8F7D83DC535552178868FF1F"></DISPLAYTEXT>
- <DISPLAYTEXT id="2" cmd="21" menuId="02" text="D01A8103012101820281028D0F0883DC5355522096646210529FFF01"></DISPLAYTEXT>
- </SELECTITEM>
- <DISPLAYTEXT id="2" cmd="21" menuId="02" text="D081BB8103012181820281028D81AF08201C00530049004D5FEB6377786E8BA4201D662F4E2D56FD79FB52A863D04F9B7684FF0C57FA4E8E624B673A00530049004D53617684727982725B8951688EAB4EFD8BA48BC1670D52A1300276F86BD44F207EDF75286237540D5BC678018BA48BC165B95F0FFF0C5B83517767094E0D53EF62E6622A30014E0D4F208F935BC6780130014F7F75285FEB63777B49727970B9FF0C662F60A87545884C4E9280547F5176848EAB4EFD536B58EB3002"></DISPLAYTEXT>
- <DISPLAYTEXT id="3" cmd="21" menuId="03" text="D02E8103012181820281028D23084E2D56FD79FB52A8901A4FE167099650516C53F8FF0C0031002E00307248672C3002">
- </DISPLAYTEXT>
- </SELECTITEM>
- <SELECTITEM id="2" cmd="24" menuId="4E" text="D04E810301240082028182850F80005500530049004D53614FE1606F8F0A0180536172477C7B578B8F14028075358BDD53F7780153CA77ED4FE15BB991CF8F100380004F00540041529F80FD4ECB7ECD">
- <DISPLAYTEXT id="1" cmd="21" menuId="01" text="D03A8103012181820281028D2F08666E901A005500530049004D5361002000560032002E003000410027FF0C652F6301004F005400410033529F80FD"></DISPLAYTEXT>
- <DISPLAYTEXT id="2" cmd="21" menuId="02" text="D05C8103012181820281028D510875358BDD53F77801672C5B5850A85BB991CF0035003000306761FF0C5DF2752875358BDD672C003100336761FF0C77ED4FE15B5850A85BB991CF003500306761FF0C5DF2752877ED4FE1003400396761"></DISPLAYTEXT>
- <DISPLAYTEXT id="3" cmd="21" menuId="03" text="D05E8103012181820281028D5308004F00540041529F80FD53EF5229752877ED4FE1606F901A9053FF0C5E2E52A95BA262375B9E73B0005500530049004D536151854E1A52A183DC5355768452A860014E0B8F7D3001522096644E0E66F465B0"></DISPLAYTEXT>
- </SELECTITEM>
-</SETUPMENU>
-
-</IccProfile>
diff --git a/host/commands/modem_simulator/files/iccprofile_for_sim0_for_CtsCarrierApiTestCases.xml b/host/commands/modem_simulator/files/iccprofile_for_sim0_for_CtsCarrierApiTestCases.xml
deleted file mode 100755
index b4363da93..000000000
--- a/host/commands/modem_simulator/files/iccprofile_for_sim0_for_CtsCarrierApiTestCases.xml
+++ /dev/null
@@ -1,207 +0,0 @@
-<IccProfile>
-<MF path="3F00">
- <EF name="EF_DIR" id="2F00" structure="linear fixed">
- <SIMIO cmd="C0" p1="0" p2="0" p3="F" data="">144,0,621A8205422100300483022F008A01058B032F0601800200C08801F0</SIMIO>
- <SIMIO cmd="B2" p1="1" p2="4" p3="30" data="">144,0,61184F10A0000003431002FF86FF0389FFFFFFFF50044353494DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="2" p2="4" p3="30" data="">144,0,61184F10A0000000871002FF86FF0389FFFFFFFF50045553494DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="3" p2="4" p3="30" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="4" p2="4" p3="30" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- </EF>
- <EF name="EF_ICCID" id="2FE2" structure="transparent">
- <SIMIO cmd="C0" p1="0" p2="0" p3="F" data="">144,0,62178202412183022FE28A01058B032F06038002000A880110</SIMIO>
- <SIMIO cmd="B0" p1="0" p2="0" p3="A" data="">144,0,98683081462002318379</SIMIO>
- <!-- Special ATC to read ICCID from modem cache -->
- <CCID>89860318640220133897</CCID>
- </EF>
- <EF name="EF_PL" id="2F05" structure="transparent">
- <SIMIO cmd="C0" p1="0" p2="0" p3="F" data="">144,0,62178202412183022F058A01058B032F060280020004880128</SIMIO>
- <SIMIO cmd="B0" p1="0" p2="0" p3="4" data="">144,0,FFFFFFFF</SIMIO>
- </EF>
-
- <DF name="TELECOM" path="7F10">
- <DF name="PHONEBOOK" path="5F3A">
- <EF name="EF_PBR" id="4F30" structure="linear fixed">
- <SIMIO cmd="C0" p1="0" p2="0" p3="F" data="">144,0,62198205422100400283024F308A01058B036F0606800200808800</SIMIO>
- <SIMIO cmd="B2" p1="1" p2="4" p3="40" data="">144,0,A81EC0034F3A01C1034F3306C5034F0902C4034F1104C6034F2503C9034F3107A905CA034F5008AA0FC2034F4A09C7034F4B0AC8034F4C0BFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="2" p2="4" p3="40" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- </EF>
- <EF name="EF_GAS" id="4F4C" structure="linear fixed">
- <SIMIO cmd="C0" p1="0" p2="0" p3="F" data="">144,0,621A8205422100140A83024F4C8A01058B036F060E800200C8880158</SIMIO>
- <SIMIO cmd="B2" p1="1" p2="4" p3="E" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="2" p2="4" p3="E" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="3" p2="4" p3="E" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="4" p2="4" p3="E" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="5" p2="4" p3="E" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="6" p2="4" p3="E" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="7" p2="4" p3="E" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="8" p2="4" p3="E" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="9" p2="4" p3="E" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="A" p2="4" p3="E" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- </EF>
- <EF name="EF_ADN" id="4F3A" structure="linear fixed">
- <SIMIO cmd="C0" p1="0" p2="0" p3="F" data="">144,0,621A82054221001C1483024F3A8A01058B036F060E80020230880108</SIMIO>
- <SIMIO cmd="B2" p1="1" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="2" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="3" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="4" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="5" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="6" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="7" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="8" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="9" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="A" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="B" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="C" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="D" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="E" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="F" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="10" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="11" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="12" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="13" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="14" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- </EF>
- <EF name="EF_IAP" id="4F33" structure="linear fixed">
- <SIMIO cmd="C0" p1="0" p2="0" p3="F" data="">144,0,621A820542210001FA83024F338A01058B036F060E800200FA880130</SIMIO>
- </EF>
- <EF name="EF_PBC" id="4F09" structure="linear fixed">
- <SIMIO cmd="C0" p1="0" p2="0" p3="F" data="">144,0,621A820542210002FA83024F098A01058B036F060E800201F4880110</SIMIO>
- </EF>
- <EF name="EF_ANR" id="4F11" structure="linear fixed">
- <SIMIO cmd="C0" p1="0" p2="0" p3="F" data="">144,0,621A82054221000FFA83024F118A01058B036F060E80020EA6880120</SIMIO>
- </EF>
- <!-- EF_SNE, EF_AAS, EF_EXT1, EF_GRP, EF_UID, EF_EMAIL, EF_CCP1, EF_PUR1 ... -->
- </DF>
- </DF>
-
- <ADF name="USIM" path="7FFF" aid="A0000000871002FF86FF0389FFFFFFFF">
- <EF name="EF_IMSI" id="6F07" structure="transparent">
- <CIMI>310260000000000</CIMI>
- </EF>
- <EF name="EF_MSISDN" id="6F40" structure="linear fixed">
- <SIMIO cmd="C0" p1="0" p2="0" p3="F" data="">144,0,621982054221001C0283026F408A01058B036F0605800200388800</SIMIO>
- <SIMIO cmd="B2" p1="1" p2="4" p3="1C" data="">144,0,00000000000000000000000000000891688118109844F0FFFFFFFFFF</SIMIO>
- </EF>
- <EF name="EF_MBI" id="6FC9" structure="linear fixed">
- <SIMIO cmd="C0" p1="0" p2="0" p3="F" data="">144,0,62258205422100040183026FC9A503C001408A01058B066F060103000080020004810200188800</SIMIO>
- <SIMIO cmd="B2" p1="1" p2="4" p3="4" data="">144,0,01000000</SIMIO>
- </EF>
- <EF name="EF_AD" id="6FAD" structure="transparent">
- <SIMIO cmd="C0" p1="0" p2="0" p3="F" data="">144,0,62178202412183026FAD8A01058B036F060180020004880118</SIMIO>
- <SIMIO cmd="B0" p1="0" p2="0" p3="4" data="">144,0,00000002</SIMIO>
- </EF>
- <EF name="EF_MBDN" id="6FC7" structure="linear fixed">
- <SIMIO cmd="C0" p1="0" p2="0" p3="F" data="">144,0,62258205422100260483026FC7A503C001408A01058B066F060103000080020098810200AC8800</SIMIO>
- <SIMIO cmd="DC" p1="1" p2="4" p3="26" data="74616741FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF06812143658709FFFFFFFFFFFFFF">144,0</SIMIO>
- <SIMIO cmd="DC" p1="1" p2="4" p3="26" data="74616742FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF06819078563412FFFFFFFFFFFFFF">144,0</SIMIO>
- <SIMIO cmd="DC" p1="1" p2="4" p3="26" data="FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF">144,0</SIMIO>
- </EF>
- <EF name="EF_MWIS" id="6FCA" structure="linear fixed">
- <SIMIO cmd="C0" p1="0" p2="0" p3="F" data="">144,0,62198205422100050183026FCA8A01058B036F060E800200058800</SIMIO>
- <SIMIO cmd="B2" p1="1" p2="4" p3="5" data="">144,0,0000000000</SIMIO>
- </EF>
- <EF name="EF_VOICE_MAIL_INDICATOR_CPHS" id="6F11" structure="transparent">
- <SIMIO cmd="C0" p1="0" p2="0" p3="F" data="">106,130</SIMIO>
- </EF>
- <EF name="EF_FPLMN" id="6F7B" structure="transparent">
- <SIMIO cmd="C0" p1="0" p2="0" p3="F" data="">144,0,621C8202412183026F7BA5038001718A01058B036F06038002001E880168</SIMIO>
- <SIMIO cmd="B0" p1="0" p2="0" p3="1E" data="">144,0,64F00064F02064F04064F07064F080FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- </EF>
- <EF name="EF_FDN" id="6F3B" structure="linear fixed">
- <SIMIO cmd="C0" p1="0" p2="0" p3="F" data="">144,0,621982054221001C0A83026F3B8A01058B036F0605800201188800</SIMIO>
- <SIMIO cmd="B2" p1="1" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="2" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="3" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="4" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="5" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="6" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="7" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="8" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="9" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="A" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- </EF>
- <!-- Other USIM files... -->
- </ADF>
-</MF>
-
-<ADF name="PKCS15" aid="A000000063504B43532D3135">
- <File id="4300">
- <CGLA cmd="00a40004024300">76,62228202412183024300A503C001408A01058B066F0601010001800201DC810201EE88009000</CGLA>
- <CGLA cmd="00b0000000">516,30088200300404024310301AA0120410A000000476416E64726F696443545340300404024311301AA0120410A000000476416E64726F696443545341300404024312301AA0120410A000000476416E64726F696443545342300404024313301AA0120410A000000476416E64726F696443545343300404024314301AA0120410A000000476416E64726F696443545344300404024315301AA0120410A000000476416E64726F696443545345300404024316301AA0120410A000000476416E64726F6964435453463004040243173010A0080406FFFFFFFFFFFF300404024318301AA0120410A000000476416E64726F696443545347300404024313301AA0129000</CGLA>
- </File>
- <File id="4318">
- <CGLA cmd="00a40004024318">76,62228202412183024318A503C001408A01058B066F0601010001800200188102002A88009000</CGLA>
- <CGLA cmd="00b0000000">124,3016041461ED377E85D386A8DFEE6B864BD85B0BFAA5AF8130220420CE7B2B47AE2B7552C8F92CC29124279883041FB623A5F194A82C9BF15D492AA09000</CGLA>
- </File>
-</ADF>
-
-<ADF name="" aid="CSIM">
- <CSIM cmd="0070000001">6,019000</CSIM>
- <CSIM cmd="80f2000000">110,62338202782183023F00A50C80016187010183040007DBF08A01058B062F0601020002C60C90016083010183010A83010D8102FFFF9000</CSIM>
- <CSIM cmd="0070000000">6,019000</CSIM>
- <CSIM cmd="0070800100">4,9000</CSIM>
- <CSIM cmd="80F20000">4,6C35</CSIM>
- <CGLA cmd="00A40000023F00">4,6B00</CGLA>
- <CGLA cmd="00A4000C023F00">4,9000</CGLA>
- <CGLA cmd="00ff000000">4,6D00</CGLA>
- <CGLA cmd="81f2ff0000">4,6B00</CGLA>
- <CGLA cmd="00a4000c02FFFF">4,6A82</CGLA>
- <CGLA cmd="0170830100">4,6A81</CGLA>
- <CGLA cmd="fff2000000">4,6E00</CGLA>
- <CGLA cmd="00a4000c022FE2">4,9000</CGLA>
- <CGLA cmd="00b0000000">24,983311111111111111029000</CGLA>
- <CGLA cmd="00a40004022F06">78,622382054221004A1283022F06A503C001408A01058B062F060101000080020534810205489000</CGLA>
- <!-- more CSIM Command -->
-</ADF>
-
-<ADF name="" aid="">
- <CSIM cmd='10,"0070000001"'>6,019000</CSIM>
- <CGLA cmd='1,14,"81F2FF0000"'>4,6b00</CGLA>
- <!-- more CGLA Command -->
-</ADF>
-
-<PinProfile>
- <!-- PIN: PINSTATE_ENABLED_NOT_VERIFIED -->
- <!-- PUK: PINSTATE_ENABLED_BLOCKED -->
- <!-- Ready: PINSTATE_UNKNOWN -->
- <PINSTATE>PINSTATE_UNKNOWN</PINSTATE>
- <PINCODE>1234</PINCODE>
- <PUKCODE>12345678</PUKCODE>
- <PINREMAINTIMES>3</PINREMAINTIMES>
- <PUKREMAINTIMES>10</PUKREMAINTIMES>
- <PIN2CODE>1234</PIN2CODE>
- <PUK2CODE>12345678</PUK2CODE>
- <PIN2REMAINTIMES>3</PIN2REMAINTIMES>
- <PUK2REMAINTIMES>10</PUK2REMAINTIMES>
-</PinProfile>
-
-<FacilityLock>
- <SC>DISABLE</SC>
- <FD>DISABLE</FD>
- <AO>DISABLE</AO>
- <OI>DISABLE</OI>
- <AI>DISABLE</AI>
- <IR>DISABLE</IR>
- <AB>DISABLE</AB>
- <AG>DISABLE</AG>
- <AC>DISABLE</AC>
-</FacilityLock>
-
-<SETUPMENU cmd="25" text="D0388103012500820281820509804E2D56FD79FB52A88F10508000530049004D5FEB6377786E8BA48F104E80005500530049004D53614FE1606F">
- <SELECTITEM id="1" cmd="24" menuId="50" text="D02D8103012400820281828F0A018053E34EE48BBE7F6E8F0A02804E1A52A14ECB7ECD8F0A0380724867434FE1606F">
- <SELECTITEM id="1" cmd="24" menuId="01" text="D0218103012400820281828F0A01806DFB52A083DC53558F0A02805220966483DC5355">
- <DISPLAYTEXT id="1" cmd="21" menuId="01" text="D0228103012181820281028D1708662F542666F465B04E0B8F7D83DC535552178868FF1F"></DISPLAYTEXT>
- <DISPLAYTEXT id="2" cmd="21" menuId="02" text="D01A8103012101820281028D0F0883DC5355522096646210529FFF01"></DISPLAYTEXT>
- </SELECTITEM>
- <DISPLAYTEXT id="2" cmd="21" menuId="02" text="D081BB8103012181820281028D81AF08201C00530049004D5FEB6377786E8BA4201D662F4E2D56FD79FB52A863D04F9B7684FF0C57FA4E8E624B673A00530049004D53617684727982725B8951688EAB4EFD8BA48BC1670D52A1300276F86BD44F207EDF75286237540D5BC678018BA48BC165B95F0FFF0C5B83517767094E0D53EF62E6622A30014E0D4F208F935BC6780130014F7F75285FEB63777B49727970B9FF0C662F60A87545884C4E9280547F5176848EAB4EFD536B58EB3002"></DISPLAYTEXT>
- <DISPLAYTEXT id="3" cmd="21" menuId="03" text="D02E8103012181820281028D23084E2D56FD79FB52A8901A4FE167099650516C53F8FF0C0031002E00307248672C3002">
- </DISPLAYTEXT>
- </SELECTITEM>
- <SELECTITEM id="2" cmd="24" menuId="4E" text="D04E810301240082028182850F80005500530049004D53614FE1606F8F0A0180536172477C7B578B8F14028075358BDD53F7780153CA77ED4FE15BB991CF8F100380004F00540041529F80FD4ECB7ECD">
- <DISPLAYTEXT id="1" cmd="21" menuId="01" text="D03A8103012181820281028D2F08666E901A005500530049004D5361002000560032002E003000410027FF0C652F6301004F005400410033529F80FD"></DISPLAYTEXT>
- <DISPLAYTEXT id="2" cmd="21" menuId="02" text="D05C8103012181820281028D510875358BDD53F77801672C5B5850A85BB991CF0035003000306761FF0C5DF2752875358BDD672C003100336761FF0C77ED4FE15B5850A85BB991CF003500306761FF0C5DF2752877ED4FE1003400396761"></DISPLAYTEXT>
- <DISPLAYTEXT id="3" cmd="21" menuId="03" text="D05E8103012181820281028D5308004F00540041529F80FD53EF5229752877ED4FE1606F901A9053FF0C5E2E52A95BA262375B9E73B0005500530049004D536151854E1A52A183DC5355768452A860014E0B8F7D3001522096644E0E66F465B0"></DISPLAYTEXT>
- </SELECTITEM>
-</SETUPMENU>
-
-</IccProfile>
diff --git a/host/commands/modem_simulator/files/numeric_operator.xml b/host/commands/modem_simulator/files/numeric_operator.xml
deleted file mode 100644
index 202c84b40..000000000
--- a/host/commands/modem_simulator/files/numeric_operator.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <add-resource name="numeric_to_operator" type="array"/>
- <string-array name="numeric_to_operator">
- <item numeric="311740">TelAlaska=TelAlaska</item>
- <item numeric="310260">T-Mobile=TMOBILE</item>
- <item numeric="46000">China Mobile=CMCC</item>
- <item numeric="46001">China UNICOM=UNICOM</item>
- <item numeric="46002">China Mobile=CMCC</item>
- <item numeric="46003">China Telecom=CT</item>
- <item numeric="46004">China Mobile=CMCC</item>
- <item numeric="46005">China Telecom=CT</item>
- <item numeric="46006">China UNICOM=UNICOM</item>
- <item numeric="46007">China Mobile=CMCC</item>
- <item numeric="46008">China Mobile=CMCC</item>
- <item numeric="46009">China UNICOM=UNICOM</item>
- <item numeric="46011">China Telecom=CT</item>
- </string-array>
-</resources>
diff --git a/host/commands/modem_simulator/main.cpp b/host/commands/modem_simulator/main.cpp
deleted file mode 100644
index 794ad77bd..000000000
--- a/host/commands/modem_simulator/main.cpp
+++ /dev/null
@@ -1,163 +0,0 @@
-//
-// Copyright (C) 2020 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 <android-base/strings.h>
-#include <gflags/gflags.h>
-#include <signal.h>
-#include <unistd.h>
-
-#include <limits>
-
-#include "common/libs/device_config/device_config.h"
-#include "common/libs/fs/shared_buf.h"
-#include "common/libs/fs/shared_fd.h"
-#include "common/libs/utils/tee_logging.h"
-#include "host/commands/modem_simulator/modem_simulator.h"
-#include "host/libs/config/cuttlefish_config.h"
-
-// we can start multiple modems simultaneously; each modem
-// will listent to one server fd for incoming sms/phone call
-// there should be at least 1 valid fd
-DEFINE_string(server_fds, "", "A comma separated list of file descriptors");
-DEFINE_int32(sim_type, 1, "Sim type: 1 for normal, 2 for CtsCarrierApiTestCases");
-
-std::vector<cuttlefish::SharedFD> ServerFdsFromCmdline() {
- // Validate the parameter
- std::string fd_list = FLAGS_server_fds;
- for (auto c: fd_list) {
- if (c != ',' && (c < '0' || c > '9')) {
- LOG(ERROR) << "Invalid file descriptor list: " << fd_list;
- std::exit(1);
- }
- }
-
- auto fds = android::base::Split(fd_list, ",");
- std::vector<cuttlefish::SharedFD> shared_fds;
- for (auto& fd_str: fds) {
- auto fd = std::stoi(fd_str);
- auto shared_fd = cuttlefish::SharedFD::Dup(fd);
- close(fd);
- shared_fds.push_back(shared_fd);
- }
-
- return shared_fds;
-}
-
-int main(int argc, char** argv) {
- ::android::base::InitLogging(argv, android::base::StderrLogger);
- google::ParseCommandLineFlags(&argc, &argv, false);
-
- // Modem simulator log saved in cuttlefish_runtime
- auto config = cuttlefish::CuttlefishConfig::Get();
- auto instance = config->ForDefaultInstance();
-
- auto modem_log_path = instance.PerInstancePath("modem_simulator.log");
-
- {
- auto log_path = instance.launcher_log_path();
- std::vector<std::string> log_files{log_path, modem_log_path};
- android::base::SetLogger(cuttlefish::LogToStderrAndFiles(log_files));
- }
-
- LOG(INFO) << "Start modem simulator, server_fds: " << FLAGS_server_fds
- << ", Sim type: " << ((FLAGS_sim_type == 2) ?
- "special for CtsCarrierApiTestCases" : "normal" );
-
- auto server_fds = ServerFdsFromCmdline();
- if (server_fds.empty()) {
- LOG(ERROR) << "Need to provide server fd";
- return -1;
- }
-
- cuttlefish::NvramConfig::InitNvramConfigService(server_fds.size(), FLAGS_sim_type);
-
- // Don't get a SIGPIPE from the clients
- if (sigaction(SIGPIPE, nullptr, nullptr) != 0) {
- LOG(ERROR) << "Failed to set SIGPIPE to be ignored: " << strerror(errno);
- }
-
- auto nvram_config = cuttlefish::NvramConfig::Get();
- auto nvram_config_file = nvram_config->ConfigFileLocation();
-
- // Start channel monitor, wait for RIL to connect
- int32_t modem_id = 0;
- std::vector<std::shared_ptr<cuttlefish::ModemSimulator>> modem_simulators;
-
- for (auto& fd : server_fds) {
- CHECK(fd->IsOpen()) << "Error creating or inheriting modem simulator server: "
- << fd->StrError();
-
- auto modem_simulator = std::make_shared<cuttlefish::ModemSimulator>(modem_id);
- auto channel_monitor =
- std::make_unique<cuttlefish::ChannelMonitor>(modem_simulator.get(), fd);
-
- modem_simulator->Initialize(std::move(channel_monitor));
-
- modem_simulators.push_back(modem_simulator);
-
- modem_id++;
- }
-
- // Monitor exit request and
- // remote call, remote sms from other cuttlefish instance
- std::string monitor_socket_name = "modem_simulator";
- std::stringstream ss;
- ss << instance.host_port();
- monitor_socket_name.append(ss.str());
-
- auto monitor_socket = cuttlefish::SharedFD::SocketLocalServer(
- monitor_socket_name.c_str(), true, SOCK_STREAM, 0666);
- if (!monitor_socket->IsOpen()) {
- LOG(ERROR) << "Unable to create monitor socket for modem simulator";
- std::exit(cuttlefish::kServerError);
- }
-
- // Server loop
- while (true) {
- cuttlefish::SharedFDSet read_set;
- read_set.Set(monitor_socket);
- int num_fds = cuttlefish::Select(&read_set, nullptr, nullptr, nullptr);
- if (num_fds <= 0) { // Ignore select error
- LOG(ERROR) << "Select call returned error : " << strerror(errno);
- } else if (read_set.IsSet(monitor_socket)) {
- auto conn = cuttlefish::SharedFD::Accept(*monitor_socket);
- std::string buf(4, ' ');
- auto read = cuttlefish::ReadExact(conn, &buf);
- if (read <= 0) {
- conn->Close();
- LOG(WARNING) << "Detected close from the other side";
- continue;
- }
- if (buf == "STOP") { // Exit request from parent process
- LOG(INFO) << "Exit request from parent process";
- nvram_config->SaveToFile(nvram_config_file);
- for (auto modem : modem_simulators) {
- modem->SaveModemState();
- }
- cuttlefish::WriteAll(conn, "OK"); // Ignore the return value. Exit anyway.
- std::exit(cuttlefish::kSuccess);
- } else if (buf.compare(0, 3, "REM") == 0) { // REMO for modem id 0 ...
- // Remote request from other cuttlefish instance
- int id = std::stoi(buf.substr(3, 1));
- if (id >= modem_simulators.size()) {
- LOG(ERROR) << "Not supported modem simulator count: " << id;
- } else {
- modem_simulators[id]->SetRemoteClient(conn, true);
- }
- }
- }
- }
- // Until kill or exit
-}
diff --git a/host/commands/modem_simulator/misc_service.cpp b/host/commands/modem_simulator/misc_service.cpp
deleted file mode 100644
index 1a2b7673f..000000000
--- a/host/commands/modem_simulator/misc_service.cpp
+++ /dev/null
@@ -1,167 +0,0 @@
-//
-// Copyright (C) 2020 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 "host/commands/modem_simulator/misc_service.h"
-
-#include <ctime>
-#include <fstream>
-#include <iomanip>
-
-namespace cuttlefish {
-
-MiscService::MiscService(int32_t service_id, ChannelMonitor* channel_monitor,
- ThreadLooper* thread_looper)
- : ModemService(service_id, this->InitializeCommandHandlers(),
- channel_monitor, thread_looper) {
- ParseTimeZone();
-}
-
-void MiscService::ParseTimeZone() {
-#if defined(__linux__)
- constexpr char TIMEZONE_FILENAME[] = "/etc/timezone";
- std::ifstream ifs(TIMEZONE_FILENAME);
- if (ifs.is_open()) {
- std::string line;
- if (std::getline(ifs, line)) {
- FixTimeZone(line);
- timezone_ = line;
- }
- }
-#endif
-}
-
-void MiscService::FixTimeZone(std::string& line) {
- auto slashpos = line.find("/");
- // "/" will be treated as separator, change it !
- if (slashpos != std::string::npos) {
- line.replace(slashpos, 1, "!");
- }
-}
-
-void MiscService::SetTimeZone(std::string timezone) {
- FixTimeZone(timezone);
- timezone_ = timezone;
-}
-
-std::vector<CommandHandler> MiscService::InitializeCommandHandlers() {
- std::vector<CommandHandler> command_handlers = {
- /* initializeCallback */
- CommandHandler("E0Q0V1",
- [this](const Client& client) {
- this->HandleCommandDefaultSupported(client);
- }),
- CommandHandler("S0=0",
- [this](const Client& client) {
- this->HandleCommandDefaultSupported(client);
- }),
- CommandHandler("+CMEE=1",
- [this](const Client& client) {
- this->HandleCommandDefaultSupported(client);
- }),
- CommandHandler("+CMOD=0",
- [this](const Client& client) {
- this->HandleCommandDefaultSupported(client);
- }),
- CommandHandler("+CSSN=0,1",
- [this](const Client& client) {
- this->HandleCommandDefaultSupported(client);
- }),
- CommandHandler("+COLP=0",
- [this](const Client& client) {
- this->HandleCommandDefaultSupported(client);
- }),
- CommandHandler("+CSCS=\"HEX\"",
- [this](const Client& client) {
- this->HandleCommandDefaultSupported(client);
- }),
- CommandHandler("+CMGF=0",
- [this](const Client& client) {
- this->HandleCommandDefaultSupported(client);
- }),
-
- CommandHandler("+CGSN",
- [this](const Client& client, std::string& cmd) {
- this->HandleGetIMEI(client, cmd);
- }),
- };
- return (command_handlers);
-}
-
-void MiscService::HandleGetIMEI(const Client& client, std::string& command) {
- const std::string identityGsmImei = "867400022047199";
- const std::string identityGsmSvn = "01";
- const std::string information = "modem simulator";
-
- std::vector<std::string> responses;
-
- if (command == "AT+CGSN") {
- responses.push_back(identityGsmImei);
- } else {
- CommandParser cmd(command);
- cmd.SkipPrefix();
- int snt = cmd.GetNextInt();
- switch (snt) {
- case 0: // SN: IMEI and more information provided by manufacturers
- responses.push_back(identityGsmImei + information);
- break;
- case 1: // IMEI
- responses.push_back(identityGsmImei);
- break;
- case 2: // IMEI and software version number
- responses.push_back(identityGsmImei + identityGsmSvn);
- break;
- case 3: // Software version number
- responses.push_back(identityGsmSvn);
- break;
- default: // Default IMEI
- responses.push_back(identityGsmImei);
- break;
- }
- }
-
- responses.push_back("OK");
- client.SendCommandResponse(responses);
-}
-
-void MiscService::TimeUpdate() {
- auto now = std::time(0);
-
- auto local_time = *std::localtime(&now);
- auto gm_time = *std::gmtime(&now);
-
- auto t_local_time = std::mktime(&local_time);
- auto t_gm_time = std::mktime(&gm_time);
-
- // Timezone offset is in number of quarter-hours
- auto tzdiff = (int)std::difftime(t_local_time, t_gm_time) / (15 * 60);
-
- std::stringstream ss;
- ss << "%CTZV: \"" << std::setfill('0') << std::setw(2)
- << local_time.tm_year % 100 << "/" << std::setfill('0') << std::setw(2)
- << local_time.tm_mon + 1 << "/" << std::setfill('0') << std::setw(2)
- << local_time.tm_mday << "," << std::setfill('0') << std::setw(2)
- << local_time.tm_hour << ":" << std::setfill('0') << std::setw(2)
- << local_time.tm_min << ":" << std::setfill('0') << std::setw(2)
- << local_time.tm_sec << (tzdiff >= 0 ? '+' : '-')
- << (tzdiff >= 0 ? tzdiff : -tzdiff) << ":" << local_time.tm_isdst;
- if (!timezone_.empty()) {
- ss << ":" << timezone_;
- }
- ss << "\"";
-
- SendUnsolicitedCommand(ss.str());
-}
-
-} // namespace cuttlefish
diff --git a/host/commands/modem_simulator/misc_service.h b/host/commands/modem_simulator/misc_service.h
deleted file mode 100644
index e795a0619..000000000
--- a/host/commands/modem_simulator/misc_service.h
+++ /dev/null
@@ -1,44 +0,0 @@
-//
-// Copyright (C) 2020 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 "host/commands/modem_simulator/modem_service.h"
-
-namespace cuttlefish {
-
-class MiscService : public ModemService, public std::enable_shared_from_this<MiscService> {
- public:
- MiscService(int32_t service_id, ChannelMonitor* channel_monitor,
- ThreadLooper* thread_looper);
- ~MiscService() = default;
-
- MiscService(const MiscService &) = delete;
- MiscService &operator=(const MiscService &) = delete;
-
- void HandleGetIMEI(const Client& client, std::string& command);
-
- void TimeUpdate();
-
- void SetTimeZone(std::string timezone);
-
- private:
- void ParseTimeZone();
- void FixTimeZone(std::string& line);
- std::string timezone_;
- std::vector<CommandHandler> InitializeCommandHandlers();
-};
-
-} // namespace cuttlefish
diff --git a/host/commands/modem_simulator/modem_service.cpp b/host/commands/modem_simulator/modem_service.cpp
deleted file mode 100644
index 062da6f98..000000000
--- a/host/commands/modem_simulator/modem_service.cpp
+++ /dev/null
@@ -1,147 +0,0 @@
-//
-// Copyright (C) 2020 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 "host/commands/modem_simulator/modem_service.h"
-
-#include <android-base/logging.h>
-
-#include <cstring>
-
-#include "host/commands/modem_simulator/device_config.h"
-
-namespace cuttlefish {
-
-const std::string ModemService::kCmeErrorOperationNotAllowed = "+CME ERROR: 3";
-const std::string ModemService::kCmeErrorOperationNotSupported = "+CME ERROR: 4";
-const std::string ModemService::kCmeErrorSimNotInserted = "+CME ERROR: 10";
-const std::string ModemService::kCmeErrorSimPinRequired = "+CME ERROR: 11";
-const std::string ModemService::kCmeErrorSimPukRequired = "+CME ERROR: 12";
-const std::string ModemService::kCmeErrorSimBusy = "+CME ERROR: 14";
-const std::string ModemService::kCmeErrorIncorrectPassword = "+CME ERROR: 16";
-const std::string ModemService::kCmeErrorMemoryFull = "+CME ERROR: 20";
-const std::string ModemService::kCmeErrorInvalidIndex = "+CME ERROR: 21";
-const std::string ModemService::kCmeErrorNotFound = "+CME ERROR: 22";
-const std::string ModemService::kCmeErrorInvalidCharactersInTextString = "+CME ERROR: 27";
-const std::string ModemService::kCmeErrorNoNetworkService = "+CME ERROR: 30";
-const std::string ModemService::kCmeErrorNetworkNotAllowedEmergencyCallsOnly = "+CME ERROR: 32";
-const std::string ModemService::kCmeErrorInCorrectParameters = "+CME ERROR: 50";
-const std::string ModemService::kCmeErrorNetworkNotAttachedDueToMTFunctionalRestrictions = "+CME ERROR: 53";
-const std::string ModemService::kCmeErrorFixedDialNumberOnlyAllowed = "+CME ERROR: 56";
-
-const std::string ModemService::kCmsErrorOperationNotAllowed = "+CMS ERROR: 302";
-const std::string ModemService::kCmsErrorOperationNotSupported = "+CMS ERROR: 303";
-const std::string ModemService::kCmsErrorInvalidPDUModeParam = "+CMS ERROR: 304";
-const std::string ModemService::kCmsErrorSCAddressUnknown = "+CMS ERROR: 304";
-
-const std::pair<int, int> ModemService::kRemotePortRange =
- std::make_pair(6520, 6527);
-
-CommandHandler::CommandHandler(const std::string& command, f_func handler)
- : command_prefix(command),
- match_mode(FULL_MATCH),
- f_command_handler(handler) {}
-
-CommandHandler::CommandHandler(const std::string& command, p_func handler)
- : command_prefix(command),
- match_mode(PARTIAL_MATCH),
- p_command_handler(handler) {}
-
-int CommandHandler::Compare(const std::string& command) const {
- int result = -1;
- if (match_mode == PARTIAL_MATCH) {
- result = command.compare(2, command_prefix.size(), command_prefix); // skip "AT"
- } else {
- result = command.compare(2, command.size(), command_prefix);
- }
- return result;
-}
-
-void CommandHandler::HandleCommand(const Client& client,
- std::string& command) const {
- if (match_mode == PARTIAL_MATCH && p_command_handler != nullptr) {
- (*p_command_handler)(client, command);
- } else if (match_mode == FULL_MATCH && f_command_handler != nullptr) {
- (*f_command_handler)(client);
- } else {
- LOG(ERROR) << "Mismatched mode and handler, CHECK!";
- }
-}
-
-ModemService::ModemService(int32_t service_id,
- std::vector<CommandHandler> command_handlers,
- ChannelMonitor* channel_monitor,
- ThreadLooper* thread_looper)
- : service_id_(service_id),
- command_handlers_(command_handlers),
- thread_looper_(thread_looper),
- channel_monitor_(channel_monitor) {}
-
-bool ModemService::HandleModemCommand(const Client& client,
- std::string command) {
- for (auto& handler : command_handlers_) {
- if (handler.Compare(command) == 0) {
- handler.HandleCommand(client, command);
- return true;
- }
- }
-
- return false;
-}
-
-void ModemService::HandleCommandDefaultSupported(const Client& client) {
- std::string response{"OK\r"};
- client.SendCommandResponse(response);
-}
-
-void ModemService::SendUnsolicitedCommand(std::string unsol_command) {
- if (channel_monitor_) {
- channel_monitor_->SendUnsolicitedCommand(unsol_command);
- ;
- }
-}
-
-cuttlefish::SharedFD ModemService::ConnectToRemoteCvd(std::string port) {
- std::string remote_sock_name = "modem_simulator" + port;
- auto remote_sock = cuttlefish::SharedFD::SocketLocalClient(
- remote_sock_name.c_str(), true, SOCK_STREAM);
- if (!remote_sock->IsOpen()) {
- LOG(ERROR) << "Failed to connect to remote cuttlefish: " << port
- << ", error: " << strerror(errno);
- }
- return remote_sock;
-}
-
-void ModemService::SendCommandToRemote(cuttlefish::SharedFD remote_client, std::string response) {
- if (channel_monitor_) {
- channel_monitor_->SendRemoteCommand(remote_client, response);
- ;
- }
-}
-
-void ModemService::CloseRemoteConnection(cuttlefish::SharedFD remote_client) {
- if (channel_monitor_) {
- channel_monitor_->CloseRemoteConnection(remote_client);
- ;
- }
-}
-
-std::string ModemService::GetHostPort() {
- auto host_port = cuttlefish::modem::DeviceConfig::host_port();
- std::stringstream ss;
- ss << host_port;
- return ss.str();
-}
-
-} // namespace cuttlefish
diff --git a/host/commands/modem_simulator/modem_service.h b/host/commands/modem_simulator/modem_service.h
deleted file mode 100644
index 0b75d7dea..000000000
--- a/host/commands/modem_simulator/modem_service.h
+++ /dev/null
@@ -1,115 +0,0 @@
-//
-// Copyright (C) 2020 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 <functional>
-#include <map>
-#include <optional>
-
-#include "host/commands/modem_simulator/channel_monitor.h"
-#include "host/commands/modem_simulator/command_parser.h"
-#include "host/commands/modem_simulator/thread_looper.h"
-
-namespace cuttlefish {
-
-enum ModemServiceType : int {
- kSimService = 0,
- kNetworkService = 1,
- kDataService = 2,
- kCallService = 3,
- kSmsService = 4,
- kSupService = 5,
- kStkService = 6,
- kMiscService = 7,
-};
-
-using f_func = std::function<void(const Client&)>; // Full match
-using p_func = std::function<void(const Client&, std::string&)>; // Partial match
-
-class CommandHandler {
- public:
- CommandHandler(const std::string& command, f_func handler);
- CommandHandler(const std::string& command, p_func handler);
-
- ~CommandHandler() = default;
-
- int Compare(const std::string& command) const;
- void HandleCommand(const Client& client, std::string& command) const;
-
- private:
- enum MatchMode {FULL_MATCH = 0, PARTIAL_MATCH = 1};
-
- std::string command_prefix;
- MatchMode match_mode;
-
- std::optional<f_func> f_command_handler;
- std::optional<p_func> p_command_handler;
-};
-
-class ModemService {
- public:
-
- virtual ~ModemService() = default;
-
- ModemService(const ModemService &) = delete;
- ModemService &operator=(const ModemService &) = delete;
-
- bool HandleModemCommand(const Client& client, std::string command);
-
- static const std::string kCmeErrorOperationNotAllowed;
- static const std::string kCmeErrorOperationNotSupported;
- static const std::string kCmeErrorSimNotInserted;
- static const std::string kCmeErrorSimPinRequired;
- static const std::string kCmeErrorSimPukRequired;
- static const std::string kCmeErrorSimBusy;
- static const std::string kCmeErrorIncorrectPassword;
- static const std::string kCmeErrorMemoryFull;
- static const std::string kCmeErrorInvalidIndex;
- static const std::string kCmeErrorNotFound;
- static const std::string kCmeErrorInvalidCharactersInTextString;
- static const std::string kCmeErrorNoNetworkService;
- static const std::string kCmeErrorNetworkNotAllowedEmergencyCallsOnly;
- static const std::string kCmeErrorInCorrectParameters;
- static const std::string kCmeErrorNetworkNotAttachedDueToMTFunctionalRestrictions;
- static const std::string kCmeErrorFixedDialNumberOnlyAllowed;
-
- static const std::string kCmsErrorOperationNotAllowed;
- static const std::string kCmsErrorOperationNotSupported;
- static const std::string kCmsErrorInvalidPDUModeParam;
- static const std::string kCmsErrorSCAddressUnknown;
-
- static const std::pair<int, int> kRemotePortRange;
-
- protected:
- ModemService(int32_t service_id, std::vector<CommandHandler> command_handlers,
- ChannelMonitor* channel_monitor, ThreadLooper* thread_looper);
- void HandleCommandDefaultSupported(const Client& client);
- void SendUnsolicitedCommand(std::string unsol_command);
-
- cuttlefish::SharedFD ConnectToRemoteCvd(std::string port);
- void SendCommandToRemote(cuttlefish::SharedFD remote_client,
- std::string response);
- void CloseRemoteConnection(cuttlefish::SharedFD remote_client);
- static std::string GetHostPort();
-
- int32_t service_id_;
- const std::vector<CommandHandler> command_handlers_;
- ThreadLooper* thread_looper_;
- ChannelMonitor* channel_monitor_;
-};
-
-} // namespace cuttlefish
diff --git a/host/commands/modem_simulator/modem_simulator.cpp b/host/commands/modem_simulator/modem_simulator.cpp
deleted file mode 100644
index 61a23bd1b..000000000
--- a/host/commands/modem_simulator/modem_simulator.cpp
+++ /dev/null
@@ -1,161 +0,0 @@
-//
-// Copyright (C) 2020 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 "host/commands/modem_simulator/modem_simulator.h"
-
-#include <android-base/logging.h>
-
-#include <memory>
-
-#include "host/commands/modem_simulator/call_service.h"
-#include "host/commands/modem_simulator/data_service.h"
-#include "host/commands/modem_simulator/misc_service.h"
-#include "host/commands/modem_simulator/network_service.h"
-#include "host/commands/modem_simulator/sim_service.h"
-#include "host/commands/modem_simulator/sms_service.h"
-#include "host/commands/modem_simulator/stk_service.h"
-#include "host/commands/modem_simulator/sup_service.h"
-
-namespace cuttlefish {
-
-ModemSimulator::ModemSimulator(int32_t modem_id)
- : modem_id_(modem_id), thread_looper_(new ThreadLooper()) {}
-
-ModemSimulator::~ModemSimulator() {
- // this will stop the looper so all the callbacks
- // will be gone;
- thread_looper_->Stop();
- modem_services_.clear();
-}
-
-void ModemSimulator::LoadNvramConfig() {
- auto nvram_config = NvramConfig::Get();
- if (!nvram_config) {
- LOG(FATAL) << "Failed to obtain nvram config singleton";
- return;
- }
-}
-
-void ModemSimulator::Initialize(
- std::unique_ptr<ChannelMonitor>&& channel_monitor) {
- channel_monitor_ = std::move(channel_monitor);
- LoadNvramConfig();
- RegisterModemService();
-}
-
-void ModemSimulator::RegisterModemService() {
- auto networkservice = std::make_unique<NetworkService>(
- modem_id_, channel_monitor_.get(), thread_looper_.get());
- auto simservice = std::make_unique<SimService>(
- modem_id_, channel_monitor_.get(), thread_looper_.get());
- auto miscservice = std::make_unique<MiscService>(
- modem_id_, channel_monitor_.get(), thread_looper_.get());
- auto callservice = std::make_unique<CallService>(
- modem_id_, channel_monitor_.get(), thread_looper_.get());
- auto stkservice = std::make_unique<StkService>(
- modem_id_, channel_monitor_.get(), thread_looper_.get());
- auto smsservice = std::make_unique<SmsService>(
- modem_id_, channel_monitor_.get(), thread_looper_.get());
- auto dataservice = std::make_unique<DataService>(
- modem_id_, channel_monitor_.get(), thread_looper_.get());
- auto supservice = std::make_unique<SupService>(
- modem_id_, channel_monitor_.get(), thread_looper_.get());
-
- networkservice->SetupDependency(miscservice.get(), simservice.get(),
- dataservice.get());
- simservice->SetupDependency(networkservice.get());
- callservice->SetupDependency(simservice.get(), networkservice.get());
- stkservice->SetupDependency(simservice.get());
- smsservice->SetupDependency(simservice.get());
-
- sms_service_ = smsservice.get();
- sim_service_ = simservice.get();
- misc_service_ = miscservice.get();
- network_service_ = networkservice.get();
- modem_services_[kSimService] = std::move(simservice);
- modem_services_[kNetworkService] = std::move(networkservice);
- modem_services_[kCallService] = std::move(callservice);
- modem_services_[kDataService] = std::move(dataservice);
- modem_services_[kSmsService] = std::move(smsservice);
- modem_services_[kSupService] = std::move(supservice);
- modem_services_[kStkService] = std::move(stkservice);
- modem_services_[kMiscService] = std::move(miscservice);
-}
-
-void ModemSimulator::DispatchCommand(const Client& client, std::string& command) {
- if (sms_service_) {
- if (sms_service_->IsWaitingSmsPdu()) {
- sms_service_->HandleSendSMSPDU(client, command);
- return;
- } else if (sms_service_->IsWaitingSmsToSim()) {
- sms_service_->HandleWriteSMSPduToSim(client, command);
- return;
- }
- }
-
- bool success = false;
- for (auto& service : modem_services_) {
- success = service.second->HandleModemCommand(client, command);
- if (success) {
- break;
- }
- }
-
- if (!success && client.type != Client::REMOTE) {
- LOG(DEBUG) << "Not supported AT command: " << command;
- client.SendCommandResponse(ModemService::kCmeErrorOperationNotSupported);
- }
-}
-
-void ModemSimulator::OnFirstClientConnected() {
- if (misc_service_) {
- misc_service_->TimeUpdate();
- }
-
- if (network_service_) {
- network_service_->OnVoiceRegisterStateChanged();
- network_service_->OnDataRegisterStateChanged();
- }
-}
-
-void ModemSimulator::SaveModemState() {
- if (sim_service_) {
- sim_service_->SavePinStateToIccProfile();
- sim_service_->SaveFacilityLockToIccProfile();
- }
-}
-
-bool ModemSimulator::IsRadioOn() const {
- if (network_service_) {
- return !network_service_->isRadioOff();
- }
- return false;
-}
-
-bool ModemSimulator::IsWaitingSmsPdu() {
- if (sms_service_) {
- return (sms_service_->IsWaitingSmsPdu() |
- sms_service_->IsWaitingSmsToSim());
- }
- return false;
-}
-
-void ModemSimulator::SetTimeZone(std::string timezone) {
- if (misc_service_) {
- misc_service_->SetTimeZone(timezone);
- }
-}
-
-} // namespace cuttlefish
diff --git a/host/commands/modem_simulator/modem_simulator.h b/host/commands/modem_simulator/modem_simulator.h
deleted file mode 100644
index 9340e4993..000000000
--- a/host/commands/modem_simulator/modem_simulator.h
+++ /dev/null
@@ -1,68 +0,0 @@
-//
-// Copyright (C) 2020 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 "host/commands/modem_simulator/channel_monitor.h"
-#include "host/commands/modem_simulator/modem_service.h"
-#include "host/commands/modem_simulator/nvram_config.h"
-#include "host/commands/modem_simulator/thread_looper.h"
-
-namespace cuttlefish {
-
-class SimService;
-class MiscService;
-class NetworkService;
-class SmsService;
-class ModemSimulator {
- public:
- ModemSimulator(int32_t modem_id);
- ~ModemSimulator();
-
- ModemSimulator(const ModemSimulator&) = delete;
- ModemSimulator& operator=(const ModemSimulator&) = delete;
-
- void Initialize(std::unique_ptr<ChannelMonitor>&& channel_monitor);
-
- void DispatchCommand(const Client& client, std::string& command);
-
- void OnFirstClientConnected();
- void SaveModemState();
- bool IsWaitingSmsPdu();
- bool IsRadioOn() const;
- void SetRemoteClient(cuttlefish::SharedFD client, bool is_accepted) {
- channel_monitor_->SetRemoteClient(client, is_accepted);
- }
-
- void SetTimeZone(std::string timezone);
-
- private:
- int32_t modem_id_;
- std::unique_ptr<ChannelMonitor> channel_monitor_;
- std::unique_ptr<ThreadLooper> thread_looper_;
-
- SmsService* sms_service_{nullptr};
- SimService* sim_service_{nullptr};
- MiscService* misc_service_{nullptr};
- NetworkService* network_service_{nullptr};
-
- std::map<ModemServiceType, std::unique_ptr<ModemService>> modem_services_;
-
- static void LoadNvramConfig();
-
- void RegisterModemService();
-};
-
-} // namespace cuttlefish
diff --git a/host/commands/modem_simulator/network_service.cpp b/host/commands/modem_simulator/network_service.cpp
deleted file mode 100644
index 56f14e514..000000000
--- a/host/commands/modem_simulator/network_service.cpp
+++ /dev/null
@@ -1,1266 +0,0 @@
-//
-// Copyright (C) 2020 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 "host/commands/modem_simulator/network_service.h"
-
-#include <android-base/logging.h>
-
-#include <map>
-#include <sstream>
-
-#include "common/libs/utils/files.h"
-#include "host/commands/modem_simulator/device_config.h"
-#include "host/commands/modem_simulator/nvram_config.h"
-#include "host/commands/modem_simulator/thread_looper.h"
-namespace cuttlefish {
-
-// string type; two byte location area code in hexadecimal format
-static const std::string kAreaCode = "2142";
-// string type; four byte GERAN/UTRAN cell ID in hexadecimal format
-static const std::string kCellId = "0000B804";
-
-// Check SignalStrength.java file for more details on how these map to
-// signal strength bars
-const std::pair<int, int> kGSMSignalStrength = std::make_pair(4, 30);
-const std::pair<int, int> kCDMASignalStrength = std::make_pair(4, 120);
-const std::pair<int, int> kEVDOSignalStrength = std::make_pair(4, 120);
-const std::pair<int, int> kLTESignalStrength = std::make_pair(4, 30);
-const std::pair<int, int> kWCDMASignalStrength = std::make_pair(4, 30);
-const std::pair<int, int> kNRSignalStrength = std::make_pair(45, 135);
-
-NetworkService::NetworkService(int32_t service_id,
- ChannelMonitor* channel_monitor,
- ThreadLooper* thread_looper)
- : ModemService(service_id, this->InitializeCommandHandlers(),
- channel_monitor, thread_looper) {
- InitializeServiceState();
-}
-
-std::vector<CommandHandler> NetworkService::InitializeCommandHandlers() {
- std::vector<CommandHandler> command_handlers = {
- CommandHandler(
- "+CFUN?",
- [this](const Client& client) { this->HandleRadioPowerReq(client); }),
- CommandHandler("+CFUN=",
- [this](const Client& client, std::string& cmd) {
- this->HandleRadioPower(client, cmd);
- }),
- CommandHandler("+REMOTECFUN=",
- [this](const Client& client, std::string& cmd) {
- this->HandleRadioPower(client, cmd);
- }),
- CommandHandler(
- "+CSQ",
- [this](const Client& client) { this->HandleSignalStrength(client); }),
- CommandHandler("+COPS?",
- [this](const Client& client) {
- this->HandleQueryNetworkSelectionMode(client);
- }),
- CommandHandler("+COPS=3,0;+COPS?;+COPS=3,1;+COPS?;+COPS=3,2;+COPS?",
- [this](const Client& client) {
- this->HandleRequestOperator(client);
- }),
- CommandHandler("+COPS=?",
- [this](const Client& client) {
- this->HandleQueryAvailableNetwork(client);
- }),
- CommandHandler("+COPS=",
- [this](const Client& client, std::string& cmd) {
- this->HandleSetNetworkSelectionMode(client, cmd);
- }),
- CommandHandler("+CREG",
- [this](const Client& client, std::string& cmd) {
- this->HandleVoiceNetworkRegistration(client, cmd);
- }),
- CommandHandler("+CGREG",
- [this](const Client& client, std::string& cmd) {
- this->HandleDataNetworkRegistration(client, cmd);
- }),
- CommandHandler("+CEREG",
- [this](const Client& client, std::string& cmd) {
- this->HandleDataNetworkRegistration(client, cmd);
- }),
- CommandHandler("+CTEC?",
- [this](const Client& client) {
- this->HandleGetPreferredNetworkType(client);
- }),
- CommandHandler("+CTEC=?",
- [this](const Client& client) {
- this->HandleQuerySupportedTechs(client);
- }),
- CommandHandler("+CTEC=",
- [this](const Client& client, std::string& cmd) {
- this->HandleSetPreferredNetworkType(client, cmd);
- }),
- CommandHandler("+REMOTECTEC",
- [this](const Client& client, std::string& cmd) {
- this->HandleReceiveRemoteCTEC(client, cmd);
- }),
- CommandHandler("+REMOTESIGNAL",
- [this](const Client& client, std::string& cmd) {
- this->HandleReceiveRemoteSignal(client, cmd);
- }),
- CommandHandler("+REMOTEREG",
- [this](const Client& client, std::string& cmd) {
- this->HandleReceiveRemoteVoiceDataReg(client, cmd);
- }),
- };
- return (command_handlers);
-}
-
-void NetworkService::InitializeServiceState() {
- radio_state_ = RadioState::RADIO_STATE_OFF;
-
- modem_radio_capability_ =
- M_MODEM_TECH_GSM | M_MODEM_TECH_WCDMA | M_MODEM_TECH_LTE | M_MODEM_TECH_NR;
-
- auto nvram_config = NvramConfig::Get();
- auto instance = nvram_config->ForInstance(service_id_);
-
- // Default to be ""
- current_operator_numeric_ = instance.operator_numeric();
- // Default to be OPER_SELECTION_AUTOMATIC
- oper_selection_mode_ = (OperatorSelectionMode)instance.network_selection_mode();
- // Default to be M_MODEM_TECH_LTE | M_MODEM_TECH_WCDMA | M_MODEM_TECH_GSM;
- preferred_network_mode_ = instance.preferred_network_mode();
- // Default to be M_MODEM_TECH_LTE
- current_network_mode_ = (ModemTechnology)instance.modem_technoloy();
-
- InitializeNetworkOperator();
-
- first_signal_strength_request_ = true;
- android_last_signal_time_ = 0;
-}
-
-void NetworkService::InitializeNetworkOperator() {
- operator_list_.push_back(
- {"311740", "Android Virtual Operator", "Android", NetworkOperator::OPER_STATE_AVAILABLE});
- operator_list_.push_back(
- {"310300", "Alternative Operator", "Alternative", NetworkOperator::OPER_STATE_AVAILABLE});
- operator_list_.push_back(
- {"310400", "Hermetic Network Operator", "Hermetic", NetworkOperator::OPER_STATE_FORBIDDEN});
-
- if (oper_selection_mode_ == OperatorSelectionMode::OPER_SELECTION_AUTOMATIC) {
- current_operator_numeric_ = operator_list_.begin()->numeric;
- operator_list_.begin()->operator_state = NetworkOperator::OPER_STATE_CURRENT;
- } else if (oper_selection_mode_ == OperatorSelectionMode::OPER_SELECTION_MANUAL_AUTOMATIC) {
- auto iter = operator_list_.begin();
- for (; iter != operator_list_.end(); ++iter) {
- if (iter->numeric == current_operator_numeric_) {
- break;
- }
- }
- if (iter == operator_list_.end()) {
- current_operator_numeric_ = operator_list_.begin()->numeric;
- operator_list_.begin()->operator_state = NetworkOperator::OPER_STATE_CURRENT;
- } else {
- iter->operator_state = NetworkOperator::OPER_STATE_CURRENT;
- }
- }
-}
-
-void NetworkService::InitializeSimOperator() {
- if (sim_service_ == nullptr) {
- return;
- }
- auto sim_operator_numeric = sim_service_->GetSimOperator();
- if (sim_operator_numeric == "") {
- return;
- }
-
- // ensure the first element is sim_operator_numeric
- for (auto iter = operator_list_.begin(); iter != operator_list_.end();
- ++iter) {
- if (iter->numeric == sim_operator_numeric) {
- std::swap(*iter, *(operator_list_.begin()));
- return;
- }
- }
-
- {
- const char *operator_numeric_xml = "etc/modem_simulator/files/numeric_operator.xml";
- auto file = cuttlefish::modem::DeviceConfig::DefaultHostArtifactsPath(
- operator_numeric_xml);
- if (!cuttlefish::FileExists(file) || !cuttlefish::FileHasContent(file)) {
- return;
- }
-
- XMLDocument doc;
- auto err = doc.LoadFile(file.c_str());
- if (err != tinyxml2::XML_SUCCESS) {
- LOG(ERROR) << "unable to load XML file '" << file << " ', error " << err;
- return;
- }
- XMLElement *resources = doc.RootElement();
- if (resources == NULL) return;
-
- XMLElement *stringArray = resources->FirstChildElement("string-array");
- if (stringArray == NULL) return;
-
- XMLElement *item = stringArray->FirstChildElement("item");
- while (item) {
- const XMLAttribute *attr_numeric = item->FindAttribute("numeric");
- std::string numeric = attr_numeric ? attr_numeric->Value() : "";
- if (numeric == sim_operator_numeric) {
- break;
- }
- item = item->NextSiblingElement("item");
- }
- if (item) {
- std::string names = item->GetText();
- auto pos = names.find('=');
- if (pos != std::string::npos) {
- auto long_name = names.substr(0, pos);
- auto short_name = names.substr(pos + 1);
- NetworkOperator sim_operator(sim_operator_numeric, long_name,
- short_name, NetworkOperator::OPER_STATE_AVAILABLE);
- operator_list_.insert(operator_list_.begin(), sim_operator);
- }
- }
- }
- InitializeNetworkOperator();
-}
-
-void NetworkService::SetupDependency(MiscService* misc, SimService* sim,
- DataService* data) {
- misc_service_ = misc;
- sim_service_ = sim;
- data_service_ = data;
- InitializeSimOperator();
-}
-
-void NetworkService::OnSimStatusChanged(SimService::SimStatus sim_status) {
- if (radio_state_ == RadioState::RADIO_STATE_OFF) {
- return; // RegistrationState::NET_REGISTRATION_UNREGISTERED unchanged
- }
- if (sim_status == SimService::SIM_STATUS_READY) {
- voice_registration_status_.registration_state = NET_REGISTRATION_HOME;
- } else {
- voice_registration_status_.registration_state = NET_REGISTRATION_EMERGENCY;
- // 3GPP TS 24.008 [8] and 3GPP TS 24.301 [83] specify the condition
- // when the MT is considered as attached for emergency bearer services.
- // applicable only when <AcT> indicates 2,4,5,6
- // Note: not saved to nvram config due to sim status may change after reboot
- current_network_mode_ = M_MODEM_TECH_WCDMA;
- }
- thread_looper_->PostWithDelay(std::chrono::seconds(1),
- makeSafeCallback(this, &NetworkService::UpdateRegisterState,
- voice_registration_status_.registration_state));
-}
-
-/**
- * AT+CFUN
- * Set command selects the level of functionality <fun> in the MT. Level
- * "full functionality" is where the highest level of power is drawn.
- * "Minimum functionality" is where minimum power is drawn. Level of functionality
- * between these may also be specified by manufacturers. When supported by
- * manufacturers, MT resetting with <rst> parameter may be utilized
- *
- * Command Possible response(s)
- * +CFUN=[<fun>[,<rst>]] +CME ERROR: <err>
- * +CFUN? +CFUN: <fun>
- * +CME ERROR: <err>
- *
- * <fun>: integer type
- * 0 minimum functionality
- * 1 full functionality. Enable (turn on) the transmit and receive RF circuits
- * for all supported radio access technologies.
- * 2 disable (turn off) MT transmit RF circuits only
- * 3 disable (turn off) MT receive RF circuits only
- * 4 disable (turn off) both MT transmit and receive RF circuits
- * 5...127 reserved for manufacturers as intermediate states between full
- * and minimum functionality
- * 128 Full functionality with radio access support according to the setting of +CSRA.
- * 129 Prepare for shutdown.
- *
- * see RIL_REQUEST_RADIO_POWER in RIL
- */
-void NetworkService::HandleRadioPowerReq(const Client& client) {
- std::stringstream ss;
- ss << "+CFUN: " << radio_state_;
-
- std::vector<std::string> responses;
- responses.push_back(ss.str());
- responses.push_back("OK");
-
- client.SendCommandResponse(responses);
-}
-
-void NetworkService::HandleRadioPower(const Client& client, std::string& command) {
- CommandParser cmd(command);
- cmd.SkipPrefix();
- int on = cmd.GetNextInt();
- switch (on) {
- case 0:
- radio_state_ = RadioState::RADIO_STATE_OFF;
- UpdateRegisterState(NET_REGISTRATION_UNREGISTERED);
- break;
- case 1:
- radio_state_ = RadioState::RADIO_STATE_ON;
- if (sim_service_ != nullptr) {
- auto sim_status = sim_service_->GetSimStatus();
- OnSimStatusChanged(sim_status);
- }
- break;
- default:
- client.SendCommandResponse(kCmeErrorOperationNotSupported);
- return;
- }
- signal_strength_.Reset();
-
- client.SendCommandResponse("OK");
-}
-
-bool NetworkService::WakeupFromSleep() {
- // It has not called once yet
- if (android_last_signal_time_ == 0) {
- return false;
- }
- // Heuristics: if guest has not asked for signal strength
- // for 2 minutes, we assume it is caused by host sleep
- time_t now = time(0);
- const bool wakeup_from_sleep = (now > android_last_signal_time_ + 120);
- return wakeup_from_sleep;
-}
-
-void NetworkService::SetSignalStrengthValue(int& value,
- const std::pair<int, int>& range,
- double percentd) {
- value = range.first + percentd * (range.second - range.first);
- AdjustSignalStrengthValue(value, range);
-}
-
-void NetworkService::AdjustSignalStrengthValue(int& value,
- const std::pair<int, int>& range) {
- if (value < range.first) {
- value = range.first;
- } else if (value > range.second) {
- value = range.second;
- }
-}
-/**
- * AT+CSQ
- * Execution command returns received signal strength indication <rssi>
- * and channel bit error rate <ber> from the MT.
- *
- * command Possible response(s)
- * AT+CSQ +CSQ: <rssi>,<ber>
- * +CME ERROR: <err>
- *
- * <rssi>: integer type
- * 0 ‑113 dBm or less
- * 1 ‑111 dBm
- * 2...30 ‑109... ‑53 dBm
- * 31 ‑51 dBm or greater
- * 99 not known or not detectable
- * <ber>: integer type; channel bit error rate (in percent)
- * 0...7 as RXQUAL values in the table in 3GPP TS 45.008 [20] subclause 8.2.4
- * 99 not known or not detectable
- *
- * see RIL_REQUEST_SIGNAL_STRENGTH in RIL
- */
-void NetworkService::HandleSignalStrength(const Client& client) {
- std::vector<std::string> responses;
- std::stringstream ss;
-
- if (WakeupFromSleep()) {
- misc_service_->TimeUpdate();
- } else if (first_signal_strength_request_) {
- first_signal_strength_request_ = false;
- misc_service_->TimeUpdate();
- }
-
- android_last_signal_time_ = time(0);
-
- auto response = GetSignalStrength();
-
- responses.push_back(response);
- responses.push_back("OK");
- client.SendCommandResponse(responses);
-}
-
-bool NetworkService::IsHasNetwork() {
- if (radio_state_ == RADIO_STATE_OFF ||
- oper_selection_mode_ == OperatorSelectionMode::OPER_SELECTION_DEREGISTRATION) {
- return false;
- }
- return true;
-}
-
-/**
- * AT+COPS
- * Set command forces an attempt to select and register to the
- * GSM/UMTS/EPS/5GS network operator using the SIM/USIM card installed
- * in the currently selected card slot.
- *
- * command Possible response(s)
- * +COPS=[<mode>[,<format> +CME ERROR: <err>
- * [,<oper>[,<AcT>]]]]
- *
- * +COPS? +COPS: <mode>[,<format>,<oper>[,<AcT>]]
- * +CME ERROR: <err>
- *
- * +COPS=? +COPS: [list of supported (<stat>,
- * long alphanumeric <oper>,
- * short alphanumeric <oper>,
- * numeric <oper>[,<AcT>])s]
- * [,,(list of supported <mode>s),
- * (list of supported <format>s)]
- * +CME ERROR: <err>
- *
- * <mode>: integer type
- * 0 automatic (<oper> field is ignored)
- * 1 manual (<oper> field shall be present, and <AcT> optionally)
- * 2 deregister from network
- * 3 set only <format> (for read command +COPS?), do not attempt
- * registration/deregistration (<oper> and <AcT> fields are ignored);
- * this value is not applicable in read command response
- * 4 manual/automatic (<oper> field shall be present); if manual selection fails, automatic mode (<mode>=0) is entered
- * <format>: integer type
- * 0 long format alphanumeric <oper>
- * 1 short format alphanumeric <oper>
- * 2 numeric <oper>
- * <oper>: string type;
- * <format> indicates if the format is alphanumeric or numeric;
- * <stat>: integer type
- * 0 unknown
- * 1 available
- * 2 current
- * 3 forbidden
- * <AcT>: integer type; access technology selected
- * 0 GSM
- * 1 GSM Compact
- * 2 UTRAN
- * 3 GSM w/EGPRS (see NOTE 1)
- * 4 UTRAN w/HSDPA (see NOTE 2)
- * 5 UTRAN w/HSUPA (see NOTE 2)
- * 6 UTRAN w/HSDPA and HSUPA (see NOTE 2)
- * 7 E-UTRAN
- * 8 EC-GSM-IoT (A/Gb mode) (see NOTE 3)
- * 9 E-UTRAN (NB-S1 mode) (see NOTE 4)
- * 10 E-UTRA connected to a 5GCN (see NOTE 5)
- * 11 NR connected to a 5GCN (see NOTE 5)
- * 12 NG-RAN
- * 13 E-UTRA-NR dual connectivity (see NOTE 6)
- *
- * see RIL_REQUEST_SET_NETWORK_SELECTION_AUTOMATIC or
- * RIL_REQUEST_QUERY_NETWORK_SELECTION_MODE or
- * RIL_REQUEST_OPERATOR in RIL
- */
-void NetworkService::HandleQueryNetworkSelectionMode(const Client& client) {
- std::vector<std::string> responses;
- std::stringstream ss;
-
- if (!IsHasNetwork()) {
- ss << "+COPS: 0,0,0";
- } else {
- auto iter = operator_list_.begin();
- for (; iter != operator_list_.end(); ++iter) {
- if (iter->numeric == current_operator_numeric_) {
- break;
- }
- }
- if (iter != operator_list_.end()) {
- ss << "+COPS: " << oper_selection_mode_ << ",2," << iter->numeric;
- } else {
- ss << "+COPS: " << oper_selection_mode_ << ",0,0";
- }
- }
- responses.push_back(ss.str());
- responses.push_back("OK");
- client.SendCommandResponse(responses);
-}
-
-/* AT+COPS=3,0;+COPS?;+COPS=3,1;+COPS?;+COPS=3,2;+COPS? */
-void NetworkService::HandleRequestOperator(const Client& client) {
- if (!IsHasNetwork()) {
- client.SendCommandResponse(kCmeErrorOperationNotAllowed);
- return;
- }
-
- auto iter = operator_list_.begin();
- for (; iter != operator_list_.end(); ++iter) {
- if (iter->numeric == current_operator_numeric_) {
- break;
- }
- }
- if (iter == operator_list_.end()) {
- client.SendCommandResponse(kCmeErrorNoNetworkService);
- return;
- }
-
- std::vector<std::string> responses;
- std::vector<std::stringstream> ss;
- ss.resize(3);
-
- ss[0] << "+COPS: 0,0," << iter->long_name;
- ss[1] << "+COPS: 0,1," << iter->short_name;
- ss[2] << "+COPS: 0,2," << iter->numeric;
-
- responses.push_back(ss[0].str());
- responses.push_back(ss[1].str());
- responses.push_back(ss[2].str());
- responses.push_back("OK");
-
- client.SendCommandResponse(responses);
-}
-
-/* AT+COPS=? */
-void NetworkService::HandleQueryAvailableNetwork(const Client& client) {
- std::vector<std::string> responses;
- std::stringstream ss;
-
- for (auto iter = operator_list_.begin(); iter != operator_list_.end(); ++iter) {
- ss.clear();
- ss << "+COPS: (" << iter->operator_state << ","
- << iter->long_name << ","
- << iter->short_name << ","
- << iter->numeric << "),";
- responses.push_back(ss.str());
- ss.str("");
- }
-
- responses.push_back("OK");
- client.SendCommandResponse(responses);
-}
-
-/* AT+COPS=mode,format,operatorNumeric,act */
-void NetworkService::HandleSetNetworkSelectionMode(const Client& client, std::string& command) {
- std::vector<std::string> responses;
- std::stringstream ss;
-
- CommandParser cmd(command);
- cmd.SkipPrefix();
-
- int mode = (OperatorSelectionMode)cmd.GetNextInt();
- cmd.SkipPrefix(); // Default to be numeric
-
- auto& registration_state = voice_registration_status_.registration_state;
-
- switch (mode) {
- // <oper> field is ignored
- case OperatorSelectionMode::OPER_SELECTION_AUTOMATIC: {
- oper_selection_mode_ = OperatorSelectionMode::OPER_SELECTION_AUTOMATIC;
-
- // The first operator stored in operator_list_ map default to be
- // the automatic selected operator
- auto iter = operator_list_.begin();
- current_operator_numeric_ = iter->numeric;
- iter->operator_state = NetworkOperator::OPER_STATE_CURRENT;
-
- // Change operator state stored in the operator_list_ map
- ++iter;
- for (; iter != operator_list_.end(); ++iter) {
- if (iter->operator_state == NetworkOperator::OPER_STATE_CURRENT) {
- iter->operator_state = NetworkOperator::OPER_STATE_AVAILABLE;
- break;
- }
- }
-
- registration_state = NET_REGISTRATION_HOME;
- client.SendCommandResponse("OK");
- break;
- }
-
- // <oper> field shall be present, and <AcT> optionally
- case OperatorSelectionMode::OPER_SELECTION_MANUAL: {
- oper_selection_mode_ = OperatorSelectionMode::OPER_SELECTION_MANUAL;
- current_operator_numeric_ = cmd.GetNextStr();
- auto iter = operator_list_.begin();
- for (; iter != operator_list_.end(); ++iter) {
- if (iter->numeric == current_operator_numeric_) {
- break;
- }
- }
- // If the selected operator is not available, no other operator shall be
- // selected (except <mode>=4).
- if (iter == operator_list_.end()) {
- registration_state = NET_REGISTRATION_UNKNOWN;
- client.SendCommandResponse(kCmeErrorNoNetworkService);
- break;
- }
-
- // Change operator state stored in the operator_list_ vector
- iter->operator_state = NetworkOperator::OPER_STATE_CURRENT;
- iter = operator_list_.begin();
- for (; iter != operator_list_.end(); ++iter) {
- if (iter->numeric != current_operator_numeric_ &&
- iter->operator_state == NetworkOperator::OPER_STATE_CURRENT) {
- iter->operator_state = NetworkOperator::OPER_STATE_AVAILABLE;
- }
- }
-
- // If the selected access technology is not available, then the same operator
- // shall be selected in other access technology
- int act = cmd.GetNextInt();
- if (act != -1) {
- auto tech = getTechFromNetworkType((NetworkRegistrationStatus::AccessTechnoloy)act);
- if (tech & modem_radio_capability_) {
- current_network_mode_ = tech;
- } // else: remain current network mode unchanged
- } // else: remain act unchanged
-
- if (iter->operator_state == NetworkOperator::OPER_STATE_FORBIDDEN) {
- registration_state = NET_REGISTRATION_DENIED;
- } else if (iter->operator_state == NetworkOperator::OPER_STATE_UNKNOWN) {
- registration_state = NET_REGISTRATION_UNKNOWN;
- } else {
- registration_state = NET_REGISTRATION_HOME;
- }
- client.SendCommandResponse("OK");
- break;
- }
-
- case OperatorSelectionMode::OPER_SELECTION_DEREGISTRATION: {
- oper_selection_mode_ = OperatorSelectionMode::OPER_SELECTION_DEREGISTRATION;
- registration_state = NET_REGISTRATION_UNREGISTERED;
- client.SendCommandResponse("OK");
- break;
- }
-
- // <oper> field shall be present
- case OperatorSelectionMode::OPER_SELECTION_MANUAL_AUTOMATIC: {
- oper_selection_mode_ = OperatorSelectionMode::OPER_SELECTION_MANUAL_AUTOMATIC;
- auto operator_numeric = cmd.GetNextStr();
- // If manual selection fails, automatic mode (<mode>=0) is entered
- auto iter = operator_list_.begin();
- for (; iter != operator_list_.end(); ++iter) {
- if (iter->numeric == operator_numeric) {
- break;
- }
- }
- // If the selected operator is not available, no other operator shall be
- // selected (except <mode>=4)
- if (iter != operator_list_.end() ||
- iter->operator_state == NetworkOperator::OPER_STATE_AVAILABLE) {
- current_operator_numeric_ = iter->numeric;
- }
-
- // Change operator state stored in the operator_list_ vector
- iter = operator_list_.begin();
- for (; iter != operator_list_.end(); ++iter) {
- if (iter->numeric == current_operator_numeric_) {
- iter->operator_state = NetworkOperator::OPER_STATE_CURRENT;
- } else if (iter->operator_state == NetworkOperator::OPER_STATE_CURRENT) {
- iter->operator_state = NetworkOperator::OPER_STATE_AVAILABLE;
- }
- }
-
- registration_state = NET_REGISTRATION_HOME;
- client.SendCommandResponse("OK");
- break;
- }
-
- default:
- client.SendCommandResponse(kCmeErrorInCorrectParameters);
- return;
- }
-
- // Save the value anyway, no matter the value changes or not
- auto nvram_config = NvramConfig::Get();
- auto instance = nvram_config->ForInstance(service_id_);
- instance.set_network_selection_mode(oper_selection_mode_);
- instance.set_operator_numeric(current_operator_numeric_);
-
- NvramConfig::SaveToFile();
-
- thread_looper_->PostWithDelay(std::chrono::seconds(1),
- makeSafeCallback(this, &NetworkService::UpdateRegisterState, registration_state));
-}
-
-NetworkService::NetworkRegistrationStatus::AccessTechnoloy
-NetworkService::getNetworkTypeFromTech(ModemTechnology modemTech) {
- switch (modemTech) {
- case ModemTechnology::M_MODEM_TECH_GSM:
- return NetworkRegistrationStatus::ACESS_TECH_EGPRS;
- case ModemTechnology::M_MODEM_TECH_WCDMA:
- return NetworkRegistrationStatus::ACESS_TECH_HSPA;
- case ModemTechnology::M_MODEM_TECH_LTE:
- return NetworkRegistrationStatus::ACESS_TECH_EUTRAN;
- case ModemTechnology::M_MODEM_TECH_NR:
- return NetworkRegistrationStatus::ACESS_TECH_NR;
- default:
- return NetworkRegistrationStatus::ACESS_TECH_EGPRS;
- }
-}
-
-NetworkService::ModemTechnology NetworkService::getTechFromNetworkType(
- NetworkRegistrationStatus::AccessTechnoloy act) {
- switch (act) {
- case NetworkRegistrationStatus::ACESS_TECH_GSM:
- case NetworkRegistrationStatus::ACESS_TECH_GSM_COMPACT:
- case NetworkRegistrationStatus::ACESS_TECH_EGPRS:
- case NetworkRegistrationStatus::ACESS_TECH_EC_GSM_IoT:
- return ModemTechnology::M_MODEM_TECH_GSM;
-
- case NetworkRegistrationStatus::ACESS_TECH_UTRAN:
- case NetworkRegistrationStatus::ACESS_TECH_HSDPA:
- case NetworkRegistrationStatus::ACESS_TECH_HSUPA:
- case NetworkRegistrationStatus::ACESS_TECH_HSPA:
- return ModemTechnology::M_MODEM_TECH_WCDMA;
-
- case NetworkRegistrationStatus::ACESS_TECH_EUTRAN:
- case NetworkRegistrationStatus::ACESS_TECH_E_UTRAN:
- case NetworkRegistrationStatus::ACESS_TECH_E_UTRA:
- return ModemTechnology::M_MODEM_TECH_LTE;
-
- case NetworkRegistrationStatus::ACESS_TECH_NR:
- case NetworkRegistrationStatus::ACESS_TECH_NG_RAN:
- case NetworkRegistrationStatus::ACESS_TECH_E_UTRA_NR:
- return ModemTechnology::M_MODEM_TECH_NR;
-
- default:
- return ModemTechnology::M_MODEM_TECH_GSM;
- }
-}
-
-/**
- * AT+CREG
- * Set command controls the presentation of an unsolicited result code
- * +CREG: <stat> when <n>=1 and there is a change in the MT’s circuit
- * mode network registration status in GERAN/UTRAN/E-UTRAN, or unsolicited
- * result code +CREG: <stat>[,[<lac>],[<ci>],[<AcT>]]
- * when <n>=2 and there is a change of the network cell in GERAN/UTRAN/E-UTRAN. The
- * parameters <AcT>, <lac> and <ci> are sent only if available.
- * The value <n>=3 further extends the unsolicited result code with [,<cause_type>,
- * <reject_cause>], when available, when the value of <stat> changes.
- *
- * command Possible response(s)
- * +CREG=[<n>] +CME ERROR: <err>
- *
- * +CREG? +CREG: <n>,<stat>[,[<lac>],[<ci>],[<AcT>]
- * [,<cause_type>,<reject_cause>]]
- *
- * <n>: integer type
- * 0 disable network registration unsolicited result code
- * 1 enable network registration unsolicited result code +CREG: <stat>
- * 2 enable network registration and location information unsolicited
- * result code +CREG: <stat>[,[<lac>],[<ci>],[<AcT>]]
- * 3 enable network registration, location information and cause value
- * information unsolicited result code +CREG: <stat>[,[<lac>],[<ci>],
- * [<AcT>][,<cause_type>,<reject_cause>]]
- *
- * <stat>: integer type;
- * 0 not registered, MT is not currently searching a new operator to register to
- * 1 registered, home network
- * 2 not registered, but MT is currently searching a new operator to register to
- * 3 registration denied
- * 4 unknown (e.g. out of GERAN/UTRAN/E-UTRAN coverage)
- * 5 registered, roaming
- *
- * <lac>: string type; two byte location area code (when <AcT> indicates
- * value 0 to 6), or tracking area code (when <AcT> indicates
- * value 7). In hexadecimal format
- * <ci>: string type; four byte GERAN/UTRAN/E-UTRAN cell ID in
- * hexadecimal format
- * <AcT>: refer line 190
- *
- * see RIL_REQUEST_VOICE_REGISTRATION_STATE or in RIL
-*/
-void NetworkService::HandleVoiceNetworkRegistration(const Client& client,
- std::string& command) {
- std::vector<std::string> responses;
- std::stringstream ss;
-
- CommandParser cmd(command);
- cmd.SkipPrefix();
- if (*cmd == "AT+CREG?") {
- ss << "+CREG: " << voice_registration_status_.unsol_mode << ","
- << voice_registration_status_.registration_state;
- if (voice_registration_status_.unsol_mode ==
- NetworkRegistrationStatus::REGISTRATION_UNSOL_ENABLED_FULL &&
- (voice_registration_status_.registration_state ==
- NET_REGISTRATION_HOME ||
- voice_registration_status_.registration_state ==
- NET_REGISTRATION_ROAMING ||
- voice_registration_status_.registration_state ==
- NET_REGISTRATION_EMERGENCY)) {
- ss << ",\"" << kAreaCode << "\"" << ",\"" << kCellId << "\","
- << voice_registration_status_.network_type;
- }
-
- responses.push_back(ss.str());
- } else {
- int n = cmd.GetNextInt();
- switch (n) {
- case 0:
- voice_registration_status_.unsol_mode =
- NetworkRegistrationStatus::REGISTRATION_UNSOL_DISABLED;
- break;
- case 1:
- voice_registration_status_.unsol_mode =
- NetworkRegistrationStatus::REGISTRATION_UNSOL_ENABLED;
- break;
- case 2:
- voice_registration_status_.unsol_mode =
- NetworkRegistrationStatus::REGISTRATION_UNSOL_ENABLED_FULL;
- break;
- default:
- client.SendCommandResponse(kCmeErrorInCorrectParameters);
- return;
- }
- }
- responses.push_back("OK");
- client.SendCommandResponse(responses);
-}
-
-/**
- * AT+CGREG
- * The set command controls the presentation of an unsolicited result
- * code +CGREG: <stat> when <n>=1 and there is a change in the MT's
- * GPRS network registration status, or code +CGREG: <stat>[,<lac>,
- * <ci>[,<AcT>]] when <n>=2 and there is a change of the network cell.
- *
- * command Possible response(s)
- * +CGREG=[<n>] +CME ERROR: <err>
- *
- * +CGREG? when <n>=0, 1, 2 or 3 and command successful:
- * +CGREG: <n>,<stat>[,[<lac>],[<ci>],[<AcT>],
- * [<rac>][,<cause_type>,<reject_cause>]]
- * when <n>=4 or 5 and command successful:
- * +CGREG: <n>,<stat>[,[<lac>],[<ci>],[<AcT>],
- * [<rac>][,[<cause_type>],[<reject_cause>][,
- * [<Active-Time>],[<Periodic-RAU>],
- * [<GPRS-READY-timer>]]]]
- * [,<cause_type>,<reject_cause>]]
- *
- * note: see AT+CREG
- *
- * see RIL_REQUEST_DATA_REGISTRATION_STATE in RIL
- */
-void NetworkService::HandleDataNetworkRegistration(const Client& client,
- std::string& command) {
- std::vector<std::string> responses;
- std::stringstream ss;
- std::string prefix;
-
- CommandParser cmd(command);
- cmd.SkipPrefix();
- if (command.find("CGREG") != std::string::npos) {
- prefix = "+CGREG: ";
- } else if (command.find("CEREG") != std::string::npos){
- prefix = "+CEREG: ";
- }
-
- if (*cmd == "AT+CGREG?" || *cmd == "AT+CEREG?") {
- ss << prefix << data_registration_status_.unsol_mode << ","
- << data_registration_status_.registration_state;
- if (voice_registration_status_.unsol_mode ==
- NetworkRegistrationStatus::REGISTRATION_UNSOL_ENABLED_FULL &&
- (voice_registration_status_.registration_state ==
- NET_REGISTRATION_HOME ||
- voice_registration_status_.registration_state ==
- NET_REGISTRATION_ROAMING ||
- voice_registration_status_.registration_state ==
- NET_REGISTRATION_EMERGENCY)) {
- data_registration_status_.network_type =
- getNetworkTypeFromTech(current_network_mode_);
- ss << ",\"" << kAreaCode << "\"" << ",\"" << kCellId << "\"" << ","
- << data_registration_status_.network_type;
- }
- responses.push_back(ss.str());
- } else {
- int n = cmd.GetNextInt();
- switch (n) {
- case 0:
- data_registration_status_.unsol_mode =
- NetworkRegistrationStatus::REGISTRATION_UNSOL_DISABLED;
- break;
- case 1:
- data_registration_status_.unsol_mode =
- NetworkRegistrationStatus::REGISTRATION_UNSOL_ENABLED;
- break;
- case 2:
- data_registration_status_.unsol_mode =
- NetworkRegistrationStatus::REGISTRATION_UNSOL_ENABLED_FULL;
- break;
- default:
- client.SendCommandResponse(kCmeErrorInCorrectParameters);
- return;
- }
- }
- responses.push_back("OK");
- client.SendCommandResponse(responses);
-}
-
-/* AT+CTEC? */
-void NetworkService::HandleGetPreferredNetworkType(const Client& client) {
- std::vector<std::string> responses;
- std::stringstream ss;
-
- ss << "+CTEC: " << current_network_mode_ << "," << std::hex << preferred_network_mode_;
-
- responses.push_back(ss.str());
- responses.push_back("OK");
- client.SendCommandResponse(responses);
-}
-
-/* AT+CTEC=? */
-void NetworkService::HandleQuerySupportedTechs(const Client& client) {
- std::vector<std::string> responses;
- std::stringstream ss;
- ss << "+CTEC: 0,1,5,6"; // NR | LTE | WCDMA | GSM
- responses.push_back(ss.str());
- responses.push_back("OK");
- client.SendCommandResponse(responses);
-}
-
-/**
- * Preferred mode bitmask. This is actually 4 byte-sized bitmasks with different priority values,
- * in which the byte number from LSB to MSB give the priority.
- *
- * |MSB| | |LSB
- * value: |00 |00 |00 |00
- * byte #: |3 |2 |1 |0
- *
- * Higher byte order give higher priority. Thus, a value of 0x0000000f represents
- * a preferred mode of GSM, WCDMA, CDMA, and EvDo in which all are equally preferrable, whereas
- * 0x00000201 represents a mode with GSM and WCDMA, in which WCDMA is preferred over GSM
- */
-int NetworkService::getModemTechFromPrefer(int preferred_mask) {
- int i, j;
-
- // Current implementation will only return the highest priority,
- // lowest numbered technology that is set in the mask.
- for (i = 3 ; i >= 0; i--) {
- for (j = 7 ; j >= 0 ; j--) {
- if (preferred_mask & (1 << (j + 8 * i)))
- return 1 << j;
- }
- }
- // This should never happen. Just to please the compiler.
- return ModemTechnology::M_MODEM_TECH_GSM;
-}
-
-void NetworkService::UpdateRegisterState(RegistrationState state ) {
- voice_registration_status_.registration_state = state;
- data_registration_status_.registration_state = state;
- voice_registration_status_.network_type =
- (NetworkRegistrationStatus::AccessTechnoloy)getNetworkTypeFromTech(current_network_mode_);
- data_registration_status_.network_type =
- (NetworkRegistrationStatus::AccessTechnoloy)getNetworkTypeFromTech(current_network_mode_);
-
- OnVoiceRegisterStateChanged();
- OnDataRegisterStateChanged();
- OnSignalStrengthChanged();
-
- int cellBandwidthDownlink = 5000;
- const int UNKNOWN = 0;
- const int MMWAVE = 4;
- int freq = UNKNOWN;
- if (current_network_mode_ == M_MODEM_TECH_NR) {
- freq = MMWAVE;
- cellBandwidthDownlink = 50000;
- }
-
- data_service_->onUpdatePhysicalChannelconfigs(current_network_mode_, freq,
- cellBandwidthDownlink);
-}
-
-/* AT+CTEC=current,preferred */
-void NetworkService::HandleSetPreferredNetworkType(const Client& client, std::string& command) {
- std::vector<std::string> responses;
- std::stringstream ss;
- int preferred_mask_new;
- CommandParser cmd(command);
- cmd.SkipPrefix();
-
- int current = cmd.GetNextInt();
- std::string preferred(cmd.GetNextStr());
- preferred_mask_new = std::stoi(preferred, nullptr, 16);
- if (preferred_mask_new != preferred_network_mode_) {
- current_network_mode_ = (ModemTechnology)getModemTechFromPrefer(preferred_mask_new);
- preferred_network_mode_ = preferred_mask_new;
- }
-
- if (current != current_network_mode_) {
- UpdateRegisterState(NET_REGISTRATION_UNREGISTERED);
- signal_strength_.Reset();
-
- ss << "+CTEC: "<< current_network_mode_;
-
- thread_looper_->PostWithDelay(std::chrono::milliseconds(200),
- makeSafeCallback(this, &NetworkService::UpdateRegisterState,
- NET_REGISTRATION_HOME));
- } else {
- ss << "+CTEC: DONE";
- }
-
- auto nvram_config = NvramConfig::Get();
- auto instance = nvram_config->ForInstance(service_id_);
- instance.set_modem_technoloy(current_network_mode_);
- instance.set_preferred_network_mode(preferred_network_mode_);
-
- NvramConfig::SaveToFile();
-
- responses.push_back(ss.str());
- responses.push_back("OK");
- client.SendCommandResponse(responses);
-}
-
-void NetworkService::OnVoiceRegisterStateChanged() {
- std::stringstream ss;
-
- switch (voice_registration_status_.unsol_mode) {
- case NetworkRegistrationStatus::REGISTRATION_UNSOL_ENABLED:
- ss << "+CREG: " << voice_registration_status_.registration_state;
- break;
- case NetworkRegistrationStatus::REGISTRATION_UNSOL_ENABLED_FULL:
- ss << "+CREG: " << voice_registration_status_.registration_state;
- if (voice_registration_status_.registration_state ==
- NET_REGISTRATION_HOME ||
- voice_registration_status_.registration_state ==
- NET_REGISTRATION_ROAMING) {
- ss << ",\""<< kAreaCode << "\",\"" << kCellId << "\","
- << voice_registration_status_.network_type;
- }
- break;
- default :
- return;
- }
- SendUnsolicitedCommand(ss.str());
-}
-
-void NetworkService::OnDataRegisterStateChanged() {
- std::stringstream ss;
-
- switch (data_registration_status_.unsol_mode) {
- case NetworkRegistrationStatus::REGISTRATION_UNSOL_ENABLED:
- ss << "+CGREG: " << data_registration_status_.registration_state;
- if (data_registration_status_.network_type ==
- NetworkRegistrationStatus::ACESS_TECH_EUTRAN) {
- ss << "\r+CEREG: " << data_registration_status_.registration_state;
- }
- break;
- case NetworkRegistrationStatus::REGISTRATION_UNSOL_ENABLED_FULL:
- ss << "+CGREG: " << data_registration_status_.registration_state;
- if (data_registration_status_.registration_state ==
- NET_REGISTRATION_HOME ||
- data_registration_status_.registration_state ==
- NET_REGISTRATION_ROAMING) {
- ss << ",\"" << kAreaCode << "\",\"" << kCellId << "\","
- << data_registration_status_.network_type;
- }
- if (data_registration_status_.network_type ==
- NetworkRegistrationStatus::ACESS_TECH_EUTRAN) {
- ss << "\r+CEREG: " << data_registration_status_.registration_state;
- if (data_registration_status_.registration_state ==
- NET_REGISTRATION_HOME ||
- data_registration_status_.registration_state ==
- NET_REGISTRATION_ROAMING) {
- ss << ",\"" << kAreaCode << "\",\"" << kCellId << "\","
- << data_registration_status_.network_type;
- }
- }
- break;
- default:
- return;
- }
- SendUnsolicitedCommand(ss.str());
-}
-
-std::string NetworkService::GetSignalStrength() {
- switch (current_network_mode_) {
- case M_MODEM_TECH_GSM:
- signal_strength_.gsm_rssi += (rand() % 3 - 1);
- AdjustSignalStrengthValue(signal_strength_.gsm_rssi, kGSMSignalStrength);
- break;
- case M_MODEM_TECH_CDMA:
- signal_strength_.cdma_dbm += (rand() % 3 - 1);
- AdjustSignalStrengthValue(signal_strength_.cdma_dbm, kCDMASignalStrength);
- break;
- case M_MODEM_TECH_EVDO:
- signal_strength_.evdo_dbm += (rand() % 3 - 1);
- AdjustSignalStrengthValue(signal_strength_.evdo_dbm, kEVDOSignalStrength);
- break;
- case M_MODEM_TECH_LTE:
- signal_strength_.lte_rssi += (rand() % 3 - 1);
- AdjustSignalStrengthValue(signal_strength_.lte_rssi, kLTESignalStrength);
- break;
- case M_MODEM_TECH_WCDMA:
- signal_strength_.wcdma_rssi += (rand() % 3 - 1);
- AdjustSignalStrengthValue(signal_strength_.wcdma_rssi, kWCDMASignalStrength);
- break;
- case M_MODEM_TECH_NR:
- signal_strength_.nr_ss_rsrp += (rand() % 3 - 1);
- AdjustSignalStrengthValue(signal_strength_.nr_ss_rsrp, kNRSignalStrength);
- break;
- default:
- break;
- }
-
- std::stringstream ss;
- ss << "+CSQ: " << signal_strength_.gsm_rssi << ","
- << signal_strength_.gsm_ber << ","
- << signal_strength_.cdma_dbm << ","
- << signal_strength_.cdma_ecio << ","
- << signal_strength_.evdo_dbm << ","
- << signal_strength_.evdo_ecio << ","
- << signal_strength_.evdo_snr << ","
- << signal_strength_.lte_rssi << ","
- << signal_strength_.lte_rsrp << ","
- << signal_strength_.lte_rsrq << ","
- << signal_strength_.lte_rssnr << ","
- << signal_strength_.lte_cqi << ","
- << signal_strength_.lte_ta << ","
- << signal_strength_.tdscdma_rscp << ","
- << signal_strength_.wcdma_rssi << ","
- << signal_strength_.wcdma_ber << ","
- << signal_strength_.nr_ss_rsrp << ","
- << signal_strength_.nr_ss_rsrq << ","
- << signal_strength_.nr_ss_sinr << ","
- << signal_strength_.nr_csi_rsrp << ","
- << signal_strength_.nr_csi_rsrq << ","
- << signal_strength_.nr_csi_sinr;;
- return ss.str();
-}
-
-/* AT+REMOTEREG: state*/
-void NetworkService::HandleReceiveRemoteVoiceDataReg(const Client& client,
- std::string& command) {
- (void)client;
- std::stringstream ss;
- std::string states = command.substr(std::string("AT+REMOTEREG:").size());
- int stated = std::stoi(states, nullptr, 10);
-
- UpdateRegisterState(NET_REGISTRATION_UNREGISTERED);
- signal_strength_.Reset();
-
- thread_looper_->PostWithDelay(
- std::chrono::seconds(1),
- makeSafeCallback(this, &NetworkService::UpdateRegisterState,
- (cuttlefish::NetworkService::RegistrationState)stated));
-}
-
-/* AT+REMOTECTEC: ctec */
-void NetworkService::HandleReceiveRemoteCTEC(const Client& client,
- std::string& command) {
- (void)client;
- LOG(DEBUG) << "calling ctec from remote";
- std::stringstream ss;
- std::string types = command.substr(std::string("AT+REMOTECTEC: ").size());
- int preferred_mask_new = std::stoi(types, nullptr, 10);
-
- if (preferred_mask_new != preferred_network_mode_) {
- preferred_network_mode_ = preferred_mask_new;
- }
- auto current_network_mode_new =
- (ModemTechnology)getModemTechFromPrefer(preferred_mask_new);
- if (current_network_mode_new != current_network_mode_) {
- current_network_mode_ = current_network_mode_new;
- auto saved_state = voice_registration_status_.registration_state;
- UpdateRegisterState(NET_REGISTRATION_UNREGISTERED);
- signal_strength_.Reset();
-
- ss << "+CTEC: " << current_network_mode_;
-
- thread_looper_->PostWithDelay(
- std::chrono::seconds(1),
- makeSafeCallback(this, &NetworkService::UpdateRegisterState,
- saved_state));
- }
-}
-
-void NetworkService::applySignalPercentage(double percentd) {
- switch (current_network_mode_) {
- case M_MODEM_TECH_GSM:
- signal_strength_.gsm_rssi = 99;
- signal_strength_.gsm_ber = 0;
- SetSignalStrengthValue(signal_strength_.gsm_rssi, kGSMSignalStrength,
- percentd);
- break;
- case M_MODEM_TECH_CDMA:
- signal_strength_.cdma_dbm = 125;
- signal_strength_.cdma_ecio = 165;
- SetSignalStrengthValue(signal_strength_.cdma_dbm, kCDMASignalStrength,
- percentd);
- break;
- case M_MODEM_TECH_EVDO:
- signal_strength_.evdo_dbm = 125;
- signal_strength_.evdo_ecio = 165;
- signal_strength_.evdo_snr = -1;
- SetSignalStrengthValue(signal_strength_.evdo_dbm, kEVDOSignalStrength,
- percentd);
- break;
- case M_MODEM_TECH_LTE:
- signal_strength_.lte_rssi = 99;
- signal_strength_.lte_rsrp = -1;
- signal_strength_.lte_rsrq = -5;
- signal_strength_.lte_rssnr = -205;
- signal_strength_.lte_cqi = -1;
- signal_strength_.lte_ta = -1;
- SetSignalStrengthValue(signal_strength_.lte_rssi, kLTESignalStrength,
- percentd);
- break;
- case M_MODEM_TECH_WCDMA:
- signal_strength_.tdscdma_rscp = 99;
- signal_strength_.wcdma_rssi = 99;
- signal_strength_.wcdma_ber = 0;
- SetSignalStrengthValue(signal_strength_.wcdma_rssi, kWCDMASignalStrength,
- percentd);
- break;
- case M_MODEM_TECH_NR:
- // special for NR: it uses LTE as primary, so LTE signal strength is
- // needed as well
- signal_strength_.lte_rssi = 99;
- signal_strength_.lte_rsrp = -1;
- signal_strength_.lte_rsrq = -5;
- signal_strength_.lte_rssnr = -205;
- signal_strength_.lte_cqi = -1;
- signal_strength_.lte_ta = -1;
- SetSignalStrengthValue(signal_strength_.lte_rssi, kLTESignalStrength,
- percentd);
- signal_strength_.nr_ss_rsrp = 0;
- signal_strength_.nr_ss_rsrq = 0;
- signal_strength_.nr_ss_sinr = 45;
- signal_strength_.nr_csi_rsrp = 0;
- signal_strength_.nr_csi_rsrq = 0;
- signal_strength_.nr_csi_sinr = 30;
- SetSignalStrengthValue(signal_strength_.nr_ss_rsrp, kNRSignalStrength,
- percentd);
- break;
- default:
- break;
- }
-}
-
-/* AT+REMOTESIGNAL: percent */
-void NetworkService::HandleReceiveRemoteSignal(const Client& client,
- std::string& command) {
- (void)client;
- std::stringstream ss;
- std::string percents = command.substr(std::string("AT+REMOTESIGNAL:").size());
- double percentd = std::stoi(percents, nullptr, 10) / 100.0;
-
- if (percentd >= 0 && percentd <= 1.0) {
- percentd_ = percentd;
- } else {
- LOG(DEBUG) << "out of bound signal strength: " << percentd;
- return;
- }
-
- OnSignalStrengthChanged();
-}
-
-void NetworkService::OnSignalStrengthChanged() {
- applySignalPercentage(percentd_);
- auto command = GetSignalStrength();
- SendUnsolicitedCommand(command);
-}
-
-NetworkService::RegistrationState NetworkService::GetVoiceRegistrationState() const {
- return voice_registration_status_.registration_state;
-}
-} // namespace cuttlefish
diff --git a/host/commands/modem_simulator/network_service.h b/host/commands/modem_simulator/network_service.h
deleted file mode 100644
index b64d4b981..000000000
--- a/host/commands/modem_simulator/network_service.h
+++ /dev/null
@@ -1,320 +0,0 @@
-//
-// Copyright (C) 2020 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 <ctime>
-
-#include "host/commands/modem_simulator/data_service.h"
-#include "host/commands/modem_simulator/misc_service.h"
-#include "host/commands/modem_simulator/modem_service.h"
-#include "host/commands/modem_simulator/sim_service.h"
-
-namespace cuttlefish {
-
-class NetworkService : public ModemService, public std::enable_shared_from_this<NetworkService> {
- public:
- NetworkService(int32_t service_id_, ChannelMonitor* channel_monitor,
- ThreadLooper* thread_looper);
- ~NetworkService() = default;
-
- NetworkService(const NetworkService &) = delete;
- NetworkService &operator=(const NetworkService &) = delete;
-
- void SetupDependency(MiscService* misc, SimService* sim, DataService* data);
-
- void HandleRadioPowerReq(const Client& client);
- void HandleRadioPower(const Client& client, std::string& command);
- void HandleSignalStrength(const Client& client);
- void HandleQueryNetworkSelectionMode(const Client& client);
- void HandleRequestOperator(const Client& client);
- void HandleQueryAvailableNetwork(const Client& client);
- void HandleSetNetworkSelectionMode(const Client& client, std::string& command);
- void HandleVoiceNetworkRegistration(const Client& client, std::string& command);
- void HandleDataNetworkRegistration(const Client& client, std::string& command);
- void HandleGetPreferredNetworkType(const Client& client);
- void HandleQuerySupportedTechs(const Client& client);
- void HandleSetPreferredNetworkType(const Client& client, std::string& command);
- void HandleNetworkRegistration(cuttlefish::SharedFD client, std::string& command);
-
- void HandleReceiveRemoteVoiceDataReg(const Client& client,
- std::string& command);
- void HandleReceiveRemoteCTEC(const Client& client, std::string& command);
- void HandleReceiveRemoteSignal(const Client& client, std::string& command);
-
- void OnSimStatusChanged(SimService::SimStatus sim_status);
- void OnVoiceRegisterStateChanged();
- void OnDataRegisterStateChanged();
- void OnSignalStrengthChanged();
-
- enum RegistrationState {
- NET_REGISTRATION_UNREGISTERED = 0,
- NET_REGISTRATION_HOME = 1,
- NET_REGISTRATION_SEARCHING = 2,
- NET_REGISTRATION_DENIED = 3,
- NET_REGISTRATION_UNKNOWN = 4,
- NET_REGISTRATION_ROAMING = 5,
- NET_REGISTRATION_EMERGENCY = 8
- };
- RegistrationState GetVoiceRegistrationState() const;
-
- bool isRadioOff() const { return radio_state_ == RADIO_STATE_OFF; }
-
- private:
- void InitializeServiceState();
- std::vector<CommandHandler> InitializeCommandHandlers();
- void InitializeNetworkOperator();
- void InitializeSimOperator();
-
- bool WakeupFromSleep();
- bool IsHasNetwork();
- void UpdateRegisterState(RegistrationState state);
- void AdjustSignalStrengthValue(int& value, const std::pair<int, int>& range);
- void SetSignalStrengthValue(int& value, const std::pair<int, int>& range,
- double percentd);
- std::string GetSignalStrength();
- void applySignalPercentage(double percentd);
-
- MiscService* misc_service_ = nullptr;
- SimService* sim_service_ = nullptr;
- DataService* data_service_ = nullptr;
-
- enum RadioState : int32_t {
- RADIO_STATE_OFF,
- RADIO_STATE_ON,
- };
- RadioState radio_state_;
-
- /* Operator */
- struct NetworkOperator {
- enum OperatorState {
- OPER_STATE_UNKNOWN = 0,
- OPER_STATE_AVAILABLE = 1,
- OPER_STATE_CURRENT = 2,
- OPER_STATE_FORBIDDEN = 3
- };
-
- std::string numeric;
- std::string long_name;
- std::string short_name;
- OperatorState operator_state;
-
- NetworkOperator() {}
-
- NetworkOperator(const std::string& number,
- const std::string& ln,
- const std::string& sn,
- OperatorState state)
- : numeric(number),
- long_name(ln),
- short_name(sn),
- operator_state(state) {}
- };
-
- enum OperatorSelectionMode {
- OPER_SELECTION_AUTOMATIC = 0,
- OPER_SELECTION_MANUAL,
- OPER_SELECTION_DEREGISTRATION,
- OPER_SELECTION_SET_FORMAT,
- OPER_SELECTION_MANUAL_AUTOMATIC
- };
-
- std::vector<NetworkOperator> operator_list_;
- std::string current_operator_numeric_ = "";
- OperatorSelectionMode oper_selection_mode_;
-
- /* SignalStrength */
- struct SignalStrength {
- int gsm_rssi; /* Valid values are (0-31, 99) as defined in TS 27.007 8.5 */
- int gsm_ber; /* bit error rate (0-7, 99) as defined in TS 27.007 8.5 */
-
- int cdma_dbm; /* Valid values are positive integers. This value is the actual RSSI value
- * multiplied by -1. Example: If the actual RSSI is -75, then this response
- * value will be 75.
- */
- int cdma_ecio; /* Valid values are positive integers. This value is the actual Ec/Io multiplied
- * by -10. Example: If the actual Ec/Io is -12.5 dB, then this response value
- * will be 125.
- */
-
- int evdo_dbm; /* Refer cdma_dbm */
- int evdo_ecio; /* Refer cdma_ecio */
- int evdo_snr; /* Valid values are 0-8. 8 is the highest signal to noise ratio. */
-
- int lte_rssi; /* Refer gsm_rssi */
- int lte_rsrp; /* The current Reference Signal Receive Power in dBm multiplied by -1.
- * Range: 44 to 140 dBm
- * INT_MAX: 0x7FFFFFFF denotes invalid value.
- * Reference: 3GPP TS 36.133 9.1.4 */
- int lte_rsrq; /* The current Reference Signal Receive Quality in dB multiplied by -1.
- * Range: 20 to 3 dB.
- * INT_MAX: 0x7FFFFFFF denotes invalid value.
- * Reference: 3GPP TS 36.133 9.1.7 */
- int lte_rssnr; /* The current reference signal signal-to-noise ratio in 0.1 dB units.
- * Range: -200 to +300 (-200 = -20.0 dB, +300 = 30dB).
- * INT_MAX : 0x7FFFFFFF denotes invalid value.
- * Reference: 3GPP TS 36.101 8.1.1 */
- int lte_cqi; /* The current Channel Quality Indicator.
- * Range: 0 to 15.
- * INT_MAX : 0x7FFFFFFF denotes invalid value.
- * Reference: 3GPP TS 36.101 9.2, 9.3, A.4 */
- int lte_ta; /* timing advance in micro seconds for a one way trip from cell to device.
- * Approximate distance can be calculated using 300m/us * timingAdvance.
- * Range: 0 to 0x7FFFFFFE
- * INT_MAX : 0x7FFFFFFF denotes invalid value.
- * Reference: 3GPP 36.321 section 6.1.3.5 */
-
- int tdscdma_rscp; /* P-CCPCH RSCP as defined in TS 25.225 5.1.1
- * Valid values are (0-96, 255) as defined in TS 27.007 8.69
- * INT_MAX denotes that the value is invalid/unreported. */
-
- int wcdma_rssi; /* Refer gsm_rssi */
- int wcdma_ber; /* Refer gsm_ber */
-
- int32_t nr_ss_rsrp; /* SS reference signal received power, multiplied by -1.
- * Reference: 3GPP TS 38.215.
- * Range [44, 140], INT_MAX means invalid/unreported. */
- int32_t nr_ss_rsrq; /* SS reference signal received quality, multiplied by -1.
- * Reference: 3GPP TS 38.215.
- * Range [3, 20], INT_MAX means invalid/unreported. */
- int32_t nr_ss_sinr; /* SS signal-to-noise and interference ratio.
- * Reference: 3GPP TS 38.215 section 5.1.*, 3GPP TS 38.133 section 10.1.16.1.
- * Range [-23, 40], INT_MAX means invalid/unreported. */
- int32_t nr_csi_rsrp; /* CSI reference signal received power, multiplied by -1.
- * Reference: 3GPP TS 38.215.
- * Range [44, 140], INT_MAX means invalid/unreported. */
- int32_t nr_csi_rsrq; /* CSI reference signal received quality, multiplied by -1.
- * Reference: 3GPP TS 38.215.
- * Range [3, 20], INT_MAX means invalid/unreported. */
- int32_t nr_csi_sinr; /* CSI signal-to-noise and interference ratio.
- * Reference: 3GPP TS 138.215 section 5.1.*, 3GPP TS 38.133 section 10.1.16.1.
- * Range [-23, 40], INT_MAX means invalid/unreported. */
-
- // Default invalid value
- SignalStrength():
- gsm_rssi(99), // [0, 31]
- gsm_ber(0), // [7, 99]
- cdma_dbm(125), // [0, 120]
- cdma_ecio(165), // [0, 160]
- evdo_dbm(125), // [0, 120]
- evdo_ecio(165), // [0, 160]
- evdo_snr(-1), // [0, 8]
- lte_rssi(99), // [0, 31]
- lte_rsrp(-1), // [43,140]
- lte_rsrq(-5), // [-3,34]
- lte_rssnr(-205), // [-200, 300]
- lte_cqi(-1), // [0, 15]
- lte_ta(-1), // [0, 1282]
- tdscdma_rscp(99), // [0, 96]
- wcdma_rssi(99), // [0, 31]
- wcdma_ber(0), // [7, 99]
- nr_ss_rsrp(0), // [44, 140]
- nr_ss_rsrq(0), // [3, 10]
- nr_ss_sinr(45), // [-23,40]
- nr_csi_rsrp(0), // [44, 140]
- nr_csi_rsrq(0), // [3, 20]
- nr_csi_sinr(30) // [-23, 23]
- {}
-
- // After radio power on, off, or set network mode, reset to invalid value
- void Reset() {
- gsm_rssi = INT_MAX;
- gsm_ber = INT_MAX;
- cdma_dbm = INT_MAX;
- cdma_ecio = INT_MAX;
- evdo_dbm = INT_MAX;
- evdo_ecio = INT_MAX;
- evdo_snr = INT_MAX;
- lte_rssi = INT_MAX;
- lte_rsrp = INT_MAX;
- lte_rsrq = INT_MAX;
- lte_rssnr = INT_MAX;
- lte_cqi = INT_MAX;
- lte_ta = INT_MAX;
- tdscdma_rscp = INT_MAX;
- wcdma_rssi = INT_MAX;
- wcdma_ber = INT_MAX;
- nr_ss_rsrp = INT_MAX;
- nr_ss_rsrq = INT_MAX;
- nr_ss_sinr = INT_MAX;
- nr_csi_rsrp = INT_MAX;
- nr_csi_rsrq = INT_MAX;
- nr_csi_sinr = INT_MAX;
- }
- };
-
- double percentd_{0.8};
- SignalStrength signal_strength_;
-
- /* Data / voice Registration State */
- struct NetworkRegistrationStatus {
- enum RegistrationUnsolMode {
- REGISTRATION_UNSOL_DISABLED = 0,
- REGISTRATION_UNSOL_ENABLED = 1,
- REGISTRATION_UNSOL_ENABLED_FULL = 2
- };
-
- enum AccessTechnoloy {
- ACESS_TECH_GSM = 0,
- ACESS_TECH_GSM_COMPACT = 1,
- ACESS_TECH_UTRAN = 2,
- ACESS_TECH_EGPRS = 3,
- ACESS_TECH_HSDPA = 4,
- ACESS_TECH_HSUPA = 5,
- ACESS_TECH_HSPA = 6,
- ACESS_TECH_EUTRAN = 7,
- ACESS_TECH_EC_GSM_IoT = 8,
- ACESS_TECH_E_UTRAN = 9,
- ACESS_TECH_E_UTRA = 10,
- ACESS_TECH_NR = 11,
- ACESS_TECH_NG_RAN = 12,
- ACESS_TECH_E_UTRA_NR = 13
- };
-
- NetworkRegistrationStatus() :
- unsol_mode(REGISTRATION_UNSOL_ENABLED_FULL),
- registration_state(NET_REGISTRATION_UNREGISTERED),
- network_type(ACESS_TECH_EUTRAN) {}
-
- RegistrationUnsolMode unsol_mode;
- RegistrationState registration_state;
- AccessTechnoloy network_type;
- };
-
- NetworkRegistrationStatus voice_registration_status_;
- NetworkRegistrationStatus data_registration_status_;
-
- enum ModemTechnology {
- M_MODEM_TECH_GSM = 1 << 0,
- M_MODEM_TECH_WCDMA = 1 << 1,
- M_MODEM_TECH_CDMA = 1 << 2,
- M_MODEM_TECH_EVDO = 1 << 3,
- M_MODEM_TECH_TDSCDMA= 1 << 4,
- M_MODEM_TECH_LTE = 1 << 5,
- M_MODEM_TECH_NR = 1 << 6,
- };
- ModemTechnology current_network_mode_;
- int preferred_network_mode_;
- int modem_radio_capability_;
-
- NetworkRegistrationStatus::AccessTechnoloy getNetworkTypeFromTech(ModemTechnology modemTech);
- int getModemTechFromPrefer(int preferred_mask);
- ModemTechnology getTechFromNetworkType(NetworkRegistrationStatus::AccessTechnoloy act);
-
- bool first_signal_strength_request_; // For time update
- time_t android_last_signal_time_;
-};
-
-} // namespace cuttlefish
diff --git a/host/commands/modem_simulator/nvram_config.cpp b/host/commands/modem_simulator/nvram_config.cpp
deleted file mode 100644
index 7efb4c936..000000000
--- a/host/commands/modem_simulator/nvram_config.cpp
+++ /dev/null
@@ -1,200 +0,0 @@
-//
-// Copyright (C) 2020 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 "host/commands/modem_simulator/nvram_config.h"
-
-#include <android-base/logging.h>
-#include <json/json.h>
-
-#include <fstream>
-#include <mutex>
-#include <sstream>
-
-#include "common/libs/utils/files.h"
-#include "host/commands/modem_simulator/device_config.h"
-
-namespace cuttlefish {
-
-const char* kInstances = "instances";
-const char* kNetworkSelectionMode = "network_selection_mode";
-const char* kOperatorNumeric = "operator_numeric";
-const char* kModemTechnoloy = "modem_technoloy";
-const char* kPreferredNetworkMode = "preferred_network_mode";
-const char* kEmergencyMode = "emergency_mode";
-const char* kSimType = "sim_type";
-
-const int kDefaultNetworkSelectionMode = 0; // AUTOMATIC
-const std::string kDefaultOperatorNumeric = "";
-const int kDefaultModemTechnoloy = 0x10; // LTE
-const int kDefaultPreferredNetworkMode = 0x13; // LTE | WCDMA | GSM
-const bool kDefaultEmergencyMode = false;
-
-/**
- * Creates the (initially empty) config object and populates it with values from
- * the config file "modem_nvram.json" located in the cuttlefish instance path,
- * or uses the default value if the config file not exists,
- * Returns nullptr if there was an error loading from file
- */
-NvramConfig* NvramConfig::BuildConfigImpl(size_t num_instances, int sim_type) {
- auto nvram_config_path =
- cuttlefish::modem::DeviceConfig::PerInstancePath("modem_nvram.json");
-
- auto ret = new NvramConfig(num_instances, sim_type);
- if (ret) {
- if (!cuttlefish::FileExists(nvram_config_path) ||
- !cuttlefish::FileHasContent(nvram_config_path.c_str())) {
- ret->InitDefaultNvramConfig();
- } else {
- auto loaded = ret->LoadFromFile(nvram_config_path.c_str());
- if (!loaded) {
- delete ret;
- return nullptr;
- }
- }
- }
- return ret;
-}
-
-std::unique_ptr<NvramConfig> NvramConfig::s_nvram_config;
-
-void NvramConfig::InitNvramConfigService(size_t num_instances, int sim_type) {
- static std::once_flag once_flag;
-
- std::call_once(once_flag, [num_instances, sim_type]() {
- NvramConfig::s_nvram_config.reset(BuildConfigImpl(num_instances, sim_type));
- });
-}
-
-/* static */ const NvramConfig* NvramConfig::Get() {
- return s_nvram_config.get();
-}
-
-void NvramConfig::SaveToFile() {
- auto nvram_config = Get();
- auto nvram_config_file = nvram_config->ConfigFileLocation();
- nvram_config->SaveToFile(nvram_config_file);
-}
-
-NvramConfig::NvramConfig(size_t num_instances, int sim_type)
- : total_instances_(num_instances),
- sim_type_(sim_type),
- dictionary_(new Json::Value()) {}
-// Can't use '= default' on the header because the compiler complains of
-// Json::Value being an incomplete type
-NvramConfig::~NvramConfig() = default;
-
-NvramConfig::NvramConfig(NvramConfig&&) = default;
-NvramConfig& NvramConfig::operator=(NvramConfig&&) = default;
-
-NvramConfig::InstanceSpecific NvramConfig::ForInstance(int num) const {
- return InstanceSpecific(this, std::to_string(num));
-}
-
-std::string NvramConfig::ConfigFileLocation() const {
- return cuttlefish::AbsolutePath(
- cuttlefish::modem::DeviceConfig::PerInstancePath("modem_nvram.json"));
-}
-
-bool NvramConfig::LoadFromFile(const char* file) {
- auto real_file_path = cuttlefish::AbsolutePath(file);
- if (real_file_path.empty()) {
- LOG(ERROR) << "Could not get real path for file " << file;
- return false;
- }
-
- Json::CharReaderBuilder builder;
- std::ifstream ifs(real_file_path);
- std::string errorMessage;
- if (!Json::parseFromStream(builder, ifs, dictionary_.get(), &errorMessage)) {
- LOG(ERROR) << "Could not read config file " << file << ": "
- << errorMessage;
- return false;
- }
- return true;
-}
-
-bool NvramConfig::SaveToFile(const std::string& file) const {
- std::ofstream ofs(file);
- if (!ofs.is_open()) {
- LOG(ERROR) << "Unable to write to file " << file;
- return false;
- }
- ofs << *dictionary_;
- return !ofs.fail();
-}
-
-void NvramConfig::InitDefaultNvramConfig() {
- for (size_t num = 0; num < total_instances_; num++) {
- auto instance = ForInstance(num);
- instance.set_modem_technoloy(kDefaultModemTechnoloy);
- instance.set_network_selection_mode(kDefaultNetworkSelectionMode);
- instance.set_preferred_network_mode(kDefaultPreferredNetworkMode);
- instance.set_emergency_mode(kDefaultEmergencyMode);
- }
-}
-
-const Json::Value* NvramConfig::InstanceSpecific::Dictionary() const {
- return &(*config_->dictionary_)[kInstances][id_];
-}
-
-Json::Value* NvramConfig::InstanceSpecific::Dictionary() {
- return &(*config_->dictionary_)[kInstances][id_];
-}
-
-int NvramConfig::InstanceSpecific::network_selection_mode() const {
- return (*Dictionary())[kNetworkSelectionMode].asInt();
-}
-
-void NvramConfig::InstanceSpecific::set_network_selection_mode(int mode) {
- (*Dictionary())[kNetworkSelectionMode] = mode;
-}
-
-std::string NvramConfig::InstanceSpecific::operator_numeric() const {
- return (*Dictionary())[kOperatorNumeric].asString();
-}
-
-void NvramConfig::InstanceSpecific::set_operator_numeric(std::string& operator_numeric) {
- (*Dictionary())[kOperatorNumeric] = operator_numeric;
-}
-
-int NvramConfig::InstanceSpecific::modem_technoloy() const {
- return (*Dictionary())[kModemTechnoloy].asInt();
-}
-
-void NvramConfig::InstanceSpecific::set_modem_technoloy(int technoloy) {
- (*Dictionary())[kModemTechnoloy] = technoloy;
-}
-
-int NvramConfig::InstanceSpecific::preferred_network_mode() const {
- return (*Dictionary())[kPreferredNetworkMode].asInt();
-}
-
-void NvramConfig::InstanceSpecific::set_preferred_network_mode(int mode) {
- (*Dictionary())[kPreferredNetworkMode] = mode;
-}
-
-bool NvramConfig::InstanceSpecific::emergency_mode() const {
- return (*Dictionary())[kEmergencyMode].asBool();
-}
-
-void NvramConfig::InstanceSpecific::set_emergency_mode(bool mode) {
- (*Dictionary())[kEmergencyMode] = mode;
-}
-
-int NvramConfig::sim_type() const {
- return sim_type_;
-}
-
-} // namespace cuttlefish
diff --git a/host/commands/modem_simulator/nvram_config.h b/host/commands/modem_simulator/nvram_config.h
deleted file mode 100644
index fc51c80fb..000000000
--- a/host/commands/modem_simulator/nvram_config.h
+++ /dev/null
@@ -1,94 +0,0 @@
-//
-// Copyright (C) 2020 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 <json/json.h>
-
-namespace cuttlefish {
-
-// Holds the configuration of modem simulator.
-class NvramConfig {
-
- public:
- static void InitNvramConfigService(size_t num_instances, int sim_type);
- static const NvramConfig* Get();
- static void SaveToFile();
-
- NvramConfig(size_t num_instances, int sim_type);
- NvramConfig(NvramConfig&&);
- ~NvramConfig();
- NvramConfig& operator=(NvramConfig&&);
-
- std::string ConfigFileLocation() const;
- // Saves the configuration object in a file
- bool SaveToFile(const std::string& file) const;
-
- class InstanceSpecific;
-
- InstanceSpecific ForInstance(int instance_num) const;
-
- std::vector<InstanceSpecific> Instances() const;
-
- int sim_type() const;
-
- // A view into an existing modem simulator object for a particular instance.
- class InstanceSpecific {
- public:
- int network_selection_mode() const;
- void set_network_selection_mode(int mode);
-
- std::string operator_numeric() const;
- void set_operator_numeric(std::string& operator_numeric);
-
- int modem_technoloy() const;
- void set_modem_technoloy(int technoloy);
-
- int preferred_network_mode() const;
- void set_preferred_network_mode(int mode);
-
- bool emergency_mode() const;
- void set_emergency_mode(bool mode);
-
- private:
- friend InstanceSpecific NvramConfig::ForInstance(int num) const;
- friend std::vector<InstanceSpecific> NvramConfig::Instances() const;
-
- InstanceSpecific(const NvramConfig* config, const std::string& id)
- : config_(config), id_(id) {}
-
- Json::Value* Dictionary();
- const Json::Value* Dictionary() const;
-
- const NvramConfig* config_;
- std::string id_;
- };
-
- private:
- static std::unique_ptr<NvramConfig> s_nvram_config;
- size_t total_instances_;
- int sim_type_;
- std::unique_ptr<Json::Value> dictionary_;
-
- bool LoadFromFile(const char* file);
- static NvramConfig* BuildConfigImpl(size_t num_instances, int sim_type);
-
- void InitDefaultNvramConfig();
-
- NvramConfig(const NvramConfig&) = delete;
- NvramConfig& operator=(const NvramConfig&) = delete;
-};
-
-} // namespace cuttlefish
diff --git a/host/commands/modem_simulator/pdu_parser.cpp b/host/commands/modem_simulator/pdu_parser.cpp
deleted file mode 100644
index 5cc425e59..000000000
--- a/host/commands/modem_simulator/pdu_parser.cpp
+++ /dev/null
@@ -1,300 +0,0 @@
-//
-// Copyright (C) 2020 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 "host/commands/modem_simulator/pdu_parser.h"
-
-#include <algorithm>
-#include <chrono>
-#include <ctime>
-#include <iomanip>
-#include <sstream>
-#include <string>
-#include <thread>
-
-namespace cuttlefish {
-
-static const std::string kWithoutServiceCenterAddress = "00";
-static const std::string kStatusReportIndicator = "06";
-static const std::string kSRIAndMMSIndicator = "24"; /* SRI is 1 && MMS is 1*/
-static const std::string kUDHIAndSRIAndMMSIndicator = "64"; /* UDHI is 1 && SRI is 1 && MMS is 1*/
-
-PDUParser::PDUParser(std::string &pdu) {
- is_valid_pdu_ = DecodePDU(pdu);
-}
-
-bool PDUParser::IsValidPDU() {
- return is_valid_pdu_;
-}
-
-/**
- * PDU format:
- * SCA PDU-Type MR OA PID DCS VP UDL UD
- * bytes: 1-12 1 1 2-12 1 1 0 1 0-140
- * eg. 00 21 00 0B 91 5155255155F4 00 00 0C AB58AD56ABC962B55A8D06
- */
-// 00 01 00 05 81 0180F6 00 00 0D 61B2996C0691CD6433190402
-bool PDUParser::DecodePDU(std::string& pdu) {
- // At least: SCA(1) + PDU-Type(1) + MR(1) + OA(2) + PID(1) + DSC(1) + UDL(1)
- auto pdu_total_length = pdu.size();
- if (pdu_total_length < 8) {
- return false;
- }
-
- std::string_view pdu_view = pdu;
- size_t pos = 0;
-
- /* 1. SMSC Address Length: 1 byte */
- std::string temp = pdu.substr(0, 2);
- pos += 2;
- if (temp != kWithoutServiceCenterAddress) {
- auto smsc_length = Hex2ToByte(temp);
- pos += smsc_length * 2; // Skip SMSC Address
- }
-
- /* 2. PDU-Type: 1 byte */
- pdu_type_ = pdu_view.substr(std::min(pos, pdu_total_length), 2);
- pos += 2;
-
- /* 3. MR: 1 byte */
- message_reference_ = pdu_view.substr(std::min(pos, pdu_total_length), 2);
- pos += 2;
-
- /* 4. Originator Address Length: 1 byte */
- temp = pdu_view.substr(std::min(pos, pdu_total_length), 2);
- auto oa_length = Hex2ToByte(temp);
- if (oa_length & 0x01) oa_length += 1;
-
- /* 5. Originator Address including OA length */
- originator_address_ = pdu_view.substr(std::min(pos, pdu_total_length), (oa_length + 4));
- pos += (oa_length + 4);
-
- /* 6. Protocol ID: 1 byte */
- protocol_id_ = pdu_view.substr(std::min(pos, pdu_total_length), 2);
- pos += 2;
-
- /* 7. Data Code Scheme: 1 byte */
- data_code_scheme_ = pdu_view.substr(std::min(pos, pdu_total_length), 2);
- pos += 2;
-
- /* 8. User Data Length: 1 byte */
- temp = pdu_view.substr(std::min(pos, pdu_total_length), 2);
- auto ud_length = Hex2ToByte(temp);
-
- /* 9. User Data including UDL */
- user_data_ = pdu_view.substr(std::min(pos, pdu_total_length));
-
- if (data_code_scheme_ == "00") { // GSM_7BIT
- pos += ud_length * 2 + 2;
- int offset = ud_length / 8;
- pos -= offset * 2;
- } else if (data_code_scheme_ == "08") { // GSM_UCS2
- pos += ud_length;
- } else {
- pos += ud_length * 2 + 2;
- }
- if (pos == pdu_total_length) {
- return true;
- }
-
- return false;
-}
-
-/**
- * The PDU-Type of receiver
- * BIT 7 6 5 4 3 2 1 0
- * Param RP UDHI SRI - - MMS MTI MTI
- * When SRR bit is 1, it represents that SMS status report should be reported.
- */
-std::string PDUParser::CreatePDU() {
- if (!is_valid_pdu_) return "";
-
- // Ignore SMSC address, default to be '00'
- std::string pdu = kWithoutServiceCenterAddress;
- int pdu_type = Hex2ToByte(pdu_type_);
-
- if (pdu_type & 0x40) {
- pdu += kUDHIAndSRIAndMMSIndicator;
- } else {
- pdu += kSRIAndMMSIndicator;
- }
-
- pdu += originator_address_ + protocol_id_ + data_code_scheme_;
- pdu += GetCurrentTimeStamp();
- pdu += user_data_;
-
- return pdu;
-}
-
-/**
- * the PDU-Type of sender
- * BIT 7 6 5 4 3 2 1 0
- * Param RP UDHI SRR VPF VPF RD MTI MTI
- * When SRR bit is 1, it represents that SMS status report should be reported.
- */
-bool PDUParser::IsNeededStatuReport() {
- if (!is_valid_pdu_) return false;
-
- int pdu_type = Hex2ToByte(pdu_type_);
- if (pdu_type & 0x20) {
- return true;
- }
-
- return false;
-}
-
-std::string PDUParser::CreateStatuReport(int message_reference) {
- if (!is_valid_pdu_) return "";
-
- std::string pdu = kWithoutServiceCenterAddress;
- pdu += kStatusReportIndicator;
-
- std::stringstream ss;
- ss << std::setfill('0') << std::setw(2) << std::hex << message_reference;
- pdu += ss.str();
-
- pdu += originator_address_;
- pdu += GetCurrentTimeStamp();
- std::this_thread::sleep_for(std::chrono::seconds(1));
- pdu += GetCurrentTimeStamp();
- pdu += "00"; /* "00" means that SMS have been sent successfully */
-
- return pdu;
-}
-
-std::string PDUParser::CreateRemotePDU(std::string& host_port) {
- if (host_port.size() != 4 || !is_valid_pdu_) {
- return "";
- }
-
- std::string pdu = kWithoutServiceCenterAddress + pdu_type_ + message_reference_;
-
- // Remove the remote port
- std::string number = GetPhoneNumberFromAddress();
- auto new_phone_number = number.substr(0, number.size() - 4);;
- new_phone_number.append(host_port);
- if (new_phone_number.size() & 1) {
- new_phone_number.append("F");
- }
-
- // Add OA length and type
- pdu += originator_address_.substr(0,
- originator_address_.size() - new_phone_number .size());
- pdu += BCDToString(new_phone_number); // Add local host port
- pdu += protocol_id_;
- pdu += data_code_scheme_;
- pdu += user_data_;
-
- return pdu;
-}
-
-std::string PDUParser::GetPhoneNumberFromAddress() {
- if (!is_valid_pdu_) return "";
-
- // Skip OA length and type
- std::string address;
- if (originator_address_.size() == 18) {
- address = originator_address_.substr(6);
- } else {
- address = originator_address_.substr(4);
- }
-
- return BCDToString(address);
-}
-
-int PDUParser::HexCharToInt(char c) {
- if (c >= '0' && c <= '9') return (c - '0');
- if (c >= 'A' && c <= 'F') return (c - 'A' + 10);
- if (c >= 'a' && c <= 'f') return (c - 'a' + 10);
-
- return -1; // Invalid hex char
-}
-
-int PDUParser::Hex2ToByte(const std::string& hex) {
- int hi = HexCharToInt(hex[0]);
- int lo = HexCharToInt(hex[1]);
-
- if (hi < 0 || lo < 0) {
- return -1;
- }
-
- return ( (hi << 4) | lo );
-}
-
-std::string PDUParser::IntToHexString(int value) {
- int hi = value / 10;
- int lo = value % 10;
- return std::to_string(lo) + std::to_string(hi);
-}
-
-std::string PDUParser::IntToHexStringTimeZoneDiff(int tzdiff_hour) {
- // https://en.wikipedia.org/wiki/GSM_03.40
- int delta = 0;
- if (tzdiff_hour < 0) {
- tzdiff_hour = -tzdiff_hour;
- delta = 8;
- }
- const int tzdiff_quarter_hour = 4 * tzdiff_hour;
- const int hi = tzdiff_quarter_hour / 10 + delta;
- const int lo = tzdiff_quarter_hour % 10;
- std::stringstream ss;
- ss << std::hex << lo;
- ss << std::hex << hi;
- return ss.str();
-}
-
-std::string PDUParser::BCDToString(std::string& data) {
- std::string dst;
- if (data.empty()) {
- return "";
- }
- int length = data.size();
- if (length & 0x01) { /* Must be even */
- return "";
- }
- for (int i = 0; i < length; i += 2) {
- dst += data[i + 1];
- dst += data[i];
- }
-
- if (dst[length -1] == 'F') {
- dst.replace(length -1, length, "\0");
- }
- return dst;
-}
-
-std::string PDUParser::GetCurrentTimeStamp() {
- std::string time_stamp;
- auto now = std::time(0);
-
- auto local_time = *std::localtime(&now);
- auto gm_time = *std::gmtime(&now);
-
- auto t_local_time = std::mktime(&local_time);
- auto t_gm_time = std::mktime(&gm_time);
-
- auto tzdiff = (int)std::difftime(t_local_time, t_gm_time) / (60 * 60);
-
- time_stamp += IntToHexString(local_time.tm_year % 100);
- time_stamp += IntToHexString(local_time.tm_mon + 1);
- time_stamp += IntToHexString(local_time.tm_mday);
- time_stamp += IntToHexString(local_time.tm_hour);
- time_stamp += IntToHexString(local_time.tm_min);
- time_stamp += IntToHexString(local_time.tm_sec);
- time_stamp += IntToHexStringTimeZoneDiff(tzdiff);
-
- return time_stamp;
-}
-
-} // namespace cuttlefish
diff --git a/host/commands/modem_simulator/pdu_parser.h b/host/commands/modem_simulator/pdu_parser.h
deleted file mode 100644
index 5618ba728..000000000
--- a/host/commands/modem_simulator/pdu_parser.h
+++ /dev/null
@@ -1,57 +0,0 @@
-//
-// Copyright (C) 2020 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>
-
-namespace cuttlefish {
-
-class PDUParser {
- public:
- explicit PDUParser(std::string &pdu);
- ~PDUParser() = default;
-
- bool IsValidPDU();
- bool IsNeededStatuReport();
- std::string CreatePDU();
- std::string CreateRemotePDU(std::string& host_port);
- std::string CreateStatuReport(int message_reference);
- std::string GetPhoneNumberFromAddress();
-
- static std::string BCDToString(std::string& data);
-
- private:
- bool DecodePDU(std::string& pdu);
- int Hex2ToByte(const std::string& hex);
- int HexCharToInt(char c);
- std::string IntToHexString(int value);
-
- // special handling for time zone differance (to GMT)
- std::string IntToHexStringTimeZoneDiff(int value);
- std::string GetCurrentTimeStamp();
-
- bool is_valid_pdu_;
-
- // Ignore SMSC address, default to be "00" when create PDU
- std::string pdu_type_;
- std::string message_reference_;
- std::string originator_address_;
- std::string protocol_id_;
- std::string data_code_scheme_;
- std::string user_data_;
-};
-
-} // namespace cuttlefish
diff --git a/host/commands/modem_simulator/sim_service.cpp b/host/commands/modem_simulator/sim_service.cpp
deleted file mode 100644
index e6eced5ab..000000000
--- a/host/commands/modem_simulator/sim_service.cpp
+++ /dev/null
@@ -1,1697 +0,0 @@
-//
-// Copyright (C) 2020 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 "host/commands/modem_simulator/sim_service.h"
-
-#include <android-base/logging.h>
-#include <tinyxml2.h>
-
-#include "common/libs/utils/files.h"
-#include "host/commands/modem_simulator/device_config.h"
-#include "host/commands/modem_simulator/network_service.h"
-#include "host/commands/modem_simulator/pdu_parser.h"
-#include "host/commands/modem_simulator/nvram_config.h"
-
-namespace cuttlefish {
-
-const std::pair<int, int> kSimPinSizeRange(4, 8);
-constexpr int kSimPukSize = 8;
-constexpr int kSimPinMaxRetryTimes = 3;
-constexpr int kSimPukMaxRetryTimes = 10;
-static const std::string kDefaultPinCode = "1234";
-static const std::string kDefaultPukCode = "12345678";
-
-static const std::string MF_SIM = "3F00";
-static const std::string DF_TELECOM = "7F10";
-static const std::string DF_PHONEBOOK = "5F3A";
-static const std::string DF_GRAPHICS = "5F50";
-static const std::string DF_GSM = "7F20";
-static const std::string DF_CDMA = "7F25";
-static const std::string DF_ADF = "7FFF"; // UICC access
-
-// In an ADN record, everything but the alpha identifier
-// is in a footer that's 14 bytes
-constexpr int kFooterSizeBytes = 14;
-// Maximum size of the un-extended number field
-constexpr int kMaxNumberSizeBytes = 11;
-
-constexpr int kMaxLogicalChannels = 3;
-
-const std::map<SimService::SimStatus, std::string> gSimStatusResponse = {
- {SimService::SIM_STATUS_ABSENT, ModemService::kCmeErrorSimNotInserted},
- {SimService::SIM_STATUS_NOT_READY, ModemService::kCmeErrorSimBusy},
- {SimService::SIM_STATUS_READY, "+CPIN: READY"},
- {SimService::SIM_STATUS_PIN, "+CPIN: SIM PIN"},
- {SimService::SIM_STATUS_PUK, "+CPIN: SIM PUK"},
-};
-
-/* SimFileSystem */
-XMLElement* SimService::SimFileSystem::GetRootElement() {
- return doc.RootElement();
-}
-
-std::string SimService::SimFileSystem::GetCommonIccEFPath(EFId efid) {
- switch (efid) {
- case EF_ADN:
- case EF_FDN:
- case EF_MSISDN:
- case EF_SDN:
- case EF_EXT1:
- case EF_EXT2:
- case EF_EXT3:
- case EF_PSI:
- return MF_SIM + DF_TELECOM;
-
- case EF_ICCID:
- case EF_PL:
- return MF_SIM;
- case EF_PBR:
- // we only support global phonebook.
- return MF_SIM + DF_TELECOM + DF_PHONEBOOK;
- case EF_IMG:
- return MF_SIM + DF_TELECOM + DF_GRAPHICS;
- default:
- return {};
- }
-}
-
-std::string SimService::SimFileSystem::GetUsimEFPath(EFId efid) {
- switch(efid) {
- case EF_SMS:
- case EF_EXT5:
- case EF_EXT6:
- case EF_MWIS:
- case EF_MBI:
- case EF_SPN:
- case EF_AD:
- case EF_MBDN:
- case EF_PNN:
- case EF_OPL:
- case EF_SPDI:
- case EF_SST:
- case EF_CFIS:
- case EF_MAILBOX_CPHS:
- case EF_VOICE_MAIL_INDICATOR_CPHS:
- case EF_CFF_CPHS:
- case EF_SPN_CPHS:
- case EF_SPN_SHORT_CPHS:
- case EF_FDN:
- case EF_SDN:
- case EF_EXT3:
- case EF_MSISDN:
- case EF_EXT2:
- case EF_INFO_CPHS:
- case EF_CSP_CPHS:
- case EF_GID1:
- case EF_GID2:
- case EF_LI:
- case EF_PLMN_W_ACT:
- case EF_OPLMN_W_ACT:
- case EF_HPLMN_W_ACT:
- case EF_EHPLMN:
- case EF_FPLMN:
- case EF_LRPLMNSI:
- case EF_HPPLMN:
- return MF_SIM + DF_ADF;
-
- case EF_PBR:
- // we only support global phonebook.
- return MF_SIM + DF_TELECOM + DF_PHONEBOOK;
- default:
- std::string path = GetCommonIccEFPath(efid);
- if (path.empty()) {
- // The EFids in USIM phone book entries are decided by the card manufacturer.
- // So if we don't match any of the cases above and if it's a USIM return
- // the phone book path.
- return MF_SIM + DF_TELECOM + DF_PHONEBOOK;
- }
- return path;
- }
-}
-
-XMLElement* SimService::SimFileSystem::FindAttribute(XMLElement *parent,
- const std::string& attr_name,
- const std::string& attr_value) {
- if (parent == nullptr) {
- return nullptr;
- }
-
- XMLElement* child = parent->FirstChildElement();
- while (child) {
- const XMLAttribute *attr = child->FindAttribute(attr_name.c_str());
- if (attr && attr->Value() == attr_value) {
- break;
- }
- child = child->NextSiblingElement();
- }
- return child;
-};
-
-XMLElement* SimService::SimFileSystem::AppendNewElement(XMLElement* parent,
- const char* name) {
- auto element = doc.NewElement(name);
- parent->InsertEndChild(element);
- return element;
-}
-
-XMLElement* SimService::SimFileSystem::AppendNewElementWithText(
- XMLElement* parent, const char* name, const char* text) {
- auto element = doc.NewElement(name);
- auto xml_text = doc.NewText(text);
- element->InsertEndChild(xml_text);
- parent->InsertEndChild(element);
- return element;
-}
-
-/* PinStatus */
-bool SimService::PinStatus::CheckPasswordValid(std::string_view password) {
- for (int i = 0; i < password.size(); i++) {
- int c = (int)password[i];
- if (c >= 48 && c <= 57) {
- continue;
- } else {
- return false;
- }
- }
- return true;
-}
-
-bool SimService::PinStatus::VerifyPIN(const std::string_view pin) {
- if (pin.size() < kSimPinSizeRange.first || pin.size() > kSimPinSizeRange.second) {
- return false;
- }
-
- if (!CheckPasswordValid(pin)) {
- return false;
- }
-
- if (pin_remaining_times_ <= 0) {
- return false;
- }
-
- std::string_view temp(pin_);
- if (pin == temp) { // C++20 remove Operator!=
- pin_remaining_times_ = kSimPinMaxRetryTimes;
- return true;
- }
-
- pin_remaining_times_ -= 1;
- return false;
-}
-
-bool SimService::PinStatus::VerifyPUK(const std::string_view puk) {
- if (puk.size() != kSimPukSize) {
- return false;
- }
-
- if (!CheckPasswordValid(puk)) {
- return false;
- }
-
- if (puk_remaining_times_ <= 0) {
- return false;
- }
-
- std::string_view temp(puk_);
- if (puk == temp) { // C++20 remove Operator!=
- pin_remaining_times_ = kSimPinMaxRetryTimes;
- puk_remaining_times_ = kSimPukMaxRetryTimes;
- return true;
- }
-
- puk_remaining_times_ -= 1;
- return false;
-}
-
-bool SimService::PinStatus::ChangePIN(ChangeMode mode,
- const std::string_view pin_or_puk,
- const std::string_view new_pin) {
- auto length = new_pin.length();
- if (length < kSimPinSizeRange.first || length > kSimPinSizeRange.second) {
- LOG(ERROR) << "Invalid digit number for PIN";
- return false;
- }
-
- bool result = false;
- if (mode == WITH_PIN) { // using old pin to change pin
- result = VerifyPIN(pin_or_puk);
- } else if (mode == WITH_PUK) { // using puk to change pin
- result = VerifyPUK(pin_or_puk);
- }
-
- if (!result) {
- LOG(ERROR) << "Incorrect PIN or PUK";
- return false;
- }
-
- if (!CheckPasswordValid(new_pin)) {
- return false;
- }
-
- std::string temp(new_pin);
- pin_ = temp;
- return true;
-}
-
-bool SimService::PinStatus::ChangePUK(const std::string_view puk,
- const std::string_view new_puk) {
- bool result = VerifyPUK(puk);
- if (!result) {
- LOG(ERROR) << "Incorrect PUK or no retry times";
- return false;
- }
-
- if (new_puk.length() != kSimPukSize) {
- LOG(ERROR) << "Invalid digit number for PUK";
- return false;
- }
-
- std::string temp(new_puk);
- puk_ = temp;
- return true;
-};
-
-SimService::SimService(int32_t service_id, ChannelMonitor* channel_monitor,
- ThreadLooper* thread_looper)
- : ModemService(service_id, this->InitializeCommandHandlers(),
- channel_monitor, thread_looper) {
- InitializeServiceState();
-}
-
-std::vector<CommandHandler> SimService::InitializeCommandHandlers() {
- std::vector<CommandHandler> command_handlers = {
- CommandHandler(
- "+CPIN?",
- [this](const Client& client) { this->HandleSIMStatusReq(client); }),
- CommandHandler("+CPIN=",
- [this](const Client& client, std::string& cmd) {
- this->HandleChangeOrEnterPIN(client, cmd);
- }),
- CommandHandler("+CRSM=",
- [this](const Client& client, std::string& cmd) {
- this->HandleSIM_IO(client, cmd);
- }),
- CommandHandler("+CSIM=",
- [this](const Client& client, std::string& cmd) {
- this->HandleCSIM_IO(client, cmd);
- }),
- CommandHandler(
- "+CIMI",
- [this](const Client& client) { this->HandleGetIMSI(client); }),
- CommandHandler(
- "+CICCID",
- [this](const Client& client) { this->HandleGetIccId(client); }),
- CommandHandler("+CLCK=",
- [this](const Client& client, std::string& cmd) {
- this->HandleFacilityLock(client, cmd);
- }),
- CommandHandler("+CCHO=",
- [this](const Client& client, std::string& cmd) {
- this->HandleOpenLogicalChannel(client, cmd);
- }),
- CommandHandler("+CCHC=",
- [this](const Client& client, std::string& cmd) {
- this->HandleCloseLogicalChannel(client, cmd);
- }),
- CommandHandler("+CGLA=",
- [this](const Client& client, std::string& cmd) {
- this->HandleTransmitLogicalChannel(client, cmd);
- }),
- CommandHandler("+CPWD=",
- [this](const Client& client, std::string& cmd) {
- this->HandleChangePassword(client, cmd);
- }),
- CommandHandler("+CPINR=",
- [this](const Client& client, std::string& cmd) {
- this->HandleQueryRemainTimes(client, cmd);
- }),
- CommandHandler("+CCSS",
- [this](const Client& client, std::string& cmd) {
- this->HandleCdmaSubscriptionSource(client, cmd);
- }),
- CommandHandler("+WRMP",
- [this](const Client& client, std::string& cmd) {
- this->HandleCdmaRoamingPreference(client, cmd);
- }),
- CommandHandler("^MBAU=",
- [this](const Client& client, std::string& cmd) {
- this->HandleSimAuthentication(client, cmd);
- }),
- };
- return (command_handlers);
-}
-
-void SimService::InitializeServiceState() {
- InitializeSimFileSystemAndSimState();
-
- InitializeFacilityLock();
-
- // Max logical channels: 3
- logical_channels_ = {
- LogicalChannel(1), LogicalChannel(2), LogicalChannel(kMaxLogicalChannels),
- };
-}
-
-void SimService::InitializeSimFileSystemAndSimState() {
- auto nvram_config = NvramConfig::Get();
- auto sim_type = nvram_config->sim_type();
- std::stringstream ss;
- if (sim_type == 2) { // Special sim card for CtsCarrierApiTestCases
- ss << "iccprofile_for_sim" << service_id_ << "_for_CtsCarrierApiTestCases.xml";
- } else {
- ss << "iccprofile_for_sim" << service_id_ << ".xml";
- }
- auto icc_profile_name = ss.str();
-
- auto icc_profile_path = cuttlefish::modem::DeviceConfig::PerInstancePath(
- icc_profile_name.c_str());
- std::string file = icc_profile_path;
-
- if (!cuttlefish::FileExists(icc_profile_path) ||
- !cuttlefish::FileHasContent(icc_profile_path.c_str())) {
- ss.clear();
- ss.str("");
-
- if (sim_type == 2) { // Special sim card for CtsCarrierApiTestCases
- ss << "etc/modem_simulator/files/iccprofile_for_sim" << service_id_
- << "_for_CtsCarrierApiTestCases.xml";
- } else {
- ss << "etc/modem_simulator/files/iccprofile_for_sim" << service_id_ << ".xml";
- }
-
- auto etc_file_path =
- cuttlefish::modem::DeviceConfig::DefaultHostArtifactsPath(ss.str());
- if (!cuttlefish::FileExists(etc_file_path) || !cuttlefish::FileHasContent(etc_file_path)) {
- sim_status_ = SIM_STATUS_ABSENT;
- return;
- }
- file = etc_file_path;
- }
-
- sim_file_system_.file_path = icc_profile_path;
- auto err = sim_file_system_.doc.LoadFile(file.c_str());
- if (err != tinyxml2::XML_SUCCESS) {
- LOG(ERROR) << "Unable to load XML file '" << file << " ', error " << err;
- sim_status_ = SIM_STATUS_ABSENT;
- return;
- }
-
- XMLElement *root = sim_file_system_.GetRootElement();
- if (!root) {
- LOG(ERROR) << "Unable to find root element: IccProfile";
- sim_status_ = SIM_STATUS_ABSENT;
- return;
- }
-
- // Default value if iccprofile not configure pin state
- sim_status_ = SIM_STATUS_READY;
- pin1_status_.pin_ = kDefaultPinCode;
- pin1_status_.puk_ = kDefaultPukCode;
- pin1_status_.pin_remaining_times_ = kSimPinMaxRetryTimes;
- pin1_status_.puk_remaining_times_ = kSimPukMaxRetryTimes;
- pin2_status_.pin_ = kDefaultPinCode;
- pin2_status_.puk_ = kDefaultPukCode;
- pin2_status_.pin_remaining_times_ = kSimPinMaxRetryTimes;
- pin2_status_.puk_remaining_times_ = kSimPukMaxRetryTimes;
-
- XMLElement *pin_profile = root->FirstChildElement("PinProfile");
- if (pin_profile) {
- // Pin1 status
- auto pin_state = pin_profile->FirstChildElement("PINSTATE");
- if (pin_state) {
- std::string state = pin_state->GetText();
- if (state == "PINSTATE_ENABLED_NOT_VERIFIED") {
- sim_status_ = SIM_STATUS_PIN;
- } else if (state == "PINSTATE_ENABLED_BLOCKED") {
- sim_status_ = SIM_STATUS_PUK;
- }
- }
- auto pin_code = pin_profile->FirstChildElement("PINCODE");
- if (pin_code) pin1_status_.pin_ = pin_code->GetText();
-
- auto puk_code = pin_profile->FirstChildElement("PUKCODE");
- if (puk_code) pin1_status_.puk_ = puk_code->GetText();
-
- auto pin_remaining_times = pin_profile->FirstChildElement("PINREMAINTIMES");
- if (pin_remaining_times) {
- pin1_status_.pin_remaining_times_ = std::stoi(pin_remaining_times->GetText());
- }
-
- auto puk_remaining_times = pin_profile->FirstChildElement("PUKREMAINTIMES");
- if (puk_remaining_times) {
- pin1_status_.puk_remaining_times_ = std::stoi(puk_remaining_times->GetText());
- }
-
- // Pin2 status
- auto pin2_code = pin_profile->FirstChildElement("PIN2CODE");
- if (pin2_code) pin2_status_.pin_ = pin2_code->GetText();
-
- auto puk2_code = pin_profile->FirstChildElement("PUK2CODE");
- if (puk2_code) pin2_status_.puk_ = puk2_code->GetText();
-
- auto pin2_remaining_times = pin_profile->FirstChildElement("PIN2REMAINTIMES");
- if (pin2_remaining_times) {
- pin2_status_.pin_remaining_times_ = std::stoi(pin2_remaining_times->GetText());
- }
-
- auto puk2_remaining_times = pin_profile->FirstChildElement("PUK2REMAINTIMES");
- if (puk2_remaining_times) {
- pin2_status_.puk_remaining_times_ = std::stoi(puk2_remaining_times->GetText());
- }
- }
-}
-
-void SimService::InitializeFacilityLock() {
- /* Default disable */
- facility_lock_ = {
- {"SC", FacilityLock(FacilityLock::LockStatus::DISABLE)},
- {"FD", FacilityLock(FacilityLock::LockStatus::DISABLE)},
- {"AO", FacilityLock(FacilityLock::LockStatus::DISABLE)},
- {"OI", FacilityLock(FacilityLock::LockStatus::DISABLE)},
- {"OX", FacilityLock(FacilityLock::LockStatus::DISABLE)},
- {"AI", FacilityLock(FacilityLock::LockStatus::DISABLE)},
- {"IR", FacilityLock(FacilityLock::LockStatus::DISABLE)},
- {"AB", FacilityLock(FacilityLock::LockStatus::DISABLE)},
- {"AG", FacilityLock(FacilityLock::LockStatus::DISABLE)},
- {"AC", FacilityLock(FacilityLock::LockStatus::DISABLE)},
- };
-
- XMLElement *root = sim_file_system_.GetRootElement();
- if (!root) {
- LOG(ERROR) << "Unable to find root element: IccProfile";
- sim_status_ = SIM_STATUS_ABSENT;
- return;
- }
-
- XMLElement *facility_lock = root->FirstChildElement("FacilityLock");
- if (!facility_lock) {
- LOG(ERROR) << "Unable to find element: FacilityLock";
- return;
- }
-
- for (auto iter = facility_lock_.begin(); iter != facility_lock_.end(); ++iter) {
- auto lock_status = facility_lock->FirstChildElement(iter->first.c_str());
- if (lock_status) {
- std::string state = lock_status->GetText();
- if (state == "ENABLE") {
- iter->second.lock_status = FacilityLock::LockStatus::ENABLE;
- }
- }
- }
-}
-
-void SimService::SavePinStateToIccProfile() {
- XMLElement *root = sim_file_system_.GetRootElement();
- if (!root) {
- LOG(ERROR) << "Unable to find root element: IccProfile";
- sim_status_ = SIM_STATUS_ABSENT;
- return;
- }
-
- XMLElement *pin_profile = root->FirstChildElement("PinProfile");
- if (!pin_profile) {
- pin_profile = sim_file_system_.AppendNewElement(root, "PinProfile");
- }
-
- const char* text = "PINSTATE_UNKNOWN";
-
- if (sim_status_ == SIM_STATUS_PUK) {
- text = "PINSTATE_ENABLED_BLOCKED";
- } else {
- auto iter = facility_lock_.find("SC");
- if (iter != facility_lock_.end()) {
- if (iter->second.lock_status == FacilityLock::ENABLE) {
- text = "PINSTATE_ENABLED_NOT_VERIFIED";
- }
- }
- }
-
- // Pin1 status
- auto pin_state = pin_profile->FirstChildElement("PINSTATE");
- if (!pin_state) {
- pin_state = sim_file_system_.AppendNewElementWithText(pin_profile, "PINSTATE", text);
- } else {
- pin_state->SetText(text);
- }
-
- auto pin_code = pin_profile->FirstChildElement("PINCODE");
- if (!pin_code) {
- pin_code = sim_file_system_.AppendNewElementWithText(pin_profile, "PINCODE",
- pin1_status_.pin_.c_str());
- } else {
- pin_code->SetText(pin1_status_.pin_.c_str());
- }
-
- auto puk_code = pin_profile->FirstChildElement("PUKCODE");
- if (!puk_code) {
- puk_code = sim_file_system_.AppendNewElementWithText(pin_profile, "PUKCODE",
- pin1_status_.puk_.c_str());
- } else {
- puk_code->SetText(pin1_status_.puk_.c_str());
- }
-
- std::stringstream ss;
- ss << pin1_status_.pin_remaining_times_;
-
- auto pin_remaining_times = pin_profile->FirstChildElement("PINREMAINTIMES");
- if (!pin_remaining_times) {
- pin_remaining_times = sim_file_system_.AppendNewElementWithText(pin_profile,
- "PINREMAINTIMES", ss.str().c_str());
- } else {
- pin_remaining_times->SetText(ss.str().c_str());
- }
- ss.clear();
- ss.str("");
- ss << pin1_status_.puk_remaining_times_;
-
- auto puk_remaining_times = pin_profile->FirstChildElement("PUKREMAINTIMES");
- if (!puk_remaining_times) {
- puk_remaining_times = sim_file_system_.AppendNewElementWithText(pin_profile,
- "PUKREMAINTIMES", ss.str().c_str());
- } else {
- puk_remaining_times->SetText(ss.str().c_str());
- }
-
- // Pin2 status
- auto pin2_code = pin_profile->FirstChildElement("PIN2CODE");
- if (!pin2_code) {
- pin2_code = sim_file_system_.AppendNewElementWithText(pin_profile, "PIN2CODE",
- pin2_status_.pin_.c_str());
- } else {
- pin2_code->SetText(pin2_status_.pin_.c_str());
- }
-
- auto puk2_code = pin_profile->FirstChildElement("PUK2CODE");
- if (!puk2_code) {
- puk2_code = sim_file_system_.AppendNewElementWithText(pin_profile, "PUK2CODE",
- pin2_status_.puk_.c_str());
- } else {
- puk2_code->SetText(pin2_status_.puk_.c_str());
- }
-
- ss.clear();
- ss.str("");
- ss << pin2_status_.pin_remaining_times_;
-
- auto pin2_remaining_times = pin_profile->FirstChildElement("PIN2REMAINTIMES");
- if (!pin2_remaining_times) {
- pin2_remaining_times = sim_file_system_.AppendNewElementWithText(pin_profile,
- "PINREMAINTIMES", ss.str().c_str());
- } else {
- pin2_remaining_times->SetText(ss.str().c_str());
- }
- ss.clear();
- ss.str("");
- ss << pin2_status_.puk_remaining_times_;
-
- auto puk2_remaining_times = pin_profile->FirstChildElement("PUK2REMAINTIMES");
- if (!puk2_remaining_times) {
- puk2_remaining_times = sim_file_system_.AppendNewElementWithText(pin_profile,
- "PUK2REMAINTIMES", ss.str().c_str());
- } else {
- puk2_remaining_times->SetText(ss.str().c_str());
- }
-
- // Save file
- sim_file_system_.doc.SaveFile(sim_file_system_.file_path.c_str());
-}
-
-void SimService::SaveFacilityLockToIccProfile() {
- XMLElement *root = sim_file_system_.GetRootElement();
- if (!root) {
- LOG(ERROR) << "Unable to find root element: IccProfile";
- sim_status_ = SIM_STATUS_ABSENT;
- return;
- }
-
- XMLElement *facility_lock = root->FirstChildElement("FacilityLock");
- if (!facility_lock) {
- facility_lock = sim_file_system_.AppendNewElement(root, "FacilityLock");
- }
-
- const char* text = "DISABLE";
-
- for (auto iter = facility_lock_.begin(); iter != facility_lock_.end(); ++iter) {
- if (iter->second.lock_status == FacilityLock::LockStatus::ENABLE) {
- text = "ENABLE";
- } else {
- text = "DISABLE";
- }
- auto element = facility_lock->FirstChildElement(iter->first.c_str());
- if (!element) {
- element = sim_file_system_.AppendNewElementWithText(facility_lock,
- iter->first.c_str(), text);
- } else {
- element->SetText(text);
- }
- }
-
- sim_file_system_.doc.SaveFile(sim_file_system_.file_path.c_str());
-
- InitializeSimFileSystemAndSimState();
- InitializeFacilityLock();
-}
-
-bool SimService::IsFDNEnabled() {
- auto iter = facility_lock_.find("FD");
- if (iter != facility_lock_.end() &&
- iter->second.lock_status == FacilityLock::LockStatus::ENABLE) {
- return true;
- }
- return false;
-}
-
-bool SimService::IsFixedDialNumber(std::string_view number) {
- XMLElement *root = sim_file_system_.GetRootElement();
- if (!root) return false;
-
- auto path = SimFileSystem::GetUsimEFPath(SimFileSystem::EFId::EF_FDN);
-
- size_t pos = 0;
- auto parent = root;
- while (pos < path.length()) {
- std::string sub_path(path.substr(pos, 4));
- auto app = SimFileSystem::FindAttribute(parent, "path", sub_path);
- if (!app) return false;
- pos += 4;
- parent = app;
- }
-
- XMLElement* ef = SimFileSystem::FindAttribute(parent, "id", "6F3B");
- if (!ef) return false;
-
- XMLElement *final = ef->FirstChildElement("SIMIO");
- while (final) {
- std::string record = final->GetText();
- int footerOffset = record.length() - kFooterSizeBytes * 2;
- int numberLength = (record[footerOffset] - '0') * 16 +
- record[footerOffset + 1] - '0';
- if (numberLength > kMaxNumberSizeBytes) { // Invalid number length
- final = final->NextSiblingElement("SIMIO");
- continue;
- }
-
- std::string bcd_fdn = "";
- if (numberLength * 2 == 16) { // Skip Type(91) and Country Code(68)
- bcd_fdn = record.substr(footerOffset + 6, numberLength * 2 - 4);
- } else { // Skip Type(81)
- bcd_fdn = record.substr(footerOffset + 4, numberLength * 2 - 2);
- }
-
- std::string fdn = PDUParser::BCDToString(bcd_fdn);
- if (fdn == number) {
- return true;
- }
- final = final->NextSiblingElement("SIMIO");
- }
-
- return false;
-}
-
-XMLElement* SimService::GetIccProfile() {
- return sim_file_system_.GetRootElement();
-}
-
-std::string SimService::GetPhoneNumber() {
- XMLElement *root = sim_file_system_.GetRootElement();
- if (!root) return "";
-
- auto path = SimFileSystem::GetUsimEFPath(SimFileSystem::EFId::EF_MSISDN);
-
- size_t pos = 0;
- auto parent = root;
- while (pos < path.length()) {
- std::string sub_path(path.substr(pos, 4));
- auto app = SimFileSystem::FindAttribute(parent, "path", sub_path);
- if (!app) return "";
- pos += 4;
- parent = app;
- }
-
- XMLElement* ef = SimFileSystem::FindAttribute(parent, "id", "6F40");
- if (!ef) return "";
-
- XMLElement *final = SimFileSystem::FindAttribute(ef, "cmd", "B2");;
- if (!final) return "";
-
- std::string record = final->GetText();
- int footerOffset = record.length() - kFooterSizeBytes * 2;
- int numberLength = (record[footerOffset] - '0') * 16 +
- record[footerOffset + 1] - '0';
- if (numberLength > kMaxNumberSizeBytes) { // Invalid number length
- return "";
- }
-
- std::string bcd_number = "";
- if (numberLength * 2 == 16) { // Skip Type(91) and Country Code(68)
- bcd_number = record.substr(footerOffset + 6, numberLength * 2 - 4);
- } else { // Skip Type(81)
- bcd_number = record.substr(footerOffset + 4, numberLength * 2 - 2);
- }
-
- return PDUParser::BCDToString(bcd_number);
-}
-
-SimService::SimStatus SimService::GetSimStatus() const {
- return sim_status_;
-}
-
-std::string SimService::GetSimOperator() {
- XMLElement *root = sim_file_system_.GetRootElement();
- if (!root) return "";
-
- XMLElement* mf = SimFileSystem::FindAttribute(root, "path", MF_SIM);
- if (!mf) return "";
-
- XMLElement* df = SimFileSystem::FindAttribute(mf, "path", DF_ADF);
- if (!df) return "";
-
- XMLElement* ef = SimFileSystem::FindAttribute(df, "id", "6F07");
- if (!ef) return "";
-
- XMLElement *cimi = ef->FirstChildElement("CIMI");
- if (!cimi) return "";
- std::string imsi = cimi->GetText();
-
- ef = SimFileSystem::FindAttribute(df, "id", "6FAD");
- if (!ef) return "";
-
- XMLElement *sim_io = ef->FirstChildElement("SIMIO");
- while (sim_io) {
- const XMLAttribute *attr_cmd = sim_io->FindAttribute("cmd");
- std::string attr_value = attr_cmd ? attr_cmd->Value() : "";
- if (attr_cmd && attr_value == "B0") {
- break;
- }
-
- sim_io = sim_io->NextSiblingElement("SIMIO");
- }
-
- if (!sim_io) return "";
-
- std::string length = sim_io->GetText();
- int mnc_size = std::stoi(length.substr(length.size() -2));
-
- return imsi.substr(0, 3 + mnc_size);
-}
-
-void SimService::SetupDependency(NetworkService* net) {
- network_service_ = net;
-}
-
-/**
- * AT+CPIN
- * Set command sends to the MT a password which is necessary before it can be
- * operated.
- * Read command returns an alphanumeric string indicating whether some
- * password is required or not.
- *
- * Command Possible response(s)
- * +CPIN=<pin>[,<newpin>] +CME ERROR: <err>
- * +CPIN? +CPIN: <code>
- * +CME ERROR: <err>
- * <pin>, <newpin>: string type values.
- * <code> values reserved by the present document:
- * READY MT is not pending for any password
- * SIM PIN MT is waiting SIM PIN to be given
- * SIM PUK MT is waiting SIM PUK to be given
- *
- * see RIL_REQUEST_GET_SIM_STATUS in RIL
- */
-void SimService::HandleSIMStatusReq(const Client& client) {
- std::vector<std::string> responses;
- auto iter = gSimStatusResponse.find(sim_status_);
- if (iter != gSimStatusResponse.end()) {
- responses.push_back(iter->second);
- responses.push_back("OK");
- } else {
- sim_status_ = SIM_STATUS_ABSENT;
- responses.push_back(kCmeErrorSimNotInserted);
- }
- client.SendCommandResponse(responses);
-}
-
-/**
- * AT+CRSM
- * By using this command instead of Generic SIM Access +CSIM TE application
- * has easier but more limited access to the SIM database.
- *
- * Command Possible response(s)
- * +CRSM=<command>[,<fileid> +CRSM: <sw1>,<sw2>[,<response>]
- * [,<P1>,<P2>,<P3>[,<data>[,<pathid>]]]] +CME ERROR: <err>
- *
- * <command>: (command passed on by the MT to the SIM; refer 3GPP TS 51.011 [28]):
- * 176 READ BINARY
- * 178 READ RECORD
- * 192 GET RESPONSE
- * 214 UPDATE BINARY
- * 220 UPDATE RECORD
- * 242 STATUS
- * 203 RETRIEVE DATA
- * 219 SET DATA
- *
- * <fileid>: integer type; this is the identifier of a elementary datafile on SIM.
- * Mandatory for every command except STATUS.
- *
- * <P1>, <P2>, <P3>: integer type; parameters passed on by the MT to the SIM.
- * These parameters are mandatory for every command,
- * except GET RESPONSE and STATUS.
- *
- * <data>: information which shall be written to the SIM (hexadecimal character format).
- *
- * <pathid>: string type; contains the path of an elementary file on the SIM/UICC
- * in hexadecimal format.
- *
- * <sw1>, <sw2>: integer type; information from the SIM about the execution of
- * the actual command.
- *
- * <response>: response of a successful completion of the command previously issued
- * (hexadecimal character format; refer +CSCS).
- */
-void SimService::HandleSIM_IO(const Client& client,
- const std::string& command) {
- std::vector<std::string> kFileNotFoud = {"+CRSM: 106,130", "OK"};
- std::vector<std::string> responses;
-
- CommandParser cmd(command);
- cmd.SkipPrefix(); // skip "AT+CRSM="
-
- if (*cmd == "242,0,0,0,0") { // for cts teset
- responses.push_back("+CRSM: 144,0,62338202782183023F00A50C80016187010183040007DBF08A01058B062F0601020002C60C90016083010183010A83010D8102FFFF");
- responses.push_back("OK");
- client.SendCommandResponse(responses);
- return;
- }
-
- auto c = cmd.GetNextStrDeciToHex();
- auto id = cmd.GetNextStrDeciToHex();
- auto p1 = cmd.GetNextStrDeciToHex();
- auto p2 = cmd.GetNextStrDeciToHex();
- auto p3 = cmd.GetNextStrDeciToHex();
-
- auto data = cmd.GetNextStr(',');
- std::string path(cmd.GetNextStr());
-
- XMLElement *root = sim_file_system_.GetRootElement();
- if (!root) {
- LOG(ERROR) << "Unable to find root element: IccProfile";
- client.SendCommandResponse(kCmeErrorOperationNotAllowed);
- return;
- }
-
- SimFileSystem::EFId fileid = (SimFileSystem::EFId)std::stoi(id, nullptr, 16);
- if (path == "") {
- path = SimFileSystem::GetUsimEFPath(fileid);
- }
- // EF_ADN under DF_PHONEBOOK is mapped to EF_ADN under DF_TELECOM per
- // 3GPP TS 31.102 4.4.2
- if (fileid == SimFileSystem::EF_ADN &&
- path == SimFileSystem::GetUsimEFPath(fileid)) {
- id = "4F3A";
- path = MF_SIM + DF_TELECOM + DF_PHONEBOOK;
- }
-
- size_t pos = 0;
- auto parent = root;
- while (pos < path.length()) {
- std::string sub_path(path.substr(pos, 4));
- auto app = SimFileSystem::FindAttribute(parent, "path", sub_path);
- if (!app) {
- client.SendCommandResponse(kFileNotFoud);
- return;
- }
- pos += 4;
- parent = app;
- }
-
- XMLElement* ef = SimFileSystem::FindAttribute(parent, "id", id);
- if (!ef) {
- client.SendCommandResponse(kFileNotFoud);
- return;
- }
-
- XMLElement *final = ef->FirstChildElement("SIMIO");
- while (final) {
- const XMLAttribute *attr_cmd = final->FindAttribute("cmd");
- const XMLAttribute *attr_p1 = final->FindAttribute("p1");
- const XMLAttribute *attr_p2 = final->FindAttribute("p2");
- const XMLAttribute *attr_p3 = final->FindAttribute("p3");
- const XMLAttribute *attr_data = final->FindAttribute("data");
-
- if (c != "DC" && c != "D6") { // Except UPDATE RECORD or UPDATE BINARY
- if ((attr_cmd && attr_cmd->Value() != c) ||
- (attr_data && attr_data->Value() != data)) {
- final = final->NextSiblingElement("SIMIO");
- continue;
- }
- }
- if (attr_p1 && attr_p1->Value() == p1 &&
- attr_p2 && attr_p2->Value() == p2 &&
- attr_p3 && attr_p3->Value() == p3) {
- break;
- }
- final = final->NextSiblingElement("SIMIO");
- }
-
- if (!final) {
- client.SendCommandResponse(kFileNotFoud);
- return;
- }
-
- std::string response = "+CRSM: ";
- if (c == "DC" || c == "D6") {
- std::string temp = "144,0,";
- temp += data;
- final->SetText(temp.c_str());
- sim_file_system_.doc.SaveFile(sim_file_system_.file_path.c_str());
- response.append("144,0");
- } else {
- response.append(final->GetText());
- }
-
- responses.push_back(response);
- responses.push_back("OK");
- client.SendCommandResponse(responses);
-}
-
-void SimService::OnSimStatusChanged() {
- auto ptr = network_service_;
- if (ptr) {
- ptr->OnSimStatusChanged(sim_status_);
- }
-}
-
-bool SimService::checkPin1AndAdjustSimStatus(std::string_view pin) {
- if (pin1_status_.VerifyPIN(pin) == true) {
- sim_status_ = SIM_STATUS_READY;
- OnSimStatusChanged();
- return true;
- }
-
- if (pin1_status_.pin_remaining_times_ <= 0) {
- sim_status_ = SIM_STATUS_PUK;
- OnSimStatusChanged();
- }
-
- return false;
-}
-
-/* AT+CSIM */
-void SimService::HandleCSIM_IO(const Client& client,
- const std::string& command) {
- std::vector<std::string> responses;
-
- CommandParser cmd(command);
- cmd.SkipPrefix(); // skip "AT+CSIM="
-
- cmd.SkipComma();
- auto data = cmd.GetNextStr();
-
- XMLElement *root = sim_file_system_.GetRootElement();
- if (!root) {
- LOG(ERROR) << "Unable to find root element: IccProfile";
- client.SendCommandResponse(kCmeErrorOperationNotAllowed);
- return;
- }
- // Get aid
- XMLElement* df = SimFileSystem::FindAttribute(root, "aid", "CSIM");
- if (!df) {
- client.SendCommandResponse(kCmeErrorNotFound);
- return;
- }
-
- std::string data_value(data);
- if (data_value.length() > 10) { // for open channel with csim
- responses.push_back("+CSIM: 4,9000");
- responses.push_back("OK");
- client.SendCommandResponse(responses);
- return;
- }
- XMLElement* final = SimFileSystem::FindAttribute(df, "cmd", data_value);
- if (!final) {
- client.SendCommandResponse(kCmeErrorNotFound);
- return;
- }
-
- auto id = data_value.substr(data_value.length() - 2, 2);
-
- std::vector<LogicalChannel>::iterator iter = logical_channels_.begin();
- for (; iter != logical_channels_.end(); ++iter) {
- if (!iter->is_open) break;
- }
-
- if (iter != logical_channels_.end() && iter->session_id ==stoi(id)) {
- iter->is_open = true;
- iter->df_name = "CSIM";
- }
-
- std::stringstream ss;
- ss << "+CSIM: " << final->GetText();
-
- responses.push_back(ss.str());
- responses.push_back("OK");
- client.SendCommandResponse(responses);
-}
-
-bool SimService::ChangePin1AndAdjustSimStatus(PinStatus::ChangeMode mode,
- std::string_view pin,
- std::string_view new_pin) {
- if (pin1_status_.ChangePIN(mode, pin, new_pin) == true) {
- sim_status_ = SIM_STATUS_READY;
- OnSimStatusChanged();
- return true;
- }
- if (sim_status_ == SIM_STATUS_READY && pin1_status_.pin_remaining_times_ <= 0) {
- sim_status_ = SIM_STATUS_PIN;
- OnSimStatusChanged();
- } else if (sim_status_ == SIM_STATUS_PIN && pin1_status_.puk_remaining_times_ <= 0) {
- sim_status_ = SIM_STATUS_ABSENT;
- OnSimStatusChanged();
- }
- return false;
-}
-
-void SimService::HandleChangeOrEnterPIN(const Client& client,
- const std::string& command) {
- std::vector<std::string> responses;
-
- CommandParser cmd(command);
- cmd.SkipPrefix(); // skip "AT+CPIN="
- switch (sim_status_) {
- case SIM_STATUS_ABSENT:
- responses.push_back(kCmeErrorSimNotInserted);
- break;
- case SIM_STATUS_NOT_READY:
- responses.push_back(kCmeErrorSimBusy);
- break;
- case SIM_STATUS_READY: {
- /*
- * this may be a request to change the PIN with pin and new pin:
- * AT+CPIN=pin,newpin
- * or a request to enter the PIN2
- * AT+CPIN=pin2
- */
- auto pos = cmd->find(',');
- if (pos != std::string_view::npos) { // change pin with new pin
- auto pin = cmd.GetNextStr(',');
- auto new_pin = *cmd;
-
- if (ChangePin1AndAdjustSimStatus(PinStatus::WITH_PIN, pin, new_pin)) {
- responses.push_back("OK");
- } else {
- responses.push_back(kCmeErrorIncorrectPassword); /* incorrect PIN */
- }
- } else { // verify pin2
- if (pin2_status_.VerifyPIN(*cmd) == true) {
- responses.push_back("OK");
- } else {
- responses.push_back(kCmeErrorIncorrectPassword); /* incorrect PIN2 */
- }
- }
- break;
- }
- case SIM_STATUS_PIN: { /* waiting for PIN */
- if (checkPin1AndAdjustSimStatus(*cmd) == true) {
- responses.push_back("OK");
- } else {
- responses.push_back(kCmeErrorIncorrectPassword);
- }
- break;
- }
- case SIM_STATUS_PUK: {
- /*
- * this may be a request to unlock the puk with new pin:
- * AT+CPIN=puk,newpin
- */
- auto pos = cmd->find(',');
- if (pos != std::string_view::npos) {
- auto puk = cmd.GetNextStr(',');
- auto new_pin = *cmd;
- if (ChangePin1AndAdjustSimStatus(PinStatus::WITH_PUK, puk, new_pin)) {
- responses.push_back("OK");
- } else {
- responses.push_back(kCmeErrorIncorrectPassword);
- }
- } else {
- responses.push_back(kCmeErrorOperationNotAllowed);
- }
- break;
- }
- default:
- responses.push_back(kCmeErrorOperationNotAllowed);
- break;
- }
-
- client.SendCommandResponse(responses);
-}
-
-/**
- * AT+CIMI
- * Execution command causes the TA to return <IMSI>, which is intended to
- * permit the TE to identify the individual SIM card or active application in
- * the UICC (GSM or USIM) which is attached to MT.
- *
- * Command Possible response(s)
- * +CIMI <IMSI>
- * +CME ERROR: <err>
- *
- * <IMSI>: International Mobile Subscriber Identity (string without double quotes)
- *
- * see RIL_REQUEST_GET_IMSI in RIL
- */
-void SimService::HandleGetIMSI(const Client& client) {
- std::vector<std::string> responses;
-
- XMLElement *root = sim_file_system_.GetRootElement();
- if (!root) {
- client.SendCommandResponse(kCmeErrorOperationNotAllowed);
- return;
- }
-
- XMLElement* mf = SimFileSystem::FindAttribute(root, "path", MF_SIM);
- if (!mf) {
- client.SendCommandResponse(kCmeErrorNotFound);
- return;
- }
-
- XMLElement* df = SimFileSystem::FindAttribute(mf, "path", DF_ADF);
- if (!df) {
- client.SendCommandResponse(kCmeErrorNotFound);
- return;
- }
-
- XMLElement* ef = SimFileSystem::FindAttribute(df, "id", "6F07");
- if (!ef) {
- client.SendCommandResponse(kCmeErrorNotFound);
- return;
- }
-
- XMLElement *final = ef->FirstChildElement("CIMI");
- if (!final) {
- client.SendCommandResponse(kCmeErrorNotFound);
- return;
- }
-
- responses.push_back(final->GetText());
- responses.push_back("OK");
- client.SendCommandResponse(responses);
-}
-
-/**
- * AT+CICCID
- * Integrated Circuit Card IDentifier (ICCID) is Unique Identifier of the SIM CARD.
- * File is located in the SIM card at EFiccid (0x2FE2).
- *
- * see RIL_REQUEST_GET_SIM_STATUS in RIL
- */
-void SimService::HandleGetIccId(const Client& client) {
- std::vector<std::string> responses;
-
- XMLElement *root = sim_file_system_.GetRootElement();
- if (!root) {
- client.SendCommandResponse(kCmeErrorOperationNotAllowed);
- return;
- }
-
- XMLElement* mf = SimFileSystem::FindAttribute(root, "path", MF_SIM);
- if (!mf) {
- client.SendCommandResponse(kCmeErrorNotFound);
- return;
- }
-
- XMLElement* ef = SimFileSystem::FindAttribute(mf, "id", "2FE2");
- if (!ef) {
- client.SendCommandResponse(kCmeErrorNotFound);
- return;
- }
-
- XMLElement *final = ef->FirstChildElement("CCID");
- if (!final) {
- client.SendCommandResponse(kCmeErrorNotFound);
- return;
- }
-
- responses.push_back(final->GetText());
- responses.push_back("OK");
- client.SendCommandResponse(responses);
-}
-
-/*
- * AT+CLCK
- * Execute command is used to lock, unlock or interrogate a MT or a network
- * facility <fac>.
- *
- * Command Possible response(s)
- * +CLCK=<fac>, <mode> [, <password> OK or +CME ERROR: <err>
- * [, <class>]] +CLCK: <status>[,<class1>[<CR><LF>+CLCK:
- * <status>,<class2>[...]](when mode=2,it’s
- * in inquiry status.)
- * <fac> values reserved by the present document:
- * "SC": SIM (lock SIM/UICC card installed in the currently selected card
- * slot) (SIM/UICC asks password in MT power‑up and when this lock
- * command issued).
- * "FD": SIM card or active application in the UICC (GSM or USIM) fixed
- * dialling memory feature (if PIN2 authentication has not been done
- * during the current session, PIN2 is required as <passwd>).
- * <mode>: integer type
- * 0: unlock
- * 1: lock
- * 2: query status
- * <status>: integer type
- * 0: not active
- * 1: active
- * <passwd>: string type; shall be the same as password specified for the
- * facility from the MT user interface or with command
- * Change Password +CPWD.
- * <classx> is a sum of integers each representing a class of information
- * (default 7 - voice, data and fax):
- * 1 voice (telephony)
- * 2 data
- * 4 fax (facsimile services)
- * 8 short message service
- * 16 data circuit sync
- * 32 data circuit async
- * 64 dedicated packet access
- * 128 dedicated PAD access
- *
- * see RIL_REQUEST_SET_FACILITY_LOCK in RIL
- */
-void SimService::HandleFacilityLock(const Client& client,
- const std::string& command) {
- CommandParser cmd(command);
- std::string lock(cmd.GetNextStr());
- int mode = cmd.GetNextInt();
- auto password = cmd.GetNextStr();
- // Ignore class from RIL
-
- auto iter = facility_lock_.find(lock);
- if (iter == facility_lock_.end()) {
- client.SendCommandResponse(kCmeErrorOperationNotSupported);
- return;
- }
-
- std::stringstream ss;
- std::vector<std::string> responses;
- switch (mode) {
- case FacilityLock::Mode::QUERY: {
- ss << "+CLCK: " << iter->second.lock_status;
- responses.push_back(ss.str());
- responses.push_back("OK");
- break;
- }
- case FacilityLock::Mode::LOCK:
- case FacilityLock::Mode::UNLOCK: {
- if (lock == "SC") {
- if (checkPin1AndAdjustSimStatus(password) == true) {
- iter->second.lock_status = (FacilityLock::LockStatus)mode;
- responses.push_back("OK");
- } else {
- responses.push_back(kCmeErrorIncorrectPassword);
- }
- } else if (lock == "FD") {
- if (pin2_status_.VerifyPIN(password) == true) {
- iter->second.lock_status = (FacilityLock::LockStatus)mode;
- responses.push_back("OK");
- } else {
- responses.push_back(kCmeErrorIncorrectPassword);
- }
- } else { // Don't need password except 'SC' and 'FD'
- iter->second.lock_status = (FacilityLock::LockStatus)mode;
- responses.push_back("OK");
- }
- break;
- }
- default:
- responses.push_back(kCmeErrorInCorrectParameters);
- break;
- }
-
- client.SendCommandResponse(responses);
-}
-
-/**
- * AT+CCHO
- * The currently selected UICC will open a new logical channel; select the
- * application identified by the <dfname> received with this command and return
- * a session Id as the response.
- *
- * Command Possible response(s)
- * +CCHO=<dfname> <sessionid>
- * +CME ERROR: <err>
- *
- * <dfname>: all selectable applications in the UICC are referenced by a DF
- * name coded on 1 to 16 bytes.
- * <sessionid>: integer type; a session Id to be used in order to target a
- * specific application on the smart card (e.g. (U)SIM, WIM, ISIM)
- * using logical channels mechanism.
- *
- * see RIL_REQUEST_SIM_OPEN_CHANNEL in RIL
- */
-void SimService::HandleOpenLogicalChannel(const Client& client,
- const std::string& command) {
- std::vector<std::string> responses;
-
- CommandParser cmd(command);
- cmd.SkipPrefix(); // skip AT+CCHO=
- if (cmd->empty()) {
- client.SendCommandResponse(kCmeErrorInCorrectParameters);
- return;
- }
-
- XMLElement *root = sim_file_system_.GetRootElement();
- if (!root) {
- client.SendCommandResponse(kCmeErrorOperationNotAllowed);
- return;
- }
-
- std::string aid_value(*cmd);
- XMLElement* df = SimFileSystem::FindAttribute(root, "aid", aid_value);
- if (!df) {
- client.SendCommandResponse(kCmeErrorNotFound);
- return;
- }
-
- std::vector<LogicalChannel>::iterator iter = logical_channels_.begin();
- for (; iter != logical_channels_.end(); ++iter) {
- if (!iter->is_open) break;
- }
-
- if (iter != logical_channels_.end()) {
- iter->is_open = true;
- iter->df_name = *cmd;
-
- std::stringstream ss;
- ss << iter->session_id;
- responses.push_back(ss.str());
- responses.push_back("OK");
- } else {
- responses.push_back(kCmeErrorMemoryFull);
- }
-
- client.SendCommandResponse(responses);
-}
-
-/**
- * AT+CCHC
- * This command asks the ME to close a communication session with the active
- * UICC.
- *
- * Command Possible response(s)
- * +CCHC=<sessionid> +CCHC
- * +CME ERROR: <err>
- * <sessionid>: see AT+CCHO
- *
- * see RIL_REQUEST_SIM_CLOSE_CHANNEL in RIL
- */
-void SimService::HandleCloseLogicalChannel(const Client& client,
- const std::string& command) {
- std::vector<std::string> responses;
-
- CommandParser cmd(command);
- cmd.SkipPrefix(); // skip AT+CCHC=
-
- int session_id = cmd.GetNextInt();
- std::vector<LogicalChannel>::iterator iter = logical_channels_.begin();
- for (; iter != logical_channels_.end(); ++iter) {
- if (iter->session_id == session_id) break;
- }
-
- if (iter != logical_channels_.end() && iter->is_open) {
- iter->is_open = false;
- iter->df_name.clear();
- responses.push_back("+CCHC");
- responses.push_back("OK");
- } else {
- responses.push_back(kCmeErrorNotFound);
- }
- client.SendCommandResponse(responses);
-}
-
-/**
- * AT+CGLA
- * Set command transmits to the MT the <command> it then shall send as it is
- * to the selected UICC. In the same manner the UICC <response> shall be sent
- * back by the MT to the TA as it is.
- *
- * Command Possible response(s)
- * +CGLA=<sessionid>,<length>, +CGLA: <length>,<response>
- * +CME ERROR: <err>
- * <sessionid>: AT+CCHO
- * <length>: integer type; length of the characters that are sent to TE in
- * <command> or <response> .
- * <command>: command passed on by the MT to the UICC in the format as described
- * in 3GPP TS 31.101 [65] (hexadecimal character format; refer +CSCS).
- * <response>: response to the command passed on by the UICC to the MT in the
- * format as described in 3GPP TS 31.101 [65] (hexadecimal character
- * format; refer +CSCS).
- *
- * see RIL_REQUEST_SIM_TRANSMIT_APDU_CHANNEL in RIL
- */
-void SimService::HandleTransmitLogicalChannel(const Client& client,
- const std::string& command) {
- std::vector<std::string> responses;
-
- CommandParser cmd(command);
- cmd.SkipPrefix(); // skip AT+CGLA=
-
- int session_id = cmd.GetNextInt();
- int length = cmd.GetNextInt();
- if (cmd->length() != length) {
- client.SendCommandResponse(kCmeErrorInCorrectParameters);
- return;
- }
-
- // Check if session id is opened
- auto iter = logical_channels_.begin();
- for (; iter != logical_channels_.end(); ++iter) {
- if (iter->session_id == session_id && iter->is_open) {
- break;
- }
- }
-
- if (iter == logical_channels_.end()) {
- client.SendCommandResponse(kCmeErrorInvalidIndex);
- return;
- }
-
- XMLElement *root = sim_file_system_.GetRootElement();
- if (!root) {
- client.SendCommandResponse(kCmeErrorOperationNotAllowed);
- return;
- }
-
- // Get aid
- XMLElement* df = SimFileSystem::FindAttribute(root, "aid", iter->df_name);
- if (!df) {
- client.SendCommandResponse(kCmeErrorNotFound);
- return;
- }
-
- if (iter->df_name != "CSIM") {
- std::string command_vaule(*cmd);
- if (command_vaule.substr(2, 2) == "a4") {
- last_file_id_ = command_vaule.substr(command_vaule.length() - 4, 4);
- }
- df = SimFileSystem::FindAttribute(df, "id", last_file_id_);
- if (!df) {
- client.SendCommandResponse(kCmeErrorNotFound);
- return;
- }
- }
-
- std::string attr_value(*cmd);
- XMLElement* final = SimFileSystem::FindAttribute(df, "cmd", attr_value);
- if (!final) {
- client.SendCommandResponse(kCmeErrorNotFound);
- return;
- }
-
- std::stringstream ss;
- ss << "+CGLA: " << final->GetText();
- responses.push_back(ss.str());
- responses.push_back("OK");
- client.SendCommandResponse(responses);
-}
-
-/**
- * AT+CPWD
- * Action command sets a new password for the facility lock function defined
- * by command Facility Lock +CLCK
- *
- * Command Possible response(s)
- * +CPWD=<fac>,<oldpwd>,<newpwd> +CME ERROR: <err>
- *
- * <fac>:
- * "P2" SIM PIN2
- * refer Facility Lock +CLCK for other values
- * <oldpwd>, <newpwd>:
- * string type; <oldpwd> shall be the same as password specified for the
- * facility from the MT user interface or with command Change Password +CPWD
- * and <newpwd> is the new password; maximum length of password can be determined
- * with <pwdlength>
- * <pwdlength>: integer type maximum length of the password for the facility
- */
-void SimService::HandleChangePassword(const Client& client,
- const std::string& command) {
- std::string response = kCmeErrorIncorrectPassword;
-
- CommandParser cmd(command);
- cmd.SkipPrefix();
- auto lock = cmd.GetNextStr();
- auto old_password = cmd.GetNextStr();
- auto new_password = cmd.GetNextStr();
-
- if (lock == "SC") {
- if (ChangePin1AndAdjustSimStatus(PinStatus::WITH_PIN, old_password, new_password)) {
- response = "OK";
- }
- } else if (lock == "P2" || lock == "FD") {
- if (pin2_status_.ChangePIN(PinStatus::WITH_PIN, old_password, new_password)) {
- response = "OK";
- }
- } else {
- response = kCmeErrorOperationNotSupported;;
- }
-
- client.SendCommandResponse(response);
-}
-
-/**
- * AT+CPINR
- * Execution command cause the MT to return the number of remaining PIN retries
- * for the MT passwords with intermediate result code
- *
- * Command Possible response(s)
- * +CPINR[=<sel_code>] +CPINR: <code>,<retries>[,<default_retries>]
- *
- * <retries>:
- * integer type. Number of remaining retries per PIN.
- * <default_retries>:
- * integer type. Number of default/initial retries per PIN.
- * <code>:
- * Type of PIN. All values listed under the description of the AT+CPIN command
- * <sel_code>: String type. Same values as for the <code> and <ext_code> parameters.
- * these values are strings and shall be indicated within double quotes.
- */
-void SimService::HandleQueryRemainTimes(const Client& client,
- const std::string& command) {
- std::vector<std::string> responses;
- std::stringstream ss;
-
- CommandParser cmd(command);
- cmd.SkipPrefix();
- auto lock_type = cmd.GetNextStr();
-
- if (lock_type == "SIM PIN") {
- ss << "+CPINR: SIM PIN," << pin1_status_.pin_remaining_times_ << ","
- << kSimPinMaxRetryTimes;
- } else if (lock_type == "SIM PUK") {
- ss << "+CPINR: SIM PUK," << pin1_status_.puk_remaining_times_ << ","
- << kSimPukMaxRetryTimes;
- } else if (lock_type == "SIM PIN2") {
- ss << "+CPINR: SIM PIN2," << pin2_status_.pin_remaining_times_ << ","
- << kSimPinMaxRetryTimes;
- } else if (lock_type == "SIM PUK2") {
- ss << "+CPINR: SIM PUK2," << pin2_status_.puk_remaining_times_ << ","
- << kSimPukMaxRetryTimes;
- } else {
- responses.push_back(kCmeErrorInCorrectParameters);
- client.SendCommandResponse(responses);
- return;
- }
-
- responses.push_back(ss.str());
- responses.push_back("OK");
- client.SendCommandResponse(responses);
-}
-
-/**
- * see
- * RIL_REQUEST_CDMA_SET_SUBSCRIPTION or
- * RIL_REQUEST_CDMA_GET_SUBSCRIPTION in RIL
- */
-void SimService::HandleCdmaSubscriptionSource(const Client& client,
- const std::string& command) {
- std::vector<std::string> responses;
-
- CommandParser cmd(command);
- if (*cmd == "AT+CCSS?") { // Query
- std::stringstream ss;
- ss << "+CCSS: " << cdma_subscription_source_;
- responses.push_back(ss.str());
- } else { // Set
- cdma_subscription_source_ = cmd.GetNextInt();
- }
- responses.push_back("OK");
- client.SendCommandResponse(responses);
-}
-
-/**
- * see
- * RIL_REQUEST_CDMA_SET_ROAMNING_PREFERENCE or
- * RIL_REQUEST_CDMA_GET_ROAMNING_PREFERENCE in RIL
- */
-void SimService::HandleCdmaRoamingPreference(const Client& client,
- const std::string& command) {
- std::vector<std::string> responses;
-
- CommandParser cmd(command);
- if (*cmd == "AT+WRMP?") { // Query
- std::stringstream ss;
- ss << "+WRMP: " << cdma_roaming_preference_;
- responses.push_back(ss.str());
- } else { // Set
- cdma_roaming_preference_ = cmd.GetNextInt();
- }
- responses.push_back("OK");
- client.SendCommandResponse(responses);
-}
-
-void SimService::HandleSimAuthentication(const Client& client,
- const std::string& command) {
- std::vector<std::string> responses;
-
- CommandParser cmd(command);
- cmd.SkipPrefix();
-
- // Input format: ^MBAU=<RAND>[,<AUTN>]
- auto cmds = cmd.GetNextStr();
- // Output format: ^MBAU: <STATUS>[,<KC>,<SRES>][,<CK>,<IK>,<RES/AUTS>]
- std::stringstream ss;
-
- // Authentication challenges done in CTS.
- if (cmds == "2713AB0BA8E8E7D8F1D74545BA03F563") {
- // CarrierApiTest#testGetIccAuthentication (base64Challenge)
- ss << "^MBAU: 0,8F2980FC3872FF89,E9620240";
- } else if (cmds == "C3718EC16B3C2A66F8A7200A64069F04") {
- // CarrierApiTest#testGetIccAuthentication (base64Challenge2)
- ss << "^MBAU: 0,CFDA6C980502DA48,F7E53577";
- } else if (cmds == "11111111111111111111111111111111") {
- // CarrierApiTest#testEapSimAuthentication
- ss << "^MBAU: 0,0000000000000000,00000000";
- } else if (cmds == "11111111111111111111111111111111,12351417161900001130131215141716") {
- // CarrierApiTest#testEapAkaAuthentication
- // Note: the "DB" prefix gets appended where the RIL parses this response.
- ss << "^MBAU: 0,111013121514171619181B1A1D1C1F1E,1013121514171619181B1A1D1C1F1E11,"
- "13121514171619181B1A1D1C1F1E1110";
- }
-
- responses.push_back(ss.str());
- responses.push_back("OK");
- client.SendCommandResponse(responses);
-}
-
-
-} // namespace cuttlefish
diff --git a/host/commands/modem_simulator/sim_service.h b/host/commands/modem_simulator/sim_service.h
deleted file mode 100644
index 7cccfcb51..000000000
--- a/host/commands/modem_simulator/sim_service.h
+++ /dev/null
@@ -1,271 +0,0 @@
-//
-// Copyright (C) 2020 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 <tinyxml2.h>
-
-#include "host/commands/modem_simulator/modem_service.h"
-
-namespace cuttlefish {
-
-using namespace tinyxml2;
-
-class NetworkService;
-
-class SimService : public ModemService, public std::enable_shared_from_this<SimService> {
- public:
- SimService(int32_t service_id, ChannelMonitor* channel_monitor,
- ThreadLooper* thread_looper);
- ~SimService() = default;
-
- SimService(const SimService &) = delete;
- SimService &operator=(const SimService &) = delete;
-
- void SetupDependency(NetworkService* net);
-
- void HandleSIMStatusReq(const Client& client);
- void HandleChangeOrEnterPIN(const Client& client, const std::string& command);
- void HandleSIM_IO(const Client& client, const std::string& command);
- void HandleCSIM_IO(const Client& client, const std::string& command);
- void HandleGetIMSI(const Client& client);
- void HandleGetIccId(const Client& client);
- void HandleFacilityLock(const Client& client, const std::string& command);
- void HandleOpenLogicalChannel(const Client& client,
- const std::string& command);
- void HandleCloseLogicalChannel(const Client& client,
- const std::string& command);
- void HandleTransmitLogicalChannel(const Client& client,
- const std::string& command);
- void HandleChangePassword(const Client& client, const std::string& command);
- void HandleQueryRemainTimes(const Client& client, const std::string& command);
- void HandleCdmaSubscriptionSource(const Client& client,
- const std::string& command);
- void HandleCdmaRoamingPreference(const Client& client,
- const std::string& command);
- void HandleSimAuthentication(const Client& client,
- const std::string& command);
-
- void SavePinStateToIccProfile();
- void SaveFacilityLockToIccProfile();
- bool IsFDNEnabled();
- bool IsFixedDialNumber(std::string_view number);
- XMLElement* GetIccProfile();
- std::string GetPhoneNumber();
-
- enum SimStatus {
- SIM_STATUS_ABSENT = 0,
- SIM_STATUS_NOT_READY,
- SIM_STATUS_READY,
- SIM_STATUS_PIN,
- SIM_STATUS_PUK,
- };
-
- SimStatus GetSimStatus() const;
- std::string GetSimOperator();
-
- private:
- void InitializeServiceState();
- std::vector<CommandHandler> InitializeCommandHandlers();
- void InitializeSimFileSystemAndSimState();
- void InitializeFacilityLock();
- void OnSimStatusChanged();
-
- NetworkService* network_service_;
-
- /* SimStatus */
- SimStatus sim_status_;
-
- /* SimFileSystem */
- struct SimFileSystem {
- enum EFId: int32_t {
- EF_ADN = 0x6F3A,
- EF_FDN = 0x6F3B,
- EF_GID1 = 0x6F3E,
- EF_GID2 = 0x6F3F,
- EF_SDN = 0x6F49,
- EF_EXT1 = 0x6F4A,
- EF_EXT2 = 0x6F4B,
- EF_EXT3 = 0x6F4C,
- EF_EXT5 = 0x6F4E,
- EF_EXT6 = 0x6FC8, // Ext record for EF[MBDN]
- EF_MWIS = 0x6FCA,
- EF_MBDN = 0x6FC7,
- EF_PNN = 0x6FC5,
- EF_OPL = 0x6FC6,
- EF_SPN = 0x6F46,
- EF_SMS = 0x6F3C,
- EF_ICCID = 0x2FE2,
- EF_AD = 0x6FAD,
- EF_MBI = 0x6FC9,
- EF_MSISDN = 0x6F40,
- EF_SPDI = 0x6FCD,
- EF_SST = 0x6F38,
- EF_CFIS = 0x6FCB,
- EF_IMG = 0x4F20,
-
- // USIM SIM file ids from TS 131.102
- EF_PBR = 0x4F30,
- EF_LI = 0x6F05,
-
- // GSM SIM file ids from CPHS (phase 2, version 4.2) CPHS4_2.WW6
- EF_MAILBOX_CPHS = 0x6F17,
- EF_VOICE_MAIL_INDICATOR_CPHS = 0x6F11,
- EF_CFF_CPHS = 0x6F13,
- EF_SPN_CPHS = 0x6F14,
- EF_SPN_SHORT_CPHS = 0x6F18,
- EF_INFO_CPHS = 0x6F16,
- EF_CSP_CPHS = 0x6F15,
-
- // CDMA RUIM file ids from 3GPP2 C.S0023-0
- EF_CST = 0x6F32,
- EF_RUIM_SPN =0x6F41,
-
- // ETSI TS.102.221
- EF_PL = 0x2F05,
- // 3GPP2 C.S0065
- EF_CSIM_LI = 0x6F3A,
- EF_CSIM_SPN =0x6F41,
- EF_CSIM_MDN = 0x6F44,
- EF_CSIM_IMSIM = 0x6F22,
- EF_CSIM_CDMAHOME = 0x6F28,
- EF_CSIM_EPRL = 0x6F5A,
- EF_CSIM_MIPUPP = 0x6F4D,
-
- //ISIM access
- EF_IMPU = 0x6F04,
- EF_IMPI = 0x6F02,
- EF_DOMAIN = 0x6F03,
- EF_IST = 0x6F07,
- EF_PCSCF = 0x6F09,
- EF_PSI = 0x6FE5,
-
- //PLMN Selection Information w/ Access Technology TS 131.102
- EF_PLMN_W_ACT = 0x6F60,
- EF_OPLMN_W_ACT = 0x6F61,
- EF_HPLMN_W_ACT = 0x6F62,
-
- //Equivalent Home and Forbidden PLMN Lists TS 131.102
- EF_EHPLMN = 0x6FD9,
- EF_FPLMN = 0x6F7B,
-
- // Last Roaming Selection Indicator
- EF_LRPLMNSI = 0x6FDC,
-
- //Search interval for higher priority PLMNs
- EF_HPPLMN = 0x6F31,
- };
-
- XMLElement* GetRootElement();
-
- static std::string GetCommonIccEFPath(EFId efid);
- static std::string GetUsimEFPath(EFId efid);
-
- static XMLElement *FindAttribute(XMLElement* parent,
- const std::string& attr_name,
- const std::string& attr_value);
-
- XMLElement* AppendNewElement(XMLElement* parent, const char* name);
- XMLElement* AppendNewElementWithText(XMLElement* parent, const char* name,
- const char* text);
-
- XMLDocument doc;
- std::string file_path;
- };
- SimFileSystem sim_file_system_;
-
-
- /* PinStatus */
- struct PinStatus {
- enum ChangeMode {WITH_PIN, WITH_PUK};
-
- std::string pin_;
- std::string puk_;
- int pin_remaining_times_;
- int puk_remaining_times_;
-
- bool CheckPasswordValid(std::string_view password);
-
- bool VerifyPIN(const std::string_view pin);
- bool VerifyPUK(const std::string_view puk);
- bool ChangePIN(ChangeMode mode, const std::string_view pin_or_puk,
- const std::string_view new_pin);
- bool ChangePUK(const std::string_view puk, const std::string_view new_puk);
- };
- PinStatus pin1_status_;
- PinStatus pin2_status_;
-
- bool checkPin1AndAdjustSimStatus(std::string_view password);
- bool ChangePin1AndAdjustSimStatus(PinStatus::ChangeMode mode,
- std::string_view pin,
- std::string_view new_pin);
-
- /* FacilityLock */
- struct FacilityLock {
- enum LockType {
- AO = 1, // Barr all outgoing calls
- OI = 2, // Barr all outgoing international calls
- OX = 3, // Barr all outgoing international calls, except to Home Country
- AI = 4, // Barr all incoming calls
- IR = 5, // Barr all call, when roaming outside Home Country
- AB = 6, // All barring services
- AG = 7, // All outgoing barring services
- AC = 8, // All incoming barring services
- SC = 9, // PIN enable/disable
- FD = 10, // SIM fixed FDN dialing lock, PIN2 is required as a password
- };
-
- enum Mode {
- UNLOCK = 0,
- LOCK = 1,
- QUERY = 2,
- };
-
- enum Class : int32_t {
- DEFAULT = 7, // all classes
- VOICE = 1 << 0, // telephony
- DATA = 1 << 1, // to all bear service
- FAX = 1 << 2, // facsimile services
- SMS = 1 << 3, // short message services
- };
-
- enum LockStatus {
- DISABLE,
- ENABLE,
- };
-
- LockStatus lock_status; // Ignore class
-
- FacilityLock(LockStatus status) : lock_status(status) {}
- };
- std::map<std::string, FacilityLock> facility_lock_;
-
- /* LogicalChannel */
- struct LogicalChannel {
- std::string df_name;
- bool is_open;
- int session_id;
-
- LogicalChannel(int session_id) :
- df_name(""), is_open(false), session_id(session_id) {};
- };
- std::vector<LogicalChannel> logical_channels_;
- std::string last_file_id_;
-
- int cdma_subscription_source_;
- int cdma_roaming_preference_;
-};
-
-} // namespace cuttlefish
diff --git a/host/commands/modem_simulator/sms_service.cpp b/host/commands/modem_simulator/sms_service.cpp
deleted file mode 100644
index 0da21a6d5..000000000
--- a/host/commands/modem_simulator/sms_service.cpp
+++ /dev/null
@@ -1,390 +0,0 @@
-//
-// Copyright (C) 2020 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 "host/commands/modem_simulator/sms_service.h"
-
-#include <android-base/logging.h>
-
-#include "host/commands/modem_simulator/pdu_parser.h"
-
-namespace cuttlefish {
-
-SmsService::SmsService(int32_t service_id, ChannelMonitor* channel_monitor,
- ThreadLooper* thread_looper)
- : ModemService(service_id, this->InitializeCommandHandlers(),
- channel_monitor, thread_looper) {
- InitializeServiceState();
-}
-
-std::vector<CommandHandler> SmsService::InitializeCommandHandlers() {
- std::vector<CommandHandler> command_handlers = {
- CommandHandler("+CMGS",
- [this](const Client& client, std::string& cmd) {
- this->HandleSendSMS(client, cmd);
- }),
- CommandHandler("+CNMA",
- [this](const Client& client, std::string& cmd) {
- this->HandleSMSAcknowledge(client, cmd);
- }),
- CommandHandler("+CMGW",
- [this](const Client& client, std::string& cmd) {
- this->HandleWriteSMSToSim(client, cmd);
- }),
- CommandHandler("+CMGD",
- [this](const Client& client, std::string& cmd) {
- this->HandleDeleteSmsOnSim(client, cmd);
- }),
- CommandHandler("+CSCB",
- [this](const Client& client, std::string& cmd) {
- this->HandleBroadcastConfig(client, cmd);
- }),
- CommandHandler(
- "+CSCA?",
- [this](const Client& client) { this->HandleGetSmscAddress(client); }),
- CommandHandler("+CSCA=",
- [this](const Client& client, std::string& cmd) {
- this->HandleSetSmscAddress(client, cmd);
- }),
- CommandHandler("+REMOTESMS",
- [this](const Client& client, std::string& cmd) {
- this->HandleReceiveRemoteSMS(client, cmd);
- }),
- };
- return (command_handlers);
-}
-
-void SmsService::InitializeServiceState() {
- is_waiting_sms_pdu_ = false;
- is_waiting_sms_to_sim_ = false;
- message_id_ = 1;
- message_reference_ = 1;
-
- broadcast_config_ = {0, "", ""};
-}
-
-void SmsService::SetupDependency(SimService* sim) { sim_service_ = sim; }
-
-/**
- * AT+CMGS
- * This command sends message from a TE to the network (SMS-SUBMIT).
- *
- * Command Possible response(s)
- * +CMGS=<length><CR> "> "
- * PDU is given<ctrl-Z/ESC> +CMGS: <mr>[,<ackpdu>]<CR>OK
- * +CMS ERROR: <err>
- *
- * <length>:must indicate the number of octets coded in the TP
- * layer data unit to be given.
- *
- * see RIL_REQUEST_SEND_SMS in RIL
- */
-void SmsService::HandleSendSMS(const Client& client, std::string& /*command*/) {
- is_waiting_sms_pdu_ = true;
-
- std::vector<std::string> responses;
- responses.push_back("> ");
- client.SendCommandResponse(responses);
-}
-
-/**
- * AT+CNMA
- * This command confirms reception of a new message (SMS-DELIVER or
- * SMS-STATUS-REPORT) which is routed directly to the TE.
- *
- * Command Possible response(s)
- * +CNMA [=<n>[, <length> [<CR> OK
- * PDU is given<ctrl-Z/ESC>]]] +CMS ERROR: <err>
- *
- * <n>: integer type
- * 0: command operates similarly as defined for the text mode
- * 1: send RP-ACK
- * 2: send RP-ERROR
- * <length>: ACKPDU length(octet)
- *
- * see RIL_REQUEST_SMS_ACKNOWLEDGE in RIL
- */
-void SmsService::HandleSMSAcknowledge(const Client& client, std::string& /*command*/) {
- client.SendCommandResponse("OK");
-}
-
-/*
- * AT+CMGW
- * This command stores message (either SMS-DELIVER or SMS-SUBMIT)
- * to memory storage <mem2>.
- *
- * Command Possible response(s)
- * +CMGW=<length>[,<stat>]<CR> "> "
- * PDU is given <ctrl-Z/ESC> +CMGW: <index>
- * +CMS ERROR: <err>
- * <length>: the length of TPDU(bit) with a range of 9-160
- * < stat >: integer:
- * 0: Unread Message. (MT)
- * 1: Read Message. (MT)
- * 2: Unsent Message. (MO)
- * 3: Sent Message. (MO)
- * < index>: index id of <mem2>
- *
- * see RIL_REQUEST_WRITE_SMS_TO_SIM in RIL
- */
-void SmsService::HandleWriteSMSToSim(const Client& client, std::string& command) {
- is_waiting_sms_to_sim_ = true;
-
- CommandParser cmd(command);
- cmd.SkipPrefix(); // skip "AT+CMGW="
- cmd.SkipComma();
- sms_status_on_sim_ = (SmsMessage::SmsStatus)cmd.GetNextInt();
- client.SendCommandResponse("> ");
-}
-
-/**
- * AT+CMGD
- * This command deletes message from preferred message storage <mem1>
- * location <index>.
- *
- * Command Possible response(s)
- * +CMGD=<index>[, <DelFlag>] OK
- * +CMS ERROR: <err>
- * < index>: index id of <mem2>
- *
- * see RIL_REQUEST_DELETE_SMS_ON_SIM in RIL
- */
-void SmsService::HandleDeleteSmsOnSim(const Client& client, std::string& command) {
- CommandParser cmd(command);
- cmd.SkipPrefix(); // skip "AT+CMGD="
-
- int index = cmd.GetNextInt();
- auto iter = messages_on_sim_card_.find(index);
- if (iter == messages_on_sim_card_.end()) {
- client.SendCommandResponse(kCmeErrorInvalidIndex); // No such message
- return;
- }
-
- messages_on_sim_card_.erase(iter);
- client.SendCommandResponse("OK");
-}
-
-/**
- * AT+CSCB
- * Set command selects which types of CBMs are to be received by the ME.
- *
- * Command Possible response(s)
- * +CSCB=[<mode>[,<mids>[,<dcss>]]] OK
- * +CSCB? +CSCB: <mode>,<mids>,<dcss>
- *
- * <mode>:
- * 0: message types specified in <mids> and <dcss> are accepted
- * 1: message types specified in <mids> and <dcss> are not accepted
- * <mids>: string type; all different possible combinations of CBM message
- * identifiers (refer <mid>).
- * <dcss>: string type; all different possible combinations of CBM data coding
- * schemes.
- *
- * see RIL_REQUEST_GSM_GET_BROADCAST_SMS_CONFIG &
- * RIL_REQUEST_GSM_SET_BROADCAST_SMS_CONFIG in RIL
- * Notes: This command is allowed in TEXT mode.
- */
-void SmsService::HandleBroadcastConfig(const Client& client, std::string& command) {
- std::vector<std::string> responses;
-
- CommandParser cmd(command);
- cmd.SkipPrefix();
- if (*cmd == "AT+CSCB?") { // Query
- std::stringstream ss;
- ss << "+CSCB: " << broadcast_config_.mode << ","
- << broadcast_config_.mids << ","
- << broadcast_config_.dcss;
- responses.push_back(ss.str());
- } else { // Set
- broadcast_config_.mode = cmd.GetNextInt();
- broadcast_config_.mids = cmd.GetNextStr();
- broadcast_config_.dcss = cmd.GetNextStr();
- }
- responses.push_back("OK");
- client.SendCommandResponse(responses);
-}
-
-/**
- * AT+CSCA
- * Set command updates the SMSC address, through which mobile originated
- * SMs are transmitted.
- *
- * Command Possible response(s)
- * +CSCA=<sca>[,<tosca>] OK
- * +CSCA? +CSCA: <sca>,<tosca>
- *
- * <sca>: service center address, its maximum length is 20.
- * <tosca>: service center address format,protocol uses 8-bit address integer.
- *
- * see RIL_REQUEST_SET_SMSC_ADDRESS in RIL
- */
-void SmsService::HandleGetSmscAddress(const Client& client) {
- std::vector<std::string> responses;
-
- std::stringstream ss;
- ss << "+CSCA: " << sms_service_center_address_.sca << ","
- << sms_service_center_address_.tosca;
- responses.push_back(ss.str());
- responses.push_back("OK");
- client.SendCommandResponse(responses);
-}
-
-void SmsService::HandleSetSmscAddress(const Client& client, std::string& command) {
- CommandParser cmd(command);
- cmd.SkipPrefix(); // skip "AT+CSCA="
-
- sms_service_center_address_.sca = cmd.GetNextStr();
- sms_service_center_address_.tosca = cmd.GetNextInt();
-
- client.SendCommandResponse("OK");
-}
-
-void SmsService::SendSmsToRemote(std::string remote_port, PDUParser& sms_pdu) {
- auto remote_client = ConnectToRemoteCvd(remote_port);
- if (!remote_client->IsOpen()) {
- return;
- }
-
- auto local_host_port = GetHostPort();
- auto pdu = sms_pdu.CreateRemotePDU(local_host_port);
-
- std::string command = "AT+REMOTESMS=" + pdu + "\r";
- std::string token = "REM0";
- remote_client->Write(token.data(), token.size());
- remote_client->Write(command.data(), command.size());
-}
-
-/* process AT+CMGS PDU */
-void SmsService::HandleSendSMSPDU(const Client& client, std::string& command) {
- is_waiting_sms_pdu_ = false;
-
- std::vector<std::string> responses;
- PDUParser sms_pdu(command);
- if (!sms_pdu.IsValidPDU()) {
- /* Invalid PDU mode parameter */
- client.SendCommandResponse(kCmsErrorInvalidPDUModeParam);
- return;
- }
-
- std::string phone_number = sms_pdu.GetPhoneNumberFromAddress();
-
- int port = 0;
- if (phone_number.length() == 11) {
- port = std::stoi(phone_number.substr(7));
- } else if (phone_number.length() == 4) {
- port = std::stoi(phone_number);
- }
-
- if (phone_number == "") { /* Phone number unknown */
- LOG(ERROR) << "Failed to get phone number form address";
- client.SendCommandResponse(kCmsErrorSCAddressUnknown);
- return;
- } else if (port >= kRemotePortRange.first &&
- port <= kRemotePortRange.second) {
- std::stringstream ss;
- ss << port;
- auto remote_host_port = ss.str();
- if (GetHostPort() == remote_host_port) { // Send SMS to local host port
- thread_looper_->PostWithDelay(
- std::chrono::seconds(1),
- makeSafeCallback<SmsService>(this, [&sms_pdu](SmsService* me) {
- me->HandleReceiveSMS(sms_pdu);
- }));
- } else { // Send SMS to remote host port
- SendSmsToRemote(remote_host_port, sms_pdu);
- }
- } else if (sim_service_ && phone_number == sim_service_->GetPhoneNumber()) {
- /* Local phone number */
- thread_looper_->PostWithDelay(
- std::chrono::seconds(1),
- makeSafeCallback<SmsService>(this, [sms_pdu](SmsService* me) {
- me->HandleReceiveSMS(sms_pdu);
- }));
- } /* else pretend send SMS success */
-
- std::stringstream ss;
- ss << "+CMGS: " << ++message_reference_;
- responses.push_back(ss.str());
- responses.push_back("OK");
- client.SendCommandResponse(responses);
-
- if (sms_pdu.IsNeededStatuReport()) {
- int ref = message_reference_;
- thread_looper_->PostWithDelay(
- std::chrono::seconds(1),
- makeSafeCallback<SmsService>(this, [sms_pdu, ref](SmsService* me) {
- me->HandleSMSStatuReport(sms_pdu, ref);
- }));
- }
-}
-
-/* AT+CMGS callback function */
-void SmsService::HandleReceiveSMS(PDUParser sms_pdu) {
- std::string pdu = sms_pdu.CreatePDU();
- if (pdu != "") {
- SendUnsolicitedCommand("+CMT: 0");
- SendUnsolicitedCommand(pdu);
- }
-}
-
-/* Process AT+CMGW PDU */
-void SmsService::HandleWriteSMSPduToSim(const Client& client, std::string& command) {
- is_waiting_sms_to_sim_ = false;
-
- SmsMessage message;
- message.status = sms_status_on_sim_;
- message.message = command;
- int index = message_id_++;
- messages_on_sim_card_[index] = message;
-
- std::vector<std::string> responses;
- std::stringstream ss;
- ss << "+CMGW: " << index;
- responses.push_back(ss.str());
- responses.push_back("OK");
- client.SendCommandResponse(responses);
-}
-
-/* SMS Status Report */
-void SmsService::HandleSMSStatuReport(PDUParser sms_pdu, int message_reference) {
- std::string response;
- std::stringstream ss;
-
- auto pdu = sms_pdu.CreateStatuReport(message_reference);
- auto pdu_length = (pdu.size() - 2) / 2; // Not Including SMSC Address
- if (pdu != "" && pdu_length > 0) {
- ss << "+CDS: " << pdu_length;
- SendUnsolicitedCommand(ss.str());
- SendUnsolicitedCommand(pdu);
- }
-}
-
-/* AT+REMOTESMS=PDU */
-void SmsService::HandleReceiveRemoteSMS(const Client& /*client*/, std::string& command) {
- CommandParser cmd(command);
- cmd.SkipPrefix();
-
- std::string pdu(*cmd);
- PDUParser sms_pdu(pdu);
- if (!sms_pdu.IsValidPDU()) {
- LOG(ERROR) << "Failed to decode PDU";
- return;
- }
- pdu = sms_pdu.CreatePDU();
- if (pdu != "") {
- SendUnsolicitedCommand("+CMT: 0");
- SendUnsolicitedCommand(pdu);
- }
-}
-} // namespace cuttlefish
diff --git a/host/commands/modem_simulator/sms_service.h b/host/commands/modem_simulator/sms_service.h
deleted file mode 100644
index 66025530a..000000000
--- a/host/commands/modem_simulator/sms_service.h
+++ /dev/null
@@ -1,89 +0,0 @@
-//
-// Copyright (C) 2020 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 "host/commands/modem_simulator/modem_service.h"
-#include "host/commands/modem_simulator/pdu_parser.h"
-#include "host/commands/modem_simulator/sim_service.h"
-
-namespace cuttlefish {
-
-class SmsService : public ModemService , public std::enable_shared_from_this<SmsService> {
- public:
- SmsService(int32_t service_id, ChannelMonitor* channel_monitor,
- ThreadLooper* thread_looper);
- ~SmsService() = default;
-
- SmsService(const SmsService &) = delete;
- SmsService &operator=(const SmsService &) = delete;
-
- void SetupDependency(SimService* sim);
-
- void HandleSendSMS(const Client& client, std::string& command);
- void HandleSendSMSPDU(const Client& client, std::string& command);
- void HandleSMSAcknowledge(const Client& client, std::string& command);
- void HandleWriteSMSToSim(const Client& client, std::string& command);
- void HandleDeleteSmsOnSim(const Client& client, std::string& command);
- void HandleBroadcastConfig(const Client& client, std::string& command);
- void HandleGetSmscAddress(const Client& client);
- void HandleSetSmscAddress(const Client& client, std::string& command);
- void HandleWriteSMSPduToSim(const Client& client, std::string& command);
- void HandleReceiveRemoteSMS(const Client& client, std::string& command);
-
- bool IsWaitingSmsPdu() { return is_waiting_sms_pdu_; }
- bool IsWaitingSmsToSim() { return is_waiting_sms_to_sim_; }
-
- private:
- void InitializeServiceState();
- std::vector<CommandHandler> InitializeCommandHandlers();
-
- void HandleReceiveSMS(PDUParser sms_pdu);
- void HandleSMSStatuReport(PDUParser sms_pdu, int message_reference);
- void SendSmsToRemote(std::string remote_port, PDUParser& sms_pdu);
-
- SimService* sim_service_;
-
- struct SmsMessage {
- enum SmsStatus { kUnread = 0, kRead = 1, kUnsent = 2, kSent = 3 };
-
- std::string message;
- SmsStatus status;
- };
-
- struct BroadcastConfig {
- int mode;
- std::string mids;
- std::string dcss;
- };
-
- struct SmsServiceCenterAddress {
- std::string sca;
- int tosca;
- };
-
- bool is_waiting_sms_pdu_;
- bool is_waiting_sms_to_sim_;
- int message_id_;
- int message_reference_;
- SmsMessage::SmsStatus sms_status_on_sim_;
-
- BroadcastConfig broadcast_config_;
- SmsServiceCenterAddress sms_service_center_address_;
-
- std::map<int, SmsMessage> messages_on_sim_card_;
-};
-
-} // namespace cuttlefish
diff --git a/host/commands/modem_simulator/stk_service.cpp b/host/commands/modem_simulator/stk_service.cpp
deleted file mode 100644
index 6002c6d50..000000000
--- a/host/commands/modem_simulator/stk_service.cpp
+++ /dev/null
@@ -1,284 +0,0 @@
-//
-// Copyright (C) 2020 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 "host/commands/modem_simulator/stk_service.h"
-
-#include <android-base/logging.h>
-namespace cuttlefish {
-
-StkService::StkService(int32_t service_id, ChannelMonitor* channel_monitor,
- ThreadLooper* thread_looper)
- : ModemService(service_id, this->InitializeCommandHandlers(),
- channel_monitor, thread_looper) {}
-
-std::vector<CommandHandler> StkService::InitializeCommandHandlers() {
- std::vector<CommandHandler> command_handlers = {
- CommandHandler("+CUSATD?",
- [this](const Client& client) {
- this->HandleReportStkServiceIsRunning(client);
- }),
- CommandHandler("+CUSATE=",
- [this](const Client& client, std::string& cmd) {
- this->HandleSendEnvelope(client, cmd);
- }),
- CommandHandler("+CUSATT=",
- [this](const Client& client, std::string& cmd) {
- this->HandleSendTerminalResponseToSim(client, cmd);
- }),
- };
- return (command_handlers);
-}
-
-void StkService::SetupDependency(SimService* sim) { sim_service_ = sim; }
-
-/**
- * AT+CUSATD
- * This command determines if, and optionally which profile should be downloaded
- * to the UICC automatically upon start-up.
- *
- * Command Possible response(s)
- * +CUSATD=[<download>[,<reporting>]] +CME ERROR: <err>
- * +CUSATD? +CUSATD: <download>,<reporting>
- *
- * <download>: integer type.
- * 0 Download MT default profile automatically during next start-up.
- * 1 Download the combined TE and MT profile
- * 2 Halt next UICC start-up when ready for profile download.
- * <reporting>: integer type.
- * 0 Disable +CUSATS, i.e. no notification.
- * 1 Enable +CUSATS, i.e. notify TE.
- *
- * see RIL_REQUEST_REPORT_STK_SERVICE_IS_RUNNING in RIL
- */
-void StkService::HandleReportStkServiceIsRunning(const Client& client) {
- std::vector<std::string> response = {{"+CUSATD: 0,1"}, {"OK"}};
- client.SendCommandResponse(response);
-
- if (!sim_service_) return;
-
- XMLElement *root = sim_service_->GetIccProfile();
- if (!root) return;
-
- XMLElement *setup_menu = root->FirstChildElement("SETUPMENU");
- auto text = setup_menu->FindAttribute("text");
-
- std::string unsol_command = "+CUSATP:";
- unsol_command += text ? text->Value() : "";
- SendUnsolicitedCommand(unsol_command);
-}
-
-/**
- * AT+CUSATE
- * Execution command allows the TE to send a USAT envelope command to the MT
- *
- * Command Possible response(s)
- * +CUSATE=<envelope_command> +CUSATE: <envelope_response>[,<busy>]
- * [<CR><LF>+CUSATE2: <sw1>,<sw2>]
- * +CME ERROR: <err>
- *
- * <envelope_command>: string type in hexadecimal character format.
- * <envelope_response>: string type in hexadecimal character format.
- * <busy>: integer type.
- * 0 UICC indicated normal ending of the command.
- * 1 UICC responded with USAT is busy, no retry by the MT.
- * 2 UICC responded with USAT is busy even after one or more retries by the MT.
- * <sw1>: integer type.
- * <sw2>: integer type.
- *
- * see RIL_REQUEST_STK_SEND_ENVELOPE_COMMAND in RIL
- */
-void StkService::HandleSendEnvelope(const Client& client , std::string& command) {
- std::vector<std::string> response = {{"+CUSATE: 0"}, {"OK"}};
- client.SendCommandResponse(response);
-
- if (!sim_service_) return;
-
- CommandParser cmd(command);
- cmd.SkipPrefix();
- auto data = cmd.GetNextStr();
- std::string menu_id(data.substr(data.size() - 2)); // get the last two char
-
- XMLElement *root = sim_service_->GetIccProfile();
- if (!root) return;
-
- XMLElement *setup_menu = root->FirstChildElement("SETUPMENU");
- if (!setup_menu) return;
-
- auto select_item = setup_menu->FirstChildElement("SELECTITEM");
- while (select_item) {
- auto menu_id_attr = select_item->FindAttribute("menuId");
- if (menu_id_attr && menu_id_attr->Value() == menu_id) {
- break;
- }
- select_item = select_item->NextSiblingElement("SELECTITEM");
- }
- if (!select_item) {
- LOG(ERROR) << "Not found menu id: " << menu_id;
- return;
- }
-
- auto select_item_cmd = select_item->FindAttribute("cmd");
- if (select_item_cmd) {
- std::string cmd_str = select_item_cmd->Value();
- if (cmd_str == "24") { // SELECT_ITEM
- current_select_item_menu_ids_.push_back(menu_id);
- }
- }
-
- std::string unsol_command = "+CUSATP:";
- auto text = select_item->FindAttribute("text");
- std::string text_value = text ? text->Value() : "";
- unsol_command.append(text_value);
- SendUnsolicitedCommand(unsol_command);
-}
-
-/**
- * AT+CUSATT
- * Execution command sends a USAT terminal response to the MT as an answer to
- * a preceding USAT proactive command sent from the UICC with unsolicited result
- * code +CUSATP: <proactive_command>
- *
- * Command Possible response(s)
- * +CUSATT=<terminal_response> +CME ERROR: <err>
- *
- * <terminal_response>: string type in hexadecimal character format.
- *
- * see RIL_REQUEST_STK_SEND_TERMINAL_RESPONSE in RIL
- */
-void StkService::HandleSendTerminalResponseToSim(const Client& client, std::string& command) {
- std::vector<std::string> response = {{"+CUSATT: 0"}, {"OK"}};
- client.SendCommandResponse(response);
-
- OnUnsolicitedCommandForTR(command);
-}
-
-XMLElement* StkService::GetCurrentSelectItem() {
- if (!sim_service_) return nullptr;
-
- XMLElement *root = sim_service_->GetIccProfile();
- if (!root) {
- current_select_item_menu_ids_.clear();
- return nullptr;
- }
-
- XMLElement *menu = root->FirstChildElement("SETUPMENU");
- if (!menu) {
- current_select_item_menu_ids_.clear();
- return nullptr;
- }
-
- /**
- * e.g. current_select_item_menu_ids_: {"1", "02"}
- * <SELECTITEM id="1">
- * <SELECTITEM id="01">
- * </SELECTITEM>
- * <SELECTITEM id="02">
- * </SELECTITEM>
- * </SELECTITEM>
- */
- XMLElement* select_item = nullptr;
- auto iter = current_select_item_menu_ids_.begin();
- for (; iter != current_select_item_menu_ids_.end(); ++iter) {
- select_item = menu->FirstChildElement("SELECTITEM");
- while (select_item) {
- auto menu_id_attr = select_item->FindAttribute("menuId");
- if (menu_id_attr && menu_id_attr->Value() == *iter) {
- auto menu_id_str = menu_id_attr->Value();
- if (menu_id_str == *iter) break;
- }
- select_item = select_item->NextSiblingElement("SELECTITEM");
- }
- if (!select_item) break;
- menu = select_item;
- }
-
- return select_item;
-}
-
-void StkService::OnUnsolicitedCommandForTR(std::string& command) {
- CommandParser cmd(command);
- cmd.SkipPrefix();
- auto data = cmd.GetNextStr();
- auto menu_id = data.substr(data.size() - 2);
-
- // '10': UICC_SESSION_TERM_BY_USER
- // '12': NO_RESPONSE_FROM_USER
- if (menu_id == "10" || menu_id == "12") {
- current_select_item_menu_ids_.clear();
- SendUnsolicitedCommand("+CUSATEND");
- return;
- }
-
- XMLElement *select_item = GetCurrentSelectItem();
- if (!select_item) {
- current_select_item_menu_ids_.clear();
- SendUnsolicitedCommand("+CUSATEND");
- return;
- }
-
- if (menu_id == "11") { // BACKWARD_MOVE_BY_USER
- current_select_item_menu_ids_.pop_back();
- if (current_select_item_menu_ids_.size() >= 1) {
- select_item = GetCurrentSelectItem();
- auto text = select_item->FindAttribute("text");
- if (text) {
- std::string unsol_command = "+CUSATP: ";
- unsol_command += text->Value();
- SendUnsolicitedCommand(unsol_command);
- }
- } else {
- SendUnsolicitedCommand("+CUSATEND");
- }
- return;
- } else if (menu_id == "00") { // OK
- auto text = select_item->FindAttribute("text");
- if (text) {
- std::string unsol_command = "+CUSATP: ";
- unsol_command += text->Value();
- SendUnsolicitedCommand(unsol_command);
- }
- return;
- }
-
- auto final = select_item->FirstChildElement();
- while (final) {
- auto attr = final->FindAttribute("menuId");
- if (attr && attr->Value() == menu_id) {
- std::string attr_value = attr->Value();
- if (attr_value == menu_id) break;
- }
- final = final->NextSiblingElement();
- }
- if (!final) {
- current_select_item_menu_ids_.clear();
- SendUnsolicitedCommand("+CUSATEND");
- return;
- }
-
- auto cmd_attr = final->FindAttribute("cmd");
- if (cmd_attr) {
- std::string cmd_attr_str = cmd_attr->Value();
- if (cmd_attr_str == "24") {
- std::string menu_id_str(menu_id);
- current_select_item_menu_ids_.push_back(menu_id_str);
- }
- }
- auto text = final->FindAttribute("text");
- std::string unsol_command = "+CUSATP:";
- unsol_command += text ? text->Value() : "";
- SendUnsolicitedCommand(unsol_command);
-}
-
-} // namespace cuttlefish
diff --git a/host/commands/modem_simulator/stk_service.h b/host/commands/modem_simulator/stk_service.h
deleted file mode 100644
index 225fbc1b4..000000000
--- a/host/commands/modem_simulator/stk_service.h
+++ /dev/null
@@ -1,76 +0,0 @@
-//
-// Copyright (C) 2020 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 "host/commands/modem_simulator/modem_service.h"
-#include "host/commands/modem_simulator/sim_service.h"
-
-namespace cuttlefish {
-
-class StkService : public ModemService, public std::enable_shared_from_this<StkService> {
- public:
- StkService(int32_t service_id, ChannelMonitor* channel_monitor,
- ThreadLooper* thread_looper);
- ~StkService() = default;
-
- StkService(const StkService &) = delete;
- StkService &operator=(const StkService &) = delete;
-
- void SetupDependency(SimService* sim);
-
- void HandleReportStkServiceIsRunning(const Client& client);
- void HandleSendEnvelope(const Client& client, std::string& command);
- void HandleSendTerminalResponseToSim(const Client& client, std::string& command);
-
- private:
- std::vector<CommandHandler> InitializeCommandHandlers();
-
- SimService* sim_service_;
-
- // For now, only support DISPLAY_TEXT, SELECT_ITEM and SETUP_MENU
- enum CommandType {
- DISPLAY_TEXT = 0x21,
- GET_INKEY = 0x22,
- GET_INPUT = 0x23,
- LAUNCH_BROWSER = 0x15,
- PLAY_TONE = 0x20,
- REFRESH = 0x01,
- SELECT_ITEM = 0x24,
- SEND_SS = 0x11,
- SEND_USSD = 0x12,
- SEND_SMS = 0x13,
- RUN_AT = 0x34,
- SEND_DTMF = 0x14,
- SET_UP_EVENT_LIST = 0x05,
- SET_UP_IDLE_MODE_TEXT = 0x28,
- SET_UP_MENU = 0x25,
- SET_UP_CALL = 0x10,
- PROVIDE_LOCAL_INFORMATION = 0x26,
- LANGUAGE_NOTIFICATION = 0x35,
- OPEN_CHANNEL = 0x40,
- CLOSE_CHANNEL = 0x41,
- RECEIVE_DATA = 0x42,
- SEND_DATA = 0x43,
- GET_CHANNEL_STATUS = 0x44
- };
-
- std::vector<std::string> current_select_item_menu_ids_;
-
- XMLElement* GetCurrentSelectItem();
- void OnUnsolicitedCommandForTR(std::string& command);
-};
-
-} // namespace cuttlefish
diff --git a/host/commands/modem_simulator/sup_service.cpp b/host/commands/modem_simulator/sup_service.cpp
deleted file mode 100644
index eb5de18f2..000000000
--- a/host/commands/modem_simulator/sup_service.cpp
+++ /dev/null
@@ -1,320 +0,0 @@
-//
-// Copyright (C) 2020 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 "host/commands/modem_simulator/sup_service.h"
-
-namespace cuttlefish {
-
-SupService::SupService(int32_t service_id, ChannelMonitor* channel_monitor,
- ThreadLooper* thread_looper)
- : ModemService(service_id, this->InitializeCommandHandlers(),
- channel_monitor, thread_looper) {
- InitializeServiceState();
-}
-
-std::vector<CommandHandler> SupService::InitializeCommandHandlers() {
- std::vector<CommandHandler> command_handlers = {
- CommandHandler("+CUSD",
- [this](const Client& client, std::string& cmd) {
- this->HandleUSSD(client, cmd);
- }),
- CommandHandler("+CLIR",
- [this](const Client& client, std::string& cmd) {
- this->HandleCLIR(client, cmd);
- }),
- CommandHandler("+CCWA",
- [this](const Client& client, std::string& cmd) {
- this->HandleCallWaiting(client, cmd);
- }),
- CommandHandler(
- "+CLIP?", [this](const Client& client) { this->HandleCLIP(client); }),
- CommandHandler("+CCFCU",
- [this](const Client& client, std::string& cmd) {
- this->HandleCallForward(client, cmd);
- }),
- CommandHandler("+CSSN",
- [this](const Client& client, std::string& cmd) {
- this->HandleSuppServiceNotifications(client, cmd);
- }),
- };
- return (command_handlers);
-}
-
-void SupService::InitializeServiceState() {
- call_forward_infos_ = {
- CallForwardInfo(CallForwardInfo::Reason::CFU),
- CallForwardInfo(CallForwardInfo::Reason::CFB),
- CallForwardInfo(CallForwardInfo::Reason::CFNR),
- CallForwardInfo(CallForwardInfo::Reason::CFNRC)
- };
-}
-
-/**
- * AT+CUSD
- * This command allows control of the Unstructured Supplementary Service Data (USSD)
- * according to 3GPP TS 22.090 [23], 3GPP TS 24.090 [148] and 3GPP TS 24.390 [131].
- * Both network and mobile initiated operations are supported.
- *
- * Command Possible response(s)
- * +CUSD=[<n>[,<str>[,<dcs>]]] +CME ERROR: <err>
- * +CUSD? +CUSD: <n>
- *
- * <n>: integer type (sets/shows the result code presentation status to the TE).
- * 0 disable the result code presentation to the TE
- * 1 enable the result code presentation to the TE
- * 2 cancel session (not applicable to read command response)
- * <str>: string type USSD string
- * when <str> parameter is not given, network is not interrogated
- * <dcs>: integer type (shows Cell Broadcast Data Coding Scheme, see 3GPP TS 23.038 [25]).
- * Default value is 0.
- *
- * see RIL_REQUEST_SEND_USSD or RIL_REQUEST_CANCEL_USSD in RIL
- */
-void SupService::HandleUSSD(const Client& client, std::string& /*command*/) {
- client.SendCommandResponse("OK");
-}
-
-/**
- * AT+CLIR
- * This command refers to CLIR‑service according to 3GPP TS 22.081 that allows
- * a calling subscriber to enable or disable the presentation of the CLI to the
- * called party when originating a call.
- *
- * Command Possible response(s)
- * +CLIR: <n>
- * +CLIR? +CLIR: <n>,<m>
- *
- * <n>: integer type (parameter sets the adjustment for outgoing calls).
- * 0 presentation indicator is used according to the subscription of the CLIR service
- * 1 CLIR invocation
- * 2 CLIR suppression
- * <m>: integer type (parameter shows the subscriber CLIR / OIR service status in the network).
- * 0 CLIR / OIR not provisioned
- * 1 CLIR / OIR provisioned in permanent mode
- * 2 unknown (e.g. no network, etc.)
- * 3 CLIR / OIR temporary mode presentation restricted
- * 4 CLIR / OIR temporary mode presentation allowed
- *
- * see RIL_REQUEST_SET_CLIR or RIL_REQUEST_GET_CLIR in RIL
- */
-void SupService::HandleCLIR(const Client& client, std::string& command) {
- std::vector<std::string> responses;
- std::stringstream ss;
-
- CommandParser cmd(command);
- cmd.SkipPrefix();
- if (*cmd == "AT+CLIR?") {
- ss << "+CLIR:" << clir_status_.type << "," << clir_status_.status;
- responses.push_back(ss.str());
- } else {
- clir_status_.type = (ClirStatusInfo::ClirType)cmd.GetNextInt();
- }
- responses.push_back("OK");
- client.SendCommandResponse(responses);
-}
-
-/**
- * AT+CLIP
- * This command refers to the supplementary service CLIP (Calling Line
- * Identification Presentation) according to 3GPP TS 22.081 [3] and OIP
- * (Originating Identification Presentation) according to 3GPP TS 24.607 [119]
- * that enables a called subscriber to get the calling line identity (CLI) of
- * the calling party when receiving a mobile terminated call.
- *
- * Command Possible response(s)
- * +CLIP? +CLIP: <n>,<m>
- *
- * <n>: integer type (parameter sets/shows the result code presentation status to the TE).
- * 0 disable
- * 1 enable
- * <m>: integer type (parameter shows the subscriber CLIR / OIR service status in the network).
- * 0 CLIP / OIP not provisioned
- * 1 CLIP / OIP provisioned
- * 2 unknown (e.g. no network, etc.)
- *
- * see RIL_REQUEST_QUERY_CLIP in RIL
- */
-void SupService::HandleCLIP(const Client& client) {
- std::vector<std::string> responses = {"+CLIP: 0, 0", "OK"};
- client.SendCommandResponse(responses);
-}
-
-/**
- * AT+CSSN
- * This command refers to supplementary service related network initiated
- * notifications. The set command enables/disables the presentation of
- * notification result codes from TA to TE.
- *
- * Command Possible response(s)
- * +CSSN: [<n>[,<m>]]
- *
- * <n>: integer type (parameter sets/shows the +CSSI intermediate result code
- * presentation status to the TE)
- * 0 disable
- * 1 enable
- * <m>: integer type (parameter sets/shows the +CSSU unsolicited result code
- * presentation status to the TE)
- * 0 disable
- * 1 enable
- *
- * see RIL_REQUEST_SET_SUPP_SVC_NOTIFICATION in RIL
- */
-void SupService::HandleSuppServiceNotifications(const Client& client, std::string& /*command*/) {
- client.SendCommandResponse("OK");
-}
-
-/**
- * AT+CCFCU
- * The command allows control of the communication forwarding supplementary service
- * according to 3GPP TS 22.072 [31], 3GPP TS 22.082 [4] and 3GPP TS 24.604 [132].
- *
- * Command Possible response(s)
- * +CCFCU=<reason>,<mode> +CME ERROR: <err>
- * [,<numbertype>,<ton>,<number> when <mode>=2 and command successful:
- * [,<class>,<ruleset> +CCFCU: <status>,<class1>[,<numbertype>,
- * [,<subaddr>[,<satype>[,<time>]]]]] <ton>,<number>[,<subaddr>,<satype>[,<time>]]]
- * [,<class>,<ruleset>
- *
- * see SupService::CallForwardInfo
- *
- * see RIL_REQUEST_SET_CALL_FORWARD or RIL_REQUEST_QUERY_CALL_FORWARD_STATUS in RIL
- */
-void SupService::HandleCallForward(const Client& client, std::string& command) {
- std::vector<std::string> responses;
- std::stringstream ss;
-
- CommandParser cmd(command);
- cmd.SkipPrefix();
-
- int reason = cmd.GetNextInt();
- int status = cmd.GetNextInt();
- int number_type = cmd.GetNextInt();
- int ton = cmd.GetNextInt();
- std::string_view number = cmd.GetNextStr();
- int classx = cmd.GetNextInt();
-
- switch (reason) {
- case CallForwardInfo::Reason::ALL_CF: {
- if (status == CallForwardInfo::CallForwardInfoStatus::INTERROGATE) {
- auto iter = call_forward_infos_.begin();
- for (; iter != call_forward_infos_.end(); ++iter) {
- ss.clear();
- ss << "+CCFCU: " << iter->status << "," << classx << "," << number_type
- << "," << ton << ",\"" << iter->number << "\"";
- if (iter->reason == CallForwardInfo::Reason::CFNR) {
- ss << ",,," << iter->timeSeconds;
- }
- responses.push_back(ss.str());
- ss.str("");
- }
- }
- break;
- }
- case CallForwardInfo::Reason::CFU:
- case CallForwardInfo::Reason::CFB:
- case CallForwardInfo::Reason::CFNR:
- case CallForwardInfo::Reason::CFNRC: {
- if (status == CallForwardInfo::CallForwardInfoStatus::INTERROGATE) {
- ss << "+CCFCU: " << call_forward_infos_[reason].status
- << "," << classx << "," << number_type << "," << ton << ",\""
- << call_forward_infos_[reason].number << "\"";
- if (reason == CallForwardInfo::Reason::CFNR) {
- ss << ",,," << call_forward_infos_[reason].timeSeconds;
- }
- responses.push_back(ss.str());
- } else {
- if (status == CallForwardInfo::CallForwardInfoStatus::REGISTRATION) {
- call_forward_infos_[reason].status
- = CallForwardInfo::CallForwardInfoStatus::ENABLE;
- } else {
- call_forward_infos_[reason].status =
- (CallForwardInfo::CallForwardInfoStatus)status;
- }
- call_forward_infos_[reason].number_type = number_type;
- call_forward_infos_[reason].ton = ton;
- call_forward_infos_[reason].number = number;
- if (reason == CallForwardInfo::Reason::CFNR) {
- cmd.SkipComma();
- cmd.SkipComma();
- cmd.SkipComma();
- int timeSeconds = cmd.GetNextInt();
- call_forward_infos_[reason].timeSeconds = timeSeconds >= 0 ? timeSeconds : 0;
- }
- }
- break;
- }
- default:
- client.SendCommandResponse(kCmeErrorInCorrectParameters);
- return;
- }
-
- responses.push_back("OK");
- client.SendCommandResponse(responses);
-}
-
-/**
- * AT+CCWA
- * This command allows control of the supplementary service Call Waiting
- * according to 3GPP TS 22.083 [5] and Communication Waiting according to
- * 3GPP TS 24.607 [137]. Activation, deactivation and status query are supported.
- *
- * Command Possible response(s)
- * +CCWA=[<n>[,<mode>[,<class>]]] +CME ERROR: <err>
- * when <mode>=2 and command successful
- +CCWA: <status>,<class1>
- [<CR><LF>+CCWA: <status>,<class2>
- * <n>: integer type (sets/shows the result code presentation status to the TE).
- * 0 disable
- * 1 enable
- * <mode>: integer type (when <mode> parameter is not given, network is not interrogated).
- * 0 disable
- * 1 enable
- * 2 query status
- * <classx>: a sum of integers each representing a class of information
- * (default 7 - voice, data and fax).
- * <status>: integer type
- * 0 not active
- * 1 active
- *
- * see RIL_REQUEST_QUERY_CALL_WAITING and RIL_REQUEST_SET_CALL_WAITING in RIL
- */
-void SupService::HandleCallWaiting(const Client& client, std::string& command) {
- std::vector<std::string> responses;
- std::stringstream ss;
-
- CommandParser cmd(command);
- cmd.SkipPrefix();
- cmd.SkipComma();
- int mode = cmd.GetNextInt();
- int classx = cmd.GetNextInt();
-
- if (mode == 2) { // Query
- if (classx == -1) {
- classx = 7;
- }
- ss << "+CCWA: " << call_waiting_info_.mode << "," << classx;
- responses.push_back(ss.str());
- } else if (mode == 0 || mode == 1) { // Enable or disable
- call_waiting_info_.mode = mode;
- if (classx != -1) {
- call_waiting_info_.classx = classx;
- }
- }
-
- responses.push_back("OK");
- client.SendCommandResponse(responses);
-}
-
-} // namespace cuttlefish
diff --git a/host/commands/modem_simulator/sup_service.h b/host/commands/modem_simulator/sup_service.h
deleted file mode 100644
index f7be4479a..000000000
--- a/host/commands/modem_simulator/sup_service.h
+++ /dev/null
@@ -1,108 +0,0 @@
-//
-// Copyright (C) 2020 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 "host/commands/modem_simulator/modem_service.h"
-
-namespace cuttlefish {
-
-class SupService : public ModemService, public std::enable_shared_from_this<SupService> {
- public:
- SupService(int32_t service_id, ChannelMonitor* channel_monitor,
- ThreadLooper* thread_looper);
- ~SupService() = default;
-
- SupService(const SupService &) = delete;
- SupService &operator=(const SupService &) = delete;
-
- void HandleUSSD(const Client& client, std::string& command);
- void HandleCLIR(const Client& client, std::string& command);
- void HandleCallWaiting(const Client& client, std::string& command);
- void HandleCLIP(const Client& client);
- void HandleCallForward(const Client& client, std::string& command);
- void HandleSuppServiceNotifications(const Client& client, std::string& command);
-
- private:
- std::vector<CommandHandler> InitializeCommandHandlers();
- void InitializeServiceState();
-
- struct ClirStatusInfo {
- enum ClirType {
- DEFAULT = 0, // "use subscription default value"
- CLIR_INVOCATION = 1, // restrict CLI presentation
- CLIR_SUPPRESSION = 2, // allow CLI presentation
- };
-
- enum ClirStatus {
- CLIR_NOT_PROVISIONED = 0,
- CLIR_PROVISIONED = 1,
- UNKNOWN = 2,
- CLIR_PRESENTATION_RESTRICTED = 3,
- CLIR_PRESENTATION_ALLOWED = 4,
- };
-
- ClirType type;
- ClirStatus status;
- };
- ClirStatusInfo clir_status_;
-
- struct CallForwardInfo {
- enum CallForwardInfoStatus {
- DISABLE = 0,
- ENABLE = 1,
- INTERROGATE = 2,
- REGISTRATION = 3,
- ERASURE = 4,
- };
-
- enum Reason {
- CFU = 0, // communication forwarding unconditional
- CFB = 1, //communication forwarding on busy user
- CFNR = 2, // communication forwarding on no reply
- CFNRC = 3, // communication forwarding on subscriber not reachable
- ALL_CF = 4, // all call forwarding
- ALL_CONDITIONAL_CF = 5, //all conditional call forwarding
- CD = 6, // communication deflection
- CFNL = 7, // communication forwarding on not logged-in
- };
-
- CallForwardInfoStatus status;
- Reason reason;
- int number_type; // From 27.007 +CCFC/+CLCK "class"
- int ton; // "type" from TS 27.007 7.11
- std::string number; // "number" from TS 27.007 7.11. May be NULL
- int timeSeconds; // for CF no reply only
-
- CallForwardInfo(Reason reason) :
- status(DISABLE), reason(reason), number_type(2), ton(129), number(""),
- timeSeconds(0){};
- };
- std::vector<CallForwardInfo> call_forward_infos_;
-
- struct CallWaitingInfo {
- int presentation_status; // sets / shows the result code presentation status to the TE,
- // 0: disable; 1: enable
- int mode; // 0: disable; 1: enable; 2: query status
- int classx; // a sum of integers each representing a class of information
- // default 7-voice, data and fax, see FacilityLock::Class
-
- CallWaitingInfo() :
- presentation_status(1), mode(0), classx(7) {};
- };
- CallWaitingInfo call_waiting_info_;
-};
-
-} // namespace cuttlefish
diff --git a/host/commands/modem_simulator/thread_looper.cpp b/host/commands/modem_simulator/thread_looper.cpp
deleted file mode 100644
index d9df9df2d..000000000
--- a/host/commands/modem_simulator/thread_looper.cpp
+++ /dev/null
@@ -1,130 +0,0 @@
-//
-// Copyright (C) 2020 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 "host/commands/modem_simulator/thread_looper.h"
-
-#include <android-base/logging.h>
-
-namespace cuttlefish {
-
-ThreadLooper::ThreadLooper()
- : stopped_(false), next_serial_(1) {
- looper_thread_ = std::thread([this]() { ThreadLoop(); });
-}
-
-ThreadLooper::~ThreadLooper() { Stop(); }
-
-bool ThreadLooper::Event::operator<=(const Event &other) const {
- return when <= other.when;
-}
-
-ThreadLooper::Serial ThreadLooper::Post(Callback cb) {
- CHECK(cb != nullptr);
-
- auto serial = next_serial_++;
- // If it's the time to process event with delay exactly when posting
- // a event without delay. Looper would process the event without delay firstly
- // if when set to be std::nullptr. so set when_ to be now.
- Insert({ std::chrono::steady_clock::now(), cb, serial });
-
- return serial;
-}
-
-ThreadLooper::Serial ThreadLooper::PostWithDelay(
- std::chrono::steady_clock::duration delay, Callback cb) {
- CHECK(cb != nullptr);
-
- auto serial = next_serial_++;
- Insert({ std::chrono::steady_clock::now() + delay, cb, serial });
-
- return serial;
-}
-
-bool ThreadLooper::CancelSerial(Serial serial) {
- std::lock_guard<std::mutex> autolock(lock_);
-
- bool found = false;
- for (auto iter = queue_.begin(); iter != queue_.end(); ++iter) {
- if (iter->serial == serial) {
- queue_.erase(iter);
- cond_.notify_all();
-
- found = true;
- break;
- }
- }
-
- return found;
-}
-
-void ThreadLooper::Insert(const Event &event) {
- std::lock_guard<std::mutex> autolock(lock_);
-
- auto iter = queue_.begin();
- while (iter != queue_.end() && *iter <= event) {
- ++iter;
- }
-
- queue_.insert(iter, event);
- cond_.notify_all();
-}
-
-void ThreadLooper::ThreadLoop() {
- for(;;) {
- Callback cb;
- {
- std::unique_lock<std::mutex> lock(lock_);
-
- if (stopped_) {
- break;
- }
-
- if (queue_.empty()) {
- cond_.wait(lock);
- continue;
- }
-
- auto time_to_wait = queue_.front().when - std::chrono::steady_clock::now();
- if (time_to_wait.count() > 0) {
- // wait with timeout
- auto durationMs =
- std::chrono::duration_cast<std::chrono::milliseconds>(time_to_wait);
- cond_.wait_for(lock, durationMs);
- continue;
- }
- cb = queue_.front().cb; // callback at front of queue
- queue_.pop_front();
- }
- cb();
- }
-}
-
-void ThreadLooper::Stop() {
- if (stopped_) {
- return;
- }
- CHECK(looper_thread_.get_id() != std::this_thread::get_id())
- << "Destructor called from looper thread";
- {
- std::lock_guard<std::mutex> autolock(lock_);
- stopped_ = true;
- }
- cond_.notify_all();
- if (looper_thread_.joinable()) {
- looper_thread_.join();
- }
-}
-
-} // namespace cuttlefish
diff --git a/host/commands/modem_simulator/thread_looper.h b/host/commands/modem_simulator/thread_looper.h
deleted file mode 100644
index dbfd20107..000000000
--- a/host/commands/modem_simulator/thread_looper.h
+++ /dev/null
@@ -1,92 +0,0 @@
-//
-// Copyright (C) 2020 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 <atomic>
-#include <chrono>
-#include <condition_variable>
-#include <deque>
-#include <functional>
-#include <mutex>
-#include <thread>
-
-namespace cuttlefish {
-
-template <typename T>
-std::function<void()> makeSafeCallback(T *me, std::function<void(T *)> f) {
- return [f, me] {
- if (me) {
- f(me);
- }
- };
-}
-
-template<typename T, typename... Params>
-std::function<void()> makeSafeCallback(
- T *obj, void (T::*f)(const Params&...), const Params&... params) {
- return makeSafeCallback<T>(obj,
- [f, params...](T *me) { (me->*f)(params...); });
-}
-
-template<typename T, typename... Params>
-std::function<void()> makeSafeCallback(
- T *obj, void (T::*f)(Params...), const Params&... params) {
- return makeSafeCallback<T>(obj,
- [f, params...](T *me) { (me->*f)(params...); });
-}
-
-class ThreadLooper {
- public:
- ThreadLooper();
- ~ThreadLooper();
-
- ThreadLooper(const ThreadLooper &) = delete;
- ThreadLooper &operator=(const ThreadLooper &) = delete;
-
- typedef std::function<void()> Callback;
- typedef int32_t Serial;
-
- Serial Post(Callback cb);
- Serial PostWithDelay(std::chrono::steady_clock::duration delay, Callback cb);
-
- void Stop();
-
- // Returns true if matching event was canceled.
- bool CancelSerial(Serial serial);
-
- private:
- struct Event {
- std::chrono::steady_clock::time_point when;
- Callback cb;
- Serial serial;
-
- bool operator<=(const Event &other) const;
- };
-
- bool stopped_;
- std::thread looper_thread_;
-
- std::mutex lock_;
- std::condition_variable cond_;
- std::deque<Event> queue_;
- std::atomic<Serial> next_serial_;
-
- void ThreadLoop();
-
- void Insert(const Event &event);
-};
-
-}; // namespace cuttlefish
diff --git a/host/commands/modem_simulator/unittest/command_parser_test.cpp b/host/commands/modem_simulator/unittest/command_parser_test.cpp
deleted file mode 100644
index 6d53fed39..000000000
--- a/host/commands/modem_simulator/unittest/command_parser_test.cpp
+++ /dev/null
@@ -1,103 +0,0 @@
-//
-// Copyright (C) 2020 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 "host/commands/modem_simulator/command_parser.h"
-
-#include <gtest/gtest.h>
-
-TEST(CommandParserUnitTest, SkipPrefix) {
- std::string command = "AT+SPUSATENVECMD=\"D3078202018190014E\"";
-
- cuttlefish::CommandParser cmd(command);
- cmd.SkipPrefix();
- std::string result(*cmd);
- ASSERT_STREQ("\"D3078202018190014E\"", result.c_str());
-}
-
-TEST(CommandParserUnitTest, SkipPrefixAT) {
- std::string command = "AT+SPUSATENVECMD=\"D3078202018190014E\"";
-
- cuttlefish::CommandParser cmd(command);
- cmd.SkipPrefixAT();
- std::string result(*cmd);
- ASSERT_STREQ("+SPUSATENVECMD=\"D3078202018190014E\"", result.c_str());
-}
-
-TEST(CommandParserUnitTest, SkipComma) {
- std::string command = "+COPS: 0,1,\"CMCC\",7";
-
- cuttlefish::CommandParser cmd(command);
- cmd.SkipComma();
- std::string result(*cmd);
- ASSERT_STREQ("1,\"CMCC\",7", result.c_str());
-}
-
-TEST(CommandParserUnitTest, SkipWhiteSpace) {
- std::string command = "+COPS: 0,1,\"CMCC\",7";
- cuttlefish::CommandParser cmd(command);
-
- cmd.GetNextStr(':');
- cmd.SkipWhiteSpace();
- std::string result(*cmd);
- ASSERT_STREQ("0,1,\"CMCC\",7", result.c_str());
-}
-
-TEST(CommandParserUnitTest, GetNextStr_default) {
- std::string command = "+COPS: 0,1,\"CMCC\",7";
-
- cuttlefish::CommandParser cmd(command);
- std::string result(cmd.GetNextStr());
- ASSERT_STREQ("CMCC", result.c_str());
-}
-
-TEST(CommandParserUnitTest, GetNextStr_withparam) {
- std::string command = "+COPS: 0,1,\"CMCC\",7";
-
- cuttlefish::CommandParser cmd(command);
- std::string result(cmd.GetNextStr(','));
- ASSERT_STREQ("+COPS: 0", result.c_str());
-
- std::string result2(cmd.GetNextStr(';'));
- ASSERT_STREQ("1,\"CMCC\",7", result2.c_str());
-}
-
-TEST(CommandParserUnitTest, GetNextInt) {
- std::string command = "AT+CRSM=192,28421,0,0,15,0,\"3F007FFF\"";
-
- cuttlefish::CommandParser cmd(command);
- cmd.SkipPrefix(); // skip "AT+CRSM="
- ASSERT_EQ(192, cmd.GetNextInt());
- ASSERT_EQ(28421, cmd.GetNextInt());
-}
-
-TEST(CommandParserUnitTest, GetNextHexInt) { // Hexadecimal string to decimal value
- std::string command = "C0,6F05";
-
- cuttlefish::CommandParser cmd(command);
- ASSERT_EQ(192, cmd.GetNextHexInt());
- ASSERT_EQ(28421, cmd.GetNextHexInt());
-}
-
-TEST(CommandParserUnitTest, GetNextStrDeciToHex) {
- std::string command = "AT+CRSM=192,28421,0,0,15,0,\"3F007FFF\"";
-
- cuttlefish::CommandParser cmd(command);
- cmd.SkipPrefix();
- std::string result(cmd.GetNextStrDeciToHex());
- ASSERT_STREQ("C0", result.c_str()); // 192
-
- std::string result2(cmd.GetNextStrDeciToHex());
- ASSERT_STREQ("6F05", result2.c_str()); // 28421
-}
diff --git a/host/commands/modem_simulator/unittest/iccfile.txt b/host/commands/modem_simulator/unittest/iccfile.txt
deleted file mode 100755
index 48e2a0272..000000000
--- a/host/commands/modem_simulator/unittest/iccfile.txt
+++ /dev/null
@@ -1,176 +0,0 @@
-R"(<IccProfile>
-<MF path="3F00">
- <EF name="EF_DIR" id="2F00" structure="linear fixed">
- <SIMIO cmd="C0" p1="0" p2="0" p3="F" data="">144,0,621A8205422100300483022F008A01058B032F0601800200C08801F0</SIMIO>
- <SIMIO cmd="B2" p1="1" p2="4" p3="30" data="">144,0,61184F10A0000003431002FF86FF0389FFFFFFFF50044353494DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="2" p2="4" p3="30" data="">144,0,61184F10A0000000871002FF86FF0389FFFFFFFF50045553494DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="3" p2="4" p3="30" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="4" p2="4" p3="30" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- </EF>
- <EF name="EF_ICCID" id="2FE2" structure="transparent">
- <SIMIO cmd="C0" p1="0" p2="0" p3="F" data="">144,0,62178202412183022FE28A01058B032F06038002000A880110</SIMIO>
- <SIMIO cmd="B0" p1="0" p2="0" p3="A" data="">144,0,98683081462002318379</SIMIO>
- <!-- Special ATC to read ICCID from modem cache -->
- <CCID>89860318640220133897</CCID>
- </EF>
- <EF name="EF_PL" id="2F05" structure="transparent">
- <SIMIO cmd="C0" p1="0" p2="0" p3="F" data="">144,0,62178202412183022F058A01058B032F060280020004880128</SIMIO>
- <SIMIO cmd="B0" p1="0" p2="0" p3="4" data="">144,0,FFFFFFFF</SIMIO>
- </EF>
-
- <DF name="TELECOM" path="7F10">
- <DF name="PHONEBOOK" path="5F3A">
- <EF name="EF_PBR" id="4F30" structure="linear fixed">
- <SIMIO cmd="C0" p1="0" p2="0" p3="F" data="">144,0,62198205422100400283024F308A01058B036F0606800200808800</SIMIO>
- <SIMIO cmd="B2" p1="1" p2="4" p3="40" data="">144,0,A81EC0034F3A01C1034F3306C5034F0902C4034F1104C6034F2503C9034F3107A905CA034F5008AA0FC2034F4A09C7034F4B0AC8034F4C0BFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="2" p2="4" p3="40" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- </EF>
- <EF name="EF_GAS" id="4F4C" structure="linear fixed">
- <SIMIO cmd="C0" p1="0" p2="0" p3="F" data="">144,0,621A8205422100140A83024F4C8A01058B036F060E800200C8880158</SIMIO>
- <SIMIO cmd="B2" p1="1" p2="4" p3="E" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="2" p2="4" p3="E" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="3" p2="4" p3="E" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="4" p2="4" p3="E" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="5" p2="4" p3="E" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="6" p2="4" p3="E" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="7" p2="4" p3="E" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="8" p2="4" p3="E" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="9" p2="4" p3="E" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="A" p2="4" p3="E" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- </EF>
- <EF name="EF_ADN" id="4F3A" structure="linear fixed">
- <SIMIO cmd="C0" p1="0" p2="0" p3="F" data="">144,0,621A82054221001C1483024F3A8A01058B036F060E80020230880108</SIMIO>
- <SIMIO cmd="B2" p1="1" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="2" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="3" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="4" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="5" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="6" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="7" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="8" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="9" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="A" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="B" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="C" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="D" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="E" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="F" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="10" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="11" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="12" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="13" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="14" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- </EF>
- <EF name="EF_IAP" id="4F33" structure="linear fixed">
- <SIMIO cmd="C0" p1="0" p2="0" p3="F" data="">144,0,621A820542210001FA83024F338A01058B036F060E800200FA880130</SIMIO>
- </EF>
- <EF name="EF_PBC" id="4F09" structure="linear fixed">
- <SIMIO cmd="C0" p1="0" p2="0" p3="F" data="">144,0,621A820542210002FA83024F098A01058B036F060E800201F4880110</SIMIO>
- </EF>
- <EF name="EF_ANR" id="4F11" structure="linear fixed">
- <SIMIO cmd="C0" p1="0" p2="0" p3="F" data="">144,0,621A82054221000FFA83024F118A01058B036F060E80020EA6880120</SIMIO>
- </EF>
- <!-- EF_SNE, EF_AAS, EF_EXT1, EF_GRP, EF_UID, EF_EMAIL, EF_CCP1, EF_PUR1 ... -->
- </DF>
- </DF>
-
- <ADF name="USIM" path="7FFF" aid="A0000000871002FF86FF0389FFFFFFFF">
- <EF name="EF_IMSI" id="6F07" structure="transparent">
- <CIMI>460110031689666</CIMI>
- </EF>
- <EF name="EF_MSISDN" id="6F40" structure="linear fixed">
- <SIMIO cmd="C0" p1="0" p2="0" p3="F" data="">144,0,621982054221001C0283026F408A01058B036F0605800200388800</SIMIO>
- <SIMIO cmd="B2" p1="1" p2="4" p3="1C" data="">144,0,00000000000000000000000000000891688118109844F0FFFFFFFFFF</SIMIO>
- </EF>
- <EF name="EF_MBI" id="6FC9" structure="linear fixed">
- <SIMIO cmd="C0" p1="0" p2="0" p3="F" data="">106,130</SIMIO>
- </EF>
- <EF name="EF_AD" id="6FAD" structure="transparent">
- <SIMIO cmd="C0" p1="0" p2="0" p3="F" data="">144,0,62178202412183026FAD8A01058B036F060180020004880118</SIMIO>
- <SIMIO cmd="B0" p1="0" p2="0" p3="4" data="">144,0,00000002</SIMIO>
- </EF>
- <EF name="EF_MWIS" id="6FCA" structure="linear fixed">
- <SIMIO cmd="C0" p1="0" p2="0" p3="F" data="">144,0,62198205422100050183026FCA8A01058B036F060E800200058800</SIMIO>
- <SIMIO cmd="B2" p1="1" p2="4" p3="5" data="">144,0,0000000000</SIMIO>
- </EF>
- <EF name="EF_VOICE_MAIL_INDICATOR_CPHS" id="6F11" structure="transparent">
- <SIMIO cmd="C0" p1="0" p2="0" p3="F" data="">106,130</SIMIO>
- </EF>
- <EF name="EF_FPLMN" id="6F7B" structure="transparent">
- <SIMIO cmd="C0" p1="0" p2="0" p3="F" data="">144,0,621C8202412183026F7BA5038001718A01058B036F06038002001E880168</SIMIO>
- <SIMIO cmd="B0" p1="0" p2="0" p3="1E" data="">144,0,64F00064F02064F04064F07064F080FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- </EF>
- <EF name="EF_FDN" id="6F3B" structure="linear fixed">
- <SIMIO cmd="C0" p1="0" p2="0" p3="F" data="">144,0,621982054221001C0A83026F3B8A01058B036F0605800201188800</SIMIO>
- <SIMIO cmd="B2" p1="1" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="2" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="3" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="4" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="5" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="6" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="7" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="8" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="9" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- <SIMIO cmd="B2" p1="A" p2="4" p3="1C" data="">144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</SIMIO>
- </EF>
- <!-- Other USIM files... -->
- </ADF>
-</MF>
-
-<ADF name="PKCS15" aid="A000000063504B43532D3135">
- <CGLA cmd="A40004025031">4,6124</CGLA>
- <CGLA cmd="C0000024">76,62228202412183025031A503C001408A01058B066F0601010001800200108102002288009000 </CGLA>
- <CGLA cmd="B0000010">36,A706300404024401A5063004040244029000</CGLA>
-</ADF>
-
-<ADF name="" aid="">
- <CSIM cmd='10,"0070000001"'>6,019000</CSIM>
- <CGLA cmd='1,14,"81F2FF0000"'>4,6b00</CGLA>
- <!-- more CGLA Command -->
-</ADF>
-
-<PinProfile>
- <!-- PIN: PINSTATE_ENABLED_NOT_VERIFIED -->
- <!-- PUK: PINSTATE_ENABLED_BLOCKED -->
- <!-- Ready: PINSTATE_UNKNOWN -->
- <PINSTATE>PINSTATE_UNKNOWN</PINSTATE>
- <PINCODE>1234</PINCODE>
- <PUKCODE>12345678</PUKCODE>
- <PINREMAINTIMES>3</PINREMAINTIMES>
- <PUKREMAINTIMES>10</PUKREMAINTIMES>
- <PIN2CODE>1234</PIN2CODE>
- <PUK2CODE>12345678</PUK2CODE>
- <PIN2REMAINTIMES>3</PIN2REMAINTIMES>
- <PUK2REMAINTIMES>10</PUK2REMAINTIMES>
-</PinProfile>
-
-<FacilityLock>
- <SC>DISABLE</SC>
- <FD>DISABLE</FD>
- <AO>DISABLE</AO>
- <OI>DISABLE</OI>
- <AI>DISABLE</AI>
- <IR>DISABLE</IR>
- <AB>DISABLE</AB>
- <AG>DISABLE</AG>
- <AC>DISABLE</AC>
-</FacilityLock>
-
-<SETUPMENU cmd="25" text="D0388103012500820281820509804E2D56FD79FB52A88F10508000530049004D5FEB6377786E8BA48F104E80005500530049004D53614FE1606F">
- <SELECTITEM id="1" cmd="24" menuId="50" text="D02D8103012400820281828F0A018053E34EE48BBE7F6E8F0A02804E1A52A14ECB7ECD8F0A0380724867434FE1606F">
- <SELECTITEM id="1" cmd="24" menuId="01" text="D0218103012400820281828F0A01806DFB52A083DC53558F0A02805220966483DC5355">
- <DISPLAYTEXT id="1" cmd="21" menuId="01" text="D0228103012181820281028D1708662F542666F465B04E0B8F7D83DC535552178868FF1F"></DISPLAYTEXT>
- <DISPLAYTEXT id="2" cmd="21" menuId="02" text="D01A8103012101820281028D0F0883DC5355522096646210529FFF01"></DISPLAYTEXT>
- </SELECTITEM>
- <DISPLAYTEXT id="2" cmd="21" menuId="02" text="D081BB8103012181820281028D81AF08201C00530049004D5FEB6377786E8BA4201D662F4E2D56FD79FB52A863D04F9B7684FF0C57FA4E8E624B673A00530049004D53617684727982725B8951688EAB4EFD8BA48BC1670D52A1300276F86BD44F207EDF75286237540D5BC678018BA48BC165B95F0FFF0C5B83517767094E0D53EF62E6622A30014E0D4F208F935BC6780130014F7F75285FEB63777B49727970B9FF0C662F60A87545884C4E9280547F5176848EAB4EFD536B58EB3002"></DISPLAYTEXT>
- <DISPLAYTEXT id="3" cmd="21" menuId="03" text="D02E8103012181820281028D23084E2D56FD79FB52A8901A4FE167099650516C53F8FF0C0031002E00307248672C3002">
- </DISPLAYTEXT>
- </SELECTITEM>
- <SELECTITEM id="2" cmd="24" menuId="4E" text="D04E810301240082028182850F80005500530049004D53614FE1606F8F0A0180536172477C7B578B8F14028075358BDD53F7780153CA77ED4FE15BB991CF8F100380004F00540041529F80FD4ECB7ECD">
- <DISPLAYTEXT id="1" cmd="21" menuId="01" text="D03A8103012181820281028D2F08666E901A005500530049004D5361002000560032002E003000410027FF0C652F6301004F005400410033529F80FD"></DISPLAYTEXT>
- <DISPLAYTEXT id="2" cmd="21" menuId="02" text="D05C8103012181820281028D510875358BDD53F77801672C5B5850A85BB991CF0035003000306761FF0C5DF2752875358BDD672C003100336761FF0C77ED4FE15B5850A85BB991CF003500306761FF0C5DF2752877ED4FE1003400396761"></DISPLAYTEXT>
- <DISPLAYTEXT id="3" cmd="21" menuId="03" text="D05E8103012181820281028D5308004F00540041529F80FD53EF5229752877ED4FE1606F901A9053FF0C5E2E52A95BA262375B9E73B0005500530049004D536151854E1A52A183DC5355768452A860014E0B8F7D3001522096644E0E66F465B0"></DISPLAYTEXT>
- </SELECTITEM>
-</SETUPMENU>
-
-</IccProfile>)"
diff --git a/host/commands/modem_simulator/unittest/pdu_parser_test.cpp b/host/commands/modem_simulator/unittest/pdu_parser_test.cpp
deleted file mode 100644
index 4129aa126..000000000
--- a/host/commands/modem_simulator/unittest/pdu_parser_test.cpp
+++ /dev/null
@@ -1,55 +0,0 @@
-//
-// Copyright (C) 2020 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 "host/commands/modem_simulator/pdu_parser.h"
-
-#include <gtest/gtest.h>
-
-TEST(PDUParserTest, IsValidPDU_true) {
- std::string pdu = "0001000D91688118109844F0000017AFD7903AB55A9BBA69D639D4ADCBF99E3DCCAE9701";
- cuttlefish::PDUParser smspdu(pdu);
- EXPECT_TRUE(smspdu.IsValidPDU());
-}
-
-TEST(PDUParserTest, IsValidPDU_false) {
- std::string pdu = "000100fD91688118109844F0000017AFD7903AB55A9BBA69D639D4ADCBF99E3DCCAE9701";
- cuttlefish::PDUParser smspdu(pdu);
- EXPECT_FALSE(smspdu.IsValidPDU());
-}
-
-TEST(PDUParserTest, CreatePDU) {
- std::string pdu = "0001000D91688118109844F0000017AFD7903AB55A9BBA69D639D4ADCBF99E3DCCAE9701";
- cuttlefish::PDUParser smspdu(pdu);
- EXPECT_TRUE(smspdu.IsValidPDU());
- std::string new_pdu = smspdu.CreatePDU();
- const char *expect = "";
- ASSERT_STRNE(new_pdu.c_str(), expect);
-}
-
-TEST(PDUParserTest, GetPhoneNumberFromAddress) {
- std::string pdu = "0001000D91688118109844F0000017AFD7903AB55A9BBA69D639D4ADCBF99E3DCCAE9701";
- cuttlefish::PDUParser smspdu(pdu);
- EXPECT_TRUE(smspdu.IsValidPDU());
- std::string phone_number = smspdu.GetPhoneNumberFromAddress();
- const char *expect = "18810189440";
- ASSERT_STREQ(phone_number.c_str(), expect);
-}
-
-TEST(PDUParserTest, BCDToString) {
- std::string value = "12345678";
- std::string process_value = cuttlefish::PDUParser::BCDToString(value);
- const char *expect = "21436587";
- ASSERT_STREQ(process_value.c_str(), expect);
-}
diff --git a/host/commands/modem_simulator/unittest/service_test.cpp b/host/commands/modem_simulator/unittest/service_test.cpp
deleted file mode 100644
index 58015864d..000000000
--- a/host/commands/modem_simulator/unittest/service_test.cpp
+++ /dev/null
@@ -1,774 +0,0 @@
-//
-// Copyright (C) 2020 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 <android-base/logging.h>
-#include <gtest/gtest.h>
-#include <stdlib.h>
-
-#include <filesystem>
-#include <fstream>
-
-#include "common/libs/fs/shared_select.h"
-#include "common/libs/utils/files.h"
-#include "host/commands/modem_simulator/channel_monitor.h"
-#include "host/commands/modem_simulator/modem_simulator.h"
-#include "host/libs/config/cuttlefish_config.h"
-namespace fs = std::filesystem;
-
-static const char *myiccfile =
-#include "iccfile.txt"
- ;
-
-static const std::string tmp_test_dir = std::string(fs::temp_directory_path()) +
- std::string("/cuttlefish_modem_test");
-using namespace cuttlefish;
-
-class ModemServiceTest : public ::testing::Test {
- protected:
- static void SetUpTestSuite() {
- {
- cuttlefish::CuttlefishConfig tmp_config_obj;
- std::string config_file = tmp_test_dir + "/.cuttlefish_config.json";
- std::string instance_dir = tmp_test_dir + "/cuttlefish_runtime.1";
- fs::create_directories(instance_dir);
- tmp_config_obj.set_ril_dns("8.8.8.8");
- std::vector<int> instance_nums;
- for (int i = 0; i < 1; i++) {
- instance_nums.push_back(cuttlefish::GetInstance() + i);
- }
- for (const auto &num : instance_nums) {
- auto instance = tmp_config_obj.ForInstance(num);
- instance.set_instance_dir(instance_dir);
- }
-
- for (auto instance : tmp_config_obj.Instances()) {
- if (!tmp_config_obj.SaveToFile(
- instance.PerInstancePath("cuttlefish_config.json"))) {
- LOG(ERROR) << "Unable to save copy config object";
- return;
- }
- }
- fs::copy_file(instance_dir + "/cuttlefish_config.json", config_file,
- fs::copy_options::overwrite_existing);
- std::string icfilename = instance_dir + "/iccprofile_for_sim0.xml";
- std::ofstream offile(icfilename, std::ofstream::out);
- offile << std::string(myiccfile);
- offile.close();
-
- ::setenv("CUTTLEFISH_CONFIG_FILE", config_file.c_str(), 1);
- }
- cuttlefish::SharedFD ril_shared_fd, modem_shared_fd;
- if (!SharedFD::SocketPair(AF_LOCAL, SOCK_STREAM, 0, &ril_shared_fd,
- &modem_shared_fd)) {
- LOG(ERROR) << "Unable to create client socket pair: " << strerror(errno);
- }
- ASSERT_TRUE(ril_shared_fd->IsOpen());
- ASSERT_TRUE(modem_shared_fd->IsOpen());
-
- NvramConfig::InitNvramConfigService(1, 1);
-
- ril_side_ = new Client(ril_shared_fd);
- modem_side_ = new Client(modem_shared_fd);
- modem_simulator_ = new ModemSimulator(0);
-
- cuttlefish::SharedFD server;
- auto channel_monitor =
- std::make_unique<ChannelMonitor>(modem_simulator_, server);
- modem_simulator_->Initialize(std::move(channel_monitor));
- }
-
- static void TearDownTestSuite() {
- delete ril_side_;
- delete modem_side_;
- delete modem_simulator_;
- fs::remove_all(tmp_test_dir);
- };
-
- void SendCommand(std::string command, std::string prefix = "") {
- command_prefix_ = prefix;
- modem_simulator_->DispatchCommand(*modem_side_, command);
- }
-
- void ReadCommandResponse(std::vector<std::string>& response) {
- do {
- std::vector<char> buffer(4096); // kMaxCommandLength
- auto bytes_read = ril_side_->client_fd->Read(buffer.data(), buffer.size());
- if (bytes_read <= 0) {
- // Close here to ensure the other side gets reset if it's still
- // connected
- ril_side_->client_fd->Close();
- LOG(WARNING) << "Detected close from the other side";
- break;
- }
-
- std::string& incomplete_command = ril_side_->incomplete_command;
-
- // Add the incomplete command from the last read
- auto commands = std::string{incomplete_command.data()};
- commands.append(buffer.data());
-
- incomplete_command.clear();
- incomplete_command.resize(0);
-
- // replacing '\n' with '\r'
- commands = android::base::StringReplace(commands, "\n", "\r", true);
-
- // split into commands and dispatch
- size_t pos = 0, r_pos = 0; // '\r' or '\n'
- while (r_pos != std::string::npos) {
- r_pos = commands.find('\r', pos);
- if (r_pos != std::string::npos) {
- auto command = commands.substr(pos, r_pos - pos);
- if (command.size() > 0) { // "\r\r" ?
- LOG(DEBUG) << "AT< " << command;
- if (IsFinalResponseSuccess(command) || IsFinalResponseError(command)) {
- response.push_back(command);
- return;
- } else if (IsIntermediateResponse(command)) {
- response.push_back(command);
- } else {
- ; // Ignore unsolicited command
- }
- }
- pos = r_pos + 1; // skip '\r'
- } else if (pos < commands.length()) { // incomplete command
- incomplete_command = commands.substr(pos);
- LOG(VERBOSE) << "incomplete command: " << incomplete_command;
- }
- }
- } while (true);
-
- // read response
- }
-
- inline bool IsFinalResponseSuccess(std::string response) {
- auto iter = kFinalResponseSuccess.begin();
- for (; iter != kFinalResponseSuccess.end(); ++iter) {
- if (*iter == response) {
- return true;
- }
- }
-
- return false;
- }
-
- inline bool IsFinalResponseError(std::string response) {
- auto iter = kFinalResponseError.begin();
- for (; iter != kFinalResponseError.end(); ++iter) {
- if (response.compare(0, iter->size(), *iter) == 0) {
- return true;
- }
- }
-
- return false;
- }
-
- inline bool IsIntermediateResponse(std::string response) {
- if (response.compare(0, command_prefix_.size(), command_prefix_) == 0) {
- return true;
- }
-
- return false;
- }
-
- int openLogicalChannel(std::string& name) {
- // Create and send command
- std::string command = "AT+CCHO=";
- command.append(name);
- std::vector<std::string> response;
- SendCommand(command);
- ReadCommandResponse(response);
- int channel = std::stoi(response[0]);
- return channel;
- }
-
- bool closeLogicalChannel(int channel) {
- std::string command = "AT+CCHC=";
- command += std::to_string(channel);
- std::vector<std::string> response;
- SendCommand(command);
- ReadCommandResponse(response);
- std::string expect = "+CCHC";
- return (response[0].compare(0, expect.size(), expect) == 0);
- }
-
- const std::vector<std::string> kFinalResponseSuccess = {"OK", "CONNECT", "> "};
- const std::vector<std::string> kFinalResponseError = {
- "ERROR",
- "+CMS ERROR:",
- "+CME ERROR:",
- "NO CARRIER", /* sometimes! */
- "NO ANSWER",
- "NO DIALTONE",
- };
-
- static Client* ril_side_;
- static Client* modem_side_;
- static ModemSimulator* modem_simulator_;
-
- // For distinguishing the response from command response or unsolicited command
- std::string command_prefix_;
-};
-
-ModemSimulator* ModemServiceTest::modem_simulator_ = nullptr;
-Client* ModemServiceTest::ril_side_ = nullptr;
-Client* ModemServiceTest::modem_side_ = nullptr;
-
-/* Sim Service Test */
-TEST_F(ModemServiceTest, GetIccCardStatus) {
- const char *expects[] = {"+CPIN: READY",
- "OK"};
-
- std::string command = "AT+CPIN?";
- std::vector<std::string> response;
- SendCommand(command, "+CPIN:");
- ReadCommandResponse(response);
- ASSERT_EQ(response.size(), 2);
- ASSERT_STREQ(response[0].c_str(), expects[0]);
- ASSERT_STREQ(response[1].c_str(), expects[1]);
-}
-
-TEST_F(ModemServiceTest, ChangeOrEnterPIN) {
- std::vector<std::string> commands = {"AT+CPIN=1234,0000",
- "AT+CPIN=1111,2222",};
- std::vector<std::string> expects = {"OK",
- "+CME ERROR: 16",};
- std::vector<std::string> response;
- auto expects_iter = expects.begin();
- for (auto iter = commands.begin(); iter != commands.end(); ++iter, ++expects_iter) {
- SendCommand(*iter);
- ReadCommandResponse(response);
- ASSERT_STREQ(response[0].c_str(), (*expects_iter).c_str());
- response.clear();
- }
-}
-
-TEST_F(ModemServiceTest, SIM_IO) {
- std::vector<std::string> commands = {"AT+CRSM=192,12258,0,0,15",
- "AT+CRSM=192,28436,0,0,15",
- "AT+CRSM=220,28618,1,4,5,0000000000"};
- std::vector<std::string> expects = {"+CRSM: 144,0,62178202412183022FE28A01058B032F06038002000A880110",
- "+CRSM: 106,130",
- "+CRSM: 144,0"};
-
- std::vector<std::string> response;
- auto expects_iter = expects.begin();
- for (auto iter = commands.begin(); iter != commands.end(); ++iter, ++expects_iter) {
- SendCommand(*iter);
- ReadCommandResponse(response);
- ASSERT_EQ(response.size(), 2);
- ASSERT_STREQ(response[0].c_str(), (*expects_iter).c_str());
- response.clear();
- }
-}
-
-TEST_F(ModemServiceTest, GetIMSI) {
- std::string command = "AT+CIMI";
- std::vector<std::string> response;
- SendCommand(command);
- ReadCommandResponse(response);
- ASSERT_EQ(response.size(), 2);
- const char *expect = "460110031689666";
- ASSERT_STREQ(response[0].c_str(),expect);
-}
-
-TEST_F(ModemServiceTest, GetIccId) {
- std::string command = "AT+CICCID";
- std::vector<std::string> response;
- SendCommand(command);
- ReadCommandResponse(response);
- ASSERT_EQ(response.size(), 2);
- const char *expect = "89860318640220133897";
- ASSERT_STREQ(response[0].c_str(),expect);
-}
-
-TEST_F(ModemServiceTest, FacilityLock) {
- std::vector<std::string> commands =
- { "AT+CLCK=\"FD\",2,"",7",
- "AT+CLCK=\"SC\",2,"",7",
- "AT+CLCK=\"SC\",1,\"1234\",7",
- "AT+CLCK=\"SC\",1,\"023000\",7"
- };
- std::vector<std::string> expects =
- { "+CLCK: 0",
- "+CLCK: 0",
- "+CME ERROR: 16",
- "+CME ERROR: 16"
- };
- std::vector<std::string> response;
- auto expects_iter = expects.begin();
- for (auto iter = commands.begin(); iter != commands.end(); ++iter, ++expects_iter) {
- SendCommand(*iter);
- ReadCommandResponse(response);
- ASSERT_STREQ(response[0].c_str(), (*expects_iter).c_str());
- response.clear();
- }
-}
-
-TEST_F(ModemServiceTest, OpenLogicalChannel) {
- std::string command= "A000000063504B43532D3135";
- int firstChannel = openLogicalChannel(command);
- ASSERT_EQ(firstChannel, 1);
-
- command= "A000000063504B43532D3135";
- int secondChannel = openLogicalChannel(command);
- ASSERT_GE(secondChannel, 1);
-
- closeLogicalChannel(firstChannel);
- closeLogicalChannel(secondChannel);
-}
-
-TEST_F(ModemServiceTest, CloseLogicalChannel) {
- std::string command= "A000000063504B43532D3135";
- int channel = openLogicalChannel(command);
- ASSERT_EQ(channel, 1);
-
- ASSERT_FALSE(closeLogicalChannel(channel + 3));
- ASSERT_TRUE(closeLogicalChannel(channel));
-}
-
-TEST_F(ModemServiceTest, TransmitLogicalChannel) {
- std::string command= "A000000063504B43532D3135";
- int channel = openLogicalChannel(command);
- ASSERT_EQ(channel, 1);
- command = "AT+CGLA=";
- command += channel;
- command += ",10,80caff4000";
- std::vector<std::string> response;
- SendCommand(command);
- ReadCommandResponse(response);
- const char *expect = "+CME ERROR: 21";
- ASSERT_STREQ(response[0].c_str(),expect);
- ASSERT_TRUE(closeLogicalChannel(channel));
-}
-
-/* Network Service Test */
-TEST_F(ModemServiceTest, testRadioPowerReq) {
- std::string command = "AT+CFUN?";
- std::vector<std::string> response;
- SendCommand(command, "+CFUN:");
- ReadCommandResponse(response);
- ASSERT_EQ(response.size(), 2);
- ASSERT_STREQ(response[response.size() - 1].c_str(), kFinalResponseSuccess[0].c_str());
-}
-
-TEST_F(ModemServiceTest, testSetRadioPower) {
- std::string command = "AT+CFUN=1";
- std::vector<std::string> response;
- SendCommand(command);
- ReadCommandResponse(response);
- ASSERT_EQ(response.size(), 1);
- ASSERT_STREQ(response[response.size() - 1].c_str(), kFinalResponseSuccess[0].c_str());
-}
-
-TEST_F(ModemServiceTest, testSignalStrength) {
- std::string command = "AT+CSQ";
- std::vector<std::string> response;
- SendCommand(command, "+CSQ:");
- ReadCommandResponse(response);
- ASSERT_EQ(response.size(), 2);
- ASSERT_STREQ(response[response.size() - 1].c_str(), kFinalResponseSuccess[0].c_str());
-}
-
-TEST_F(ModemServiceTest, testQueryNetworkSelectionMode) {
- std::string command = "AT+COPS?";
- std::vector<std::string> response;
- SendCommand(command, "+COPS:");
- ReadCommandResponse(response);
- ASSERT_EQ(response.size(), 2);
- ASSERT_STREQ(response[response.size() - 1].c_str(), kFinalResponseSuccess[0].c_str());
-}
-
-TEST_F(ModemServiceTest, testRequestOperator) {
- std::string command = "AT+COPS=3,0;+COPS?;+COPS=3,1;+COPS?;+COPS=3,2;+COPS?";
- std::vector<std::string> response;
- SendCommand(command, "+COPS:");
- ReadCommandResponse(response);
- ASSERT_EQ(response.size(), 4);
-}
-
-TEST_F(ModemServiceTest, testVoiceNetworkRegistration) {
- std::string command = "AT+CREG?";
- std::vector<std::string> response;
- SendCommand(command, "+CREG:");
- ReadCommandResponse(response);
- ASSERT_EQ(response.size(), 2);
- ASSERT_STREQ(response[response.size() - 1].c_str(), kFinalResponseSuccess[0].c_str());
-}
-
-TEST_F(ModemServiceTest, testDataNetworkRegistration) {
- std::string command = "AT+CGREG?";
- std::vector<std::string> response;
- SendCommand(command, "+CGREG:");
- ReadCommandResponse(response);
- ASSERT_EQ(response.size(), 2);
- ASSERT_STREQ(response[response.size() - 1].c_str(), kFinalResponseSuccess[0].c_str());
-}
-
-TEST_F(ModemServiceTest, testDataNetworkRegistrationWithLte2) {
- std::string command = "AT+CEREG?";
- std::vector<std::string> response;
- SendCommand(command, "+CEREG:");
- ReadCommandResponse(response);
- ASSERT_EQ(response.size(), 2);
- ASSERT_STREQ(response[response.size() - 1].c_str(), kFinalResponseSuccess[0].c_str());
-}
-
-TEST_F(ModemServiceTest, testGetPreferredNetworkType) {
- std::string command = "AT+CTEC?";
- std::vector<std::string> response;
- SendCommand(command, "+CTEC:");
- ReadCommandResponse(response);
- ASSERT_EQ(response.size(), 2);
- ASSERT_STREQ(response[response.size() - 1].c_str(), kFinalResponseSuccess[0].c_str());
-}
-
-TEST_F(ModemServiceTest, testQuerySupportedTechs) {
- std::string command = "AT+CTEC=?";
- std::vector<std::string> response;
- SendCommand(command, "+CTEC:");
- ReadCommandResponse(response);
- ASSERT_EQ(response.size(), 2);
- ASSERT_STREQ(response[response.size() - 1].c_str(), kFinalResponseSuccess[0].c_str());
-}
-
-TEST_F(ModemServiceTest, testSetPreferredNetworkType) {
- std::string command = "AT+CTEC=1,\"201\"";
- std::vector<std::string> response;
- SendCommand(command, "+CTEC:");
- ReadCommandResponse(response);
- ASSERT_EQ(response.size(), 2);
- ASSERT_STREQ(response[response.size() - 1].c_str(), kFinalResponseSuccess[0].c_str());
-}
-
-/* Call Service Test */
-TEST_F(ModemServiceTest, testCurrentCalls) {
- std::string command = "AT+CLCC";
- std::vector<std::string> response;
- SendCommand(command, "+CLCC:");
- ReadCommandResponse(response);
- ASSERT_EQ(response.size(), 1);
-}
-
-TEST_F(ModemServiceTest, testHangup) {
- for (int i = 0; i < 5; i ++) {
- std::stringstream ss;
- ss.clear();
- ss << "AT+CHLD=" << i;
- SendCommand(ss.str());
- }
- std::vector<std::string> response;
- ReadCommandResponse(response);
- ASSERT_EQ(response.size(), 1);
- ASSERT_STREQ(response[response.size() - 1].c_str(), kFinalResponseSuccess[0].c_str());
-}
-
-TEST_F(ModemServiceTest, testMute) {
- std::string command = "AT+CMUT=1";
- std::vector<std::string> response;
- SendCommand(command);
- ReadCommandResponse(response);
- ASSERT_EQ(response.size(), 1);
- ASSERT_STREQ(response[response.size() - 1].c_str(), kFinalResponseSuccess[0].c_str());
-}
-
-TEST_F(ModemServiceTest, testSendDtmf) {
- std::string command = "AT+VTS=1";
- std::vector<std::string> response;
- SendCommand(command);
- ReadCommandResponse(response);
- ASSERT_EQ(response.size(), 1);
- ASSERT_STREQ(response[response.size() - 1].c_str(), kFinalResponseSuccess[0].c_str());
-}
-
-TEST_F(ModemServiceTest, testExitEmergencyMode) {
- std::string command = "AT+WSOS=0";
- std::vector<std::string> response;
- SendCommand(command);
- ReadCommandResponse(response);
- ASSERT_EQ(response.size(), 1);
- ASSERT_STREQ(response[response.size() - 1].c_str(), kFinalResponseSuccess[0].c_str());
-}
-
-/* Data Service Test */
-TEST_F(ModemServiceTest, SetPDPContext) {
- std::string command = "AT+CGDCONT=1,\"IPV4V6\",\"ctlte\",,0,0";
- std::vector<std::string> response;
- SendCommand(command);
- ReadCommandResponse(response);
- ASSERT_EQ(response.size(), 1);
- ASSERT_STREQ(response.at(0).c_str(), kFinalResponseSuccess[0].c_str());
-}
-
-TEST_F(ModemServiceTest, QueryPDPContextList) {
- for (int i = 1; i < 5; i ++) {
- std::stringstream ss;
- ss.clear();
- ss << "AT+CGDCONT=" << i << ",\"IPV4V6\",\"ctlte\",,0,0";
- SendCommand(ss.str());
- }
- std::string command = "AT+CGDCONT?";
- std::vector<std::string> response;
- SendCommand(command, "+CGDCONT:");
- ReadCommandResponse(response);
- const char *result = response[response.size() - 1].c_str();
- ASSERT_EQ(response.size(), 1);
- ASSERT_STREQ(result, kFinalResponseSuccess[0].c_str());
-}
-
-TEST_F(ModemServiceTest, ActivateDataCall) {
- std::string command = "AT+CGACT= 1,0";
- std::vector<std::string> response;
- SendCommand(command);
- ReadCommandResponse(response);
- const char *result = response[0].c_str();
- ASSERT_STREQ(result, kFinalResponseSuccess[0].c_str());
-}
-
-TEST_F(ModemServiceTest, QueryDataCallList) {
- std::string command = "AT+CGACT?";
- std::vector<std::string> response;
- SendCommand(command, "+CGACT:");
- ReadCommandResponse(response);
- const char *result = response[response.size() - 1].c_str();
- ASSERT_STREQ(result, kFinalResponseSuccess[0].c_str());
-}
-
-TEST_F(ModemServiceTest, ReadDynamicParamTrue) {
- std::string command = "AT+CGCONTRDP=1";
- std::vector<std::string> response;
- SendCommand(command);
- ReadCommandResponse(response);
- const char *result = response[response.size() - 1].c_str();
- ASSERT_STREQ(result, kFinalResponseSuccess[0].c_str());
-}
-
-TEST_F(ModemServiceTest, ReadDynamicParamFalse) {
- std::string command = "AT+CGCONTRDP=10";
- std::vector<std::string> response;
- SendCommand(command);
- ReadCommandResponse(response);
- const char *result = response[response.size() - 1].c_str();
- const char *expect = "+CME ERROR: 21";
- ASSERT_STREQ(result, expect);
-}
-
-TEST_F(ModemServiceTest, EnterDataState) {
- std::string command = "AT+CGDATA=1,1";
- std::vector<std::string> response;
- SendCommand(command);
- ReadCommandResponse(response);
- const char *result = response[response.size() - 1].c_str();
- ASSERT_STREQ(result, kFinalResponseSuccess[1].c_str());
-}
-
-/* SMS Service Test */
-TEST_F(ModemServiceTest, SendSMS) {
- std::string command = "AT+CMGS=35";
- std::vector<std::string> response;
- SendCommand(command);
- ReadCommandResponse(response);
- const char *result = response[response.size() - 1].c_str();
- const char *expect = "> ";
- ASSERT_STREQ(result, expect);
- command = "0001000D91688118109844F0000017AFD7903AB55A9BBA69D639D4ADCBF99E3DCCAE9701^Z";
- //command += '\032';
- SendCommand(command);
- ReadCommandResponse(response);
- // TODO (bohu) for some reason the follwoing asserts fail, fix them
- // ASSERT_EQ(response.size(), 3);
- // ASSERT_STREQ(response[response.size() - 1].c_str(),
- // kFinalResponseSuccess[0].c_str());
-}
-
-TEST_F(ModemServiceTest, WriteSMSToSim) {
- std::string command = "AT+CMGW=24,3";
- std::vector<std::string> response;
- SendCommand(command);
- ReadCommandResponse(response);
- const char *result = response[response.size() - 1].c_str();
- const char *expect = "> ";
- ASSERT_STREQ(result, expect);
- command = "00240B815123106351F100000240516054410005C8329BFD06^Z";
- SendCommand(command);
- ReadCommandResponse(response);
- ASSERT_EQ(response.size(), 3);
- ASSERT_STREQ(response[response.size() - 1].c_str(), kFinalResponseSuccess[0].c_str());
-}
-
-TEST_F(ModemServiceTest, SMSAcknowledge) {
- std::string command = "AT+CNMA=1";
- std::vector<std::string> response;
- SendCommand(command);
- ReadCommandResponse(response);
- const char *result = response[response.size() - 1].c_str();
- ASSERT_STREQ(result, kFinalResponseSuccess[0].c_str());
-}
-
-TEST_F(ModemServiceTest, DeleteSmsOnSimTure) {
- std::string command = "AT+CMGD=1";
- std::vector<std::string> response;
- SendCommand(command);
- ReadCommandResponse(response);
- const char *result = response[0].c_str();
- ASSERT_STREQ(result, kFinalResponseSuccess[0].c_str());
-}
-
-TEST_F(ModemServiceTest, DeleteSmsOnSimFalse) {
- std::string command = "AT+CMGD=1";
- std::vector<std::string> response;
- SendCommand(command);
- ReadCommandResponse(response);
- const char *result = response[0].c_str();
- const char *expect = "+CME ERROR: 21";
- ASSERT_STREQ(result, expect);
-}
-
-TEST_F(ModemServiceTest, SetBroadcastConfig) {
- std::string command = "AT+CSCB=0,\"4356\",\"0-255\"";
- std::vector<std::string> response;
- SendCommand(command);
- ReadCommandResponse(response);
- const char *result = response[0].c_str();
- ASSERT_STREQ(result, kFinalResponseSuccess[0].c_str());
-}
-
-TEST_F(ModemServiceTest, GetBroadcastConfig) {
- std::string command = "AT+CSCB?";
- std::vector<std::string> response;
- SendCommand(command);
- ReadCommandResponse(response);
- ASSERT_EQ(response.size(), 2);
- const char *result = response[response.size() - 1].c_str();
- ASSERT_STREQ(result, kFinalResponseSuccess[0].c_str());
-}
-
-TEST_F(ModemServiceTest, SetSmscAddress) {
- std::string command = "AT+CSCA=\"91688115667566F4\",16";
- std::vector<std::string> response;
- SendCommand(command);
- ReadCommandResponse(response);
- ASSERT_EQ(response.size(), 1);
- const char *result = response[response.size() - 1].c_str();
- ASSERT_STREQ(result, kFinalResponseSuccess[0].c_str());
-}
-
-TEST_F(ModemServiceTest, GetSmscAddress) {
- std::string command = "AT+CSCA?";
- std::vector<std::string> response;
- SendCommand(command);
- ReadCommandResponse(response);
- ASSERT_EQ(response.size(), 2);
- const char *result = response[response.size() - 1].c_str();
- ASSERT_STREQ(result, kFinalResponseSuccess[0].c_str());
-}
-
-/* SUP Service Test */
-TEST_F(ModemServiceTest, testUSSD) {
- std::string command = "AT+CUSD=1";
- std::vector<std::string> response;
- SendCommand(command);
- ReadCommandResponse(response);
- ASSERT_EQ(response.size(), 1);
- ASSERT_STREQ(response[response.size() - 1].c_str(), kFinalResponseSuccess[0].c_str());
-}
-
-TEST_F(ModemServiceTest, testCLIR) {
- std::string command = "AT+CLIR=2";
- std::vector<std::string> response;
- SendCommand(command);
- ReadCommandResponse(response);
- ASSERT_EQ(response.size(), 1);
- ASSERT_STREQ(response[response.size() - 1].c_str(), kFinalResponseSuccess[0].c_str());
-}
-
-TEST_F(ModemServiceTest, testQueryCLIR) {
- std::string command = "AT+CLIR?";
- std::vector<std::string> response;
- SendCommand(command, "+CLIR:");
- ReadCommandResponse(response);
- ASSERT_EQ(response.size(), 2);
-}
-
-TEST_F(ModemServiceTest, testCallWaiting) {
- std::string command = "AT+CCWA";
- std::vector<std::string> response;
- SendCommand(command, "+CCWA:");
- ReadCommandResponse(response);
- ASSERT_EQ(response.size(), 1);
- ASSERT_STREQ(response[response.size() - 1].c_str(), kFinalResponseSuccess[0].c_str());
-}
-
-TEST_F(ModemServiceTest, testCLIP) {
- std::string command = "AT+CLIP?";
- std::vector<std::string> response;
- SendCommand(command, "+CLIP:");
- ReadCommandResponse(response);
- ASSERT_EQ(response.size(), 2);
-}
-
-TEST_F(ModemServiceTest, testCallForward) {
- std::string command = "AT+CCFCU=1,1,2,145,\"10086\"";
- std::vector<std::string> response;
- SendCommand(command, "+CCFCU:");
- ReadCommandResponse(response);
- ASSERT_EQ(response.size(), 1);
-}
-
-/* STK Service Test */
-TEST_F(ModemServiceTest, ReportStkServiceIsRunning) {
- std::string command = "AT+CUSATD?";
- std::vector<std::string> response;
- SendCommand(command);
- ReadCommandResponse(response);
- ASSERT_EQ(response.size(), 2);
- const char *result = response[0].c_str();
- const char *expect = "+CUSATD: 0,1";
- ASSERT_STREQ(result, expect);
-}
-
-TEST_F(ModemServiceTest, SendEnvelope) {
- std::string command = "AT+CUSATT=\"810301250002028281830100\"";
- std::vector<std::string> response;
- SendCommand(command);
- ReadCommandResponse(response);
- ASSERT_EQ(response.size(), 2);
- const char *result = response[0].c_str();
- const char *expect = "+CUSATT: 0";
- ASSERT_STREQ(result, expect);
-}
-
-TEST_F(ModemServiceTest, GetSendTerminalResponseToSim) {
- std::string command = "AT+CUSATE=\"D3078202018190014E\"";
- std::vector<std::string> response;
- SendCommand(command);
- ReadCommandResponse(response);
- ASSERT_EQ(response.size(), 2);
- const char *result = response[0].c_str();
- const char *expect = "+CUSATE: 0";
- ASSERT_STREQ(result, expect);
-}
-
-/* Misc Service Test */
-TEST_F(ModemServiceTest, GetIMEI) {
- std::string command = "AT+CGSN";
- std::vector<std::string> response;
- SendCommand(command);
- ReadCommandResponse(response);
- ASSERT_EQ(response.size(), 2);
- const char *result = response[0].c_str();
- const char *expect = "867400022047199";
- ASSERT_STREQ(result, expect);
-}
diff --git a/host/commands/powerwash_cvd/powerwash_cvd.cc b/host/commands/powerwash_cvd/powerwash_cvd.cc
deleted file mode 100644
index b2e322b06..000000000
--- a/host/commands/powerwash_cvd/powerwash_cvd.cc
+++ /dev/null
@@ -1,163 +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.
- */
-
-#include <inttypes.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/wait.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <signal.h>
-
-#include <algorithm>
-#include <cstdlib>
-#include <fstream>
-#include <iomanip>
-#include <memory>
-#include <sstream>
-#include <string>
-#include <vector>
-
-#include <gflags/gflags.h>
-#include <android-base/logging.h>
-
-#include "common/libs/fs/shared_buf.h"
-#include "common/libs/fs/shared_fd.h"
-#include "common/libs/fs/shared_select.h"
-#include "common/libs/utils/environment.h"
-#include "host/commands/run_cvd/runner_defs.h"
-#include "host/libs/config/cuttlefish_config.h"
-#include "host/libs/vm_manager/vm_manager.h"
-
-DEFINE_int32(instance_num, cuttlefish::GetInstance(),
- "Which instance to powerwash");
-
-DEFINE_int32(wait_for_launcher, 30,
- "How many seconds to wait for the launcher to respond to the status "
- "command. A value of zero means wait indefinetly");
-
-DEFINE_int32(boot_timeout, 1000, "How many seconds to wait for the device to "
- "reboot.");
-
-namespace cuttlefish {
-namespace {
-
-int PowerwashCvdMain(int argc, char** argv) {
- ::android::base::InitLogging(argv, android::base::StderrLogger);
- google::ParseCommandLineFlags(&argc, &argv, true);
-
- auto config = CuttlefishConfig::Get();
- if (!config) {
- LOG(ERROR) << "Failed to obtain config object";
- return 1;
- }
-
- auto instance = config->ForInstance(FLAGS_instance_num);
- auto monitor_path = instance.launcher_monitor_socket_path();
- if (monitor_path.empty()) {
- LOG(ERROR) << "No path to launcher monitor found";
- return 2;
- }
- auto monitor_socket = SharedFD::SocketLocalClient(
- monitor_path.c_str(), false, SOCK_STREAM, FLAGS_wait_for_launcher);
- if (!monitor_socket->IsOpen()) {
- LOG(ERROR) << "Unable to connect to launcher monitor at " << monitor_path
- << ": " << monitor_socket->StrError();
- return 3;
- }
- auto request = LauncherAction::kPowerwash;
- auto bytes_sent = monitor_socket->Send(&request, sizeof(request), 0);
- if (bytes_sent < 0) {
- LOG(ERROR) << "Error sending launcher monitor the status command: "
- << monitor_socket->StrError();
- return 4;
- }
- // Perform a select with a timeout to guard against launcher hanging
- SharedFDSet read_set;
- read_set.Set(monitor_socket);
- struct timeval timeout = {FLAGS_wait_for_launcher, 0};
- int selected = Select(&read_set, nullptr, nullptr,
- FLAGS_wait_for_launcher <= 0 ? nullptr : &timeout);
- if (selected < 0){
- LOG(ERROR) << "Failed communication with the launcher monitor: "
- << strerror(errno);
- return 5;
- }
- if (selected == 0) {
- LOG(ERROR) << "Timeout expired waiting for launcher monitor to respond";
- return 6;
- }
- LauncherResponse response;
- auto bytes_recv = monitor_socket->Recv(&response, sizeof(response), 0);
- if (bytes_recv < 0) {
- LOG(ERROR) << "Error receiving response from launcher monitor: "
- << monitor_socket->StrError();
- return 7;
- }
- LOG(INFO) << "Requesting powerwash";
- if (response != LauncherResponse::kSuccess) {
- LOG(ERROR) << "Received '" << static_cast<char>(response)
- << "' response from launcher monitor for powerwash request";
- return 8;
- }
- LOG(INFO) << "Waiting for device to boot up again";
-
- read_set.Set(monitor_socket);
- timeout = {FLAGS_boot_timeout, 0};
- selected = Select(&read_set, nullptr, nullptr,
- FLAGS_boot_timeout <= 0 ? nullptr : &timeout);
- if (selected < 0){
- LOG(ERROR) << "Failed communication with the launcher monitor: "
- << strerror(errno);
- return 5;
- }
- if (selected == 0) {
- LOG(ERROR) << "Timeout expired waiting for launcher monitor to respond";
- return 6;
- }
-
- RunnerExitCodes exit_code;
- bytes_recv = ReadExactBinary(monitor_socket, &exit_code);
- if (bytes_recv < 0) {
- LOG(ERROR) << "Error in stream response: " << monitor_socket->StrError();
- return 9;
- } else if (bytes_recv == 0) {
- LOG(ERROR) << "Launcher socket closed unexpectedly";
- return 10;
- } else if (bytes_recv != sizeof(exit_code)) {
- LOG(ERROR) << "Launcher response was too short";
- return 11;
- } else if (exit_code == RunnerExitCodes::kVirtualDeviceBootFailed) {
- LOG(ERROR) << "Boot failed";
- return 12;
- } else if (exit_code != RunnerExitCodes::kSuccess) {
- LOG(ERROR) << "Unknown response: " << (int) exit_code;
- return 13;
- }
- LOG(INFO) << "Powerwash successful";
- return 0;
-}
-
-} // namespace
-} // namespace cuttlefish
-
-int main(int argc, char** argv) {
- return cuttlefish::PowerwashCvdMain(argc, argv);
-}
diff --git a/host/commands/restart_cvd/Android.bp b/host/commands/restart_cvd/Android.bp
deleted file mode 100644
index dc7a044b8..000000000
--- a/host/commands/restart_cvd/Android.bp
+++ /dev/null
@@ -1,37 +0,0 @@
-//
-// Copyright (C) 2021 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-cc_binary {
- name: "restart_cvd",
- srcs: [
- "restart_cvd.cc",
- ],
- shared_libs: [
- "libbase",
- "libcuttlefish_fs",
- "libcuttlefish_utils",
- "libjsoncpp",
- ],
- static_libs: [
- "libcuttlefish_host_config",
- "libcuttlefish_vm_manager",
- "libgflags",
- ],
- defaults: ["cuttlefish_host", "cuttlefish_libicuuc"],
-}
diff --git a/host/commands/restart_cvd/restart_cvd.cc b/host/commands/restart_cvd/restart_cvd.cc
deleted file mode 100644
index 68ff3e668..000000000
--- a/host/commands/restart_cvd/restart_cvd.cc
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Copyright (C) 2021 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 <inttypes.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/wait.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <signal.h>
-
-#include <algorithm>
-#include <cstdlib>
-#include <fstream>
-#include <iomanip>
-#include <memory>
-#include <sstream>
-#include <string>
-#include <vector>
-
-#include <gflags/gflags.h>
-#include <android-base/logging.h>
-
-#include "common/libs/fs/shared_buf.h"
-#include "common/libs/fs/shared_fd.h"
-#include "common/libs/fs/shared_select.h"
-#include "common/libs/utils/environment.h"
-#include "host/commands/run_cvd/runner_defs.h"
-#include "host/libs/config/cuttlefish_config.h"
-#include "host/libs/vm_manager/vm_manager.h"
-
-DEFINE_int32(instance_num, cuttlefish::GetInstance(),
- "Which instance to restart");
-
-DEFINE_int32(wait_for_launcher, 30,
- "How many seconds to wait for the launcher to respond to the status "
- "command. A value of zero means wait indefinetly");
-
-DEFINE_int32(boot_timeout, 1000, "How many seconds to wait for the device to "
- "reboot.");
-
-namespace cuttlefish {
-namespace {
-
-int RestartCvdMain(int argc, char** argv) {
- ::android::base::InitLogging(argv, android::base::StderrLogger);
- google::ParseCommandLineFlags(&argc, &argv, true);
-
- auto config = CuttlefishConfig::Get();
- if (!config) {
- LOG(ERROR) << "Failed to obtain config object";
- return 1;
- }
-
- auto instance = config->ForInstance(FLAGS_instance_num);
- auto monitor_path = instance.launcher_monitor_socket_path();
- if (monitor_path.empty()) {
- LOG(ERROR) << "No path to launcher monitor found";
- return 2;
- }
- // This may hang if the server never picks up the connection.
- auto monitor_socket = SharedFD::SocketLocalClient(
- monitor_path.c_str(), false, SOCK_STREAM, FLAGS_wait_for_launcher);
- if (!monitor_socket->IsOpen()) {
- LOG(ERROR) << "Unable to connect to launcher monitor at " << monitor_path
- << ": " << monitor_socket->StrError();
- return 3;
- }
- auto request = LauncherAction::kRestart;
- auto bytes_sent = monitor_socket->Send(&request, sizeof(request), 0);
- if (bytes_sent < 0) {
- LOG(ERROR) << "Error sending launcher monitor the status command: "
- << monitor_socket->StrError();
- return 4;
- }
- // Perform a select with a timeout to guard against launcher hanging
- SharedFDSet read_set;
- read_set.Set(monitor_socket);
- struct timeval timeout = {FLAGS_wait_for_launcher, 0};
- int selected = Select(&read_set, nullptr, nullptr,
- FLAGS_wait_for_launcher <= 0 ? nullptr : &timeout);
- if (selected < 0){
- LOG(ERROR) << "Failed communication with the launcher monitor: "
- << strerror(errno);
- return 5;
- }
- if (selected == 0) {
- LOG(ERROR) << "Timeout expired waiting for launcher monitor to respond";
- return 6;
- }
- LauncherResponse response;
- auto bytes_recv = monitor_socket->Recv(&response, sizeof(response), 0);
- if (bytes_recv < 0) {
- LOG(ERROR) << "Error receiving response from launcher monitor: "
- << monitor_socket->StrError();
- return 7;
- }
- LOG(INFO) << "Requesting restart";
- if (response != LauncherResponse::kSuccess) {
- LOG(ERROR) << "Received '" << static_cast<char>(response)
- << "' response from launcher monitor for restart request";
- return 8;
- }
- LOG(INFO) << "Waiting for device to boot up again";
-
- read_set.Set(monitor_socket);
- timeout = {FLAGS_boot_timeout, 0};
- selected = Select(&read_set, nullptr, nullptr,
- FLAGS_boot_timeout <= 0 ? nullptr : &timeout);
- if (selected < 0){
- LOG(ERROR) << "Failed communication with the launcher monitor: "
- << strerror(errno);
- return 5;
- }
- if (selected == 0) {
- LOG(ERROR) << "Timeout expired waiting for launcher monitor to respond";
- return 6;
- }
-
- RunnerExitCodes exit_code;
- bytes_recv = ReadExactBinary(monitor_socket, &exit_code);
- if (bytes_recv < 0) {
- LOG(ERROR) << "Error in stream response: " << monitor_socket->StrError();
- return 9;
- } else if (bytes_recv == 0) {
- LOG(ERROR) << "Launcher socket closed unexpectedly";
- return 10;
- } else if (bytes_recv != sizeof(exit_code)) {
- LOG(ERROR) << "Launcher response was too short";
- return 11;
- } else if (exit_code == RunnerExitCodes::kVirtualDeviceBootFailed) {
- LOG(ERROR) << "Boot failed";
- return 12;
- } else if (exit_code != RunnerExitCodes::kSuccess) {
- LOG(ERROR) << "Unknown response: " << (int) exit_code;
- return 13;
- }
- LOG(INFO) << "Restart successful";
- return 0;
-}
-
-} // namespace
-} // namespace cuttlefish
-
-int main(int argc, char** argv) {
- return cuttlefish::RestartCvdMain(argc, argv);
-}
diff --git a/host/commands/run_cvd/Android.bp b/host/commands/run_cvd/Android.bp
index 09b11d54d..2afc59c83 100644
--- a/host/commands/run_cvd/Android.bp
+++ b/host/commands/run_cvd/Android.bp
@@ -13,37 +13,26 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-cc_binary {
+cc_binary_host {
name: "run_cvd",
srcs: [
- "boot_state_machine.cc",
+ "kernel_args.cc",
"launch.cc",
- "launch_adb.cpp",
- "launch_modem.cpp",
- "launch_streamer.cpp",
"main.cc",
"process_monitor.cc",
- "server_loop.cpp",
],
shared_libs: [
"libcuttlefish_fs",
"libcuttlefish_utils",
- "libcuttlefish_kernel_log_monitor_utils",
"libbase",
- "libjsoncpp",
- "libnl",
+ "libnl"
],
static_libs: [
"libcuttlefish_host_config",
"libcuttlefish_vm_manager",
"libgflags",
+ "libxml2",
+ "libjsoncpp",
],
- defaults: [
- "cuttlefish_host",
- "cuttlefish_libicuuc",
- ],
+ defaults: ["cuttlefish_host_only", "cuttlefish_libicuuc"],
}
diff --git a/host/commands/run_cvd/boot_state_machine.cc b/host/commands/run_cvd/boot_state_machine.cc
deleted file mode 100644
index 64eb893f5..000000000
--- a/host/commands/run_cvd/boot_state_machine.cc
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2021 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 "host/commands/run_cvd/boot_state_machine.h"
-
-#include <memory>
-#include <thread>
-
-#include "android-base/logging.h"
-#include "common/libs/fs/shared_fd.h"
-#include "host/commands/kernel_log_monitor/kernel_log_server.h"
-#include "host/commands/kernel_log_monitor/utils.h"
-#include "host/commands/run_cvd/runner_defs.h"
-
-namespace cuttlefish {
-
-CvdBootStateMachine::CvdBootStateMachine(SharedFD fg_launcher_pipe,
- SharedFD reboot_notification,
- SharedFD boot_events_pipe)
- : fg_launcher_pipe_(fg_launcher_pipe),
- reboot_notification_(reboot_notification),
- state_(kBootStarted) {
- boot_event_handler_ = std::thread([this, boot_events_pipe]() {
- while (true) {
- SharedFDSet fd_set;
- fd_set.Set(boot_events_pipe);
- int result = Select(&fd_set, nullptr, nullptr, nullptr);
- if (result < 0) {
- PLOG(FATAL) << "Failed to call Select";
- return;
- }
- if (!fd_set.IsSet(boot_events_pipe)) {
- continue;
- }
- auto sent_code = OnBootEvtReceived(boot_events_pipe);
- if (sent_code) {
- break;
- }
- }
- });
-}
-
-CvdBootStateMachine::~CvdBootStateMachine() { boot_event_handler_.join(); }
-
-// Returns true if the machine is left in a final state
-bool CvdBootStateMachine::OnBootEvtReceived(SharedFD boot_events_pipe) {
- std::optional<monitor::ReadEventResult> read_result =
- monitor::ReadEvent(boot_events_pipe);
- if (!read_result) {
- LOG(ERROR) << "Failed to read a complete kernel log boot event.";
- state_ |= kGuestBootFailed;
- return MaybeWriteNotification();
- }
-
- if (read_result->event == monitor::Event::BootCompleted) {
- LOG(INFO) << "Virtual device booted successfully";
- state_ |= kGuestBootCompleted;
- } else if (read_result->event == monitor::Event::BootFailed) {
- LOG(ERROR) << "Virtual device failed to boot";
- state_ |= kGuestBootFailed;
- } // Ignore the other signals
-
- return MaybeWriteNotification();
-}
-
-bool CvdBootStateMachine::BootCompleted() const {
- return state_ & kGuestBootCompleted;
-}
-
-bool CvdBootStateMachine::BootFailed() const {
- return state_ & kGuestBootFailed;
-}
-
-void CvdBootStateMachine::SendExitCode(RunnerExitCodes exit_code, SharedFD fd) {
- fd->Write(&exit_code, sizeof(exit_code));
- // The foreground process will exit after receiving the exit code, if we try
- // to write again we'll get a SIGPIPE
- fd->Close();
-}
-
-bool CvdBootStateMachine::MaybeWriteNotification() {
- std::vector<SharedFD> fds = {reboot_notification_, fg_launcher_pipe_};
- for (auto& fd : fds) {
- if (fd->IsOpen()) {
- if (BootCompleted()) {
- SendExitCode(RunnerExitCodes::kSuccess, fd);
- } else if (state_ & kGuestBootFailed) {
- SendExitCode(RunnerExitCodes::kVirtualDeviceBootFailed, fd);
- }
- }
- }
- // Either we sent the code before or just sent it, in any case the state is
- // final
- return BootCompleted() || (state_ & kGuestBootFailed);
-}
-
-} // namespace cuttlefish
diff --git a/host/commands/run_cvd/boot_state_machine.h b/host/commands/run_cvd/boot_state_machine.h
deleted file mode 100644
index 0d02e728f..000000000
--- a/host/commands/run_cvd/boot_state_machine.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2021 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 <memory>
-#include <thread>
-
-#include "common/libs/fs/shared_fd.h"
-#include "host/commands/run_cvd/runner_defs.h"
-
-namespace cuttlefish {
-
-// Maintains the state of the boot process, once a final state is reached
-// (success or failure) it sends the appropriate exit code to the foreground
-// launcher process
-class CvdBootStateMachine {
- public:
- CvdBootStateMachine(SharedFD fg_launcher_pipe, SharedFD reboot_notification,
- SharedFD boot_events_pipe);
- ~CvdBootStateMachine();
-
- private:
- // Returns true if the machine is left in a final state
- bool OnBootEvtReceived(SharedFD boot_events_pipe);
- bool BootCompleted() const;
- bool BootFailed() const;
-
- void SendExitCode(RunnerExitCodes exit_code, SharedFD fd);
- bool MaybeWriteNotification();
-
- std::thread boot_event_handler_;
- SharedFD fg_launcher_pipe_;
- SharedFD reboot_notification_;
- int state_;
- static const int kBootStarted = 0;
- static const int kGuestBootCompleted = 1 << 0;
- static const int kGuestBootFailed = 1 << 1;
-};
-
-} // namespace cuttlefish
diff --git a/host/commands/run_cvd/kernel_args.cc b/host/commands/run_cvd/kernel_args.cc
new file mode 100644
index 000000000..308ef8a7c
--- /dev/null
+++ b/host/commands/run_cvd/kernel_args.cc
@@ -0,0 +1,151 @@
+/*
+ * 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 "host/commands/run_cvd/kernel_args.h"
+
+#include <array>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include "common/libs/utils/files.h"
+#include "host/commands/run_cvd/launch.h"
+#include "host/commands/run_cvd/runner_defs.h"
+#include "host/libs/config/cuttlefish_config.h"
+#include "host/libs/vm_manager/vm_manager.h"
+
+template<typename T>
+static void AppendVector(std::vector<T>* destination, const std::vector<T>& source) {
+ destination->insert(destination->end(), source.begin(), source.end());
+}
+
+template<typename S, typename T>
+static std::string concat(const S& s, const T& t) {
+ std::ostringstream os;
+ os << s << t;
+ return os.str();
+}
+
+static std::string mac_to_str(const std::array<unsigned char, 6>& mac) {
+ std::ostringstream stream;
+ stream << std::hex << (int) mac[0];
+ for (int i = 1; i < 6; i++) {
+ stream << ":" << std::hex << (int) mac[i];
+ }
+ return stream.str();
+}
+
+std::vector<std::string> KernelCommandLineFromConfig(const vsoc::CuttlefishConfig& config) {
+ auto instance = config.ForDefaultInstance();
+ std::vector<std::string> kernel_cmdline;
+
+ AppendVector(&kernel_cmdline, config.boot_image_kernel_cmdline());
+ AppendVector(&kernel_cmdline,
+ vm_manager::VmManager::ConfigureGpuMode(config.vm_manager(), config.gpu_mode()));
+ AppendVector(&kernel_cmdline, vm_manager::VmManager::ConfigureBootDevices(config.vm_manager()));
+
+ kernel_cmdline.push_back(concat("androidboot.serialno=", instance.serial_number()));
+ kernel_cmdline.push_back(concat("androidboot.lcd_density=", config.dpi()));
+ if (config.logcat_mode() == cvd::kLogcatVsockMode) {
+ }
+ kernel_cmdline.push_back(concat(
+ "androidboot.setupwizard_mode=", config.setupwizard_mode()));
+ if (!config.use_bootloader()) {
+ std::string slot_suffix;
+ if (config.boot_slot().empty()) {
+ slot_suffix = "_a";
+ } else {
+ slot_suffix = "_" + config.boot_slot();
+ }
+ kernel_cmdline.push_back(concat("androidboot.slot_suffix=", slot_suffix));
+ }
+ kernel_cmdline.push_back(concat("loop.max_part=", config.loop_max_part()));
+ if (config.guest_enforce_security()) {
+ kernel_cmdline.push_back("enforcing=1");
+ } else {
+ kernel_cmdline.push_back("enforcing=0");
+ kernel_cmdline.push_back("androidboot.selinux=permissive");
+ }
+ if (config.guest_audit_security()) {
+ kernel_cmdline.push_back("audit=1");
+ } else {
+ kernel_cmdline.push_back("audit=0");
+ }
+ if (config.guest_force_normal_boot()) {
+ kernel_cmdline.push_back("androidboot.force_normal_boot=1");
+ }
+
+ if (config.enable_vehicle_hal_grpc_server() && instance.vehicle_hal_server_port() &&
+ cvd::FileExists(config.vehicle_hal_grpc_server_binary())) {
+ constexpr int vehicle_hal_server_cid = 2;
+ kernel_cmdline.push_back(concat("androidboot.vendor.vehiclehal.server.cid=", vehicle_hal_server_cid));
+ kernel_cmdline.push_back(concat("androidboot.vendor.vehiclehal.server.port=", instance.vehicle_hal_server_port()));
+ }
+
+ // TODO(b/158131610): Set this in crosvm instead
+ kernel_cmdline.push_back(concat("androidboot.wifi_mac_address=",
+ mac_to_str(instance.wifi_mac_address())));
+
+ AppendVector(&kernel_cmdline, config.extra_kernel_cmdline());
+
+ return kernel_cmdline;
+}
+
+std::vector<std::string> KernelCommandLineFromStreamer(
+ const StreamerLaunchResult& streamer_launch) {
+ std::vector<std::string> kernel_args;
+ if (streamer_launch.frames_server_vsock_port) {
+ kernel_args.push_back(concat("androidboot.vsock_frames_port=",
+ *streamer_launch.frames_server_vsock_port));
+ }
+ if (streamer_launch.touch_server_vsock_port) {
+ kernel_args.push_back(concat("androidboot.vsock_touch_port=",
+ *streamer_launch.touch_server_vsock_port));
+ }
+ if (streamer_launch.keyboard_server_vsock_port) {
+ kernel_args.push_back(concat("androidboot.vsock_keyboard_port=",
+ *streamer_launch.keyboard_server_vsock_port));
+ }
+ return kernel_args;
+}
+
+std::vector<std::string> KernelCommandLineFromTombstone(const TombstoneReceiverPorts& tombstone) {
+ if (!tombstone.server_vsock_port) {
+ return { "androidboot.tombstone_transmit=0" };
+ }
+ return {
+ "androidboot.tombstone_transmit=1",
+ concat("androidboot.vsock_tombstone_port=", *tombstone.server_vsock_port),
+ };
+}
+
+std::vector<std::string> KernelCommandLineFromConfigServer(const ConfigServerPorts& config_server) {
+ if (!config_server.server_vsock_port) {
+ return {};
+ }
+ return {
+ concat("androidboot.cuttlefish_config_server_port=", *config_server.server_vsock_port),
+ };
+}
+
+std::vector<std::string> KernelCommandLineFromLogcatServer(const LogcatServerPorts& logcat_server) {
+ if (!logcat_server.server_vsock_port) {
+ return {};
+ }
+ return {
+ concat("androidboot.vsock_logcat_port=", *logcat_server.server_vsock_port),
+ };
+}
diff --git a/host/libs/config/bootconfig_args.h b/host/commands/run_cvd/kernel_args.h
index 6c43204fe..b5d159516 100644
--- a/host/libs/config/bootconfig_args.h
+++ b/host/commands/run_cvd/kernel_args.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 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.
@@ -19,12 +19,11 @@
#include <string>
#include <vector>
+#include "host/commands/run_cvd/launch.h"
#include "host/libs/config/cuttlefish_config.h"
-namespace cuttlefish {
-
-std::vector<std::string> BootconfigArgsFromConfig(
- const CuttlefishConfig& config,
- const CuttlefishConfig::InstanceSpecific& instance);
-
-} // namespace cuttlefish
+std::vector<std::string> KernelCommandLineFromConfig(const vsoc::CuttlefishConfig& config);
+std::vector<std::string> KernelCommandLineFromStreamer(const StreamerLaunchResult& vnc_config);
+std::vector<std::string> KernelCommandLineFromTombstone(const TombstoneReceiverPorts& tombstone);
+std::vector<std::string> KernelCommandLineFromConfigServer(const ConfigServerPorts& config_server);
+std::vector<std::string> KernelCommandLineFromLogcatServer(const LogcatServerPorts& config_server);
diff --git a/host/commands/run_cvd/launch.cc b/host/commands/run_cvd/launch.cc
index a6184b27e..3cc1f77c5 100644
--- a/host/commands/run_cvd/launch.cc
+++ b/host/commands/run_cvd/launch.cc
@@ -1,46 +1,140 @@
-//
-// 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.
-
#include "host/commands/run_cvd/launch.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+
#include <android-base/logging.h>
-#include <utility>
#include "common/libs/fs/shared_fd.h"
#include "common/libs/utils/files.h"
-#include "common/libs/utils/subprocess.h"
-#include "host/commands/run_cvd/process_monitor.h"
+#include "common/libs/utils/size_utils.h"
#include "host/commands/run_cvd/runner_defs.h"
-#include "host/libs/config/cuttlefish_config.h"
-#include "host/libs/config/known_paths.h"
+#include "host/commands/run_cvd/pre_launch_initializers.h"
+#include "host/libs/vm_manager/crosvm_manager.h"
+#include "host/libs/vm_manager/qemu_manager.h"
-namespace cuttlefish {
+using cvd::RunnerExitCodes;
+using cvd::MonitorEntry;
namespace {
-template <typename T>
-std::vector<T> single_element_emplace(T&& element) {
- std::vector<T> vec;
- vec.emplace_back(std::move(element));
- return vec;
+std::string GetAdbConnectorTcpArg(const vsoc::CuttlefishConfig& config) {
+ auto instance = config.ForDefaultInstance();
+ return std::string{"127.0.0.1:"} + std::to_string(instance.host_port());
+}
+
+std::string GetAdbConnectorVsockArg(const vsoc::CuttlefishConfig& config) {
+ auto instance = config.ForDefaultInstance();
+ return std::string{"vsock:"}
+ + std::to_string(instance.vsock_guest_cid())
+ + std::string{":5555"};
+}
+
+bool AdbModeEnabled(const vsoc::CuttlefishConfig& config, vsoc::AdbMode mode) {
+ return config.adb_mode().count(mode) > 0;
}
-} // namespace
+bool AdbVsockTunnelEnabled(const vsoc::CuttlefishConfig& config) {
+ auto instance = config.ForDefaultInstance();
+ return instance.vsock_guest_cid() > 2
+ && AdbModeEnabled(config, vsoc::AdbMode::VsockTunnel);
+}
-KernelLogMonitorData LaunchKernelLogMonitor(
- const CuttlefishConfig& config, unsigned int number_of_event_pipes) {
+bool AdbVsockHalfTunnelEnabled(const vsoc::CuttlefishConfig& config) {
+ auto instance = config.ForDefaultInstance();
+ return instance.vsock_guest_cid() > 2
+ && AdbModeEnabled(config, vsoc::AdbMode::VsockHalfTunnel);
+}
+
+bool AdbTcpConnectorEnabled(const vsoc::CuttlefishConfig& config) {
+ bool vsock_tunnel = AdbVsockTunnelEnabled(config);
+ bool vsock_half_tunnel = AdbVsockHalfTunnelEnabled(config);
+ return config.run_adb_connector() && (vsock_tunnel || vsock_half_tunnel);
+}
+
+bool AdbVsockConnectorEnabled(const vsoc::CuttlefishConfig& config) {
+ return config.run_adb_connector()
+ && AdbModeEnabled(config, vsoc::AdbMode::NativeVsock);
+}
+
+cvd::OnSocketReadyCb GetOnSubprocessExitCallback(
+ const vsoc::CuttlefishConfig& config) {
+ if (config.restart_subprocesses()) {
+ return cvd::ProcessMonitor::RestartOnExitCb;
+ } else {
+ return cvd::ProcessMonitor::DoNotMonitorCb;
+ }
+}
+
+cvd::SharedFD CreateUnixInputServer(const std::string& path) {
+ auto server = cvd::SharedFD::SocketLocalServer(path.c_str(), false, SOCK_STREAM, 0666);
+ if (!server->IsOpen()) {
+ LOG(ERROR) << "Unable to create unix input server: "
+ << server->StrError();
+ return cvd::SharedFD();
+ }
+ return server;
+}
+
+// Creates the frame and input sockets and add the relevant arguments to the vnc
+// server and webrtc commands
+StreamerLaunchResult CreateStreamerServers(cvd::Command* cmd,
+ const vsoc::CuttlefishConfig& config) {
+ StreamerLaunchResult server_ret;
+ cvd::SharedFD touch_server;
+ cvd::SharedFD keyboard_server;
+
+ auto instance = config.ForDefaultInstance();
+ if (config.vm_manager() == vm_manager::QemuManager::name()) {
+ cmd->AddParameter("-write_virtio_input");
+
+ touch_server = cvd::SharedFD::VsockServer(SOCK_STREAM);
+ server_ret.touch_server_vsock_port = touch_server->VsockServerPort();
+
+ keyboard_server = cvd::SharedFD::VsockServer(SOCK_STREAM);
+ server_ret.keyboard_server_vsock_port = keyboard_server->VsockServerPort();
+ } else {
+ touch_server = CreateUnixInputServer(instance.touch_socket_path());
+ keyboard_server = CreateUnixInputServer(instance.keyboard_socket_path());
+ }
+ if (!touch_server->IsOpen()) {
+ LOG(ERROR) << "Could not open touch server: " << touch_server->StrError();
+ return {};
+ }
+ cmd->AddParameter("-touch_fd=", touch_server);
+
+ if (!keyboard_server->IsOpen()) {
+ LOG(ERROR) << "Could not open keyboard server: " << keyboard_server->StrError();
+ return {};
+ }
+ cmd->AddParameter("-keyboard_fd=", keyboard_server);
+
+ cvd::SharedFD frames_server;
+ if (config.gpu_mode() == vsoc::kGpuModeDrmVirgl ||
+ config.gpu_mode() == vsoc::kGpuModeGfxStream) {
+ frames_server = CreateUnixInputServer(instance.frames_socket_path());
+ } else {
+ frames_server = cvd::SharedFD::VsockServer(SOCK_STREAM);
+ server_ret.frames_server_vsock_port = frames_server->VsockServerPort();
+ }
+ if (!frames_server->IsOpen()) {
+ LOG(ERROR) << "Could not open frames server: " << frames_server->StrError();
+ return {};
+ }
+ cmd->AddParameter("-frame_server_fd=", frames_server);
+ return server_ret;
+}
+
+} // namespace
+
+bool LogcatReceiverEnabled(const vsoc::CuttlefishConfig& config) {
+ return config.logcat_mode() == cvd::kLogcatVsockMode;
+}
+
+std::vector<cvd::SharedFD> LaunchKernelLogMonitor(
+ const vsoc::CuttlefishConfig& config,
+ cvd::ProcessMonitor* process_monitor,
+ unsigned int number_of_event_pipes) {
auto instance = config.ForDefaultInstance();
auto log_name = instance.kernel_log_pipe_name();
if (mkfifo(log_name.c_str(), 0600) != 0) {
@@ -49,101 +143,83 @@ KernelLogMonitorData LaunchKernelLogMonitor(
return {};
}
- SharedFD pipe;
+ cvd::SharedFD pipe;
// Open the pipe here (from the launcher) to ensure the pipe is not deleted
// due to the usage counters in the kernel reaching zero. If this is not done
// and the kernel_log_monitor crashes for some reason the VMM may get SIGPIPE.
- pipe = SharedFD::Open(log_name.c_str(), O_RDWR);
- Command command(KernelLogMonitorBinary());
+ pipe = cvd::SharedFD::Open(log_name.c_str(), O_RDWR);
+ cvd::Command command(config.kernel_log_monitor_binary());
command.AddParameter("-log_pipe_fd=", pipe);
- KernelLogMonitorData ret;
+ std::vector<cvd::SharedFD> ret;
if (number_of_event_pipes > 0) {
- command.AddParameter("-subscriber_fds=");
+ auto param_builder = command.GetParameterBuilder();
+ param_builder << "-subscriber_fds=";
for (unsigned int i = 0; i < number_of_event_pipes; ++i) {
- SharedFD event_pipe_write_end, event_pipe_read_end;
- if (!SharedFD::Pipe(&event_pipe_read_end, &event_pipe_write_end)) {
- LOG(ERROR) << "Unable to create kernel log events pipe: " << strerror(errno);
+ cvd::SharedFD event_pipe_write_end, event_pipe_read_end;
+ if (!cvd::SharedFD::Pipe(&event_pipe_read_end, &event_pipe_write_end)) {
+ LOG(ERROR) << "Unable to create boot events pipe: " << strerror(errno);
std::exit(RunnerExitCodes::kPipeIOError);
}
if (i > 0) {
- command.AppendToLastParameter(",");
+ param_builder << ",";
}
- command.AppendToLastParameter(event_pipe_write_end);
- ret.pipes.push_back(event_pipe_read_end);
+ param_builder << event_pipe_write_end;
+ ret.push_back(event_pipe_read_end);
}
+ param_builder.Build();
}
- ret.commands.emplace_back(std::move(command));
+ process_monitor->StartSubprocess(std::move(command),
+ GetOnSubprocessExitCallback(config));
return ret;
}
-std::vector<Command> LaunchRootCanal(const CuttlefishConfig& config) {
- if (!config.enable_host_bluetooth()) {
+LogcatServerPorts LaunchLogcatReceiverIfEnabled(const vsoc::CuttlefishConfig& config,
+ cvd::ProcessMonitor* process_monitor) {
+ if (!LogcatReceiverEnabled(config)) {
return {};
}
-
- auto instance = config.ForDefaultInstance();
- Command command(RootCanalBinary());
-
- // Test port
- command.AddParameter(instance.rootcanal_test_port());
- // HCI server port
- command.AddParameter(instance.rootcanal_hci_port());
- // Link server port
- command.AddParameter(instance.rootcanal_link_port());
- // Bluetooth controller properties file
- command.AddParameter("--controller_properties_file=",
- instance.rootcanal_config_file());
- // Default commands file
- command.AddParameter("--default_commands_file=",
- instance.rootcanal_default_commands_file());
-
- return single_element_emplace(std::move(command));
-}
-
-std::vector<Command> LaunchLogcatReceiver(const CuttlefishConfig& config) {
- auto instance = config.ForDefaultInstance();
- auto log_name = instance.logcat_pipe_name();
- if (mkfifo(log_name.c_str(), 0600) != 0) {
- LOG(ERROR) << "Unable to create named pipe at " << log_name << ": "
- << strerror(errno);
- return {};
+ auto socket = cvd::SharedFD::VsockServer(SOCK_STREAM);
+ if (!socket->IsOpen()) {
+ LOG(ERROR) << "Unable to create logcat server socket: "
+ << socket->StrError();
+ std::exit(RunnerExitCodes::kLogcatServerError);
}
-
- SharedFD pipe;
- // Open the pipe here (from the launcher) to ensure the pipe is not deleted
- // due to the usage counters in the kernel reaching zero. If this is not done
- // and the logcat_receiver crashes for some reason the VMM may get SIGPIPE.
- pipe = SharedFD::Open(log_name.c_str(), O_RDWR);
- Command command(LogcatReceiverBinary());
- command.AddParameter("-log_pipe_fd=", pipe);
-
- return single_element_emplace(std::move(command));
+ cvd::Command cmd(config.logcat_receiver_binary());
+ cmd.AddParameter("-server_fd=", socket);
+ process_monitor->StartSubprocess(std::move(cmd),
+ GetOnSubprocessExitCallback(config));
+ return { socket->VsockServerPort() };
}
-std::vector<Command> LaunchConfigServer(const CuttlefishConfig& config) {
- auto instance = config.ForDefaultInstance();
- auto port = instance.config_server_port();
- auto socket = SharedFD::VsockServer(port, SOCK_STREAM);
+ConfigServerPorts LaunchConfigServer(const vsoc::CuttlefishConfig& config,
+ cvd::ProcessMonitor* process_monitor) {
+ auto socket = cvd::SharedFD::VsockServer(SOCK_STREAM);
if (!socket->IsOpen()) {
LOG(ERROR) << "Unable to create configuration server socket: "
<< socket->StrError();
std::exit(RunnerExitCodes::kConfigServerError);
}
- Command cmd(ConfigServerBinary());
+ cvd::Command cmd(config.config_server_binary());
cmd.AddParameter("-server_fd=", socket);
- return single_element_emplace(std::move(cmd));
+ process_monitor->StartSubprocess(std::move(cmd),
+ GetOnSubprocessExitCallback(config));
+ return { socket->VsockServerPort() };
}
-std::vector<Command> LaunchTombstoneReceiver(const CuttlefishConfig& config) {
+TombstoneReceiverPorts LaunchTombstoneReceiverIfEnabled(
+ const vsoc::CuttlefishConfig& config, cvd::ProcessMonitor* process_monitor) {
+ if (!config.enable_tombstone_receiver()) {
+ return {};
+ }
auto instance = config.ForDefaultInstance();
std::string tombstoneDir = instance.PerInstancePath("tombstones");
- if (!DirectoryExists(tombstoneDir.c_str())) {
- LOG(DEBUG) << "Setting up " << tombstoneDir;
+ if (!cvd::DirectoryExists(tombstoneDir.c_str())) {
+ LOG(INFO) << "Setting up " << tombstoneDir;
if (mkdir(tombstoneDir.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) <
0) {
LOG(ERROR) << "Failed to create tombstone directory: " << tombstoneDir
@@ -153,221 +229,139 @@ std::vector<Command> LaunchTombstoneReceiver(const CuttlefishConfig& config) {
}
}
- auto port = instance.tombstone_receiver_port();
- auto socket = SharedFD::VsockServer(port, SOCK_STREAM);
+ auto socket = cvd::SharedFD::VsockServer(SOCK_STREAM);
if (!socket->IsOpen()) {
LOG(ERROR) << "Unable to create tombstone server socket: "
<< socket->StrError();
std::exit(RunnerExitCodes::kTombstoneServerError);
return {};
}
- Command cmd(TombstoneReceiverBinary());
+ cvd::Command cmd(config.tombstone_receiver_binary());
cmd.AddParameter("-server_fd=", socket);
cmd.AddParameter("-tombstone_dir=", tombstoneDir);
- return single_element_emplace(std::move(cmd));
-}
-
-std::vector<Command> LaunchMetrics() {
- return single_element_emplace(Command(MetricsBinary()));
+ process_monitor->StartSubprocess(std::move(cmd),
+ GetOnSubprocessExitCallback(config));
+ return { socket->VsockServerPort() };
}
-std::vector<Command> LaunchGnssGrpcProxyServerIfEnabled(
- const CuttlefishConfig& config) {
- if (!config.enable_gnss_grpc_proxy() || !FileExists(GnssGrpcProxyBinary())) {
- return {};
- }
-
- Command gnss_grpc_proxy_cmd(GnssGrpcProxyBinary());
+StreamerLaunchResult LaunchVNCServer(
+ const vsoc::CuttlefishConfig& config,
+ cvd::ProcessMonitor* process_monitor,
+ std::function<bool(MonitorEntry*)> callback) {
auto instance = config.ForDefaultInstance();
+ // Launch the vnc server, don't wait for it to complete
+ auto port_options = "-port=" + std::to_string(instance.vnc_server_port());
+ cvd::Command vnc_server(config.vnc_server_binary());
+ vnc_server.AddParameter(port_options);
- auto gnss_in_pipe_name = instance.gnss_in_pipe_name();
- if (mkfifo(gnss_in_pipe_name.c_str(), 0600) != 0) {
- auto error = errno;
- LOG(ERROR) << "Failed to create gnss input fifo for crosvm: "
- << strerror(error);
- return {};
- }
+ auto server_ret = CreateStreamerServers(&vnc_server, config);
- auto gnss_out_pipe_name = instance.gnss_out_pipe_name();
- if (mkfifo(gnss_out_pipe_name.c_str(), 0660) != 0) {
- auto error = errno;
- LOG(ERROR) << "Failed to create gnss output fifo for crosvm: "
- << strerror(error);
- return {};
- }
+ process_monitor->StartSubprocess(std::move(vnc_server), callback);
+ server_ret.launched = true;
+ return server_ret;
+}
- // These fds will only be read from or written to, but open them with
- // read and write access to keep them open in case the subprocesses exit
- SharedFD gnss_grpc_proxy_in_wr =
- SharedFD::Open(gnss_in_pipe_name.c_str(), O_RDWR);
- if (!gnss_grpc_proxy_in_wr->IsOpen()) {
- LOG(ERROR) << "Failed to open gnss_grpc_proxy input fifo for writes: "
- << gnss_grpc_proxy_in_wr->StrError();
- return {};
- }
+void LaunchAdbConnectorIfEnabled(cvd::ProcessMonitor* process_monitor,
+ const vsoc::CuttlefishConfig& config,
+ cvd::SharedFD adbd_events_pipe) {
+ cvd::Command adb_connector(config.adb_connector_binary());
+ adb_connector.AddParameter("-adbd_events_fd=", adbd_events_pipe);
+ std::set<std::string> addresses;
- SharedFD gnss_grpc_proxy_out_rd =
- SharedFD::Open(gnss_out_pipe_name.c_str(), O_RDWR);
- if (!gnss_grpc_proxy_out_rd->IsOpen()) {
- LOG(ERROR) << "Failed to open gnss_grpc_proxy output fifo for reads: "
- << gnss_grpc_proxy_out_rd->StrError();
- return {};
+ if (AdbTcpConnectorEnabled(config)) {
+ addresses.insert(GetAdbConnectorTcpArg(config));
}
-
- const unsigned gnss_grpc_proxy_server_port =
- instance.gnss_grpc_proxy_server_port();
- gnss_grpc_proxy_cmd.AddParameter("--gnss_in_fd=", gnss_grpc_proxy_in_wr);
- gnss_grpc_proxy_cmd.AddParameter("--gnss_out_fd=", gnss_grpc_proxy_out_rd);
- gnss_grpc_proxy_cmd.AddParameter("--gnss_grpc_port=",
- gnss_grpc_proxy_server_port);
- if (!instance.gnss_file_path().empty()) {
- // If path is provided, proxy will start as local mode.
- gnss_grpc_proxy_cmd.AddParameter("--gnss_file_path=",
- instance.gnss_file_path());
+ if (AdbVsockConnectorEnabled(config)) {
+ addresses.insert(GetAdbConnectorVsockArg(config));
}
- return single_element_emplace(std::move(gnss_grpc_proxy_cmd));
-}
-std::vector<Command> LaunchBluetoothConnector(const CuttlefishConfig& config) {
- auto instance = config.ForDefaultInstance();
- std::vector<std::string> fifo_paths = {
- instance.PerInstanceInternalPath("bt_fifo_vm.in"),
- instance.PerInstanceInternalPath("bt_fifo_vm.out"),
- };
- std::vector<SharedFD> fifos;
- for (const auto& path : fifo_paths) {
- unlink(path.c_str());
- if (mkfifo(path.c_str(), 0660) < 0) {
- PLOG(ERROR) << "Could not create " << path;
- return {};
- }
- auto fd = SharedFD::Open(path, O_RDWR);
- if (!fd->IsOpen()) {
- LOG(ERROR) << "Could not open " << path << ": " << fd->StrError();
- return {};
+ if (addresses.size() > 0) {
+ std::string address_arg = "--addresses=";
+ for (auto& arg : addresses) {
+ address_arg += arg + ",";
}
- fifos.push_back(fd);
+ address_arg.pop_back();
+ adb_connector.AddParameter(address_arg);
+ process_monitor->StartSubprocess(std::move(adb_connector),
+ GetOnSubprocessExitCallback(config));
}
-
- Command command(DefaultHostArtifactsPath("bin/bt_connector"));
- command.AddParameter("-bt_out=", fifos[0]);
- command.AddParameter("-bt_in=", fifos[1]);
- command.AddParameter("-hci_port=", instance.rootcanal_hci_port());
- command.AddParameter("-link_port=", instance.rootcanal_link_port());
- command.AddParameter("-test_port=", instance.rootcanal_test_port());
- return single_element_emplace(std::move(command));
}
-std::vector<Command> LaunchSecureEnvironment(const CuttlefishConfig& config) {
- auto instance = config.ForDefaultInstance();
- std::vector<std::string> fifo_paths = {
- instance.PerInstanceInternalPath("keymaster_fifo_vm.in"),
- instance.PerInstanceInternalPath("keymaster_fifo_vm.out"),
- instance.PerInstanceInternalPath("gatekeeper_fifo_vm.in"),
- instance.PerInstanceInternalPath("gatekeeper_fifo_vm.out"),
- };
- std::vector<SharedFD> fifos;
- for (const auto& path : fifo_paths) {
- unlink(path.c_str());
- if (mkfifo(path.c_str(), 0600) < 0) {
- PLOG(ERROR) << "Could not create " << path;
- return {};
- }
- auto fd = SharedFD::Open(path, O_RDWR);
- if (!fd->IsOpen()) {
- LOG(ERROR) << "Could not open " << path << ": " << fd->StrError();
- return {};
- }
- fifos.push_back(fd);
- }
+StreamerLaunchResult LaunchWebRTC(cvd::ProcessMonitor* process_monitor,
+ const vsoc::CuttlefishConfig& config) {
+ cvd::Command webrtc(config.webrtc_binary());
- Command command(HostBinaryPath("secure_env"));
- command.AddParameter("-keymaster_fd_out=", fifos[0]);
- command.AddParameter("-keymaster_fd_in=", fifos[1]);
- command.AddParameter("-gatekeeper_fd_out=", fifos[2]);
- command.AddParameter("-gatekeeper_fd_in=", fifos[3]);
+ if (!config.webrtc_certs_dir().empty()) {
+ webrtc.AddParameter("--certs_dir=", config.webrtc_certs_dir());
+ }
- const auto& secure_hals = config.secure_hals();
- bool secure_keymint = secure_hals.count(SecureHal::Keymint) > 0;
- command.AddParameter("-keymint_impl=", secure_keymint ? "tpm" : "software");
- bool secure_gatekeeper = secure_hals.count(SecureHal::Gatekeeper) > 0;
- auto gatekeeper_impl = secure_gatekeeper ? "tpm" : "software";
- command.AddParameter("-gatekeeper_impl=", gatekeeper_impl);
+ webrtc.AddParameter("--http_server_port=", vsoc::ForCurrentInstance(8443));
+ webrtc.AddParameter("--public_ip=", config.webrtc_public_ip());
+ webrtc.AddParameter("--assets_dir=", config.webrtc_assets_dir());
- return single_element_emplace(std::move(command));
-}
+ auto server_ret = CreateStreamerServers(&webrtc, config);
-std::vector<Command> LaunchVehicleHalServerIfEnabled(
- const CuttlefishConfig& config) {
- if (!config.enable_vehicle_hal_grpc_server() ||
- !FileExists(config.vehicle_hal_grpc_server_binary())) {
- return {};
+ if (config.webrtc_enable_adb_websocket()) {
+ auto instance = config.ForDefaultInstance();
+ webrtc.AddParameter("--adb=", instance.adb_ip_and_port());
}
- Command grpc_server(config.vehicle_hal_grpc_server_binary());
- auto instance = config.ForDefaultInstance();
+ process_monitor->StartSubprocess(std::move(webrtc),
+ GetOnSubprocessExitCallback(config));
+ server_ret.launched = true;
- const unsigned vhal_server_cid = 2;
- const unsigned vhal_server_port = instance.vehicle_hal_server_port();
- const std::string vhal_server_power_state_file =
- AbsolutePath(instance.PerInstancePath("power_state"));
- const std::string vhal_server_power_state_socket =
- AbsolutePath(instance.PerInstancePath("power_state_socket"));
-
- grpc_server.AddParameter("--server_cid=", vhal_server_cid);
- grpc_server.AddParameter("--server_port=", vhal_server_port);
- grpc_server.AddParameter("--power_state_file=", vhal_server_power_state_file);
- grpc_server.AddParameter("--power_state_socket=", vhal_server_power_state_socket);
- return single_element_emplace(std::move(grpc_server));
+ return server_ret;
}
-std::vector<Command> LaunchConsoleForwarderIfEnabled(
- const CuttlefishConfig& config) {
- if (!config.console()) {
- return {};
- }
-
- Command console_forwarder_cmd(ConsoleForwarderBinary());
+void LaunchSocketVsockProxyIfEnabled(cvd::ProcessMonitor* process_monitor,
+ const vsoc::CuttlefishConfig& config) {
auto instance = config.ForDefaultInstance();
-
- auto console_in_pipe_name = instance.console_in_pipe_name();
- if (mkfifo(console_in_pipe_name.c_str(), 0600) != 0) {
- auto error = errno;
- LOG(ERROR) << "Failed to create console input fifo for crosvm: "
- << strerror(error);
- return {};
+ if (AdbVsockTunnelEnabled(config)) {
+ cvd::Command adb_tunnel(config.socket_vsock_proxy_binary());
+ adb_tunnel.AddParameter("--server=tcp");
+ adb_tunnel.AddParameter("--vsock_port=6520");
+ adb_tunnel.AddParameter(
+ std::string{"--tcp_port="} + std::to_string(instance.host_port()));
+ adb_tunnel.AddParameter(std::string{"--vsock_cid="} +
+ std::to_string(instance.vsock_guest_cid()));
+ process_monitor->StartSubprocess(std::move(adb_tunnel),
+ GetOnSubprocessExitCallback(config));
}
-
- auto console_out_pipe_name = instance.console_out_pipe_name();
- if (mkfifo(console_out_pipe_name.c_str(), 0660) != 0) {
- auto error = errno;
- LOG(ERROR) << "Failed to create console output fifo for crosvm: "
- << strerror(error);
- return {};
- }
-
- // These fds will only be read from or written to, but open them with
- // read and write access to keep them open in case the subprocesses exit
- SharedFD console_forwarder_in_wr =
- SharedFD::Open(console_in_pipe_name.c_str(), O_RDWR);
- if (!console_forwarder_in_wr->IsOpen()) {
- LOG(ERROR) << "Failed to open console_forwarder input fifo for writes: "
- << console_forwarder_in_wr->StrError();
- return {};
+ if (AdbVsockHalfTunnelEnabled(config)) {
+ cvd::Command adb_tunnel(config.socket_vsock_proxy_binary());
+ adb_tunnel.AddParameter("--server=tcp");
+ adb_tunnel.AddParameter("--vsock_port=5555");
+ adb_tunnel.AddParameter(
+ std::string{"--tcp_port="} + std::to_string(instance.host_port()));
+ adb_tunnel.AddParameter(std::string{"--vsock_cid="} +
+ std::to_string(instance.vsock_guest_cid()));
+ process_monitor->StartSubprocess(std::move(adb_tunnel),
+ GetOnSubprocessExitCallback(config));
}
+}
- SharedFD console_forwarder_out_rd =
- SharedFD::Open(console_out_pipe_name.c_str(), O_RDWR);
- if (!console_forwarder_out_rd->IsOpen()) {
- LOG(ERROR) << "Failed to open console_forwarder output fifo for reads: "
- << console_forwarder_out_rd->StrError();
- return {};
- }
+void LaunchVerhicleHalServerIfEnabled(const vsoc::CuttlefishConfig& config,
+ cvd::ProcessMonitor* process_monitor) {
+ if (!config.enable_vehicle_hal_grpc_server() &&
+ !cvd::FileExists(config.vehicle_hal_grpc_server_binary())) {
+ return;
+ }
- console_forwarder_cmd.AddParameter("--console_in_fd=", console_forwarder_in_wr);
- console_forwarder_cmd.AddParameter("--console_out_fd=", console_forwarder_out_rd);
- return single_element_emplace(std::move(console_forwarder_cmd));
+ cvd::Command grpc_server(config.vehicle_hal_grpc_server_binary());
+ auto instance = config.ForDefaultInstance();
+
+ const unsigned vhal_server_cid = 2;
+ const unsigned vhal_server_port = instance.vehicle_hal_server_port();
+ const std::string vhal_server_power_state_file =
+ cvd::AbsolutePath(instance.PerInstancePath("power_state"));
+ const std::string vhal_server_power_state_socket =
+ cvd::AbsolutePath(instance.PerInstancePath("power_state_socket"));
+
+ grpc_server.AddParameter("--server_cid=", vhal_server_cid);
+ grpc_server.AddParameter("--server_port=", vhal_server_port);
+ grpc_server.AddParameter("--power_state_file=", vhal_server_power_state_file);
+ grpc_server.AddParameter("--power_state_socket=", vhal_server_power_state_socket);
+ process_monitor->StartSubprocess(std::move(grpc_server),
+ GetOnSubprocessExitCallback(config));
}
-
-} // namespace cuttlefish
diff --git a/host/commands/run_cvd/launch.h b/host/commands/run_cvd/launch.h
index 30d5aff48..0a8756f53 100644
--- a/host/commands/run_cvd/launch.h
+++ b/host/commands/run_cvd/launch.h
@@ -1,65 +1,55 @@
-//
-// 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.
-
#pragma once
+#include <functional>
+#include <set>
#include <string>
-#include <vector>
#include "common/libs/fs/shared_fd.h"
#include "common/libs/utils/subprocess.h"
+#include "host/commands/run_cvd/process_monitor.h"
#include "host/libs/config/cuttlefish_config.h"
-namespace cuttlefish {
-
-struct KernelLogMonitorData {
- std::vector<SharedFD> pipes;
- std::vector<Command> commands;
+std::vector <cvd::SharedFD> LaunchKernelLogMonitor(
+ const vsoc::CuttlefishConfig& config,
+ cvd::ProcessMonitor* process_monitor,
+ unsigned int number_of_event_pipes);
+void LaunchAdbConnectorIfEnabled(cvd::ProcessMonitor* process_monitor,
+ const vsoc::CuttlefishConfig& config,
+ cvd::SharedFD adbd_events_pipe);
+void LaunchSocketVsockProxyIfEnabled(cvd::ProcessMonitor* process_monitor,
+ const vsoc::CuttlefishConfig& config);
+
+struct StreamerLaunchResult {
+ bool launched = false;
+ std::optional<unsigned int> frames_server_vsock_port;
+ std::optional<unsigned int> touch_server_vsock_port;
+ std::optional<unsigned int> keyboard_server_vsock_port;
};
+StreamerLaunchResult LaunchVNCServer(
+ const vsoc::CuttlefishConfig& config,
+ cvd::ProcessMonitor* process_monitor,
+ std::function<bool(cvd::MonitorEntry*)> callback);
-KernelLogMonitorData LaunchKernelLogMonitor(const CuttlefishConfig& config,
- unsigned int number_of_event_pipes);
-std::vector<Command> LaunchAdbConnectorIfEnabled(
- const CuttlefishConfig& config);
-std::vector<Command> LaunchSocketVsockProxyIfEnabled(
- const CuttlefishConfig& config, SharedFD adbd_events_pipe);
-std::vector<Command> LaunchModemSimulatorIfEnabled(
- const CuttlefishConfig& config);
-
-std::vector<Command> LaunchVNCServer(const CuttlefishConfig& config);
-
-std::vector<Command> LaunchTombstoneReceiver(const CuttlefishConfig& config);
-std::vector<Command> LaunchRootCanal(const CuttlefishConfig& config);
-std::vector<Command> LaunchLogcatReceiver(const CuttlefishConfig& config);
-std::vector<Command> LaunchConfigServer(const CuttlefishConfig& config);
-
-std::vector<Command> LaunchWebRTC(const CuttlefishConfig& config,
- SharedFD kernel_log_events_pipe);
-
-std::vector<Command> LaunchMetrics();
-
-std::vector<Command> LaunchGnssGrpcProxyServerIfEnabled(
- const CuttlefishConfig& config);
+struct TombstoneReceiverPorts {
+ std::optional<unsigned int> server_vsock_port;
+};
+TombstoneReceiverPorts LaunchTombstoneReceiverIfEnabled(
+ const vsoc::CuttlefishConfig& config, cvd::ProcessMonitor* process_monitor);
-std::vector<Command> LaunchSecureEnvironment(const CuttlefishConfig& config);
+struct ConfigServerPorts {
+ std::optional<unsigned int> server_vsock_port;
+};
+ConfigServerPorts LaunchConfigServer(const vsoc::CuttlefishConfig& config,
+ cvd::ProcessMonitor* process_monitor);
-std::vector<Command> LaunchBluetoothConnector(const CuttlefishConfig& config);
-std::vector<Command> LaunchVehicleHalServerIfEnabled(
- const CuttlefishConfig& config);
+struct LogcatServerPorts {
+ std::optional<unsigned int> server_vsock_port;
+};
+LogcatServerPorts LaunchLogcatReceiverIfEnabled(const vsoc::CuttlefishConfig& config,
+ cvd::ProcessMonitor* process_monitor);
-std::vector<Command> LaunchConsoleForwarderIfEnabled(
- const CuttlefishConfig& config);
+StreamerLaunchResult LaunchWebRTC(cvd::ProcessMonitor* process_monitor,
+ const vsoc::CuttlefishConfig& config);
-} // namespace cuttlefish
+void LaunchVerhicleHalServerIfEnabled(const vsoc::CuttlefishConfig& config,
+ cvd::ProcessMonitor* process_monitor);
diff --git a/host/commands/run_cvd/launch_adb.cpp b/host/commands/run_cvd/launch_adb.cpp
deleted file mode 100644
index b7996ee66..000000000
--- a/host/commands/run_cvd/launch_adb.cpp
+++ /dev/null
@@ -1,156 +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.
-
-#include "host/commands/run_cvd/launch.h"
-
-#include <android-base/logging.h>
-#include <set>
-#include <string>
-#include <utility>
-
-#include "common/libs/fs/shared_fd.h"
-#include "common/libs/utils/subprocess.h"
-#include "host/libs/config/cuttlefish_config.h"
-#include "host/libs/config/known_paths.h"
-
-namespace cuttlefish {
-
-namespace {
-
-std::string GetAdbConnectorTcpArg(const CuttlefishConfig& config) {
- auto instance = config.ForDefaultInstance();
- return std::string{"0.0.0.0:"} + std::to_string(instance.host_port());
-}
-
-std::string GetAdbConnectorVsockArg(const CuttlefishConfig& config) {
- auto instance = config.ForDefaultInstance();
- return std::string{"vsock:"} + std::to_string(instance.vsock_guest_cid()) +
- std::string{":5555"};
-}
-
-bool AdbModeEnabled(const CuttlefishConfig& config, AdbMode mode) {
- return config.adb_mode().count(mode) > 0;
-}
-
-bool AdbVsockTunnelEnabled(const CuttlefishConfig& config) {
- auto instance = config.ForDefaultInstance();
- return instance.vsock_guest_cid() > 2 &&
- AdbModeEnabled(config, AdbMode::VsockTunnel);
-}
-
-bool AdbVsockHalfTunnelEnabled(const CuttlefishConfig& config) {
- auto instance = config.ForDefaultInstance();
- return instance.vsock_guest_cid() > 2 &&
- AdbModeEnabled(config, AdbMode::VsockHalfTunnel);
-}
-
-bool AdbTcpConnectorEnabled(const CuttlefishConfig& config) {
- bool vsock_tunnel = AdbVsockTunnelEnabled(config);
- bool vsock_half_tunnel = AdbVsockHalfTunnelEnabled(config);
- return config.run_adb_connector() && (vsock_tunnel || vsock_half_tunnel);
-}
-
-bool AdbVsockConnectorEnabled(const CuttlefishConfig& config) {
- return config.run_adb_connector() &&
- AdbModeEnabled(config, AdbMode::NativeVsock);
-}
-
-} // namespace
-
-std::vector<Command> LaunchAdbConnectorIfEnabled(
- const CuttlefishConfig& config) {
- Command adb_connector(AdbConnectorBinary());
- std::set<std::string> addresses;
-
- if (AdbTcpConnectorEnabled(config)) {
- addresses.insert(GetAdbConnectorTcpArg(config));
- }
- if (AdbVsockConnectorEnabled(config)) {
- addresses.insert(GetAdbConnectorVsockArg(config));
- }
-
- if (addresses.size() == 0) {
- return {};
- }
- std::string address_arg = "--addresses=";
- for (auto& arg : addresses) {
- address_arg += arg + ",";
- }
- address_arg.pop_back();
- adb_connector.AddParameter(address_arg);
- std::vector<Command> commands;
- commands.emplace_back(std::move(adb_connector));
- return std::move(commands);
-}
-
-std::vector<Command> LaunchSocketVsockProxyIfEnabled(
- const CuttlefishConfig& config, SharedFD adbd_events_pipe) {
- auto instance = config.ForDefaultInstance();
- auto append = [](const std::string& s, const int i) -> std::string {
- return s + std::to_string(i);
- };
- auto tcp_server =
- SharedFD::SocketLocalServer(instance.host_port(), SOCK_STREAM);
- CHECK(tcp_server->IsOpen())
- << "Unable to create socket_vsock_proxy server socket: "
- << tcp_server->StrError();
- std::vector<Command> commands;
- if (AdbVsockTunnelEnabled(config)) {
- Command adb_tunnel(SocketVsockProxyBinary());
- adb_tunnel.AddParameter("-adbd_events_fd=", adbd_events_pipe);
- /**
- * This socket_vsock_proxy (a.k.a. sv proxy) runs on the host. It assumes
- * that another sv proxy runs inside the guest. see:
- * shared/config/init.vendor.rc The sv proxy in the guest exposes
- * vsock:cid:6520 across the cuttlefish instances in multi-tenancy. cid is
- * different per instance.
- *
- * This host sv proxy should cooperate with the guest sv proxy. Thus, one
- * end of the tunnel is vsock:cid:6520 regardless of instance number.
- * Another end faces the host adb daemon via tcp. Thus, the server type is
- * tcp here. The tcp port differs from instance to instance, and is
- * instance.host_port()
- *
- */
- adb_tunnel.AddParameter("--server=tcp");
- adb_tunnel.AddParameter("--vsock_port=6520");
- adb_tunnel.AddParameter(std::string{"--server_fd="}, tcp_server);
- adb_tunnel.AddParameter(std::string{"--vsock_cid="} +
- std::to_string(instance.vsock_guest_cid()));
- commands.emplace_back(std::move(adb_tunnel));
- }
- if (AdbVsockHalfTunnelEnabled(config)) {
- Command adb_tunnel(SocketVsockProxyBinary());
- adb_tunnel.AddParameter("-adbd_events_fd=", adbd_events_pipe);
- /*
- * This socket_vsock_proxy (a.k.a. sv proxy) runs on the host, and
- * cooperates with the adbd inside the guest. See this file:
- * shared/device.mk, especially the line says "persist.adb.tcp.port="
- *
- * The guest adbd is listening on vsock:cid:5555 across cuttlefish
- * instances. Sv proxy faces the host adb daemon via tcp. The server type
- * should be therefore tcp, and the port should differ from instance to
- * instance and be equal to instance.host_port()
- */
- adb_tunnel.AddParameter("--server=tcp");
- adb_tunnel.AddParameter(append("--vsock_port=", 5555));
- adb_tunnel.AddParameter(std::string{"--server_fd="}, tcp_server);
- adb_tunnel.AddParameter(append("--vsock_cid=", instance.vsock_guest_cid()));
- commands.emplace_back(std::move(adb_tunnel));
- }
- return commands;
-}
-
-} // namespace cuttlefish
diff --git a/host/commands/run_cvd/launch_modem.cpp b/host/commands/run_cvd/launch_modem.cpp
deleted file mode 100644
index 07af9f12c..000000000
--- a/host/commands/run_cvd/launch_modem.cpp
+++ /dev/null
@@ -1,117 +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.
-
-#include "host/commands/run_cvd/launch.h"
-
-#include <android-base/logging.h>
-#include <string.h>
-#include <sstream>
-#include <string>
-#include <utility>
-
-#include "common/libs/fs/shared_fd.h"
-#include "common/libs/utils/subprocess.h"
-#include "host/libs/config/cuttlefish_config.h"
-#include "host/libs/config/known_paths.h"
-
-namespace cuttlefish {
-
-static bool StopModemSimulator() {
- auto config = CuttlefishConfig::Get();
- auto instance = config->ForDefaultInstance();
-
- std::string monitor_socket_name = "modem_simulator";
- std::stringstream ss;
- ss << instance.host_port();
- monitor_socket_name.append(ss.str());
- auto monitor_sock = SharedFD::SocketLocalClient(monitor_socket_name.c_str(),
- true, SOCK_STREAM);
- if (!monitor_sock->IsOpen()) {
- LOG(ERROR) << "The connection to modem simulator is closed";
- return false;
- }
- std::string msg("STOP");
- if (monitor_sock->Write(msg.data(), msg.size()) < 0) {
- monitor_sock->Close();
- LOG(ERROR) << "Failed to send 'STOP' to modem simulator";
- return false;
- }
- char buf[64] = {0};
- if (monitor_sock->Read(buf, sizeof(buf)) <= 0) {
- monitor_sock->Close();
- LOG(ERROR) << "Failed to read message from modem simulator";
- return false;
- }
- if (strcmp(buf, "OK")) {
- monitor_sock->Close();
- LOG(ERROR) << "Read '" << buf << "' instead of 'OK' from modem simulator";
- return false;
- }
-
- return true;
-}
-
-std::vector<Command> LaunchModemSimulatorIfEnabled(
- const CuttlefishConfig& config) {
- if (!config.enable_modem_simulator()) {
- LOG(DEBUG) << "Modem simulator not enabled";
- return {};
- }
-
- int instance_number = config.modem_simulator_instance_number();
- if (instance_number > 3 /* max value */ || instance_number < 0) {
- LOG(ERROR)
- << "Modem simulator instance number should range between 1 and 3";
- return {};
- }
-
- Command cmd(ModemSimulatorBinary(), [](Subprocess* proc) {
- auto stopped = StopModemSimulator();
- if (stopped) {
- return true;
- }
- LOG(WARNING) << "Failed to stop modem simulator nicely, "
- << "attempting to KILL";
- return KillSubprocess(proc);
- });
-
- auto sim_type = config.modem_simulator_sim_type();
- cmd.AddParameter(std::string{"-sim_type="} + std::to_string(sim_type));
-
- auto instance = config.ForDefaultInstance();
- auto ports = instance.modem_simulator_ports();
- cmd.AddParameter("-server_fds=");
- for (int i = 0; i < instance_number; ++i) {
- auto pos = ports.find(',');
- auto temp = (pos != std::string::npos) ? ports.substr(0, pos) : ports;
- auto port = std::stoi(temp);
- ports = ports.substr(pos + 1);
-
- auto socket = SharedFD::VsockServer(port, SOCK_STREAM);
- CHECK(socket->IsOpen())
- << "Unable to create modem simulator server socket: "
- << socket->StrError();
- if (i > 0) {
- cmd.AppendToLastParameter(",");
- }
- cmd.AppendToLastParameter(socket);
- }
-
- std::vector<Command> commands;
- commands.emplace_back(std::move(cmd));
- return commands;
-}
-
-} // namespace cuttlefish
diff --git a/host/commands/run_cvd/launch_streamer.cpp b/host/commands/run_cvd/launch_streamer.cpp
deleted file mode 100644
index bf0d77d7d..000000000
--- a/host/commands/run_cvd/launch_streamer.cpp
+++ /dev/null
@@ -1,224 +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.
-
-#include "host/commands/run_cvd/launch.h"
-
-#include <android-base/logging.h>
-#include <string>
-#include <utility>
-
-#include "common/libs/fs/shared_buf.h"
-#include "common/libs/fs/shared_fd.h"
-#include "common/libs/utils/files.h"
-#include "host/libs/config/cuttlefish_config.h"
-#include "host/libs/config/known_paths.h"
-#include "host/libs/vm_manager/crosvm_manager.h"
-#include "host/libs/vm_manager/qemu_manager.h"
-
-namespace cuttlefish {
-
-namespace {
-
-SharedFD CreateUnixInputServer(const std::string& path) {
- auto server =
- SharedFD::SocketLocalServer(path.c_str(), false, SOCK_STREAM, 0666);
- if (!server->IsOpen()) {
- LOG(ERROR) << "Unable to create unix input server: " << server->StrError();
- return {};
- }
- return server;
-}
-
-// Creates the frame and input sockets and add the relevant arguments to the vnc
-// server and webrtc commands
-void CreateStreamerServers(Command* cmd, const CuttlefishConfig& config) {
- SharedFD touch_server;
- SharedFD keyboard_server;
-
- auto instance = config.ForDefaultInstance();
- if (config.vm_manager() == vm_manager::QemuManager::name()) {
- cmd->AddParameter("-write_virtio_input");
-
- touch_server =
- SharedFD::VsockServer(instance.touch_server_port(), SOCK_STREAM);
- keyboard_server =
- SharedFD::VsockServer(instance.keyboard_server_port(), SOCK_STREAM);
- } else {
- touch_server = CreateUnixInputServer(instance.touch_socket_path());
- keyboard_server = CreateUnixInputServer(instance.keyboard_socket_path());
- }
- if (!touch_server->IsOpen()) {
- LOG(ERROR) << "Could not open touch server: " << touch_server->StrError();
- return;
- }
- cmd->AddParameter("-touch_fd=", touch_server);
-
- if (!keyboard_server->IsOpen()) {
- LOG(ERROR) << "Could not open keyboard server: "
- << keyboard_server->StrError();
- return;
- }
- cmd->AddParameter("-keyboard_fd=", keyboard_server);
-
- if (config.enable_webrtc() &&
- config.vm_manager() == vm_manager::CrosvmManager::name()) {
- SharedFD switches_server =
- CreateUnixInputServer(instance.switches_socket_path());
- if (!switches_server->IsOpen()) {
- LOG(ERROR) << "Could not open switches server: "
- << switches_server->StrError();
- return;
- }
- cmd->AddParameter("-switches_fd=", switches_server);
- }
-
- SharedFD frames_server = CreateUnixInputServer(instance.frames_socket_path());
- if (!frames_server->IsOpen()) {
- LOG(ERROR) << "Could not open frames server: " << frames_server->StrError();
- return;
- }
- cmd->AddParameter("-frame_server_fd=", frames_server);
-
- if (config.enable_audio()) {
- auto path = config.ForDefaultInstance().audio_server_path();
- auto audio_server =
- SharedFD::SocketLocalServer(path.c_str(), false, SOCK_SEQPACKET, 0666);
- if (!audio_server->IsOpen()) {
- LOG(ERROR) << "Could not create audio server: "
- << audio_server->StrError();
- return;
- }
- cmd->AddParameter("--audio_server_fd=", audio_server);
- }
-}
-
-std::vector<Command> LaunchCustomActionServers(Command& webrtc_cmd,
- const CuttlefishConfig& config) {
- bool first = true;
- std::vector<Command> commands;
- for (const auto& custom_action : config.custom_actions()) {
- if (custom_action.server) {
- // Create a socket pair that will be used for communication between
- // WebRTC and the action server.
- SharedFD webrtc_socket, action_server_socket;
- if (!SharedFD::SocketPair(AF_LOCAL, SOCK_STREAM, 0, &webrtc_socket,
- &action_server_socket)) {
- LOG(ERROR) << "Unable to create custom action server socket pair: "
- << strerror(errno);
- continue;
- }
-
- // Launch the action server, providing its socket pair fd as the only
- // argument.
- std::string binary = "bin/" + *(custom_action.server);
- Command command(DefaultHostArtifactsPath(binary));
- command.AddParameter(action_server_socket);
- commands.emplace_back(std::move(command));
-
- // Pass the WebRTC socket pair fd to WebRTC.
- if (first) {
- first = false;
- webrtc_cmd.AddParameter("-action_servers=", *custom_action.server, ":",
- webrtc_socket);
- } else {
- webrtc_cmd.AppendToLastParameter(",", *custom_action.server, ":",
- webrtc_socket);
- }
- }
- }
- return commands;
-}
-
-} // namespace
-
-std::vector<Command> LaunchVNCServer(const CuttlefishConfig& config) {
- auto instance = config.ForDefaultInstance();
- // Launch the vnc server, don't wait for it to complete
- auto port_options = "-port=" + std::to_string(instance.vnc_server_port());
- Command vnc_server(VncServerBinary());
- vnc_server.AddParameter(port_options);
-
- CreateStreamerServers(&vnc_server, config);
-
- std::vector<Command> commands;
- commands.emplace_back(std::move(vnc_server));
- return std::move(commands);
-}
-
-std::vector<Command> LaunchWebRTC(const CuttlefishConfig& config,
- SharedFD kernel_log_events_pipe) {
- std::vector<Command> commands;
- if (config.ForDefaultInstance().start_webrtc_sig_server()) {
- Command sig_server(WebRtcSigServerBinary());
- sig_server.AddParameter("-assets_dir=", config.webrtc_assets_dir());
- if (!config.webrtc_certs_dir().empty()) {
- sig_server.AddParameter("-certs_dir=", config.webrtc_certs_dir());
- }
- sig_server.AddParameter("-http_server_port=", config.sig_server_port());
- commands.emplace_back(std::move(sig_server));
- }
-
- // Currently there is no way to ensure the signaling server will already have
- // bound the socket to the port by the time the webrtc process runs (the
- // common technique of doing it from the launcher is not possible here as the
- // server library being used creates its own sockets). However, this issue is
- // mitigated slightly by doing some retrying and backoff in the webrtc process
- // when connecting to the websocket, so it shouldn't be an issue most of the
- // time.
- SharedFD client_socket;
- SharedFD host_socket;
- CHECK(SharedFD::SocketPair(AF_LOCAL, SOCK_STREAM, 0, &client_socket,
- &host_socket))
- << "Could not open command socket for webRTC";
-
- auto stopper = [host_socket = std::move(host_socket)](Subprocess* proc) {
- struct timeval timeout;
- timeout.tv_sec = 3;
- timeout.tv_usec = 0;
- CHECK(host_socket->SetSockOpt(SOL_SOCKET, SO_RCVTIMEO, &timeout,
- sizeof(timeout)) == 0)
- << "Could not set receive timeout";
-
- WriteAll(host_socket, "C");
- char response[1];
- int read_ret = host_socket->Read(response, sizeof(response));
- if (read_ret != 0) {
- LOG(ERROR) << "Failed to read response from webrtc";
- }
- cuttlefish::KillSubprocess(proc);
- return true;
- };
-
- Command webrtc(WebRtcBinary(), SubprocessStopper(stopper));
-
- webrtc.UnsetFromEnvironment({"http_proxy"});
-
- CreateStreamerServers(&webrtc, config);
-
- webrtc.AddParameter("--command_fd=", client_socket);
- webrtc.AddParameter("-kernel_log_events_fd=", kernel_log_events_pipe);
-
- auto actions = LaunchCustomActionServers(webrtc, config);
-
- // TODO get from launcher params
- commands.emplace_back(std::move(webrtc));
- for (auto& action : actions) {
- commands.emplace_back(std::move(action));
- }
-
- return commands;
-}
-
-} // namespace cuttlefish
diff --git a/host/commands/run_cvd/main.cc b/host/commands/run_cvd/main.cc
index f40226a3a..ad684e39a 100644
--- a/host/commands/run_cvd/main.cc
+++ b/host/commands/run_cvd/main.cc
@@ -14,51 +14,147 @@
* limitations under the License.
*/
+#include <limits.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <fcntl.h>
#include <unistd.h>
-#include <fstream>
+
+#include <algorithm>
+#include <functional>
#include <iostream>
+#include <fstream>
+#include <iomanip>
#include <memory>
+#include <sstream>
#include <string>
-#include <utility>
+#include <thread>
#include <vector>
-#include <android-base/logging.h>
#include <android-base/strings.h>
#include <gflags/gflags.h>
+#include <android-base/logging.h>
#include "common/libs/fs/shared_buf.h"
#include "common/libs/fs/shared_fd.h"
+#include "common/libs/fs/shared_select.h"
#include "common/libs/utils/environment.h"
#include "common/libs/utils/files.h"
#include "common/libs/utils/network.h"
-#include "common/libs/utils/size_utils.h"
#include "common/libs/utils/subprocess.h"
+#include "common/libs/utils/size_utils.h"
+#include "host/commands/run_cvd/kernel_args.h"
#include "common/libs/utils/tee_logging.h"
-#include "host/commands/run_cvd/boot_state_machine.h"
#include "host/commands/run_cvd/launch.h"
-#include "host/commands/run_cvd/process_monitor.h"
#include "host/commands/run_cvd/runner_defs.h"
-#include "host/commands/run_cvd/server_loop.h"
+#include "host/commands/run_cvd/process_monitor.h"
#include "host/libs/config/cuttlefish_config.h"
-#include "host/libs/vm_manager/host_configuration.h"
+#include "host/commands/kernel_log_monitor/kernel_log_server.h"
+#include <host/libs/vm_manager/crosvm_manager.h>
#include "host/libs/vm_manager/vm_manager.h"
+#include "host/libs/vm_manager/qemu_manager.h"
-DEFINE_int32(reboot_notification_fd, -1,
- "A file descriptor to notify when boot completes.");
+using vsoc::ForCurrentInstance;
+using cvd::RunnerExitCodes;
-namespace cuttlefish {
+namespace {
-using vm_manager::GetVmManager;
-using vm_manager::ValidateHostConfiguration;
+cvd::OnSocketReadyCb GetOnSubprocessExitCallback(
+ const vsoc::CuttlefishConfig& config) {
+ if (config.restart_subprocesses()) {
+ return cvd::ProcessMonitor::RestartOnExitCb;
+ } else {
+ return cvd::ProcessMonitor::DoNotMonitorCb;
+ }
+}
-namespace {
+// Maintains the state of the boot process, once a final state is reached
+// (success or failure) it sends the appropriate exit code to the foreground
+// launcher process
+class CvdBootStateMachine {
+ public:
+ CvdBootStateMachine(cvd::SharedFD fg_launcher_pipe)
+ : fg_launcher_pipe_(fg_launcher_pipe), state_(kBootStarted) {}
+
+ // Returns true if the machine is left in a final state
+ bool OnBootEvtReceived(cvd::SharedFD boot_events_pipe) {
+ monitor::BootEvent evt;
+ auto bytes_read = boot_events_pipe->Read(&evt, sizeof(evt));
+ if (bytes_read != sizeof(evt)) {
+ LOG(ERROR) << "Fail to read a complete event, read " << bytes_read
+ << " bytes only instead of the expected " << sizeof(evt);
+ state_ |= kGuestBootFailed;
+ } else if (evt == monitor::BootEvent::BootCompleted) {
+ LOG(INFO) << "Virtual device booted successfully";
+ state_ |= kGuestBootCompleted;
+ } else if (evt == monitor::BootEvent::BootFailed) {
+ LOG(ERROR) << "Virtual device failed to boot";
+ state_ |= kGuestBootFailed;
+ } // Ignore the other signals
-constexpr char kGreenColor[] = "\033[1;32m";
-constexpr char kResetColor[] = "\033[0m";
+ return MaybeWriteToForegroundLauncher();
+ }
+
+ bool BootCompleted() const {
+ return state_ & kGuestBootCompleted;
+ }
+
+ bool BootFailed() const {
+ return state_ & kGuestBootFailed;
+ }
-bool WriteCuttlefishEnvironment(const CuttlefishConfig& config) {
- auto env = SharedFD::Open(config.cuttlefish_env_path().c_str(),
- O_CREAT | O_RDWR, 0755);
+ private:
+ void SendExitCode(cvd::RunnerExitCodes exit_code) {
+ fg_launcher_pipe_->Write(&exit_code, sizeof(exit_code));
+ // The foreground process will exit after receiving the exit code, if we try
+ // to write again we'll get a SIGPIPE
+ fg_launcher_pipe_->Close();
+ }
+ bool MaybeWriteToForegroundLauncher() {
+ if (fg_launcher_pipe_->IsOpen()) {
+ if (BootCompleted()) {
+ SendExitCode(cvd::RunnerExitCodes::kSuccess);
+ } else if (state_ & kGuestBootFailed) {
+ SendExitCode(cvd::RunnerExitCodes::kVirtualDeviceBootFailed);
+ } else {
+ // No final state was reached
+ return false;
+ }
+ }
+ // Either we sent the code before or just sent it, in any case the state is
+ // final
+ return true;
+ }
+
+ cvd::SharedFD fg_launcher_pipe_;
+ int state_;
+ static const int kBootStarted = 0;
+ static const int kGuestBootCompleted = 1 << 0;
+ static const int kGuestBootFailed = 1 << 1;
+};
+
+// Abuse the process monitor to make it call us back when boot events are ready
+void SetUpHandlingOfBootEvents(
+ cvd::ProcessMonitor* process_monitor, cvd::SharedFD boot_events_pipe,
+ std::shared_ptr<CvdBootStateMachine> state_machine) {
+ process_monitor->MonitorExistingSubprocess(
+ // A dummy command, so logs are desciptive
+ cvd::Command("boot_events_listener"),
+ // A dummy subprocess, with the boot events pipe as control socket
+ cvd::Subprocess(-1, boot_events_pipe),
+ [boot_events_pipe, state_machine](cvd::MonitorEntry*) {
+ auto sent_code = state_machine->OnBootEvtReceived(boot_events_pipe);
+ return !sent_code;
+ });
+}
+
+bool WriteCuttlefishEnvironment(const vsoc::CuttlefishConfig& config) {
+ auto env = cvd::SharedFD::Open(config.cuttlefish_env_path().c_str(),
+ O_CREAT | O_RDWR, 0755);
if (!env->IsOpen()) {
LOG(ERROR) << "Unable to create cuttlefish.env file";
return false;
@@ -73,12 +169,12 @@ bool WriteCuttlefishEnvironment(const CuttlefishConfig& config) {
// Forks and returns the write end of a pipe to the child process. The parent
// process waits for boot events to come through the pipe and exits accordingly.
-SharedFD DaemonizeLauncher(const CuttlefishConfig& config) {
+cvd::SharedFD DaemonizeLauncher(const vsoc::CuttlefishConfig& config) {
auto instance = config.ForDefaultInstance();
- SharedFD read_end, write_end;
- if (!SharedFD::Pipe(&read_end, &write_end)) {
+ cvd::SharedFD read_end, write_end;
+ if (!cvd::SharedFD::Pipe(&read_end, &write_end)) {
LOG(ERROR) << "Unable to create pipe";
- return {}; // a closed FD
+ return cvd::SharedFD(); // a closed FD
}
auto pid = fork();
if (pid) {
@@ -99,9 +195,9 @@ SharedFD DaemonizeLauncher(const CuttlefishConfig& config) {
LOG(ERROR) << "Unexpected exit code: " << exit_code;
}
if (exit_code == RunnerExitCodes::kSuccess) {
- LOG(INFO) << kBootCompletedMessage;
+ LOG(INFO) << vsoc::kBootCompletedMessage;
} else {
- LOG(INFO) << kBootFailedMessage;
+ LOG(INFO) << vsoc::kBootFailedMessage;
}
std::exit(exit_code);
} else {
@@ -112,15 +208,17 @@ SharedFD DaemonizeLauncher(const CuttlefishConfig& config) {
}
// Redirect standard I/O
auto log_path = instance.launcher_log_path();
- auto log = SharedFD::Open(log_path.c_str(), O_CREAT | O_WRONLY | O_APPEND,
- S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
+ auto log =
+ cvd::SharedFD::Open(log_path.c_str(), O_CREAT | O_WRONLY | O_APPEND,
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
if (!log->IsOpen()) {
LOG(ERROR) << "Failed to create launcher log file: " << log->StrError();
std::exit(RunnerExitCodes::kDaemonizationError);
}
- ::android::base::SetLogger(
- TeeLogger({{LogFileSeverity(), log, MetadataLevel::FULL}}));
- auto dev_null = SharedFD::Open("/dev/null", O_RDONLY);
+ ::android::base::SetLogger(cvd::TeeLogger({
+ {cvd::LogFileSeverity(), log},
+ }));
+ auto dev_null = cvd::SharedFD::Open("/dev/null", O_RDONLY);
if (!dev_null->IsOpen()) {
LOG(ERROR) << "Failed to open /dev/null: " << dev_null->StrError();
std::exit(RunnerExitCodes::kDaemonizationError);
@@ -143,29 +241,48 @@ SharedFD DaemonizeLauncher(const CuttlefishConfig& config) {
}
}
-std::string GetConfigFilePath(const CuttlefishConfig& config) {
- auto instance = config.ForDefaultInstance();
- return instance.PerInstancePath("cuttlefish_config.json");
+void ServerLoop(cvd::SharedFD server,
+ cvd::ProcessMonitor* process_monitor) {
+ while (true) {
+ // TODO: use select to handle simultaneous connections.
+ auto client = cvd::SharedFD::Accept(*server);
+ cvd::LauncherAction action;
+ while (client->IsOpen() && client->Read(&action, sizeof(action)) > 0) {
+ switch (action) {
+ case cvd::LauncherAction::kStop:
+ if (process_monitor->StopMonitoredProcesses()) {
+ auto response = cvd::LauncherResponse::kSuccess;
+ client->Write(&response, sizeof(response));
+ std::exit(0);
+ } else {
+ auto response = cvd::LauncherResponse::kError;
+ client->Write(&response, sizeof(response));
+ }
+ break;
+ case cvd::LauncherAction::kStatus: {
+ // TODO(schuffelen): Return more information on a side channel
+ auto response = cvd::LauncherResponse::kSuccess;
+ client->Write(&response, sizeof(response));
+ break;
+ }
+ default:
+ LOG(ERROR) << "Unrecognized launcher action: "
+ << static_cast<char>(action);
+ auto response = cvd::LauncherResponse::kError;
+ client->Write(&response, sizeof(response));
+ }
+ }
+ }
}
-void PrintStreamingInformation(const CuttlefishConfig& config) {
- if (config.ForDefaultInstance().start_webrtc_sig_server()) {
- // TODO (jemoreira): Change this when webrtc is moved to the debian package.
- LOG(INFO) << kGreenColor << "Point your browser to https://"
- << config.sig_server_address() << ":" << config.sig_server_port()
- << " to interact with the device." << kResetColor;
- } else if (config.enable_vnc_server()) {
- LOG(INFO) << kGreenColor << "VNC server started on port "
- << config.ForDefaultInstance().vnc_server_port() << kResetColor;
- }
- // When WebRTC is enabled but an operator other than the one launched by
- // run_cvd is used there is no way to know the url to which to point the
- // browser to.
+std::string GetConfigFilePath(const vsoc::CuttlefishConfig& config) {
+ auto instance = config.ForDefaultInstance();
+ return instance.PerInstancePath("cuttlefish_config.json");
}
} // namespace
-int RunCvdMain(int argc, char** argv) {
+int main(int argc, char** argv) {
setenv("ANDROID_LOG_TAGS", "*:v", /* overwrite */ 0);
::android::base::InitLogging(argv, android::base::StderrLogger);
google::ParseCommandLineFlags(&argc, &argv, false);
@@ -173,20 +290,20 @@ int RunCvdMain(int argc, char** argv) {
if (isatty(0)) {
LOG(FATAL) << "stdin was a tty, expected to be passed the output of a previous stage. "
<< "Did you mean to run launch_cvd?";
- return RunnerExitCodes::kInvalidHostConfiguration;
+ return cvd::RunnerExitCodes::kInvalidHostConfiguration;
} else {
int error_num = errno;
if (error_num == EBADF) {
LOG(FATAL) << "stdin was not a valid file descriptor, expected to be passed the output "
<< "of assemble_cvd. Did you mean to run launch_cvd?";
- return RunnerExitCodes::kInvalidHostConfiguration;
+ return cvd::RunnerExitCodes::kInvalidHostConfiguration;
}
}
std::string input_files_str;
{
- auto input_fd = SharedFD::Dup(0);
- auto bytes_read = ReadAll(input_fd, &input_files_str);
+ auto input_fd = cvd::SharedFD::Dup(0);
+ auto bytes_read = cvd::ReadAll(input_fd, &input_files_str);
if (bytes_read < 0) {
LOG(FATAL) << "Failed to read input files. Error was \"" << input_fd->StrError() << "\"";
}
@@ -196,28 +313,24 @@ int RunCvdMain(int argc, char** argv) {
for (const auto& file : input_files) {
if (file.find("cuttlefish_config.json") != std::string::npos) {
found_config = true;
- setenv(kCuttlefishConfigEnvVarName, file.c_str(), /* overwrite */ false);
+ setenv(vsoc::kCuttlefishConfigEnvVarName, file.c_str(), /* overwrite */ false);
}
}
if (!found_config) {
return RunnerExitCodes::kCuttlefishConfigurationInitError;
}
- auto config = CuttlefishConfig::Get();
+ auto config = vsoc::CuttlefishConfig::Get();
auto instance = config->ForDefaultInstance();
auto log_path = instance.launcher_log_path();
{
std::ofstream launcher_log_ofstream(log_path.c_str());
- auto assembly_path = config->AssemblyPath("assemble_cvd.log");
- std::ifstream assembly_log_ifstream(assembly_path);
- if (assembly_log_ifstream) {
- auto assemble_log = ReadFile(assembly_path);
- launcher_log_ofstream << assemble_log;
- }
+ auto assemble_log = cvd::ReadFile(config->AssemblyPath("assemble_cvd.log"));
+ launcher_log_ofstream << assemble_log;
}
- ::android::base::SetLogger(LogToStderrAndFiles({log_path}));
+ ::android::base::SetLogger(cvd::LogToStderrAndFiles({log_path}));
// Change working directory to the instance directory as early as possible to
// ensure all host processes have the same working dir. This helps stop_cvd
@@ -231,24 +344,20 @@ int RunCvdMain(int argc, char** argv) {
return RunnerExitCodes::kInstanceDirCreationError;
}
- auto used_tap_devices = TapInterfacesInUse();
+ auto used_tap_devices = cvd::TapInterfacesInUse();
if (used_tap_devices.count(instance.wifi_tap_name())) {
LOG(ERROR) << "Wifi TAP device already in use";
return RunnerExitCodes::kTapDeviceInUse;
} else if (used_tap_devices.count(instance.mobile_tap_name())) {
LOG(ERROR) << "Mobile TAP device already in use";
return RunnerExitCodes::kTapDeviceInUse;
- } else if (config->ethernet() &&
- used_tap_devices.count(instance.ethernet_tap_name())) {
- LOG(ERROR) << "Ethernet TAP device already in use";
}
- auto vm_manager = GetVmManager(config->vm_manager(), config->target_arch());
+ auto vm_manager = vm_manager::VmManager::Get(config->vm_manager(), config);
-#ifndef __ANDROID__
// Check host configuration
std::vector<std::string> config_commands;
- if (!ValidateHostConfiguration(&config_commands)) {
+ if (!vm_manager->ValidateHostConfiguration(&config_commands)) {
LOG(ERROR) << "Validation of user configuration failed";
std::cout << "Execute the following to correctly configure:" << std::endl;
for (auto& command : config_commands) {
@@ -258,51 +367,31 @@ int RunCvdMain(int argc, char** argv) {
<< std::endl;
return RunnerExitCodes::kInvalidHostConfiguration;
}
-#endif
if (!WriteCuttlefishEnvironment(*config)) {
LOG(ERROR) << "Unable to write cuttlefish environment file";
}
- PrintStreamingInformation(*config);
-
- if (config->console()) {
- LOG(INFO) << kGreenColor << "To access the console run: screen "
- << instance.console_path() << kResetColor;
- } else {
- LOG(INFO) << kGreenColor
- << "Serial console is disabled; use -console=true to enable it"
- << kResetColor;
+ LOG(INFO) << "The following files contain useful debugging information:";
+ if (config->run_as_daemon()) {
+ LOG(INFO) << " Launcher log: " << instance.launcher_log_path();
}
-
- LOG(INFO) << kGreenColor
- << "The following files contain useful debugging information:"
- << kResetColor;
- LOG(INFO) << kGreenColor
- << " Launcher log: " << instance.launcher_log_path()
- << kResetColor;
- LOG(INFO) << kGreenColor
- << " Android's logcat output: " << instance.logcat_path()
- << kResetColor;
- LOG(INFO) << kGreenColor
- << " Kernel log: " << instance.PerInstancePath("kernel.log")
- << kResetColor;
- LOG(INFO) << kGreenColor
- << " Instance configuration: " << GetConfigFilePath(*config)
- << kResetColor;
- LOG(INFO) << kGreenColor
- << " Instance environment: " << config->cuttlefish_env_path()
- << kResetColor;
+ LOG(INFO) << " Android's logcat output: " << instance.logcat_path();
+ LOG(INFO) << " Kernel log: " << instance.PerInstancePath("kernel.log");
+ LOG(INFO) << " Instance configuration: " << GetConfigFilePath(*config);
+ LOG(INFO) << " Instance environment: " << config->cuttlefish_env_path();
+ LOG(INFO) << "To access the console run: socat file:$(tty),raw,echo=0 "
+ << instance.console_path();
auto launcher_monitor_path = instance.launcher_monitor_socket_path();
- auto launcher_monitor_socket = SharedFD::SocketLocalServer(
+ auto launcher_monitor_socket = cvd::SharedFD::SocketLocalServer(
launcher_monitor_path.c_str(), false, SOCK_STREAM, 0666);
if (!launcher_monitor_socket->IsOpen()) {
LOG(ERROR) << "Error when opening launcher server: "
<< launcher_monitor_socket->StrError();
- return RunnerExitCodes::kMonitorCreationFailed;
+ return cvd::RunnerExitCodes::kMonitorCreationFailed;
}
- SharedFD foreground_launcher_pipe;
+ cvd::SharedFD foreground_launcher_pipe;
if (config->run_as_daemon()) {
foreground_launcher_pipe = DaemonizeLauncher(*config);
if (!foreground_launcher_pipe->IsOpen()) {
@@ -320,70 +409,69 @@ int RunCvdMain(int argc, char** argv) {
}
}
- SharedFD reboot_notification;
- if (FLAGS_reboot_notification_fd >= 0) {
- reboot_notification = SharedFD::Dup(FLAGS_reboot_notification_fd);
- close(FLAGS_reboot_notification_fd);
- }
+ auto boot_state_machine =
+ std::make_shared<CvdBootStateMachine>(foreground_launcher_pipe);
// Monitor and restart host processes supporting the CVD
- ProcessMonitor process_monitor(config->restart_subprocesses());
+ cvd::ProcessMonitor process_monitor;
- if (config->enable_metrics() == CuttlefishConfig::kYes) {
- process_monitor.AddCommands(LaunchMetrics());
- }
- process_monitor.AddCommands(LaunchModemSimulatorIfEnabled(*config));
-
- auto kernel_log_monitor = LaunchKernelLogMonitor(*config, 3);
- SharedFD boot_events_pipe = kernel_log_monitor.pipes[0];
- SharedFD adbd_events_pipe = kernel_log_monitor.pipes[1];
- SharedFD webrtc_events_pipe = kernel_log_monitor.pipes[2];
- kernel_log_monitor.pipes.clear();
- process_monitor.AddCommands(std::move(kernel_log_monitor.commands));
-
- CvdBootStateMachine boot_state_machine(foreground_launcher_pipe,
- reboot_notification, boot_events_pipe);
-
- process_monitor.AddCommands(LaunchRootCanal(*config));
- process_monitor.AddCommands(LaunchLogcatReceiver(*config));
- process_monitor.AddCommands(LaunchConfigServer(*config));
- process_monitor.AddCommands(LaunchTombstoneReceiver(*config));
- process_monitor.AddCommands(LaunchGnssGrpcProxyServerIfEnabled(*config));
- process_monitor.AddCommands(LaunchSecureEnvironment(*config));
- if (config->enable_host_bluetooth()) {
- process_monitor.AddCommands(LaunchBluetoothConnector(*config));
- }
- process_monitor.AddCommands(LaunchVehicleHalServerIfEnabled(*config));
- process_monitor.AddCommands(LaunchConsoleForwarderIfEnabled(*config));
+ auto event_pipes =
+ LaunchKernelLogMonitor(*config, &process_monitor, 2);
+ cvd::SharedFD boot_events_pipe = event_pipes[0];
+ cvd::SharedFD adbd_events_pipe = event_pipes[1];
+ event_pipes.clear();
+
+ std::set<std::string> extra_kernel_cmdline;
+
+ SetUpHandlingOfBootEvents(&process_monitor, boot_events_pipe,
+ boot_state_machine);
+
+ auto logcat_server = LaunchLogcatReceiverIfEnabled(*config, &process_monitor);
+ auto logcat_server_args = KernelCommandLineFromLogcatServer(logcat_server);
+
+ auto config_server = LaunchConfigServer(*config, &process_monitor);
+ auto config_server_args = KernelCommandLineFromConfigServer(config_server);
+
+ auto tombstone_server = LaunchTombstoneReceiverIfEnabled(*config, &process_monitor);
+ auto tombstone_kernel_args = KernelCommandLineFromTombstone(tombstone_server);
+
+ LaunchVerhicleHalServerIfEnabled(*config, &process_monitor);
// The streamer needs to launch before the VMM because it serves on several
// sockets (input devices, vsock frame server) when using crosvm.
+ StreamerLaunchResult streamer_config;
if (config->enable_vnc_server()) {
- process_monitor.AddCommands(LaunchVNCServer(*config));
+ streamer_config = LaunchVNCServer(
+ *config, &process_monitor, GetOnSubprocessExitCallback(*config));
}
if (config->enable_webrtc()) {
- process_monitor.AddCommands(LaunchWebRTC(*config, webrtc_events_pipe));
+ streamer_config = LaunchWebRTC(&process_monitor, *config);
}
+ auto streamer_kernel_args = KernelCommandLineFromStreamer(streamer_config);
+
+ auto kernel_args = KernelCommandLineFromConfig(*config);
+ kernel_args.insert(kernel_args.end(), streamer_kernel_args.begin(),
+ streamer_kernel_args.end());
+ kernel_args.insert(kernel_args.end(), tombstone_kernel_args.begin(),
+ tombstone_kernel_args.end());
+ kernel_args.insert(kernel_args.end(), config_server_args.begin(), config_server_args.end());
+ kernel_args.insert(kernel_args.end(), logcat_server_args.begin(), logcat_server_args.end());
+
// Start the guest VM
- process_monitor.AddCommands(vm_manager->StartCommands(*config));
+ vm_manager->WithFrontend(streamer_config.launched);
+ vm_manager->WithKernelCommandLine(android::base::Join(kernel_args, " "));
+ auto vmm_commands = vm_manager->StartCommands();
+ for (auto& vmm_cmd: vmm_commands) {
+ process_monitor.StartSubprocess(std::move(vmm_cmd),
+ GetOnSubprocessExitCallback(*config));
+ }
// Start other host processes
- process_monitor.AddCommands(
- LaunchSocketVsockProxyIfEnabled(*config, adbd_events_pipe));
- process_monitor.AddCommands(LaunchAdbConnectorIfEnabled(*config));
-
- CHECK(process_monitor.StartAndMonitorProcesses())
- << "Could not start subprocesses";
+ LaunchSocketVsockProxyIfEnabled(&process_monitor, *config);
+ LaunchAdbConnectorIfEnabled(&process_monitor, *config, adbd_events_pipe);
ServerLoop(launcher_monitor_socket, &process_monitor); // Should not return
LOG(ERROR) << "The server loop returned, it should never happen!!";
-
- return RunnerExitCodes::kServerError;
-}
-
-} // namespace cuttlefish
-
-int main(int argc, char** argv) {
- return cuttlefish::RunCvdMain(argc, argv);
+ return cvd::RunnerExitCodes::kServerError;
}
diff --git a/host/frontend/webrtc/lib/audio_sink.h b/host/commands/run_cvd/pre_launch_initializers.h
index e54170b02..79f6eedc6 100644
--- a/host/frontend/webrtc/lib/audio_sink.h
+++ b/host/commands/run_cvd/pre_launch_initializers.h
@@ -1,5 +1,7 @@
+#pragma once
+
/*
- * Copyright (C) 2020 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.
@@ -14,21 +16,19 @@
* limitations under the License.
*/
-#pragma once
-
#include <memory>
-#include "host/frontend/webrtc/lib/audio_frame_buffer.h"
+#include <host/libs/config/cuttlefish_config.h>
-namespace cuttlefish {
-namespace webrtc_streaming {
+// Handles initialization of regions that require it strictly before the virtual
+// machine is started.
+// To add initializers for more regions declare here, implement in its own
+// source file and call from PreLaunchInitializers::Initialize().
+void InitializeScreenRegion(const vsoc::CuttlefishConfig& config);
-class AudioSink {
+class PreLaunchInitializers {
public:
- virtual ~AudioSink() = default;
- virtual void OnFrame(std::shared_ptr<AudioFrameBuffer> frame,
- int64_t timestamp_us) = 0;
+ static void Initialize(const vsoc::CuttlefishConfig& config) {
+ InitializeScreenRegion(config);
+ }
};
-
-} // namespace webrtc_streaming
-} // namespace cuttlefish
diff --git a/host/commands/run_cvd/process_monitor.cc b/host/commands/run_cvd/process_monitor.cc
index a4f7f7263..e1b276168 100644
--- a/host/commands/run_cvd/process_monitor.cc
+++ b/host/commands/run_cvd/process_monitor.cc
@@ -14,9 +14,6 @@
* limitations under the License.
*/
-#include "host/commands/run_cvd/process_monitor.h"
-
-#include <sys/prctl.h>
#include <sys/types.h>
#include <sys/wait.h>
@@ -25,194 +22,199 @@
#include <signal.h>
#include <stdio.h>
-#include <algorithm>
-#include <thread>
+#include <map>
#include <android-base/logging.h>
-#include "common/libs/fs/shared_buf.h"
#include "common/libs/fs/shared_select.h"
+#include "host/commands/run_cvd/process_monitor.h"
-namespace cuttlefish {
+namespace cvd {
-struct ParentToChildMessage {
- bool stop;
-};
+namespace {
-ProcessMonitor::ProcessMonitor(bool restart_subprocesses)
- : restart_subprocesses_(restart_subprocesses), monitor_(-1) {
+void NotifyThread(SharedFD fd) {
+ // The restarter thread is (likely) blocked on a call to select, to make it
+ // wake up and do some work we write something (anything, the content is not
+ // important) into the main side of the socket pair so that the call to select
+ // returns and the notification fd (restarter side of the socket pair) is
+ // marked as ready to read.
+ char buffer = 'a';
+ fd->Write(&buffer, sizeof(buffer));
}
-void ProcessMonitor::AddCommand(Command cmd) {
- CHECK(monitor_ == -1) << "The monitor process is already running.";
- CHECK(!monitor_socket_->IsOpen()) << "The monitor socket is already open.";
-
- monitored_processes_.push_back(MonitorEntry());
- auto& entry = monitored_processes_.back();
- entry.cmd.reset(new Command(std::move(cmd)));
+void ConsumeNotifications(SharedFD fd) {
+ // Once the starter thread is waken up due to a notification, the calls to
+ // select will continue to return immediately unless we read what was written
+ // on the main side of the socket pair. More than one notification can
+ // accumulate before the restarter thread consumes them, so we attempt to read
+ // more than it's written to consume them all at once. In the unlikely case of
+ // more than 8 notifications acummulating we simply read the first 8 and have
+ // another iteration on the restarter thread loop.
+ char buffer[8];
+ fd->Read(buffer, sizeof(buffer));
}
-bool ProcessMonitor::StopMonitoredProcesses() {
- if (monitor_ == -1) {
- LOG(ERROR) << "The monitor process is already dead.";
- return false;
- }
- if (!monitor_socket_->IsOpen()) {
- LOG(ERROR) << "The monitor socket is already closed.";
- return false;
- }
- ParentToChildMessage message;
- message.stop = true;
- if (WriteAllBinary(monitor_socket_, &message) != sizeof(message)) {
- LOG(ERROR) << "Failed to communicate with monitor socket: "
- << monitor_socket_->StrError();
- return false;
- }
- pid_t last_monitor = monitor_;
- monitor_ = -1;
- monitor_socket_->Close();
- int wstatus;
- if (waitpid(last_monitor, &wstatus, 0) != last_monitor) {
- LOG(ERROR) << "Failed to wait for monitor process";
- return false;
- }
- if (WIFSIGNALED(wstatus)) {
- LOG(ERROR) << "Monitor process exited due to a signal";
- return false;
- }
- if (!WIFEXITED(wstatus)) {
- LOG(ERROR) << "Monitor process exited for unknown reasons";
- return false;
+} // namespace
+
+ProcessMonitor::ProcessMonitor() {
+ if (!SharedFD::SocketPair(AF_LOCAL, SOCK_STREAM, 0, &thread_comm_main_,
+ &thread_comm_monitor_)) {
+ LOG(ERROR) << "Unable to create restarter communication socket pair: "
+ << strerror(errno);
+ return;
}
- if (WEXITSTATUS(wstatus) != 0) {
- LOG(ERROR) << "Monitor process exited with code " << WEXITSTATUS(wstatus);
- return false;
+ monitor_thread_ = std::thread([this]() { MonitorRoutine(); });
+}
+
+void ProcessMonitor::StartSubprocess(Command cmd, OnSocketReadyCb callback) {
+ cvd::SubprocessOptions options;
+ options.InGroup(true);
+ options.WithControlSocket(true);
+ auto proc = cmd.Start(options);
+ if (!proc.Started()) {
+ LOG(ERROR) << "Failed to start process";
+ return;
}
- return true;
+ MonitorExistingSubprocess(std::move(cmd), std::move(proc), callback);
}
-bool ProcessMonitor::StartAndMonitorProcesses() {
- if (monitor_ != -1) {
- LOG(ERROR) << "The monitor process was already started";
- return false;
+void ProcessMonitor::MonitorExistingSubprocess(Command cmd, Subprocess proc,
+ OnSocketReadyCb callback) {
+ {
+ std::lock_guard<std::mutex> lock(processes_mutex_);
+ monitored_processes_.push_back(MonitorEntry());
+ auto& entry = monitored_processes_.back();
+ entry.cmd.reset(new Command(std::move(cmd)));
+ entry.proc.reset(new Subprocess(std::move(proc)));
+ entry.on_control_socket_ready_cb = callback;
}
- if (monitor_socket_->IsOpen()) {
- LOG(ERROR) << "The monitor socket was already opened.";
- return false;
+ // Wake the restarter thread up so that it starts monitoring this subprocess
+ // Do this after releasing the lock so that the restarter thread is free to
+ // begin work as soon as select returns.
+ NotifyThread(thread_comm_main_);
+}
+
+bool ProcessMonitor::StopMonitoredProcesses() {
+ // Because the mutex is held while this function executes, the restarter
+ // thread is kept blocked and by the time it resumes execution there are no
+ // more processes to monitor
+ std::lock_guard<std::mutex> lock(processes_mutex_);
+ bool result = true;
+ // Processes were started in the order they appear in the vector, stop them in
+ // reverse order for symmetry.
+ for (auto entry_it = monitored_processes_.rbegin();
+ entry_it != monitored_processes_.rend(); ++entry_it) {
+ auto& entry = *entry_it;
+ result = result && entry.proc->Stop();
}
- SharedFD client_pipe, host_pipe;
- if (!SharedFD::Pipe(&client_pipe, &host_pipe)) {
- LOG(ERROR) << "Could not create the monitor socket.";
- return false;
+ // Wait for all processes to actually exit.
+ for (auto& entry : monitored_processes_) {
+ // Most processes are being killed by signals, calling Wait(void) would be
+ // too verbose on the logs.
+ int wstatus;
+ auto ret = entry.proc->Wait(&wstatus, 0);
+ if (ret < 0) {
+ LOG(WARNING) << "Failed to wait for process "
+ << entry.cmd->GetShortName();
+ }
}
- monitor_ = fork();
- if (monitor_ == 0) {
- monitor_socket_ = client_pipe;
- host_pipe->Close();
- std::exit(MonitorRoutine() ? 0 : 1);
- } else {
- client_pipe->Close();
- monitor_socket_ = host_pipe;
+ // Clear the list to ensure they are not started again
+ monitored_processes_.clear();
+ return result;
+}
+
+bool ProcessMonitor::RestartOnExitCb(MonitorEntry* entry) {
+ // Make sure the process actually exited
+ char buffer[16];
+ auto bytes_read = entry->proc->control_socket()->Read(buffer, sizeof(buffer));
+ if (bytes_read > 0) {
+ LOG(WARNING) << "Subprocess " << entry->cmd->GetShortName() << " wrote "
+ << bytes_read
+ << " bytes on the control socket, this is unexpected";
+ // The process may not have exited, continue monitoring without restarting
return true;
}
-}
-static void LogSubprocessExit(const std::string& name, pid_t pid, int wstatus) {
- LOG(INFO) << "Detected exit of monitored subprocess " << name;
+ LOG(INFO) << "Detected exit of monitored subprocess";
+ // Make sure the subprocess isn't left in a zombie state, and that the
+ // pid is logged
+ int wstatus;
+ auto wait_ret = TEMP_FAILURE_RETRY(entry->proc->Wait(&wstatus, 0));
+ // None of the error conditions specified on waitpid(2) apply
+ assert(wait_ret > 0);
if (WIFEXITED(wstatus)) {
- LOG(INFO) << "Subprocess " << name << " (" << pid
+ LOG(INFO) << "Subprocess " << entry->cmd->GetShortName() << " (" << wait_ret
<< ") has exited with exit code " << WEXITSTATUS(wstatus);
} else if (WIFSIGNALED(wstatus)) {
- LOG(ERROR) << "Subprocess " << name << " (" << pid
+ LOG(ERROR) << "Subprocess " << entry->cmd->GetShortName() << " ("
+ << wait_ret
<< ") was interrupted by a signal: " << WTERMSIG(wstatus);
} else {
- LOG(INFO) << "subprocess " << name << " (" << pid
+ LOG(INFO) << "subprocess " << entry->cmd->GetShortName() << " (" << wait_ret
<< ") has exited for unknown reasons";
}
+ cvd::SubprocessOptions options;
+ options.WithControlSocket(true);
+ entry->proc.reset(new Subprocess(entry->cmd->Start(options)));
+ return true;
}
-bool ProcessMonitor::MonitorRoutine() {
- // Make this process a subreaper to reliably catch subprocess exits.
- // See https://man7.org/linux/man-pages/man2/prctl.2.html
- prctl(PR_SET_CHILD_SUBREAPER, 1);
- prctl(PR_SET_PDEATHSIG, SIGHUP); // Die when parent dies
-
- LOG(DEBUG) << "Starting monitoring subprocesses";
- for (auto& monitored : monitored_processes_) {
- cuttlefish::SubprocessOptions options;
- options.InGroup(true);
- monitored.proc.reset(new Subprocess(monitored.cmd->Start(options)));
- CHECK(monitored.proc->Started()) << "Failed to start process";
- }
-
- bool running = true;
- std::thread parent_comms_thread([&running, this]() {
- LOG(DEBUG) << "Waiting for a `stop` message from the parent.";
- while (running) {
- ParentToChildMessage message;
- CHECK(ReadExactBinary(monitor_socket_, &message) == sizeof(message))
- << "Could not read message from parent.";
- if (message.stop) {
- running = false;
- // Wake up the wait() loop by giving it an exited child process
- if (fork() == 0) {
- std::exit(0);
+bool ProcessMonitor::DoNotMonitorCb(MonitorEntry*) { return false; }
+
+void ProcessMonitor::MonitorRoutine() {
+ LOG(INFO) << "Started monitoring subprocesses";
+ do {
+ SharedFDSet read_set;
+ read_set.Set(thread_comm_monitor_);
+ {
+ std::lock_guard<std::mutex> lock(processes_mutex_);
+ for (auto& monitored_process : monitored_processes_) {
+ auto control_socket = monitored_process.proc->control_socket();
+ if (!control_socket->IsOpen()) {
+ LOG(ERROR) << "The control socket for "
+ << monitored_process.cmd->GetShortName()
+ << " is closed, it's effectively NOT being monitored";
}
+ read_set.Set(control_socket);
}
}
- });
-
- auto& monitored = monitored_processes_;
-
- LOG(DEBUG) << "Monitoring subprocesses";
- while(running) {
- int wstatus;
- pid_t pid = wait(&wstatus);
- int error_num = errno;
- CHECK(pid != -1) << "Wait failed: " << strerror(error_num);
- if (!WIFSIGNALED(wstatus) && !WIFEXITED(wstatus)) {
- LOG(DEBUG) << "Unexpected status from wait: " << wstatus
- << " for pid " << pid;
- continue;
- }
- if (!running) { // Avoid extra restarts near the end
- break;
+ // We can't call select while holding the lock as it would lead to a
+ // deadlock (restarter thread waiting for notifications from main thread,
+ // main thread waiting for the lock)
+ int num_fds = cvd::Select(&read_set, nullptr, nullptr, nullptr);
+ if (num_fds < 0) {
+ LOG(ERROR) << "Select call returned error on restarter thread: "
+ << strerror(errno);
}
- auto matches = [pid](const auto& it) { return it.proc->pid() == pid; };
- auto it = std::find_if(monitored.begin(), monitored.end(), matches);
- if (it == monitored.end()) {
- LogSubprocessExit("(unknown)", pid, wstatus);
- } else {
- LogSubprocessExit(it->cmd->GetShortName(), it->proc->pid(), wstatus);
- if (restart_subprocesses_) {
- cuttlefish::SubprocessOptions options;
- options.InGroup(true);
- it->proc.reset(new Subprocess(it->cmd->Start(options)));
- } else {
- monitored_processes_.erase(it);
+ if (num_fds > 0) {
+ // Try the communication fd, it's the most likely to be set
+ if (read_set.IsSet(thread_comm_monitor_)) {
+ --num_fds;
+ ConsumeNotifications(thread_comm_monitor_);
}
}
- }
-
- parent_comms_thread.join(); // Should have exited if `running` is false
- // Processes were started in the order they appear in the vector, stop them in
- // reverse order for symmetry.
- auto stop = [](const auto& it) {
- if (!it.proc->Stop()) {
- LOG(WARNING) << "Error in stopping \"" << it.cmd->GetShortName() << "\"";
- return false;
- }
- int wstatus = 0;
- auto ret = it.proc->Wait(&wstatus, 0);
- if (ret < 0) {
- LOG(WARNING) << "Failed to wait for process " << it.cmd->GetShortName();
- return false;
+ {
+ std::lock_guard<std::mutex> lock(processes_mutex_);
+ // Keep track of the number of file descriptors ready for read, chances
+ // are we don't need to go over the entire list of subprocesses
+ auto it = monitored_processes_.begin();
+ while (it != monitored_processes_.end()) {
+ auto control_socket = it->proc->control_socket();
+ bool keep_monitoring = true;
+ if (read_set.IsSet(control_socket)) {
+ --num_fds;
+ keep_monitoring = it->on_control_socket_ready_cb(&(*it));
+ }
+ if (keep_monitoring) {
+ ++it;
+ } else {
+ it = monitored_processes_.erase(it);
+ }
+ }
}
- return true;
- };
- size_t stopped = std::count_if(monitored.rbegin(), monitored.rend(), stop);
- LOG(DEBUG) << "Done monitoring subprocesses";
- return stopped == monitored.size();
+ assert(num_fds == 0);
+ } while (true);
}
-} // namespace cuttlefish
+} // namespace cvd
diff --git a/host/commands/run_cvd/process_monitor.h b/host/commands/run_cvd/process_monitor.h
index 18b8ab8dc..5683c61b1 100644
--- a/host/commands/run_cvd/process_monitor.h
+++ b/host/commands/run_cvd/process_monitor.h
@@ -22,43 +22,44 @@
#include <common/libs/utils/subprocess.h>
-namespace cuttlefish {
+namespace cvd {
struct MonitorEntry;
-using OnSocketReadyCb = std::function<bool(MonitorEntry*, int)>;
+using OnSocketReadyCb = std::function<bool(MonitorEntry*)>;
struct MonitorEntry {
std::unique_ptr<Command> cmd;
std::unique_ptr<Subprocess> proc;
+ OnSocketReadyCb on_control_socket_ready_cb;
};
// Keeps track of launched subprocesses, restarts them if they unexpectedly exit
class ProcessMonitor {
public:
- ProcessMonitor(bool restart_subprocesses);
- // Adds a command to the list of commands to be run and monitored. The
- // callback will be called when the subprocess has ended. If the callback
- // returns false the subprocess will no longer be monitored. Can only be
- // called before StartAndMonitorProcesses is called. OnSocketReadyCb will be
- // called inside a forked process.
- void AddCommand(Command cmd);
- template <typename T>
- void AddCommands(T&& commands) {
- for (auto& command : commands) {
- AddCommand(std::move(command));
- }
- }
-
- // Start all processes given by AddCommand.
- bool StartAndMonitorProcesses();
+ ProcessMonitor();
+ // Starts a managed subprocess with a controlling socket.
+ // The on_control_socket_ready_cb callback will be called when data is ready
+ // to be read from the socket or the subprocess has ended. No member functions
+ // of the process monitor object should be called from the callback as it may
+ // lead to a deadlock. If the callback returns false the subprocess will no
+ // longer be monitored.
+ void StartSubprocess(Command cmd, OnSocketReadyCb on_control_socket_ready_cb);
+ // Monitors an already started subprocess
+ void MonitorExistingSubprocess(Command cmd, Subprocess sub_process,
+ OnSocketReadyCb on_control_socket_ready_cb);
// Stops all monitored subprocesses.
bool StopMonitoredProcesses();
+ static bool RestartOnExitCb(MonitorEntry* entry);
+ static bool DoNotMonitorCb(MonitorEntry* entry);
+
private:
- bool MonitorRoutine();
+ void MonitorRoutine();
- bool restart_subprocesses_;
std::vector<MonitorEntry> monitored_processes_;
- pid_t monitor_;
- SharedFD monitor_socket_;
+ // Used for communication with the restarter thread
+ cvd::SharedFD thread_comm_main_, thread_comm_monitor_;
+ std::thread monitor_thread_;
+ // Protects access to the monitored_processes_
+ std::mutex processes_mutex_;
};
-} // namespace cuttlefish
+} // namespace cvd
diff --git a/host/commands/run_cvd/runner_defs.h b/host/commands/run_cvd/runner_defs.h
index b51e89451..daf88686f 100644
--- a/host/commands/run_cvd/runner_defs.h
+++ b/host/commands/run_cvd/runner_defs.h
@@ -15,7 +15,10 @@
*/
#pragma once
-namespace cuttlefish {
+namespace cvd {
+
+constexpr char kLogcatSerialMode[] = "serial";
+constexpr char kLogcatVsockMode[] = "vsock";
enum RunnerExitCodes : int {
kSuccess = 0,
@@ -42,15 +45,10 @@ enum RunnerExitCodes : int {
kTombstoneDirCreationError = 21,
kInitRamFsConcatError = 22,
kTapDeviceInUse = 23,
- kTpmPassthroughError = 24,
- kModemSimulatorServerError = 25,
- kSocketProxyServerError = 26,
};
// Actions supported by the launcher server
enum class LauncherAction : char {
- kPowerwash = 'P',
- kRestart = 'R',
kStatus = 'I',
kStop = 'X',
};
@@ -61,4 +59,4 @@ enum class LauncherResponse : char {
kError = 'E',
kUnknownAction = 'U',
};
-} // namespace cuttlefish
+} // namespace cvd
diff --git a/host/commands/run_cvd/server_loop.cpp b/host/commands/run_cvd/server_loop.cpp
deleted file mode 100644
index 5e77b9da7..000000000
--- a/host/commands/run_cvd/server_loop.cpp
+++ /dev/null
@@ -1,213 +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.
- */
-
-#include "host/commands/run_cvd/server_loop.h"
-
-#include <gflags/gflags.h>
-#include <unistd.h>
-#include <string>
-
-#include "common/libs/fs/shared_buf.h"
-#include "common/libs/utils/files.h"
-#include "common/libs/utils/subprocess.h"
-#include "host/commands/run_cvd/runner_defs.h"
-#include "host/libs/config/cuttlefish_config.h"
-#include "host/libs/config/data_image.h"
-
-namespace cuttlefish {
-
-namespace {
-
-bool CreateQcowOverlay(const std::string& crosvm_path,
- const std::string& backing_file,
- const std::string& output_overlay_path) {
- Command crosvm_qcow2_cmd(crosvm_path);
- crosvm_qcow2_cmd.AddParameter("create_qcow2");
- crosvm_qcow2_cmd.AddParameter("--backing_file=", backing_file);
- crosvm_qcow2_cmd.AddParameter(output_overlay_path);
- int success = crosvm_qcow2_cmd.Start().Wait();
- if (success != 0) {
- LOG(ERROR) << "Unable to run crosvm create_qcow2. Exited with status "
- << success;
- return false;
- }
- return true;
-}
-
-void DeleteFifos(const CuttlefishConfig::InstanceSpecific& instance) {
- // TODO(schuffelen): Create these FIFOs in assemble_cvd instead of run_cvd.
- std::vector<std::string> pipes = {
- instance.kernel_log_pipe_name(),
- instance.console_in_pipe_name(),
- instance.console_out_pipe_name(),
- instance.logcat_pipe_name(),
- instance.PerInstanceInternalPath("keymaster_fifo_vm.in"),
- instance.PerInstanceInternalPath("keymaster_fifo_vm.out"),
- instance.PerInstanceInternalPath("gatekeeper_fifo_vm.in"),
- instance.PerInstanceInternalPath("gatekeeper_fifo_vm.out"),
- instance.PerInstanceInternalPath("bt_fifo_vm.in"),
- instance.PerInstanceInternalPath("bt_fifo_vm.out"),
- };
- for (const auto& pipe : pipes) {
- unlink(pipe.c_str());
- }
-}
-
-bool PowerwashFiles() {
- auto config = CuttlefishConfig::Get();
- if (!config) {
- LOG(ERROR) << "Could not load the config.";
- return false;
- }
- auto instance = config->ForDefaultInstance();
-
- DeleteFifos(instance);
-
- // TODO(schuffelen): Clean up duplication with assemble_cvd
- auto kregistry_path = instance.access_kregistry_path();
- unlink(kregistry_path.c_str());
- CreateBlankImage(kregistry_path, 2 /* mb */, "none");
-
- auto pstore_path = instance.pstore_path();
- unlink(pstore_path.c_str());
- CreateBlankImage(pstore_path, 2 /* mb */, "none");
-
- auto sdcard_path = instance.sdcard_path();
- auto sdcard_size = FileSize(sdcard_path);
- unlink(sdcard_path.c_str());
- // round up
- auto sdcard_mb_size = (sdcard_size + (1 << 20) - 1) / (1 << 20);
- LOG(DEBUG) << "Size in mb is " << sdcard_mb_size;
- CreateBlankImage(sdcard_path, sdcard_mb_size, "sdcard");
-
- auto overlay_path = instance.PerInstancePath("overlay.img");
- unlink(overlay_path.c_str());
- if (!CreateQcowOverlay(config->crosvm_binary(),
- instance.os_composite_disk_path(), overlay_path)) {
- LOG(ERROR) << "CreateQcowOverlay failed";
- return false;
- }
- return true;
-}
-
-void RestartRunCvd(const CuttlefishConfig& config, int notification_fd) {
- auto config_path = config.AssemblyPath("cuttlefish_config.json");
- auto followup_stdin = SharedFD::MemfdCreate("pseudo_stdin");
- WriteAll(followup_stdin, config_path + "\n");
- followup_stdin->LSeek(0, SEEK_SET);
- followup_stdin->UNMANAGED_Dup2(0);
-
- auto argv_vec = gflags::GetArgvs();
- char** argv = new char*[argv_vec.size() + 2];
- for (size_t i = 0; i < argv_vec.size(); i++) {
- argv[i] = argv_vec[i].data();
- }
- // Will take precedence over any earlier arguments.
- std::string reboot_notification =
- "-reboot_notification_fd=" + std::to_string(notification_fd);
- argv[argv_vec.size()] = reboot_notification.data();
- argv[argv_vec.size() + 1] = nullptr;
-
- execv("/proc/self/exe", argv);
- // execve should not return, so something went wrong.
- PLOG(ERROR) << "execv returned: ";
-}
-
-} // namespace
-
-void ServerLoop(SharedFD server, ProcessMonitor* process_monitor) {
- while (true) {
- // TODO: use select to handle simultaneous connections.
- auto client = SharedFD::Accept(*server);
- LauncherAction action;
- while (client->IsOpen() && client->Read(&action, sizeof(action)) > 0) {
- switch (action) {
- case LauncherAction::kStop:
- if (process_monitor->StopMonitoredProcesses()) {
- auto response = LauncherResponse::kSuccess;
- client->Write(&response, sizeof(response));
- std::exit(0);
- } else {
- auto response = LauncherResponse::kError;
- client->Write(&response, sizeof(response));
- }
- break;
- case LauncherAction::kStatus: {
- // TODO(schuffelen): Return more information on a side channel
- auto response = LauncherResponse::kSuccess;
- client->Write(&response, sizeof(response));
- break;
- }
- case LauncherAction::kPowerwash: {
- LOG(INFO) << "Received a Powerwash request from the monitor socket";
- if (!process_monitor->StopMonitoredProcesses()) {
- LOG(ERROR) << "Stopping processes failed.";
- auto response = LauncherResponse::kError;
- client->Write(&response, sizeof(response));
- break;
- }
- if (!PowerwashFiles()) {
- LOG(ERROR) << "Powerwashing files failed.";
- auto response = LauncherResponse::kError;
- client->Write(&response, sizeof(response));
- break;
- }
- auto response = LauncherResponse::kSuccess;
- client->Write(&response, sizeof(response));
-
- auto config = CuttlefishConfig::Get();
- CHECK(config) << "Could not load config";
- RestartRunCvd(*config, client->UNMANAGED_Dup());
- // RestartRunCvd should not return, so something went wrong.
- response = LauncherResponse::kError;
- client->Write(&response, sizeof(response));
- LOG(FATAL) << "run_cvd in a bad state";
- break;
- }
- case LauncherAction::kRestart: {
- if (!process_monitor->StopMonitoredProcesses()) {
- LOG(ERROR) << "Stopping processes failed.";
- auto response = LauncherResponse::kError;
- client->Write(&response, sizeof(response));
- break;
- }
-
- auto config = CuttlefishConfig::Get();
- CHECK(config) << "Could not load config";
- auto instance = config->ForDefaultInstance();
- DeleteFifos(instance);
-
- auto response = LauncherResponse::kSuccess;
- client->Write(&response, sizeof(response));
- CHECK(config) << "Could not load config";
- RestartRunCvd(*config, client->UNMANAGED_Dup());
- // RestartRunCvd should not return, so something went wrong.
- response = LauncherResponse::kError;
- client->Write(&response, sizeof(response));
- LOG(FATAL) << "run_cvd in a bad state";
- break;
- }
- default:
- LOG(ERROR) << "Unrecognized launcher action: "
- << static_cast<char>(action);
- auto response = LauncherResponse::kError;
- client->Write(&response, sizeof(response));
- }
- }
- }
-}
-
-} // namespace cuttlefish
diff --git a/host/commands/secure_env/Android.bp b/host/commands/secure_env/Android.bp
deleted file mode 100644
index 3ceeda507..000000000
--- a/host/commands/secure_env/Android.bp
+++ /dev/null
@@ -1,77 +0,0 @@
-//
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-cc_binary_host {
- name: "secure_env",
- srcs: [
- "composite_serialization.cpp",
- "device_tpm.cpp",
- "encrypted_serializable.cpp",
- "fragile_tpm_storage.cpp",
- "gatekeeper_responder.cpp",
- "hmac_serializable.cpp",
- "in_process_tpm.cpp",
- "insecure_fallback_storage.cpp",
- "json_serializable.cpp",
- "keymaster_responder.cpp",
- "primary_key_builder.cpp",
- "secure_env.cpp",
- "tpm_attestation_record.cpp",
- "tpm_auth.cpp",
- "tpm_commands.cpp",
- "tpm_encrypt_decrypt.cpp",
- "tpm_gatekeeper.cpp",
- "tpm_hmac.cpp",
- "tpm_key_blob_maker.cpp",
- "tpm_keymaster_context.cpp",
- "tpm_keymaster_enforcement.cpp",
- "tpm_random_source.cpp",
- "tpm_resource_manager.cpp",
- "tpm_serialize.cpp",
- ],
- shared_libs: [
- "libbase",
- "libcuttlefish_fs",
- "libcuttlefish_security",
- "libcuttlefish_utils",
- "libgatekeeper",
- "libjsoncpp",
- "libkeymaster_portable",
- "libkeymaster_messages",
- "libsoft_attestation_cert",
- "liblog",
- "libcrypto",
- "libcutils",
- "libpuresoftkeymasterdevice_host",
- "ms-tpm-20-ref-lib",
- "tpm2-tss2-esys",
- "tpm2-tss2-mu",
- "tpm2-tss2-rc",
- "tpm2-tss2-tcti",
- ],
- static_libs: [
- "libcuttlefish_host_config",
- "libgflags",
- "libscrypt_static",
- ],
- defaults: ["cuttlefish_buildhost_only"],
- cflags: [
- "-fno-rtti", // Required for libkeymaster_portable
- ],
-}
diff --git a/host/commands/secure_env/OWNERS b/host/commands/secure_env/OWNERS
deleted file mode 100644
index f9d83f225..000000000
--- a/host/commands/secure_env/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-include platform/system/keymaster:/OWNERS
-include platform/system/gatekeeper:/OWNERS
diff --git a/host/commands/secure_env/composite_serialization.cpp b/host/commands/secure_env/composite_serialization.cpp
deleted file mode 100644
index e3d6e433c..000000000
--- a/host/commands/secure_env/composite_serialization.cpp
+++ /dev/null
@@ -1,48 +0,0 @@
-//
-// Copyright (C) 2020 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 "composite_serialization.h"
-
-using keymaster::Serializable;
-
-CompositeSerializable::CompositeSerializable(
- const std::vector<Serializable*>& members) : members_(members) {
-}
-
-size_t CompositeSerializable::SerializedSize() const {
- size_t sum = 0;
- for (const auto& member : members_) {
- sum += member->SerializedSize();
- }
- return sum;
-}
-
-uint8_t* CompositeSerializable::Serialize(
- uint8_t* buf, const uint8_t* end) const {
- for (const auto& member : members_) {
- buf = member->Serialize(buf, end);
- }
- return buf;
-}
-
-bool CompositeSerializable::Deserialize(
- const uint8_t** buf_ptr, const uint8_t* end) {
- for (const auto& member : members_) {
- if (!member->Deserialize(buf_ptr, end)) {
- return false;
- }
- }
- return true;
-}
diff --git a/host/commands/secure_env/composite_serialization.h b/host/commands/secure_env/composite_serialization.h
deleted file mode 100644
index dfe288391..000000000
--- a/host/commands/secure_env/composite_serialization.h
+++ /dev/null
@@ -1,39 +0,0 @@
-//
-// Copyright (C) 2020 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 <vector>
-
-#include "keymaster/serializable.h"
-
-/**
- * A keymaster::Serializable type that refers to multiple other
- * keymaster::Serializable instances by pointer. When data is serialized or
- * deserialized, it's delegated to the instances pointed to.
- *
- * The serialization format is to put the instances one after the other in
- * the byte stream.
- */
-class CompositeSerializable : public keymaster::Serializable {
-public:
- CompositeSerializable(const std::vector<keymaster::Serializable*>&);
-
- size_t SerializedSize() const override;
- uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const override;
- bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end) override;
-private:
- std::vector<keymaster::Serializable*> members_;
-};
diff --git a/host/commands/secure_env/device_tpm.cpp b/host/commands/secure_env/device_tpm.cpp
deleted file mode 100644
index 6e4b4bea3..000000000
--- a/host/commands/secure_env/device_tpm.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-//
-// Copyright (C) 2020 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 "host/commands/secure_env/device_tpm.h"
-
-#include <android-base/logging.h>
-#include <tss2/tss2_rc.h>
-#include <tss2/tss2_tcti.h>
-#include <tss2/tss2_tcti_device.h>
-
-static void FinalizeTcti(TSS2_TCTI_CONTEXT* tcti_context) {
- if (tcti_context == nullptr) {
- return;
- }
- auto finalize_fn = TSS2_TCTI_FINALIZE(tcti_context);
- if (finalize_fn != nullptr) {
- finalize_fn(tcti_context);
- }
- delete[] (char*) tcti_context;
-}
-
-DeviceTpm::DeviceTpm(const std::string& path) : tpm_(nullptr, &FinalizeTcti) {
- size_t size = 0;
- auto rc = Tss2_Tcti_Device_Init(nullptr, &size, path.c_str());
- if (rc != TSS2_RC_SUCCESS) {
- LOG(ERROR) << "Could not get Device TCTI size: " << Tss2_RC_Decode(rc)
- << "(" << rc << ")";
- return;
- }
- tpm_.reset(reinterpret_cast<TSS2_TCTI_CONTEXT*>(new char[size]));
- rc = Tss2_Tcti_Device_Init(tpm_.get(), &size, path.c_str());
- if (rc != TSS2_RC_SUCCESS) {
- LOG(ERROR) << "Could not create Device TCTI: " << Tss2_RC_Decode(rc)
- << "(" << rc << ")";
- delete[] (char*) tpm_.release();
- return;
- }
-}
-
-TSS2_TCTI_CONTEXT* DeviceTpm::TctiContext() {
- return tpm_.get();
-}
diff --git a/host/commands/secure_env/device_tpm.h b/host/commands/secure_env/device_tpm.h
deleted file mode 100644
index a52666edb..000000000
--- a/host/commands/secure_env/device_tpm.h
+++ /dev/null
@@ -1,35 +0,0 @@
-//
-// Copyright (C) 2020 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 <memory>
-
-#include <tss2/tss2_tcti.h>
-
-#include "host/commands/secure_env/tpm.h"
-
-/*
- * Exposes a TSS2_TCTI_CONTEXT for interacting with a TPM device node.
- */
-class DeviceTpm : public Tpm {
-public:
- DeviceTpm(const std::string& path);
- ~DeviceTpm() = default;
-
- TSS2_TCTI_CONTEXT* TctiContext() override;
-private:
- std::unique_ptr<TSS2_TCTI_CONTEXT, void(*)(TSS2_TCTI_CONTEXT*)> tpm_;
-};
diff --git a/host/commands/secure_env/encrypted_serializable.cpp b/host/commands/secure_env/encrypted_serializable.cpp
deleted file mode 100644
index 3845212c5..000000000
--- a/host/commands/secure_env/encrypted_serializable.cpp
+++ /dev/null
@@ -1,300 +0,0 @@
-//
-// Copyright (C) 2020 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 "encrypted_serializable.h"
-
-#include <vector>
-
-#include <android-base/logging.h>
-
-#include "host/commands/secure_env/tpm_auth.h"
-#include "host/commands/secure_env/tpm_encrypt_decrypt.h"
-#include "host/commands/secure_env/tpm_serialize.h"
-
-EncryptedSerializable::EncryptedSerializable(
- TpmResourceManager& resource_manager,
- std::function<TpmObjectSlot(TpmResourceManager&)> parent_key_fn,
- Serializable& wrapped) :
- resource_manager_(resource_manager),
- parent_key_fn_(parent_key_fn),
- wrapped_(wrapped) {
-}
-
-static bool CreateKey(
- TpmResourceManager& resource_manager, // in
- ESYS_TR parent_key, // in
- TPM2B_PUBLIC* key_public_out, // out
- TPM2B_PRIVATE* key_private_out, // out
- TpmObjectSlot* key_slot_out) { // out
- TPM2B_AUTH authValue = {};
- auto rc = Esys_TR_SetAuth(resource_manager.Esys(), parent_key, &authValue);
- if (rc != TSS2_RC_SUCCESS) {
- LOG(ERROR) << "Esys_TR_SetAuth failed with return code " << rc
- << " (" << Tss2_RC_Decode(rc) << ")";
- return false;
- }
-
- TPMT_PUBLIC public_area = {
- .type = TPM2_ALG_SYMCIPHER,
- .nameAlg = TPM2_ALG_SHA256,
- .objectAttributes = (TPMA_OBJECT_USERWITHAUTH |
- TPMA_OBJECT_DECRYPT |
- TPMA_OBJECT_SIGN_ENCRYPT |
- TPMA_OBJECT_FIXEDTPM |
- TPMA_OBJECT_FIXEDPARENT |
- TPMA_OBJECT_SENSITIVEDATAORIGIN),
- .authPolicy.size = 0,
- .parameters.symDetail.sym = {
- .algorithm = TPM2_ALG_AES,
- .keyBits.aes = 128, // The default maximum AES key size in the simulator.
- .mode.aes = TPM2_ALG_CFB,
- },
- };
-
- TPM2B_TEMPLATE public_template = {};
- size_t offset = 0;
- rc = Tss2_MU_TPMT_PUBLIC_Marshal(&public_area, &public_template.buffer[0],
- sizeof(public_template.buffer), &offset);
- if (rc != TSS2_RC_SUCCESS) {
- LOG(ERROR) << "Tss2_MU_TPMT_PUBLIC_Marshal failed with return code " << rc
- << " (" << Tss2_RC_Decode(rc) << ")";
- return false;
- }
- public_template.size = offset;
-
- TPM2B_SENSITIVE_CREATE in_sensitive = {};
-
- auto key_slot = resource_manager.ReserveSlot();
- if (!key_slot) {
- LOG(ERROR) << "No slots available";
- return false;
- }
- ESYS_TR raw_handle;
- // TODO(b/154956668): Define better ACLs on these keys.
- TPM2B_PUBLIC* key_public = nullptr;
- TPM2B_PRIVATE* key_private = nullptr;
- // TODO(schuffelen): Use Esys_Create when key_slot is NULL
- rc = Esys_CreateLoaded(
- /* esysContext */ resource_manager.Esys(),
- /* primaryHandle */ parent_key,
- /* shandle1 */ ESYS_TR_PASSWORD,
- /* shandle2 */ ESYS_TR_NONE,
- /* shandle3 */ ESYS_TR_NONE,
- /* inSensitive */ &in_sensitive,
- /* inPublic */ &public_template,
- /* objectHandle */ &raw_handle,
- /* outPrivate */ &key_private,
- /* outPublic */ &key_public);
- if (rc != TSS2_RC_SUCCESS) {
- LOG(ERROR) << "Esys_CreateLoaded failed with return code " << rc
- << " (" << Tss2_RC_Decode(rc) << ")";
- return false;
- }
- CHECK(key_public != nullptr) << "key_public was not assigned.";
- CHECK(key_private != nullptr) << "key_private was not assigned.";
- *key_public_out = *key_public;
- *key_private_out = *key_private;
- key_slot->set(raw_handle);
- Esys_Free(key_public);
- Esys_Free(key_private);
- if (key_slot_out) {
- rc = Esys_TR_SetAuth(resource_manager.Esys(), raw_handle, &authValue);
- if (rc != TSS2_RC_SUCCESS) {
- LOG(ERROR) << "Esys_TR_SetAuth failed with return code " << rc
- << " (" << Tss2_RC_Decode(rc) << ")";
- return false;
- }
- }
- if (key_slot_out) {
- *key_slot_out = key_slot;
- }
- return true;
-}
-
-static TpmObjectSlot LoadKey(
- TpmResourceManager& resource_manager,
- ESYS_TR parent_key,
- const TPM2B_PUBLIC* key_public,
- const TPM2B_PRIVATE* key_private) {
- // TODO
- ESYS_TR raw_handle;
- auto key_slot = resource_manager.ReserveSlot();
- if (!key_slot) {
- LOG(ERROR) << "No slots available";
- return {};
- }
- auto rc = Esys_Load(
- resource_manager.Esys(),
- parent_key,
- ESYS_TR_PASSWORD,
- ESYS_TR_NONE,
- ESYS_TR_NONE,
- key_private,
- key_public,
- &raw_handle);
- if (rc != TSS2_RC_SUCCESS) {
- LOG(ERROR) << "Esys_Load failed with return code " << rc
- << " (" << Tss2_RC_Decode(rc) << ")";
- return {};
- }
- key_slot->set(raw_handle);
- return key_slot;
-}
-
-static constexpr uint32_t BLOCK_SIZE = 16;
-
-static uint32_t RoundUpToBlockSize(uint32_t num) {
- return num % BLOCK_SIZE == 0 ? num : num + (BLOCK_SIZE - (num % BLOCK_SIZE));
-}
-
-size_t EncryptedSerializable::SerializedSize() const {
- TPM2B_PUBLIC key_public;
- TPM2B_PRIVATE key_private;
- auto parent = parent_key_fn_(resource_manager_);
- if (!CreateKey(
- resource_manager_, parent->get(), &key_public, &key_private, nullptr)) {
- LOG(ERROR) << "Unable to create key";
- return 0;
- }
- // Assumes all created keys will have the same size.
- SerializeTpmKeyPublic serialize_public(&key_public);
- SerializeTpmKeyPrivate serialize_private(&key_private);
- auto encrypted_size = RoundUpToBlockSize(wrapped_.SerializedSize());
- return serialize_public.SerializedSize()
- + serialize_private.SerializedSize()
- + sizeof(uint32_t)
- + sizeof(uint32_t)
- + encrypted_size;
-}
-
-uint8_t* EncryptedSerializable::Serialize(
- uint8_t* buf, const uint8_t* end) const {
- TPM2B_PUBLIC key_public;
- TPM2B_PRIVATE key_private;
- auto parent = parent_key_fn_(resource_manager_);
- if (!parent) {
- LOG(ERROR) << "Unable to load encryption parent key";
- return buf;
- }
- TpmObjectSlot key_slot;
- if (!CreateKey(
- resource_manager_, parent->get(), &key_public, &key_private, &key_slot)) {
- LOG(ERROR) << "Unable to create key";
- return buf;
- }
-
- auto wrapped_size = wrapped_.SerializedSize();
- auto encrypted_size = RoundUpToBlockSize(wrapped_size);
- std::vector<uint8_t> unencrypted(encrypted_size + 1, 0);
- auto unencrypted_buf = unencrypted.data();
- auto unencrypted_buf_end = unencrypted_buf + unencrypted.size();
- auto next_buf = wrapped_.Serialize(unencrypted_buf, unencrypted_buf_end);
- if (next_buf - unencrypted_buf != wrapped_size) {
- LOG(ERROR) << "Size mismatch on wrapped data";
- return buf;
- }
- std::vector<uint8_t> encrypted(encrypted_size, 0);
- if (!TpmEncrypt(
- resource_manager_.Esys(),
- key_slot->get(),
- TpmAuth(ESYS_TR_PASSWORD),
- unencrypted.data(),
- encrypted.data(),
- encrypted_size)) {
- LOG(ERROR) << "Encryption failed";
- return buf;
- }
- SerializeTpmKeyPublic serialize_public(&key_public);
- SerializeTpmKeyPrivate serialize_private(&key_private);
-
- buf = serialize_public.Serialize(buf, end);
- buf = serialize_private.Serialize(buf, end);
- buf = keymaster::append_uint32_to_buf(buf, end, BLOCK_SIZE);
- buf = keymaster::append_uint32_to_buf(buf, end, wrapped_size);
- buf = keymaster::append_to_buf(buf, end, encrypted.data(), encrypted_size);
- return buf;
-}
-
-bool EncryptedSerializable::Deserialize(
- const uint8_t** buf_ptr, const uint8_t* end) {
- auto parent_key = parent_key_fn_(resource_manager_);
- if (!parent_key) {
- LOG(ERROR) << "Unable to load encryption parent key";
- return false;
- }
- TPM2B_PUBLIC key_public;
- SerializeTpmKeyPublic serialize_public(&key_public);
- if (!serialize_public.Deserialize(buf_ptr, end)) {
- LOG(ERROR) << "Unable to deserialize key public part";
- return false;
- }
- TPM2B_PRIVATE key_private;
- SerializeTpmKeyPrivate serialize_private(&key_private);
- if (!serialize_private.Deserialize(buf_ptr, end)) {
- LOG(ERROR) << "Unable to deserialize key private part";
- return false;
- }
- auto key_slot =
- LoadKey(resource_manager_, parent_key->get(), &key_public, &key_private);
- if (!key_slot) {
- LOG(ERROR) << "Failed to load key into TPM";
- return false;
- }
- uint32_t block_size = 0;
- if (!keymaster::copy_uint32_from_buf(buf_ptr, end, &block_size)) {
- LOG(ERROR) << "Failed to read block size";
- return false;
- }
- if (block_size != BLOCK_SIZE) {
- LOG(ERROR) << "Unexpected block size: was " << block_size
- << ", expected " << BLOCK_SIZE;
- return false;
- }
- uint32_t wrapped_size = 0;
- if (!keymaster::copy_uint32_from_buf(buf_ptr, end, &wrapped_size)) {
- LOG(ERROR) << "Failed to read wrapped size";
- return false;
- }
- uint32_t encrypted_size = RoundUpToBlockSize(wrapped_size);
- std::vector<uint8_t> encrypted_data(encrypted_size, 0);
- if (!keymaster::copy_from_buf(
- buf_ptr, end, encrypted_data.data(), encrypted_size)) {
- LOG(ERROR) << "Failed to read encrypted data";
- return false;
- }
- std::vector<uint8_t> decrypted_data(encrypted_size, 0);
- if (!TpmDecrypt(
- resource_manager_.Esys(),
- key_slot->get(),
- TpmAuth(ESYS_TR_PASSWORD),
- encrypted_data.data(),
- decrypted_data.data(),
- encrypted_size)) {
- LOG(ERROR) << "Failed to decrypt encrypted data";
- return false;
- }
- auto decrypted_buf = decrypted_data.data();
- auto decrypted_buf_end = decrypted_data.data() + wrapped_size;
- if (!wrapped_.Deserialize(
- const_cast<const uint8_t **>(&decrypted_buf), decrypted_buf_end)) {
- LOG(ERROR) << "Failed to deserialize wrapped type";
- return false;
- }
- if (decrypted_buf != decrypted_buf_end) {
- LOG(ERROR) << "Inner type did not use all data";
- return false;
- }
- return true;
-}
diff --git a/host/commands/secure_env/encrypted_serializable.h b/host/commands/secure_env/encrypted_serializable.h
deleted file mode 100644
index c4a2e08b0..000000000
--- a/host/commands/secure_env/encrypted_serializable.h
+++ /dev/null
@@ -1,59 +0,0 @@
-//
-// Copyright (C) 2020 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 <keymaster/serializable.h>
-
-#include "host/commands/secure_env/tpm_resource_manager.h"
-
-/**
- * A keymaster::Serializable that wraps another keymaster::Serializable,
- * encrypting the data with a TPM to ensure privacy.
- *
- * This implementation randomly generates a unique key which only exists inside
- * the TPM, and uses it to encrypt the data from the other Serializable
- * instance. The encrypted data, together with information about the unique key
- * is stored in the output data. The unique key information is something that
- * can only be decoded using a TPM, which will detect if the key is corrupted.
- * However, this implementation will not detect if the encrypted data is
- * corrupted, which could break the other Serializable instance on
- * deserialization. This class should be used with something else to verify
- * that the data hasn't been tampered with.
- *
- * The serialization format is:
- * [tpm key public data] [tpm key private data]
- * [uint32_t: block_size]
- * [uint32_t: encrypted_length] [encrypted_data]
- *
- * The actual length of [encrypted_data] in the serialized format is
- * [encrypted_length] rounded up to the nearest multiple of [block_size].
- * [encrypted_length] is the true length of the data before encryption, without
- * padding.
- */
-class EncryptedSerializable : public keymaster::Serializable {
-public:
- EncryptedSerializable(TpmResourceManager&,
- std::function<TpmObjectSlot(TpmResourceManager&)>,
- Serializable&);
-
- size_t SerializedSize() const override;
- uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const override;
- bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end) override;
-private:
- TpmResourceManager& resource_manager_;
- std::function<TpmObjectSlot(TpmResourceManager&)> parent_key_fn_;
- keymaster::Serializable& wrapped_;
-};
diff --git a/host/commands/secure_env/fragile_tpm_storage.cpp b/host/commands/secure_env/fragile_tpm_storage.cpp
deleted file mode 100644
index ae661645e..000000000
--- a/host/commands/secure_env/fragile_tpm_storage.cpp
+++ /dev/null
@@ -1,240 +0,0 @@
-//
-// Copyright (C) 2020 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 "host/commands/secure_env/fragile_tpm_storage.h"
-
-#include <fstream>
-
-#include <android-base/logging.h>
-#include <tss2/tss2_rc.h>
-
-#include "host/commands/secure_env/json_serializable.h"
-#include "host/commands/secure_env/tpm_random_source.h"
-
-static constexpr char kEntries[] = "entries";
-static constexpr char kKey[] = "key";
-static constexpr char kHandle[] = "handle";
-
-FragileTpmStorage::FragileTpmStorage(
- TpmResourceManager& resource_manager, const std::string& index_file)
- : resource_manager_(resource_manager), index_file_(index_file) {
- index_ = ReadProtectedJsonFromFile(resource_manager_, index_file);
- if (!index_.isMember(kEntries)
- || index_[kEntries].type() != Json::arrayValue) {
- if (index_.empty()) {
- LOG(DEBUG) << "Initializing secure index file";
- } else {
- LOG(WARNING) << "Index file missing entries, likely corrupted.";
- }
- index_[kEntries] = Json::Value(Json::arrayValue);
- } else {
- LOG(DEBUG) << "Restoring index from file";
- }
-}
-
-TPM2_HANDLE FragileTpmStorage::GenerateRandomHandle() {
- TpmRandomSource random_source{resource_manager_.Esys()};
- TPM2_HANDLE handle = 0;
- random_source.GenerateRandom(
- reinterpret_cast<uint8_t*>(&handle), sizeof(handle));
- if (handle == 0) {
- LOG(WARNING) << "TPM randomness failed. Falling back to software RNG.";
- handle = rand();
- }
- handle = handle % (TPM2_NV_INDEX_LAST + 1 - TPM2_NV_INDEX_FIRST);
- handle += TPM2_NV_INDEX_FIRST;
- return handle;
-}
-
-static constexpr size_t MAX_HANDLE_ATTEMPTS = 1;
-
-bool FragileTpmStorage::Allocate(const Json::Value& key, uint16_t size) {
- if (HasKey(key)) {
- LOG(WARNING) << "Key " << key << " is already defined.";
- return false;
- }
- TPM2_HANDLE handle;
- for (int i = 0; i < MAX_HANDLE_ATTEMPTS; i++) {
- handle = GenerateRandomHandle();
- TPM2B_NV_PUBLIC public_info = {
- .size = 0,
- .nvPublic = {
- .nvIndex = handle,
- .nameAlg = TPM2_ALG_SHA1,
- .attributes = TPMA_NV_AUTHWRITE | TPMA_NV_AUTHREAD,
- .authPolicy = { .size = 0, .buffer = {} },
- .dataSize = size,
- }
- };
- TPM2B_AUTH auth = { .size = 0, .buffer = {} };
- Esys_TR_SetAuth(resource_manager_.Esys(), ESYS_TR_RH_OWNER, &auth);
- ESYS_TR nv_handle;
- auto rc = Esys_NV_DefineSpace(
- /* esysContext */ resource_manager_.Esys(),
- /* authHandle */ ESYS_TR_RH_OWNER,
- /* shandle1 */ ESYS_TR_PASSWORD,
- /* shandle2 */ ESYS_TR_NONE,
- /* shandle3 */ ESYS_TR_NONE,
- /* auth */ &auth,
- /* publicInfo */ &public_info,
- /* nvHandle */ &nv_handle);
- if (rc == TPM2_RC_NV_DEFINED) {
- LOG(VERBOSE) << "Esys_NV_DefineSpace failed with TPM2_RC_NV_DEFINED";
- continue;
- } else if (rc == TPM2_RC_SUCCESS) {
- Esys_TR_Close(resource_manager_.Esys(), &nv_handle);
- break;
- } else {
- LOG(DEBUG) << "Esys_NV_DefineSpace failed with " << rc << ": "
- << Tss2_RC_Decode(rc);
- }
- }
- Json::Value entry(Json::objectValue);
- entry[kKey] = key;
- entry[kHandle] = handle;
- index_[kEntries].append(entry);
-
- if (!WriteProtectedJsonToFile(resource_manager_, index_file_, index_)) {
- LOG(ERROR) << "Failed to save changes to " << index_file_;
- return false;
- }
- return true;
-}
-
-TPM2_HANDLE FragileTpmStorage::GetHandle(const Json::Value& key) const {
- for (const auto& entry : index_[kEntries]) {
- if (!entry.isMember(kKey)) {
- LOG(ERROR) << "Index was corrupted";
- return 0;
- }
- if (entry[kKey] != key) {
- continue;
- }
- if (!entry.isMember(kHandle)) {
- LOG(ERROR) << "Index was corrupted";
- return 0;
- }
- return entry[kHandle].asUInt();
- }
- return 0;
-}
-
-bool FragileTpmStorage::HasKey(const Json::Value& key) const {
- return GetHandle(key) != 0;
-}
-
-std::unique_ptr<TPM2B_MAX_NV_BUFFER> FragileTpmStorage::Read(
- const Json::Value& key) const {
- auto handle = GetHandle(key);
- if (handle == 0) {
- LOG(WARNING) << "Could not read from " << key;
- return {};
- }
- auto close_tr = [this](ESYS_TR* handle) {
- Esys_TR_Close(resource_manager_.Esys(), handle);
- delete handle;
- };
- std::unique_ptr<ESYS_TR, decltype(close_tr)> nv_handle(new ESYS_TR, close_tr);
- auto rc = Esys_TR_FromTPMPublic(
- /* esysContext */ resource_manager_.Esys(),
- /* tpm_handle */ handle,
- /* optionalSession1 */ ESYS_TR_NONE,
- /* optionalSession2 */ ESYS_TR_NONE,
- /* optionalSession3 */ ESYS_TR_NONE,
- /* object */ nv_handle.get());
- if (rc != TPM2_RC_SUCCESS) {
- LOG(ERROR) << "Esys_TR_FromTPMPublic failed: " << rc << ": "
- << Tss2_RC_Decode(rc);
- return {};
- }
- TPM2B_AUTH auth = { .size = 0, .buffer = {} };
- Esys_TR_SetAuth(resource_manager_.Esys(), *nv_handle, &auth);
-
- TPM2B_NV_PUBLIC* public_area;
- rc = Esys_NV_ReadPublic(
- /* esysContext */ resource_manager_.Esys(),
- /* nvIndex */ *nv_handle,
- /* shandle1 */ ESYS_TR_NONE,
- /* shandle2 */ ESYS_TR_NONE,
- /* shandle3 */ ESYS_TR_NONE,
- /* nvPublic */ &public_area,
- /* nvName */ nullptr);
- if (rc != TPM2_RC_SUCCESS || public_area == nullptr) {
- LOG(ERROR) << "Esys_NV_ReadPublic failed: " << rc << ": "
- << Tss2_RC_Decode(rc);
- return {};
- }
- std::unique_ptr<TPM2B_NV_PUBLIC, decltype(Esys_Free)*>
- public_deleter(public_area, Esys_Free);
- TPM2B_MAX_NV_BUFFER* buffer = nullptr;
- rc = Esys_NV_Read(
- /* esysContext */ resource_manager_.Esys(),
- /* authHandle */ *nv_handle,
- /* nvIndex */ *nv_handle,
- /* shandle1 */ ESYS_TR_PASSWORD,
- /* shandle2 */ ESYS_TR_NONE,
- /* shandle3 */ ESYS_TR_NONE,
- /* size */ public_area->nvPublic.dataSize,
- /* offset */ 0,
- /* data */ &buffer);
- if (rc != TSS2_RC_SUCCESS || buffer == nullptr) {
- LOG(ERROR) << "Esys_NV_Read failed with return code " << rc
- << " (" << Tss2_RC_Decode(rc) << ")";
- return {};
- }
- auto ret = std::make_unique<TPM2B_MAX_NV_BUFFER>(*buffer);
- return ret;
-}
-
-bool FragileTpmStorage::Write(
- const Json::Value& key, const TPM2B_MAX_NV_BUFFER& data) {
- auto handle = GetHandle(key);
- if (handle == 0) {
- LOG(WARNING) << "Could not read from " << key;
- return false;
- }
- ESYS_TR nv_handle;
- auto rc = Esys_TR_FromTPMPublic(
- /* esysContext */ resource_manager_.Esys(),
- /* tpm_handle */ handle,
- /* optionalSession1 */ ESYS_TR_NONE,
- /* optionalSession2 */ ESYS_TR_NONE,
- /* optionalSession3 */ ESYS_TR_NONE,
- /* object */ &nv_handle);
- if (rc != TPM2_RC_SUCCESS) {
- LOG(ERROR) << "Esys_TR_FromTPMPublic failed: " << rc << ": "
- << Tss2_RC_Decode(rc);
- return false;
- }
- TPM2B_AUTH auth = { .size = 0, .buffer = {} };
- Esys_TR_SetAuth(resource_manager_.Esys(), nv_handle, &auth);
-
- rc = Esys_NV_Write(
- /* esysContext */ resource_manager_.Esys(),
- /* authHandle */ nv_handle,
- /* nvIndex */ nv_handle,
- /* shandle1 */ ESYS_TR_PASSWORD,
- /* shandle2 */ ESYS_TR_NONE,
- /* shandle3 */ ESYS_TR_NONE,
- /* data */ &data,
- /* offset */ 0);
- Esys_TR_Close(resource_manager_.Esys(), &nv_handle);
- if (rc != TSS2_RC_SUCCESS) {
- LOG(ERROR) << "Esys_NV_Write failed with return code " << rc
- << " (" << Tss2_RC_Decode(rc) << ")";
- return false;
- }
- return true;
-}
diff --git a/host/commands/secure_env/fragile_tpm_storage.h b/host/commands/secure_env/fragile_tpm_storage.h
deleted file mode 100644
index b52b3739f..000000000
--- a/host/commands/secure_env/fragile_tpm_storage.h
+++ /dev/null
@@ -1,60 +0,0 @@
-//
-// Copyright (C) 2020 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 <memory>
-#include <string>
-#include <vector>
-
-#include <tss2/tss2_esys.h>
-#include <tss2/tss2_tpm2_types.h>
-#include <json/json.h>
-
-#include "host/commands/secure_env/gatekeeper_storage.h"
-#include "host/commands/secure_env/tpm_resource_manager.h"
-
-/**
- * Manager for data stored inside the TPM with an index outside of the TPM. The
- * contents of the data cannot be corrupted or decrypted by accessing the index,
- * but the index can be corrupted by an attacker.
- *
- * As the actual data is stored inside the TPM, a replay attack can be used to
- * restore deleted index entries or hide revert to before an index entry was
- * added, but not change the contents that an index points to if it still
- * exists.
- *
- * This class is not thread-safe, and should be synchronized externally if it
- * is going to be used from multiple threads.
- */
-class FragileTpmStorage : public GatekeeperStorage {
-public:
- FragileTpmStorage(TpmResourceManager&, const std::string& index_file);
- ~FragileTpmStorage() = default;
-
- bool Allocate(const Json::Value& key, uint16_t size) override;
- bool HasKey(const Json::Value& key) const override;
-
- std::unique_ptr<TPM2B_MAX_NV_BUFFER> Read(const Json::Value& key) const
- override;
- bool Write(const Json::Value& key, const TPM2B_MAX_NV_BUFFER& data) override;
-private:
- TPM2_HANDLE GetHandle(const Json::Value& key) const;
- TPM2_HANDLE GenerateRandomHandle();
-
- TpmResourceManager& resource_manager_;
- std::string index_file_;
- Json::Value index_;
-};
diff --git a/host/commands/secure_env/gatekeeper_responder.cpp b/host/commands/secure_env/gatekeeper_responder.cpp
deleted file mode 100644
index 7d43a18aa..000000000
--- a/host/commands/secure_env/gatekeeper_responder.cpp
+++ /dev/null
@@ -1,62 +0,0 @@
-//
-// Copyright (C) 2020 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 "gatekeeper_responder.h"
-
-#include <android-base/logging.h>
-#include <gatekeeper/gatekeeper_messages.h>
-
-GatekeeperResponder::GatekeeperResponder(
- cuttlefish::GatekeeperChannel& channel, gatekeeper::GateKeeper& gatekeeper)
- : channel_(channel), gatekeeper_(gatekeeper) {
-}
-
-bool GatekeeperResponder::ProcessMessage() {
- auto request = channel_.ReceiveMessage();
- if (!request) {
- LOG(ERROR) << "Could not receive message";
- return false;
- }
- const uint8_t* buffer = request->payload;
- const uint8_t* buffer_end = request->payload + request->payload_size;
- switch(request->cmd) {
- using namespace gatekeeper;
- case ENROLL: {
- EnrollRequest enroll_request;
- auto rc = enroll_request.Deserialize(buffer, buffer_end);
- if (rc != ERROR_NONE) {
- LOG(ERROR) << "Failed to deserialize Enroll Request";
- return false;
- }
- EnrollResponse response;
- gatekeeper_.Enroll(enroll_request, &response);
- return channel_.SendResponse(ENROLL, response);
- }
- case VERIFY: {
- VerifyRequest verify_request;
- auto rc = verify_request.Deserialize(buffer, buffer_end);
- if (rc != ERROR_NONE) {
- LOG(ERROR) << "Failed to deserialize Verify Request";
- return false;
- }
- VerifyResponse response;
- gatekeeper_.Verify(verify_request, &response);
- return channel_.SendResponse(VERIFY, response);
- }
- default:
- LOG(ERROR) << "Unrecognized message id " << request->cmd;
- return false;
- }
-}
diff --git a/host/commands/secure_env/gatekeeper_responder.h b/host/commands/secure_env/gatekeeper_responder.h
deleted file mode 100644
index bd2795560..000000000
--- a/host/commands/secure_env/gatekeeper_responder.h
+++ /dev/null
@@ -1,31 +0,0 @@
-//
-// Copyright (C) 2020 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 <gatekeeper/gatekeeper.h>
-
-#include "common/libs/security/gatekeeper_channel.h"
-
-class GatekeeperResponder {
-private:
- cuttlefish::GatekeeperChannel& channel_;
- gatekeeper::GateKeeper& gatekeeper_;
-public:
- GatekeeperResponder(cuttlefish::GatekeeperChannel& channel,
- gatekeeper::GateKeeper& gatekeeper);
-
- bool ProcessMessage();
-};
diff --git a/host/commands/secure_env/gatekeeper_storage.h b/host/commands/secure_env/gatekeeper_storage.h
deleted file mode 100644
index d272f71db..000000000
--- a/host/commands/secure_env/gatekeeper_storage.h
+++ /dev/null
@@ -1,42 +0,0 @@
-//
-// Copyright (C) 2020 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 <json/json.h>
-#include <tss2/tss2_tpm2_types.h>
-
-/**
- * Data storage tailored to Gatekeeper's storage needs: storing binary blobs
- * that can be destroyed without a trace or corrupted with an obvious trace, but
- * not silently tampered with or read by an unauthorized user.
- *
- * Data can be stored through Write and retrieved through Read. To delete data,
- * issue a Write that overwrites the data to destroy it.
- */
-class GatekeeperStorage {
-public:
- virtual ~GatekeeperStorage() = default;
-
- virtual bool Allocate(const Json::Value& key, uint16_t size) = 0;
- virtual bool HasKey(const Json::Value& key) const = 0;
-
- virtual std::unique_ptr<TPM2B_MAX_NV_BUFFER> Read(const Json::Value& key)
- const = 0;
- virtual bool Write(const Json::Value& key, const TPM2B_MAX_NV_BUFFER& data)
- = 0;
-};
diff --git a/host/commands/secure_env/hmac_serializable.cpp b/host/commands/secure_env/hmac_serializable.cpp
deleted file mode 100644
index c40b73668..000000000
--- a/host/commands/secure_env/hmac_serializable.cpp
+++ /dev/null
@@ -1,127 +0,0 @@
-//
-// Copyright (C) 2020 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 "hmac_serializable.h"
-
-#include <android-base/logging.h>
-
-#include "host/commands/secure_env/tpm_auth.h"
-#include "host/commands/secure_env/tpm_hmac.h"
-
-HmacSerializable::HmacSerializable(
- TpmResourceManager& resource_manager,
- std::function<TpmObjectSlot(TpmResourceManager&)> signing_key_fn,
- uint32_t digest_size,
- Serializable* wrapped) :
- resource_manager_(resource_manager),
- signing_key_fn_(signing_key_fn),
- digest_size_(digest_size),
- wrapped_(wrapped) {
-}
-
-size_t HmacSerializable::SerializedSize() const {
- auto digest_size = sizeof(uint32_t) + digest_size_;
- auto data_size = sizeof(uint32_t) + wrapped_->SerializedSize();
- return digest_size + data_size;
-}
-
-uint8_t* HmacSerializable::Serialize(uint8_t* buf, const uint8_t* end) const {
- auto wrapped_size = wrapped_->SerializedSize();
- buf = keymaster::append_uint32_to_buf(buf, end, wrapped_size);
- auto signed_data = buf;
- buf = wrapped_->Serialize(buf, end);
- if (buf - signed_data != wrapped_size) {
- LOG(ERROR) << "Serialized wrapped data did not match expected size.";
- return buf;
- }
- auto key = signing_key_fn_(resource_manager_);
- if (!key) {
- LOG(ERROR) << "Could not retrieve key";
- return buf;
- }
- auto hmac_data =
- TpmHmac(
- resource_manager_,
- key->get(),
- TpmAuth(ESYS_TR_PASSWORD),
- signed_data,
- wrapped_size);
- if (!hmac_data) {
- LOG(ERROR) << "Failed to produce hmac";
- return buf;
- }
- if (hmac_data->size != digest_size_) {
- LOG(ERROR) << "Unexpected digest size. Wanted " << digest_size_
- << ", TPM produced " << hmac_data->size;
- return buf;
- }
- return keymaster::append_size_and_data_to_buf(
- buf, end, hmac_data->buffer, digest_size_);
-}
-
-bool HmacSerializable::Deserialize(const uint8_t** buf_ptr, const uint8_t* end) {
- size_t signed_data_size;
- keymaster::UniquePtr<uint8_t[]> signed_data;
- bool success =
- keymaster::copy_size_and_data_from_buf(
- buf_ptr, end, &signed_data_size, &signed_data);
- if (!success) {
- LOG(ERROR) << "Failed to retrieve signed data";
- return false;
- }
- size_t signature_size;
- keymaster::UniquePtr<uint8_t[]> signature;
- success =
- keymaster::copy_size_and_data_from_buf(
- buf_ptr, end, &signature_size, &signature);
- if (!success) {
- LOG(ERROR) << "Failed to retrieve signature";
- return false;
- }
- if (signature_size != digest_size_) {
- LOG(ERROR) << "Digest size did not match expected size.";
- return false;
- }
- auto key = signing_key_fn_(resource_manager_);
- if (!key) {
- LOG(ERROR) << "Could not retrieve key";
- return false;
- }
- auto hmac_check =
- TpmHmac(
- resource_manager_,
- key->get(),
- TpmAuth(ESYS_TR_PASSWORD),
- signed_data.get(),
- signed_data_size);
- if (!hmac_check) {
- LOG(ERROR) << "Unable to calculate signature check";
- return false;
- }
- if (hmac_check->size != digest_size_) {
- LOG(ERROR) << "Unexpected signature check size. Wanted " << digest_size_
- << ", TPM produced " << hmac_check->size;
- return false;
- }
- if (memcmp(signature.get(), hmac_check->buffer, digest_size_) != 0) {
- LOG(ERROR) << "Signature check did not match original signature.";
- return false;
- }
- // Now that we've validated integrity on the data, do the inner deserialization
- auto inner_buf = signed_data.get();
- auto inner_buf_end = inner_buf + signed_data_size;
- return wrapped_->Deserialize(
- const_cast<const uint8_t**>(&inner_buf), inner_buf_end);
-}
diff --git a/host/commands/secure_env/hmac_serializable.h b/host/commands/secure_env/hmac_serializable.h
deleted file mode 100644
index 4b9012472..000000000
--- a/host/commands/secure_env/hmac_serializable.h
+++ /dev/null
@@ -1,54 +0,0 @@
-//
-// Copyright (C) 2020 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 <keymaster/serializable.h>
-
-#include "host/commands/secure_env/tpm_resource_manager.h"
-
-/**
- * A keymaster::Serializable that wraps another keymaster::Serializable,
- * protecting it from tampering while it is stored elsewhere. This stores
- * the serialized data of the other type together with a signature over that
- * serialized data. When deserializing, it will attempt to make the same
- * signature over the data. If the signature or data has been tampered with,
- * the signatures won't match and it won't attempt to deserialize the wrapped
- * type.
- *
- * The serialization format is:
- * [uint32_t: wrapped_size] [wrapped_data]
- * [uint32_t: signature_size] [signature_data]
- *
- * While this class currently assumes all signatures will use the same key
- * and algorithm and therefore be the same size, the serialization format is
- * future-proof to accommodate signature changes.
- */
-class HmacSerializable : public keymaster::Serializable {
-public:
- HmacSerializable(TpmResourceManager&,
- std::function<TpmObjectSlot(TpmResourceManager&)>,
- uint32_t digest_size,
- Serializable*);
-
- size_t SerializedSize() const override;
- uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const override;
- bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end) override;
-private:
- TpmResourceManager& resource_manager_;
- std::function<TpmObjectSlot(TpmResourceManager&)> signing_key_fn_;
- uint32_t digest_size_;
- keymaster::Serializable* wrapped_;
-};
diff --git a/host/commands/secure_env/in_process_tpm.cpp b/host/commands/secure_env/in_process_tpm.cpp
deleted file mode 100644
index f240c0847..000000000
--- a/host/commands/secure_env/in_process_tpm.cpp
+++ /dev/null
@@ -1,156 +0,0 @@
-//
-// Copyright (C) 2020 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 "in_process_tpm.h"
-
-#include <endian.h>
-#include <stddef.h>
-
-#include <tss2/tss2_esys.h>
-#include <tss2/tss2_rc.h>
-
-#include "host/commands/secure_env/tpm_commands.h"
-
-extern "C" {
-typedef int SOCKET;
-#include "TpmBuildSwitches.h"
-#include "TpmTcpProtocol.h"
-#include "Simulator_fp.h"
-#include "Manufacture_fp.h"
-#define delete delete_
-#include "Platform_fp.h"
-#undef delete
-#undef DEBUG
-}
-
-#include <android-base/logging.h>
-
-struct __attribute__((__packed__)) tpm_message_header {
- uint16_t tag;
- uint32_t length;
- uint32_t ordinal;
-};
-
-struct InProcessTpm::Impl {
- static Impl* FromContext(TSS2_TCTI_CONTEXT* context) {
- auto offset = offsetof(Impl, tcti_context_);
- char* context_char = reinterpret_cast<char*>(context);
- return reinterpret_cast<Impl*>(context_char - offset);
- }
-
- static TSS2_RC Transmit(
- TSS2_TCTI_CONTEXT *context, size_t size, uint8_t const *command) {
- auto impl = FromContext(context);
- std::lock_guard lock(impl->queue_mutex_);
- impl->command_queue_.emplace_back(command, command + size);
- return TSS2_RC_SUCCESS;
- }
-
- static TSS2_RC Receive(
- TSS2_TCTI_CONTEXT *context,
- size_t* size,
- uint8_t* response,
- int32_t /* timeout */) {
- auto impl = FromContext(context);
- // TODO(schuffelen): Use the timeout argument
- std::vector<uint8_t> request;
- {
- std::lock_guard lock(impl->queue_mutex_);
- if (impl->command_queue_.empty()) {
- return TSS2_TCTI_RC_GENERAL_FAILURE;
- }
- request = std::move(impl->command_queue_.front());
- impl->command_queue_.pop_front();
- }
- auto header = reinterpret_cast<tpm_message_header*>(request.data());
- LOG(VERBOSE) << "Sending TPM command "
- << TpmCommandName(be32toh(header->ordinal));
- _IN_BUFFER input = {
- .BufferSize = request.size(),
- .Buffer = request.data(),
- };
- _OUT_BUFFER output = {
- .BufferSize = (uint32_t) *size,
- .Buffer = response,
- };
- _rpc__Send_Command(3, input, &output);
- *size = output.BufferSize;
- header = reinterpret_cast<tpm_message_header*>(response);
- auto rc = be32toh(header->ordinal);
- LOG(VERBOSE) << "Received TPM response " << Tss2_RC_Decode(rc)
- << " (" << rc << ")";
- return TSS2_RC_SUCCESS;
- }
-
- TSS2_TCTI_CONTEXT_COMMON_CURRENT tcti_context_;
- std::list<std::vector<uint8_t>> command_queue_;
- std::mutex queue_mutex_;
-};
-
-InProcessTpm::InProcessTpm() : impl_(new Impl()) {
- impl_->tcti_context_.v1.magic = 0xFAD;
- impl_->tcti_context_.v1.version = 1;
- impl_->tcti_context_.v1.transmit = Impl::Transmit;
- impl_->tcti_context_.v1.receive = Impl::Receive;
- _plat__NVEnable(NULL);
- if (_plat__NVNeedsManufacture()) {
- // Can't use android logging here due to a macro conflict with TPM internals
- LOG(DEBUG) << "Manufacturing TPM state";
- if (TPM_Manufacture(1)) {
- LOG(FATAL) << "Failed to manufacture TPM state";
- }
- }
- _rpc__Signal_PowerOn(false);
- _rpc__Signal_NvOn();
-
- ESYS_CONTEXT* esys = nullptr;
- auto rc = Esys_Initialize(&esys, TctiContext(), nullptr);
- if (rc != TPM2_RC_SUCCESS) {
- LOG(FATAL) << "Could not initialize esys: " << Tss2_RC_Decode(rc)
- << " (" << rc << ")";
- }
-
- rc = Esys_Startup(esys, TPM2_SU_CLEAR);
- if (rc != TPM2_RC_SUCCESS) {
- LOG(FATAL) << "TPM2_Startup failed: " << Tss2_RC_Decode(rc)
- << " (" << rc << ")";
- }
-
- TPM2B_AUTH auth = {};
- Esys_TR_SetAuth(esys, ESYS_TR_RH_LOCKOUT, &auth);
-
- rc = Esys_DictionaryAttackLockReset(
- /* esysContext */ esys,
- /* lockHandle */ ESYS_TR_RH_LOCKOUT,
- /* shandle1 */ ESYS_TR_PASSWORD,
- /* shandle2 */ ESYS_TR_NONE,
- /* shandle3 */ ESYS_TR_NONE);
-
- if (rc != TPM2_RC_SUCCESS) {
- LOG(FATAL) << "Could not reset TPM lockout: " << Tss2_RC_Decode(rc)
- << " (" << rc << ")";
- }
-
- Esys_Finalize(&esys);
-}
-
-InProcessTpm::~InProcessTpm() {
- _rpc__Signal_NvOff();
- _rpc__Signal_PowerOff();
-}
-
-TSS2_TCTI_CONTEXT* InProcessTpm::TctiContext() {
- return reinterpret_cast<TSS2_TCTI_CONTEXT*>(&impl_->tcti_context_);
-}
diff --git a/host/commands/secure_env/in_process_tpm.h b/host/commands/secure_env/in_process_tpm.h
deleted file mode 100644
index 35fecfbe0..000000000
--- a/host/commands/secure_env/in_process_tpm.h
+++ /dev/null
@@ -1,47 +0,0 @@
-//
-// Copyright (C) 2020 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 <list>
-#include <mutex>
-#include <vector>
-
-#include <tss2/tss2_tcti.h>
-
-#include "host/commands/secure_env/tpm.h"
-
-/*
- * Exposes a TSS2_TCTI_CONTEXT for interacting with an in-process TPM simulator.
- *
- * TSS2_TCTI_CONTEXT is the abstraction for "communication channel to a TPM".
- * It is not safe to create more than one of these per process or per working
- * directory, as the TPM simulator implementation relies heavily on global
- * variables and files saved in the working directory.
- *
- * TODO(schuffelen): Consider moving this to a separate process with its own
- * working directory.
- */
-class InProcessTpm : public Tpm {
-public:
- InProcessTpm();
- ~InProcessTpm();
-
- TSS2_TCTI_CONTEXT* TctiContext() override;
-private:
- struct Impl;
-
- std::unique_ptr<Impl> impl_;
-};
diff --git a/host/commands/secure_env/insecure_fallback_storage.cpp b/host/commands/secure_env/insecure_fallback_storage.cpp
deleted file mode 100644
index f906bd534..000000000
--- a/host/commands/secure_env/insecure_fallback_storage.cpp
+++ /dev/null
@@ -1,149 +0,0 @@
-//
-// Copyright (C) 2020 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 "host/commands/secure_env/insecure_fallback_storage.h"
-
-#include <fstream>
-
-#include <android-base/logging.h>
-#include <tss2/tss2_rc.h>
-
-#include "host/commands/secure_env/json_serializable.h"
-#include "host/commands/secure_env/tpm_random_source.h"
-
-static constexpr char kEntries[] = "entries";
-static constexpr char kKey[] = "key";
-static constexpr char kValue[] = "value";
-
-InsecureFallbackStorage::InsecureFallbackStorage(
- TpmResourceManager& resource_manager, const std::string& index_file)
- : resource_manager_(resource_manager), index_file_(index_file) {
- index_ = ReadProtectedJsonFromFile(resource_manager_, index_file);
- if (!index_.isMember(kEntries)
- || index_[kEntries].type() != Json::arrayValue) {
- if (index_.empty()) {
- LOG(DEBUG) << "Initializing secure index file";
- } else {
- LOG(WARNING) << "Index file missing entries, likely corrupted.";
- }
- index_[kEntries] = Json::Value(Json::arrayValue);
- } else {
- LOG(DEBUG) << "Restoring index from file";
- }
-}
-
-bool InsecureFallbackStorage::Allocate(const Json::Value& key, uint16_t size) {
- if (HasKey(key)) {
- LOG(WARNING) << "Key " << key << " is already defined.";
- return false;
- }
- if (size > sizeof(((TPM2B_MAX_NV_BUFFER*)nullptr)->buffer)) {
- LOG(ERROR) << "Size " << size << " was too large.";
- return false;
- }
- Json::Value entry(Json::objectValue);
- entry[kKey] = key;
- Json::Value value(Json::arrayValue);
- for (int i = 0; i < size; i++) {
- value.append(0);
- }
- entry[kValue] = value;
- index_[kEntries].append(entry);
-
- if (!WriteProtectedJsonToFile(resource_manager_, index_file_, index_)) {
- LOG(ERROR) << "Failed to save changes to " << index_file_;
- return false;
- }
- return true;
-}
-
-const Json::Value* InsecureFallbackStorage::GetEntry(
- const Json::Value& key) const {
- for (auto& entry : index_[kEntries]) {
- if (!entry.isMember(kKey)) {
- LOG(WARNING) << "Index was corrupted";
- return nullptr;
- }
- if (entry[kKey] != key) {
- continue;
- }
- if (!entry.isMember(kValue) || entry[kValue].type() != Json::arrayValue) {
- LOG(WARNING) << "Index was corrupted";
- return nullptr;
- }
- return &entry;
- }
- return nullptr;
-}
-
-Json::Value* InsecureFallbackStorage::GetEntry(const Json::Value& key) {
- return const_cast<Json::Value*>(
- static_cast<const InsecureFallbackStorage&>(*this).GetEntry(key));
-}
-
-bool InsecureFallbackStorage::HasKey(const Json::Value& key) const {
- return static_cast<bool>(GetEntry(key));
-}
-
-std::unique_ptr<TPM2B_MAX_NV_BUFFER> InsecureFallbackStorage::Read(
- const Json::Value& key) const {
- auto entry = GetEntry(key);
- if (!entry) {
- LOG(WARNING) << "Could not read from " << key;
- return {};
- }
- const auto& value = (*entry)[kValue];
- if (value.type() != Json::arrayValue) {
- LOG(WARNING) << "Index was corrupted";
- return {};
- }
- auto ret = std::make_unique<TPM2B_MAX_NV_BUFFER>();
- if (value.size() > sizeof(ret->buffer)) {
- LOG(ERROR) << "Index was corrupted: size of data was too large";
- return {};
- }
- ret->size = value.size();
- for (unsigned int i = 0; i < value.size(); i++) {
- ret->buffer[i] = value[i].asUInt();
- }
- return ret;
-}
-
-bool InsecureFallbackStorage::Write(
- const Json::Value& key, const TPM2B_MAX_NV_BUFFER& data) {
- auto entry = GetEntry(key);
- if (!entry) {
- LOG(WARNING) << "Could not read from " << key;
- return false;
- }
- auto& value = (*entry)[kValue];
- if (value.type() != Json::arrayValue) {
- LOG(WARNING) << "Index was corrupted";
- return false;
- }
- if (data.size != value.size()) {
- LOG(ERROR) << "Size of data given was incorrect";
- return false;
- };
- for (unsigned int i = 0; i < value.size(); i++) {
- value[i] = data.buffer[i];
- }
-
- if (!WriteProtectedJsonToFile(resource_manager_, index_file_, index_)) {
- LOG(ERROR) << "Failed to save changes to " << index_file_;
- return false;
- }
- return true;
-}
diff --git a/host/commands/secure_env/insecure_fallback_storage.h b/host/commands/secure_env/insecure_fallback_storage.h
deleted file mode 100644
index 93788a094..000000000
--- a/host/commands/secure_env/insecure_fallback_storage.h
+++ /dev/null
@@ -1,56 +0,0 @@
-//
-// Copyright (C) 2020 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 <json/json.h>
-#include <tss2/tss2_tpm2_types.h>
-
-#include "host/commands/secure_env/gatekeeper_storage.h"
-#include "host/commands/secure_env/tpm_resource_manager.h"
-
-/**
- * A GatekeeperStorage fallback implementation that is less secure. It uses an
- * index file that is signed and encrypted by the TPM and the sensitive data
- * is contained inside the index file. This file can be deleted or corrupted
- * to lose access to the data inside, and is also susceptible to replay attacks.
- * If the index file is replaced with an older version and the secure
- * environment is restarted, it will still accept the old file with the old
- * data.
- *
- * This class is not thread-safe, and should be synchronized externally if it
- * is going to be used from multiple threads.
- */
-class InsecureFallbackStorage : public GatekeeperStorage {
-public:
- InsecureFallbackStorage(TpmResourceManager&, const std::string& index_file);
- ~InsecureFallbackStorage() = default;
-
- bool Allocate(const Json::Value& key, uint16_t size) override;
- bool HasKey(const Json::Value& key) const override;
-
- std::unique_ptr<TPM2B_MAX_NV_BUFFER> Read(const Json::Value& key) const
- override;
- bool Write(const Json::Value& key, const TPM2B_MAX_NV_BUFFER& data) override;
-private:
- Json::Value* GetEntry(const Json::Value& key);
- const Json::Value* GetEntry(const Json::Value& key) const;
-
- TpmResourceManager& resource_manager_;
- std::string index_file_;
- Json::Value index_;
-};
diff --git a/host/commands/secure_env/json_serializable.cpp b/host/commands/secure_env/json_serializable.cpp
deleted file mode 100644
index d4f2fd894..000000000
--- a/host/commands/secure_env/json_serializable.cpp
+++ /dev/null
@@ -1,153 +0,0 @@
-//
-// Copyright (C) 2020 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 "host/commands/secure_env/json_serializable.h"
-
-#include <fstream>
-
-#include <android-base/logging.h>
-#include <keymaster/serializable.h>
-
-#include "host/commands/secure_env/encrypted_serializable.h"
-#include "host/commands/secure_env/hmac_serializable.h"
-#include "host/commands/secure_env/primary_key_builder.h"
-
-static constexpr char kUniqueKey[] = "JsonSerializable";
-
-class JsonSerializable : public keymaster::Serializable {
-public:
- JsonSerializable(Json::Value& json);
-
- size_t SerializedSize() const override;
-
- uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const override;
-
- bool Deserialize(const uint8_t** buf_ptr, const uint8_t* buf_end) override;
-private:
- Json::Value& json_;
-};
-
-JsonSerializable::JsonSerializable(Json::Value& json) : json_(json) {}
-
-size_t JsonSerializable::SerializedSize() const {
- Json::StreamWriterBuilder factory;
- auto serialized = Json::writeString(factory, json_);
- return serialized.size() + sizeof(uint32_t);
-}
-
-uint8_t* JsonSerializable::Serialize(uint8_t* buf, const uint8_t* end) const {
- Json::StreamWriterBuilder factory;
- auto serialized = Json::writeString(factory, json_);
- if (end - buf < serialized.size() + sizeof(uint32_t)) {
- LOG(ERROR) << "Not enough space to serialize json";
- return buf;
- }
- return keymaster::append_size_and_data_to_buf(
- buf, end, serialized.data(), serialized.size());
-}
-
-bool JsonSerializable::Deserialize(
- const uint8_t** buf_ptr, const uint8_t* buf_end) {
- size_t size;
- keymaster::UniquePtr<uint8_t[]> json_bytes;
- bool success = keymaster::copy_size_and_data_from_buf(
- buf_ptr, buf_end, &size, &json_bytes);
- if (!success) {
- LOG(ERROR) << "Failed to deserialize json bytes";
- return false;
- }
- auto doc_begin = reinterpret_cast<const char*>(json_bytes.get());
- auto doc_end = doc_begin + size;
- Json::CharReaderBuilder builder;
- std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
- std::string errorMessage;
- if (!reader->parse(doc_begin, doc_end, &json_, &errorMessage)) {
- LOG(ERROR) << "Failed to parse json: " << errorMessage;
- return false;
- }
- return true;
-}
-
-bool WriteProtectedJsonToFile(
- TpmResourceManager& resource_manager,
- const std::string& filename,
- Json::Value json) {
- JsonSerializable sensitive_material(json);
- auto parent_key_fn = ParentKeyCreator(kUniqueKey);
- EncryptedSerializable encryption(
- resource_manager, parent_key_fn, sensitive_material);
- auto signing_key_fn = SigningKeyCreator(kUniqueKey);
- HmacSerializable sign_check(
- resource_manager, signing_key_fn, TPM2_SHA256_DIGEST_SIZE, &encryption);
-
- auto size = sign_check.SerializedSize();
- LOG(INFO) << "size : " << size;
- std::vector<uint8_t> data(size + 1);
- uint8_t* buf = data.data();
- uint8_t* buf_end = buf + data.size();
- buf = sign_check.Serialize(buf, buf_end);
- if (buf != (buf_end - 1)) {
- LOG(ERROR) << "Serialized size did not match up with actual usage.";
- return false;
- }
-
- std::ofstream file_stream(filename, std::ios::trunc | std::ios::binary);
- file_stream.write(reinterpret_cast<char*>(data.data()), data.size() - 1);
- if (!file_stream) {
- LOG(ERROR) << "Failed to save data to " << filename;
- return false;
- }
- return true;
-}
-
-Json::Value ReadProtectedJsonFromFile(
- TpmResourceManager& resource_manager, const std::string& filename) {
- std::ifstream file_stream(filename, std::ios::binary | std::ios::ate);
- std::streamsize size = file_stream.tellg();
- file_stream.seekg(0, std::ios::beg);
-
- if (size <= 0) {
- LOG(VERBOSE) << "File " << filename << " was empty.";
- return {};
- }
-
- std::vector<char> buffer(size);
- if (!file_stream.read(buffer.data(), size)) {
- LOG(ERROR) << "Unable to read from " << filename;
- return {};
- }
- if (!file_stream) {
- LOG(ERROR) << "Unable to read from " << filename;
- return {};
- }
-
- Json::Value json;
- JsonSerializable sensitive_material(json);
- auto parent_key_fn = ParentKeyCreator(kUniqueKey);
- EncryptedSerializable encryption(
- resource_manager, parent_key_fn, sensitive_material);
- auto signing_key_fn = SigningKeyCreator(kUniqueKey);
- HmacSerializable sign_check(
- resource_manager, signing_key_fn, TPM2_SHA256_DIGEST_SIZE, &encryption);
-
- auto buf = reinterpret_cast<const uint8_t*>(buffer.data());
- auto buf_end = buf + buffer.size();
- if (!sign_check.Deserialize(&buf, buf_end)) {
- LOG(ERROR) << "Failed to deserialize json data from " << filename;
- return {};
- }
-
- return json;
-}
diff --git a/host/commands/secure_env/json_serializable.h b/host/commands/secure_env/json_serializable.h
deleted file mode 100644
index f96aab35a..000000000
--- a/host/commands/secure_env/json_serializable.h
+++ /dev/null
@@ -1,25 +0,0 @@
-//
-// Copyright (C) 2020 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 <json/json.h>
-
-#include "host/commands/secure_env/tpm_resource_manager.h"
-
-bool WriteProtectedJsonToFile(
- TpmResourceManager&, const std::string& filename, Json::Value);
-Json::Value ReadProtectedJsonFromFile(
- TpmResourceManager&, const std::string& filename);
diff --git a/host/commands/secure_env/keymaster_responder.cpp b/host/commands/secure_env/keymaster_responder.cpp
deleted file mode 100644
index a564254d2..000000000
--- a/host/commands/secure_env/keymaster_responder.cpp
+++ /dev/null
@@ -1,109 +0,0 @@
-//
-// Copyright (C) 2020 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 "keymaster_responder.h"
-
-#include <android-base/logging.h>
-#include <keymaster/android_keymaster_messages.h>
-
-KeymasterResponder::KeymasterResponder(
- cuttlefish::KeymasterChannel& channel, keymaster::AndroidKeymaster& keymaster)
- : channel_(channel), keymaster_(keymaster) {
-}
-
-bool KeymasterResponder::ProcessMessage() {
- auto request = channel_.ReceiveMessage();
- if (!request) {
- LOG(ERROR) << "Could not receive message";
- return false;
- }
- const uint8_t* buffer = request->payload;
- const uint8_t* end = request->payload + request->payload_size;
- switch(request->cmd) {
- using namespace keymaster;
-#define HANDLE_MESSAGE(ENUM_NAME, METHOD_NAME) \
- case ENUM_NAME: {\
- METHOD_NAME##Request request(keymaster_.message_version()); \
- if (!request.Deserialize(&buffer, end)) { \
- LOG(ERROR) << "Failed to deserialize " #METHOD_NAME "Request"; \
- return false; \
- } \
- METHOD_NAME##Response response(keymaster_.message_version()); \
- keymaster_.METHOD_NAME(request, &response); \
- return channel_.SendResponse(ENUM_NAME, response); \
- }
- HANDLE_MESSAGE(GENERATE_KEY, GenerateKey)
- HANDLE_MESSAGE(BEGIN_OPERATION, BeginOperation)
- HANDLE_MESSAGE(UPDATE_OPERATION, UpdateOperation)
- HANDLE_MESSAGE(FINISH_OPERATION, FinishOperation)
- HANDLE_MESSAGE(ABORT_OPERATION, AbortOperation)
- HANDLE_MESSAGE(IMPORT_KEY, ImportKey)
- HANDLE_MESSAGE(EXPORT_KEY, ExportKey)
- HANDLE_MESSAGE(GET_VERSION, GetVersion)
- HANDLE_MESSAGE(GET_SUPPORTED_ALGORITHMS, SupportedAlgorithms)
- HANDLE_MESSAGE(GET_SUPPORTED_BLOCK_MODES, SupportedBlockModes)
- HANDLE_MESSAGE(GET_SUPPORTED_PADDING_MODES, SupportedPaddingModes)
- HANDLE_MESSAGE(GET_SUPPORTED_DIGESTS, SupportedDigests)
- HANDLE_MESSAGE(GET_SUPPORTED_IMPORT_FORMATS, SupportedImportFormats)
- HANDLE_MESSAGE(GET_SUPPORTED_EXPORT_FORMATS, SupportedExportFormats)
- HANDLE_MESSAGE(GET_KEY_CHARACTERISTICS, GetKeyCharacteristics)
- HANDLE_MESSAGE(ATTEST_KEY, AttestKey)
- HANDLE_MESSAGE(UPGRADE_KEY, UpgradeKey)
- HANDLE_MESSAGE(CONFIGURE, Configure)
- HANDLE_MESSAGE(DELETE_KEY, DeleteKey)
- HANDLE_MESSAGE(DELETE_ALL_KEYS, DeleteAllKeys)
- HANDLE_MESSAGE(IMPORT_WRAPPED_KEY, ImportWrappedKey)
- HANDLE_MESSAGE(GENERATE_TIMESTAMP_TOKEN, GenerateTimestampToken)
-#undef HANDLE_MESSAGE
-#define HANDLE_MESSAGE_W_RETURN(ENUM_NAME, METHOD_NAME) \
- case ENUM_NAME: {\
- METHOD_NAME##Request request(keymaster_.message_version()); \
- if (!request.Deserialize(&buffer, end)) { \
- LOG(ERROR) << "Failed to deserialize " #METHOD_NAME "Request"; \
- return false; \
- } \
- auto response = keymaster_.METHOD_NAME(request); \
- return channel_.SendResponse(ENUM_NAME, response); \
- }
- HANDLE_MESSAGE_W_RETURN(COMPUTE_SHARED_HMAC, ComputeSharedHmac)
- HANDLE_MESSAGE_W_RETURN(VERIFY_AUTHORIZATION, VerifyAuthorization)
- HANDLE_MESSAGE_W_RETURN(DEVICE_LOCKED, DeviceLocked)
- HANDLE_MESSAGE_W_RETURN(GET_VERSION_2, GetVersion2)
-#undef HANDLE_MESSAGE
-#define HANDLE_MESSAGE_W_RETURN_NO_ARG(ENUM_NAME, METHOD_NAME) \
- case ENUM_NAME: {\
- auto response = keymaster_.METHOD_NAME(); \
- return channel_.SendResponse(ENUM_NAME, response); \
- }
- HANDLE_MESSAGE_W_RETURN_NO_ARG(GET_HMAC_SHARING_PARAMETERS, GetHmacSharingParameters)
- HANDLE_MESSAGE_W_RETURN_NO_ARG(EARLY_BOOT_ENDED, EarlyBootEnded)
-#undef HANDLE_MESSAGE
- case ADD_RNG_ENTROPY: {
- AddEntropyRequest request(keymaster_.message_version());
- if (!request.Deserialize(&buffer, end)) {
- LOG(ERROR) << "Failed to deserialize AddEntropyRequest";
- return false;
- }
- AddEntropyResponse response(keymaster_.message_version());;
- keymaster_.AddRngEntropy(request, &response);
- return channel_.SendResponse(ADD_RNG_ENTROPY, response);
- }
- case DESTROY_ATTESTATION_IDS:
- // Cuttlefish doesn't support ID attestation.
- default:
- LOG(ERROR) << "Unknown request type: " << request->cmd;
- return false;
- }
-}
diff --git a/host/commands/secure_env/keymaster_responder.h b/host/commands/secure_env/keymaster_responder.h
deleted file mode 100644
index f8fb6ec87..000000000
--- a/host/commands/secure_env/keymaster_responder.h
+++ /dev/null
@@ -1,31 +0,0 @@
-//
-// Copyright (C) 2020 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 <keymaster/android_keymaster.h>
-
-#include "common/libs/security/keymaster_channel.h"
-
-class KeymasterResponder {
-private:
- cuttlefish::KeymasterChannel& channel_;
- keymaster::AndroidKeymaster& keymaster_;
-public:
- KeymasterResponder(cuttlefish::KeymasterChannel& channel,
- keymaster::AndroidKeymaster& keymaster);
-
- bool ProcessMessage();
-};
diff --git a/host/commands/secure_env/primary_key_builder.cpp b/host/commands/secure_env/primary_key_builder.cpp
deleted file mode 100644
index a44ff248e..000000000
--- a/host/commands/secure_env/primary_key_builder.cpp
+++ /dev/null
@@ -1,135 +0,0 @@
-//
-// Copyright (C) 2020 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 "host/commands/secure_env/primary_key_builder.h"
-
-#include <android-base/logging.h>
-#include <tss2/tss2_mu.h>
-#include <tss2/tss2_rc.h>
-
-PrimaryKeyBuilder::PrimaryKeyBuilder() : public_area_({}) {
- public_area_.nameAlg = TPM2_ALG_SHA256;
-};
-
-void PrimaryKeyBuilder::SigningKey() {
- public_area_.type = TPM2_ALG_KEYEDHASH;
- public_area_.objectAttributes |= TPMA_OBJECT_SIGN_ENCRYPT;
- public_area_.objectAttributes |= TPMA_OBJECT_USERWITHAUTH;
- public_area_.objectAttributes |= TPMA_OBJECT_SENSITIVEDATAORIGIN;
- public_area_.parameters.keyedHashDetail.scheme = (TPMT_KEYEDHASH_SCHEME) {
- .scheme = TPM2_ALG_HMAC,
- .details.hmac.hashAlg = TPM2_ALG_SHA256,
- };
-}
-
-void PrimaryKeyBuilder::ParentKey() {
- public_area_.type = TPM2_ALG_SYMCIPHER;
- public_area_.objectAttributes |= TPMA_OBJECT_USERWITHAUTH;
- public_area_.objectAttributes |= TPMA_OBJECT_RESTRICTED;
- public_area_.objectAttributes |= TPMA_OBJECT_DECRYPT;
- public_area_.objectAttributes |= TPMA_OBJECT_FIXEDTPM;
- public_area_.objectAttributes |= TPMA_OBJECT_FIXEDPARENT;
- public_area_.objectAttributes |= TPMA_OBJECT_SENSITIVEDATAORIGIN;
- public_area_.parameters.symDetail.sym = (TPMT_SYM_DEF_OBJECT) {
- .algorithm = TPM2_ALG_AES,
- .keyBits.aes = 128, // The default maximum AES key size in the simulator.
- .mode.aes = TPM2_ALG_CFB,
- };
-}
-
-void PrimaryKeyBuilder::UniqueData(const std::string& data) {
- if (data.size() > TPM2_SHA256_DIGEST_SIZE) {
- LOG(FATAL) << "Unique data size was too large";
- }
- /* The unique field normally has a precise size to go with the type of the
- * object. During primary key creation the unique field accepts any short byte
- * string to let the user introduce variability into the primary key creation
- * process which is otherwise determinstic relative to secret TPM state. */
- public_area_.unique.sym.size = data.size();
- memcpy(&public_area_.unique.sym.buffer, data.data(), data.size());
-}
-
-TpmObjectSlot PrimaryKeyBuilder::CreateKey(
- TpmResourceManager& resource_manager) {
- TPM2B_AUTH authValue = {};
- auto rc =
- Esys_TR_SetAuth(resource_manager.Esys(), ESYS_TR_RH_OWNER, &authValue);
- if (rc != TSS2_RC_SUCCESS) {
- LOG(ERROR) << "Esys_TR_SetAuth failed with return code " << rc
- << " (" << Tss2_RC_Decode(rc) << ")";
- return {};
- }
-
- TPM2B_TEMPLATE public_template = {};
- size_t offset = 0;
- rc = Tss2_MU_TPMT_PUBLIC_Marshal(&public_area_, &public_template.buffer[0],
- sizeof(public_template.buffer), &offset);
- if (rc != TSS2_RC_SUCCESS) {
- LOG(ERROR) << "Tss2_MU_TPMT_PUBLIC_Marshal failed with return code " << rc
- << " (" << Tss2_RC_Decode(rc) << ")";
- return {};
- }
- public_template.size = offset;
-
- TPM2B_SENSITIVE_CREATE in_sensitive = {};
-
- auto key_slot = resource_manager.ReserveSlot();
- if (!key_slot) {
- LOG(ERROR) << "No slots available";
- return {};
- }
- ESYS_TR raw_handle;
- // TODO(b/154956668): Define better ACLs on these keys.
- // Since this is a primary key, it's generated deterministically. It would
- // also be possible to generate this once and hold it in storage.
- rc = Esys_CreateLoaded(
- /* esysContext */ resource_manager.Esys(),
- /* primaryHandle */ ESYS_TR_RH_OWNER,
- /* shandle1 */ ESYS_TR_PASSWORD,
- /* shandle2 */ ESYS_TR_NONE,
- /* shandle3 */ ESYS_TR_NONE,
- /* inSensitive */ &in_sensitive,
- /* inPublic */ &public_template,
- /* objectHandle */ &raw_handle,
- /* outPrivate */ nullptr,
- /* outPublic */ nullptr);
- if (rc != TSS2_RC_SUCCESS) {
- LOG(ERROR) << "Esys_CreateLoaded failed with return code " << rc
- << " (" << Tss2_RC_Decode(rc) << ")";
- return {};
- }
- key_slot->set(raw_handle);
- return key_slot;
-}
-
-std::function<TpmObjectSlot(TpmResourceManager&)>
-SigningKeyCreator(const std::string& unique) {
- return [unique](TpmResourceManager& resource_manager) {
- PrimaryKeyBuilder key_builder;
- key_builder.SigningKey();
- key_builder.UniqueData(unique);
- return key_builder.CreateKey(resource_manager);
- };
-}
-
-std::function<TpmObjectSlot(TpmResourceManager&)>
-ParentKeyCreator(const std::string& unique) {
- return [unique](TpmResourceManager& resource_manager) {
- PrimaryKeyBuilder key_builder;
- key_builder.ParentKey();
- key_builder.UniqueData(unique);
- return key_builder.CreateKey(resource_manager);
- };
-}
diff --git a/host/commands/secure_env/primary_key_builder.h b/host/commands/secure_env/primary_key_builder.h
deleted file mode 100644
index 46e5461fa..000000000
--- a/host/commands/secure_env/primary_key_builder.h
+++ /dev/null
@@ -1,42 +0,0 @@
-//
-// Copyright (C) 2020 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 <functional>
-#include <string>
-
-#include <tss2/tss2_esys.h>
-
-#include "host/commands/secure_env/tpm_resource_manager.h"
-
-class PrimaryKeyBuilder {
-public:
- PrimaryKeyBuilder();
-
- void SigningKey();
- void ParentKey();
- void UniqueData(const std::string&);
-
- TpmObjectSlot CreateKey(TpmResourceManager&);
-private:
- TPMT_PUBLIC public_area_;
-};
-
-std::function<TpmObjectSlot(TpmResourceManager&)>
-SigningKeyCreator(const std::string& unique);
-
-std::function<TpmObjectSlot(TpmResourceManager&)>
-ParentKeyCreator(const std::string& unique);
diff --git a/host/commands/secure_env/secure_env.cpp b/host/commands/secure_env/secure_env.cpp
deleted file mode 100644
index c050c58d1..000000000
--- a/host/commands/secure_env/secure_env.cpp
+++ /dev/null
@@ -1,182 +0,0 @@
-//
-// Copyright (C) 2020 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 <thread>
-
-#include <android-base/logging.h>
-#include <gflags/gflags.h>
-#include <keymaster/android_keymaster.h>
-#include <keymaster/soft_keymaster_logger.h>
-#include <keymaster/contexts/pure_soft_keymaster_context.h>
-#include <tss2/tss2_esys.h>
-#include <tss2/tss2_rc.h>
-
-#include "common/libs/fs/shared_fd.h"
-#include "common/libs/security/gatekeeper_channel.h"
-#include "common/libs/security/keymaster_channel.h"
-#include "host/commands/secure_env/device_tpm.h"
-#include "host/commands/secure_env/fragile_tpm_storage.h"
-#include "host/commands/secure_env/gatekeeper_responder.h"
-#include "host/commands/secure_env/insecure_fallback_storage.h"
-#include "host/commands/secure_env/in_process_tpm.h"
-#include "host/commands/secure_env/keymaster_responder.h"
-#include "host/commands/secure_env/soft_gatekeeper.h"
-#include "host/commands/secure_env/tpm_gatekeeper.h"
-#include "host/commands/secure_env/tpm_keymaster_context.h"
-#include "host/commands/secure_env/tpm_keymaster_enforcement.h"
-#include "host/commands/secure_env/tpm_resource_manager.h"
-#include "host/libs/config/logging.h"
-
-// Copied from AndroidKeymaster4Device
-constexpr size_t kOperationTableSize = 16;
-
-DEFINE_int32(keymaster_fd_in, -1, "A pipe for keymaster communication");
-DEFINE_int32(keymaster_fd_out, -1, "A pipe for keymaster communication");
-DEFINE_int32(gatekeeper_fd_in, -1, "A pipe for gatekeeper communication");
-DEFINE_int32(gatekeeper_fd_out, -1, "A pipe for gatekeeper communication");
-
-DEFINE_string(tpm_impl,
- "in_memory",
- "The TPM implementation. \"in_memory\" or \"host_device\"");
-
-DEFINE_string(keymint_impl, "tpm",
- "The keymaster implementation. \"tpm\" or \"software\"");
-
-DEFINE_string(gatekeeper_impl, "tpm",
- "The gatekeeper implementation. \"tpm\" or \"software\"");
-
-int main(int argc, char** argv) {
- cuttlefish::DefaultSubprocessLogging(argv);
- gflags::ParseCommandLineFlags(&argc, &argv, true);
- keymaster::SoftKeymasterLogger km_logger;
-
- std::unique_ptr<Tpm> tpm;
- if (FLAGS_tpm_impl == "in_memory") {
- tpm.reset(new InProcessTpm());
- } else if (FLAGS_tpm_impl == "host_device") {
- tpm.reset(new DeviceTpm("/dev/tpm0"));
- } else {
- LOG(FATAL) << "Unknown TPM implementation: " << FLAGS_tpm_impl;
- }
-
- if (tpm->TctiContext() == nullptr) {
- LOG(FATAL) << "Unable to connect to TPM implementation.";
- }
-
- std::unique_ptr<TpmResourceManager> resource_manager;
- std::unique_ptr<ESYS_CONTEXT, void(*)(ESYS_CONTEXT*)> esys(
- nullptr, [](ESYS_CONTEXT* esys) { Esys_Finalize(&esys); });
- if (FLAGS_keymint_impl == "tpm" || FLAGS_gatekeeper_impl == "tpm") {
- ESYS_CONTEXT* esys_ptr = nullptr;
- auto rc = Esys_Initialize(&esys_ptr, tpm->TctiContext(), nullptr);
- if (rc != TPM2_RC_SUCCESS) {
- LOG(FATAL) << "Could not initialize esys: " << Tss2_RC_Decode(rc)
- << " (" << rc << ")";
- }
- esys.reset(esys_ptr);
- resource_manager.reset(new TpmResourceManager(esys.get()));
- }
-
- std::unique_ptr<GatekeeperStorage> secure_storage;
- std::unique_ptr<GatekeeperStorage> insecure_storage;
- std::unique_ptr<gatekeeper::GateKeeper> gatekeeper;
- std::unique_ptr<keymaster::KeymasterEnforcement> keymaster_enforcement;
- if (FLAGS_gatekeeper_impl == "software") {
- gatekeeper.reset(new gatekeeper::SoftGateKeeper);
- keymaster_enforcement.reset(
- new keymaster::SoftKeymasterEnforcement(64, 64));
- } else if (FLAGS_gatekeeper_impl == "tpm") {
- secure_storage.reset(
- new FragileTpmStorage(*resource_manager, "gatekeeper_secure"));
- insecure_storage.reset(
- new InsecureFallbackStorage(*resource_manager, "gatekeeper_insecure"));
- TpmGatekeeper* tpm_gatekeeper =
- new TpmGatekeeper(*resource_manager, *secure_storage, *insecure_storage);
- gatekeeper.reset(tpm_gatekeeper);
- keymaster_enforcement.reset(
- new TpmKeymasterEnforcement(*resource_manager, *tpm_gatekeeper));
- }
-
- // keymaster::AndroidKeymaster puts the given pointer into a UniquePtr,
- // taking ownership.
- keymaster::KeymasterContext* keymaster_context;
- if (FLAGS_keymint_impl == "software") {
- // TODO: See if this is the right KM version.
- keymaster_context =
- new keymaster::PureSoftKeymasterContext(keymaster::KmVersion::KEYMASTER_4,
- KM_SECURITY_LEVEL_SOFTWARE);
- } else if (FLAGS_keymint_impl == "tpm") {
- keymaster_context =
- new TpmKeymasterContext(*resource_manager, *keymaster_enforcement);
- } else {
- LOG(FATAL) << "Unknown keymaster implementation " << FLAGS_keymint_impl;
- return -1;
- }
- keymaster::AndroidKeymaster keymaster{
- keymaster_context, kOperationTableSize,
- keymaster::MessageVersion(keymaster::KmVersion::KEYMINT_1,
- 0 /* km_date */)};
-
- CHECK(FLAGS_keymaster_fd_in != -1);
- auto keymaster_in = cuttlefish::SharedFD::Dup(FLAGS_keymaster_fd_in);
- CHECK(keymaster_in->IsOpen()) << "Could not dup input fd: "
- << keymaster_in->StrError();
- close(FLAGS_keymaster_fd_in);
-
- CHECK(FLAGS_keymaster_fd_out != -1);
- auto keymaster_out = cuttlefish::SharedFD::Dup(FLAGS_keymaster_fd_out);
- CHECK(keymaster_out->IsOpen()) << "Could not dup output fd: "
- << keymaster_out->StrError();
- close(FLAGS_keymaster_fd_out);
-
- CHECK(FLAGS_gatekeeper_fd_in != -1);
- auto gatekeeper_in = cuttlefish::SharedFD::Dup(FLAGS_gatekeeper_fd_in);
- CHECK(gatekeeper_in->IsOpen()) << "Could not dup input fd: "
- << gatekeeper_in->StrError();
- close(FLAGS_gatekeeper_fd_in);
-
- CHECK(FLAGS_gatekeeper_fd_out != -1);
- auto gatekeeper_out = cuttlefish::SharedFD::Dup(FLAGS_gatekeeper_fd_out);
- CHECK(gatekeeper_out->IsOpen()) << "Could not dup output fd: "
- << keymaster_out->StrError();
- close(FLAGS_gatekeeper_fd_out);
-
- std::thread keymaster_thread([keymaster_in, keymaster_out, &keymaster]() {
- while (true) {
- cuttlefish::KeymasterChannel keymaster_channel(
- keymaster_in, keymaster_out);
-
- KeymasterResponder keymaster_responder(keymaster_channel, keymaster);
-
- while (keymaster_responder.ProcessMessage()) {
- }
- }
- });
-
- std::thread gatekeeper_thread([gatekeeper_in, gatekeeper_out, &gatekeeper]() {
- while (true) {
- cuttlefish::GatekeeperChannel gatekeeper_channel(
- gatekeeper_in, gatekeeper_out);
-
- GatekeeperResponder gatekeeper_responder(gatekeeper_channel, *gatekeeper);
-
- while (gatekeeper_responder.ProcessMessage()) {
- }
- }
- });
-
- keymaster_thread.join();
- gatekeeper_thread.join();
-}
diff --git a/host/commands/secure_env/soft_gatekeeper.h b/host/commands/secure_env/soft_gatekeeper.h
deleted file mode 100644
index c3322e87d..000000000
--- a/host/commands/secure_env/soft_gatekeeper.h
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * 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.
- *
- */
-
-#pragma once
-
-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 <memory>
-#include <unordered_map>
-
-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;
- *auth_token_key = key_.get();
- *length = SIGNATURE_LENGTH_BYTES;
- return true;
- }
-
- virtual void GetPasswordKey(const uint8_t** password_key, uint32_t* length) {
- if (password_key == NULL || length == NULL) return;
- *password_key = key_.get();
- *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.size() + 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.Data<uint8_t>(), password.size());
-
- 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_;
-};
-} // namespace gatekeeper
diff --git a/host/commands/secure_env/tpm_attestation_record.cpp b/host/commands/secure_env/tpm_attestation_record.cpp
deleted file mode 100644
index f47a0ef7c..000000000
--- a/host/commands/secure_env/tpm_attestation_record.cpp
+++ /dev/null
@@ -1,81 +0,0 @@
-//
-// Copyright (C) 2020 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 "host/commands/secure_env/tpm_attestation_record.h"
-
-#include <keymaster/contexts/soft_attestation_cert.h>
-
-#include <android-base/logging.h>
-
-using keymaster::AuthorizationSet;
-
-keymaster_security_level_t TpmAttestationRecordContext::GetSecurityLevel() const {
- return KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT;
-}
-
-keymaster_error_t TpmAttestationRecordContext::VerifyAndCopyDeviceIds(
- const AuthorizationSet& attestation_params,
- AuthorizationSet* attestation) const {
- LOG(DEBUG) << "TODO(schuffelen): Implement VerifyAndCopyDeviceIds";
- attestation->Difference(attestation_params);
- attestation->Union(attestation_params);
- if (int index = attestation->find(keymaster::TAG_ATTESTATION_APPLICATION_ID)) {
- attestation->erase(index);
- }
- return KM_ERROR_OK;
-}
-
-keymaster::Buffer TpmAttestationRecordContext::GenerateUniqueId(
- uint64_t, const keymaster_blob_t&, bool, keymaster_error_t* error) const {
- LOG(ERROR) << "TODO(schuffelen): Implement GenerateUniqueId";
- *error = KM_ERROR_UNIMPLEMENTED;
- return {};
-}
-
-const keymaster::AttestationContext::VerifiedBootParams*
-TpmAttestationRecordContext::GetVerifiedBootParams(keymaster_error_t* error) const {
- LOG(DEBUG) << "TODO(schuffelen): Implement GetVerifiedBootParams";
- if (!vb_params_) {
- vb_params_.reset(new VerifiedBootParams{});
-
- // TODO(schuffelen): Get this data out of vbmeta
- static uint8_t fake_vb_key[32];
- static bool fake_vb_key_initialized = false;
- if (!fake_vb_key_initialized) {
- for (int i = 0; i < sizeof(fake_vb_key); i++) {
- fake_vb_key[i] = rand();
- }
- fake_vb_key_initialized = true;
- }
- vb_params_->verified_boot_key = {fake_vb_key, sizeof(fake_vb_key)};
- vb_params_->verified_boot_hash = {fake_vb_key, sizeof(fake_vb_key)};
- vb_params_->verified_boot_state = KM_VERIFIED_BOOT_VERIFIED;
- vb_params_->device_locked = true;
- }
- *error = KM_ERROR_OK;
- return vb_params_.get();
-}
-
-keymaster::KeymasterKeyBlob
-TpmAttestationRecordContext::GetAttestationKey(keymaster_algorithm_t algorithm,
- keymaster_error_t* error) const {
- return keymaster::KeymasterKeyBlob(*keymaster::getAttestationKey(algorithm, error));
-}
-
-keymaster::CertificateChain
-TpmAttestationRecordContext::GetAttestationChain(keymaster_algorithm_t algorithm,
- keymaster_error_t* error) const {
- return keymaster::getAttestationChain(algorithm, error);
-}
diff --git a/host/commands/secure_env/tpm_attestation_record.h b/host/commands/secure_env/tpm_attestation_record.h
deleted file mode 100644
index 01e31d7f8..000000000
--- a/host/commands/secure_env/tpm_attestation_record.h
+++ /dev/null
@@ -1,43 +0,0 @@
-//
-// Copyright (C) 2020 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 <memory>
-
-#include <keymaster/attestation_context.h>
-
-class TpmAttestationRecordContext : public keymaster::AttestationContext {
-public:
- TpmAttestationRecordContext()
- : keymaster::AttestationContext(::keymaster::KmVersion::KEYMINT_1) {}
- ~TpmAttestationRecordContext() = default;
-
- keymaster_security_level_t GetSecurityLevel() const override;
- keymaster_error_t VerifyAndCopyDeviceIds(
- const keymaster::AuthorizationSet&,
- keymaster::AuthorizationSet*) const override;
- keymaster::Buffer GenerateUniqueId(uint64_t, const keymaster_blob_t&, bool,
- keymaster_error_t*) const override;
- const VerifiedBootParams* GetVerifiedBootParams(
- keymaster_error_t* error) const override;
- keymaster::KeymasterKeyBlob GetAttestationKey(
- keymaster_algorithm_t algorithm, keymaster_error_t* error) const override;
- keymaster::CertificateChain GetAttestationChain(
- keymaster_algorithm_t algorithm, keymaster_error_t* error) const override;
-
-private:
- mutable std::unique_ptr<VerifiedBootParams> vb_params_;
-};
diff --git a/host/commands/secure_env/tpm_auth.cpp b/host/commands/secure_env/tpm_auth.cpp
deleted file mode 100644
index 10f4b2d7c..000000000
--- a/host/commands/secure_env/tpm_auth.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-//
-// Copyright (C) 2020 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 "tpm_auth.h"
-
-#include <tuple>
-
-TpmAuth::TpmAuth(ESYS_TR auth): TpmAuth(auth, ESYS_TR_NONE, ESYS_TR_NONE) {}
-TpmAuth::TpmAuth(ESYS_TR auth1, ESYS_TR auth2)
- : TpmAuth(auth1, auth2, ESYS_TR_NONE) {}
-TpmAuth::TpmAuth(ESYS_TR auth1, ESYS_TR auth2, ESYS_TR auth3) {
- if (auth2 == ESYS_TR_NONE && auth3 != ESYS_TR_NONE) {
- std::swap(auth2, auth3);
- }
- if (auth1 == ESYS_TR_NONE && auth2 != ESYS_TR_NONE) {
- std::swap(auth1, auth2);
- }
- std::tie(auth1_, auth2_, auth3_) = std::make_tuple(auth1, auth2, auth3);
-}
-
-ESYS_TR TpmAuth::auth1() const {
- return auth1_;
-}
-
-ESYS_TR TpmAuth::auth2() const {
- return auth2_;
-}
-
-ESYS_TR TpmAuth::auth3() const {
- return auth3_;
-}
diff --git a/host/commands/secure_env/tpm_auth.h b/host/commands/secure_env/tpm_auth.h
deleted file mode 100644
index 196b5fd0c..000000000
--- a/host/commands/secure_env/tpm_auth.h
+++ /dev/null
@@ -1,43 +0,0 @@
-//
-// Copyright (C) 2020 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 <tss2/tss2_esys.h>
-
-/**
- * Authorization wrapper for TPM2 calls.
- *
- * Most methods in tss2_esys.h take 3 ESYS_TR values for sessions and
- * authorization, with constraints that unused authorizations are all
- * ESYS_TR_NONE and are all at the end.
- *
- * This class is a convenience for specifying between 1 and 3
- * authorizations concisely and enforcing that the constraints are met.
- */
-class TpmAuth {
-public:
- TpmAuth(ESYS_TR auth1);
- TpmAuth(ESYS_TR auth1, ESYS_TR auth2);
- TpmAuth(ESYS_TR auth1, ESYS_TR auth2, ESYS_TR auth3);
-
- ESYS_TR auth1() const;
- ESYS_TR auth2() const;
- ESYS_TR auth3() const;
-private:
- ESYS_TR auth1_;
- ESYS_TR auth2_;
- ESYS_TR auth3_;
-};
diff --git a/host/commands/secure_env/tpm_commands.cpp b/host/commands/secure_env/tpm_commands.cpp
deleted file mode 100644
index 78e9d7fb7..000000000
--- a/host/commands/secure_env/tpm_commands.cpp
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Copyright (C) 2020 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 "tpm_commands.h"
-
-#include <tss2/tss2_tpm2_types.h>
-
-#include <cstddef>
-#include <string>
-
-std::string TpmCommandName(std::uint32_t command_num) {
- switch(command_num) {
- #define MATCH_TPM_COMMAND(name) case name: return #name;
- MATCH_TPM_COMMAND(TPM2_CC_NV_UndefineSpaceSpecial)
- MATCH_TPM_COMMAND(TPM2_CC_EvictControl)
- MATCH_TPM_COMMAND(TPM2_CC_HierarchyControl)
- MATCH_TPM_COMMAND(TPM2_CC_NV_UndefineSpace)
- MATCH_TPM_COMMAND(TPM2_CC_ChangeEPS)
- MATCH_TPM_COMMAND(TPM2_CC_ChangePPS)
- MATCH_TPM_COMMAND(TPM2_CC_Clear)
- MATCH_TPM_COMMAND(TPM2_CC_ClearControl)
- MATCH_TPM_COMMAND(TPM2_CC_ClockSet)
- MATCH_TPM_COMMAND(TPM2_CC_HierarchyChangeAuth)
- MATCH_TPM_COMMAND(TPM2_CC_NV_DefineSpace)
- MATCH_TPM_COMMAND(TPM2_CC_PCR_Allocate)
- MATCH_TPM_COMMAND(TPM2_CC_PCR_SetAuthPolicy)
- MATCH_TPM_COMMAND(TPM2_CC_PP_Commands)
- MATCH_TPM_COMMAND(TPM2_CC_SetPrimaryPolicy)
- MATCH_TPM_COMMAND(TPM2_CC_FieldUpgradeStart)
- MATCH_TPM_COMMAND(TPM2_CC_ClockRateAdjust)
- MATCH_TPM_COMMAND(TPM2_CC_CreatePrimary)
- MATCH_TPM_COMMAND(TPM2_CC_NV_GlobalWriteLock)
- MATCH_TPM_COMMAND(TPM2_CC_GetCommandAuditDigest)
- MATCH_TPM_COMMAND(TPM2_CC_NV_Increment)
- MATCH_TPM_COMMAND(TPM2_CC_NV_SetBits)
- MATCH_TPM_COMMAND(TPM2_CC_NV_Extend)
- MATCH_TPM_COMMAND(TPM2_CC_NV_Write)
- MATCH_TPM_COMMAND(TPM2_CC_NV_WriteLock)
- MATCH_TPM_COMMAND(TPM2_CC_DictionaryAttackLockReset)
- MATCH_TPM_COMMAND(TPM2_CC_DictionaryAttackParameters)
- MATCH_TPM_COMMAND(TPM2_CC_NV_ChangeAuth)
- MATCH_TPM_COMMAND(TPM2_CC_PCR_Event)
- MATCH_TPM_COMMAND(TPM2_CC_PCR_Reset)
- MATCH_TPM_COMMAND(TPM2_CC_SequenceComplete)
- MATCH_TPM_COMMAND(TPM2_CC_SetAlgorithmSet)
- MATCH_TPM_COMMAND(TPM2_CC_SetCommandCodeAuditStatus)
- MATCH_TPM_COMMAND(TPM2_CC_FieldUpgradeData)
- MATCH_TPM_COMMAND(TPM2_CC_IncrementalSelfTest)
- MATCH_TPM_COMMAND(TPM2_CC_SelfTest)
- MATCH_TPM_COMMAND(TPM2_CC_Startup)
- MATCH_TPM_COMMAND(TPM2_CC_Shutdown)
- MATCH_TPM_COMMAND(TPM2_CC_StirRandom)
- MATCH_TPM_COMMAND(TPM2_CC_ActivateCredential)
- MATCH_TPM_COMMAND(TPM2_CC_Certify)
- MATCH_TPM_COMMAND(TPM2_CC_PolicyNV)
- MATCH_TPM_COMMAND(TPM2_CC_CertifyCreation)
- MATCH_TPM_COMMAND(TPM2_CC_Duplicate)
- MATCH_TPM_COMMAND(TPM2_CC_GetTime)
- MATCH_TPM_COMMAND(TPM2_CC_GetSessionAuditDigest)
- MATCH_TPM_COMMAND(TPM2_CC_NV_Read)
- MATCH_TPM_COMMAND(TPM2_CC_NV_ReadLock)
- MATCH_TPM_COMMAND(TPM2_CC_ObjectChangeAuth)
- MATCH_TPM_COMMAND(TPM2_CC_PolicySecret)
- MATCH_TPM_COMMAND(TPM2_CC_Rewrap)
- MATCH_TPM_COMMAND(TPM2_CC_Create)
- MATCH_TPM_COMMAND(TPM2_CC_ECDH_ZGen)
- MATCH_TPM_COMMAND(TPM2_CC_HMAC)
- MATCH_TPM_COMMAND(TPM2_CC_Import)
- MATCH_TPM_COMMAND(TPM2_CC_Load)
- MATCH_TPM_COMMAND(TPM2_CC_Quote)
- MATCH_TPM_COMMAND(TPM2_CC_RSA_Decrypt)
- MATCH_TPM_COMMAND(TPM2_CC_HMAC_Start)
- MATCH_TPM_COMMAND(TPM2_CC_SequenceUpdate)
- MATCH_TPM_COMMAND(TPM2_CC_Sign)
- MATCH_TPM_COMMAND(TPM2_CC_Unseal)
- MATCH_TPM_COMMAND(TPM2_CC_PolicySigned)
- MATCH_TPM_COMMAND(TPM2_CC_ContextLoad)
- MATCH_TPM_COMMAND(TPM2_CC_ContextSave)
- MATCH_TPM_COMMAND(TPM2_CC_ECDH_KeyGen)
- MATCH_TPM_COMMAND(TPM2_CC_EncryptDecrypt)
- MATCH_TPM_COMMAND(TPM2_CC_FlushContext)
- MATCH_TPM_COMMAND(TPM2_CC_LoadExternal)
- MATCH_TPM_COMMAND(TPM2_CC_MakeCredential)
- MATCH_TPM_COMMAND(TPM2_CC_NV_ReadPublic)
- MATCH_TPM_COMMAND(TPM2_CC_PolicyAuthorize)
- MATCH_TPM_COMMAND(TPM2_CC_PolicyAuthValue)
- MATCH_TPM_COMMAND(TPM2_CC_PolicyCommandCode)
- MATCH_TPM_COMMAND(TPM2_CC_PolicyCounterTimer)
- MATCH_TPM_COMMAND(TPM2_CC_PolicyCpHash)
- MATCH_TPM_COMMAND(TPM2_CC_PolicyLocality)
- MATCH_TPM_COMMAND(TPM2_CC_PolicyNameHash)
- MATCH_TPM_COMMAND(TPM2_CC_PolicyOR)
- MATCH_TPM_COMMAND(TPM2_CC_PolicyTicket)
- MATCH_TPM_COMMAND(TPM2_CC_ReadPublic)
- MATCH_TPM_COMMAND(TPM2_CC_RSA_Encrypt)
- MATCH_TPM_COMMAND(TPM2_CC_StartAuthSession)
- MATCH_TPM_COMMAND(TPM2_CC_VerifySignature)
- MATCH_TPM_COMMAND(TPM2_CC_ECC_Parameters)
- MATCH_TPM_COMMAND(TPM2_CC_FirmwareRead)
- MATCH_TPM_COMMAND(TPM2_CC_GetCapability)
- MATCH_TPM_COMMAND(TPM2_CC_GetRandom)
- MATCH_TPM_COMMAND(TPM2_CC_GetTestResult)
- MATCH_TPM_COMMAND(TPM2_CC_Hash)
- MATCH_TPM_COMMAND(TPM2_CC_PCR_Read)
- MATCH_TPM_COMMAND(TPM2_CC_PolicyPCR)
- MATCH_TPM_COMMAND(TPM2_CC_PolicyRestart)
- MATCH_TPM_COMMAND(TPM2_CC_ReadClock)
- MATCH_TPM_COMMAND(TPM2_CC_PCR_Extend)
- MATCH_TPM_COMMAND(TPM2_CC_PCR_SetAuthValue)
- MATCH_TPM_COMMAND(TPM2_CC_NV_Certify)
- MATCH_TPM_COMMAND(TPM2_CC_EventSequenceComplete)
- MATCH_TPM_COMMAND(TPM2_CC_HashSequenceStart)
- MATCH_TPM_COMMAND(TPM2_CC_PolicyPhysicalPresence)
- MATCH_TPM_COMMAND(TPM2_CC_PolicyDuplicationSelect)
- MATCH_TPM_COMMAND(TPM2_CC_PolicyGetDigest)
- MATCH_TPM_COMMAND(TPM2_CC_TestParms)
- MATCH_TPM_COMMAND(TPM2_CC_Commit)
- MATCH_TPM_COMMAND(TPM2_CC_PolicyPassword)
- MATCH_TPM_COMMAND(TPM2_CC_ZGen_2Phase)
- MATCH_TPM_COMMAND(TPM2_CC_EC_Ephemeral)
- MATCH_TPM_COMMAND(TPM2_CC_PolicyNvWritten)
- MATCH_TPM_COMMAND(TPM2_CC_PolicyTemplate)
- MATCH_TPM_COMMAND(TPM2_CC_CreateLoaded)
- MATCH_TPM_COMMAND(TPM2_CC_PolicyAuthorizeNV)
- MATCH_TPM_COMMAND(TPM2_CC_EncryptDecrypt2)
- MATCH_TPM_COMMAND(TPM2_CC_AC_GetCapability)
- MATCH_TPM_COMMAND(TPM2_CC_AC_Send)
- MATCH_TPM_COMMAND(TPM2_CC_Policy_AC_SendSelect)
- MATCH_TPM_COMMAND(TPM2_CC_Vendor_TCG_Test)
- #undef MATCH_TPM_COMMAND
- default:
- return "Unknown";
- }
-}
diff --git a/host/commands/secure_env/tpm_encrypt_decrypt.cpp b/host/commands/secure_env/tpm_encrypt_decrypt.cpp
deleted file mode 100644
index 4a1711e0f..000000000
--- a/host/commands/secure_env/tpm_encrypt_decrypt.cpp
+++ /dev/null
@@ -1,100 +0,0 @@
-//
-// Copyright (C) 2020 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 "tpm_encrypt_decrypt.h"
-
-#include <algorithm>
-#include <cstring>
-#include <vector>
-
-#include <android-base/logging.h>
-#include <tss2/tss2_rc.h>
-
-using keymaster::KeymasterBlob;
-
-static bool TpmEncryptDecrypt(
- ESYS_CONTEXT* esys,
- ESYS_TR key_handle,
- TpmAuth auth,
- uint8_t* data_in,
- uint8_t* data_out,
- size_t data_size,
- bool decrypt) {
- // TODO(schuffelen): Pipeline this for performance. Will require reevaluating
- // the initialization vector logic.
- std::vector<unsigned char> converted(data_size);
- // malloc for parity with Esys_EncryptDecrypt2
- TPM2B_IV* init_vector_in = (TPM2B_IV*) malloc(sizeof(TPM2B_IV));
- *init_vector_in = {};
- init_vector_in->size = 16;
- for (auto processed = 0; processed < data_size;) {
- TPM2B_MAX_BUFFER in_data;
- in_data.size =
- std::min(data_size - processed, sizeof(in_data.buffer));
- std::memcpy(in_data.buffer, &data_in[processed], in_data.size);
- TPM2B_IV* init_vector_out = nullptr;
- TPM2B_MAX_BUFFER* out_data = nullptr;
- auto rc = Esys_EncryptDecrypt2(
- esys,
- key_handle,
- auth.auth1(),
- auth.auth2(),
- auth.auth3(),
- &in_data,
- decrypt ? TPM2_YES : TPM2_NO,
- TPM2_ALG_NULL,
- init_vector_in,
- &out_data,
- &init_vector_out);
- if (rc != TPM2_RC_SUCCESS) {
- LOG(ERROR) << "Esys_EncryptDecrypt2 failed: " << Tss2_RC_Decode(rc)
- << "(" << rc << ")";
- Esys_Free(init_vector_in);
- return false;
- }
- CHECK(init_vector_out != nullptr) << "init_vector_out was NULL";
- CHECK(out_data != nullptr) << "out_data was NULL";
- CHECK(out_data->size == in_data.size) << "data size mismatch";
- std::memcpy(&data_out[processed], out_data->buffer, out_data->size);
- Esys_Free(out_data);
- Esys_Free(init_vector_in);
- init_vector_in = init_vector_out;
- processed += in_data.size;
- }
- Esys_Free(init_vector_in);
- return true;
-}
-
-bool TpmEncrypt(
- ESYS_CONTEXT* esys,
- ESYS_TR key_handle,
- TpmAuth auth,
- uint8_t* data_in,
- uint8_t* data_out,
- size_t data_size) {
- return TpmEncryptDecrypt(
- esys, key_handle, auth, data_in, data_out, data_size, false);
-}
-
-bool TpmDecrypt(
- ESYS_CONTEXT* esys,
- ESYS_TR key_handle,
- TpmAuth auth,
- uint8_t* data_in,
- uint8_t* data_out,
- size_t data_size) {
- return TpmEncryptDecrypt(
- esys, key_handle, auth, data_in, data_out, data_size, true);
-}
diff --git a/host/commands/secure_env/tpm_encrypt_decrypt.h b/host/commands/secure_env/tpm_encrypt_decrypt.h
deleted file mode 100644
index b75bafb88..000000000
--- a/host/commands/secure_env/tpm_encrypt_decrypt.h
+++ /dev/null
@@ -1,50 +0,0 @@
-//
-// Copyright (C) 2020 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 <keymaster/android_keymaster_utils.h>
-#include <tss2/tss2_esys.h>
-
-#include "host/commands/secure_env/tpm_auth.h"
-
-/**
- * Encrypt `data_in` to `data_out`, which are both buffers of size `data_size`.
- *
- * There are no integrity guarantees on this data: if the encrypted data is
- * corrupted, decrypting it could either fail or produce corrupted output.
- */
-bool TpmEncrypt(
- ESYS_CONTEXT* esys,
- ESYS_TR key_handle,
- TpmAuth auth,
- uint8_t* data_in,
- uint8_t* data_out,
- size_t data_size);
-
-
-/**
- * Decrypt `data_in` to `data_out`, which are both buffers of size `data_size`.
- *
- * There are no integrity guarantees on this data: if the encrypted data is
- * corrupted, decrypting it could either fail or produce corrupted output.
- */
-bool TpmDecrypt(
- ESYS_CONTEXT* esys,
- ESYS_TR key_handle,
- TpmAuth auth,
- uint8_t* data_in,
- uint8_t* data_out,
- size_t data_size);
diff --git a/host/commands/secure_env/tpm_gatekeeper.cpp b/host/commands/secure_env/tpm_gatekeeper.cpp
deleted file mode 100644
index e4f61e7b8..000000000
--- a/host/commands/secure_env/tpm_gatekeeper.cpp
+++ /dev/null
@@ -1,242 +0,0 @@
-//
-// Copyright (C) 2020 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 "tpm_gatekeeper.h"
-
-#include <algorithm>
-#include <optional>
-#include <vector>
-
-#include <android-base/logging.h>
-#include <tss2/tss2_esys.h>
-#include <tss2/tss2_mu.h>
-#include <tss2/tss2_rc.h>
-
-#include "host/commands/secure_env/primary_key_builder.h"
-#include "host/commands/secure_env/tpm_auth.h"
-#include "host/commands/secure_env/tpm_hmac.h"
-#include "host/commands/secure_env/tpm_random_source.h"
-
-TpmGatekeeper::TpmGatekeeper(
- TpmResourceManager& resource_manager,
- GatekeeperStorage& secure_storage,
- GatekeeperStorage& insecure_storage)
- : resource_manager_(resource_manager)
- , secure_storage_(secure_storage)
- , insecure_storage_(insecure_storage) {
-}
-
-/*
- * The reinterpret_cast and kPasswordUnique data is combined together with TPM
- * internal state to create the actual key used for Gatekeeper operations.
- */
-
-bool TpmGatekeeper::GetAuthTokenKey(
- const uint8_t** auth_token_key, uint32_t* length) const {
- static constexpr char kAuthTokenUnique[] = "TpmGatekeeper auth token key";
- *auth_token_key = reinterpret_cast<const uint8_t*>(kAuthTokenUnique);
- *length = sizeof(kAuthTokenUnique);
- return true;
-}
-
-void TpmGatekeeper::GetPasswordKey(
- const uint8_t** password_key, uint32_t* length) {
- static constexpr char kPasswordUnique[] = "TpmGatekeeper password key";
- *password_key = reinterpret_cast<const uint8_t*>(kPasswordUnique);
- *length = sizeof(kPasswordUnique);
-}
-
-void TpmGatekeeper::ComputePasswordSignature(
- uint8_t* signature,
- uint32_t signature_length,
- const uint8_t* key,
- uint32_t key_length,
- const uint8_t* password,
- uint32_t password_length,
- gatekeeper::salt_t salt) const {
- std::vector<uint8_t> message(password_length + sizeof(salt));
- memcpy(message.data(), password, password_length);
- memcpy(message.data() + password_length, &salt, sizeof(salt));
- return ComputeSignature(
- signature,
- signature_length,
- key,
- key_length,
- message.data(),
- message.size());
-}
-
-void TpmGatekeeper::GetRandom(void* random, uint32_t requested_size) const {
- auto random_uint8 = reinterpret_cast<uint8_t*>(random);
- TpmRandomSource(resource_manager_.Esys())
- .GenerateRandom(random_uint8, requested_size);
-}
-
-void TpmGatekeeper::ComputeSignature(
- uint8_t* signature,
- uint32_t signature_length,
- const uint8_t* key,
- uint32_t key_length,
- const uint8_t* message,
- uint32_t length) const {
- memset(signature, 0, signature_length);
- std::string key_unique(reinterpret_cast<const char*>(key), key_length);
- PrimaryKeyBuilder key_builder;
- key_builder.UniqueData(key_unique);
- key_builder.SigningKey();
- auto key_slot = key_builder.CreateKey(resource_manager_);
- if (!key_slot) {
- LOG(ERROR) << "Unable to load signing key into TPM memory";
- return;
- }
- auto calculated_signature =
- TpmHmac(
- resource_manager_,
- key_slot->get(),
- TpmAuth(ESYS_TR_PASSWORD),
- message,
- length);
- if (!calculated_signature) {
- LOG(ERROR) << "Failure in calculating signature";
- return;
- }
- memcpy(
- signature,
- calculated_signature->buffer,
- std::min((int) calculated_signature->size, (int) signature_length));
-}
-
-uint64_t TpmGatekeeper::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);
-}
-
-gatekeeper::failure_record_t DefaultRecord(
- gatekeeper::secure_id_t secure_user_id) {
- return (gatekeeper::failure_record_t) {
- .secure_user_id = secure_user_id,
- .last_checked_timestamp = 0,
- .failure_counter = 0,
- };
-}
-
-static std::unique_ptr<TPM2B_MAX_NV_BUFFER> RecordToNvBuffer(
- const gatekeeper::failure_record_t& record) {
- auto ret = std::make_unique<TPM2B_MAX_NV_BUFFER>();
- static_assert(sizeof(ret->buffer) >= sizeof(record));
- ret->size = sizeof(record);
- std::memcpy(ret->buffer, &record, sizeof(record));
- return ret;
-}
-
-static std::optional<gatekeeper::failure_record_t> NvBufferToRecord(
- const TPM2B_MAX_NV_BUFFER& buffer) {
- gatekeeper::failure_record_t ret;
- if (buffer.size != sizeof(ret)) {
- LOG(ERROR) << "NV Buffer had an incorrect size.";
- return {};
- }
- memcpy(&ret, buffer.buffer, sizeof(ret));
- return ret;
-}
-
-static bool GetFailureRecordImpl(
- GatekeeperStorage& storage,
- uint32_t uid,
- gatekeeper::secure_id_t secure_user_id,
- gatekeeper::failure_record_t *record) {
- Json::Value key{std::to_string(uid)}; // jsoncpp integer comparisons are janky
- if (!storage.HasKey(key)) {
- if (!storage.Allocate(key, sizeof(gatekeeper::failure_record_t))) {
- LOG(ERROR) << "Allocation failed for user " << uid;
- return false;
- }
- auto buf = RecordToNvBuffer(DefaultRecord(secure_user_id));
- if (!storage.Write(key, *buf)) {
- LOG(ERROR) << "Failed to write record for " << uid;
- return false;
- }
- }
- auto record_read = storage.Read(key);
- if (!record_read) {
- LOG(ERROR) << "Failed to read record for " << uid;
- return false;
- }
- auto record_decoded = NvBufferToRecord(*record_read);
- if (!record_decoded) {
- LOG(ERROR) << "Failed to deserialize record for " << uid;
- return false;
- }
- if (record_decoded->secure_user_id == secure_user_id) {
- *record = *record_decoded;
- return true;
- }
- LOG(DEBUG) << "User id mismatch for " << uid;
- auto buf = RecordToNvBuffer(DefaultRecord(secure_user_id));
- if (!storage.Write(key, *buf)) {
- LOG(ERROR) << "Failed to write record for " << uid;
- return false;
- }
- *record = DefaultRecord(secure_user_id);
- return true;
-}
-
-bool TpmGatekeeper::GetFailureRecord(
- uint32_t uid,
- gatekeeper::secure_id_t secure_user_id,
- gatekeeper::failure_record_t *record,
- bool secure) {
- GatekeeperStorage& storage = secure ? secure_storage_ : insecure_storage_;
- return GetFailureRecordImpl(storage, uid, secure_user_id, record);
-}
-
-static bool WriteFailureRecordImpl(
- GatekeeperStorage& storage,
- uint32_t uid,
- gatekeeper::failure_record_t* record) {
- Json::Value key{std::to_string(uid)}; // jsoncpp integer comparisons are janky
- if (!storage.HasKey(key)) {
- if (!storage.Allocate(key, sizeof(gatekeeper::failure_record_t))) {
- LOG(ERROR) << "Allocation failed for user " << uid;
- return false;
- }
- }
- auto buf = RecordToNvBuffer(*record);
- if (!storage.Write(key, *buf)) {
- LOG(ERROR) << "Failed to write record for " << uid;
- return false;
- }
- return true;
-}
-
-bool TpmGatekeeper::ClearFailureRecord(
- uint32_t uid, gatekeeper::secure_id_t secure_user_id, bool secure) {
- GatekeeperStorage& storage = secure ? secure_storage_ : insecure_storage_;
- gatekeeper::failure_record_t record = DefaultRecord(secure_user_id);
- return WriteFailureRecordImpl(storage, uid, &record);
-}
-
-bool TpmGatekeeper::WriteFailureRecord(
- uint32_t uid, gatekeeper::failure_record_t *record, bool secure) {
- GatekeeperStorage& storage = secure ? secure_storage_ : insecure_storage_;
- return WriteFailureRecordImpl(storage, uid, record);
-}
-
-bool TpmGatekeeper::IsHardwareBacked() const {
- return true;
-}
-
diff --git a/host/commands/secure_env/tpm_gatekeeper.h b/host/commands/secure_env/tpm_gatekeeper.h
deleted file mode 100644
index 021ab5873..000000000
--- a/host/commands/secure_env/tpm_gatekeeper.h
+++ /dev/null
@@ -1,83 +0,0 @@
-//
-// Copyright (C) 2020 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 "gatekeeper/gatekeeper.h"
-#include "tss2/tss2_esys.h"
-
-#include "host/commands/secure_env/gatekeeper_storage.h"
-#include "host/commands/secure_env/tpm_resource_manager.h"
-
-/**
- * See method descriptions for this class in
- * system/gatekeeper/include/gatekeeper/gatekeeper.h
- */
-class TpmGatekeeper : public gatekeeper::GateKeeper {
-public:
- TpmGatekeeper(
- TpmResourceManager& resource_manager,
- GatekeeperStorage& secure_storage,
- GatekeeperStorage& insecure_storage);
-
- bool GetAuthTokenKey(
- const uint8_t** auth_token_key, uint32_t* length) const override;
-
- void GetPasswordKey(const uint8_t** pasword_key, uint32_t* length) override;
-
- void ComputePasswordSignature(
- uint8_t* signature,
- uint32_t signature_length,
- const uint8_t* key,
- uint32_t key_length,
- const uint8_t* password,
- uint32_t password_length,
- gatekeeper::salt_t salt) const override;
-
- void GetRandom(void* random, uint32_t requested_size) const override;
-
- void ComputeSignature(
- uint8_t* signature,
- uint32_t signature_length,
- const uint8_t* key,
- uint32_t key_length,
- const uint8_t* message,
- uint32_t length) const override;
-
- uint64_t GetMillisecondsSinceBoot() const override;
-
- /**
- * Retrieves the failure record for user `uid`, assuming a user secret value
- * of `user_id`. If the secret value `user_id` is incorrect, the original
- * secret `user_id` value will be lost and cannot be recovered.
- */
- bool GetFailureRecord(
- uint32_t uid,
- gatekeeper::secure_id_t user_id,
- gatekeeper::failure_record_t *record,
- bool secure) override;
-
- bool ClearFailureRecord(
- uint32_t uid, gatekeeper::secure_id_t user_id, bool secure) override;
-
- bool WriteFailureRecord(
- uint32_t uid, gatekeeper::failure_record_t *record, bool secure) override;
-
- bool IsHardwareBacked() const override;
-private:
- TpmResourceManager& resource_manager_;
- GatekeeperStorage& secure_storage_;
- GatekeeperStorage& insecure_storage_;
-};
diff --git a/host/commands/secure_env/tpm_hmac.cpp b/host/commands/secure_env/tpm_hmac.cpp
deleted file mode 100644
index 80003d0fe..000000000
--- a/host/commands/secure_env/tpm_hmac.cpp
+++ /dev/null
@@ -1,155 +0,0 @@
-//
-// Copyright (C) 2020 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 "tpm_hmac.h"
-
-#include <android-base/logging.h>
-#include <tss2/tss2_rc.h>
-
-#include "host/commands/secure_env/tpm_resource_manager.h"
-
-/* For data large enough to fit in a single TPM2_HMAC call. */
-static UniqueEsysPtr<TPM2B_DIGEST> OneshotHmac(
- TpmResourceManager& resource_manager,
- ESYS_TR key_handle,
- TpmAuth auth,
- const uint8_t* data,
- size_t data_size) {
- if (data_size > TPM2_MAX_DIGEST_BUFFER) {
- LOG(ERROR) << "Logic error: OneshotSign called with data_size "
- << data_size << " (> " << TPM2_MAX_DIGEST_BUFFER << ")";
- return {};
- }
- TPM2B_MAX_BUFFER buffer;
- static_assert(sizeof(buffer.buffer) >= TPM2_MAX_DIGEST_BUFFER);
- buffer.size = data_size;
- memcpy(buffer.buffer, data, data_size);
- TPM2B_DIGEST* out_hmac = nullptr;
- auto rc = Esys_HMAC(
- resource_manager.Esys(),
- key_handle,
- auth.auth1(),
- auth.auth2(),
- auth.auth3(),
- &buffer,
- TPM2_ALG_NULL,
- &out_hmac);
- if (rc != TPM2_RC_SUCCESS) {
- LOG(ERROR) << "TPM2_HMAC failed: " << Tss2_RC_Decode(rc) << "(" << rc << ")";
- return {};
- }
- if (out_hmac == nullptr) {
- LOG(ERROR) << "out_hmac unset";
- return {};
- }
- return UniqueEsysPtr<TPM2B_DIGEST>(out_hmac);
-}
-
-/* For data too large to fit in a single TPM2_HMAC call. */
-static UniqueEsysPtr<TPM2B_DIGEST> SegmentedHmac(
- TpmResourceManager& resource_manager,
- ESYS_TR key_handle,
- TpmAuth key_auth,
- const uint8_t* data,
- size_t data_size) {
- // TODO(schuffelen): Pipeline commands where possible.
- TPM2B_AUTH sequence_auth;
- sequence_auth.size = sizeof(rand());
- *reinterpret_cast<decltype(rand())*>(sequence_auth.buffer) = rand();
- ESYS_TR sequence_handle;
- auto slot = resource_manager.ReserveSlot();
- if (!slot) {
- LOG(ERROR) << "No slots available";
- return {};
- }
- auto rc = Esys_HMAC_Start(
- resource_manager.Esys(),
- key_handle,
- key_auth.auth1(),
- key_auth.auth2(),
- key_auth.auth3(),
- &sequence_auth,
- TPM2_ALG_NULL,
- &sequence_handle);
- if (rc != TPM2_RC_SUCCESS) {
- LOG(ERROR) << "TPM2_HMAC_Start failed: " << Tss2_RC_Decode(rc)
- << "(" << rc << ")";
- return {};
- }
- slot->set(sequence_handle);
- rc = Esys_TR_SetAuth(
- resource_manager.Esys(), sequence_handle, &sequence_auth);
- if (rc != TPM2_RC_SUCCESS) {
- LOG(ERROR) << "Esys_TR_SetAuth failed: " << Tss2_RC_Decode(rc)
- << "(" << rc << ")";
- return {};
- }
- auto hashed = 0;
- TPM2B_MAX_BUFFER buffer;
- while (data_size - hashed > TPM2_MAX_DIGEST_BUFFER) {
- buffer.size = TPM2_MAX_DIGEST_BUFFER;
- memcpy(buffer.buffer, &data[hashed], TPM2_MAX_DIGEST_BUFFER);
- hashed += TPM2_MAX_DIGEST_BUFFER;
- rc = Esys_SequenceUpdate(
- resource_manager.Esys(),
- sequence_handle,
- ESYS_TR_PASSWORD,
- ESYS_TR_NONE,
- ESYS_TR_NONE,
- &buffer);
- if (rc != TPM2_RC_SUCCESS) {
- LOG(ERROR) << "Esys_SequenceUpdate failed: " << Tss2_RC_Decode(rc)
- << "(" << rc << ")";
- return {};
- }
- }
- buffer.size = data_size - hashed;
- memcpy(buffer.buffer, &data[hashed], buffer.size);
- TPM2B_DIGEST* out_hmac = nullptr;
- TPMT_TK_HASHCHECK* validation = nullptr;
- rc = Esys_SequenceComplete(
- resource_manager.Esys(),
- sequence_handle,
- ESYS_TR_PASSWORD,
- ESYS_TR_NONE,
- ESYS_TR_NONE,
- &buffer,
- TPM2_RH_OWNER,
- &out_hmac,
- &validation);
- if (rc != TPM2_RC_SUCCESS) {
- LOG(ERROR) << "Esys_SequenceComplete failed: " << Tss2_RC_Decode(rc)
- << "(" << rc << ")";
- return {};
- }
- // TPM2_SequenceComplete already flushes the sequence context on success.
- slot->set(ESYS_TR_NONE);
- if (out_hmac == nullptr) {
- LOG(ERROR) << "out_hmac was null";
- return {};
- }
- Esys_Free(validation);
- return UniqueEsysPtr<TPM2B_DIGEST>(out_hmac);
-}
-
-UniqueEsysPtr<TPM2B_DIGEST> TpmHmac(
- TpmResourceManager& resource_manager,
- ESYS_TR key_handle,
- TpmAuth auth,
- const uint8_t* data,
- size_t data_size) {
- auto fn = data_size > TPM2_MAX_DIGEST_BUFFER ? SegmentedHmac : OneshotHmac;
- return fn(resource_manager, key_handle, auth, data, data_size);
-}
diff --git a/host/commands/secure_env/tpm_hmac.h b/host/commands/secure_env/tpm_hmac.h
deleted file mode 100644
index e4686b662..000000000
--- a/host/commands/secure_env/tpm_hmac.h
+++ /dev/null
@@ -1,51 +0,0 @@
-//
-// Copyright (C) 2020 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 <memory>
-
-#include <tss2/tss2_esys.h>
-
-#include "host/commands/secure_env/tpm_auth.h"
-
-class TpmResourceManager;
-
-struct EsysDeleter {
- void operator()(void* data) { Esys_Free(data); }
-};
-
-template<typename T>
-using UniqueEsysPtr = std::unique_ptr<T, EsysDeleter>;
-
-/**
- * Returns a HMAC signature for `data` with the key loaded into the TPM at
- * `key_handle`.
- *
- * The signature is a byte string that certifies a process that can make TPM
- * API calls has signed off on using another byte string (`data`) for some
- * purpose, which is implicitly tied to the signing key. In this case, the
- * secure_env process is the only process that should have TPM access.
- * secure_env can then transmit some data together with a signature over that
- * data, an external system (Android) can hold onto this data and the signature,
- * and then the secure_env process can receive the data back. The signature
- * is used to check that the data has not been tampered with.
- */
-UniqueEsysPtr<TPM2B_DIGEST> TpmHmac(
- TpmResourceManager& resource_manager,
- ESYS_TR key_handle,
- TpmAuth auth,
- const uint8_t* data,
- size_t data_size);
diff --git a/host/commands/secure_env/tpm_key_blob_maker.cpp b/host/commands/secure_env/tpm_key_blob_maker.cpp
deleted file mode 100644
index 64f344a66..000000000
--- a/host/commands/secure_env/tpm_key_blob_maker.cpp
+++ /dev/null
@@ -1,192 +0,0 @@
-//
-// Copyright (C) 2020 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 "tpm_key_blob_maker.h"
-
-#include <vector>
-
-#include <android-base/logging.h>
-#include <tss2/tss2_mu.h>
-#include <tss2/tss2_rc.h>
-
-#include "host/commands/secure_env/composite_serialization.h"
-#include "host/commands/secure_env/encrypted_serializable.h"
-#include "host/commands/secure_env/hmac_serializable.h"
-#include "host/commands/secure_env/primary_key_builder.h"
-
-using keymaster::AuthorizationSet;
-using keymaster::KeymasterKeyBlob;
-using keymaster::Serializable;
-
-static constexpr char kUniqueKey[] = "TpmKeyBlobMaker";
-
-/**
- * Distinguish what properties the secure_env implementation handles. If
- * secure_env handles it, the property is put in `hw_enforced`. Otherwise, the
- * property is put in `sw_enforced`, and the Keystore process inside Android
- * will try to enforce the property.
- */
-static keymaster_error_t SplitEnforcedProperties(
- const keymaster::AuthorizationSet& key_description,
- keymaster::AuthorizationSet* hw_enforced,
- keymaster::AuthorizationSet* sw_enforced) {
- for (auto& entry : key_description) {
- switch (entry.tag) {
- case KM_TAG_PURPOSE:
- case KM_TAG_ALGORITHM:
- case KM_TAG_KEY_SIZE:
- case KM_TAG_RSA_PUBLIC_EXPONENT:
- case KM_TAG_BLOB_USAGE_REQUIREMENTS:
- case KM_TAG_DIGEST:
- case KM_TAG_PADDING:
- case KM_TAG_BLOCK_MODE:
- case KM_TAG_MIN_SECONDS_BETWEEN_OPS:
- case KM_TAG_MAX_USES_PER_BOOT:
- case KM_TAG_USER_SECURE_ID:
- case KM_TAG_NO_AUTH_REQUIRED:
- case KM_TAG_AUTH_TIMEOUT:
- case KM_TAG_CALLER_NONCE:
- case KM_TAG_MIN_MAC_LENGTH:
- case KM_TAG_KDF:
- case KM_TAG_EC_CURVE:
- case KM_TAG_ECIES_SINGLE_HASH_MODE:
- case KM_TAG_USER_AUTH_TYPE:
- case KM_TAG_ORIGIN:
- case KM_TAG_OS_VERSION:
- case KM_TAG_OS_PATCHLEVEL:
- case KM_TAG_EARLY_BOOT_ONLY:
- case KM_TAG_UNLOCKED_DEVICE_REQUIRED:
- hw_enforced->push_back(entry);
- break;
- default:
- sw_enforced->push_back(entry);
- }
- }
- return KM_ERROR_OK;
-}
-
-static KeymasterKeyBlob SerializableToKeyBlob(
- const Serializable& serializable) {
- std::vector<uint8_t> data(serializable.SerializedSize() + 1);
- uint8_t* buf = data.data();
- uint8_t* buf_end = buf + data.size();
- buf = serializable.Serialize(buf, buf_end);
- if (buf != (buf_end - 1)) {
- LOG(ERROR) << "Serialized size did not match up with actual usage.";
- return {};
- }
- return KeymasterKeyBlob(data.data(), buf - data.data());
-}
-
-
-TpmKeyBlobMaker::TpmKeyBlobMaker(TpmResourceManager& resource_manager)
- : resource_manager_(resource_manager) {
-}
-
-keymaster_error_t TpmKeyBlobMaker::CreateKeyBlob(
- const AuthorizationSet& key_description,
- keymaster_key_origin_t origin,
- const KeymasterKeyBlob& key_material,
- KeymasterKeyBlob* blob,
- AuthorizationSet* hw_enforced,
- AuthorizationSet* sw_enforced) const {
- std::set<keymaster_tag_t> protected_tags = {
- KM_TAG_ROOT_OF_TRUST,
- KM_TAG_ORIGIN,
- KM_TAG_OS_VERSION,
- KM_TAG_OS_PATCHLEVEL,
- };
- for (auto tag : protected_tags) {
- if (key_description.Contains(tag)) {
- LOG(ERROR) << "Invalid tag " << tag;
- return KM_ERROR_INVALID_TAG;
- }
- }
- auto rc =
- SplitEnforcedProperties(key_description, hw_enforced, sw_enforced);
- if (rc != KM_ERROR_OK) {
- return rc;
- }
- hw_enforced->push_back(keymaster::TAG_ORIGIN, origin);
-
- // TODO(schuffelen): Set the os level and patch level properly.
- hw_enforced->push_back(keymaster::TAG_OS_VERSION, os_version_);
- hw_enforced->push_back(keymaster::TAG_OS_PATCHLEVEL, os_patchlevel_);
-
- return UnvalidatedCreateKeyBlob(key_material, *hw_enforced, *sw_enforced,
- blob);
-}
-
-keymaster_error_t TpmKeyBlobMaker::UnvalidatedCreateKeyBlob(
- const KeymasterKeyBlob& key_material, const AuthorizationSet& hw_enforced,
- const AuthorizationSet& sw_enforced, KeymasterKeyBlob* blob) const {
- keymaster::Buffer key_material_buffer(
- key_material.key_material, key_material.key_material_size);
- AuthorizationSet hw_enforced_mutable = hw_enforced;
- AuthorizationSet sw_enforced_mutable = sw_enforced;
- CompositeSerializable sensitive_material(
- {&key_material_buffer, &hw_enforced_mutable, &sw_enforced_mutable});
- auto parent_key_fn = ParentKeyCreator(kUniqueKey);
- EncryptedSerializable encryption(
- resource_manager_, parent_key_fn, sensitive_material);
- auto signing_key_fn = SigningKeyCreator(kUniqueKey);
- HmacSerializable sign_check(
- resource_manager_, signing_key_fn, TPM2_SHA256_DIGEST_SIZE, &encryption);
- auto generated_blob = SerializableToKeyBlob(sign_check);
- LOG(VERBOSE) << "Keymaster key size: " << generated_blob.key_material_size;
- if (generated_blob.key_material_size != 0) {
- *blob = generated_blob;
- return KM_ERROR_OK;
- }
- LOG(ERROR) << "Failed to serialize key.";
- return KM_ERROR_UNKNOWN_ERROR;
-}
-
-keymaster_error_t TpmKeyBlobMaker::UnwrapKeyBlob(
- const keymaster_key_blob_t& blob,
- AuthorizationSet* hw_enforced,
- AuthorizationSet* sw_enforced,
- KeymasterKeyBlob* key_material) const {
- keymaster::Buffer key_material_buffer(blob.key_material_size);
- CompositeSerializable sensitive_material(
- {&key_material_buffer, hw_enforced, sw_enforced});
- auto parent_key_fn = ParentKeyCreator(kUniqueKey);
- EncryptedSerializable encryption(
- resource_manager_, parent_key_fn, sensitive_material);
- auto signing_key_fn = SigningKeyCreator(kUniqueKey);
- HmacSerializable sign_check(
- resource_manager_, signing_key_fn, TPM2_SHA256_DIGEST_SIZE, &encryption);
- auto buf = blob.key_material;
- auto buf_end = buf + blob.key_material_size;
- if (!sign_check.Deserialize(&buf, buf_end)) {
- LOG(ERROR) << "Failed to deserialize key.";
- return KM_ERROR_UNKNOWN_ERROR;
- }
- if (key_material_buffer.available_read() == 0) {
- LOG(ERROR) << "Key material was corrupted and the size was too large";
- return KM_ERROR_UNKNOWN_ERROR;
- }
- *key_material = KeymasterKeyBlob(
- key_material_buffer.peek_read(), key_material_buffer.available_read());
- return KM_ERROR_OK;
-}
-
-keymaster_error_t TpmKeyBlobMaker::SetSystemVersion(
- uint32_t os_version, uint32_t os_patchlevel) {
- // TODO(b/155697375): Only accept new values of these from the bootloader
- os_version_ = os_version;
- os_patchlevel_ = os_patchlevel;
- return KM_ERROR_OK;
-}
diff --git a/host/commands/secure_env/tpm_key_blob_maker.h b/host/commands/secure_env/tpm_key_blob_maker.h
deleted file mode 100644
index a0483b449..000000000
--- a/host/commands/secure_env/tpm_key_blob_maker.h
+++ /dev/null
@@ -1,70 +0,0 @@
-//
-// Copyright (C) 2020 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 <keymaster/soft_key_factory.h>
-
-#include "host/commands/secure_env/tpm_resource_manager.h"
-
-/**
- * Encrypts key data using a TPM-resident key and signs it with a TPM-resident
- * key for privacy and integrity.
- *
- * This class is used to encrypt KeyMint data when it leaves the secure_env
- * process, and is sent for storage to Android. When the data comes back, this
- * class decrypts it again for use in Keymaster and other HAL API calls.
- */
-class TpmKeyBlobMaker : public keymaster::SoftwareKeyBlobMaker {
-public:
- TpmKeyBlobMaker(TpmResourceManager& resource_manager);
-
- keymaster_error_t CreateKeyBlob(
- const keymaster::AuthorizationSet& key_description,
- keymaster_key_origin_t origin,
- const keymaster::KeymasterKeyBlob& key_material,
- keymaster::KeymasterKeyBlob* blob,
- keymaster::AuthorizationSet* hw_enforced,
- keymaster::AuthorizationSet* sw_enforced) const override;
-
- keymaster_error_t UnvalidatedCreateKeyBlob(
- const keymaster::KeymasterKeyBlob& key_material,
- const keymaster::AuthorizationSet& hw_enforced,
- const keymaster::AuthorizationSet& sw_enforced,
- keymaster::KeymasterKeyBlob* blob) const;
-
- /**
- * Intermediate function between KeymasterContext::ParseKeyBlob and
- * KeyFactory::LoadKey, The inputs of this function match the outputs of
- * KeymasterContext::ParseKeyBlob and the outputs of this function match the
- * inputs of KeyFactory::LoadKey.
- *
- * KeymasterContext::ParseKeyBlob is the common entry point for decoding all
- * keys, and is expected to delegate to a KeyFactory depending on the type of
- * the serialized key. This method performs decryption operations shared
- * between all TPM-Keymaster keys.
- */
- keymaster_error_t UnwrapKeyBlob(
- const keymaster_key_blob_t& blob,
- keymaster::AuthorizationSet* hw_enforced,
- keymaster::AuthorizationSet* sw_enforced,
- keymaster::KeymasterKeyBlob* key_material) const;
-
- keymaster_error_t SetSystemVersion(uint32_t os_version, uint32_t os_patchlevel);
-private:
- TpmResourceManager& resource_manager_;
- uint32_t os_version_;
- uint32_t os_patchlevel_;
-};
diff --git a/host/commands/secure_env/tpm_keymaster_context.cpp b/host/commands/secure_env/tpm_keymaster_context.cpp
deleted file mode 100644
index 850d48ba2..000000000
--- a/host/commands/secure_env/tpm_keymaster_context.cpp
+++ /dev/null
@@ -1,321 +0,0 @@
-//
-// Copyright (C) 2020 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 "tpm_keymaster_context.h"
-
-#include <android-base/logging.h>
-#include <keymaster/contexts/soft_attestation_cert.h>
-#include <keymaster/km_openssl/aes_key.h>
-#include <keymaster/km_openssl/asymmetric_key.h>
-#include <keymaster/km_openssl/attestation_utils.h>
-#include <keymaster/km_openssl/certificate_utils.h>
-#include <keymaster/km_openssl/ec_key_factory.h>
-#include <keymaster/km_openssl/hmac_key.h>
-#include <keymaster/km_openssl/rsa_key_factory.h>
-#include <keymaster/km_openssl/soft_keymaster_enforcement.h>
-#include <keymaster/km_openssl/triple_des_key.h>
-
-#include "host/commands/secure_env/tpm_attestation_record.h"
-#include "host/commands/secure_env/tpm_random_source.h"
-#include "host/commands/secure_env/tpm_key_blob_maker.h"
-
-using keymaster::AuthorizationSet;
-using keymaster::KeymasterKeyBlob;
-using keymaster::KeyFactory;
-using keymaster::OperationFactory;
-
-TpmKeymasterContext::TpmKeymasterContext(
- TpmResourceManager& resource_manager,
- keymaster::KeymasterEnforcement& enforcement)
- : resource_manager_(resource_manager)
- , enforcement_(enforcement)
- , key_blob_maker_(new TpmKeyBlobMaker(resource_manager_))
- , random_source_(new TpmRandomSource(resource_manager_.Esys()))
- , attestation_context_(new TpmAttestationRecordContext()) {
- key_factories_.emplace(
- KM_ALGORITHM_RSA, new keymaster::RsaKeyFactory(*key_blob_maker_, *this));
- key_factories_.emplace(
- KM_ALGORITHM_EC, new keymaster::EcKeyFactory(*key_blob_maker_, *this));
- key_factories_.emplace(
- KM_ALGORITHM_AES,
- new keymaster::AesKeyFactory(*key_blob_maker_, *random_source_));
- key_factories_.emplace(
- KM_ALGORITHM_TRIPLE_DES,
- new keymaster::TripleDesKeyFactory(*key_blob_maker_, *random_source_));
- key_factories_.emplace(
- KM_ALGORITHM_HMAC,
- new keymaster::HmacKeyFactory(*key_blob_maker_, *random_source_));
- for (const auto& it : key_factories_) {
- supported_algorithms_.push_back(it.first);
- }
-}
-
-keymaster_error_t TpmKeymasterContext::SetSystemVersion(
- uint32_t os_version, uint32_t os_patchlevel) {
- // TODO(b/155697375): Only accept new values of these from the bootloader
- os_version_ = os_version;
- os_patchlevel_ = os_patchlevel;
- key_blob_maker_->SetSystemVersion(os_version, os_patchlevel);
- return KM_ERROR_OK;
-}
-
-void TpmKeymasterContext::GetSystemVersion(
- uint32_t* os_version, uint32_t* os_patchlevel) const {
- *os_version = os_version_;
- *os_patchlevel = os_patchlevel_;
-}
-
-const KeyFactory* TpmKeymasterContext::GetKeyFactory(
- keymaster_algorithm_t algorithm) const {
- auto it = key_factories_.find(algorithm);
- if (it == key_factories_.end()) {
- LOG(ERROR) << "Could not find key factory for " << algorithm;
- return nullptr;
- }
- return it->second.get();
-}
-
-const OperationFactory* TpmKeymasterContext::GetOperationFactory(
- keymaster_algorithm_t algorithm, keymaster_purpose_t purpose) const {
- auto key_factory = GetKeyFactory(algorithm);
- if (key_factory == nullptr) {
- LOG(ERROR) << "Tried to get operation factory for " << purpose
- << " for invalid algorithm " << algorithm;
- return nullptr;
- }
- auto operation_factory = key_factory->GetOperationFactory(purpose);
- if (operation_factory == nullptr) {
- LOG(ERROR) << "Could not get operation factory for " << purpose
- << " from key factory for " << algorithm;
- }
- return operation_factory;
-}
-
-const keymaster_algorithm_t* TpmKeymasterContext::GetSupportedAlgorithms(
- size_t* algorithms_count) const {
- *algorithms_count = supported_algorithms_.size();
- return supported_algorithms_.data();
-}
-
-// Based on https://cs.android.com/android/platform/superproject/+/master:system/keymaster/key_blob_utils/software_keyblobs.cpp;l=44;drc=master
-
-static bool UpgradeIntegerTag(
- keymaster_tag_t tag,
- uint32_t value,
- AuthorizationSet* set,
- bool* set_changed) {
- int index = set->find(tag);
- if (index == -1) {
- keymaster_key_param_t param;
- param.tag = tag;
- param.integer = value;
- set->push_back(param);
- *set_changed = true;
- return true;
- }
-
- if (set->params[index].integer > value) {
- return false;
- }
-
- if (set->params[index].integer != value) {
- set->params[index].integer = value;
- *set_changed = true;
- }
- return true;
-}
-
-// Based on https://cs.android.com/android/platform/superproject/+/master:system/keymaster/key_blob_utils/software_keyblobs.cpp;l=310;drc=master
-
-keymaster_error_t TpmKeymasterContext::UpgradeKeyBlob(
- const KeymasterKeyBlob& blob_to_upgrade,
- const AuthorizationSet& upgrade_params,
- KeymasterKeyBlob* upgraded_key) const {
- keymaster::UniquePtr<keymaster::Key> key;
- auto error = ParseKeyBlob(blob_to_upgrade, upgrade_params, &key);
- if (error != KM_ERROR_OK) {
- LOG(ERROR) << "Failed to parse key blob";
- return error;
- }
-
- bool set_changed = false;
-
- if (os_version_ == 0) {
- // We need to allow "upgrading" OS version to zero, to support upgrading
- // from proper numbered releases to unnumbered development and preview
- // releases.
-
- int key_os_version_pos = key->hw_enforced().find(keymaster::TAG_OS_VERSION);
- if (key_os_version_pos != -1) {
- uint32_t key_os_version = key->hw_enforced()[key_os_version_pos].integer;
- if (key_os_version != 0) {
- key->hw_enforced()[key_os_version_pos].integer = os_version_;
- set_changed = true;
- }
- }
- }
-
- auto update_os = UpgradeIntegerTag(keymaster::TAG_OS_VERSION, os_version_,
- &key->hw_enforced(), &set_changed);
-
- auto update_patchlevel =
- UpgradeIntegerTag(keymaster::TAG_OS_PATCHLEVEL, os_patchlevel_,
- &key->hw_enforced(), &set_changed);
-
- if (!update_os || !update_patchlevel) {
- LOG(ERROR) << "One of the version fields would have been a downgrade. "
- << "Not allowed.";
- return KM_ERROR_INVALID_ARGUMENT;
- }
-
- if (!set_changed) {
- // Don't need an upgrade.
- return KM_ERROR_OK;
- }
-
- return key_blob_maker_->UnvalidatedCreateKeyBlob(
- key->key_material(), key->hw_enforced(), key->sw_enforced(),
- upgraded_key);
-}
-
-keymaster_error_t TpmKeymasterContext::ParseKeyBlob(
- const KeymasterKeyBlob& blob,
- const AuthorizationSet& additional_params,
- keymaster::UniquePtr<keymaster::Key>* key) const {
- keymaster::AuthorizationSet hw_enforced;
- keymaster::AuthorizationSet sw_enforced;
- keymaster::KeymasterKeyBlob key_material;
-
- auto rc =
- key_blob_maker_->UnwrapKeyBlob(
- blob,
- &hw_enforced,
- &sw_enforced,
- &key_material);
- if (rc != KM_ERROR_OK) {
- LOG(ERROR) << "Failed to unwrap key: " << rc;
- return rc;
- }
-
- keymaster_algorithm_t algorithm;
- if (!hw_enforced.GetTagValue(keymaster::TAG_ALGORITHM, &algorithm) &&
- !sw_enforced.GetTagValue(keymaster::TAG_ALGORITHM, &algorithm)) {
- LOG(ERROR) << "No TAG_ALGORITHM value in hw_enforced or sw_enforced.";
- return KM_ERROR_UNKNOWN_ERROR;
- }
-
- auto factory = GetKeyFactory(algorithm);
- if (factory == nullptr) {
- LOG(ERROR) << "Unable to find key factory for " << algorithm;
- return KM_ERROR_UNSUPPORTED_ALGORITHM;
- }
- rc =
- factory->LoadKey(
- std::move(key_material),
- additional_params,
- std::move(hw_enforced),
- std::move(sw_enforced),
- key);
- if (rc != KM_ERROR_OK) {
- LOG(ERROR) << "Unable to load unwrapped key: " << rc;
- }
- return rc;
-}
-
-keymaster_error_t TpmKeymasterContext::AddRngEntropy(
- const uint8_t* buffer, size_t size) const {
- return random_source_->AddRngEntropy(buffer, size);
-}
-
-keymaster::KeymasterEnforcement* TpmKeymasterContext::enforcement_policy() {
- return &enforcement_;
-}
-
-// Based on https://cs.android.com/android/platform/superproject/+/master:system/keymaster/contexts/pure_soft_keymaster_context.cpp;l=261;drc=8367d5351c4d417a11f49b12394b63a413faa02d
-
-keymaster::CertificateChain TpmKeymasterContext::GenerateAttestation(
- const keymaster::Key& key, const keymaster::AuthorizationSet& attest_params,
- keymaster::UniquePtr<keymaster::Key> /* attest_key */,
- const keymaster::KeymasterBlob& /* issuer_subject */,
- keymaster_error_t* error) const {
- LOG(INFO) << "TODO(b/155697200): Link attestation back to the TPM";
- keymaster_algorithm_t key_algorithm;
- if (!key.authorizations().GetTagValue(keymaster::TAG_ALGORITHM,
- &key_algorithm)) {
- *error = KM_ERROR_UNKNOWN_ERROR;
- return {};
- }
-
- if ((key_algorithm != KM_ALGORITHM_RSA && key_algorithm != KM_ALGORITHM_EC)) {
- *error = KM_ERROR_INCOMPATIBLE_ALGORITHM;
- return {};
- }
-
- // We have established that the given key has the correct algorithm, and
- // because this is the TpmKeymasterContext we can assume that the Key is an
- // AsymmetricKey. So we can downcast.
- const keymaster::AsymmetricKey& asymmetric_key =
- static_cast<const keymaster::AsymmetricKey&>(key);
-
- // DEVICE_UNIQUE_ATTESTATION is only allowed for strongbox devices. See
- // hardware/interfaces/security/keymint/aidl/android/hardware/security/keymint/Tag.aidl:845
- // at commit beefae4790ccd4f1ee75ea69603d4c9c2a45c0aa .
- // While the specification says to return ErrorCode::INVALID_ARGUMENT , the
- // relevant VTS test actually tests for ErrorCode::UNIMPLEMENTED . See
- // hardware/interfaces/keymaster/4.1/vts/functional/DeviceUniqueAttestationTest.cpp:203
- // at commit 36dcf1a404a9cf07ca5a2a6ad92371507194fe1b .
- if (attest_params.find(keymaster::TAG_DEVICE_UNIQUE_ATTESTATION) != -1) {
- *error = KM_ERROR_UNIMPLEMENTED;
- return {};
- }
-
- return keymaster::generate_attestation(asymmetric_key, attest_params,
- {} /* attest_key */,
- *attestation_context_, error);
-}
-
-keymaster::CertificateChain TpmKeymasterContext::GenerateSelfSignedCertificate(
- const keymaster::Key& key, const keymaster::AuthorizationSet& cert_params,
- bool fake_signature, keymaster_error_t* error) const {
- keymaster_algorithm_t key_algorithm;
- if (!key.authorizations().GetTagValue(keymaster::TAG_ALGORITHM, &key_algorithm)) {
- *error = KM_ERROR_UNKNOWN_ERROR;
- return {};
- }
-
- if ((key_algorithm != KM_ALGORITHM_RSA && key_algorithm != KM_ALGORITHM_EC)) {
- *error = KM_ERROR_INCOMPATIBLE_ALGORITHM;
- return {};
- }
-
- // We have established that the given key has the correct algorithm, and because this is the
- // SoftKeymasterContext we can assume that the Key is an AsymmetricKey. So we can downcast.
- const keymaster::AsymmetricKey& asymmetric_key =
- static_cast<const keymaster::AsymmetricKey&>(key);
-
- return generate_self_signed_cert(asymmetric_key, cert_params, fake_signature, error);
-}
-
-keymaster_error_t TpmKeymasterContext::UnwrapKey(
- const KeymasterKeyBlob&,
- const KeymasterKeyBlob&,
- const AuthorizationSet&,
- const KeymasterKeyBlob&,
- AuthorizationSet*,
- keymaster_key_format_t*,
- KeymasterKeyBlob*) const {
- LOG(ERROR) << "TODO(b/155697375): Implement UnwrapKey";
- return KM_ERROR_UNIMPLEMENTED;
-}
diff --git a/host/commands/secure_env/tpm_keymaster_context.h b/host/commands/secure_env/tpm_keymaster_context.h
deleted file mode 100644
index 54ba97398..000000000
--- a/host/commands/secure_env/tpm_keymaster_context.h
+++ /dev/null
@@ -1,105 +0,0 @@
-//
-// Copyright (C) 2020 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 <map>
-#include <vector>
-
-#include <keymaster/keymaster_context.h>
-#include <keymaster/km_openssl/attestation_record.h>
-
-#include "tpm_attestation_record.h"
-
-class TpmAttestationRecordContext;
-class TpmResourceManager;
-class TpmKeyBlobMaker;
-class TpmRandomSource;
-
-/**
- * Implementation of KeymasterContext that wraps its keys with a TPM.
- *
- * See the parent class for details:
- * https://cs.android.com/android/platform/superproject/+/master:system/keymaster/include/keymaster/keymaster_context.h;drc=821acb74d7febb886a9b7cefee4ee3df4cc8c556
- */
-class TpmKeymasterContext : public keymaster::KeymasterContext {
-private:
- TpmResourceManager& resource_manager_;
- keymaster::KeymasterEnforcement& enforcement_;
- std::unique_ptr<TpmKeyBlobMaker> key_blob_maker_;
- std::unique_ptr<TpmRandomSource> random_source_;
- std::unique_ptr<TpmAttestationRecordContext> attestation_context_;
- std::map<keymaster_algorithm_t, std::unique_ptr<keymaster::KeyFactory>> key_factories_;
- std::vector<keymaster_algorithm_t> supported_algorithms_;
- uint32_t os_version_;
- uint32_t os_patchlevel_;
-public:
- TpmKeymasterContext(TpmResourceManager&, keymaster::KeymasterEnforcement&);
- ~TpmKeymasterContext() = default;
-
- keymaster::KmVersion GetKmVersion() const override {
- return attestation_context_->GetKmVersion();
- }
-
- keymaster_error_t SetSystemVersion(
- uint32_t os_version, uint32_t os_patchlevel) override;
- void GetSystemVersion(
- uint32_t* os_version, uint32_t* os_patchlevel) const override;
-
- const keymaster::KeyFactory* GetKeyFactory(
- keymaster_algorithm_t algorithm) const override;
- const keymaster::OperationFactory* GetOperationFactory(
- keymaster_algorithm_t algorithm,
- keymaster_purpose_t purpose) const override;
- const keymaster_algorithm_t* GetSupportedAlgorithms(
- size_t* algorithms_count) const override;
-
- keymaster_error_t UpgradeKeyBlob(
- const keymaster::KeymasterKeyBlob& key_to_upgrade,
- const keymaster::AuthorizationSet& upgrade_params,
- keymaster::KeymasterKeyBlob* upgraded_key) const override;
-
- keymaster_error_t ParseKeyBlob(
- const keymaster::KeymasterKeyBlob& blob,
- const keymaster::AuthorizationSet& additional_params,
- keymaster::UniquePtr<keymaster::Key>* key) const override;
-
- keymaster_error_t AddRngEntropy(
- const uint8_t* buf, size_t length) const override;
-
- keymaster::KeymasterEnforcement* enforcement_policy() override;
-
- keymaster::CertificateChain GenerateAttestation(
- const keymaster::Key& key,
- const keymaster::AuthorizationSet& attest_params,
- keymaster::UniquePtr<keymaster::Key> attest_key,
- const keymaster::KeymasterBlob& issuer_subject,
- keymaster_error_t* error) const override;
-
- keymaster::CertificateChain GenerateSelfSignedCertificate(
- const keymaster::Key& key,
- const keymaster::AuthorizationSet& cert_params,
- bool fake_signature,
- keymaster_error_t* error) const override;
-
- keymaster_error_t UnwrapKey(
- const keymaster::KeymasterKeyBlob& wrapped_key_blob,
- const keymaster::KeymasterKeyBlob& wrapping_key_blob,
- const keymaster::AuthorizationSet& wrapping_key_params,
- const keymaster::KeymasterKeyBlob& masking_key,
- keymaster::AuthorizationSet* wrapped_key_params,
- keymaster_key_format_t* wrapped_key_format,
- keymaster::KeymasterKeyBlob* wrapped_key_material) const override;
-};
diff --git a/host/commands/secure_env/tpm_keymaster_enforcement.cpp b/host/commands/secure_env/tpm_keymaster_enforcement.cpp
deleted file mode 100644
index f5b890352..000000000
--- a/host/commands/secure_env/tpm_keymaster_enforcement.cpp
+++ /dev/null
@@ -1,334 +0,0 @@
-//
-// Copyright (C) 2020 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 "host/commands/secure_env/tpm_keymaster_enforcement.h"
-
-#include <android-base/logging.h>
-#if defined(__BIONIC__)
-#include <sys/endian.h> // for be64toh
-#endif
-
-#include "host/commands/secure_env/primary_key_builder.h"
-#include "host/commands/secure_env/tpm_hmac.h"
-#include "host/commands/secure_env/tpm_key_blob_maker.h"
-#include "host/commands/secure_env/tpm_random_source.h"
-
-using keymaster::km_id_t;
-using keymaster::HmacSharingParameters;
-using keymaster::HmacSharingParametersArray;
-using keymaster::KeymasterBlob;
-using keymaster::KeymasterEnforcement;
-using keymaster::VerifyAuthorizationRequest;
-using keymaster::VerifyAuthorizationResponse;
-namespace {
-inline bool operator==(const keymaster_blob_t& a, const keymaster_blob_t& b) {
- if (!a.data_length && !b.data_length) return true;
- if (!(a.data && b.data)) return a.data == b.data;
- return (a.data_length == b.data_length &&
- !memcmp(a.data, b.data, a.data_length));
-}
-
-bool operator==(const HmacSharingParameters& a,
- const HmacSharingParameters& b) {
- return a.seed == b.seed && !memcmp(a.nonce, b.nonce, sizeof(a.nonce));
-}
-} // namespace
-class CompareHmacSharingParams {
-public:
- bool operator()(
- const HmacSharingParameters& a, const HmacSharingParameters& b) const {
- if (a.seed.data_length != b.seed.data_length) {
- return a.seed.data_length < b.seed.data_length;
- }
- auto res = memcmp(a.seed.data, b.seed.data, a.seed.data_length);
- if (res != 0) {
- return res < 0;
- }
- static_assert(sizeof(a.nonce) == sizeof(b.nonce));
- return memcmp(a.nonce, b.nonce, sizeof(a.nonce)) < 0;
- }
-};
-
-namespace {
-
-uint64_t timespec_to_ms(const struct timespec& tp) {
- if (tp.tv_sec < 0) {
- return 0;
- }
- return static_cast<uint64_t>(tp.tv_sec) * 1000 +
- static_cast<uint64_t>(tp.tv_nsec) / 1000000;
-}
-
-uint64_t get_wall_clock_time_ms() {
- struct timespec tp;
- int err = clock_gettime(CLOCK_REALTIME, &tp);
- if (err) {
- return 0;
- }
- return timespec_to_ms(tp);
-}
-
-} // namespace
-
-TpmKeymasterEnforcement::TpmKeymasterEnforcement(
- TpmResourceManager& resource_manager, TpmGatekeeper& gatekeeper)
- : KeymasterEnforcement(64, 64),
- resource_manager_(resource_manager),
- gatekeeper_(gatekeeper) {
-}
-
-TpmKeymasterEnforcement::~TpmKeymasterEnforcement() {
-}
-
-bool TpmKeymasterEnforcement::activation_date_valid(
- uint64_t activation_date) const {
- return activation_date < get_wall_clock_time_ms();
-}
-
-bool TpmKeymasterEnforcement::expiration_date_passed(
- uint64_t expiration_date) const {
- return expiration_date > get_wall_clock_time_ms();
-}
-
-bool TpmKeymasterEnforcement::auth_token_timed_out(
- const hw_auth_token_t& token, uint32_t timeout) const {
- // timeout comes in seconds, token.timestamp comes in milliseconds
- uint64_t timeout_ms = 1000 * (uint64_t) timeout;
- return (be64toh(token.timestamp) + timeout_ms) < get_current_time_ms();
-}
-
-uint64_t TpmKeymasterEnforcement::get_current_time_ms() const {
- struct timespec tp;
- int err = clock_gettime(CLOCK_BOOTTIME, &tp);
- if (err) {
- return 0;
- }
- return timespec_to_ms(tp);
-}
-
-keymaster_security_level_t TpmKeymasterEnforcement::SecurityLevel() const {
- return KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT;
-}
-
-bool TpmKeymasterEnforcement::ValidateTokenSignature(
- const hw_auth_token_t& token) const {
- hw_auth_token_t comparison_token = token;
- memset(comparison_token.hmac, 0, sizeof(comparison_token.hmac));
-
- /*
- * Should match implementation in system/gatekeeper/gatekeeper.cpp
- * GateKeeper::MintAuthToken
- */
-
- const uint8_t *auth_token_key = nullptr;
- uint32_t auth_token_key_len = 0;
- if (!gatekeeper_.GetAuthTokenKey(&auth_token_key, &auth_token_key_len)) {
- LOG(WARNING) << "Unable to get gatekeeper auth token";
- return false;
- }
-
-
- constexpr uint32_t hashable_length = sizeof(token.version) +
- sizeof(token.challenge) +
- sizeof(token.user_id) +
- sizeof(token.authenticator_id) +
- sizeof(token.authenticator_type) +
- sizeof(token.timestamp);
-
- static_assert(
- offsetof(hw_auth_token_t, hmac) == hashable_length,
- "hw_auth_token_t does not appear to be packed");
-
-
- gatekeeper_.ComputeSignature(
- comparison_token.hmac,
- sizeof(comparison_token.hmac),
- auth_token_key,
- auth_token_key_len,
- reinterpret_cast<uint8_t*>(&comparison_token),
- hashable_length);
-
- static_assert(sizeof(token.hmac) == sizeof(comparison_token.hmac));
-
- return memcmp(token.hmac, comparison_token.hmac, sizeof(token.hmac)) == 0;
-}
-
-keymaster_error_t TpmKeymasterEnforcement::GetHmacSharingParameters(
- HmacSharingParameters* params) {
- if (!have_saved_params_) {
- saved_params_.seed = {};
- TpmRandomSource random_source{resource_manager_.Esys()};
- auto rc =
- random_source.GenerateRandom(
- saved_params_.nonce, sizeof(saved_params_.nonce));
- if (rc != KM_ERROR_OK) {
- LOG(ERROR) << "Failed to generate HmacSharingParameters nonce";
- return rc;
- }
- have_saved_params_ = true;
- }
- params->seed = saved_params_.seed;
- memcpy(params->nonce, saved_params_.nonce, sizeof(params->nonce));
- return KM_ERROR_OK;
-}
-
-keymaster_error_t TpmKeymasterEnforcement::ComputeSharedHmac(
- const HmacSharingParametersArray& hmac_array,
- KeymasterBlob* sharingCheck) {
- std::set<HmacSharingParameters, CompareHmacSharingParams> sorted_hmac_inputs;
- bool found_mine = false;
- for (int i = 0; i < hmac_array.num_params; i++) {
- HmacSharingParameters sharing_params;
- sharing_params.seed =
- keymaster::KeymasterBlob(hmac_array.params_array[i].seed);
- memcpy(
- sharing_params.nonce,
- hmac_array.params_array[i].nonce,
- sizeof(sharing_params.nonce));
- found_mine = found_mine || (sharing_params == saved_params_);
- sorted_hmac_inputs.emplace(std::move(sharing_params));
- }
-
- if (!found_mine) return KM_ERROR_INVALID_ARGUMENT;
-
- // unique data has a low maximum size, so combine the hmac parameters
- char unique_data[] = "\0\0\0\0\0\0\0\0\0\0";
- int unique_index = 0;
- for (const auto& hmac_sharing : sorted_hmac_inputs) {
- for (size_t j = 0; j < hmac_sharing.seed.data_length; j++) {
- unique_data[unique_index % sizeof(unique_data)] ^=
- hmac_sharing.seed.data[j];
- unique_index++;
- }
- for (auto nonce_byte : hmac_sharing.nonce) {
- unique_data[unique_index % sizeof(unique_data)] ^= nonce_byte;
- unique_index++;
- }
- }
-
-
- auto signing_key_builder = PrimaryKeyBuilder();
- signing_key_builder.SigningKey();
- signing_key_builder.UniqueData(std::string(unique_data, sizeof(unique_data)));
- auto signing_key = signing_key_builder.CreateKey(resource_manager_);
- if (!signing_key) {
- LOG(ERROR) << "Could not make signing key for key id";
- return KM_ERROR_UNKNOWN_ERROR;
- }
-
- static const uint8_t signing_input[] = "Keymaster HMAC Verification";
-
- auto hmac = TpmHmac(
- resource_manager_,
- signing_key->get(),
- TpmAuth(ESYS_TR_PASSWORD),
- signing_input,
- sizeof(signing_input));
-
- if (!hmac) {
- LOG(ERROR) << "Unable to complete signing check";
- return KM_ERROR_UNKNOWN_ERROR;
- }
-
- *sharingCheck = KeymasterBlob(hmac->buffer, hmac->size);
-
- return KM_ERROR_OK;
-}
-
-VerifyAuthorizationResponse TpmKeymasterEnforcement::VerifyAuthorization(
- const VerifyAuthorizationRequest& request) {
- struct VerificationData {
- uint64_t challenge;
- uint64_t timestamp;
- keymaster_security_level_t security_level;
- };
- VerifyAuthorizationResponse response(keymaster::kDefaultMessageVersion);
- response.error = KM_ERROR_UNKNOWN_ERROR;
- response.token.challenge = request.challenge;
- response.token.timestamp = get_current_time_ms();
- response.token.security_level = SecurityLevel();
-
- VerificationData verify_data {
- .challenge = response.token.challenge,
- .timestamp = response.token.timestamp,
- .security_level = response.token.security_level,
- };
-
- auto signing_key_builder = PrimaryKeyBuilder();
- signing_key_builder.SigningKey();
- signing_key_builder.UniqueData("verify_authorization");
- auto signing_key = signing_key_builder.CreateKey(resource_manager_);
- if (!signing_key) {
- LOG(ERROR) << "Could not make signing key for verifying authorization";
- return response;
- }
- auto hmac = TpmHmac(
- resource_manager_,
- signing_key->get(),
- TpmAuth(ESYS_TR_PASSWORD),
- reinterpret_cast<uint8_t*>(&verify_data),
- sizeof(verify_data));
-
- if (!hmac) {
- LOG(ERROR) << "Could not calculate verification hmac";
- return response;
- } else if (hmac->size == 0) {
- LOG(ERROR) << "hmac was too short";
- return response;
- }
- response.token.mac = KeymasterBlob(hmac->buffer, hmac->size);
- response.error = KM_ERROR_OK;
-
- return response;
-}
-
-bool TpmKeymasterEnforcement::CreateKeyId(
- const keymaster_key_blob_t& key_blob, km_id_t* keyid) const {
- keymaster::AuthorizationSet hw_enforced;
- keymaster::AuthorizationSet sw_enforced;
- keymaster::KeymasterKeyBlob key_material;
- auto rc =
- TpmKeyBlobMaker(resource_manager_)
- .UnwrapKeyBlob(key_blob, &hw_enforced, &sw_enforced, &key_material);
- if (rc != KM_ERROR_OK) {
- LOG(ERROR) << "Could not unwrap key: " << rc;
- return false;
- }
- auto signing_key_builder = PrimaryKeyBuilder();
- signing_key_builder.SigningKey();
- signing_key_builder.UniqueData("key_id");
- auto signing_key = signing_key_builder.CreateKey(resource_manager_);
- if (!signing_key) {
- LOG(ERROR) << "Could not make signing key for key id";
- return false;
- }
- auto hmac = TpmHmac(
- resource_manager_,
- signing_key->get(),
- TpmAuth(ESYS_TR_PASSWORD),
- key_material.key_material,
- key_material.key_material_size);
- if (!hmac) {
- LOG(ERROR) << "Failed to make a signature for a key id";
- return false;
- }
- if (hmac->size < sizeof(km_id_t)) {
- LOG(ERROR) << "hmac return size was less than " << sizeof(km_id_t)
- << ", got " << hmac->size;
- return false;
- }
- memcpy(keyid, hmac->buffer, sizeof(km_id_t));
- return true;
-}
diff --git a/host/commands/secure_env/tpm_keymaster_enforcement.h b/host/commands/secure_env/tpm_keymaster_enforcement.h
deleted file mode 100644
index 1d6a1e560..000000000
--- a/host/commands/secure_env/tpm_keymaster_enforcement.h
+++ /dev/null
@@ -1,61 +0,0 @@
-//
-// Copyright (C) 2020 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 <keymaster/keymaster_enforcement.h>
-
-#include "host/commands/secure_env/tpm_gatekeeper.h"
-#include "host/commands/secure_env/tpm_resource_manager.h"
-
-/**
- * Implementation of keymaster::KeymasterEnforcement that depends on having a
- * TPM available. See the definitions in
- * system/keymaster/include/keymaster/keymaster_enforcement.h
- */
-class TpmKeymasterEnforcement : public keymaster::KeymasterEnforcement {
-public:
- TpmKeymasterEnforcement(
- TpmResourceManager& resource_manager, TpmGatekeeper& gatekeeper);
- ~TpmKeymasterEnforcement();
-
- bool activation_date_valid(uint64_t activation_date) const override;
- bool expiration_date_passed(uint64_t expiration_date) const override;
- bool auth_token_timed_out(
- const hw_auth_token_t& token, uint32_t timeout) const override;
- uint64_t get_current_time_ms() const override;
-
- keymaster_security_level_t SecurityLevel() const override;
- bool ValidateTokenSignature(const hw_auth_token_t& token) const override;
-
- keymaster_error_t GetHmacSharingParameters(
- keymaster::HmacSharingParameters* params) override;
- keymaster_error_t ComputeSharedHmac(
- const keymaster::HmacSharingParametersArray& params_array,
- keymaster::KeymasterBlob* sharingCheck) override;
-
- keymaster::VerifyAuthorizationResponse VerifyAuthorization(
- const keymaster::VerifyAuthorizationRequest& request) override;
-
- bool CreateKeyId(
- const keymaster_key_blob_t& key_blob,
- keymaster::km_id_t* keyid) const override;
-
-private:
- TpmResourceManager& resource_manager_;
- TpmGatekeeper& gatekeeper_;
- bool have_saved_params_ = false;
- keymaster::HmacSharingParameters saved_params_;
-};
diff --git a/host/commands/secure_env/tpm_random_source.cpp b/host/commands/secure_env/tpm_random_source.cpp
deleted file mode 100644
index 8695e4af0..000000000
--- a/host/commands/secure_env/tpm_random_source.cpp
+++ /dev/null
@@ -1,99 +0,0 @@
-//
-// Copyright (C) 2020 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 "tpm_random_source.h"
-
-#include <android-base/logging.h>
-#include "tss2/tss2_esys.h"
-#include "tss2/tss2_rc.h"
-
-TpmRandomSource::TpmRandomSource(ESYS_CONTEXT* esys) : esys_(esys) {
-}
-
-keymaster_error_t TpmRandomSource::GenerateRandom(
- uint8_t* random, size_t requested_length) const {
- if (requested_length == 0) {
- return KM_ERROR_OK;
- }
- // TODO(b/158790549): Pipeline these calls.
- TPM2B_DIGEST* generated = nullptr;
- while (requested_length > sizeof(generated->buffer)) {
- auto rc = Esys_GetRandom(esys_, ESYS_TR_NONE, ESYS_TR_NONE,
- ESYS_TR_NONE, sizeof(generated->buffer),
- &generated);
- if (rc != TSS2_RC_SUCCESS) {
- LOG(ERROR) << "Esys_GetRandom failed with " << rc << " ("
- << Tss2_RC_Decode(rc) << ")";
- // TODO(b/158790404): Return a better error code.
- return KM_ERROR_UNKNOWN_ERROR;
- }
- memcpy(random, generated->buffer, sizeof(generated->buffer));
- random = (uint8_t*) random + sizeof(generated->buffer);
- requested_length -= sizeof(generated->buffer);
- Esys_Free(generated);
- }
- auto rc = Esys_GetRandom(esys_, ESYS_TR_NONE, ESYS_TR_NONE,
- ESYS_TR_NONE, requested_length, &generated);
- if (rc != TSS2_RC_SUCCESS) {
- LOG(ERROR) << "Esys_GetRandom failed with " << rc << " ("
- << Tss2_RC_Decode(rc) << ")";
- // TODO(b/158790404): Return a better error code.
- return KM_ERROR_UNKNOWN_ERROR;
- }
- memcpy(random, generated->buffer, requested_length);
- Esys_Free(generated);
- return KM_ERROR_OK;
-}
-
-// From TPM2_StirRandom specification.
-static int MAX_STIR_RANDOM_BUFFER_SIZE = 128;
-
-keymaster_error_t TpmRandomSource::AddRngEntropy(
- const uint8_t* buffer, size_t size) const {
- TPM2B_SENSITIVE_DATA in_data;
- while (size > MAX_STIR_RANDOM_BUFFER_SIZE) {
- memcpy(in_data.buffer, buffer, MAX_STIR_RANDOM_BUFFER_SIZE);
- in_data.size = MAX_STIR_RANDOM_BUFFER_SIZE;
- buffer += MAX_STIR_RANDOM_BUFFER_SIZE;
- size -= MAX_STIR_RANDOM_BUFFER_SIZE;
- auto rc = Esys_StirRandom(
- esys_,
- ESYS_TR_NONE,
- ESYS_TR_NONE,
- ESYS_TR_NONE,
- &in_data);
- if (rc != TSS2_RC_SUCCESS) {
- LOG(ERROR) << "Esys_StirRandom failed with " << rc << "("
- << Tss2_RC_Decode(rc) << ")";
- return KM_ERROR_UNKNOWN_ERROR;
- }
- }
- if (size == 0) {
- return KM_ERROR_OK;
- }
- memcpy(in_data.buffer, buffer, size);
- auto rc = Esys_StirRandom(
- esys_,
- ESYS_TR_NONE,
- ESYS_TR_NONE,
- ESYS_TR_NONE,
- &in_data);
- if (rc != TSS2_RC_SUCCESS) {
- LOG(ERROR) << "Esys_StirRandom failed with " << rc << "("
- << Tss2_RC_Decode(rc) << ")";
- return KM_ERROR_UNKNOWN_ERROR;
- }
- return KM_ERROR_OK;
-}
diff --git a/host/commands/secure_env/tpm_random_source.h b/host/commands/secure_env/tpm_random_source.h
deleted file mode 100644
index 2e7d8a18f..000000000
--- a/host/commands/secure_env/tpm_random_source.h
+++ /dev/null
@@ -1,38 +0,0 @@
-//
-// Copyright (C) 2020 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 <keymaster/random_source.h>
-
-struct ESYS_CONTEXT;
-
-/**
- * Secure random number generator, pulling data from a TPM.
- *
- * RandomSource is used by the OpenSSL HMAC key and AES key implementations.
- */
-class TpmRandomSource : public keymaster::RandomSource {
-public:
- TpmRandomSource(ESYS_CONTEXT* esys);
- virtual ~TpmRandomSource() = default;
-
- keymaster_error_t GenerateRandom(
- uint8_t* buffer, size_t length) const override;
-
- keymaster_error_t AddRngEntropy(const uint8_t*, size_t) const;
-private:
- ESYS_CONTEXT* esys_;
-};
diff --git a/host/commands/secure_env/tpm_resource_manager.cpp b/host/commands/secure_env/tpm_resource_manager.cpp
deleted file mode 100644
index 3651ec85d..000000000
--- a/host/commands/secure_env/tpm_resource_manager.cpp
+++ /dev/null
@@ -1,77 +0,0 @@
-//
-// Copyright (C) 2020 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 "tpm_resource_manager.h"
-
-#include <android-base/logging.h>
-#include <tss2/tss2_rc.h>
-
-TpmResourceManager::ObjectSlot::ObjectSlot(TpmResourceManager* resource_manager)
- : ObjectSlot(resource_manager, ESYS_TR_NONE) {
-}
-
-TpmResourceManager::ObjectSlot::ObjectSlot(TpmResourceManager* resource_manager,
- ESYS_TR resource)
- : resource_manager_(resource_manager), resource_(resource) {
- LOG(VERBOSE) << "Resource allocated";
-}
-
-TpmResourceManager::ObjectSlot::~ObjectSlot() {
- if (resource_ != ESYS_TR_NONE) {
- LOG(VERBOSE) << "Freeing resource";
- auto rc = Esys_FlushContext(resource_manager_->esys_, resource_);
- if (rc != TPM2_RC_SUCCESS) {
- LOG(ERROR) << "Esys_FlushContext failed: " << Tss2_RC_Decode(rc)
- << "(" << rc << ")";
- }
- } else {
- LOG(VERBOSE) << "Resource is NONE";
- }
- resource_manager_->used_slots_--;
-}
-
-ESYS_TR TpmResourceManager::ObjectSlot::get() {
- return resource_;
-}
-
-void TpmResourceManager::ObjectSlot::set(ESYS_TR resource) {
- resource_ = resource;
-}
-
-TpmResourceManager::TpmResourceManager(ESYS_CONTEXT* esys)
- : esys_(esys), maximum_object_slots_(3), used_slots_(0) {
- // TODO(b/158791154): Find maximum_object_slots dynamically using
- // TPM2_GetCapability. Now equal to MAX_LOADED_OBJECTS from TpmProfile.h.
-}
-
-TpmResourceManager::~TpmResourceManager() {
- if (used_slots_ > 0) {
- LOG(FATAL) << "Outstanding TpmResourceManager::ObjectSlot instances. "
- "These hold a dangling pointer to this instance.";
- }
-}
-
-ESYS_CONTEXT* TpmResourceManager::Esys() {
- return esys_;
-}
-
-TpmObjectSlot TpmResourceManager::ReserveSlot() {
- auto slot_num = used_slots_.fetch_add(1);
- if (slot_num >= maximum_object_slots_) {
- used_slots_--;
- return nullptr;
- }
- return TpmObjectSlot{new ObjectSlot(this)};
-}
diff --git a/host/commands/secure_env/tpm_resource_manager.h b/host/commands/secure_env/tpm_resource_manager.h
deleted file mode 100644
index e1ed83fc2..000000000
--- a/host/commands/secure_env/tpm_resource_manager.h
+++ /dev/null
@@ -1,62 +0,0 @@
-//
-// Copyright (C) 2020 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 <cstdint>
-#include <memory>
-#include <set>
-
-#include <tss2/tss2_esys.h>
-
-/**
- * Object slot manager for TPM memory. The TPM can only hold a fixed number of
- * objects at once. Some TPM operations are defined to consume slots either
- * temporarily or until the resource is explicitly unloaded.
- *
- * This implementation is intended for future extension, to track what objects
- * are resident if we run out of space, or implement optimizations like LRU
- * caching to avoid re-loading often-used resources.
- */
-class TpmResourceManager {
-public:
- class ObjectSlot {
- public:
- friend class TpmResourceManager;
-
- ~ObjectSlot();
-
- ESYS_TR get();
- void set(ESYS_TR resource);
- private:
- ObjectSlot(TpmResourceManager* resource_manager);
- ObjectSlot(TpmResourceManager* resource_manager, ESYS_TR resource);
-
- TpmResourceManager* resource_manager_;
- ESYS_TR resource_;
- };
-
- TpmResourceManager(ESYS_CONTEXT* esys);
- ~TpmResourceManager();
-
- ESYS_CONTEXT* Esys();
- std::shared_ptr<ObjectSlot> ReserveSlot();
-private:
- ESYS_CONTEXT* esys_;
- const std::uint32_t maximum_object_slots_;
- std::atomic<std::uint32_t> used_slots_;
-};
-
-using TpmObjectSlot = std::shared_ptr<TpmResourceManager::ObjectSlot>;
diff --git a/host/commands/secure_env/tpm_serialize.cpp b/host/commands/secure_env/tpm_serialize.cpp
deleted file mode 100644
index 1cf07ff1a..000000000
--- a/host/commands/secure_env/tpm_serialize.cpp
+++ /dev/null
@@ -1,84 +0,0 @@
-//
-// Copyright (C) 2020 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 "tpm_serialize.h"
-
-#include <cstring>
-
-#include <android-base/logging.h>
-#include "tss2/tss2_mu.h"
-#include "tss2/tss2_rc.h"
-
-template<typename T>
-int MarshalFn = 0; // Break code without an explicit specialization.
-
-template<typename T>
-int UnmarshalFn = 0; // Break code without an explicit specialization.
-
-template<>
-auto MarshalFn<TPM2B_PRIVATE> = Tss2_MU_TPM2B_PRIVATE_Marshal;
-
-template<>
-auto UnmarshalFn<TPM2B_PRIVATE> = Tss2_MU_TPM2B_PRIVATE_Unmarshal;
-
-template<>
-auto MarshalFn<TPM2B_PUBLIC> = Tss2_MU_TPM2B_PUBLIC_Marshal;
-
-template<>
-auto UnmarshalFn<TPM2B_PUBLIC> = Tss2_MU_TPM2B_PUBLIC_Unmarshal;
-
-template<typename T>
-TpmSerializable<T>::TpmSerializable(T* instance) : instance_(instance) {}
-
-template<typename T>
-size_t TpmSerializable<T>::SerializedSize() const {
- std::size_t size = 0;
- auto rc = MarshalFn<T>(instance_, nullptr, sizeof(T), &size);
- if (rc != TPM2_RC_SUCCESS) {
- LOG(ERROR) << "tss2 marshalling failed: " << Tss2_RC_Decode(rc)
- << "(" << rc << ")";
- return -1;
- }
- return size;
-}
-
-template<typename T>
-uint8_t* TpmSerializable<T>::Serialize(uint8_t* buf, const uint8_t* end) const {
- std::size_t offset = 0;
- auto rc = MarshalFn<T>(instance_, buf, end - buf, &offset);
- if (rc != TPM2_RC_SUCCESS) {
- LOG(ERROR) << "tss2 marshalling failed: " << Tss2_RC_Decode(rc)
- << "(" << rc << ")";
- return buf;
- }
- return buf + offset;
-}
-
-template<typename T>
-bool TpmSerializable<T>::Deserialize(
- const uint8_t** buf_ptr, const uint8_t* end) {
- std::size_t offset = 0;
- auto rc = UnmarshalFn<T>(*buf_ptr, end - *buf_ptr, &offset, instance_);
- if (rc != TPM2_RC_SUCCESS) {
- LOG(ERROR) << "tss2 unmarshalling failed: " << Tss2_RC_Decode(rc)
- << "(" << rc << ")";
- return false;
- }
- *buf_ptr += offset;
- return true;
-}
-
-template class TpmSerializable<TPM2B_PRIVATE>;
-template class TpmSerializable<TPM2B_PUBLIC>;
diff --git a/host/commands/secure_env/tpm_serialize.h b/host/commands/secure_env/tpm_serialize.h
deleted file mode 100644
index 17884a5c3..000000000
--- a/host/commands/secure_env/tpm_serialize.h
+++ /dev/null
@@ -1,52 +0,0 @@
-//
-// Copyright (C) 2020 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 <cstddef>
-
-#include "keymaster/serializable.h"
-#include "tss2/tss2_mu.h"
-#include "tss2/tss2_rc.h"
-#include "tss2/tss2_tpm2_types.h"
-
-#include <android-base/logging.h>
-
-/**
- * An implementation of a keymaster::Serializable type that refers to a TPM type
- * by an unmanaged pointer. When the TpmSerializable serializes or deserializes
- * data, it loads it from and saves it to the pointed at instance.
- *
- * The serialization format is the same as the one used in the command protocol
- * for TPM messages.
- *
- * This is a template class, specialized in the corresponding implementation
- * file for the TPM types necessary to serialize as part of larger Keymaster
- * serializable types.
- */
-template<typename Type>
-class TpmSerializable : public keymaster::Serializable {
-public:
- TpmSerializable(Type*);
-
- size_t SerializedSize() const override;
- uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const override;
- bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end) override;
-private:
- Type* instance_;
-};
-
-using SerializeTpmKeyPrivate = TpmSerializable<TPM2B_PRIVATE>;
-using SerializeTpmKeyPublic = TpmSerializable<TPM2B_PUBLIC>;
diff --git a/host/commands/stop_cvd/Android.bp b/host/commands/stop_cvd/Android.bp
index a670a2503..8c95d83e7 100644
--- a/host/commands/stop_cvd/Android.bp
+++ b/host/commands/stop_cvd/Android.bp
@@ -13,11 +13,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-cc_binary {
+cc_binary_host {
name: "stop_cvd",
srcs: [
"main.cc",
@@ -26,13 +22,13 @@ cc_binary {
"libbase",
"libcuttlefish_fs",
"libcuttlefish_utils",
- "libcuttlefish_allocd_utils",
- "libjsoncpp",
],
static_libs: [
"libcuttlefish_host_config",
"libcuttlefish_vm_manager",
+ "libjsoncpp",
"libgflags",
+ "libxml2",
],
- defaults: ["cuttlefish_host", "cuttlefish_libicuuc"],
+ defaults: ["cuttlefish_host_only", "cuttlefish_libicuuc"],
}
diff --git a/host/commands/stop_cvd/main.cc b/host/commands/stop_cvd/main.cc
index 9e4fdd47c..5736561d7 100644
--- a/host/commands/stop_cvd/main.cc
+++ b/host/commands/stop_cvd/main.cc
@@ -44,8 +44,6 @@
#include "common/libs/fs/shared_select.h"
#include "common/libs/utils/environment.h"
#include "host/commands/run_cvd/runner_defs.h"
-#include "host/libs/allocd/request.h"
-#include "host/libs/allocd/utils.h"
#include "host/libs/config/cuttlefish_config.h"
#include "host/libs/vm_manager/vm_manager.h"
@@ -53,12 +51,11 @@ DEFINE_int32(wait_for_launcher, 5,
"How many seconds to wait for the launcher to respond to the stop "
"command. A value of zero means wait indefinetly");
-namespace cuttlefish {
namespace {
std::set<std::string> FallbackPaths() {
std::set<std::string> paths;
- std::string parent_path = StringFromEnv("HOME", ".");
+ std::string parent_path = cvd::StringFromEnv("HOME", ".");
paths.insert(parent_path + "/cuttlefish_assembly");
paths.insert(parent_path + "/cuttlefish_assembly/*");
@@ -76,15 +73,13 @@ std::set<std::string> FallbackPaths() {
// Add files in the tombstone directory
paths.insert(instance_dir + "/tombstones/*");
// Add files in the internal directory
- paths.insert(instance_dir + "/" + std::string(kInternalDirName) + "/*");
- // Add files in the shared directory
- paths.insert(instance_dir + "/" + std::string(kSharedDirName) + "/*");
+ paths.insert(instance_dir + "/" + std::string(vsoc::kInternalDirName) + "/*");
}
return paths;
}
-std::set<std::string> PathsForInstance(const CuttlefishConfig& config,
- const CuttlefishConfig::InstanceSpecific instance) {
+std::set<std::string> PathsForInstance(const vsoc::CuttlefishConfig& config,
+ const vsoc::CuttlefishConfig::InstanceSpecific instance) {
return {
config.assembly_dir(),
config.assembly_dir() + "/*",
@@ -94,8 +89,6 @@ std::set<std::string> PathsForInstance(const CuttlefishConfig& config,
instance.PerInstancePath("tombstones/*"),
instance.instance_internal_dir(),
instance.PerInstanceInternalPath("*"),
- instance.PerInstancePath(kSharedDirName),
- instance.PerInstancePath(kSharedDirName) + "/*",
};
}
@@ -145,20 +138,20 @@ int FallBackStop(const std::set<std::string>& paths) {
return exit_code;
}
-bool CleanStopInstance(const CuttlefishConfig::InstanceSpecific& instance) {
+bool CleanStopInstance(const vsoc::CuttlefishConfig::InstanceSpecific& instance) {
auto monitor_path = instance.launcher_monitor_socket_path();
if (monitor_path.empty()) {
LOG(ERROR) << "No path to launcher monitor found";
return false;
}
- auto monitor_socket = SharedFD::SocketLocalClient(
- monitor_path.c_str(), false, SOCK_STREAM, FLAGS_wait_for_launcher);
+ auto monitor_socket = cvd::SharedFD::SocketLocalClient(monitor_path.c_str(),
+ false, SOCK_STREAM);
if (!monitor_socket->IsOpen()) {
LOG(ERROR) << "Unable to connect to launcher monitor at " << monitor_path
<< ": " << monitor_socket->StrError();
return false;
}
- auto request = LauncherAction::kStop;
+ auto request = cvd::LauncherAction::kStop;
auto bytes_sent = monitor_socket->Send(&request, sizeof(request), 0);
if (bytes_sent < 0) {
LOG(ERROR) << "Error sending launcher monitor the stop command: "
@@ -166,11 +159,11 @@ bool CleanStopInstance(const CuttlefishConfig::InstanceSpecific& instance) {
return false;
}
// Perform a select with a timeout to guard against launcher hanging
- SharedFDSet read_set;
+ cvd::SharedFDSet read_set;
read_set.Set(monitor_socket);
struct timeval timeout = {FLAGS_wait_for_launcher, 0};
- int selected = Select(&read_set, nullptr, nullptr,
- FLAGS_wait_for_launcher <= 0 ? nullptr : &timeout);
+ int selected = cvd::Select(&read_set, nullptr, nullptr,
+ FLAGS_wait_for_launcher <= 0 ? nullptr : &timeout);
if (selected < 0){
LOG(ERROR) << "Failed communication with the launcher monitor: "
<< strerror(errno);
@@ -180,14 +173,14 @@ bool CleanStopInstance(const CuttlefishConfig::InstanceSpecific& instance) {
LOG(ERROR) << "Timeout expired waiting for launcher monitor to respond";
return false;
}
- LauncherResponse response;
+ cvd::LauncherResponse response;
auto bytes_recv = monitor_socket->Recv(&response, sizeof(response), 0);
if (bytes_recv < 0) {
LOG(ERROR) << "Error receiving response from launcher monitor: "
<< monitor_socket->StrError();
return false;
}
- if (response != LauncherResponse::kSuccess) {
+ if (response != cvd::LauncherResponse::kSuccess) {
LOG(ERROR) << "Received '" << static_cast<char>(response)
<< "' response from launcher monitor";
return false;
@@ -196,8 +189,8 @@ bool CleanStopInstance(const CuttlefishConfig::InstanceSpecific& instance) {
return true;
}
-int StopInstance(const CuttlefishConfig& config,
- const CuttlefishConfig::InstanceSpecific& instance) {
+int StopInstance(const vsoc::CuttlefishConfig& config,
+ const vsoc::CuttlefishConfig::InstanceSpecific& instance) {
bool res = CleanStopInstance(instance);
if (!res) {
return FallBackStop(PathsForInstance(config, instance));
@@ -205,34 +198,13 @@ int StopInstance(const CuttlefishConfig& config,
return 0;
}
-/// Send a StopSession request to allocd
-void ReleaseAllocdResources(SharedFD allocd_sock, uint32_t session_id) {
- if (!allocd_sock->IsOpen() || session_id == -1) {
- return;
- }
- Json::Value config;
- Json::Value request_list;
- Json::Value req;
- req["request_type"] =
- ReqTyToStr(RequestType::StopSession);
- req["session_id"] = session_id;
- request_list.append(req);
- config["config_request"]["request_list"] = request_list;
- SendJsonMsg(allocd_sock, config);
- auto resp_opt = RecvJsonMsg(allocd_sock);
- if (!resp_opt.has_value()) {
- LOG(ERROR) << "Bad response from allocd";
- return;
- }
- auto resp = resp_opt.value();
- LOG(INFO) << "Stop Session operation: " << resp["config_status"];
-}
+} // anonymous namespace
-int StopCvdMain(int argc, char** argv) {
+int main(int argc, char** argv) {
::android::base::InitLogging(argv, android::base::StderrLogger);
google::ParseCommandLineFlags(&argc, &argv, true);
- auto config = CuttlefishConfig::Get();
+ auto config = vsoc::CuttlefishConfig::Get();
if (!config) {
LOG(ERROR) << "Failed to obtain config object";
return FallBackStop(FallbackPaths());
@@ -240,29 +212,8 @@ int StopCvdMain(int argc, char** argv) {
int ret = 0;
for (const auto& instance : config->Instances()) {
- auto session_id = instance.session_id();
- int exit_status = StopInstance(*config, instance);
- if (exit_status == 0 && instance.use_allocd()) {
- // only release session resources if the instance was stopped
- SharedFD allocd_sock =
- SharedFD::SocketLocalClient(kDefaultLocation, false, SOCK_STREAM);
- if (!allocd_sock->IsOpen()) {
- LOG(ERROR) << "Unable to connect to allocd on "
- << kDefaultLocation << ": "
- << allocd_sock->StrError();
- }
-
- ReleaseAllocdResources(allocd_sock, session_id);
- }
- ret |= exit_status;
+ ret |= StopInstance(*config, instance);
}
return ret;
}
-
-} // namespace
-} // namespace cuttlefish
-
-int main(int argc, char** argv) {
- return cuttlefish::StopCvdMain(argc, argv);
-}
diff --git a/host/commands/tapsetiff/Android.bp b/host/commands/tapsetiff/Android.bp
index 1d7dedb61..c86024126 100644
--- a/host/commands/tapsetiff/Android.bp
+++ b/host/commands/tapsetiff/Android.bp
@@ -13,10 +13,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
sh_binary_host {
name: "tapsetiff",
src: "tapsetiff.py",
diff --git a/host/commands/tapsetiff/tapsetiff.py b/host/commands/tapsetiff/tapsetiff.py
index 8a0999ef6..3e7c9e49f 100755
--- a/host/commands/tapsetiff/tapsetiff.py
+++ b/host/commands/tapsetiff/tapsetiff.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python3
+#!/usr/bin/python
# Copyright (C) 2020 The Android Open Source Project
#
@@ -26,5 +26,5 @@ IFF_VNET_HDR = 0x4000
tun_fd = int(sys.argv[1])
tap_name = sys.argv[2]
-ifr = struct.pack('16sH', tap_name.encode('utf-8'), IFF_TAP | IFF_NO_PI | IFF_VNET_HDR)
+ifr = struct.pack('16sH', tap_name, IFF_TAP | IFF_NO_PI | IFF_VNET_HDR)
fcntl.ioctl(tun_fd, TUNSETIFF, ifr)
diff --git a/host/commands/tombstone_receiver/Android.bp b/host/commands/tombstone_receiver/Android.bp
index 51830fc7d..9fed4e2a6 100644
--- a/host/commands/tombstone_receiver/Android.bp
+++ b/host/commands/tombstone_receiver/Android.bp
@@ -13,11 +13,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-cc_binary {
+cc_binary_host {
name: "tombstone_receiver",
srcs: [
"main.cpp",
@@ -25,13 +21,13 @@ cc_binary {
shared_libs: [
"libbase",
"libcuttlefish_fs",
- "libjsoncpp",
"liblog",
"libcuttlefish_utils",
],
static_libs: [
"libcuttlefish_host_config",
+ "libjsoncpp",
"libgflags",
],
- defaults: ["cuttlefish_host"],
+ defaults: ["cuttlefish_host_only"],
}
diff --git a/host/commands/tombstone_receiver/main.cpp b/host/commands/tombstone_receiver/main.cpp
index 2e0ea699c..a84761e71 100644
--- a/host/commands/tombstone_receiver/main.cpp
+++ b/host/commands/tombstone_receiver/main.cpp
@@ -50,26 +50,26 @@ static std::string next_tombstone_path() {
num_tombstones_in_last_second = 0;
}
- LOG(DEBUG) << "Creating " << retval;
+ LOG(INFO) << "Creating " << retval;
return retval;
}
#define CHUNK_RECV_MAX_LEN (1024)
int main(int argc, char** argv) {
- cuttlefish::DefaultSubprocessLogging(argv);
+ cvd::DefaultSubprocessLogging(argv);
google::ParseCommandLineFlags(&argc, &argv, true);
- cuttlefish::SharedFD server_fd = cuttlefish::SharedFD::Dup(FLAGS_server_fd);
+ cvd::SharedFD server_fd = cvd::SharedFD::Dup(FLAGS_server_fd);
close(FLAGS_server_fd);
CHECK(server_fd->IsOpen()) << "Error inheriting tombstone server: "
<< server_fd->StrError();
- LOG(DEBUG) << "Host is starting server on port "
- << server_fd->VsockServerPort();
+ LOG(INFO) << "Host is starting server on port "
+ << server_fd->VsockServerPort();
// Server loop
while (true) {
- auto conn = cuttlefish::SharedFD::Accept(*server_fd);
+ auto conn = cvd::SharedFD::Accept(*server_fd);
std::ofstream file(next_tombstone_path(),
std::ofstream::out | std::ofstream::binary);
diff --git a/host/example_custom_actions/Android.bp b/host/example_custom_actions/Android.bp
deleted file mode 100644
index 36161f631..000000000
--- a/host/example_custom_actions/Android.bp
+++ /dev/null
@@ -1,28 +0,0 @@
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-cc_binary_host {
- name: "cuttlefish_example_action_server",
- srcs: ["main.cpp"],
- defaults: [
- "cuttlefish_buildhost_only",
- ],
- shared_libs: [
- "libbase",
- "liblog",
- "libutils",
- "libjsoncpp",
- "libcuttlefish_fs",
- "libcuttlefish_utils",
- ],
- static_libs: [
- "libcuttlefish_host_config",
- ],
-}
-
-prebuilt_etc_host {
- name: "cuttlefish_example_action_config.json",
- src: "custom_action_config.json",
- sub_dir: "cvd_custom_action_config",
-}
diff --git a/host/example_custom_actions/README.md b/host/example_custom_actions/README.md
deleted file mode 100644
index de3764da7..000000000
--- a/host/example_custom_actions/README.md
+++ /dev/null
@@ -1,12 +0,0 @@
-To try out the custom action config and action server in this path, set the
-following build vars:
-
-```
-SOONG_CONFIG_NAMESPACES += cvd
-SOONG_CONFIG_cvd += custom_action_config custom_action_servers
-
-SOONG_CONFIG_cvd_custom_action_config := cuttlefish_example_action_config.json
-SOONG_CONFIG_cvd_custom_action_servers += cuttlefish_example_action_server
-```
-
-See `device/google/cuttlefish/build/README.md` for more information.
diff --git a/host/example_custom_actions/custom_action_config.json b/host/example_custom_actions/custom_action_config.json
deleted file mode 100644
index 56dae0d4a..000000000
--- a/host/example_custom_actions/custom_action_config.json
+++ /dev/null
@@ -1,25 +0,0 @@
-[
- {
- "shell_command":"am start -a android.intent.action.VIEW -d https://www.android.com/",
- "button":{
- "command":"web",
- "title":"Web Page",
- "icon_name":"language"
- }
- },
- {
- "server":"cuttlefish_example_action_server",
- "buttons":[
- {
- "command":"settings",
- "title":"Quick Settings",
- "icon_name":"settings"
- },
- {
- "command":"alert",
- "title":"Do Not Disturb",
- "icon_name":"notifications_paused"
- }
- ]
- }
-]
diff --git a/host/example_custom_actions/main.cpp b/host/example_custom_actions/main.cpp
deleted file mode 100644
index c6d3b3c59..000000000
--- a/host/example_custom_actions/main.cpp
+++ /dev/null
@@ -1,78 +0,0 @@
-#include <android-base/logging.h>
-#include <android-base/strings.h>
-#include <sys/socket.h>
-
-#include "common/libs/fs/shared_buf.h"
-#include "common/libs/fs/shared_fd.h"
-#include "host/libs/config/cuttlefish_config.h"
-
-// Messages are always 128 bytes.
-#define MESSAGE_SIZE 128
-
-using cuttlefish::SharedFD;
-
-int main(int argc, char** argv) {
- if (argc <= 1) {
- return 1;
- }
-
- // Connect to WebRTC
- int fd = std::atoi(argv[1]);
- LOG(INFO) << "Connecting to WebRTC server...";
- SharedFD webrtc_socket = SharedFD::Dup(fd);
- close(fd);
- if (webrtc_socket->IsOpen()) {
- LOG(INFO) << "Connected";
- } else {
- LOG(ERROR) << "Could not connect, exiting...";
- return 1;
- }
-
- // Track state for our two commands.
- bool statusbar_expanded = false;
- bool dnd_on = false;
-
- char buf[MESSAGE_SIZE];
- while (1) {
- // Read the command message from the socket.
- if (!webrtc_socket->IsOpen()) {
- LOG(WARNING) << "WebRTC was closed.";
- break;
- }
- if (cuttlefish::ReadExact(webrtc_socket, buf, MESSAGE_SIZE) !=
- MESSAGE_SIZE) {
- LOG(WARNING) << "Failed to read the correct number of bytes.";
- break;
- }
- auto split = android::base::Split(buf, ":");
- std::string command = split[0];
- std::string state = split[1];
-
- // Ignore button-release events, when state != down.
- if (state != "down") {
- continue;
- }
-
- // Demonstrate two commands. For demonstration purposes these two
- // commands use adb shell, but commands can execute any action you choose.
- std::string adb_shell_command =
- cuttlefish::HostBinaryPath("adb");
- if (command == "settings") {
- adb_shell_command += " shell cmd statusbar ";
- adb_shell_command += statusbar_expanded ? "collapse" : "expand-settings";
- statusbar_expanded = !statusbar_expanded;
- } else if (command == "alert") {
- adb_shell_command += " shell cmd notification set_dnd ";
- adb_shell_command += dnd_on ? "off" : "on";
- dnd_on = !dnd_on;
- } else {
- LOG(WARNING) << "Unexpected command: " << buf;
- }
-
- if (!adb_shell_command.empty()) {
- if (system(adb_shell_command.c_str()) != 0) {
- LOG(ERROR) << "Failed to run command: " << adb_shell_command;
- }
- }
- }
-}
diff --git a/host/frontend/Android.bp b/host/frontend/Android.bp
new file mode 100644
index 000000000..19d7f9b08
--- /dev/null
+++ b/host/frontend/Android.bp
@@ -0,0 +1,20 @@
+//
+// 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.
+
+subdirs = [
+ "gcastv2",
+ "vnc_server",
+ "adb_connector",
+]
diff --git a/host/frontend/adb_connector/Android.bp b/host/frontend/adb_connector/Android.bp
index d0927afd6..a2cf3c62f 100644
--- a/host/frontend/adb_connector/Android.bp
+++ b/host/frontend/adb_connector/Android.bp
@@ -13,11 +13,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-cc_binary {
+cc_binary_host {
name: "adb_connector",
srcs: [
"adb_connection_maintainer.cpp",
@@ -34,5 +30,5 @@ cc_binary {
"libcuttlefish_utils",
"liblog",
],
- defaults: ["cuttlefish_host"],
+ defaults: ["cuttlefish_host_only"],
}
diff --git a/host/frontend/adb_connector/adb_connection_maintainer.cpp b/host/frontend/adb_connector/adb_connection_maintainer.cpp
index 5f9ff1d73..625071b50 100644
--- a/host/frontend/adb_connector/adb_connection_maintainer.cpp
+++ b/host/frontend/adb_connector/adb_connection_maintainer.cpp
@@ -49,11 +49,11 @@ std::string MakeConnectMessage(const std::string& address) {
}
std::string MakeDisconnectMessage(const std::string& address) {
- return MakeMessage("host:disconnect:" + address);
+ return MakeMessage("host:connect:" + address);
}
// returns true if successfully sent the whole message
-bool SendAll(cuttlefish::SharedFD sock, const std::string& msg) {
+bool SendAll(cvd::SharedFD sock, const std::string& msg) {
ssize_t total_written{};
while (total_written < static_cast<ssize_t>(msg.size())) {
if (!sock->IsOpen()) {
@@ -69,7 +69,7 @@ bool SendAll(cuttlefish::SharedFD sock, const std::string& msg) {
return true;
}
-std::string RecvAll(cuttlefish::SharedFD sock, const size_t count) {
+std::string RecvAll(cvd::SharedFD sock, const size_t count) {
size_t total_read{};
std::unique_ptr<char[]> data(new char[count]);
while (total_read < count) {
@@ -93,7 +93,7 @@ constexpr std::size_t kAdbMessageLengthLength = 4;
constexpr int kAdbDaemonPort = 5037;
-bool AdbSendMessage(cuttlefish::SharedFD sock, const std::string& message) {
+bool AdbSendMessage(cvd::SharedFD sock, const std::string& message) {
if (!sock->IsOpen()) {
return false;
}
@@ -105,7 +105,7 @@ bool AdbSendMessage(cuttlefish::SharedFD sock, const std::string& message) {
}
bool AdbSendMessage(const std::string& message) {
- auto sock = cuttlefish::SharedFD::SocketLocalClient(kAdbDaemonPort, SOCK_STREAM);
+ auto sock = cvd::SharedFD::SocketLocalClient(kAdbDaemonPort, SOCK_STREAM);
return AdbSendMessage(sock, message);
}
@@ -123,7 +123,7 @@ bool IsInteger(const std::string& str) {
}
// assumes the OKAY/FAIL status has already been read
-std::string RecvAdbResponse(cuttlefish::SharedFD sock) {
+std::string RecvAdbResponse(cvd::SharedFD sock) {
auto length_as_hex_str = RecvAll(sock, kAdbMessageLengthLength);
if (!IsInteger(length_as_hex_str)) {
return {};
@@ -134,13 +134,13 @@ std::string RecvAdbResponse(cuttlefish::SharedFD sock) {
// Returns a negative value if uptime result couldn't be read for
// any reason.
-int RecvUptimeResult(cuttlefish::SharedFD sock) {
+int RecvUptimeResult(cvd::SharedFD sock) {
std::vector<char> uptime_vec{};
std::vector<char> just_read(16);
do {
auto count = sock->Read(just_read.data(), just_read.size());
if (count < 0) {
- LOG(WARNING) << "couldn't receive adb shell output";
+ LOG(INFO) << "couldn't receive adb shell output";
return -1;
}
just_read.resize(count);
@@ -148,7 +148,7 @@ int RecvUptimeResult(cuttlefish::SharedFD sock) {
} while (!just_read.empty());
if (uptime_vec.empty()) {
- LOG(WARNING) << "empty adb shell result";
+ LOG(INFO) << "empty adb shell result";
return -1;
}
@@ -156,7 +156,7 @@ int RecvUptimeResult(cuttlefish::SharedFD sock) {
auto uptime_str = std::string{uptime_vec.data(), uptime_vec.size()};
if (!IsInteger(uptime_str)) {
- LOG(WARNING) << "non-numeric: uptime result: " << uptime_str;
+ LOG(INFO) << "non-numeric: uptime result: " << uptime_str;
return -1;
}
@@ -169,46 +169,46 @@ int RecvUptimeResult(cuttlefish::SharedFD sock) {
static constexpr int kAdbCommandGapTime = 5;
void EstablishConnection(const std::string& address) {
- LOG(DEBUG) << "Attempting to connect to device with address " << address;
+ LOG(INFO) << "Attempting to connect to device with address " << address;
while (!AdbConnect(address)) {
sleep(kAdbCommandGapTime);
}
- LOG(DEBUG) << "adb connect message for " << address << " successfully sent";
+ LOG(INFO) << "adb connect message for " << address << " successfully sent";
sleep(kAdbCommandGapTime);
}
void WaitForAdbDisconnection(const std::string& address) {
// adb daemon doesn't seem to handle quick, successive messages well. The
// sleeps stabilize the communication.
- LOG(DEBUG) << "Watching for disconnect on " << address;
+ LOG(INFO) << "Watching for disconnect on " << address;
while (true) {
- auto sock = cuttlefish::SharedFD::SocketLocalClient(kAdbDaemonPort, SOCK_STREAM);
+ auto sock = cvd::SharedFD::SocketLocalClient(kAdbDaemonPort, SOCK_STREAM);
if (!AdbSendMessage(sock, MakeTransportMessage(address))) {
- LOG(WARNING) << "transport message failed, response body: "
- << RecvAdbResponse(sock);
+ LOG(INFO) << "transport message failed, response body: "
+ << RecvAdbResponse(sock);
break;
}
if (!AdbSendMessage(sock, MakeShellUptimeMessage())) {
- LOG(WARNING) << "adb shell uptime message failed";
+ LOG(INFO) << "adb shell uptime message failed";
break;
}
auto uptime = RecvUptimeResult(sock);
if (uptime < 0) {
- LOG(WARNING) << "couldn't read uptime result";
+ LOG(INFO) << "couldn't read uptime result";
break;
}
- LOG(VERBOSE) << "device on " << address << " uptime " << uptime;
+ LOG(DEBUG) << "device on " << address << " uptime " << uptime;
sleep(kAdbCommandGapTime);
}
- LOG(DEBUG) << "Sending adb disconnect";
+ LOG(INFO) << "Sending adb disconnect";
AdbDisconnect(address);
sleep(kAdbCommandGapTime);
}
} // namespace
-[[noreturn]] void cuttlefish::EstablishAndMaintainConnection(std::string address) {
+[[noreturn]] void cvd::EstablishAndMaintainConnection(std::string address) {
while (true) {
EstablishConnection(address);
WaitForAdbDisconnection(address);
diff --git a/host/frontend/adb_connector/adb_connection_maintainer.h b/host/frontend/adb_connector/adb_connection_maintainer.h
index 23a7b4420..ca5584fe0 100644
--- a/host/frontend/adb_connector/adb_connection_maintainer.h
+++ b/host/frontend/adb_connector/adb_connection_maintainer.h
@@ -15,8 +15,8 @@
*/
#pragma once
-namespace cuttlefish {
+namespace cvd {
[[noreturn]] void EstablishAndMaintainConnection(std::string address);
-} // namespace cuttlefish
+} // namespace cvd
diff --git a/host/frontend/adb_connector/main.cpp b/host/frontend/adb_connector/main.cpp
index aaca8cf0b..2e27d3e56 100644
--- a/host/frontend/adb_connector/main.cpp
+++ b/host/frontend/adb_connector/main.cpp
@@ -26,7 +26,6 @@
#include <unistd.h>
#include <host/commands/kernel_log_monitor/kernel_log_server.h>
-#include <host/commands/kernel_log_monitor/utils.h>
#include "common/libs/fs/shared_fd.h"
#include "host/frontend/adb_connector/adb_connection_maintainer.h"
@@ -35,10 +34,13 @@
DEFINE_string(addresses, "", "Comma-separated list of addresses to "
"'adb connect' to");
+DEFINE_int32(adbd_events_fd, -1, "A file descriptor. If set it will wait for "
+ "AdbdStarted boot event from the kernel log "
+ "monitor before trying to connect adb");
namespace {
void LaunchConnectionMaintainerThread(const std::string& address) {
- std::thread(cuttlefish::EstablishAndMaintainConnection, address).detach();
+ std::thread(cvd::EstablishAndMaintainConnection, address).detach();
}
std::vector<std::string> ParseAddressList(std::string ports) {
@@ -54,13 +56,36 @@ std::vector<std::string> ParseAddressList(std::string ports) {
}
}
+void WaitForAdbdToBeStarted(int events_fd) {
+ auto evt_shared_fd = cvd::SharedFD::Dup(events_fd);
+ close(events_fd);
+ while (evt_shared_fd->IsOpen()) {
+ monitor::BootEvent event;
+ auto bytes_read = evt_shared_fd->Read(&event, sizeof(event));
+ if (bytes_read != sizeof(event)) {
+ LOG(ERROR) << "Fail to read a complete event, read " << bytes_read
+ << " bytes only instead of the expected " << sizeof(event);
+ // The file descriptor can't be trusted anymore, stop waiting and try to
+ // connect
+ return;
+ }
+ if (event == monitor::BootEvent::AdbdStarted) {
+ LOG(INFO) << "Adbd has started in the guest, connecting adb";
+ return;
+ }
+ }
+}
} // namespace
int main(int argc, char* argv[]) {
- cuttlefish::DefaultSubprocessLogging(argv);
+ cvd::DefaultSubprocessLogging(argv);
gflags::ParseCommandLineFlags(&argc, &argv, true);
CHECK(!FLAGS_addresses.empty()) << "Must specify --addresses flag";
+ if (FLAGS_adbd_events_fd >= 0) {
+ WaitForAdbdToBeStarted(FLAGS_adbd_events_fd);
+ }
+
for (auto address : ParseAddressList(FLAGS_addresses)) {
LaunchConnectionMaintainerThread(address);
}
diff --git a/host/libs/websocket/Android.bp b/host/frontend/gcastv2/https/Android.bp
index 2a4a5227f..4078e80f8 100644
--- a/host/libs/websocket/Android.bp
+++ b/host/frontend/gcastv2/https/Android.bp
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2020 The Android Open Source Project
+// 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.
@@ -13,25 +13,31 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-cc_library_host_static {
- name: "libcuttlefish_host_websocket",
+cc_library_static {
+ name: "libhttps",
+ host_supported: true,
srcs: [
- "websocket_handler.cpp",
- "websocket_server.cpp",
+ "BaseConnection.cpp",
+ "BufferedSocket.cpp",
+ "ClientSocket.cpp",
+ "HTTPClientConnection.cpp",
+ "HTTPRequestResponse.cpp",
+ "HTTPServer.cpp",
+ "PlainSocket.cpp",
+ "SSLSocket.cpp",
+ "ServerSocket.cpp",
+ "WebSocketHandler.cpp",
+ "RunLoop.cpp",
+ "Support.cpp",
],
+ defaults: ["cuttlefish_host_only"],
shared_libs: [
"libbase",
- "liblog",
- "libssl",
"libcrypto",
+ "libssl",
+ "liblog",
],
- static_libs: [
- "libcap",
- "libwebsockets",
- ],
- defaults: ["cuttlefish_buildhost_only"],
+ local_include_dirs: ["include"],
+ export_include_dirs: ["include"],
}
+
diff --git a/host/frontend/gcastv2/https/BaseConnection.cpp b/host/frontend/gcastv2/https/BaseConnection.cpp
new file mode 100644
index 000000000..4041b9725
--- /dev/null
+++ b/host/frontend/gcastv2/https/BaseConnection.cpp
@@ -0,0 +1,122 @@
+/*
+ * 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.
+ */
+
+#include <https/BaseConnection.h>
+
+#include <https/SafeCallbackable.h>
+#include <https/PlainSocket.h>
+
+BaseConnection::BaseConnection(std::shared_ptr<RunLoop> runLoop, int sock)
+ : mRunLoop(runLoop),
+ mSocket(std::make_unique<PlainSocket>(mRunLoop, sock)),
+ mInBufferLen(0),
+ mSendPending(false) {
+}
+
+void BaseConnection::run() {
+ receiveClientRequest();
+}
+
+void BaseConnection::receiveClientRequest() {
+ mSocket->postRecv(makeSafeCallback(this, &BaseConnection::onClientRequest));
+}
+
+void BaseConnection::onClientRequest() {
+ static constexpr size_t kMaxChunkSize = 8192;
+
+ mInBuffer.resize(mInBufferLen + kMaxChunkSize);
+
+ ssize_t n;
+ do {
+ n = mSocket->recv(&mInBuffer[mInBufferLen], kMaxChunkSize);
+ } while (n < 0 && errno == EINTR);
+
+ if (n <= 0) {
+ onDisconnect((n < 0) ? -errno : 0);
+ return;
+ }
+
+ mInBufferLen += static_cast<size_t>(n);
+
+ while (mInBufferLen > 0) {
+ n = processClientRequest(mInBuffer.data(), mInBufferLen);
+
+ if (n <= 0) {
+ break;
+ }
+
+ mInBuffer.erase(mInBuffer.begin(), mInBuffer.begin() + n);
+ mInBufferLen -= n;
+ }
+
+ if (n <= 0 && n != -EAGAIN && n != EWOULDBLOCK) {
+ onDisconnect(n);
+ return;
+ }
+
+ receiveClientRequest();
+}
+
+void BaseConnection::send(const void *_data, size_t size) {
+ const uint8_t *data = static_cast<const uint8_t *>(_data);
+ std::copy(data, data + size, std::back_inserter(mOutBuffer));
+
+ if (!mSendPending) {
+ mSendPending = true;
+ mSocket->postSend(
+ makeSafeCallback(this, &BaseConnection::sendOutputData));
+ }
+}
+
+void BaseConnection::sendOutputData() {
+ mSendPending = false;
+
+ const size_t size = mOutBuffer.size();
+ size_t offset = 0;
+
+ while (offset < size) {
+ ssize_t n = mSocket->send(mOutBuffer.data() + offset, size - offset);
+
+ if (n < 0) {
+ if (errno == EINTR) {
+ continue;
+ }
+
+ assert(!"Should not be here");
+ } else if (n == 0) {
+ // The remote seems gone, clear the output buffer and disconnect.
+ offset = size;
+ break;
+ }
+
+ offset += static_cast<size_t>(n);
+ }
+
+ mOutBuffer.erase(mOutBuffer.begin(), mOutBuffer.begin() + offset);
+
+ if (!mOutBuffer.empty()) {
+ mSendPending = true;
+
+ mSocket->postSend(
+ makeSafeCallback(this, &BaseConnection::sendOutputData));
+ return;
+ }
+}
+
+int BaseConnection::fd() const {
+ return mSocket->fd();
+}
+
diff --git a/host/commands/assemble_cvd/disk_flags.h b/host/frontend/gcastv2/https/BufferedSocket.cpp
index 3491c3a01..0156b1cf4 100644
--- a/host/commands/assemble_cvd/disk_flags.h
+++ b/host/frontend/gcastv2/https/BufferedSocket.cpp
@@ -14,20 +14,28 @@
* limitations under the License.
*/
-#pragma once
+#include <https/BufferedSocket.h>
-#include <chrono>
-#include <memory>
-#include <vector>
+#include <cassert>
+#include <unistd.h>
-#include "host/libs/config/cuttlefish_config.h"
-#include "host/libs/config/fetcher_config.h"
+BufferedSocket::BufferedSocket(std::shared_ptr<RunLoop> rl, int sock)
+ : mRunLoop(rl),
+ mSock(sock) {
+ assert(mSock >= 0);
+}
-namespace cuttlefish {
+BufferedSocket::~BufferedSocket() {
+ mRunLoop->cancelSocket(mSock);
-bool ResolveInstanceFiles();
-bool ShouldCreateAllCompositeDisks(const CuttlefishConfig& config);
-void CreateDynamicDiskFiles(const FetcherConfig& fetcher_config,
- const CuttlefishConfig* config);
+ close(mSock);
+ mSock = -1;
+}
-} // namespace cuttlefish
+int BufferedSocket::fd() const {
+ return mSock;
+}
+
+RunLoop *BufferedSocket::runLoop() {
+ return mRunLoop.get();
+}
diff --git a/host/frontend/gcastv2/https/ClientSocket.cpp b/host/frontend/gcastv2/https/ClientSocket.cpp
new file mode 100644
index 000000000..6e2a8ade3
--- /dev/null
+++ b/host/frontend/gcastv2/https/ClientSocket.cpp
@@ -0,0 +1,244 @@
+/*
+ * 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.
+ */
+
+#include <https/ClientSocket.h>
+
+#include <https/HTTPServer.h>
+#include <https/RunLoop.h>
+#include <https/SafeCallbackable.h>
+#include <https/ServerSocket.h>
+
+#include <android-base/logging.h>
+
+#include <cstdlib>
+
+ClientSocket::ClientSocket(
+ std::shared_ptr<RunLoop> rl,
+ HTTPServer *server,
+ ServerSocket *parent,
+ const sockaddr_in &addr,
+ int sock)
+ : mRunLoop(rl),
+ mServer(server),
+ mParent(parent),
+ mRemoteAddr(addr),
+ mInBufferLen(0),
+ mSendPending(false),
+ mDisconnecting(false) {
+ if (parent->transportType() == ServerSocket::TransportType::TLS) {
+ mImplSSL = std::make_shared<SSLSocket>(
+ mRunLoop,
+ sock,
+ *server->certificate_pem_path(),
+ *server->private_key_pem_path());
+ } else {
+ mImplPlain = std::make_shared<PlainSocket>(mRunLoop, sock);
+ }
+}
+
+void ClientSocket::run() {
+ getImpl()->postRecv(makeSafeCallback(this, &ClientSocket::handleIncomingData));
+}
+
+int ClientSocket::fd() const {
+ return getImpl()->fd();
+}
+
+void ClientSocket::setWebSocketHandler(
+ std::shared_ptr<WebSocketHandler> handler) {
+ mWebSocketHandler = handler;
+ mWebSocketHandler->setClientSocket(shared_from_this());
+}
+
+void ClientSocket::handleIncomingData() {
+ mInBuffer.resize(mInBufferLen + 1024);
+
+ ssize_t n;
+ do {
+ n = getImpl()->recv(mInBuffer.data() + mInBufferLen, 1024);
+ } while (n < 0 && errno == EINTR);
+
+ if (n == 0) {
+ if (errno == 0) {
+ // Don't process any data if there was an actual failure.
+ // This could be an authentication failure for example...
+ // We shouldn't trust anything the client says.
+ (void)handleRequest(true /* sawEOS */);
+ }
+
+ disconnect();
+ return;
+ } else if (n < 0) {
+ LOG(ERROR)
+ << "recv returned error "
+ << errno
+ << " ("
+ << strerror(errno)
+ << ")";
+
+ mParent->onClientSocketClosed(fd());
+ return;
+ }
+
+ mInBufferLen += static_cast<size_t>(n);
+ const bool closeConnection = handleRequest(false /* sawEOS */);
+
+ if (closeConnection) {
+ disconnect();
+ } else {
+ getImpl()->postRecv(
+ makeSafeCallback(this, &ClientSocket::handleIncomingData));
+ }
+}
+
+void ClientSocket::disconnect() {
+ if (mDisconnecting) {
+ return;
+ }
+
+ mDisconnecting = true;
+
+ finishDisconnect();
+}
+
+void ClientSocket::finishDisconnect() {
+ if (!mSendPending) {
+ // Our output queue may now be empty, but the underlying socket
+ // implementation may still buffer something that we need to flush
+ // first.
+ getImpl()->postFlush(
+ makeSafeCallback<ClientSocket>(this, [](ClientSocket *me) {
+ me->mParent->onClientSocketClosed(me->fd());
+ }));
+ }
+}
+
+bool ClientSocket::handleRequest(bool isEOS) {
+ if (mWebSocketHandler) {
+ ssize_t n = mWebSocketHandler->handleRequest(
+ mInBuffer.data(), mInBufferLen, isEOS);
+
+ LOG(VERBOSE)
+ << "handleRequest returned "
+ << n
+ << " when called with "
+ << mInBufferLen
+ << ", eos="
+ << isEOS;
+
+ if (n > 0) {
+ mInBuffer.erase(mInBuffer.begin(), mInBuffer.begin() + n);
+ mInBufferLen -= n;
+ }
+
+ // NOTE: Do not return true, i.e. disconnect, if the json handler
+ // returns 0 bytes read, it simply means we need more data to continue.
+ return n < 0;
+ }
+
+ size_t len = mInBufferLen;
+
+ if (!isEOS) {
+ static const char kPattern[] = "\r\n\r\n";
+
+ // Don't count the trailing NUL.
+ static constexpr size_t kPatternLength = sizeof(kPattern) - 1;
+
+ size_t i = 0;
+ while (i + kPatternLength <= mInBufferLen
+ && memcmp(mInBuffer.data() + i, kPattern, kPatternLength)) {
+ ++i;
+ }
+
+ if (i + kPatternLength > mInBufferLen) {
+ return false;
+ }
+
+ // Found a match.
+ len = i + kPatternLength;
+ }
+
+ const bool closeConnection =
+ mServer->handleSingleRequest(this, mInBuffer.data(), len, isEOS);
+
+ mInBuffer.clear();
+ mInBufferLen = 0;
+
+ return closeConnection;
+}
+
+void ClientSocket::queueOutputData(const uint8_t *data, size_t size) {
+ std::copy(data, data + size, std::back_inserter(mOutBuffer));
+
+ if (!mSendPending) {
+ mSendPending = true;
+ getImpl()->postSend(makeSafeCallback(this, &ClientSocket::sendOutputData));
+ }
+}
+
+sockaddr_in ClientSocket::remoteAddr() const {
+ return mRemoteAddr;
+}
+
+void ClientSocket::queueResponse(
+ const std::string &response, const std::string &body) {
+ std::copy(response.begin(), response.end(), std::back_inserter(mOutBuffer));
+ std::copy(body.begin(), body.end(), std::back_inserter(mOutBuffer));
+
+ if (!mSendPending) {
+ mSendPending = true;
+ getImpl()->postSend(makeSafeCallback(this, &ClientSocket::sendOutputData));
+ }
+}
+
+void ClientSocket::sendOutputData() {
+ mSendPending = false;
+
+ const size_t size = mOutBuffer.size();
+ size_t offset = 0;
+
+ while (offset < size) {
+ ssize_t n = getImpl()->send(mOutBuffer.data() + offset, size - offset);
+
+ if (n < 0) {
+ if (errno == EINTR) {
+ continue;
+ }
+
+ assert(!"Should not be here");
+ } else if (n == 0) {
+ // The remote seems gone, clear the output buffer and disconnect.
+ offset = size;
+ mDisconnecting = true;
+ break;
+ }
+
+ offset += static_cast<size_t>(n);
+ }
+
+ mOutBuffer.erase(mOutBuffer.begin(), mOutBuffer.begin() + offset);
+
+ if (!mOutBuffer.empty()) {
+ mSendPending = true;
+ getImpl()->postSend(makeSafeCallback(this, &ClientSocket::sendOutputData));
+ return;
+ }
+
+ if (mDisconnecting) {
+ finishDisconnect();
+ }
+}
+
diff --git a/host/frontend/gcastv2/https/HTTPClientConnection.cpp b/host/frontend/gcastv2/https/HTTPClientConnection.cpp
new file mode 100644
index 000000000..95e3d7c84
--- /dev/null
+++ b/host/frontend/gcastv2/https/HTTPClientConnection.cpp
@@ -0,0 +1,286 @@
+/*
+ * 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.
+ */
+
+#include <https/HTTPClientConnection.h>
+
+#include <https/HTTPRequestResponse.h>
+#include <https/PlainSocket.h>
+#include <https/RunLoop.h>
+#include <https/SafeCallbackable.h>
+#include <https/SSLSocket.h>
+
+#include <https/Support.h>
+
+#include <android-base/logging.h>
+
+#include <arpa/inet.h>
+#include <cerrno>
+#include <netinet/in.h>
+#include <unistd.h>
+
+using namespace android;
+
+HTTPClientConnection::HTTPClientConnection(
+ std::shared_ptr<RunLoop> rl,
+ std::shared_ptr<WebSocketHandler> webSocketHandler,
+ std::string_view path,
+ ServerSocket::TransportType transportType,
+ const std::optional<std::string> &trusted_pem_path)
+ : mInitCheck(-ENODEV),
+ mRunLoop(rl),
+ mWebSocketHandler(webSocketHandler),
+ mPath(path),
+ mTransportType(transportType),
+ mSendPending(false),
+ mInBufferLen(0),
+ mWebSocketMode(false) {
+ int sock;
+
+ sock = socket(PF_INET, SOCK_STREAM, 0);
+ if (sock < 0) {
+ mInitCheck = -errno;
+ goto bail;
+ }
+
+ makeFdNonblocking(sock);
+
+ if (mTransportType == ServerSocket::TransportType::TLS) {
+ CHECK(trusted_pem_path.has_value());
+
+ mImpl = std::make_shared<SSLSocket>(
+ mRunLoop, sock, 0 /* flags */, *trusted_pem_path);
+ } else {
+ mImpl = std::make_shared<PlainSocket>(mRunLoop, sock);
+ }
+
+ mInitCheck = 0;
+ return;
+
+bail:
+ ;
+}
+
+int HTTPClientConnection::initCheck() const {
+ return mInitCheck;
+}
+
+int HTTPClientConnection::connect(const char *host, uint16_t port) {
+ if (mInitCheck < 0) {
+ return mInitCheck;
+ }
+
+ sockaddr_in addr;
+ memset(addr.sin_zero, 0, sizeof(addr.sin_zero));
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(port);
+ addr.sin_addr.s_addr = inet_addr(host);
+
+ mRemoteAddr = addr;
+
+ int res = ::connect(
+ mImpl->fd(), reinterpret_cast<sockaddr *>(&addr), sizeof(addr));
+
+ if (res < 0 && errno != EINPROGRESS) {
+ return -errno;
+ }
+
+ mImpl->postSend(makeSafeCallback(this, &HTTPClientConnection::sendRequest));
+
+ return 0;
+}
+
+void HTTPClientConnection::sendRequest() {
+ std::string request;
+ request =
+ "GET " + mPath + " HTTP/1.1\r\n"
+ "Connection: Upgrade\r\n"
+ "Upgrade: websocket\r\n"
+ "Sec-WebSocket-Version: 13\r\n"
+ "Sec-WebSocket-Key: foobar\r\n"
+ "\r\n";
+
+ CHECK(mRunLoop->isCurrentThread());
+ std::copy(request.begin(), request.end(), std::back_inserter(mOutBuffer));
+
+ if (!mSendPending) {
+ mSendPending = true;
+ mImpl->postSend(
+ makeSafeCallback(this, &HTTPClientConnection::sendOutputData));
+ }
+
+ mImpl->postRecv(
+ makeSafeCallback(this, &HTTPClientConnection::receiveResponse));
+}
+
+void HTTPClientConnection::receiveResponse() {
+ mInBuffer.resize(mInBufferLen + 1024);
+
+ ssize_t n;
+ do {
+ n = mImpl->recv(mInBuffer.data() + mInBufferLen, 1024);
+ } while (n < 0 && errno == EINTR);
+
+ if (n == 0) {
+ (void)handleResponse(true /* isEOS */);
+ return;
+ } else if (n < 0) {
+ LOG(ERROR) << "recv returned error '" << strerror(errno) << "'.";
+ return;
+ }
+
+ mInBufferLen += static_cast<size_t>(n);
+
+ if (!handleResponse(false /* isEOS */)) {
+ mImpl->postRecv(
+ makeSafeCallback(this, &HTTPClientConnection::receiveResponse));
+ }
+}
+
+bool HTTPClientConnection::handleResponse(bool isEOS) {
+ if (mWebSocketMode) {
+ ssize_t n = mWebSocketHandler->handleRequest(
+ mInBuffer.data(), mInBufferLen, isEOS);
+
+ if (n > 0) {
+ mInBuffer.erase(mInBuffer.begin(), mInBuffer.begin() + n);
+ mInBufferLen -= n;
+ }
+
+ return n <= 0;
+ }
+
+ size_t len = mInBufferLen;
+
+ if (!isEOS) {
+ static const char kPattern[] = "\r\n\r\n";
+
+ // Don't count the trailing NUL.
+ static constexpr size_t kPatternLength = sizeof(kPattern) - 1;
+
+ size_t i = 0;
+ while (i + kPatternLength <= mInBufferLen
+ && memcmp(mInBuffer.data() + i, kPattern, kPatternLength)) {
+ ++i;
+ }
+
+ if (i + kPatternLength > mInBufferLen) {
+ return false;
+ }
+
+ // Found a match.
+ len = i + kPatternLength;
+ }
+
+ HTTPResponse response;
+ if (response.setTo(mInBuffer.data(), len) < 0) {
+ LOG(ERROR) << "failed to get valid server response.";
+
+ mInBuffer.clear();
+ mInBufferLen = 0;
+
+ return true;
+ } else {
+ LOG(INFO)
+ << "got response: "
+ << response.getVersion()
+ << ", "
+ << response.getStatusCode()
+ << ", "
+ << response.getStatusMessage();
+
+ hexdump(mInBuffer.data(), len);
+
+ mInBuffer.erase(mInBuffer.begin(), mInBuffer.begin() + len);
+ mInBufferLen -= len;
+
+ size_t contentLength = response.getContentLength();
+ LOG(VERBOSE) << "contentLength = " << contentLength;
+ assert(mInBufferLen >= contentLength);
+
+ hexdump(mInBuffer.data(), contentLength);
+ mInBuffer.clear();
+
+ if (response.getStatusCode() == 101) {
+ mWebSocketMode = true;
+
+ mWebSocketHandler->setOutputCallback(
+ mRemoteAddr,
+ [this](const uint8_t *data, size_t size) {
+ queueOutputData(data, size);
+ });
+
+ const std::string msg = "\"message\":\"Hellow, world!\"";
+ mWebSocketHandler->sendMessage(msg.c_str(), msg.size());
+
+ return false;
+ }
+ }
+
+ return true;
+}
+
+void HTTPClientConnection::queueOutputData(const uint8_t *data, size_t size) {
+ CHECK(mRunLoop->isCurrentThread());
+ std::copy(data, &data[size], std::back_inserter(mOutBuffer));
+
+ if (!mSendPending) {
+ mSendPending = true;
+ mImpl->postSend(
+ makeSafeCallback(this, &HTTPClientConnection::sendOutputData));
+ }
+}
+
+void HTTPClientConnection::sendOutputData() {
+ mSendPending = false;
+
+ const size_t size = mOutBuffer.size();
+ size_t offset = 0;
+
+ while (offset < size) {
+ ssize_t n = mImpl->send(mOutBuffer.data() + offset, size - offset);
+
+ if (n < 0) {
+ if (errno == EINTR) {
+ continue;
+ }
+
+ if (errno == EAGAIN) {
+ break;
+ }
+
+ // The remote is gone (due to error), clear the output buffer and disconnect.
+ offset = size;
+ break;
+ } else if (n == 0) {
+ // The remote seems gone, clear the output buffer and disconnect.
+ offset = size;
+ break;
+ }
+
+ offset += static_cast<size_t>(n);
+ }
+
+ mOutBuffer.erase(mOutBuffer.begin(), mOutBuffer.begin() + offset);
+
+ if (!mOutBuffer.empty()) {
+ mSendPending = true;
+ mImpl->postSend(
+ makeSafeCallback(this, &HTTPClientConnection::sendOutputData));
+
+ return;
+ }
+}
+
diff --git a/host/frontend/gcastv2/https/HTTPRequestResponse.cpp b/host/frontend/gcastv2/https/HTTPRequestResponse.cpp
new file mode 100644
index 000000000..3f0506589
--- /dev/null
+++ b/host/frontend/gcastv2/https/HTTPRequestResponse.cpp
@@ -0,0 +1,174 @@
+/*
+ * 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.
+ */
+
+#include <https/HTTPRequestResponse.h>
+
+#include <cerrno>
+#include <iostream>
+#include <regex>
+
+HTTPRequestResponse::HTTPRequestResponse()
+ : mInitCheck(-ENODEV),
+ mContentLength(0) {
+}
+
+int HTTPRequestResponse::setTo(const uint8_t *data, size_t size) {
+ mInitCheck = -EINVAL;
+
+ bool sawEmptyLine = false;
+
+ size_t start = 0;
+ while (start < size) {
+ size_t end = start;
+ while (end + 1 < size && memcmp(&data[end], "\r\n", 2)) {
+ ++end;
+ }
+
+ if ((end + 1) == size) {
+ return mInitCheck;
+ }
+
+ std::string line(
+ reinterpret_cast<const char *>(&data[start]), end - start);
+
+ if (start == 0) {
+ // Parse the request/response line.
+
+ if (!parseRequestResponseLine(line)) {
+ return mInitCheck;
+ }
+
+ } else if (end > start) {
+ std::regex re("([a-zA-Z0-9-]+): (.*)");
+ std::smatch match;
+
+ if (!std::regex_match(line, match, re)) {
+ return mInitCheck;
+ }
+
+ auto key = match[1];
+ auto value = match[2];
+ mHeaders[key] = value;
+ }
+
+ sawEmptyLine = line.empty();
+
+ start = end + 2;
+ }
+
+ if (!sawEmptyLine) {
+ return mInitCheck;
+ }
+
+ std::string stringValue;
+ if (getHeaderField("Content-Length", &stringValue)) {
+ char *end;
+ unsigned long value = strtoul(stringValue.c_str(), &end, 10);
+
+ if (end == stringValue.c_str() || *end != '\0') {
+ return mInitCheck;
+ }
+
+ mContentLength = value;
+ }
+
+ mInitCheck = 0;
+ return mInitCheck;
+}
+
+int HTTPRequestResponse::initCheck() const {
+ return mInitCheck;
+}
+
+bool HTTPRequestResponse::getHeaderField(
+ std::string_view key, std::string *value) const {
+ auto it = mHeaders.find(std::string(key));
+
+ if (it != mHeaders.end()) {
+ *value = it->second;
+ return true;
+ }
+
+ return false;
+}
+
+size_t HTTPRequestResponse::getContentLength() const {
+ return mContentLength;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+std::string HTTPRequest::getMethod() const {
+ return mMethod;
+}
+
+std::string HTTPRequest::getPath() const {
+ return mPath;
+}
+
+std::string HTTPRequest::getVersion() const {
+ return mVersion;
+}
+
+bool HTTPRequest::parseRequestResponseLine(const std::string &line) {
+ std::regex re("(GET|HEAD) ([a-zA-Z_/.0-9?&=]+) (HTTP/1\\.1)");
+ std::smatch match;
+
+ if (!std::regex_match(line, match, re)) {
+ return false;
+ }
+
+ mMethod = match[1];
+ mPath = match[2];
+ mVersion = match[3];
+
+ return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+std::string HTTPResponse::getVersion() const {
+ return mVersion;
+}
+
+int32_t HTTPResponse::getStatusCode() const {
+ return mStatusCode;
+}
+
+std::string HTTPResponse::getStatusMessage() const {
+ return mStatusMessage;
+}
+
+bool HTTPResponse::parseRequestResponseLine(const std::string &line) {
+ std::regex re(
+ "(HTTP/1\\.1) ([1-9][0-9][0-9]) ([a-zA-Z _0-9.]+)");
+
+ std::smatch match;
+
+ if (!std::regex_match(line, match, re)) {
+ return false;
+ }
+
+ mVersion = match[1];
+ std::string statusString = match[2];
+ mStatusMessage = match[3];
+
+ mStatusCode =
+ static_cast<int32_t>(strtol(statusString.c_str(), nullptr, 10));
+
+ return true;
+}
+
diff --git a/host/frontend/gcastv2/https/HTTPServer.cpp b/host/frontend/gcastv2/https/HTTPServer.cpp
new file mode 100644
index 000000000..967f5f73c
--- /dev/null
+++ b/host/frontend/gcastv2/https/HTTPServer.cpp
@@ -0,0 +1,391 @@
+/*
+ * 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.
+ */
+
+#include <https/HTTPServer.h>
+
+#include <https/ClientSocket.h>
+#include <https/HTTPRequestResponse.h>
+#include <https/Support.h>
+
+#include <android-base/logging.h>
+
+#include <iostream>
+#include <map>
+#include <string>
+
+#include <openssl/sha.h>
+
+#define CC_SHA1_CTX SHA_CTX
+#define CC_SHA1_Init SHA1_Init
+#define CC_SHA1_Update SHA1_Update
+#define CC_SHA1_Final SHA1_Final
+#define CC_LONG size_t
+
+HTTPServer::HTTPServer(
+ std::shared_ptr<RunLoop> runLoop,
+ const char *iface,
+ uint16_t port,
+ ServerSocket::TransportType transportType,
+ const std::optional<std::string> &certificate_pem_path,
+ const std::optional<std::string> &private_key_pem_path)
+ : mRunLoop(runLoop),
+ mLocalPort(port),
+ mSocketTLS(
+ std::make_shared<ServerSocket>(
+ this,
+ transportType,
+ iface ? iface : "0.0.0.0",
+ port,
+ certificate_pem_path,
+ private_key_pem_path)) {
+ CHECK(mSocketTLS->initCheck() == 0);
+}
+
+uint16_t HTTPServer::getLocalPort() const {
+ return mLocalPort;
+}
+
+void HTTPServer::run() {
+ mSocketTLS->run(mRunLoop);
+}
+
+bool HTTPServer::handleSingleRequest(
+ ClientSocket *clientSocket,
+ const uint8_t *data,
+ size_t size,
+ bool isEOS) {
+ (void)isEOS;
+
+ static const std::unordered_map<int32_t, std::string> kStatusMessage {
+ { 101, "Switching Protocols" },
+ { 200, "OK" },
+ { 400, "Bad Request" },
+ { 404, "Not Found" },
+ { 405, "Method Not Allowed" },
+ { 503, "Service Unavailable" },
+ { 505, "HTTP Version Not Supported" },
+ };
+
+ HTTPRequest request;
+ request.setTo(data, size);
+
+ int32_t httpResultCode;
+ std::string body;
+ std::unordered_map<std::string, std::string> responseHeaders;
+
+ if (request.initCheck() < 0) {
+ httpResultCode = 400; // Bad Request
+ } else if (request.getMethod() != "GET") {
+ httpResultCode = 405; // Method Not Allowed
+ } else if (request.getVersion() != "HTTP/1.1") {
+ httpResultCode = 505; // HTTP Version Not Supported
+ } else {
+ httpResultCode = 404;
+
+ auto path = request.getPath();
+
+ std::string query;
+
+ auto separatorPos = path.find('?');
+ if (separatorPos != std::string::npos) {
+ query = path.substr(separatorPos);
+ path.erase(separatorPos);
+ }
+
+ if (path == "/") { path = "/index.html"; }
+
+ bool done = false;
+
+ {
+ std::lock_guard autoLock(mContentLock);
+
+ auto it = mStaticFiles.find(path);
+
+ if (it != mStaticFiles.end()) {
+ handleStaticFileRequest(
+ it->second,
+ request,
+ &httpResultCode,
+ &responseHeaders,
+ &body);
+
+ done = true;
+ }
+ }
+
+ if (!done) {
+ std::lock_guard autoLock(mContentLock);
+
+ auto it = mWebSocketHandlerFactories.find(path);
+
+ if (it != mWebSocketHandlerFactories.end()) {
+ handleWebSocketRequest(
+ clientSocket,
+ it->second,
+ request,
+ &httpResultCode,
+ &responseHeaders,
+ &body);
+
+ done = true;
+ }
+ }
+
+ const auto remoteAddr = clientSocket->remoteAddr();
+ uint32_t ip = ntohl(remoteAddr.sin_addr.s_addr);
+
+ LOG(INFO)
+ << (ip >> 24)
+ << "."
+ << ((ip >> 16) & 0xff)
+ << "."
+ << ((ip >> 8) & 0xff)
+ << "."
+ << (ip & 0xff)
+ << ":"
+ << ntohs(remoteAddr.sin_port)
+ << " "
+ << httpResultCode << " \"" << path << "\"";
+ }
+
+ const std::string status =
+ std::to_string(httpResultCode)
+ + " "
+ + kStatusMessage.find(httpResultCode)->second;
+
+ bool closeConnection = false;
+
+ if (httpResultCode != 200 && httpResultCode != 101) {
+ body = "<h1>" + status + "</h1>";
+
+ responseHeaders["Connection"] = "close";
+ responseHeaders["Content-Type"] = "text/html";
+
+ closeConnection = true;
+ }
+
+ std::string value;
+ if (request.getHeaderField("Connection", &value) && value == "close") {
+ LOG(VERBOSE) << "Closing connection per client's request.";
+ closeConnection = true;
+ }
+
+ responseHeaders["Content-Length"] = std::to_string(body.size());
+
+ if (closeConnection) {
+ responseHeaders["Connection"] = "close";
+ }
+
+ std::string response;
+ response = "HTTP/1.1 " + status + "\r\n";
+
+ for (const auto &pair : responseHeaders) {
+ response += pair.first + ": " + pair.second + "\r\n";
+ }
+
+ response += "\r\n";
+
+ clientSocket->queueResponse(response, body);
+
+ return closeConnection;
+}
+
+void HTTPServer::addStaticFile(
+ const char *at, const char *path, std::optional<std::string> mimeType) {
+ std::lock_guard autoLock(mContentLock);
+ mStaticFiles[at] = { path, mimeType };
+}
+
+void HTTPServer::addStaticContent(
+ const char *at,
+ const void *_data,
+ size_t size,
+ std::optional<std::string> mimeType) {
+ if (!mimeType) {
+ // Note: unlike for static, file-based content, we guess the mime type
+ // based on the path we're mapping the content at, not the path it's
+ // originating from (since we don't know that for memory based content).
+ mimeType = GuessMimeType(at);
+ }
+
+ auto data = static_cast<const uint8_t *>(_data);
+
+ std::lock_guard autoLock(mContentLock);
+ mStaticFiles[at] = { std::vector<uint8_t>(data, data + size), mimeType };
+}
+
+void HTTPServer::addWebSocketHandlerFactory(
+ const char *at, WebSocketHandlerFactory factory) {
+ std::lock_guard autoLock(mContentLock);
+ mWebSocketHandlerFactories[at] = factory;
+}
+
+void HTTPServer::handleWebSocketRequest(
+ ClientSocket *clientSocket,
+ WebSocketHandlerFactory factory,
+ const HTTPRequest &request,
+ int32_t *httpResultCode,
+ std::unordered_map<std::string, std::string> *responseHeaders,
+ std::string *body) {
+ (void)body;
+
+ auto [status, handler] = factory();
+
+ if (status != 0 || !handler) {
+ *httpResultCode = 503; // Service unavailable.
+ return;
+ }
+
+ *httpResultCode = 400;
+
+ std::string value;
+ if (!request.getHeaderField("Connection", &value)
+ || (value != "Upgrade" && value != "keep-alive, Upgrade")) {
+ return;
+ }
+
+ if (!request.getHeaderField("Upgrade", &value) || value != "websocket") {
+ return;
+ }
+
+ if (!request.getHeaderField("Sec-WebSocket-Version", &value)) {
+ return;
+ }
+
+ char *end;
+ long version = strtol(value.c_str(), &end, 10);
+
+ if (end == value.c_str() || *end != '\0' || version < 13) {
+ return;
+ }
+
+ if (!request.getHeaderField("Sec-WebSocket-Key", &value)) {
+ return;
+ }
+
+ *httpResultCode = 101;
+
+ (*responseHeaders)["Connection"] = "Upgrade";
+ (*responseHeaders)["Upgrade"] = "websocket";
+
+ std::string tmp = value;
+ tmp += "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
+
+ CC_SHA1_CTX ctx;
+ int res = CC_SHA1_Init(&ctx);
+ CHECK_EQ(res, 1);
+
+ res = CC_SHA1_Update(
+ &ctx, tmp.c_str(), static_cast<CC_LONG>(tmp.size()));
+
+ CHECK_EQ(res, 1);
+
+ unsigned char digest[20]; // 160 bit
+ res = CC_SHA1_Final(digest, &ctx);
+ CHECK_EQ(res, 1);
+
+ std::string acceptKey;
+ encodeBase64(digest, sizeof(digest), &acceptKey);
+
+ (*responseHeaders)["Sec-WebSocket-Accept"] = acceptKey;
+
+ clientSocket->setWebSocketHandler(handler);
+}
+
+void HTTPServer::handleStaticFileRequest(
+ const StaticFileInfo &info,
+ const HTTPRequest &request,
+ int32_t *httpResultCode,
+ std::unordered_map<std::string, std::string> *responseHeaders,
+ std::string *body) {
+ (void)request;
+
+ if (std::holds_alternative<std::string>(info.mPathOrContent)) {
+ const auto &path = std::get<std::string>(info.mPathOrContent);
+
+ std::unique_ptr<FILE, std::function<int(FILE *)>> file(
+ fopen(path.c_str(), "r"),
+ fclose);
+
+ if (!file) {
+ *httpResultCode = 404;
+ return;
+ }
+
+ fseek(file.get(), 0, SEEK_END);
+ long fileSize = ftell(file.get());
+ fseek(file.get(), 0, SEEK_SET);
+
+ (*responseHeaders)["Content-Length"] = std::to_string(fileSize);
+
+ if (info.mMimeType) {
+ (*responseHeaders)["Content-Type"] = *info.mMimeType;
+ } else {
+ (*responseHeaders)["Content-Type"] = GuessMimeType(path);
+ }
+
+ while (!feof(file.get())) {
+ char buffer[1024];
+ auto n = fread(buffer, 1, sizeof(buffer), file.get());
+
+ body->append(buffer, n);
+ }
+ } else {
+ CHECK(std::holds_alternative<std::vector<uint8_t>>(
+ info.mPathOrContent));
+
+ const auto &content =
+ std::get<std::vector<uint8_t>>(info.mPathOrContent);
+
+ body->append(content.begin(), content.end());
+
+ (*responseHeaders)["Content-Length"] = std::to_string(content.size());
+ }
+
+ *httpResultCode = 200;
+}
+
+// static
+std::string HTTPServer::GuessMimeType(const std::string &path) {
+ auto dotPos = path.rfind('.');
+ if (dotPos != std::string::npos) {
+ auto extension = std::string(path, dotPos + 1);
+
+ static std::unordered_map<std::string, std::string>
+ sMimeTypeByExtension {
+
+ { "html", "text/html" },
+ { "htm", "text/html" },
+ { "css", "text/css" },
+ { "js", "text/javascript" },
+ };
+
+ auto it = sMimeTypeByExtension.find(extension);
+ if (it != sMimeTypeByExtension.end()) {
+ return it->second;
+ }
+ }
+
+ return "application/octet-stream";
+}
+
+std::optional<std::string> HTTPServer::certificate_pem_path() const {
+ return mSocketTLS->certificate_pem_path();
+}
+
+std::optional<std::string> HTTPServer::private_key_pem_path() const {
+ return mSocketTLS->private_key_pem_path();
+}
diff --git a/host/frontend/gcastv2/https/PlainSocket.cpp b/host/frontend/gcastv2/https/PlainSocket.cpp
new file mode 100644
index 000000000..26ee5749a
--- /dev/null
+++ b/host/frontend/gcastv2/https/PlainSocket.cpp
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+
+#include <https/PlainSocket.h>
+
+#include <sys/socket.h>
+
+PlainSocket::PlainSocket(std::shared_ptr<RunLoop> rl, int sock)
+ : BufferedSocket(rl, sock) {
+}
+
+void PlainSocket::postRecv(RunLoop::AsyncFunction fn) {
+ runLoop()->postSocketRecv(fd(), fn);
+}
+
+void PlainSocket::postSend(RunLoop::AsyncFunction fn) {
+ runLoop()->postSocketSend(fd(), fn);
+}
+
+ssize_t PlainSocket::recvfrom(
+ void *data,
+ size_t size,
+ sockaddr *address,
+ socklen_t *addressLen) {
+ return ::recvfrom(fd(), data, size, 0, address, addressLen);
+}
+
+ssize_t PlainSocket::sendto(
+ const void *data,
+ size_t size,
+ const sockaddr *addr,
+ socklen_t addrLen) {
+ if (!addr) {
+ return ::send(fd(), data, size, 0);
+ }
+ return ::sendto(fd(), data, size, 0, addr, addrLen);
+}
+
+void PlainSocket::postFlush(RunLoop::AsyncFunction fn) {
+ fn();
+}
diff --git a/host/frontend/gcastv2/https/README b/host/frontend/gcastv2/https/README
new file mode 100644
index 000000000..49fefc66c
--- /dev/null
+++ b/host/frontend/gcastv2/https/README
@@ -0,0 +1,5 @@
+Test using
+
+ curl --cacert certs/server.crt https://localhost:443/
+
+
diff --git a/host/frontend/gcastv2/https/RunLoop.cpp b/host/frontend/gcastv2/https/RunLoop.cpp
new file mode 100644
index 000000000..f9d50c659
--- /dev/null
+++ b/host/frontend/gcastv2/https/RunLoop.cpp
@@ -0,0 +1,448 @@
+/*
+ * 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.
+ */
+
+#include <https/RunLoop.h>
+
+#include <https/Support.h>
+
+#include <android-base/logging.h>
+
+#include <cstring>
+#include <fcntl.h>
+#include <iostream>
+#include <unistd.h>
+
+#include <mutex>
+#include <condition_variable>
+
+bool RunLoop::QueueElem::operator<=(const QueueElem &other) const {
+ if (mWhen) {
+ if (other.mWhen) {
+ return mWhen <= other.mWhen;
+ }
+
+ return false;
+ }
+
+ if (other.mWhen) {
+ return true;
+ }
+
+ // This ensures that two events posted without a trigger time are queued in
+ // the order they were post()ed in.
+ return true;
+}
+
+RunLoop::RunLoop()
+ : mDone(false),
+ mPThread(0),
+ mNextToken(1) {
+ int res = pipe(mControlFds);
+ CHECK_GE(res, 0);
+
+ makeFdNonblocking(mControlFds[0]);
+}
+
+RunLoop::RunLoop(std::string_view name)
+ : RunLoop() {
+ mName = name;
+
+ mThread = std::thread([this]{ run(); });
+}
+
+RunLoop::~RunLoop() {
+ stop();
+
+ close(mControlFds[1]);
+ mControlFds[1] = -1;
+
+ close(mControlFds[0]);
+ mControlFds[0] = -1;
+}
+
+void RunLoop::stop() {
+ mDone = true;
+ interrupt();
+
+ if (mThread.joinable()) {
+ mThread.join();
+ }
+}
+
+RunLoop::Token RunLoop::post(AsyncFunction fn) {
+ CHECK(fn != nullptr);
+
+ auto token = mNextToken++;
+ insert({ std::nullopt, fn, token });
+
+ return token;
+}
+
+bool RunLoop::postAndAwait(AsyncFunction fn) {
+ if (isCurrentThread()) {
+ // To wait from the runloop's thread would cause deadlock
+ post(fn);
+ return false;
+ }
+
+ std::mutex mtx;
+ bool ran = false;
+ std::condition_variable cond_var;
+
+ post([&cond_var, &mtx, &ran, fn](){
+ fn();
+ {
+ std::unique_lock<std::mutex> lock(mtx);
+ ran = true;
+ // Notify while holding the mutex, otherwise the condition variable
+ // could be destroyed before the call to notify_all.
+ cond_var.notify_all();
+ }
+ });
+
+ {
+ std::unique_lock<std::mutex> lock(mtx);
+ cond_var.wait(lock, [&ran](){ return ran;});
+ }
+ return ran;
+}
+
+RunLoop::Token RunLoop::postWithDelay(
+ std::chrono::steady_clock::duration delay, AsyncFunction fn) {
+ CHECK(fn != nullptr);
+
+ auto token = mNextToken++;
+ insert({ std::chrono::steady_clock::now() + delay, fn, token });
+
+ return token;
+}
+
+bool RunLoop::cancelToken(Token token) {
+ std::lock_guard<std::mutex> autoLock(mLock);
+
+ bool found = false;
+ for (auto it = mQueue.begin(); it != mQueue.end(); ++it) {
+ if (it->mToken == token) {
+ mQueue.erase(it);
+
+ if (it == mQueue.begin()) {
+ interrupt();
+ }
+
+ found = true;
+ break;
+ }
+ }
+
+ return found;
+}
+
+void RunLoop::postSocketRecv(int sock, AsyncFunction fn) {
+ CHECK_GE(sock, 0);
+ CHECK(fn != nullptr);
+
+ std::lock_guard<std::mutex> autoLock(mLock);
+ mAddInfos.push_back({ sock, InfoType::RECV, fn });
+ interrupt();
+}
+
+void RunLoop::postSocketSend(int sock, AsyncFunction fn) {
+ CHECK_GE(sock, 0);
+ CHECK(fn != nullptr);
+
+ std::lock_guard<std::mutex> autoLock(mLock);
+ mAddInfos.push_back({ sock, InfoType::SEND, fn });
+ interrupt();
+}
+
+void RunLoop::cancelSocket(int sock) {
+ CHECK_GE(sock, 0);
+
+ std::lock_guard<std::mutex> autoLock(mLock);
+ mAddInfos.push_back({ sock, InfoType::CANCEL, nullptr });
+ interrupt();
+}
+
+void RunLoop::insert(const QueueElem &elem) {
+ std::lock_guard<std::mutex> autoLock(mLock);
+
+ auto it = mQueue.begin();
+ while (it != mQueue.end() && *it <= elem) {
+ ++it;
+ }
+
+ if (it == mQueue.begin()) {
+ interrupt();
+ }
+
+ mQueue.insert(it, elem);
+}
+
+void RunLoop::run() {
+ mPThread = pthread_self();
+
+ std::map<int, SocketCallbacks> socketCallbacksByFd;
+ std::vector<pollfd> pollFds;
+
+ auto removePollFdAt = [&socketCallbacksByFd, &pollFds](size_t i) {
+ if (i + 1 == pollFds.size()) {
+ pollFds.pop_back();
+ } else {
+ // Instead of leaving a hole in the middle of the
+ // pollFds vector, we copy the last item into
+ // that hole and reduce the size of the vector by 1,
+ // taking are of updating the corresponding callback
+ // with the correct, new index.
+ pollFds[i] = pollFds.back();
+ pollFds.pop_back();
+ socketCallbacksByFd[pollFds[i].fd].mPollFdIndex = i;
+ }
+ };
+
+ // The control channel's pollFd will always be at index 0.
+ pollFds.push_back({ mControlFds[0], POLLIN, 0 });
+
+ for (;;) {
+ int timeoutMs = -1; // wait Forever
+
+ {
+ std::lock_guard<std::mutex> autoLock(mLock);
+
+ if (mDone) {
+ break;
+ }
+
+ for (const auto &addInfo : mAddInfos) {
+ const int sock = addInfo.mSock;
+ const auto fn = addInfo.mFn;
+
+ auto it = socketCallbacksByFd.find(sock);
+
+ switch (addInfo.mType) {
+ case InfoType::RECV:
+ {
+ if (it == socketCallbacksByFd.end()) {
+ socketCallbacksByFd[sock] = { fn, nullptr, pollFds.size() };
+ pollFds.push_back({ sock, POLLIN, 0 });
+ } else {
+ // There's already a pollFd for this socket.
+ CHECK(it->second.mSendFn != nullptr);
+
+ CHECK(it->second.mRecvFn == nullptr);
+ it->second.mRecvFn = fn;
+
+ pollFds[it->second.mPollFdIndex].events |= POLLIN;
+ }
+ break;
+ }
+
+ case InfoType::SEND:
+ {
+ if (it == socketCallbacksByFd.end()) {
+ socketCallbacksByFd[sock] = { nullptr, fn, pollFds.size() };
+ pollFds.push_back({ sock, POLLOUT, 0 });
+ } else {
+ // There's already a pollFd for this socket.
+ if (it->second.mRecvFn == nullptr) {
+ LOG(ERROR)
+ << "There's an entry but no recvFn "
+ "notification for socket "
+ << sock;
+ }
+
+ CHECK(it->second.mRecvFn != nullptr);
+
+ if (it->second.mSendFn != nullptr) {
+ LOG(ERROR)
+ << "There's already a pending send "
+ "notification for socket "
+ << sock;
+ }
+ CHECK(it->second.mSendFn == nullptr);
+ it->second.mSendFn = fn;
+
+ pollFds[it->second.mPollFdIndex].events |= POLLOUT;
+ }
+ break;
+ }
+
+ case InfoType::CANCEL:
+ {
+ if (it != socketCallbacksByFd.end()) {
+ const size_t i = it->second.mPollFdIndex;
+
+ socketCallbacksByFd.erase(it);
+ removePollFdAt(i);
+ }
+ break;
+ }
+ }
+ }
+
+ mAddInfos.clear();
+
+ if (!mQueue.empty()) {
+ timeoutMs = 0;
+
+ if (mQueue.front().mWhen) {
+ auto duration =
+ *mQueue.front().mWhen - std::chrono::steady_clock::now();
+
+ auto durationMs =
+ std::chrono::duration_cast<std::chrono::milliseconds>(duration);
+
+ if (durationMs.count() > 0) {
+ timeoutMs = static_cast<int>(durationMs.count());
+ }
+ }
+ }
+ }
+
+ int pollRes = 0;
+ if (timeoutMs != 0) {
+ // NOTE: The inequality is on purpose, we'll want to execute this
+ // code if timeoutMs == -1 (infinite) or timeoutMs > 0, but not
+ // if it's 0.
+
+ pollRes = poll(
+ pollFds.data(),
+ static_cast<nfds_t>(pollFds.size()),
+ timeoutMs);
+ }
+
+ if (pollRes < 0) {
+ if (errno != EINTR) {
+ std::cerr
+ << "poll FAILED w/ "
+ << errno
+ << " ("
+ << strerror(errno)
+ << ")"
+ << std::endl;
+ }
+
+ CHECK_EQ(errno, EINTR);
+ continue;
+ }
+
+ std::vector<AsyncFunction> fnArray;
+
+ {
+ std::lock_guard<std::mutex> autoLock(mLock);
+
+ if (pollRes > 0) {
+ if (pollFds[0].revents & POLLIN) {
+ ssize_t res;
+ do {
+ uint8_t c[32];
+ while ((res = read(mControlFds[0], c, sizeof(c))) < 0
+ && errno == EINTR) {
+ }
+ } while (res > 0);
+ CHECK(res < 0 && errno == EWOULDBLOCK);
+
+ --pollRes;
+ }
+
+ // NOTE: Skip index 0, as we already handled it above.
+ // Also, bail early if we exhausted all actionable pollFds
+ // according to pollRes.
+ for (size_t i = pollFds.size(); pollRes && i-- > 1;) {
+ pollfd &pollFd = pollFds[i];
+ const short revents = pollFd.revents;
+
+ if (revents) {
+ --pollRes;
+ }
+
+ const bool readable = (revents & POLLIN);
+ const bool writable = (revents & POLLOUT);
+ const bool dead = (revents & POLLNVAL);
+
+ bool removeCallback = dead;
+
+ if (readable || writable || dead) {
+ const int sock = pollFd.fd;
+
+ const auto &it = socketCallbacksByFd.find(sock);
+ auto &cb = it->second;
+ CHECK_EQ(cb.mPollFdIndex, i);
+
+ if (readable) {
+ CHECK(cb.mRecvFn != nullptr);
+ fnArray.push_back(cb.mRecvFn);
+ cb.mRecvFn = nullptr;
+ pollFd.events &= ~POLLIN;
+
+ removeCallback |= (cb.mSendFn == nullptr);
+ }
+
+ if (writable) {
+ CHECK(cb.mSendFn != nullptr);
+ fnArray.push_back(cb.mSendFn);
+ cb.mSendFn = nullptr;
+ pollFd.events &= ~POLLOUT;
+
+ removeCallback |= (cb.mRecvFn == nullptr);
+ }
+
+ if (removeCallback) {
+ socketCallbacksByFd.erase(it);
+ removePollFdAt(i);
+ }
+ }
+ }
+ } else {
+ // No interrupt, no socket notifications.
+ fnArray.push_back(mQueue.front().mFn);
+ mQueue.pop_front();
+ }
+ }
+
+ for (const auto &fn : fnArray) {
+ fn();
+ }
+ }
+}
+
+void RunLoop::interrupt() {
+ uint8_t c = 1;
+ ssize_t res;
+ while ((res = write(mControlFds[1], &c, 1)) < 0 && errno == EINTR) {
+ }
+
+ CHECK_EQ(res, 1);
+}
+
+struct MainRunLoop : public RunLoop {
+};
+
+static std::mutex gLock;
+static std::shared_ptr<RunLoop> gMainRunLoop;
+
+// static
+std::shared_ptr<RunLoop> RunLoop::main() {
+ std::lock_guard<std::mutex> autoLock(gLock);
+ if (!gMainRunLoop) {
+ gMainRunLoop = std::make_shared<MainRunLoop>();
+ }
+ return gMainRunLoop;
+}
+
+bool RunLoop::isCurrentThread() const {
+ return pthread_equal(pthread_self(), mPThread);
+}
+
diff --git a/host/frontend/gcastv2/https/SSLSocket.cpp b/host/frontend/gcastv2/https/SSLSocket.cpp
new file mode 100644
index 000000000..db8543a36
--- /dev/null
+++ b/host/frontend/gcastv2/https/SSLSocket.cpp
@@ -0,0 +1,569 @@
+/*
+ * 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.
+ */
+
+#include <https/SSLSocket.h>
+
+#include <https/SafeCallbackable.h>
+#include <https/Support.h>
+#include <android-base/logging.h>
+#include <sstream>
+#include <sys/socket.h>
+
+// static
+void SSLSocket::Init() {
+ SSL_library_init();
+ SSL_load_error_strings();
+}
+
+// static
+SSL_CTX *SSLSocket::CreateSSLContext() {
+ SSL_CTX *ctx = SSL_CTX_new(SSLv23_method());
+
+ /* Recommended to avoid SSLv2 & SSLv3 */
+ SSL_CTX_set_options(
+ ctx, SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
+
+ return ctx;
+}
+
+SSLSocket::SSLSocket(
+ std::shared_ptr<RunLoop> rl, Mode mode, int sock, uint32_t flags)
+ : BufferedSocket(rl, sock),
+ mMode(mode),
+ mFlags(flags),
+ mCtx(CreateSSLContext(), SSL_CTX_free),
+ mSSL(SSL_new(mCtx.get()), SSL_free),
+ mBioR(BIO_new(BIO_s_mem())),
+ mBioW(BIO_new(BIO_s_mem())),
+ mEOS(false),
+ mFinalErrno(0),
+ mRecvPending(false),
+ mRecvCallback(nullptr),
+ mSendPending(false),
+ mFlushFn(nullptr) {
+ if (mMode == Mode::ACCEPT) {
+ SSL_set_accept_state(mSSL.get());
+ } else {
+ SSL_set_connect_state(mSSL.get());
+ }
+ SSL_set_bio(mSSL.get(), mBioR, mBioW);
+}
+
+bool SSLSocket::useCertificate(const std::string &path) {
+ return 1 == SSL_use_certificate_file(
+ mSSL.get(), path.c_str(), SSL_FILETYPE_PEM);
+}
+
+bool SSLSocket::usePrivateKey(const std::string &path) {
+ return 1 == SSL_use_PrivateKey_file(
+ mSSL.get(), path.c_str(), SSL_FILETYPE_PEM)
+ && 1 == SSL_check_private_key(mSSL.get());
+}
+
+bool SSLSocket::useTrustedCertificates(const std::string &path) {
+ return 1 == SSL_CTX_load_verify_locations(
+ mCtx.get(),
+ path.c_str(),
+ nullptr /* CApath */);
+}
+
+SSLSocket::SSLSocket(
+ std::shared_ptr<RunLoop> rl,
+ int sock,
+ const std::string &certificate_pem_path,
+ const std::string &private_key_pem_path,
+ uint32_t flags)
+ : SSLSocket(rl, Mode::ACCEPT, sock, flags) {
+
+ // This flag makes no sense for a server.
+ CHECK(!(mFlags & FLAG_DONT_CHECK_PEER_CERTIFICATE));
+
+ CHECK(useCertificate(certificate_pem_path)
+ && usePrivateKey(private_key_pem_path));
+}
+
+SSLSocket::SSLSocket(
+ std::shared_ptr<RunLoop> rl,
+ int sock,
+ uint32_t flags,
+ const std::optional<std::string> &trusted_pem_path)
+ : SSLSocket(rl, Mode::CONNECT, sock, flags) {
+
+ if (!(mFlags & FLAG_DONT_CHECK_PEER_CERTIFICATE)) {
+ CHECK(trusted_pem_path.has_value());
+ CHECK(useTrustedCertificates(*trusted_pem_path));
+ }
+}
+
+SSLSocket::~SSLSocket() {
+ SSL_shutdown(mSSL.get());
+
+ mBioW = mBioR = nullptr;
+}
+
+void SSLSocket::postRecv(RunLoop::AsyncFunction fn) {
+ char tmp[128];
+ int n = SSL_peek(mSSL.get(), tmp, sizeof(tmp));
+
+ if (n > 0) {
+ fn();
+ return;
+ }
+
+ CHECK(mRecvCallback == nullptr);
+ mRecvCallback = fn;
+
+ if (!mRecvPending) {
+ mRecvPending = true;
+ runLoop()->postSocketRecv(
+ fd(),
+ makeSafeCallback(this, &SSLSocket::handleIncomingData));
+ }
+}
+
+void SSLSocket::handleIncomingData() {
+ mRecvPending = false;
+
+ uint8_t buffer[1024];
+ ssize_t len;
+ do {
+ len = ::recv(fd(), buffer, sizeof(buffer), 0);
+ } while (len < 0 && errno == EINTR);
+
+ if (len <= 0) {
+ mEOS = true;
+ mFinalErrno = (len < 0) ? errno : 0;
+
+ sendRecvCallback();
+ return;
+ }
+
+ size_t offset = 0;
+ while (len > 0) {
+ int n = BIO_write(mBioR, &buffer[offset], len);
+ CHECK_GT(n, 0);
+
+ offset += n;
+ len -= n;
+
+ if (!SSL_is_init_finished(mSSL.get())) {
+ if (mMode == Mode::ACCEPT) {
+ n = SSL_accept(mSSL.get());
+ } else {
+ n = SSL_connect(mSSL.get());
+ }
+
+ auto err = SSL_get_error(mSSL.get(), n);
+
+ switch (err) {
+ case SSL_ERROR_WANT_READ:
+ {
+ CHECK_EQ(len, 0);
+ queueOutputDataFromSSL();
+
+ mRecvPending = true;
+
+ runLoop()->postSocketRecv(
+ fd(),
+ makeSafeCallback(
+ this, &SSLSocket::handleIncomingData));
+
+ return;
+ }
+
+ case SSL_ERROR_WANT_WRITE:
+ {
+ CHECK_EQ(len, 0);
+
+ mRecvPending = true;
+
+ runLoop()->postSocketRecv(
+ fd(),
+ makeSafeCallback(
+ this, &SSLSocket::handleIncomingData));
+
+ return;
+ }
+
+ case SSL_ERROR_NONE:
+ break;
+
+ case SSL_ERROR_SYSCALL:
+ default:
+ {
+ // This is where we end up if the client doesn't trust us.
+ mEOS = true;
+ mFinalErrno = ECONNREFUSED;
+
+ sendRecvCallback();
+ return;
+ }
+ }
+
+ CHECK(SSL_is_init_finished(mSSL.get()));
+
+ drainOutputBufferPlain();
+
+ if (!(mFlags & FLAG_DONT_CHECK_PEER_CERTIFICATE)
+ && !isPeerCertificateValid()) {
+ mEOS = true;
+ mFinalErrno = ECONNREFUSED;
+ sendRecvCallback();
+ }
+ }
+ }
+
+ int n = SSL_peek(mSSL.get(), buffer, sizeof(buffer));
+
+ if (n > 0) {
+ sendRecvCallback();
+ return;
+ }
+
+ auto err = SSL_get_error(mSSL.get(), n);
+
+ switch (err) {
+ case SSL_ERROR_WANT_READ:
+ {
+ queueOutputDataFromSSL();
+
+ mRecvPending = true;
+
+ runLoop()->postSocketRecv(
+ fd(),
+ makeSafeCallback(this, &SSLSocket::handleIncomingData));
+
+ break;
+ }
+
+ case SSL_ERROR_WANT_WRITE:
+ {
+ mRecvPending = true;
+
+ runLoop()->postSocketRecv(
+ fd(),
+ makeSafeCallback(this, &SSLSocket::handleIncomingData));
+
+ break;
+ }
+
+ case SSL_ERROR_ZERO_RETURN:
+ {
+ mEOS = true;
+ mFinalErrno = 0;
+
+ sendRecvCallback();
+ break;
+ }
+
+ case SSL_ERROR_NONE:
+ break;
+
+ case SSL_ERROR_SYSCALL:
+ default:
+ {
+ // This is where we end up if the client doesn't trust us.
+ mEOS = true;
+ mFinalErrno = ECONNREFUSED;
+
+ sendRecvCallback();
+ break;
+ }
+ }
+}
+
+void SSLSocket::sendRecvCallback() {
+ const auto cb = mRecvCallback;
+ mRecvCallback = nullptr;
+ if (cb != nullptr) {
+ cb();
+ }
+}
+
+void SSLSocket::postSend(RunLoop::AsyncFunction fn) {
+ runLoop()->post(fn);
+}
+
+ssize_t SSLSocket::recvfrom(
+ void *data,
+ size_t size,
+ sockaddr *address,
+ socklen_t *addressLen) {
+ if (address || addressLen) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (mEOS) {
+ errno = mFinalErrno;
+ return (mFinalErrno == 0) ? 0 : -1;
+ }
+
+ int n = SSL_read(mSSL.get(), data, size);
+
+ // We should only get here after SSL_peek signaled that there's data to
+ // be read.
+ CHECK_GT(n, 0);
+
+ return n;
+}
+
+void SSLSocket::queueOutputDataFromSSL() {
+ int n;
+ do {
+ char buf[1024];
+ n = BIO_read(mBioW, buf, sizeof(buf));
+
+ if (n > 0) {
+ queueOutputData(buf, n);
+ } else if (BIO_should_retry(mBioW)) {
+ continue;
+ } else {
+ LOG(FATAL) << "Should not be here.";
+ }
+ } while (n > 0);
+}
+
+void SSLSocket::queueOutputData(const void *data, size_t size) {
+ if (!size) {
+ return;
+ }
+
+ const size_t pos = mOutBuffer.size();
+ mOutBuffer.resize(pos + size);
+ memcpy(mOutBuffer.data() + pos, data, size);
+
+ if (!mSendPending) {
+ mSendPending = true;
+ runLoop()->postSocketSend(
+ fd(),
+ makeSafeCallback(this, &SSLSocket::sendOutputData));
+ }
+}
+
+void SSLSocket::sendOutputData() {
+ mSendPending = false;
+
+ const size_t size = mOutBuffer.size();
+ size_t offset = 0;
+
+ while (offset < size) {
+ ssize_t n = ::send(
+ fd(), mOutBuffer.data() + offset, size - offset, 0);
+
+ if (n < 0) {
+ if (errno == EINTR) {
+ continue;
+ } else if (errno == EAGAIN || errno == EWOULDBLOCK) {
+ break;
+ }
+
+ LOG(FATAL) << "Should not be here.";
+ }
+
+ offset += static_cast<size_t>(n);
+ }
+
+ mOutBuffer.erase(mOutBuffer.begin(), mOutBuffer.begin() + offset);
+
+ if (!mOutBufferPlain.empty()) {
+ drainOutputBufferPlain();
+ }
+
+ if (!mOutBuffer.empty()) {
+ mSendPending = true;
+ runLoop()->postSocketSend(
+ fd(),
+ makeSafeCallback(this, &SSLSocket::sendOutputData));
+
+ return;
+ }
+
+ auto fn = mFlushFn;
+ mFlushFn = nullptr;
+ if (fn != nullptr) {
+ fn();
+ }
+}
+
+ssize_t SSLSocket::sendto(
+ const void *data,
+ size_t size,
+ const sockaddr *addr,
+ socklen_t addrLen) {
+ if (addr || addrLen) {
+ errno = -EINVAL;
+ return -1;
+ }
+
+ if (mEOS) {
+ errno = mFinalErrno;
+ return (mFinalErrno == 0) ? 0 : -1;
+ }
+
+ const size_t pos = mOutBufferPlain.size();
+ mOutBufferPlain.resize(pos + size);
+ memcpy(&mOutBufferPlain[pos], data, size);
+
+ drainOutputBufferPlain();
+
+ return size;
+}
+
+void SSLSocket::drainOutputBufferPlain() {
+ size_t offset = 0;
+ const size_t size = mOutBufferPlain.size();
+
+ while (offset < size) {
+ int n = SSL_write(mSSL.get(), &mOutBufferPlain[offset], size - offset);
+
+ if (!SSL_is_init_finished(mSSL.get())) {
+ if (mMode == Mode::ACCEPT) {
+ n = SSL_accept(mSSL.get());
+ } else {
+ n = SSL_connect(mSSL.get());
+ }
+
+ auto err = SSL_get_error(mSSL.get(), n);
+
+ switch (err) {
+ case SSL_ERROR_WANT_WRITE:
+ {
+ mOutBufferPlain.erase(
+ mOutBufferPlain.begin(),
+ mOutBufferPlain.begin() + offset);
+
+ queueOutputDataFromSSL();
+ return;
+ }
+
+ case SSL_ERROR_WANT_READ:
+ {
+ mOutBufferPlain.erase(
+ mOutBufferPlain.begin(),
+ mOutBufferPlain.begin() + offset);
+
+ queueOutputDataFromSSL();
+
+ if (!mRecvPending) {
+ mRecvPending = true;
+
+ runLoop()->postSocketRecv(
+ fd(),
+ makeSafeCallback(
+ this, &SSLSocket::handleIncomingData));
+ }
+ return;
+ }
+
+ case SSL_ERROR_SYSCALL:
+ {
+ // This is where we end up if the client doesn't trust us.
+ mEOS = true;
+ mFinalErrno = ECONNREFUSED;
+
+ LOG(FATAL) << "Should not be here.";
+ return;
+ }
+
+ case SSL_ERROR_NONE:
+ break;
+
+ default:
+ LOG(FATAL) << "Should not be here.";
+ }
+
+ CHECK(SSL_is_init_finished(mSSL.get()));
+
+ if (!isPeerCertificateValid()) {
+ mEOS = true;
+ mFinalErrno = ECONNREFUSED;
+ sendRecvCallback();
+ }
+ }
+
+ offset += n;
+ }
+
+ mOutBufferPlain.erase(
+ mOutBufferPlain.begin(), mOutBufferPlain.begin() + offset);
+
+ queueOutputDataFromSSL();
+}
+
+bool SSLSocket::isPeerCertificateValid() {
+ if (mMode == Mode::ACCEPT || (mFlags & FLAG_DONT_CHECK_PEER_CERTIFICATE)) {
+ // For now we won't validate the client if we are the server.
+ return true;
+ }
+
+ std::unique_ptr<X509, std::function<void(X509 *)>> cert(
+ SSL_get_peer_certificate(mSSL.get()), X509_free);
+
+ if (!cert) {
+ LOG(ERROR) << "SSLSocket::isPeerCertificateValid no certificate.";
+
+ return false;
+ }
+
+ int res = SSL_get_verify_result(mSSL.get());
+
+ bool valid = (res == X509_V_OK);
+
+ if (!valid) {
+ LOG(ERROR) << "SSLSocket::isPeerCertificateValid invalid certificate.";
+
+ const EVP_MD *digest = EVP_get_digestbyname("sha256");
+
+ unsigned char md[EVP_MAX_MD_SIZE];
+ unsigned int n;
+ int res = X509_digest(cert.get(), digest, md, &n);
+ CHECK_EQ(res, 1);
+
+ std::stringstream ss;
+ for (unsigned int i = 0; i < n; ++i) {
+ if (i > 0) {
+ ss << ":";
+ }
+
+ auto byte = md[i];
+
+ auto nibble = byte >> 4;
+ ss << (char)((nibble < 10) ? ('0' + nibble) : ('A' + nibble - 10));
+
+ nibble = byte & 0x0f;
+ ss << (char)((nibble < 10) ? ('0' + nibble) : ('A' + nibble - 10));
+ }
+
+ LOG(ERROR)
+ << "Server offered certificate w/ fingerprint "
+ << ss.str();
+ }
+
+ return valid;
+}
+
+void SSLSocket::postFlush(RunLoop::AsyncFunction fn) {
+ CHECK(mFlushFn == nullptr);
+
+ if (!mSendPending) {
+ fn();
+ return;
+ }
+
+ mFlushFn = fn;
+}
+
diff --git a/host/frontend/gcastv2/https/ServerSocket.cpp b/host/frontend/gcastv2/https/ServerSocket.cpp
new file mode 100644
index 000000000..1f9501805
--- /dev/null
+++ b/host/frontend/gcastv2/https/ServerSocket.cpp
@@ -0,0 +1,182 @@
+/*
+ * 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.
+ */
+
+#include <https/ServerSocket.h>
+
+#include <https/ClientSocket.h>
+#include <https/RunLoop.h>
+#include <https/SafeCallbackable.h>
+#include <https/Support.h>
+
+#include <android-base/logging.h>
+
+#include <arpa/inet.h>
+#include <fcntl.h>
+#include <iostream>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <unistd.h>
+
+ServerSocket::ServerSocket(
+ HTTPServer *server,
+ TransportType transportType,
+ const char *iface,
+ uint16_t port,
+ const std::optional<std::string> &certificate_pem_path,
+ const std::optional<std::string> &private_key_pem_path)
+ : mInitCheck(-ENODEV),
+ mServer(server),
+ mCertificatePath(certificate_pem_path),
+ mPrivateKeyPath(private_key_pem_path),
+ mSocket(-1),
+ mTransportType(transportType) {
+ if (mTransportType == TransportType::TLS) {
+ CHECK(mCertificatePath.has_value());
+ CHECK(mPrivateKeyPath.has_value());
+ }
+
+ sockaddr_in addr;
+ int res;
+
+ mSocket = socket(PF_INET, SOCK_STREAM, 0);
+ if (mSocket < 0) {
+ mInitCheck = -errno;
+ goto bail;
+ }
+
+ makeFdNonblocking(mSocket);
+
+ static constexpr int yes = 1;
+ res = setsockopt(mSocket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));
+ if (res < 0) {
+ mInitCheck = -errno;
+ goto bail2;
+ }
+
+ memset(addr.sin_zero, 0, sizeof(addr.sin_zero));
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(port);
+ addr.sin_addr.s_addr = inet_addr(iface);
+
+ res = bind(mSocket, reinterpret_cast<sockaddr *>(&addr), sizeof(addr));
+ if (res < 0) {
+ mInitCheck = -errno;
+ goto bail2;
+ }
+
+ res = listen(mSocket, 4);
+ if (res < 0) {
+ mInitCheck = -errno;
+ goto bail2;
+ }
+
+ mInitCheck = 0;
+ return;
+
+bail2:
+ close(mSocket);
+ mSocket = -1;
+
+bail:
+ ;
+}
+
+ServerSocket::~ServerSocket() {
+ if (mSocket >= 0) {
+ close(mSocket);
+ mSocket = -1;
+ }
+}
+
+int ServerSocket::initCheck() const {
+ return mInitCheck;
+}
+
+ServerSocket::TransportType ServerSocket::transportType() const {
+ return mTransportType;
+}
+
+int ServerSocket::run(std::shared_ptr<RunLoop> rl) {
+ if (mInitCheck < 0) {
+ return mInitCheck;
+ }
+
+ if (mRunLoop) {
+ return -EBUSY;
+ }
+
+ mRunLoop = rl;
+ mRunLoop->postSocketRecv(
+ mSocket,
+ makeSafeCallback(this, &ServerSocket::acceptIncomingConnection));
+
+ return 0;
+}
+
+void ServerSocket::acceptIncomingConnection() {
+ sockaddr_in addr;
+ socklen_t addrLen = sizeof(addr);
+
+ int s = accept(mSocket, reinterpret_cast<sockaddr *>(&addr), &addrLen);
+
+ if (s >= 0) {
+ uint32_t ip = ntohl(addr.sin_addr.s_addr);
+
+ LOG(VERBOSE)
+ << "Accepted incoming connection from "
+ << (ip >> 24)
+ << "."
+ << ((ip >> 16) & 0xff)
+ << "."
+ << ((ip >> 8) & 0xff)
+ << "."
+ << (ip & 0xff)
+ << ":"
+ << ntohs(addr.sin_port);
+
+ makeFdNonblocking(s);
+
+ auto clientSocket =
+ std::make_shared<ClientSocket>(mRunLoop, mServer, this, addr, s);
+
+ clientSocket->run();
+
+ mClientSockets.push_back(clientSocket);
+ }
+
+ mRunLoop->postSocketRecv(
+ mSocket,
+ makeSafeCallback(this, &ServerSocket::acceptIncomingConnection));
+}
+
+void ServerSocket::onClientSocketClosed(int sock) {
+ for (size_t i = mClientSockets.size(); i--;) {
+ if (mClientSockets[i]->fd() == sock) {
+ LOG(VERBOSE) << "Closing client connection.";
+ mClientSockets.erase(mClientSockets.begin() + i);
+ break;
+ }
+ }
+}
+
+std::optional<std::string> ServerSocket::certificate_pem_path() const {
+ return mCertificatePath;
+}
+
+std::optional<std::string> ServerSocket::private_key_pem_path() const {
+ return mPrivateKeyPath;
+}
+
diff --git a/host/frontend/gcastv2/https/Support.cpp b/host/frontend/gcastv2/https/Support.cpp
new file mode 100644
index 000000000..013836576
--- /dev/null
+++ b/host/frontend/gcastv2/https/Support.cpp
@@ -0,0 +1,137 @@
+/*
+ * 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.
+ */
+
+#include <https/Support.h>
+
+#include <cassert>
+#include <cstdint>
+#include <cstdio>
+#include <ctype.h>
+#include <fcntl.h>
+#include <sys/errno.h>
+
+void makeFdNonblocking(int fd) {
+ int flags = fcntl(fd, F_GETFL, 0);
+ if (flags < 0) { flags = 0; }
+ DEBUG_ONLY(int res = )fcntl(fd, F_SETFL, flags | O_NONBLOCK);
+ assert(res >= 0);
+}
+
+void hexdump(const void *_data, size_t size) {
+ const uint8_t *data = static_cast<const uint8_t *>(_data);
+
+ size_t offset = 0;
+ while (offset < size) {
+ printf("%08zx: ", offset);
+
+ for (size_t col = 0; col < 16; ++col) {
+ if (offset + col < size) {
+ printf("%02x ", data[offset + col]);
+ } else {
+ printf(" ");
+ }
+
+ if (col == 7) {
+ printf(" ");
+ }
+ }
+
+ printf(" ");
+
+ for (size_t col = 0; col < 16; ++col) {
+ if (offset + col < size && isprint(data[offset + col])) {
+ printf("%c", data[offset + col]);
+ } else if (offset + col < size) {
+ printf(".");
+ }
+ }
+
+ printf("\n");
+
+ offset += 16;
+ }
+}
+
+static char encode6Bit(unsigned x) {
+ static char base64[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+ return base64[x & 63];
+}
+
+void encodeBase64(const void *_data, size_t size, std::string *out) {
+ out->clear();
+ out->reserve(((size+2)/3)*4);
+
+ const uint8_t *data = (const uint8_t *)_data;
+
+ size_t i;
+ for (i = 0; i < (size / 3) * 3; i += 3) {
+ uint8_t x1 = data[i];
+ uint8_t x2 = data[i + 1];
+ uint8_t x3 = data[i + 2];
+
+ out->append(1, encode6Bit(x1 >> 2));
+ out->append(1, encode6Bit((x1 << 4 | x2 >> 4) & 0x3f));
+ out->append(1, encode6Bit((x2 << 2 | x3 >> 6) & 0x3f));
+ out->append(1, encode6Bit(x3 & 0x3f));
+ }
+ switch (size % 3) {
+ case 0:
+ break;
+ case 2:
+ {
+ uint8_t x1 = data[i];
+ uint8_t x2 = data[i + 1];
+ out->append(1, encode6Bit(x1 >> 2));
+ out->append(1, encode6Bit((x1 << 4 | x2 >> 4) & 0x3f));
+ out->append(1, encode6Bit((x2 << 2) & 0x3f));
+ out->append(1, '=');
+ break;
+ }
+ default:
+ {
+ uint8_t x1 = data[i];
+ out->append(1, encode6Bit(x1 >> 2));
+ out->append(1, encode6Bit((x1 << 4) & 0x3f));
+ out->append("==");
+ break;
+ }
+ }
+}
+
+uint16_t U16_AT(const uint8_t *ptr) {
+ return ptr[0] << 8 | ptr[1];
+}
+
+uint32_t U32_AT(const uint8_t *ptr) {
+ return ptr[0] << 24 | ptr[1] << 16 | ptr[2] << 8 | ptr[3];
+}
+
+uint64_t U64_AT(const uint8_t *ptr) {
+ return ((uint64_t)U32_AT(ptr)) << 32 | U32_AT(ptr + 4);
+}
+
+uint16_t U16LE_AT(const uint8_t *ptr) {
+ return ptr[0] | (ptr[1] << 8);
+}
+
+uint32_t U32LE_AT(const uint8_t *ptr) {
+ return ptr[3] << 24 | ptr[2] << 16 | ptr[1] << 8 | ptr[0];
+}
+
+uint64_t U64LE_AT(const uint8_t *ptr) {
+ return ((uint64_t)U32LE_AT(ptr + 4)) << 32 | U32LE_AT(ptr);
+}
diff --git a/host/frontend/gcastv2/https/WebSocketHandler.cpp b/host/frontend/gcastv2/https/WebSocketHandler.cpp
new file mode 100644
index 000000000..fe8c74eba
--- /dev/null
+++ b/host/frontend/gcastv2/https/WebSocketHandler.cpp
@@ -0,0 +1,221 @@
+/*
+ * 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.
+ */
+
+#include <https/WebSocketHandler.h>
+
+#include <https/ClientSocket.h>
+#include <https/Support.h>
+
+#include <iostream>
+#include <sstream>
+
+ssize_t WebSocketHandler::handleRequest(
+ uint8_t *data, size_t size, bool isEOS) {
+ (void)isEOS;
+
+ size_t offset = 0;
+ while (offset + 1 < size) {
+ uint8_t *packet = &data[offset];
+ const size_t avail = size - offset;
+
+ size_t packetOffset = 0;
+ const uint8_t headerByte = packet[packetOffset];
+
+ const bool hasMask = (packet[packetOffset + 1] & 0x80) != 0;
+ size_t payloadLen = packet[packetOffset + 1] & 0x7f;
+ packetOffset += 2;
+
+ if (payloadLen == 126) {
+ if (packetOffset + 1 >= avail) {
+ break;
+ }
+
+ payloadLen = U16_AT(&packet[packetOffset]);
+ packetOffset += 2;
+ } else if (payloadLen == 127) {
+ if (packetOffset + 7 >= avail) {
+ break;
+ }
+
+ payloadLen = U64_AT(&packet[packetOffset]);
+ packetOffset += 8;
+ }
+
+ uint32_t mask = 0;
+ if (hasMask) {
+ if (packetOffset + 3 >= avail) {
+ break;
+ }
+
+ mask = U32_AT(&packet[packetOffset]);
+ packetOffset += 4;
+ }
+
+ if (packetOffset + payloadLen > avail) {
+ break;
+ }
+
+ if (mask) {
+ for (size_t i = 0; i < payloadLen; ++i) {
+ packet[packetOffset + i] ^= ((mask >> (8 * (3 - (i % 4)))) & 0xff);
+ }
+ }
+
+ int err = handleMessage(headerByte, &packet[packetOffset], payloadLen);
+
+ offset += packetOffset + payloadLen;
+
+ if (err < 0) {
+ return err;
+ }
+ }
+
+ return offset;
+}
+
+bool WebSocketHandler::isConnected() {
+ return mOutputCallback != nullptr || mClientSocket.lock() != nullptr;
+}
+
+void WebSocketHandler::setClientSocket(std::weak_ptr<ClientSocket> clientSocket) {
+ mClientSocket = clientSocket;
+}
+
+void WebSocketHandler::setOutputCallback(
+ const sockaddr_in &remoteAddr, OutputCallback fn) {
+ mOutputCallback = fn;
+ mRemoteAddr = remoteAddr;
+}
+
+int WebSocketHandler::handleMessage(
+ uint8_t headerByte, const uint8_t *msg, size_t len) {
+ std::cerr
+ << "WebSocketHandler::handleMessage(0x"
+ << std::hex
+ << (unsigned)headerByte
+ << std::dec
+ << ")"
+ << std::endl;
+
+ hexdump(msg, len);
+
+ const uint8_t opcode = headerByte & 0x0f;
+ if (opcode == 8) {
+ // Connection close.
+ return -1;
+ }
+
+ return 0;
+}
+
+int WebSocketHandler::sendMessage(
+ const void *data, size_t size, SendMode mode) {
+ static constexpr bool kUseMask = false;
+
+ size_t numHeaderBytes = 2 + (kUseMask ? 4 : 0);
+ if (size > 65535) {
+ numHeaderBytes += 8;
+ } else if (size > 125) {
+ numHeaderBytes += 2;
+ }
+
+ static constexpr uint8_t kOpCodeBySendMode[] = {
+ 0x1, // text
+ 0x2, // binary
+ 0x8, // closeConnection
+ };
+
+ auto opcode = kOpCodeBySendMode[static_cast<uint8_t>(mode)];
+
+ std::unique_ptr<uint8_t[]> buffer(new uint8_t[numHeaderBytes + size]);
+ uint8_t *msg = buffer.get();
+ msg[0] = 0x80 | opcode; // FIN==1
+ msg[1] = kUseMask ? 0x80 : 0x00;
+
+ if (size > 65535) {
+ msg[1] |= 127;
+ msg[2] = 0x00;
+ msg[3] = 0x00;
+ msg[4] = 0x00;
+ msg[5] = 0x00;
+ msg[6] = (size >> 24) & 0xff;
+ msg[7] = (size >> 16) & 0xff;
+ msg[8] = (size >> 8) & 0xff;
+ msg[9] = size & 0xff;
+ } else if (size > 125) {
+ msg[1] |= 126;
+ msg[2] = (size >> 8) & 0xff;
+ msg[3] = size & 0xff;
+ } else {
+ msg[1] |= size;
+ }
+
+ if (kUseMask) {
+ uint32_t mask = rand();
+ msg[numHeaderBytes - 4] = (mask >> 24) & 0xff;
+ msg[numHeaderBytes - 3] = (mask >> 16) & 0xff;
+ msg[numHeaderBytes - 2] = (mask >> 8) & 0xff;
+ msg[numHeaderBytes - 1] = mask & 0xff;
+
+ for (size_t i = 0; i < size; ++i) {
+ msg[numHeaderBytes + i] =
+ ((const uint8_t *)data)[i]
+ ^ ((mask >> (8 * (3 - (i % 4)))) & 0xff);
+ }
+ } else {
+ memcpy(&msg[numHeaderBytes], data, size);
+ }
+
+ if (mOutputCallback) {
+ mOutputCallback(msg, numHeaderBytes + size);
+ } else {
+ auto clientSocket = mClientSocket.lock();
+ if (clientSocket) {
+ clientSocket->queueOutputData(msg, numHeaderBytes + size);
+ }
+ }
+
+ return 0;
+}
+
+std::string WebSocketHandler::remoteHost() const {
+ sockaddr_in remoteAddr;
+
+ if (mOutputCallback) {
+ remoteAddr = mRemoteAddr;
+ } else {
+ auto clientSocket = mClientSocket.lock();
+ if (clientSocket) {
+ remoteAddr = clientSocket->remoteAddr();
+ } else {
+ return "0.0.0.0";
+ }
+ }
+
+ const uint32_t ipAddress = ntohl(remoteAddr.sin_addr.s_addr);
+
+ std::stringstream ss;
+ ss << (ipAddress >> 24)
+ << "."
+ << ((ipAddress >> 16) & 0xff)
+ << "."
+ << ((ipAddress >> 8) & 0xff)
+ << "."
+ << (ipAddress & 0xff);
+
+ return ss.str();
+}
+
diff --git a/host/frontend/webrtc_operator/certs/create_certs.sh b/host/frontend/gcastv2/https/certs/create_certs.sh
index fefc27578..9f85e4047 100755
--- a/host/frontend/webrtc_operator/certs/create_certs.sh
+++ b/host/frontend/gcastv2/https/certs/create_certs.sh
@@ -3,15 +3,15 @@
# As explained in
# https://gist.github.com/darrenjs/4645f115d10aa4b5cebf57483ec82eca
-openssl genrsa -des3 -passout pass:xxxx -out server.pass.key 2048
-openssl rsa -passin pass:xxxx -in server.pass.key -out server.key
+openssl genrsa -des3 -passout pass:x -out server.pass.key 2048
+openssl rsa -passin pass:x -in server.pass.key -out server.key
rm -f server.pass.key
openssl req \
-subj "/C=US/ST=California/L=Santa Clara/O=Beyond Aggravated/CN=localhost" \
-new -key server.key -out server.csr
-openssl x509 -req -sha256 -days 99999 -in server.csr -signkey server.key -out server.crt
+openssl x509 -req -sha256 -days 365 -in server.csr -signkey server.key -out server.crt
rm -f server.csr
# Now create the list of certificates we trust as a client.
diff --git a/host/frontend/gcastv2/https/certs/server.crt b/host/frontend/gcastv2/https/certs/server.crt
new file mode 100644
index 000000000..93108a7e9
--- /dev/null
+++ b/host/frontend/gcastv2/https/certs/server.crt
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDVzCCAj8CFBlyltiL2iwsm/yiGCMKdiHNfnhkMA0GCSqGSIb3DQEBCwUAMGgx
+CzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRQwEgYDVQQHDAtTYW50
+YSBDbGFyYTEaMBgGA1UECgwRQmV5b25kIEFnZ3JhdmF0ZWQxEjAQBgNVBAMMCWxv
+Y2FsaG9zdDAeFw0xOTA4MjExNjQzNTdaFw0yMDA4MjAxNjQzNTdaMGgxCzAJBgNV
+BAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRQwEgYDVQQHDAtTYW50YSBDbGFy
+YTEaMBgGA1UECgwRQmV5b25kIEFnZ3JhdmF0ZWQxEjAQBgNVBAMMCWxvY2FsaG9z
+dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANspCLPC//6LNZIArmxS
+YRrojSPiizASN0svdh1376Bgp9KjUw1NFQhMcq+IobGJjXlxvTqRiXaf3P0dJKZV
+Mdcyc9AOmCNwH8H86OmZTHwV3MdVVqPH2eYl+otWa2eLh8A0J7eN/xn9cl7xtG8u
+UqWc/0Qna7bp4kUOq70M4Kn1NGvlLhtT6jo6DJrpZTj64TTB2c420e86K6UBWSDW
+KPLmarV1mDrYo7gxSu1zqLssYit/X8Xdi8ESQ0WRe1QWNUxMk7qLFTQh1fSUGv6a
+pjWLLrGK9DeYdHsdXX2ttRAlDUtllGctypjCKc0Wcg4ZGfSXZoTlV2k8aEyjYFxu
+VbkCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAwo6JLn09RZsTbMoMeCY6JXRMCff8
+mKN3gUao4ob8r6dmZjGDzhBK4oc04OZ28j/5VmnYnLgY0g/+MzbY7hCy35gee/rr
+6Z540m9vYtOrAKyquoOxrS43SciZMjpuL1PKT7Cvo7b6B26x81WSDLkms2NMltUZ
+V9Ayal61cIZOEsUd9JQesYrchoYqJjlqWhGcEe/Gy0O6rTt+ZaHHxS3RwCaQTDfw
+q3d2Z+WozMlOkFGvqhflI7uNuxiAFlwIrvWpn/k//f13x+jFfNLOUUPnzgFPxtWN
+v+yNlVX8KSG5mjgBrDKua5P8s+7zzmoprQk6+/SkUyieS6GgPO/aUF9lPg==
+-----END CERTIFICATE-----
diff --git a/host/frontend/gcastv2/https/certs/server.key b/host/frontend/gcastv2/https/certs/server.key
new file mode 100644
index 000000000..3c49d41d0
--- /dev/null
+++ b/host/frontend/gcastv2/https/certs/server.key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEA2ykIs8L//os1kgCubFJhGuiNI+KLMBI3Sy92HXfvoGCn0qNT
+DU0VCExyr4ihsYmNeXG9OpGJdp/c/R0kplUx1zJz0A6YI3Afwfzo6ZlMfBXcx1VW
+o8fZ5iX6i1ZrZ4uHwDQnt43/Gf1yXvG0by5SpZz/RCdrtuniRQ6rvQzgqfU0a+Uu
+G1PqOjoMmullOPrhNMHZzjbR7zorpQFZINYo8uZqtXWYOtijuDFK7XOouyxiK39f
+xd2LwRJDRZF7VBY1TEyTuosVNCHV9JQa/pqmNYsusYr0N5h0ex1dfa21ECUNS2WU
+Zy3KmMIpzRZyDhkZ9JdmhOVXaTxoTKNgXG5VuQIDAQABAoIBADSgKNfJlmEQGoAB
+q+CU835bozCfwJ59cUubjPhMiXzwWLwqvdGu1cMVYGCoJXOVPSSRXEgJFIIopw8c
+hWVvhbVQByFJr9yqmuWhDmixh/0v3sD6zAAuCDPMoNn+mXHWvnU30OWxsjUSd/k2
+fwZHkE72YRGDicj1ZoEAodqWkggdSIDSxenT7U7SdoIMzEX7s68g9rt338zjgHdx
+r8qYvYqSB6qufNk8vQ/Rq5cz6gBNCrqrJkoC+pzZY0Ps61fEOX7HiyjAxmUSHViq
+6d1+BcAhtoXCy47WmuUH5XD0JixaYtrwon+LTxS/57X9Te+iKFCeLeTkEL++w9TW
+U92DEQECgYEA8MrKzdH79i4dduIIVecwvOE1EPb3Clz89bihFK3aRMPQn1sRMoLB
+glOLnygAn6m3FvIBQYOLwu77+Hfu20Wn0AHHboZ6TOzOLw14bIegA8JUpWmGFKp8
+QGRLBCbFDe/Jzldbmnz5+czmfGC976ZnrAcltchliLqIY51Tlcy7iWECgYEA6QB9
+lDfwpzRHkv9Higcr5ek/jJh6yxa/lolJ8da18HXz8CNsESIUQzQ5NafiH0UKmHNb
+lU0d3XNUWbciauIkZBp/hI7a3qpBvBpMIibhVbbYZwffHIcB2sl9aMNvbRepGSin
+8RhS1/gjYGpDZUFAb9nI+Q9ds1LhtDuVNYWlc1kCgYBnFstA1vfCa/fdX+Qlsvcg
+xmJLww/89dau9L6x9cSO0C7PKtPwBh8GxvHtz9iEgsqKHk3/WGxLprllpSMz6Vxx
+J3HUlepiaLfVWTUHcgFF2rsWnljzHBJaFxYuztJqpxCFMM1dFMiI8/pxoZFvupSE
+CANTElq18PZXf5G7fo2DwQKBgEmEFBteAxpejm69CQ9t79Xc4GY1/hhyFwUiUChz
+/HfgX5VXN9O4EviZU6uwStJe8FblnvHeoRusNeMQu1VKAP1stutWP4yd35vAGGF2
+LwbiaCkp/KV9m4IyrNUPROsA2iPMBiE18X2fF1pmbNlX20LvTk/3HzNjZT9+xTdb
+8bYRAoGBANKwX+QCpCQCNf+hxTPUjf4reShz5w/Wpk2xPxa+FnVxe3jtyxAOZ5uW
+lUWe7UXyNSWh8oiH8japwMkgN+dGnrzW5rMiXwpBFROAqgblRdbvLafebyGQBwAV
+2l6G4RfgG7LJAWsHu0rA74ZwOknfXfebxtrcLhfU7UYdl7fus71D
+-----END RSA PRIVATE KEY-----
diff --git a/host/frontend/gcastv2/https/certs/trusted.pem b/host/frontend/gcastv2/https/certs/trusted.pem
new file mode 100644
index 000000000..3429b7562
--- /dev/null
+++ b/host/frontend/gcastv2/https/certs/trusted.pem
@@ -0,0 +1,70 @@
+Certificate:
+ Data:
+ Version: 1 (0x0)
+ Serial Number:
+ 19:72:96:d8:8b:da:2c:2c:9b:fc:a2:18:23:0a:76:21:cd:7e:78:64
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C = US, ST = California, L = Santa Clara, O = Beyond Aggravated, CN = localhost
+ Validity
+ Not Before: Aug 21 16:43:57 2019 GMT
+ Not After : Aug 20 16:43:57 2020 GMT
+ Subject: C = US, ST = California, L = Santa Clara, O = Beyond Aggravated, CN = localhost
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (2048 bit)
+ Modulus:
+ 00:db:29:08:b3:c2:ff:fe:8b:35:92:00:ae:6c:52:
+ 61:1a:e8:8d:23:e2:8b:30:12:37:4b:2f:76:1d:77:
+ ef:a0:60:a7:d2:a3:53:0d:4d:15:08:4c:72:af:88:
+ a1:b1:89:8d:79:71:bd:3a:91:89:76:9f:dc:fd:1d:
+ 24:a6:55:31:d7:32:73:d0:0e:98:23:70:1f:c1:fc:
+ e8:e9:99:4c:7c:15:dc:c7:55:56:a3:c7:d9:e6:25:
+ fa:8b:56:6b:67:8b:87:c0:34:27:b7:8d:ff:19:fd:
+ 72:5e:f1:b4:6f:2e:52:a5:9c:ff:44:27:6b:b6:e9:
+ e2:45:0e:ab:bd:0c:e0:a9:f5:34:6b:e5:2e:1b:53:
+ ea:3a:3a:0c:9a:e9:65:38:fa:e1:34:c1:d9:ce:36:
+ d1:ef:3a:2b:a5:01:59:20:d6:28:f2:e6:6a:b5:75:
+ 98:3a:d8:a3:b8:31:4a:ed:73:a8:bb:2c:62:2b:7f:
+ 5f:c5:dd:8b:c1:12:43:45:91:7b:54:16:35:4c:4c:
+ 93:ba:8b:15:34:21:d5:f4:94:1a:fe:9a:a6:35:8b:
+ 2e:b1:8a:f4:37:98:74:7b:1d:5d:7d:ad:b5:10:25:
+ 0d:4b:65:94:67:2d:ca:98:c2:29:cd:16:72:0e:19:
+ 19:f4:97:66:84:e5:57:69:3c:68:4c:a3:60:5c:6e:
+ 55:b9
+ Exponent: 65537 (0x10001)
+ Signature Algorithm: sha256WithRSAEncryption
+ c2:8e:89:2e:7d:3d:45:9b:13:6c:ca:0c:78:26:3a:25:74:4c:
+ 09:f7:fc:98:a3:77:81:46:a8:e2:86:fc:af:a7:66:66:31:83:
+ ce:10:4a:e2:87:34:e0:e6:76:f2:3f:f9:56:69:d8:9c:b8:18:
+ d2:0f:fe:33:36:d8:ee:10:b2:df:98:1e:7b:fa:eb:e9:9e:78:
+ d2:6f:6f:62:d3:ab:00:ac:aa:ba:83:b1:ad:2e:37:49:c8:99:
+ 32:3a:6e:2f:53:ca:4f:b0:af:a3:b6:fa:07:6e:b1:f3:55:92:
+ 0c:b9:26:b3:63:4c:96:d5:19:57:d0:32:6a:5e:b5:70:86:4e:
+ 12:c5:1d:f4:94:1e:b1:8a:dc:86:86:2a:26:39:6a:5a:11:9c:
+ 11:ef:c6:cb:43:ba:ad:3b:7e:65:a1:c7:c5:2d:d1:c0:26:90:
+ 4c:37:f0:ab:77:76:67:e5:a8:cc:c9:4e:90:51:af:aa:17:e5:
+ 23:bb:8d:bb:18:80:16:5c:08:ae:f5:a9:9f:f9:3f:fd:fd:77:
+ c7:e8:c5:7c:d2:ce:51:43:e7:ce:01:4f:c6:d5:8d:bf:ec:8d:
+ 95:55:fc:29:21:b9:9a:38:01:ac:32:ae:6b:93:fc:b3:ee:f3:
+ ce:6a:29:ad:09:3a:fb:f4:a4:53:28:9e:4b:a1:a0:3c:ef:da:
+ 50:5f:65:3e
+-----BEGIN CERTIFICATE-----
+MIIDVzCCAj8CFBlyltiL2iwsm/yiGCMKdiHNfnhkMA0GCSqGSIb3DQEBCwUAMGgx
+CzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRQwEgYDVQQHDAtTYW50
+YSBDbGFyYTEaMBgGA1UECgwRQmV5b25kIEFnZ3JhdmF0ZWQxEjAQBgNVBAMMCWxv
+Y2FsaG9zdDAeFw0xOTA4MjExNjQzNTdaFw0yMDA4MjAxNjQzNTdaMGgxCzAJBgNV
+BAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRQwEgYDVQQHDAtTYW50YSBDbGFy
+YTEaMBgGA1UECgwRQmV5b25kIEFnZ3JhdmF0ZWQxEjAQBgNVBAMMCWxvY2FsaG9z
+dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANspCLPC//6LNZIArmxS
+YRrojSPiizASN0svdh1376Bgp9KjUw1NFQhMcq+IobGJjXlxvTqRiXaf3P0dJKZV
+Mdcyc9AOmCNwH8H86OmZTHwV3MdVVqPH2eYl+otWa2eLh8A0J7eN/xn9cl7xtG8u
+UqWc/0Qna7bp4kUOq70M4Kn1NGvlLhtT6jo6DJrpZTj64TTB2c420e86K6UBWSDW
+KPLmarV1mDrYo7gxSu1zqLssYit/X8Xdi8ESQ0WRe1QWNUxMk7qLFTQh1fSUGv6a
+pjWLLrGK9DeYdHsdXX2ttRAlDUtllGctypjCKc0Wcg4ZGfSXZoTlV2k8aEyjYFxu
+VbkCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAwo6JLn09RZsTbMoMeCY6JXRMCff8
+mKN3gUao4ob8r6dmZjGDzhBK4oc04OZ28j/5VmnYnLgY0g/+MzbY7hCy35gee/rr
+6Z540m9vYtOrAKyquoOxrS43SciZMjpuL1PKT7Cvo7b6B26x81WSDLkms2NMltUZ
+V9Ayal61cIZOEsUd9JQesYrchoYqJjlqWhGcEe/Gy0O6rTt+ZaHHxS3RwCaQTDfw
+q3d2Z+WozMlOkFGvqhflI7uNuxiAFlwIrvWpn/k//f13x+jFfNLOUUPnzgFPxtWN
+v+yNlVX8KSG5mjgBrDKua5P8s+7zzmoprQk6+/SkUyieS6GgPO/aUF9lPg==
+-----END CERTIFICATE-----
diff --git a/host/frontend/gcastv2/https/content/index.html b/host/frontend/gcastv2/https/content/index.html
new file mode 100644
index 000000000..081f46a08
--- /dev/null
+++ b/host/frontend/gcastv2/https/content/index.html
@@ -0,0 +1,19 @@
+<script>
+
+var sock = new WebSocket("wss://localhost:8443/control", "protocolOne");
+
+sock.onopen = function(event) {
+ // Close connection after 5 secs.
+ // setTimeout(function() { sock.close(); }, 5000);
+
+ sock.send("Here's some sample text");
+}
+
+sock.onmessage = function(event) {
+ console.log(event.data);
+}
+
+</script>
+
+<h1>Test</h1>
+
diff --git a/host/frontend/gcastv2/https/include/https/BaseConnection.h b/host/frontend/gcastv2/https/include/https/BaseConnection.h
new file mode 100644
index 000000000..7dd7dc6a7
--- /dev/null
+++ b/host/frontend/gcastv2/https/include/https/BaseConnection.h
@@ -0,0 +1,61 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <https/BufferedSocket.h>
+#include <https/RunLoop.h>
+
+#include <memory>
+#include <vector>
+
+struct BaseConnection : public std::enable_shared_from_this<BaseConnection> {
+ explicit BaseConnection(std::shared_ptr<RunLoop> runLoop, int sock);
+ virtual ~BaseConnection() = default;
+
+ void run();
+
+ BaseConnection(const BaseConnection &) = delete;
+ BaseConnection &operator=(const BaseConnection &) = delete;
+
+protected:
+ // Return -EAGAIN to indicate that not enough data was provided (yet).
+ // Return a positive (> 0) value to drain some amount of data.
+ // Return values <= 0 are considered an error.
+ virtual ssize_t processClientRequest(const void *data, size_t size) = 0;
+
+ virtual void onDisconnect(int err) = 0;
+
+ void send(const void *_data, size_t size);
+
+ int fd() const;
+
+private:
+ std::shared_ptr<RunLoop> mRunLoop;
+
+ std::unique_ptr<BufferedSocket> mSocket;
+
+ std::vector<uint8_t> mInBuffer;
+ size_t mInBufferLen;
+
+ bool mSendPending;
+ std::vector<uint8_t> mOutBuffer;
+
+ void receiveClientRequest();
+ void sendOutputData();
+
+ void onClientRequest();
+};
diff --git a/host/frontend/gcastv2/https/include/https/BufferedSocket.h b/host/frontend/gcastv2/https/include/https/BufferedSocket.h
new file mode 100644
index 000000000..f6095ff20
--- /dev/null
+++ b/host/frontend/gcastv2/https/include/https/BufferedSocket.h
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <https/RunLoop.h>
+
+#include <sys/socket.h>
+
+struct BufferedSocket {
+ explicit BufferedSocket(std::shared_ptr<RunLoop> rl, int sock);
+ virtual ~BufferedSocket();
+
+ BufferedSocket(const BufferedSocket &) = delete;
+ BufferedSocket &operator=(const BufferedSocket &) = delete;
+
+ virtual void postRecv(RunLoop::AsyncFunction fn) = 0;
+ virtual void postSend(RunLoop::AsyncFunction fn) = 0;
+
+ ssize_t recv(void *data, size_t size) {
+ return recvfrom(data, size, nullptr, nullptr);
+ }
+
+ virtual ssize_t recvfrom(
+ void *data,
+ size_t size,
+ sockaddr *address,
+ socklen_t *addressLen) = 0;
+
+ ssize_t send(const void *data, size_t size) {
+ return sendto(data, size, nullptr, 0);
+ }
+
+ virtual ssize_t sendto(
+ const void *data,
+ size_t size,
+ const sockaddr *addr,
+ socklen_t addrLen) = 0;
+
+ virtual void postFlush(RunLoop::AsyncFunction fn) = 0;
+
+ int fd() const;
+
+protected:
+ RunLoop *runLoop();
+
+private:
+ std::shared_ptr<RunLoop> mRunLoop;
+ int mSock;
+};
diff --git a/host/frontend/gcastv2/https/include/https/ClientSocket.h b/host/frontend/gcastv2/https/include/https/ClientSocket.h
new file mode 100644
index 000000000..fd29daf8c
--- /dev/null
+++ b/host/frontend/gcastv2/https/include/https/ClientSocket.h
@@ -0,0 +1,86 @@
+/*
+ * 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.
+ */
+
+#include <https/BufferedSocket.h>
+
+#include <https/WebSocketHandler.h>
+
+#include <arpa/inet.h>
+#include <vector>
+#include <memory>
+
+#include <https/PlainSocket.h>
+#include <https/SSLSocket.h>
+
+struct HTTPServer;
+struct RunLoop;
+struct ServerSocket;
+
+struct ClientSocket : public std::enable_shared_from_this<ClientSocket> {
+ explicit ClientSocket(
+ std::shared_ptr<RunLoop> rl,
+ HTTPServer *server,
+ ServerSocket *parent,
+ const sockaddr_in &addr,
+ int sock);
+
+ ClientSocket(const ClientSocket &) = delete;
+ ClientSocket &operator=(const ClientSocket &) = delete;
+
+ void run();
+
+ int fd() const;
+
+ void queueResponse(const std::string &response, const std::string &body);
+ void setWebSocketHandler(std::shared_ptr<WebSocketHandler> handler);
+
+ void queueOutputData(const uint8_t *data, size_t size);
+
+ sockaddr_in remoteAddr() const;
+
+private:
+ std::shared_ptr<RunLoop> mRunLoop;
+ HTTPServer *mServer;
+ ServerSocket *mParent;
+ sockaddr_in mRemoteAddr;
+
+ std::shared_ptr<BufferedSocket> mImplPlain;
+ std::shared_ptr<SSLSocket> mImplSSL;
+
+ std::vector<uint8_t> mInBuffer;
+ size_t mInBufferLen;
+
+ std::vector<uint8_t> mOutBuffer;
+ bool mSendPending;
+
+ bool mDisconnecting;
+
+ std::shared_ptr<WebSocketHandler> mWebSocketHandler;
+
+ void handleIncomingData();
+
+ // Returns true iff the client should close the connection.
+ bool handleRequest(bool isEOS);
+
+ void sendOutputData();
+
+ void disconnect();
+ void finishDisconnect();
+
+ BufferedSocket *getImpl() const {
+ return mImplSSL ? mImplSSL.get() : mImplPlain.get();
+ }
+};
diff --git a/host/frontend/gcastv2/https/include/https/HTTPClientConnection.h b/host/frontend/gcastv2/https/include/https/HTTPClientConnection.h
new file mode 100644
index 000000000..357136fa8
--- /dev/null
+++ b/host/frontend/gcastv2/https/include/https/HTTPClientConnection.h
@@ -0,0 +1,73 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <arpa/inet.h>
+#include <https/BufferedSocket.h>
+#include <https/ServerSocket.h>
+#include <https/WebSocketHandler.h>
+
+#include <memory>
+#include <optional>
+#include <string>
+
+struct HTTPClientConnection
+ : public std::enable_shared_from_this<HTTPClientConnection> {
+
+ explicit HTTPClientConnection(
+ std::shared_ptr<RunLoop> rl,
+ std::shared_ptr<WebSocketHandler> webSocketHandler,
+ std::string_view path,
+ ServerSocket::TransportType transportType,
+ const std::optional<std::string> &trusted_pem_path = std::nullopt);
+
+ HTTPClientConnection(const HTTPClientConnection &) = delete;
+ HTTPClientConnection &operator=(const HTTPClientConnection &) = delete;
+
+ int initCheck() const;
+
+ int connect(const char *host, uint16_t port);
+
+private:
+ int mInitCheck;
+
+ std::shared_ptr<RunLoop> mRunLoop;
+ std::shared_ptr<WebSocketHandler> mWebSocketHandler;
+ std::string mPath;
+ ServerSocket::TransportType mTransportType;
+ std::shared_ptr<BufferedSocket> mImpl;
+
+ std::vector<uint8_t> mOutBuffer;
+ bool mSendPending;
+
+ std::vector<uint8_t> mInBuffer;
+ size_t mInBufferLen;
+
+ sockaddr_in mRemoteAddr;
+
+ bool mWebSocketMode;
+
+ void sendRequest();
+ void receiveResponse();
+
+ // Returns true iff response was received fully.
+ bool handleResponse(bool isEOS);
+
+ void queueOutputData(const uint8_t *data, size_t size);
+ void sendOutputData();
+};
+
diff --git a/host/frontend/gcastv2/https/include/https/HTTPRequestResponse.h b/host/frontend/gcastv2/https/include/https/HTTPRequestResponse.h
new file mode 100644
index 000000000..e353cbc61
--- /dev/null
+++ b/host/frontend/gcastv2/https/include/https/HTTPRequestResponse.h
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <map>
+#include <string>
+#include <string_view>
+
+struct HTTPRequestResponse {
+ explicit HTTPRequestResponse();
+ virtual ~HTTPRequestResponse() = default;
+
+ HTTPRequestResponse(const HTTPRequestResponse &) = delete;
+ HTTPRequestResponse &operator=(const HTTPRequestResponse &) = delete;
+
+ int setTo(const uint8_t *data, size_t size);
+ int initCheck() const;
+
+ bool getHeaderField(std::string_view key, std::string *value) const;
+
+ size_t getContentLength() const;
+
+protected:
+ virtual bool parseRequestResponseLine(const std::string &line) = 0;
+
+private:
+ struct CaseInsensitiveCompare {
+ bool operator()(const std::string &a, const std::string &b) const {
+ return strcasecmp(a.c_str(), b.c_str()) < 0;
+ }
+ };
+
+ int mInitCheck;
+
+ size_t mContentLength;
+
+ std::map<std::string, std::string, CaseInsensitiveCompare> mHeaders;
+};
+
+struct HTTPRequest : public HTTPRequestResponse {
+ std::string getMethod() const;
+ std::string getPath() const;
+ std::string getVersion() const;
+
+protected:
+ bool parseRequestResponseLine(const std::string &line) override;
+
+private:
+ std::string mMethod;
+ std::string mPath;
+ std::string mVersion;
+};
+
+struct HTTPResponse : public HTTPRequestResponse {
+ std::string getVersion() const;
+ int32_t getStatusCode() const;
+ std::string getStatusMessage() const;
+
+protected:
+ bool parseRequestResponseLine(const std::string &line) override;
+
+private:
+ std::string mVersion;
+ std::string mStatusMessage;
+ int32_t mStatusCode;
+};
+
diff --git a/host/frontend/gcastv2/https/include/https/HTTPServer.h b/host/frontend/gcastv2/https/include/https/HTTPServer.h
new file mode 100644
index 000000000..d003e8788
--- /dev/null
+++ b/host/frontend/gcastv2/https/include/https/HTTPServer.h
@@ -0,0 +1,110 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <https/ServerSocket.h>
+#include <https/WebSocketHandler.h>
+
+#include <functional>
+#include <mutex>
+#include <optional>
+#include <string>
+#include <unordered_map>
+#include <variant>
+#include <vector>
+
+struct HTTPRequest;
+
+struct HTTPServer {
+ explicit HTTPServer(
+ std::shared_ptr<RunLoop> runLoop,
+ const char *iface = nullptr, // defaults to 0.0.0.0, i.e. INADDR_ANY
+ uint16_t port = 8443,
+ ServerSocket::TransportType transportType =
+ ServerSocket::TransportType::TLS,
+ const std::optional<std::string> &certificate_pem_path =
+ std::nullopt,
+ const std::optional<std::string> &private_key_pem_path =
+ std::nullopt);
+
+ HTTPServer(const HTTPServer &) = delete;
+ HTTPServer &operator=(const HTTPServer &) = delete;
+
+ uint16_t getLocalPort() const;
+
+ void run();
+
+ // Returns true iff the client should close the connection.
+ bool handleSingleRequest(
+ ClientSocket *client, const uint8_t *data, size_t size, bool isEOS);
+
+ void addStaticFile(
+ const char *at,
+ const char *path,
+ std::optional<std::string> mimeType = std::nullopt);
+
+ void addStaticContent(
+ const char *at,
+ const void *data,
+ size_t size,
+ std::optional<std::string> mimeType = std::nullopt);
+
+ using WebSocketHandlerFactory =
+ std::function<std::pair<int32_t, std::shared_ptr<WebSocketHandler>>()>;
+
+ void addWebSocketHandlerFactory(
+ const char *at, WebSocketHandlerFactory factory);
+
+ std::optional<std::string> certificate_pem_path() const;
+ std::optional<std::string> private_key_pem_path() const;
+
+private:
+ struct StaticFileInfo {
+ std::variant<std::string, std::vector<uint8_t>> mPathOrContent;
+ std::optional<std::string> mMimeType;
+ };
+
+ std::shared_ptr<RunLoop> mRunLoop;
+ uint16_t mLocalPort;
+
+ std::shared_ptr<ServerSocket> mSocketTLS;
+
+ // Protects mStaticFiles and mWebSocketHandlerFactories below.
+ std::mutex mContentLock;
+
+ std::unordered_map<std::string, StaticFileInfo> mStaticFiles;
+
+ std::unordered_map<std::string, WebSocketHandlerFactory>
+ mWebSocketHandlerFactories;
+
+ void handleWebSocketRequest(
+ ClientSocket *clientSocket,
+ WebSocketHandlerFactory factory,
+ const HTTPRequest &request,
+ int32_t *httpResultCode,
+ std::unordered_map<std::string, std::string> *responseHeaders,
+ std::string *body);
+
+ void handleStaticFileRequest(
+ const StaticFileInfo &info,
+ const HTTPRequest &request,
+ int32_t *httpResultCode,
+ std::unordered_map<std::string, std::string> *responseHeaders,
+ std::string *body);
+
+ static std::string GuessMimeType(const std::string &path);
+};
diff --git a/host/frontend/gcastv2/https/include/https/PlainSocket.h b/host/frontend/gcastv2/https/include/https/PlainSocket.h
new file mode 100644
index 000000000..634c5a79b
--- /dev/null
+++ b/host/frontend/gcastv2/https/include/https/PlainSocket.h
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <https/BufferedSocket.h>
+
+struct PlainSocket : public BufferedSocket {
+ explicit PlainSocket(std::shared_ptr<RunLoop> rl, int sock);
+
+ PlainSocket(const PlainSocket &) = delete;
+ PlainSocket &operator=(const PlainSocket &) = delete;
+
+ void postRecv(RunLoop::AsyncFunction fn) override;
+ void postSend(RunLoop::AsyncFunction fn) override;
+
+ ssize_t recvfrom(
+ void *data,
+ size_t size,
+ sockaddr *address,
+ socklen_t *addressLen) override;
+
+ ssize_t sendto(
+ const void *data,
+ size_t size,
+ const sockaddr *addr,
+ socklen_t addrLen) override;
+
+ void postFlush(RunLoop::AsyncFunction fn) override;
+};
diff --git a/host/frontend/gcastv2/https/include/https/RunLoop.h b/host/frontend/gcastv2/https/include/https/RunLoop.h
new file mode 100644
index 000000000..7987cdeb9
--- /dev/null
+++ b/host/frontend/gcastv2/https/include/https/RunLoop.h
@@ -0,0 +1,122 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <atomic>
+#include <chrono>
+#include <deque>
+#include <functional>
+#include <map>
+#include <memory>
+#include <mutex>
+#include <optional>
+#include <poll.h>
+#include <string>
+#include <string_view>
+#include <thread>
+#include <vector>
+
+#include <sys/select.h>
+
+struct MainRunLoop;
+
+struct RunLoop {
+ explicit RunLoop(std::string_view name);
+ ~RunLoop();
+
+ static std::shared_ptr<RunLoop> main();
+
+ // For public use on the main RunLoop only.
+ void stop();
+ void run();
+
+ RunLoop(const RunLoop &) = delete;
+ RunLoop &operator=(const RunLoop &) = delete;
+
+ typedef std::function<void()> AsyncFunction;
+ typedef int32_t Token;
+
+ Token post(AsyncFunction fn);
+ // Post a callback to the run loop and wait for it to be executed. Returns
+ // whether it actually waited for the execution to happen (if posted from
+ // the same run loop's thread it won't wait to avoid a deadlock).
+ // WARNING: This function can cause the calling thread to wait forever if
+ // the run loop is stopped.
+ bool postAndAwait(AsyncFunction fn);
+
+ Token postWithDelay(
+ std::chrono::steady_clock::duration delay, AsyncFunction fn);
+
+ // Returns true iff matching event was cancelled.
+ bool cancelToken(Token token);
+
+ void postSocketRecv(int sock, AsyncFunction fn);
+ void postSocketSend(int sock, AsyncFunction fn);
+ void cancelSocket(int sock);
+
+ bool isCurrentThread() const;
+
+private:
+ friend struct MainRunLoop;
+
+ struct QueueElem {
+ std::optional<std::chrono::steady_clock::time_point> mWhen;
+ AsyncFunction mFn;
+ Token mToken;
+
+ bool operator<=(const QueueElem &other) const;
+ };
+
+ struct SocketCallbacks {
+ AsyncFunction mRecvFn;
+ AsyncFunction mSendFn;
+ size_t mPollFdIndex;
+ };
+
+ enum class InfoType {
+ RECV,
+ SEND,
+ CANCEL,
+ };
+
+ struct AddSocketCallbackInfo {
+ int mSock;
+ InfoType mType;
+ AsyncFunction mFn;
+ };
+
+ std::string mName;
+
+ int mControlFds[2];
+
+ std::mutex mLock;
+ std::deque<QueueElem> mQueue;
+ std::vector<AddSocketCallbackInfo> mAddInfos;
+
+ std::atomic<bool> mDone;
+ std::thread mThread;
+ pthread_t mPThread;
+
+ std::atomic<Token> mNextToken;
+
+ explicit RunLoop(); // constructor for the main RunLoop.
+
+ void interrupt();
+ void insert(const QueueElem &elem);
+ void addPollFd_l(int sock);
+};
+
diff --git a/host/frontend/gcastv2/https/include/https/SSLSocket.h b/host/frontend/gcastv2/https/include/https/SSLSocket.h
new file mode 100644
index 000000000..7b204d80a
--- /dev/null
+++ b/host/frontend/gcastv2/https/include/https/SSLSocket.h
@@ -0,0 +1,120 @@
+/*
+ * 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.
+ */
+
+#include <https/BufferedSocket.h>
+
+#include <openssl/bio.h>
+#include <openssl/err.h>
+#include <openssl/pem.h>
+#include <openssl/ssl.h>
+
+#include <memory>
+
+struct SSLSocket
+ : public BufferedSocket,
+ public std::enable_shared_from_this<SSLSocket> {
+ static void Init();
+
+ enum {
+ // Client only.
+ FLAG_DONT_CHECK_PEER_CERTIFICATE = 1,
+ };
+
+ explicit SSLSocket(
+ std::shared_ptr<RunLoop> rl,
+ int sock,
+ const std::string &certificate_pem_path,
+ const std::string &private_key_pem_path,
+ uint32_t flags = 0);
+
+ explicit SSLSocket(
+ std::shared_ptr<RunLoop> rl,
+ int sock,
+ uint32_t flags = 0,
+ const std::optional<std::string> &trusted_pem_path = std::nullopt);
+
+ ~SSLSocket() override;
+
+ SSLSocket(const SSLSocket &) = delete;
+ SSLSocket &operator=(const SSLSocket &) = delete;
+
+ void postRecv(RunLoop::AsyncFunction fn) override;
+ void postSend(RunLoop::AsyncFunction fn) override;
+
+ ssize_t recvfrom(
+ void *data,
+ size_t size,
+ sockaddr *address,
+ socklen_t *addressLen) override;
+
+ ssize_t sendto(
+ const void *data,
+ size_t size,
+ const sockaddr *addr,
+ socklen_t addrLen) override;
+
+ void postFlush(RunLoop::AsyncFunction fn) override;
+
+private:
+ enum class Mode {
+ CONNECT,
+ ACCEPT,
+ };
+
+ Mode mMode;
+ uint32_t mFlags;
+
+ std::unique_ptr<SSL_CTX, std::function<void(SSL_CTX *)>> mCtx;
+ std::unique_ptr<SSL, std::function<void(SSL *)>> mSSL;
+
+ // These are owned by the SSL object.
+ BIO *mBioR;
+ BIO *mBioW;
+
+ bool mEOS;
+ int mFinalErrno;
+
+ bool mRecvPending;
+ RunLoop::AsyncFunction mRecvCallback;
+
+ bool mSendPending;
+ std::vector<uint8_t> mOutBuffer;
+
+ // This is as yet unencrypted data that has yet to be submitted to SSL_write.
+ std::vector<uint8_t> mOutBufferPlain;
+
+ RunLoop::AsyncFunction mFlushFn;
+
+ explicit SSLSocket(
+ std::shared_ptr<RunLoop> rl, Mode mode, int sock, uint32_t flags);
+
+ void handleIncomingData();
+ void sendRecvCallback();
+
+ void queueOutputDataFromSSL();
+
+ void queueOutputData(const void *data, size_t size);
+ void sendOutputData();
+
+ void drainOutputBufferPlain();
+ bool isPeerCertificateValid();
+
+ static SSL_CTX *CreateSSLContext();
+
+ bool useCertificate(const std::string &path);
+ bool usePrivateKey(const std::string &path);
+ bool useTrustedCertificates(const std::string &path);
+};
diff --git a/host/frontend/gcastv2/https/include/https/SafeCallbackable.h b/host/frontend/gcastv2/https/include/https/SafeCallbackable.h
new file mode 100644
index 000000000..9e88813c4
--- /dev/null
+++ b/host/frontend/gcastv2/https/include/https/SafeCallbackable.h
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <memory>
+
+template<typename T>
+std::function<void()> makeSafeCallback(T *obj, std::function<void(T *)> f) {
+ auto weak_me = std::weak_ptr<T>(obj->shared_from_this());
+ return [f, weak_me]{
+ auto me = weak_me.lock();
+ if (me) {
+ f(me.get());
+ }
+ };
+}
+
+template<typename T, typename... Params>
+std::function<void()> makeSafeCallback(
+ T *obj, void (T::*f)(const Params&...), const Params&... params) {
+ return makeSafeCallback<T>(
+ obj,
+ [f, params...](T *me) {
+ (me->*f)(params...);
+ });
+}
+
+template<typename T, typename... Params>
+std::function<void()> makeSafeCallback(
+ T *obj, void (T::*f)(Params...), const Params&... params) {
+ return makeSafeCallback<T>(
+ obj,
+ [f, params...](T *me) {
+ (me->*f)(params...);
+ });
+}
diff --git a/host/frontend/gcastv2/https/include/https/ServerSocket.h b/host/frontend/gcastv2/https/include/https/ServerSocket.h
new file mode 100644
index 000000000..d422a82d2
--- /dev/null
+++ b/host/frontend/gcastv2/https/include/https/ServerSocket.h
@@ -0,0 +1,71 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <memory>
+#include <optional>
+#include <string>
+#include <vector>
+
+struct ClientSocket;
+struct HTTPServer;
+struct RunLoop;
+
+struct ServerSocket : public std::enable_shared_from_this<ServerSocket> {
+ enum class TransportType {
+ TCP,
+ TLS,
+ };
+
+ explicit ServerSocket(
+ HTTPServer *server,
+ TransportType transportType,
+ const char *iface,
+ uint16_t port,
+ const std::optional<std::string> &certificate_pem_path,
+ const std::optional<std::string> &private_key_pem_path);
+
+ ~ServerSocket();
+
+ ServerSocket(const ServerSocket &) = delete;
+ ServerSocket &operator=(const ServerSocket &) = delete;
+
+ int initCheck() const;
+
+ TransportType transportType() const;
+
+ int run(std::shared_ptr<RunLoop> rl);
+
+ void onClientSocketClosed(int sock);
+
+ std::optional<std::string> certificate_pem_path() const;
+ std::optional<std::string> private_key_pem_path() const;
+
+private:
+ int mInitCheck;
+ HTTPServer *mServer;
+ std::optional<std::string> mCertificatePath, mPrivateKeyPath;
+ int mSocket;
+ TransportType mTransportType;
+
+ std::shared_ptr<RunLoop> mRunLoop;
+ std::vector<std::shared_ptr<ClientSocket>> mClientSockets;
+
+ void acceptIncomingConnection();
+};
+
diff --git a/common/libs/utils/base64.h b/host/frontend/gcastv2/https/include/https/Support.h
index dd262c38e..6ab5520ae 100644
--- a/common/libs/utils/base64.h
+++ b/host/frontend/gcastv2/https/include/https/Support.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2020 The Android Open Source Project
+ * 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.
@@ -16,14 +16,25 @@
#pragma once
-#include <cinttypes>
+#include <sys/types.h>
+
#include <string>
-#include <vector>
-namespace cuttlefish {
+#ifdef NDEBUG
+#define DEBUG_ONLY(x)
+#else
+#define DEBUG_ONLY(x) x
+#endif
+
+void makeFdNonblocking(int fd);
+void hexdump(const void *_data, size_t size);
-bool EncodeBase64(const void* _data, size_t size, std::string* out);
+void encodeBase64(const void *_data, size_t size, std::string *out);
-bool DecodeBase64(const std::string& data, std::vector<uint8_t>* buffer);
+uint16_t U16_AT(const uint8_t *ptr);
+uint32_t U32_AT(const uint8_t *ptr);
+uint64_t U64_AT(const uint8_t *ptr);
-} // namespace cuttlefish
+uint16_t U16LE_AT(const uint8_t *ptr);
+uint32_t U32LE_AT(const uint8_t *ptr);
+uint64_t U64LE_AT(const uint8_t *ptr);
diff --git a/host/frontend/gcastv2/https/include/https/WebSocketHandler.h b/host/frontend/gcastv2/https/include/https/WebSocketHandler.h
new file mode 100644
index 000000000..76708764f
--- /dev/null
+++ b/host/frontend/gcastv2/https/include/https/WebSocketHandler.h
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <arpa/inet.h>
+#include <cstdint>
+#include <functional>
+#include <memory>
+#include <string>
+#include <sys/types.h>
+
+struct ClientSocket;
+
+struct WebSocketHandler {
+ virtual ~WebSocketHandler() = default;
+
+ // Returns number bytes processed or error.
+ ssize_t handleRequest(uint8_t *data, size_t size, bool isEOS);
+
+ bool isConnected();
+
+ virtual void setClientSocket(std::weak_ptr<ClientSocket> client);
+
+ typedef std::function<void(const uint8_t *, size_t)> OutputCallback;
+ void setOutputCallback(const sockaddr_in &remoteAddr, OutputCallback fn);
+
+ enum class SendMode {
+ text,
+ binary,
+ closeConnection,
+ };
+ int sendMessage(
+ const void *data, size_t size, SendMode mode = SendMode::text);
+
+ std::string remoteHost() const;
+
+protected:
+ virtual int handleMessage(
+ uint8_t headerByte, const uint8_t *msg, size_t len) = 0;
+
+private:
+ std::weak_ptr<ClientSocket> mClientSocket;
+
+ OutputCallback mOutputCallback;
+ sockaddr_in mRemoteAddr;
+};
diff --git a/host/commands/cvd_host_bugreport/Android.bp b/host/frontend/gcastv2/libsource/Android.bp
index 4f6aedaee..70af4e00e 100644
--- a/host/commands/cvd_host_bugreport/Android.bp
+++ b/host/frontend/gcastv2/libsource/Android.bp
@@ -1,4 +1,3 @@
-//
// Copyright (C) 2018 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
@@ -13,26 +12,30 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-cc_binary {
- name: "cvd_host_bugreport",
+cc_library_host_static {
+ name: "libsource",
srcs: [
- "main.cc",
+ "AudioSource.cpp",
+ "InputSink.cpp",
+ "KeyboardSink.cpp",
+ "TouchSink.cpp",
+ "FrameBufferSource.cpp",
+ "HostToGuestComms.cpp",
+ "StreamingSource.cpp",
],
shared_libs: [
"libbase",
- "libcuttlefish_fs",
- "libcuttlefish_utils",
- "libjsoncpp",
- "libziparchive",
+ "libyuv",
+ "libopus",
+ "libvpx",
],
static_libs: [
"libcuttlefish_host_config",
- "libcuttlefish_vm_manager",
"libgflags",
+ "libhttps",
],
- defaults: ["cuttlefish_host", "cuttlefish_libicuuc"],
+ local_include_dirs: ["include"],
+ export_include_dirs: ["include"],
+ defaults: ["cuttlefish_host_only"],
}
+
diff --git a/host/frontend/gcastv2/libsource/AudioSource.cpp b/host/frontend/gcastv2/libsource/AudioSource.cpp
new file mode 100644
index 000000000..c3f40dd35
--- /dev/null
+++ b/host/frontend/gcastv2/libsource/AudioSource.cpp
@@ -0,0 +1,836 @@
+/*
+ * 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.
+ */
+
+#include <source/AudioSource.h>
+
+#include <libyuv/convert.h>
+
+#include <system/audio.h>
+
+#include "host/libs/config/cuttlefish_config.h"
+
+#include <opus.h>
+
+#include <gflags/gflags.h>
+#include <cmath>
+
+#define LOG_AUDIO 0
+
+namespace android {
+
+namespace {
+
+// These definitions are deleted in master, copying here temporarily
+typedef uint32_t size32_t;
+
+struct timespec32 {
+ uint32_t tv_sec;
+ uint32_t tv_nsec;
+
+ timespec32() = default;
+
+ timespec32(const timespec &from)
+ : tv_sec(from.tv_sec),
+ tv_nsec(from.tv_nsec) {
+ }
+};
+
+struct gce_audio_message {
+// static const size32_t kMaxAudioFrameLen = 65536;
+ enum message_t {
+ UNKNOWN = 0,
+ DATA_SAMPLES = 1,
+ OPEN_INPUT_STREAM = 2,
+ OPEN_OUTPUT_STREAM = 3,
+ CLOSE_INPUT_STREAM = 4,
+ CLOSE_OUTPUT_STREAM = 5,
+ CONTROL_PAUSE = 100
+ };
+ // Size of the header + data. Used to frame when we're on TCP.
+ size32_t total_size;
+ // Size of the audio header
+ size32_t header_size;
+ message_t message_type;
+ // Identifier for the stream.
+ uint32_t stream_number;
+ // HAL assigned frame number, starts from 0.
+ int64_t frame_num;
+ // MONOTONIC_TIME when these frames were presented to the HAL.
+ timespec32 time_presented;
+ // Sample rate from the audio configuration.
+ uint32_t frame_rate;
+ // Channel mask from the audio configuration.
+ audio_channel_mask_t channel_mask;
+ // Format from the audio configuration.
+ audio_format_t format;
+ // Size of each frame in bytes.
+ size32_t frame_size;
+ // Number of frames that were presented to the HAL.
+ size32_t num_frames_presented;
+ // Number of frames that the HAL accepted.
+ // For blocking audio this will be the same as num_frames.
+ // For non-blocking audio this may be less.
+ size32_t num_frames_accepted;
+ // Count of the number of packets that were dropped because they would
+ // have blocked the HAL or exceeded the maximum message size.
+ size32_t num_packets_dropped;
+ // Count of the number of packets that were shortened to fit within
+ // kMaxAudioFrameLen.
+ size32_t num_packets_shortened;
+ // num_frames_presented (not num_frames_accepted) will follow here.
+
+ gce_audio_message() :
+ total_size(sizeof(gce_audio_message)),
+ header_size(sizeof(gce_audio_message)),
+ message_type(UNKNOWN),
+ stream_number(0),
+ frame_num(0),
+ frame_rate(0),
+ channel_mask(0),
+ format(AUDIO_FORMAT_DEFAULT),
+ frame_size(0),
+ num_frames_presented(0),
+ num_frames_accepted(0),
+ num_packets_dropped(0),
+ num_packets_shortened(0) {
+ time_presented.tv_sec = 0;
+ time_presented.tv_nsec = 0;
+ }
+};
+
+}
+
+struct AudioSource::Encoder {
+ explicit Encoder();
+ virtual ~Encoder() = default;
+
+ virtual int32_t initCheck() const = 0;
+ virtual void encode(const void *data, size_t size) = 0;
+ virtual void reset() = 0;
+
+ void setFrameCallback(
+ std::function<void(const std::shared_ptr<SBuffer> &)> onFrameFn);
+
+protected:
+ std::function<void(const std::shared_ptr<SBuffer> &)> mOnFrameFn;
+};
+
+AudioSource::Encoder::Encoder()
+ : mOnFrameFn(nullptr) {
+}
+
+void AudioSource::Encoder::setFrameCallback(
+ std::function<void(const std::shared_ptr<SBuffer> &)> onFrameFn) {
+ mOnFrameFn = onFrameFn;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+struct Upsampler {
+ explicit Upsampler(int32_t from = 44100, int32_t to = 48000)
+ : mFrom(from),
+ mTo(to),
+ mCounter(0) {
+ }
+
+ void append(const int16_t *data, size_t numFrames) {
+ for (size_t i = 0; i < numFrames; ++i) {
+ int16_t l = *data++;
+ int16_t r = *data++;
+
+ mCounter += mTo;
+ while (mCounter >= mFrom) {
+ mCounter -= mFrom;
+
+ mBuffer.push_back(l);
+ mBuffer.push_back(r);
+ }
+ }
+ }
+
+ const int16_t *data() const { return mBuffer.data(); }
+
+ size_t numFramesAvailable() const { return mBuffer.size() / 2; }
+
+ void drain(size_t numFrames) {
+ CHECK_LE(numFrames, numFramesAvailable());
+
+ mBuffer.erase(mBuffer.begin(), mBuffer.begin() + numFrames * 2);
+ }
+
+private:
+ int32_t mFrom;
+ int32_t mTo;
+
+ std::vector<int16_t> mBuffer;
+
+ int32_t mCounter;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+struct AudioSource::OPUSEncoder : public AudioSource::Encoder {
+ explicit OPUSEncoder();
+ ~OPUSEncoder() override;
+
+ int32_t initCheck() const override;
+
+ OPUSEncoder(const OPUSEncoder &) = delete;
+ OPUSEncoder &operator=(const OPUSEncoder &) = delete;
+
+ void encode(const void *data, size_t size) override;
+ void reset() override;
+
+private:
+ int32_t mInitCheck;
+
+ gce_audio_message mPrevHeader;
+ bool mPrevHeaderValid;
+
+ size_t mChannelCount;
+
+ OpusEncoder *mImpl;
+
+ std::unique_ptr<Upsampler> mUpSampler;
+
+ FILE *mLogFile;
+};
+
+AudioSource::OPUSEncoder::OPUSEncoder()
+ : mInitCheck(-ENODEV),
+ mImpl(nullptr),
+ mLogFile(nullptr) {
+ reset();
+ mInitCheck = 0;
+}
+
+AudioSource::OPUSEncoder::~OPUSEncoder() {
+ reset();
+}
+
+int32_t AudioSource::OPUSEncoder::initCheck() const {
+ return mInitCheck;
+}
+
+void AudioSource::OPUSEncoder::reset() {
+ if (mLogFile != nullptr) {
+ fclose(mLogFile);
+ mLogFile = nullptr;
+ }
+
+ mUpSampler.reset();
+
+ if (mImpl) {
+ opus_encoder_destroy(mImpl);
+ mImpl = nullptr;
+ }
+
+ mPrevHeaderValid = false;
+ mChannelCount = 0;
+}
+
+void AudioSource::OPUSEncoder::encode(const void *_data, size_t size) {
+ auto data = static_cast<const uint8_t *>(_data);
+
+ CHECK_GE(size, sizeof(gce_audio_message));
+
+ gce_audio_message hdr;
+ std::memcpy(&hdr, data, sizeof(gce_audio_message));
+
+ if (hdr.message_type != gce_audio_message::DATA_SAMPLES) {
+ return;
+ }
+
+ static int64_t timeUs = 0;
+
+ static int64_t prevTimeUs = 0;
+
+ LOG(VERBOSE)
+ << "encode received "
+ << ((size - sizeof(gce_audio_message)) / (2 * sizeof(int16_t)))
+ << " frames, "
+ << " deltaTime = "
+ << (((timeUs - prevTimeUs) * hdr.frame_rate) / 1000000ll)
+ << " frames";
+
+ prevTimeUs = timeUs;
+
+ if (!mPrevHeaderValid
+ || mPrevHeader.frame_size != hdr.frame_size
+ || mPrevHeader.frame_rate != hdr.frame_rate
+ || mPrevHeader.stream_number != hdr.stream_number) {
+
+ if (mPrevHeaderValid) {
+ LOG(INFO)
+ << "Found audio data in a different configuration than before!"
+ << " frame_size="
+ << hdr.frame_size
+ << " vs. "
+ << mPrevHeader.frame_size
+ << ", frame_rate="
+ << hdr.frame_rate
+ << " vs. "
+ << mPrevHeader.frame_rate
+ << ", stream_number="
+ << hdr.stream_number
+ << " vs. "
+ << mPrevHeader.stream_number;
+
+ // reset?
+ return;
+ }
+
+ mPrevHeaderValid = true;
+ mPrevHeader = hdr;
+
+ const size_t numChannels = hdr.frame_size / sizeof(int16_t);
+
+#if LOG_AUDIO
+ mLogFile = fopen("/tmp/log_remote.opus", "wb");
+ CHECK(mLogFile != nullptr);
+#endif
+
+ LOG(INFO)
+ << "Calling opus_encoder_create w/ "
+ << "hdr.frame_rate = "
+ << hdr.frame_rate
+ << ", numChannels = "
+ << numChannels;
+
+ int err;
+ mImpl = opus_encoder_create(
+ 48000,
+ numChannels,
+ OPUS_APPLICATION_AUDIO,
+ &err);
+
+ CHECK_EQ(err, OPUS_OK);
+
+ mChannelCount = numChannels;
+
+ static_assert(sizeof(int16_t) == sizeof(opus_int16));
+
+ err = opus_encoder_ctl(mImpl, OPUS_SET_INBAND_FEC(true));
+ CHECK_EQ(err, OPUS_OK);
+
+ err = opus_encoder_ctl(mImpl, OPUS_SET_PACKET_LOSS_PERC(10));
+ CHECK_EQ(err, OPUS_OK);
+
+ err = opus_encoder_ctl(
+ mImpl, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_WIDEBAND));
+
+ CHECK_EQ(err, OPUS_OK);
+
+ CHECK_LE(hdr.frame_rate, 48000);
+ mUpSampler = std::make_unique<Upsampler>(hdr.frame_rate, 48000);
+ }
+
+ // {2.5, 5, 10, 20, 40, 60, 80, 100, 120} ms
+ static constexpr size_t kNumFramesPerOutputBuffer = 48 * 20;
+
+ const size_t offset = sizeof(gce_audio_message);
+ mUpSampler->append(
+ reinterpret_cast<const int16_t *>(&data[offset]),
+ (size - offset) / (mChannelCount * sizeof(int16_t)));
+
+ while (mUpSampler->numFramesAvailable() >= kNumFramesPerOutputBuffer) {
+ size_t copyFrames =
+ std::min(mUpSampler->numFramesAvailable(),
+ kNumFramesPerOutputBuffer);
+
+ static constexpr size_t kMaxPacketSize = 8192;
+
+ std::shared_ptr<SBuffer> outBuffer(new SBuffer(kMaxPacketSize));
+
+ auto outSize = opus_encode(
+ mImpl,
+ reinterpret_cast<const opus_int16 *>(mUpSampler->data()),
+ copyFrames,
+ outBuffer->data(),
+ outBuffer->capacity());
+
+ CHECK_GT(outSize, 0);
+
+ outBuffer->resize(outSize);
+
+ outBuffer->time_us(timeUs);
+
+ mUpSampler->drain(copyFrames);
+
+ timeUs += (copyFrames * 1000ll) / 48;
+
+#if LOG_AUDIO
+ fwrite(outBuffer->data(), 1, outBuffer->size(), mLogFile);
+ fflush(mLogFile);
+#endif
+
+ if (mOnFrameFn) {
+ mOnFrameFn(outBuffer);
+ }
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+struct Downsampler {
+ explicit Downsampler(int32_t from = 44100, int32_t to = 8000)
+ : mFrom(from),
+ mTo(to),
+ mCounter(0) {
+ }
+
+ void append(const int16_t *data, size_t numFrames) {
+ for (size_t i = 0; i < numFrames; ++i) {
+ int16_t l = *data++;
+ int16_t r = *data++;
+
+ mCounter += mTo;
+ if (mCounter >= mFrom) {
+ mCounter -= mFrom;
+
+ auto mono = (l + r) / 2;
+ mBuffer.push_back(mono);
+ }
+ }
+ }
+
+ const int16_t *data() const { return mBuffer.data(); }
+
+ size_t numFramesAvailable() const { return mBuffer.size(); }
+
+ void drain(size_t numFrames) {
+ CHECK_LE(numFrames, numFramesAvailable());
+
+ mBuffer.erase(mBuffer.begin(), mBuffer.begin() + numFrames);
+ }
+
+private:
+ int32_t mFrom;
+ int32_t mTo;
+
+ std::vector<int16_t> mBuffer;
+
+ int32_t mCounter;
+};
+
+struct AudioSource::G711Encoder : public AudioSource::Encoder {
+ enum class Mode {
+ ALAW,
+ ULAW,
+ };
+
+ explicit G711Encoder(Mode mode);
+
+ int32_t initCheck() const override;
+
+ G711Encoder(const G711Encoder &) = delete;
+ G711Encoder &operator=(const G711Encoder &) = delete;
+
+ void encode(const void *data, size_t size) override;
+ void reset() override;
+
+private:
+ static constexpr size_t kNumFramesPerBuffer = 512;
+
+ int32_t mInitCheck;
+ Mode mMode;
+
+ gce_audio_message mPrevHeader;
+ bool mPrevHeaderValid;
+
+ size_t mChannelCount;
+
+ std::shared_ptr<SBuffer> mOutputFrame;
+ Downsampler mDownSampler;
+
+ void doEncode(const int16_t *src, size_t numFrames);
+};
+
+AudioSource::G711Encoder::G711Encoder(Mode mode)
+ : mInitCheck(-ENODEV),
+ mMode(mode) {
+ reset();
+ mInitCheck = 0;
+}
+
+int32_t AudioSource::G711Encoder::initCheck() const {
+ return mInitCheck;
+}
+
+void AudioSource::G711Encoder::reset() {
+ mPrevHeaderValid = false;
+ mChannelCount = 0;
+}
+
+void AudioSource::G711Encoder::encode(const void *_data, size_t size) {
+ auto data = static_cast<const uint8_t *>(_data);
+
+ CHECK_GE(size, sizeof(gce_audio_message));
+
+ gce_audio_message hdr;
+ std::memcpy(&hdr, data, sizeof(gce_audio_message));
+
+ if (hdr.message_type != gce_audio_message::DATA_SAMPLES) {
+ return;
+ }
+
+ static int64_t timeUs = 0;
+
+ static int64_t prevTimeUs = 0;
+
+ LOG(VERBOSE)
+ << "encode received "
+ << ((size - sizeof(gce_audio_message)) / (2 * sizeof(int16_t)))
+ << " frames, "
+ << " deltaTime = "
+ << ((timeUs - prevTimeUs) * 441) / 10000
+ << " frames";
+
+ prevTimeUs = timeUs;
+
+ if (!mPrevHeaderValid
+ || mPrevHeader.frame_size != hdr.frame_size
+ || mPrevHeader.frame_rate != hdr.frame_rate
+ || mPrevHeader.stream_number != hdr.stream_number) {
+
+ if (mPrevHeaderValid) {
+ LOG(INFO)
+ << "Found audio data in a different configuration than before!"
+ << " frame_size="
+ << hdr.frame_size
+ << " vs. "
+ << mPrevHeader.frame_size
+ << ", frame_rate="
+ << hdr.frame_rate
+ << " vs. "
+ << mPrevHeader.frame_rate
+ << ", stream_number="
+ << hdr.stream_number
+ << " vs. "
+ << mPrevHeader.stream_number;
+
+ // reset?
+ return;
+ }
+
+ mPrevHeaderValid = true;
+ mPrevHeader = hdr;
+
+ mChannelCount = hdr.frame_size / sizeof(int16_t);
+
+ // mono, 8-bit output samples.
+ mOutputFrame.reset(new SBuffer(kNumFramesPerBuffer));
+ }
+
+ const size_t offset = sizeof(gce_audio_message);
+ mDownSampler.append(
+ reinterpret_cast<const int16_t *>(&data[offset]),
+ (size - offset) / (mChannelCount * sizeof(int16_t)));
+
+ while (mDownSampler.numFramesAvailable() >= kNumFramesPerBuffer) {
+ doEncode(mDownSampler.data(), kNumFramesPerBuffer);
+
+ mOutputFrame->time_us(timeUs);
+
+ mDownSampler.drain(kNumFramesPerBuffer);
+
+ timeUs += (kNumFramesPerBuffer * 1000ll) / 8;
+
+ if (mOnFrameFn) {
+ mOnFrameFn(mOutputFrame);
+ }
+ }
+}
+
+static unsigned clz16(uint16_t x) {
+ unsigned n = 0;
+ if ((x & 0xff00) == 0) {
+ n += 8;
+ x <<= 8;
+ }
+ if ((x & 0xf000) == 0) {
+ n += 4;
+ x <<= 4;
+ }
+
+ static const unsigned kClzNibble[] = {
+ 4, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0
+ };
+
+ return n + kClzNibble[n >> 12];
+}
+
+void AudioSource::G711Encoder::doEncode(const int16_t *src, size_t numFrames) {
+ switch (mMode) {
+ case Mode::ALAW:
+ {
+ uint8_t *dst = mOutputFrame->data();
+
+ for (size_t i = numFrames; i--;) {
+ uint16_t in = (*src++) >> 3; // Convert from 16-bit to 13-bit.
+ uint8_t inverseSign = 0x80;
+
+ if (in & 0x8000) {
+ in = ~in;
+ inverseSign = 0x00;
+ }
+
+ auto numLeadingZeroes = clz16(in);
+ auto suffixLength = 16 - numLeadingZeroes;
+
+ static constexpr uint8_t kMask = 0x55;
+
+ if (suffixLength <= 5) {
+ *dst++ = (((in >> 1) & 0x0f) | inverseSign) ^ kMask;
+ } else {
+ auto shift = suffixLength - 5;
+ auto abcd = (in >> shift) & 0x0f;
+ *dst++ = (abcd | (shift << 4) | inverseSign) ^ kMask;
+ }
+ }
+ break;
+ }
+
+ case Mode::ULAW:
+ {
+ uint8_t *dst = mOutputFrame->data();
+
+ for (size_t i = numFrames; i--;) {
+ uint16_t in = (*src++) >> 2; // Convert from 16-bit to 14-bit.
+ uint8_t inverseSign = 0x80;
+
+ if (in & 0x8000) {
+ in = ~in;
+ inverseSign = 0x00;
+ }
+
+ in += 33;
+
+ auto numLeadingZeroes = clz16(in);
+ auto suffixLength = 16 - numLeadingZeroes;
+
+ static constexpr uint8_t kMask = 0xff;
+
+ if (suffixLength <= 6) {
+ *dst++ = (((in >> 1) & 0x0f) | inverseSign) ^ kMask;
+ } else {
+ auto shift = suffixLength - 5;
+ auto abcd = (in >> shift) & 0x0f;
+ *dst++ = (abcd | ((shift - 1) << 4) | inverseSign) ^ kMask;
+ }
+ }
+ break;
+ }
+
+ default:
+ LOG(FATAL) << "Should not be here.";
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+AudioSource::AudioSource(Format format, bool useADTSFraming)
+ : mInitCheck(-ENODEV),
+ mState(STOPPED)
+#if SIMULATE_AUDIO
+ ,mPhase(0)
+#endif
+{
+ switch (format) {
+ case Format::OPUS:
+ {
+ CHECK(!useADTSFraming);
+ mEncoder.reset(new OPUSEncoder);
+ break;
+ }
+
+ case Format::G711_ALAW:
+ case Format::G711_ULAW:
+ {
+ CHECK(!useADTSFraming);
+
+ mEncoder.reset(
+ new G711Encoder(
+ (format == Format::G711_ALAW)
+ ? G711Encoder::Mode::ALAW
+ : G711Encoder::Mode::ULAW));
+ break;
+ }
+
+ default:
+ LOG(FATAL) << "Should not be here.";
+ }
+
+ mEncoder->setFrameCallback([this](const std::shared_ptr<SBuffer> &accessUnit) {
+ StreamingSource::onAccessUnit(accessUnit);
+ });
+
+ mInitCheck = 0;
+}
+
+AudioSource::~AudioSource() {
+ stop();
+}
+
+int32_t AudioSource::initCheck() const {
+ return mInitCheck;
+}
+
+int32_t AudioSource::start() {
+ std::lock_guard<std::mutex> autoLock(mLock);
+
+ if (mState != STOPPED) {
+ return 0;
+ }
+
+ mEncoder->reset();
+
+ mState = RUNNING;
+
+#if SIMULATE_AUDIO
+ mThread.reset(
+ new std::thread([this]{
+ auto startTime = std::chrono::steady_clock::now();
+
+ std::vector<uint8_t> raw(
+ sizeof(gce_audio_message)
+ + kNumFramesPerBuffer * kNumChannels * sizeof(int16_t));
+
+ gce_audio_message *buffer =
+ reinterpret_cast<gce_audio_message *>(raw.data());
+
+ buffer->message_type = gce_audio_message::DATA_SAMPLES;
+ buffer->frame_size = kNumChannels * sizeof(int16_t);
+ buffer->frame_rate = kSampleRate;
+ buffer->stream_number = 0;
+
+ const double k = (double)kFrequency / kSampleRate * (2.0 * M_PI);
+
+ while (mState != STOPPING) {
+ std::chrono::microseconds durationSinceStart(
+ (mPhase * 1000000ll) / kSampleRate);
+
+ auto time = startTime + durationSinceStart;
+ auto now = std::chrono::steady_clock::now();
+ auto delayUs = std::chrono::duration_cast<
+ std::chrono::microseconds>(time - now).count();
+
+ if (delayUs > 0) {
+ usleep(delayUs);
+ }
+
+ auto usSinceStart =
+ std::chrono::duration_cast<std::chrono::microseconds>(
+ std::chrono::steady_clock::now() - startTime).count();
+
+ buffer->time_presented.tv_sec = usSinceStart / 1000000ll;
+
+ buffer->time_presented.tv_nsec =
+ (usSinceStart % 1000000ll) * 1000;
+
+ int16_t *ptr =
+ reinterpret_cast<int16_t *>(
+ raw.data() + sizeof(gce_audio_message));
+
+ double x = mPhase * k;
+ for (size_t i = 0; i < kNumFramesPerBuffer; ++i) {
+ int16_t amplitude = (int16_t)(32767.0 * sin(x));
+
+ *ptr++ = amplitude;
+ if (kNumChannels == 2) {
+ *ptr++ = amplitude;
+ }
+
+ x += k;
+ }
+
+ mEncoder->encode(raw.data(), raw.size());
+
+ mPhase += kNumFramesPerBuffer;
+ }
+ }));
+#else
+/*
+ if (mRegionView) {
+ mThread.reset(
+ new std::thread([this]{
+ while (mState != STOPPING) {
+ uint8_t buffer[4096];
+
+ struct timespec absTimeLimit;
+ vsoc::RegionView::GetFutureTime(
+ 1000000000ll ns_from_now, &absTimeLimit);
+
+ intptr_t res = mRegionView->data()->audio_queue.Read(
+ mRegionView,
+ reinterpret_cast<char *>(buffer),
+ sizeof(buffer),
+ &absTimeLimit);
+
+ if (res < 0) {
+ if (res == -ETIMEDOUT) {
+ LOG(VERBOSE) << "AudioSource read timed out";
+ }
+ continue;
+ }
+
+ if (mState == RUNNING) {
+ mEncoder->encode(buffer, static_cast<size_t>(res));
+ }
+ }
+ }));
+ }
+ */
+#endif // SIMULATE_AUDIO
+
+ return 0;
+}
+
+int32_t AudioSource::stop() {
+ std::lock_guard<std::mutex> autoLock(mLock);
+
+ if (mState == STOPPED) {
+ return 0;
+ }
+
+ mState = STOPPING;
+
+ if (mThread) {
+ mThread->join();
+ mThread.reset();
+ }
+
+ mState = STOPPED;
+
+ return 0;
+}
+
+int32_t AudioSource::requestIDRFrame() {
+ return 0;
+}
+
+void AudioSource::inject(const void *data, size_t size) {
+ // Only used in the case of CrosVM operation.
+
+ std::lock_guard<std::mutex> autoLock(mLock);
+ if (mState != State::RUNNING) {
+ return;
+ }
+
+ mEncoder->encode(static_cast<const uint8_t *>(data), size);
+}
+
+} // namespace android
diff --git a/host/frontend/gcastv2/libsource/FrameBufferSource.cpp b/host/frontend/gcastv2/libsource/FrameBufferSource.cpp
new file mode 100644
index 000000000..9b742cca6
--- /dev/null
+++ b/host/frontend/gcastv2/libsource/FrameBufferSource.cpp
@@ -0,0 +1,415 @@
+/*
+ * 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.
+ */
+
+#include <source/FrameBufferSource.h>
+
+#include <algorithm>
+#include <chrono>
+
+#include <libyuv/convert.h>
+
+#include "host/libs/config/cuttlefish_config.h"
+
+#include "vpx/vpx_encoder.h"
+#include "vpx/vpx_codec.h"
+#include "vpx/vp8cx.h"
+
+#include <gflags/gflags.h>
+
+#define ENABLE_LOGGING 0
+
+namespace android {
+
+namespace {
+ int64_t GetNowUs() {
+ auto now = std::chrono::steady_clock::now().time_since_epoch();
+ return std::chrono::duration_cast<std::chrono::microseconds>(now).count();
+ }
+}
+
+struct FrameBufferSource::Encoder {
+ Encoder() = default;
+ virtual ~Encoder() = default;
+
+ virtual void forceIDRFrame() = 0;
+ virtual bool isForcingIDRFrame() const = 0;
+
+ virtual void storeFrame(const void* frame) = 0;
+ virtual std::shared_ptr<SBuffer> encodeStoredFrame(int64_t timeUs) = 0;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+struct FrameBufferSource::VPXEncoder : public FrameBufferSource::Encoder {
+ VPXEncoder(int width, int height, int rateHz);
+ ~VPXEncoder() override;
+
+ void forceIDRFrame() override;
+ bool isForcingIDRFrame() const override;
+
+ void storeFrame(const void* frame) override;
+ std::shared_ptr<SBuffer> encodeStoredFrame(int64_t timeUs) override;
+
+private:
+ int mWidth, mHeight, mRefreshRateHz;
+
+ int mSizeY, mSizeUV;
+ void *mI420Data;
+
+ vpx_codec_iface_t *mCodecInterface;
+ std::unique_ptr<vpx_codec_enc_cfg_t> mCodecConfiguration;
+
+ using contextFreeFunc = std::function<vpx_codec_err_t(vpx_codec_ctx_t *)>;
+ std::unique_ptr<vpx_codec_ctx_t, contextFreeFunc> mCodecContext;
+
+ std::atomic<bool> mForceIDRFrame;
+ bool mFirstFrame;
+ bool mStoredFrame;
+ int64_t mLastTimeUs;
+};
+
+static int GetCPUCoreCount() {
+ int cpuCoreCount;
+
+#if defined(_SC_NPROCESSORS_ONLN)
+ cpuCoreCount = sysconf(_SC_NPROCESSORS_ONLN);
+#else
+ // _SC_NPROC_ONLN must be defined...
+ cpuCoreCount = sysconf(_SC_NPROC_ONLN);
+#endif
+
+ CHECK_GE(cpuCoreCount, 1);
+ return cpuCoreCount;
+}
+
+FrameBufferSource::VPXEncoder::VPXEncoder(int width, int height, int rateHz)
+ : mWidth(width),
+ mHeight(height),
+ mRefreshRateHz(rateHz),
+ mCodecContext(nullptr, vpx_codec_destroy),
+ mForceIDRFrame(false),
+ mFirstFrame(true),
+ mStoredFrame(false),
+ mLastTimeUs(0) {
+
+ CHECK((width & 1) == 0);
+ CHECK((height & 1) == 0);
+ mSizeY = width * height;
+ mSizeUV = (width / 2) * (height / 2);
+ size_t totalSize = mSizeY + 2 * mSizeUV;
+ mI420Data = malloc(totalSize);
+
+ mCodecInterface = vpx_codec_vp8_cx();
+ mCodecConfiguration = std::make_unique<vpx_codec_enc_cfg_t>();
+
+ auto res = vpx_codec_enc_config_default(
+ mCodecInterface, mCodecConfiguration.get(), 0 /* usage */);
+
+ mCodecConfiguration->g_w = width;
+ mCodecConfiguration->g_h = height;
+ mCodecConfiguration->g_threads = std::min(GetCPUCoreCount(), 64);
+ mCodecConfiguration->g_error_resilient = false;
+ mCodecConfiguration->g_timebase.num = 1;
+ mCodecConfiguration->g_timebase.den = 1000000;
+ mCodecConfiguration->rc_target_bitrate = 2500; // This appears to match x264
+ mCodecConfiguration->rc_end_usage = VPX_VBR;
+ mCodecConfiguration->rc_dropframe_thresh = 0;
+ mCodecConfiguration->g_lag_in_frames = 0;
+
+ mCodecConfiguration->g_profile = 0;
+
+ CHECK_EQ(res, VPX_CODEC_OK);
+
+ mCodecContext.reset(new vpx_codec_ctx_t);
+
+ res = vpx_codec_enc_init(
+ mCodecContext.get(),
+ mCodecInterface,
+ mCodecConfiguration.get(),
+ 0 /* flags */);
+
+ CHECK_EQ(res, VPX_CODEC_OK);
+
+ res = vpx_codec_control(mCodecContext.get(), VP8E_SET_TOKEN_PARTITIONS, 0);
+ CHECK_EQ(res, VPX_CODEC_OK);
+}
+
+FrameBufferSource::VPXEncoder::~VPXEncoder() {
+ free(mI420Data);
+ mI420Data = nullptr;
+}
+
+void FrameBufferSource::VPXEncoder::forceIDRFrame() {
+ mForceIDRFrame = true;
+}
+
+bool FrameBufferSource::VPXEncoder::isForcingIDRFrame() const {
+ return mForceIDRFrame;
+}
+
+void FrameBufferSource::VPXEncoder::storeFrame(const void *frame) {
+ uint8_t *yPlane = static_cast<uint8_t *>(mI420Data);
+ uint8_t *uPlane = yPlane + mSizeY;
+ uint8_t *vPlane = uPlane + mSizeUV;
+
+ libyuv::ABGRToI420(
+ static_cast<const uint8_t *>(frame),
+ mWidth * 4,
+ yPlane,
+ mWidth,
+ uPlane,
+ mWidth / 2,
+ vPlane,
+ mWidth / 2,
+ mWidth,
+ mHeight);
+ mStoredFrame = true;
+}
+
+std::shared_ptr<SBuffer> FrameBufferSource::VPXEncoder::encodeStoredFrame(
+ int64_t timeUs) {
+ if (!mStoredFrame) {
+ return nullptr;
+ }
+ vpx_image_t raw_frame;
+ vpx_img_wrap(&raw_frame, VPX_IMG_FMT_I420, mWidth, mHeight,
+ 2 /* stride_align */,
+ reinterpret_cast<unsigned char *>(mI420Data));
+
+ vpx_enc_frame_flags_t flags = 0;
+
+ if (mForceIDRFrame.exchange(false)) {
+ flags |= VPX_EFLAG_FORCE_KF;
+ }
+
+ uint32_t frameDuration;
+
+ if (!mFirstFrame) {
+ frameDuration = timeUs - mLastTimeUs;
+ } else {
+ frameDuration = 1000000 / mRefreshRateHz;
+ mFirstFrame = false;
+ }
+
+ mLastTimeUs = timeUs;
+
+ auto res = vpx_codec_encode(
+ mCodecContext.get(),
+ &raw_frame,
+ timeUs,
+ frameDuration,
+ flags,
+ VPX_DL_REALTIME);
+
+ if (res != VPX_CODEC_OK) {
+ LOG(ERROR) << "vpx_codec_encode failed w/ " << res;
+ return nullptr;
+ }
+
+ vpx_codec_iter_t iter = nullptr;
+ const vpx_codec_cx_pkt_t *packet;
+
+ std::shared_ptr<SBuffer> accessUnit;
+
+ while ((packet = vpx_codec_get_cx_data(mCodecContext.get(), &iter)) !=
+ nullptr) {
+ if (packet->kind == VPX_CODEC_CX_FRAME_PKT) {
+ LOG(VERBOSE)
+ << "vpx_codec_encode returned packet of size "
+ << packet->data.frame.sz;
+
+ if (accessUnit != nullptr) {
+ LOG(ERROR)
+ << "vpx_codec_encode returned more than one packet of "
+ "compressed data!";
+
+ return nullptr;
+ }
+
+ accessUnit.reset(new SBuffer(packet->data.frame.sz));
+
+ memcpy(accessUnit->data(),
+ packet->data.frame.buf,
+ packet->data.frame.sz);
+
+ accessUnit->time_us(timeUs);
+ } else {
+ LOG(INFO)
+ << "vpx_codec_encode returned a packet of type "
+ << packet->kind;
+ }
+ }
+
+ return accessUnit;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+FrameBufferSource::FrameBufferSource(Format format)
+ : mInitCheck(-ENODEV),
+ mState(STOPPED),
+ mFormat(format),
+ mScreenWidth(0),
+ mScreenHeight(0),
+ mScreenDpi(0),
+ mScreenRate(0),
+ mNumConsumers(0),
+ mOnFrameFn(nullptr) {
+ mInitCheck = 0;
+}
+
+FrameBufferSource::~FrameBufferSource() {
+ stop();
+}
+
+int32_t FrameBufferSource::initCheck() const {
+ return mInitCheck;
+}
+
+int32_t FrameBufferSource::start() {
+ std::lock_guard<std::mutex> autoLock(mLock);
+
+ if (mState != STOPPED) {
+ return 0;
+ }
+
+ switch (mFormat) {
+ case Format::VP8:
+ {
+ mEncoder.reset(
+ new VPXEncoder(mScreenWidth, mScreenHeight, mScreenRate));
+
+ break;
+ }
+
+ default:
+ LOG(FATAL) << "Should not be here.";
+ }
+
+ mState = RUNNING;
+
+ return 0;
+}
+
+int32_t FrameBufferSource::stop() {
+ std::lock_guard<std::mutex> autoLock(mLock);
+
+ if (mState == STOPPED) {
+ return 0;
+ }
+
+ mState = STOPPING;
+
+ mState = STOPPED;
+
+ mEncoder.reset();
+
+ return 0;
+}
+
+int32_t FrameBufferSource::pause() {
+ std::lock_guard<std::mutex> autoLock(mLock);
+
+ if (mState == PAUSED) {
+ return 0;
+ }
+
+ if (mState != RUNNING) {
+ return -EINVAL;
+ }
+
+ mState = PAUSED;
+
+ LOG(VERBOSE) << "Now paused.";
+
+ return 0;
+}
+
+int32_t FrameBufferSource::resume() {
+ std::lock_guard<std::mutex> autoLock(mLock);
+
+ if (mState == RUNNING) {
+ return 0;
+ }
+
+ if (mState != PAUSED) {
+ return -EINVAL;
+ }
+
+ mState = RUNNING;
+
+ LOG(VERBOSE) << "Now running.";
+
+ return 0;
+}
+
+bool FrameBufferSource::paused() const {
+ return mState == PAUSED;
+}
+
+int32_t FrameBufferSource::requestIDRFrame() {
+ mEncoder->forceIDRFrame();
+
+ return 0;
+}
+
+void FrameBufferSource::setScreenParams(const int32_t screenParams[4]) {
+ mScreenWidth = screenParams[0];
+ mScreenHeight = screenParams[1];
+ mScreenDpi = screenParams[2];
+ mScreenRate = screenParams[3];
+}
+
+void FrameBufferSource::injectFrame(const void *data, size_t size) {
+ // Only used in the case of CrosVM operation.
+ (void)size;
+
+ std::lock_guard<std::mutex> autoLock(mLock);
+ if (mState != State::RUNNING) {
+ return;
+ }
+
+ mEncoder->storeFrame(data);
+ // Only encode and forward the frame when there are consumers connected
+ if (mNumConsumers) {
+ auto accessUnit = mEncoder->encodeStoredFrame(GetNowUs());
+ StreamingSource::onAccessUnit(accessUnit);
+ }
+}
+
+void FrameBufferSource::notifyNewStreamConsumer() {
+ std::lock_guard<std::mutex> autoLock(mLock);
+ ++mNumConsumers;
+ if (mState != State::RUNNING) {
+ return;
+ }
+
+ mEncoder->forceIDRFrame();
+ auto accessUnit = mEncoder->encodeStoredFrame(GetNowUs());
+ if (!accessUnit) {
+ // nullptr means there isn't a stored frame to encode.
+ return;
+ }
+
+ StreamingSource::onAccessUnit(accessUnit);
+}
+
+void FrameBufferSource::notifyStreamConsumerDisconnected() {
+ std::lock_guard<std::mutex> autoLock(mLock);
+ --mNumConsumers;
+}
+
+} // namespace android
diff --git a/host/frontend/gcastv2/libsource/HostToGuestComms.cpp b/host/frontend/gcastv2/libsource/HostToGuestComms.cpp
new file mode 100644
index 000000000..44b9b5b7e
--- /dev/null
+++ b/host/frontend/gcastv2/libsource/HostToGuestComms.cpp
@@ -0,0 +1,408 @@
+/*
+ * 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.
+ */
+
+#include <source/HostToGuestComms.h>
+
+#include <https/SafeCallbackable.h>
+#include <https/Support.h>
+
+#include <android-base/logging.h>
+
+HostToGuestComms::HostToGuestComms(
+ std::shared_ptr<RunLoop> runLoop,
+ bool isServer,
+ int fd,
+ ReceiveCb onReceive)
+ : mRunLoop(runLoop),
+ mIsServer(isServer),
+ mOnReceive(onReceive),
+ mServerSock(-1),
+ mSock(-1),
+ mInBufferLen(0),
+ mSendPending(false),
+ mConnected(false) {
+ makeFdNonblocking(fd);
+ if (mIsServer) {
+ mServerSock = fd;
+ } else {
+ mSock = fd;
+ }
+}
+
+HostToGuestComms::HostToGuestComms(
+ std::shared_ptr<RunLoop> runLoop,
+ bool isServer,
+ uint32_t cid,
+ uint16_t port,
+ ReceiveCb onReceive)
+ : mRunLoop(runLoop),
+ mIsServer(isServer),
+ mOnReceive(onReceive),
+ mServerSock(-1),
+ mSock(-1),
+ mInBufferLen(0),
+ mSendPending(false),
+ mConnected(false) {
+ int s = socket(AF_VSOCK, SOCK_STREAM, 0);
+ CHECK_GE(s, 0);
+
+ LOG(INFO) << "HostToGuestComms created socket " << s;
+
+ makeFdNonblocking(s);
+
+ sockaddr_vm addr;
+ memset(&addr, 0, sizeof(addr));
+ addr.svm_family = AF_VSOCK;
+ addr.svm_port = port;
+ addr.svm_cid = cid;
+
+ int res;
+ if (mIsServer) {
+ LOG(INFO)
+ << "Binding to cid "
+ << (addr.svm_cid == VMADDR_CID_ANY)
+ ? "VMADDR_CID_ANY" : std::to_string(addr.svm_cid);
+
+ res = bind(s, reinterpret_cast<const sockaddr *>(&addr), sizeof(addr));
+
+ if (res) {
+ LOG(ERROR)
+ << (mIsServer ? "bind" : "connect")
+ << " FAILED w/ errno "
+ << errno
+ << " ("
+ << strerror(errno)
+ << ")";
+ }
+
+ CHECK(!res);
+
+ res = listen(s, 4);
+ CHECK(!res);
+
+ mServerSock = s;
+ } else {
+ mSock = s;
+ mConnectToAddr = addr;
+ }
+}
+
+HostToGuestComms::~HostToGuestComms() {
+ if (mSock >= 0) {
+ mRunLoop->cancelSocket(mSock);
+
+ close(mSock);
+ mSock = -1;
+ }
+
+ if (mServerSock >= 0) {
+ mRunLoop->cancelSocket(mServerSock);
+
+ close(mServerSock);
+ mServerSock = -1;
+ }
+}
+
+void HostToGuestComms::start() {
+ if (mIsServer) {
+ mRunLoop->postSocketRecv(
+ mServerSock,
+ makeSafeCallback(this, &HostToGuestComms::onServerConnection));
+ } else {
+ mRunLoop->postWithDelay(
+ std::chrono::milliseconds(5000),
+ makeSafeCallback(
+ this,
+ &HostToGuestComms::onAttemptToConnect,
+ mConnectToAddr));
+ }
+}
+
+void HostToGuestComms::send(const void *data, size_t size, bool addFraming) {
+ if (!size) {
+ return;
+ }
+
+ std::lock_guard autoLock(mLock);
+
+ size_t offset = mOutBuffer.size();
+
+ if (addFraming) {
+ uint32_t packetLen = size;
+ size_t totalSize = sizeof(packetLen) + size;
+
+ mOutBuffer.resize(offset + totalSize);
+ memcpy(mOutBuffer.data() + offset, &packetLen, sizeof(packetLen));
+ memcpy(mOutBuffer.data() + offset + sizeof(packetLen), data, size);
+ } else {
+ mOutBuffer.resize(offset + size);
+ memcpy(mOutBuffer.data() + offset, data, size);
+ }
+
+ if (mSock >= 0 && (mIsServer || mConnected) && !mSendPending) {
+ mSendPending = true;
+ mRunLoop->postSocketSend(
+ mSock,
+ makeSafeCallback(this, &HostToGuestComms::onSocketSend));
+ }
+}
+
+void HostToGuestComms::onServerConnection() {
+ int s = accept(mServerSock, nullptr, nullptr);
+
+ if (s >= 0) {
+ if (mSock >= 0) {
+ LOG(INFO) << "Rejecting client, we already have one.";
+
+ // We already have a client.
+ close(s);
+ s = -1;
+ } else {
+ LOG(INFO) << "Accepted client socket " << s << ".";
+
+ makeFdNonblocking(s);
+
+ mSock = s;
+ mRunLoop->postSocketRecv(
+ mSock,
+ makeSafeCallback(this, &HostToGuestComms::onSocketReceive));
+
+ std::lock_guard autoLock(mLock);
+ if (!mOutBuffer.empty()) {
+ CHECK(!mSendPending);
+
+ mSendPending = true;
+ mRunLoop->postSocketSend(
+ mSock,
+ makeSafeCallback(
+ this, &HostToGuestComms::onSocketSend));
+ }
+ }
+ }
+
+ mRunLoop->postSocketRecv(
+ mServerSock,
+ makeSafeCallback(this, &HostToGuestComms::onServerConnection));
+}
+
+void HostToGuestComms::onSocketReceive() {
+ ssize_t n;
+ for (;;) {
+ static constexpr size_t kChunkSize = 65536;
+
+ mInBuffer.resize(mInBufferLen + kChunkSize);
+
+ do {
+ n = recv(mSock, mInBuffer.data() + mInBufferLen, kChunkSize, 0);
+ } while (n < 0 && errno == EINTR);
+
+ if (n <= 0) {
+ break;
+ }
+
+ mInBufferLen += static_cast<size_t>(n);
+ }
+
+ int savedErrno = errno;
+
+ drainInBuffer();
+
+ if ((n < 0 && savedErrno != EAGAIN && savedErrno != EWOULDBLOCK)
+ || n == 0) {
+ LOG(ERROR) << "Client is gone.";
+
+ // Client is gone.
+ mRunLoop->cancelSocket(mSock);
+
+ mSendPending = false;
+
+ close(mSock);
+ mSock = -1;
+ return;
+ }
+
+ mRunLoop->postSocketRecv(
+ mSock,
+ makeSafeCallback(this, &HostToGuestComms::onSocketReceive));
+}
+
+void HostToGuestComms::drainInBuffer() {
+ for (;;) {
+ uint32_t packetLen;
+
+ if (mInBufferLen < sizeof(packetLen)) {
+ return;
+ }
+
+ memcpy(&packetLen, mInBuffer.data(), sizeof(packetLen));
+
+ size_t totalLen = sizeof(packetLen) + packetLen;
+
+ if (mInBufferLen < totalLen) {
+ return;
+ }
+
+ if (mOnReceive) {
+ // LOG(INFO) << "Dispatching packet of size " << packetLen;
+
+ mOnReceive(mInBuffer.data() + sizeof(packetLen), packetLen);
+ }
+
+ mInBuffer.erase(mInBuffer.begin(), mInBuffer.begin() + totalLen);
+ mInBufferLen -= totalLen;
+ }
+}
+
+void HostToGuestComms::onSocketSend() {
+ std::lock_guard autoLock(mLock);
+
+ CHECK(mSendPending);
+ mSendPending = false;
+
+ if (mSock < 0) {
+ return;
+ }
+
+ ssize_t n;
+ while (!mOutBuffer.empty()) {
+ do {
+ n = ::send(mSock, mOutBuffer.data(), mOutBuffer.size(), 0);
+ } while (n < 0 && errno == EINTR);
+
+ if (n <= 0) {
+ break;
+ }
+
+ mOutBuffer.erase(mOutBuffer.begin(), mOutBuffer.begin() + n);
+ }
+
+ if ((n < 0 && errno != EAGAIN && errno != EWOULDBLOCK) || n == 0) {
+ LOG(ERROR) << "Client is gone.";
+
+ // Client is gone.
+ mRunLoop->cancelSocket(mSock);
+
+ close(mSock);
+ mSock = -1;
+ return;
+ }
+
+ if (!mOutBuffer.empty()) {
+ mSendPending = true;
+ mRunLoop->postSocketSend(
+ mSock,
+ makeSafeCallback(this, &HostToGuestComms::onSocketSend));
+ }
+}
+
+void HostToGuestComms::onAttemptToConnect(const sockaddr_vm &addr) {
+ LOG(VERBOSE) << "Attempting to connect to cid " << addr.svm_cid;
+
+ int res;
+ do {
+ res = connect(
+ mSock, reinterpret_cast<const sockaddr *>(&addr), sizeof(addr));
+ } while (res < 0 && errno == EINTR);
+
+ if (res < 0) {
+ if (errno == EINPROGRESS) {
+ LOG(VERBOSE) << "EINPROGRESS, waiting to check the connection.";
+
+ mRunLoop->postSocketSend(
+ mSock,
+ makeSafeCallback(
+ this, &HostToGuestComms::onCheckConnection, addr));
+
+ return;
+ }
+
+ LOG(INFO)
+ << "Our attempt to connect to the guest FAILED w/ error "
+ << errno
+ << " ("
+ << strerror(errno)
+ << "), will try again shortly.";
+
+ mRunLoop->postWithDelay(
+ std::chrono::milliseconds(5000),
+ makeSafeCallback(
+ this, &HostToGuestComms::onAttemptToConnect, addr));
+
+ return;
+ }
+
+ onConnected();
+}
+
+void HostToGuestComms::onCheckConnection(const sockaddr_vm &addr) {
+ int err;
+
+ int res;
+ do {
+ socklen_t errSize = sizeof(err);
+
+ res = getsockopt(mSock, SOL_SOCKET, SO_ERROR, &err, &errSize);
+ } while (res < 0 && errno == EINTR);
+
+ CHECK(!res);
+
+ if (!err) {
+ onConnected();
+ } else {
+ LOG(VERBOSE)
+ << "Connection failed w/ error "
+ << err
+ << " ("
+ << strerror(err)
+ << "), will try again shortly.";
+
+ // Is there a better way of cancelling the (failed) connection that
+ // somehow is still in progress on the socket and restarting it?
+ mRunLoop->cancelSocket(mSock);
+
+ close(mSock);
+ mSock = socket(AF_VSOCK, SOCK_STREAM, 0);
+ CHECK_GE(mSock, 0);
+
+ makeFdNonblocking(mSock);
+
+ mRunLoop->postWithDelay(
+ std::chrono::milliseconds(5000),
+ makeSafeCallback(
+ this, &HostToGuestComms::onAttemptToConnect, addr));
+ }
+}
+
+void HostToGuestComms::onConnected() {
+ LOG(INFO) << "Connected to guest.";
+
+ std::lock_guard autoLock(mLock);
+
+ mConnected = true;
+ CHECK(!mSendPending);
+
+ if (!mOutBuffer.empty()) {
+ mSendPending = true;
+ mRunLoop->postSocketSend(
+ mSock,
+ makeSafeCallback(this, &HostToGuestComms::onSocketSend));
+ }
+
+ mRunLoop->postSocketRecv(
+ mSock,
+ makeSafeCallback(this, &HostToGuestComms::onSocketReceive));
+}
+
diff --git a/host/frontend/gcastv2/libsource/InputSink.cpp b/host/frontend/gcastv2/libsource/InputSink.cpp
new file mode 100644
index 000000000..d72ca68f2
--- /dev/null
+++ b/host/frontend/gcastv2/libsource/InputSink.cpp
@@ -0,0 +1,218 @@
+/*
+ * 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.
+ */
+
+#include <source/InputSink.h>
+
+#include <linux/input.h>
+
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <android-base/logging.h>
+#include <https/SafeCallbackable.h>
+#include <https/Support.h>
+
+namespace android {
+
+namespace {
+
+// TODO de-dup this from vnc server and here
+struct virtio_input_event {
+ uint16_t type;
+ uint16_t code;
+ int32_t value;
+};
+
+template <typename T>
+struct InputEventBufferImpl : public InputEventBuffer {
+ InputEventBufferImpl() {
+ buffer_.reserve(6); // 6 is usually enough even for multi-touch
+ }
+ void addEvent(uint16_t type, uint16_t code, int32_t value) override {
+ buffer_.push_back({.type = type, .code = code, .value = value});
+ }
+ T* data() { return buffer_.data(); }
+ const void* data() const override { return buffer_.data(); }
+ std::size_t size() const override { return buffer_.size() * sizeof(T); }
+
+ private:
+ std::vector<T> buffer_;
+};
+
+} // namespace
+
+InputSink::InputSink(std::shared_ptr<RunLoop> runLoop, int serverFd,
+ bool write_virtio_input)
+ : mRunLoop(runLoop),
+ mServerFd(serverFd),
+ mClientFd(-1),
+ mSendPending(false),
+ mWriteVirtioInput(write_virtio_input) {
+ if (mServerFd >= 0) {
+ makeFdNonblocking(mServerFd);
+ }
+}
+
+InputSink::~InputSink() {
+ if (mClientFd >= 0) {
+ mRunLoop->cancelSocket(mClientFd);
+
+ close(mClientFd);
+ mClientFd = -1;
+ }
+
+ if (mServerFd >= 0) {
+ mRunLoop->cancelSocket(mServerFd);
+
+ close(mServerFd);
+ mServerFd = -1;
+ }
+}
+
+void InputSink::start() {
+ if (mServerFd < 0) {
+ return;
+ }
+
+ mRunLoop->postSocketRecv(
+ mServerFd, makeSafeCallback(this, &InputSink::onServerConnection));
+}
+
+std::unique_ptr<InputEventBuffer> InputSink::getEventBuffer() const {
+ InputEventBuffer* raw_ptr;
+ if (mWriteVirtioInput) {
+ raw_ptr = new InputEventBufferImpl<virtio_input_event>();
+ } else {
+ raw_ptr = new InputEventBufferImpl<input_event>();
+ }
+ return std::unique_ptr<InputEventBuffer>(raw_ptr);
+}
+
+void InputSink::SendEvents(std::unique_ptr<InputEventBuffer> evt_buffer) {
+ sendRawEvents(evt_buffer->data(), evt_buffer->size());
+}
+
+void InputSink::onServerConnection() {
+ int s = accept(mServerFd, nullptr, nullptr);
+
+ if (s >= 0) {
+ if (mClientFd >= 0) {
+ LOG(INFO) << "Rejecting client, we already have one.";
+
+ // We already have a client.
+ close(s);
+ s = -1;
+ } else {
+ LOG(INFO) << "Accepted client socket " << s << ".";
+
+ makeFdNonblocking(s);
+
+ mClientFd = s;
+ mRunLoop->postSocketRecv(
+ mClientFd, makeSafeCallback(this, &InputSink::onSocketRecv));
+ }
+ }
+
+ mRunLoop->postSocketRecv(
+ mServerFd, makeSafeCallback(this, &InputSink::onServerConnection));
+}
+
+void InputSink::sendRawEvents(const void* evt_buffer, size_t size) {
+ if (size <= 0) return;
+
+ std::lock_guard autoLock(mLock);
+
+ if (mClientFd < 0) {
+ return;
+ }
+
+ size_t offset = mOutBuffer.size();
+ mOutBuffer.resize(offset + size);
+ memcpy(mOutBuffer.data() + offset, evt_buffer, size);
+
+ if (!mSendPending) {
+ mSendPending = true;
+
+ mRunLoop->postSocketSend(mClientFd,
+ makeSafeCallback(this, &InputSink::onSocketSend));
+ }
+}
+
+void InputSink::onSocketRecv() {
+ if (mClientFd < 0) return;
+
+ char buff[512];
+ auto n = recv(mClientFd, buff, sizeof(buff), 0 /* flags */);
+ if (n > 0) {
+ LOG(INFO) << "Discarding " << n << " bytes received from the input device.";
+ mRunLoop->postSocketRecv(
+ mClientFd, makeSafeCallback(this, &InputSink::onSocketRecv));
+ } else {
+ // Client disconnected
+ if (n < 0) {
+ auto errno_save = errno;
+ LOG(ERROR) << "Error receiving from socket: " << strerror(errno_save);
+ }
+ mRunLoop->cancelSocket(mClientFd);
+ close(mClientFd);
+ mClientFd = -1;
+ }
+}
+
+void InputSink::onSocketSend() {
+ std::lock_guard autoLock(mLock);
+
+ CHECK(mSendPending);
+ mSendPending = false;
+
+ if (mClientFd < 0) {
+ return;
+ }
+
+ ssize_t n;
+ while (!mOutBuffer.empty()) {
+ do {
+ n = ::send(mClientFd, mOutBuffer.data(), mOutBuffer.size(), 0);
+ } while (n < 0 && errno == EINTR);
+
+ if (n <= 0) {
+ break;
+ }
+
+ mOutBuffer.erase(mOutBuffer.begin(), mOutBuffer.begin() + n);
+ }
+
+ if ((n < 0 && errno != EAGAIN && errno != EWOULDBLOCK) || n == 0) {
+ LOG(ERROR) << "Client is gone.";
+
+ // Client is gone.
+ mRunLoop->cancelSocket(mClientFd);
+
+ close(mClientFd);
+ mClientFd = -1;
+ return;
+ }
+
+ if (!mOutBuffer.empty()) {
+ mSendPending = true;
+ mRunLoop->postSocketSend(mClientFd,
+ makeSafeCallback(this, &InputSink::onSocketSend));
+ }
+}
+
+} // namespace android
diff --git a/host/libs/allocd/resource.cpp b/host/frontend/gcastv2/libsource/KeyboardSink.cpp
index 881dd8519..cf19b3878 100644
--- a/host/libs/allocd/resource.cpp
+++ b/host/frontend/gcastv2/libsource/KeyboardSink.cpp
@@ -14,30 +14,30 @@
* limitations under the License.
*/
-#include "host/libs/allocd/resource.h"
+#include <source/KeyboardSink.h>
-#include <android-base/logging.h>
-
-#include "host/libs/allocd/alloc_utils.h"
-
-namespace cuttlefish {
-
-bool MobileIface::AcquireResource() {
- return CreateMobileIface(GetName(), iface_id_, ipaddr_);
-}
+#include <linux/input.h>
-bool MobileIface::ReleaseResource() {
- return DestroyMobileIface(GetName(), iface_id_, ipaddr_);
-}
+#include <android-base/logging.h>
-bool EthernetIface::AcquireResource() {
- return CreateEthernetIface(GetName(), GetBridgeName(), has_ipv4_, has_ipv6_,
- use_ebtables_legacy_);
+namespace android {
+
+KeyboardSink::KeyboardSink(std::shared_ptr<RunLoop> runLoop, int serverFd,
+ bool write_virtio_input)
+ : sink_(
+ std::make_shared<InputSink>(runLoop, serverFd, write_virtio_input)) {}
+
+void KeyboardSink::injectEvent(bool down, uint16_t code) {
+ LOG(VERBOSE)
+ << "Received keyboard (down="
+ << down
+ << ", code="
+ << code;
+ auto buffer = sink_->getEventBuffer();
+ buffer->addEvent(EV_KEY, code, down);
+ buffer->addEvent(EV_SYN, 0, 0);
+ sink_->SendEvents(std::move(buffer));
}
-bool EthernetIface::ReleaseResource() {
- return DestroyEthernetIface(GetName(), has_ipv4_, has_ipv6_,
- use_ebtables_legacy_);
-}
+} // namespace android
-} // namespace cuttlefish
diff --git a/host/commands/assemble_cvd/boot_config.h b/host/frontend/gcastv2/libsource/StreamingSource.cpp
index 1a81b7975..d96bf2b2a 100644
--- a/host/commands/assemble_cvd/boot_config.h
+++ b/host/frontend/gcastv2/libsource/StreamingSource.cpp
@@ -13,14 +13,24 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-#pragma once
-#include <string>
-#include <host/libs/config/cuttlefish_config.h>
+#include <source/StreamingSource.h>
-namespace cuttlefish {
+namespace android {
-bool InitBootloaderEnvPartition(const CuttlefishConfig& config,
- const CuttlefishConfig::InstanceSpecific& instance);
+StreamingSource::StreamingSource()
+ : mCallbackFn(nullptr) {
+}
-} // namespace cuttlefish
+void StreamingSource::setCallback(std::function<void(const std::shared_ptr<SBuffer> &)> cb) {
+ CHECK(cb);
+ mCallbackFn = cb;
+}
+
+void StreamingSource::onAccessUnit(const std::shared_ptr<SBuffer> &accessUnit) {
+ if (mCallbackFn) {
+ mCallbackFn(accessUnit);
+ }
+}
+
+} // namespace android
diff --git a/host/frontend/gcastv2/libsource/TouchSink.cpp b/host/frontend/gcastv2/libsource/TouchSink.cpp
new file mode 100644
index 000000000..a66744f6d
--- /dev/null
+++ b/host/frontend/gcastv2/libsource/TouchSink.cpp
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ */
+
+#include <source/TouchSink.h>
+
+#include <https/SafeCallbackable.h>
+#include <https/Support.h>
+
+#include <android-base/logging.h>
+
+#include <linux/input.h>
+
+#include <sys/socket.h>
+#include <unistd.h>
+
+namespace android {
+
+TouchSink::TouchSink(std::shared_ptr<RunLoop> runLoop, int serverFd,
+ bool write_virtio_input)
+ : sink_(
+ std::make_shared<InputSink>(runLoop, serverFd, write_virtio_input)) {}
+
+void TouchSink::injectTouchEvent(int32_t x, int32_t y, bool down) {
+ LOG(VERBOSE)
+ << "Received touch (down="
+ << down
+ << ", x="
+ << x
+ << ", y="
+ << y;
+
+ auto buffer = sink_->getEventBuffer();
+ buffer->addEvent(EV_ABS, ABS_X, x);
+ buffer->addEvent(EV_ABS, ABS_Y, y);
+ buffer->addEvent(EV_KEY, BTN_TOUCH, down);
+ buffer->addEvent(EV_SYN, 0, 0);
+ sink_->SendEvents(std::move(buffer));
+}
+
+void TouchSink::injectMultiTouchEvent(int32_t /*id*/, int32_t /*slot*/,
+ int32_t x, int32_t y, bool initialDown) {
+ // TODO (muntsinger): Enable multitouch
+ return injectTouchEvent(x, y, initialDown);
+}
+
+} // namespace android
+
diff --git a/host/frontend/gcastv2/libsource/include/source/AudioSource.h b/host/frontend/gcastv2/libsource/include/source/AudioSource.h
new file mode 100644
index 000000000..7c7771eac
--- /dev/null
+++ b/host/frontend/gcastv2/libsource/include/source/AudioSource.h
@@ -0,0 +1,92 @@
+/*
+ * 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 <source/StreamingSource.h>
+
+#include <memory>
+#include <thread>
+
+#define SIMULATE_AUDIO 0
+
+namespace vsoc {
+ class RegionWorker;
+ namespace audio_data {
+ class AudioDataRegionView;
+ }
+}
+
+namespace android {
+
+struct AudioSource : public StreamingSource {
+ using AudioDataRegionView = vsoc::audio_data::AudioDataRegionView;
+
+ enum class Format {
+ OPUS,
+ G711_ALAW,
+ G711_ULAW,
+ };
+ // ADTS framing is only supported for AAC.
+ explicit AudioSource(Format format, bool useADTSFraming = false);
+
+ AudioSource(const AudioSource &) = delete;
+ AudioSource &operator=(const AudioSource &) = delete;
+
+ ~AudioSource() override;
+
+ int32_t initCheck() const override;
+
+ int32_t start() override;
+ int32_t stop() override;
+
+ int32_t requestIDRFrame() override;
+ void notifyNewStreamConsumer() override {}
+ void notifyStreamConsumerDisconnected() override {}
+
+ void inject(const void *data, size_t size);
+
+private:
+ enum State {
+ STOPPING,
+ STOPPED,
+ RUNNING,
+ PAUSED
+ };
+
+ struct Encoder;
+ struct OPUSEncoder;
+ struct G711Encoder;
+
+ int32_t mInitCheck;
+ State mState;
+ std::unique_ptr<Encoder> mEncoder;
+
+ std::mutex mLock;
+ std::unique_ptr<std::thread> mThread;
+
+#if SIMULATE_AUDIO
+ static constexpr int32_t kSampleRate = 44100;
+ static constexpr int32_t kNumChannels = 2;
+ static constexpr size_t kNumFramesPerBuffer = 400;
+ static constexpr int32_t kFrequency = 500;
+ size_t mPhase;
+#endif
+};
+
+} // namespace android
+
+
diff --git a/host/frontend/gcastv2/libsource/include/source/FrameBufferSource.h b/host/frontend/gcastv2/libsource/include/source/FrameBufferSource.h
new file mode 100644
index 000000000..7990be426
--- /dev/null
+++ b/host/frontend/gcastv2/libsource/include/source/FrameBufferSource.h
@@ -0,0 +1,81 @@
+/*
+ * 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 <source/StreamingSource.h>
+
+#include <functional>
+#include <memory>
+#include <thread>
+
+namespace android {
+
+struct FrameBufferSource : public StreamingSource {
+ enum class Format {
+ VP8,
+ };
+
+ explicit FrameBufferSource(Format format);
+
+ FrameBufferSource(const FrameBufferSource &) = delete;
+ FrameBufferSource &operator=(const FrameBufferSource &) = delete;
+
+ ~FrameBufferSource() override;
+
+ int32_t initCheck() const override;
+
+ int32_t start() override;
+ int32_t stop() override;
+
+ int32_t pause() override;
+ int32_t resume() override;
+
+ bool paused() const override;
+
+ int32_t requestIDRFrame() override;
+ void notifyNewStreamConsumer() override;
+ void notifyStreamConsumerDisconnected() override;
+
+ void setScreenParams(const int32_t screenParams[4]);
+ void injectFrame(const void *data, size_t size);
+
+private:
+ enum State {
+ STOPPING,
+ STOPPED,
+ RUNNING,
+ PAUSED
+ };
+
+ struct Encoder;
+ struct VPXEncoder;
+
+ int32_t mInitCheck;
+ State mState;
+ Format mFormat;
+ std::unique_ptr<Encoder> mEncoder;
+
+ std::mutex mLock;
+
+ int32_t mScreenWidth, mScreenHeight, mScreenDpi, mScreenRate, mNumConsumers;
+
+ std::function<void(const std::shared_ptr<SBuffer> &)> mOnFrameFn;
+};
+
+} // namespace android
+
+
diff --git a/host/frontend/gcastv2/libsource/include/source/HostToGuestComms.h b/host/frontend/gcastv2/libsource/include/source/HostToGuestComms.h
new file mode 100644
index 000000000..2325608b0
--- /dev/null
+++ b/host/frontend/gcastv2/libsource/include/source/HostToGuestComms.h
@@ -0,0 +1,75 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <https/RunLoop.h>
+
+#include <sys/socket.h>
+#include "common/libs/fs/vm_sockets.h"
+
+#include <memory>
+
+struct HostToGuestComms : std::enable_shared_from_this<HostToGuestComms> {
+ using ReceiveCb = std::function<void(const void *data, size_t size)>;
+
+ explicit HostToGuestComms(
+ std::shared_ptr<RunLoop> runLoop,
+ bool isServer,
+ uint32_t cid,
+ uint16_t port,
+ ReceiveCb onReceive);
+
+ explicit HostToGuestComms(
+ std::shared_ptr<RunLoop> runLoop,
+ bool isServer,
+ int fd,
+ ReceiveCb onReceive);
+
+ ~HostToGuestComms();
+
+ void start();
+
+ void send(const void *data, size_t size, bool addFraming = true);
+
+private:
+ std::shared_ptr<RunLoop> mRunLoop;
+ bool mIsServer;
+ ReceiveCb mOnReceive;
+
+ int mServerSock;
+ int mSock;
+ sockaddr_vm mConnectToAddr;
+
+ std::vector<uint8_t> mInBuffer;
+ size_t mInBufferLen;
+
+ std::mutex mLock;
+ std::vector<uint8_t> mOutBuffer;
+ bool mSendPending;
+
+ bool mConnected;
+
+ void onServerConnection();
+ void onSocketReceive();
+ void onSocketSend();
+ void drainInBuffer();
+
+ void onAttemptToConnect(const sockaddr_vm &addr);
+ void onCheckConnection(const sockaddr_vm &addr);
+ void onConnected();
+};
+
diff --git a/host/frontend/gcastv2/libsource/include/source/InputSink.h b/host/frontend/gcastv2/libsource/include/source/InputSink.h
new file mode 100644
index 000000000..38af13b79
--- /dev/null
+++ b/host/frontend/gcastv2/libsource/include/source/InputSink.h
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <array>
+#include <cinttypes>
+#include <functional>
+#include <memory>
+#include <vector>
+
+#include <https/RunLoop.h>
+
+namespace android {
+
+struct InputEventBuffer {
+ virtual ~InputEventBuffer() = default;
+ virtual void addEvent(uint16_t type, uint16_t code, int32_t value) = 0;
+ virtual size_t size() const = 0;
+ virtual const void* data() const = 0;
+};
+
+struct InputSink : public std::enable_shared_from_this<InputSink> {
+ explicit InputSink(std::shared_ptr<RunLoop> runLoop, int serverFd,
+ bool write_virtio_input);
+ ~InputSink();
+ void start();
+
+ std::unique_ptr<InputEventBuffer> getEventBuffer() const;
+ void SendEvents(std::unique_ptr<InputEventBuffer> evt_buffer);
+
+ private:
+ std::shared_ptr<RunLoop> mRunLoop;
+ int mServerFd;
+
+ int mClientFd;
+
+ std::mutex mLock;
+ std::vector<uint8_t> mOutBuffer;
+ bool mSendPending;
+ bool mWriteVirtioInput;
+
+ void onServerConnection();
+ void onSocketRecv();
+ void onSocketSend();
+
+ void sendRawEvents(const void* evt_buffer, size_t length);
+};
+
+} // namespace android
diff --git a/host/frontend/webrtc/lib/audio_frame_buffer.h b/host/frontend/gcastv2/libsource/include/source/KeyboardSink.h
index 4c656b5c7..cbc99361d 100644
--- a/host/frontend/webrtc/lib/audio_frame_buffer.h
+++ b/host/frontend/gcastv2/libsource/include/source/KeyboardSink.h
@@ -17,20 +17,25 @@
#pragma once
#include <cinttypes>
+#include <memory>
-namespace cuttlefish {
-namespace webrtc_streaming {
+#include <https/RunLoop.h>
+#include <source/InputSink.h>
-class AudioFrameBuffer {
- public:
- virtual ~AudioFrameBuffer() = default;
+namespace android {
- virtual int bits_per_sample() const = 0;
- virtual int sample_rate() const = 0;
- virtual int channels() const = 0;
- virtual int frames() const = 0;
- virtual const uint8_t* data() const = 0;
+struct KeyboardSink {
+ explicit KeyboardSink(std::shared_ptr<RunLoop> runLoop, int serverFd,
+ bool write_virtio_input);
+ ~KeyboardSink() = default;
+
+ void start() {sink_->start();}
+
+ void injectEvent(bool down, uint16_t code);
+
+ private:
+ std::shared_ptr<InputSink> sink_;
};
-} // namespace webrtc_streaming
-} // namespace cuttlefish
+} // namespace android
+
diff --git a/host/frontend/gcastv2/libsource/include/source/StreamingSource.h b/host/frontend/gcastv2/libsource/include/source/StreamingSource.h
new file mode 100644
index 000000000..27a30a4d8
--- /dev/null
+++ b/host/frontend/gcastv2/libsource/include/source/StreamingSource.h
@@ -0,0 +1,104 @@
+/*
+ * 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 <android-base/logging.h>
+
+#include <cinttypes>
+#include <memory>
+#include <vector>
+
+namespace android {
+
+class SBuffer {
+public:
+ SBuffer() = delete;
+ SBuffer(const SBuffer&) = delete;
+ SBuffer(SBuffer&&) = default;
+ explicit SBuffer(std::size_t size)
+ : buffer_(size, 0), time_us_(0) {}
+
+ SBuffer& operator=(const SBuffer&) = delete;
+ SBuffer& operator=(SBuffer&&) = default;
+
+ std::size_t capacity() const {
+ return buffer_.capacity();
+ }
+
+ std::size_t size() const {
+ return buffer_.size();
+ }
+
+ void resize(std::size_t size) {
+ buffer_.resize(size);
+ }
+
+ uint8_t* data() {
+ return buffer_.data();
+ }
+
+ const uint8_t* data() const {
+ return buffer_.data();
+ }
+
+ int64_t time_us() const {
+ return time_us_;
+ }
+
+ void time_us(int64_t time_us) {
+ time_us_ = time_us;
+ }
+private:
+ std::vector<uint8_t> buffer_;
+ int64_t time_us_;
+
+};
+
+struct StreamingSource {
+ explicit StreamingSource();
+
+ StreamingSource(const StreamingSource &) = delete;
+ StreamingSource &operator=(const StreamingSource &) = delete;
+
+ virtual ~StreamingSource() = default;
+
+ virtual int32_t initCheck() const = 0;
+
+ void setCallback(std::function<void(const std::shared_ptr<SBuffer> &)> cb);
+
+ virtual int32_t start() = 0;
+ virtual int32_t stop() = 0;
+
+ virtual bool canPause() { return false; }
+ virtual int32_t pause() { return -EINVAL; }
+ virtual int32_t resume() { return -EINVAL; }
+
+ virtual bool paused() const { return false; }
+
+ virtual int32_t requestIDRFrame() = 0;
+ virtual void notifyNewStreamConsumer() = 0;
+ virtual void notifyStreamConsumerDisconnected() = 0;
+
+protected:
+ void onAccessUnit(const std::shared_ptr<SBuffer> &accessUnit);
+
+private:
+ std::function<void(const std::shared_ptr<SBuffer> &)> mCallbackFn;
+};
+
+} // namespace android
+
diff --git a/host/frontend/webrtc/adb_handler.h b/host/frontend/gcastv2/libsource/include/source/TouchSink.h
index 24a06d6bc..d4490f0e0 100644
--- a/host/frontend/webrtc/adb_handler.h
+++ b/host/frontend/gcastv2/libsource/include/source/TouchSink.h
@@ -16,35 +16,29 @@
#pragma once
-#include <memory>
-#include <thread>
+#include <https/RunLoop.h>
-#include "common/libs/fs/shared_fd.h"
-#include "common/libs/fs/shared_select.h"
+#include <memory>
-namespace cuttlefish {
-namespace webrtc_streaming {
+#include <source/InputSink.h>
-struct AdbHandler {
- explicit AdbHandler(const std::string
- &adb_host_and_port,
- std::function<void(const uint8_t *, size_t)> send_to_client);
+namespace android {
- ~AdbHandler();
+struct TouchSink {
+ explicit TouchSink(std::shared_ptr<RunLoop> runLoop, int serverFd,
+ bool write_virtio_input);
+ ~TouchSink() = default;
- void handleMessage(const uint8_t *msg, size_t len);
+ void start() {sink_->start();}
- private:
+ void injectTouchEvent(int32_t x, int32_t y, bool down);
+ void injectMultiTouchEvent(int32_t id, int32_t slot, int32_t x, int32_t y,
+ bool initialDown);
- std::function<void(const uint8_t *, size_t)> send_to_client_;
+ private:
+ std::shared_ptr<InputSink> sink_;
+};
- void ReadLoop();
+} // namespace android
- SharedFD adb_socket_;
- SharedFD shutdown_;
- SharedFDSet read_set_;
- std::thread read_thread_;
-};
-} // namespace webrtc_streaming
-} // namespace cuttlefish
diff --git a/host/frontend/gcastv2/webrtc/AdbWebSocketHandler.cpp b/host/frontend/gcastv2/webrtc/AdbWebSocketHandler.cpp
new file mode 100644
index 000000000..dcb6d503d
--- /dev/null
+++ b/host/frontend/gcastv2/webrtc/AdbWebSocketHandler.cpp
@@ -0,0 +1,259 @@
+/*
+ * 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.
+ */
+
+#include <webrtc/AdbWebSocketHandler.h>
+
+#include "Utils.h"
+
+#include <https/BaseConnection.h>
+#include <https/Support.h>
+
+#include <android-base/logging.h>
+
+#include <unistd.h>
+
+using namespace android;
+
+struct AdbWebSocketHandler::AdbConnection : public BaseConnection {
+ explicit AdbConnection(
+ AdbWebSocketHandler *parent,
+ std::shared_ptr<RunLoop> runLoop,
+ int sock);
+
+ void send(const void *_data, size_t size);
+
+protected:
+ ssize_t processClientRequest(const void *data, size_t size) override;
+ void onDisconnect(int err) override;
+
+private:
+ AdbWebSocketHandler *mParent;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+AdbWebSocketHandler::AdbConnection::AdbConnection(
+ AdbWebSocketHandler *parent,
+ std::shared_ptr<RunLoop> runLoop,
+ int sock)
+ : BaseConnection(runLoop, sock),
+ mParent(parent) {
+}
+
+// Thanks for calling it a crc32, adb documentation!
+static uint32_t computeNotACrc32(const void *_data, size_t size) {
+ auto data = static_cast<const uint8_t *>(_data);
+ uint32_t sum = 0;
+ for (size_t i = 0; i < size; ++i) {
+ sum += data[i];
+ }
+
+ return sum;
+}
+
+static int verifyAdbHeader(
+ const void *_data, size_t size, size_t *_payloadLength) {
+ auto data = static_cast<const uint8_t *>(_data);
+
+ *_payloadLength = 0;
+
+ if (size < 24) {
+ return -EAGAIN;
+ }
+
+ uint32_t command = U32LE_AT(data);
+ uint32_t magic = U32LE_AT(data + 20);
+
+ if (command != (magic ^ 0xffffffff)) {
+ return -EINVAL;
+ }
+
+ uint32_t payloadLength = U32LE_AT(data + 12);
+
+ if (size < 24 + payloadLength) {
+ return -EAGAIN;
+ }
+
+ auto payloadCrc = U32LE_AT(data + 16);
+ auto crc32 = computeNotACrc32(data + 24, payloadLength);
+
+ if (payloadCrc != crc32) {
+ return -EINVAL;
+ }
+
+ *_payloadLength = payloadLength;
+
+ return 0;
+}
+
+ssize_t AdbWebSocketHandler::AdbConnection::processClientRequest(
+ const void *_data, size_t size) {
+ auto data = static_cast<const uint8_t *>(_data);
+
+ LOG(VERBOSE)
+ << "AdbConnection::processClientRequest (size = " << size << ")";
+
+ // hexdump(data, size);
+
+ size_t payloadLength;
+ int err = verifyAdbHeader(data, size, &payloadLength);
+
+ if (err) {
+ return err;
+ }
+
+ mParent->sendMessage(
+ data, payloadLength + 24, WebSocketHandler::SendMode::binary);
+
+ return payloadLength + 24;
+}
+
+void AdbWebSocketHandler::AdbConnection::onDisconnect(int err) {
+ LOG(INFO) << "AdbConnection::onDisconnect(err=" << err << ")";
+
+ mParent->sendMessage(
+ nullptr /* data */,
+ 0 /* size */,
+ WebSocketHandler::SendMode::closeConnection);
+}
+
+void AdbWebSocketHandler::AdbConnection::send(const void *_data, size_t size) {
+ BaseConnection::send(_data, size);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+AdbWebSocketHandler::AdbWebSocketHandler(
+ std::shared_ptr<RunLoop> runLoop,
+ const std::string &adb_host_and_port)
+ : mRunLoop(runLoop),
+ mSocket(-1) {
+ LOG(INFO) << "Connecting to " << adb_host_and_port;
+
+ auto err = setupSocket(adb_host_and_port);
+ CHECK(!err);
+
+ mAdbConnection = std::make_shared<AdbConnection>(this, mRunLoop, mSocket);
+}
+
+AdbWebSocketHandler::~AdbWebSocketHandler() {
+ if (mSocket >= 0) {
+ close(mSocket);
+ mSocket = -1;
+ }
+}
+
+void AdbWebSocketHandler::run() {
+ mAdbConnection->run();
+}
+
+int AdbWebSocketHandler::setupSocket(const std::string &adb_host_and_port) {
+ auto colonPos = adb_host_and_port.find(':');
+ if (colonPos == std::string::npos) {
+ return -EINVAL;
+ }
+
+ auto host = adb_host_and_port.substr(0, colonPos);
+
+ const char *portString = adb_host_and_port.c_str() + colonPos + 1;
+ char *end;
+ unsigned long port = strtoul(portString, &end, 10);
+
+ if (end == portString || *end != '\0' || port > 65535) {
+ return -EINVAL;
+ }
+
+ int err;
+
+ int sock = socket(PF_INET, SOCK_STREAM, 0);
+
+ if (sock < 0) {
+ err = -errno;
+ goto bail;
+ }
+
+ makeFdNonblocking(sock);
+
+ sockaddr_in addr;
+ memset(addr.sin_zero, 0, sizeof(addr.sin_zero));
+ addr.sin_family = AF_INET;
+ addr.sin_addr.s_addr = inet_addr(host.c_str());
+ addr.sin_port = htons(port);
+
+ if (connect(sock,
+ reinterpret_cast<const sockaddr *>(&addr),
+ sizeof(addr)) < 0
+ && errno != EINPROGRESS) {
+ err = -errno;
+ goto bail2;
+ }
+
+ mSocket = sock;
+
+ return 0;
+
+bail2:
+ close(sock);
+ sock = -1;
+
+bail:
+ return err;
+}
+
+int AdbWebSocketHandler::handleMessage(
+ uint8_t headerByte, const uint8_t *msg, size_t len) {
+ LOG(VERBOSE)
+ << "headerByte = "
+ << StringPrintf("0x%02x", (unsigned)headerByte);
+
+ // hexdump(msg, len);
+
+ if (!(headerByte & 0x80)) {
+ // I only want to receive whole messages here, not fragments.
+ return -EINVAL;
+ }
+
+ auto opcode = headerByte & 0x1f;
+ switch (opcode) {
+ case 0x8:
+ {
+ // closeConnection.
+ break;
+ }
+
+ case 0x2:
+ {
+ // binary
+
+ size_t payloadLength;
+ int err = verifyAdbHeader(msg, len, &payloadLength);
+
+ if (err || len != 24 + payloadLength) {
+ LOG(ERROR) << "websocket message is not a valid adb message.";
+ return -EINVAL;
+ }
+
+ mAdbConnection->send(msg, len);
+ break;
+ }
+
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
diff --git a/host/frontend/webrtc_operator/Android.bp b/host/frontend/gcastv2/webrtc/Android.bp
index 54eda4406..b0c775c08 100644
--- a/host/frontend/webrtc_operator/Android.bp
+++ b/host/frontend/gcastv2/webrtc/Android.bp
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2020 The Android Open Source Project
+// 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.
@@ -13,47 +13,83 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-cc_library_headers {
- name: "webrtc_signaling_headers",
- export_include_dirs: ["./constants"],
- host_supported: true,
+cc_library_static {
+ name: "libwebrtc",
+ srcs: [
+ "AdbWebSocketHandler.cpp",
+ "DTLS.cpp",
+ "G711Packetizer.cpp",
+ "Keyboard.cpp",
+ "MyWebSocketHandler.cpp",
+ "OpusPacketizer.cpp",
+ "Packetizer.cpp",
+ "RTPSender.cpp",
+ "RTPSession.cpp",
+ "RTPSocketHandler.cpp",
+ "SCTPHandler.cpp",
+ "SDP.cpp",
+ "ServerState.cpp",
+ "STUNClient.cpp",
+ "STUNMessage.cpp",
+ "Utils.cpp",
+ "VP8Packetizer.cpp",
+ ],
+ static_libs: [
+ "libhttps",
+ "libsrtp2",
+ "libcuttlefish_host_config",
+ "libcuttlefish_screen_connector",
+ "libcuttlefish_wayland_server",
+ "libgflags",
+ "libjsoncpp",
+ "libsource",
+ "libdrm",
+ "libffi",
+ "libwayland_server",
+ "libwayland_extension_server_protocols",
+ ],
+ shared_libs: [
+ "libssl",
+ "libbase",
+ "libcuttlefish_fs",
+ ],
+ defaults: ["cuttlefish_host_only"],
+ local_include_dirs: ["include"],
+ export_include_dirs: ["include"],
}
cc_binary_host {
- name: "webrtc_operator",
+ name: "webRTC",
srcs: [
- "client_handler.cpp",
- "device_registry.cpp",
- "device_handler.cpp",
- "device_list_handler.cpp",
- "server_config.cpp",
- "server.cpp",
- "signal_handler.cpp",
- ],
- header_libs: [
- "webrtc_signaling_headers",
+ "webRTC.cpp",
],
shared_libs: [
"libbase",
- "liblog",
"libcrypto",
- "libjsoncpp",
- "libssl",
"libcuttlefish_fs",
+ "libcuttlefish_utils",
+ "libopus",
+ "libssl",
+ "libvpx",
+ "libyuv",
],
static_libs: [
- "libcap",
- "libgflags",
- "libcuttlefish_utils",
"libcuttlefish_host_config",
- "libcuttlefish_host_websocket",
- "libwebsockets",
+ "libcuttlefish_screen_connector",
+ "libcuttlefish_wayland_server",
+ "libgflags",
+ "libhttps",
+ "libjsoncpp",
+ "libsource",
+ "libsrtp2",
+ "libwebrtc",
+ "libdrm",
+ "libffi",
+ "libwayland_server",
+ "libwayland_extension_server_protocols",
],
- defaults: ["cuttlefish_buildhost_only"],
+ cpp_std: "experimental",
+ defaults: ["cuttlefish_host_only"],
}
// TODO(jemoreira): Ideally these files should be in $HOST_OUT/webrtc but I
@@ -74,44 +110,23 @@ prebuilt_usr_share_host {
}
prebuilt_usr_share_host {
- name: "webrtc_controls.css",
- src: "assets/controls.css",
- filename: "controls.css",
- sub_dir: "webrtc/assets",
-}
-
-prebuilt_usr_share_host {
- name: "webrtc_adb.js",
- src: "assets/js/adb.js",
- filename: "adb.js",
- sub_dir: "webrtc/assets/js",
-}
-
-prebuilt_usr_share_host {
- name: "webrtc_cf.js",
- src: "assets/js/cf_webrtc.js",
- filename: "cf_webrtc.js",
- sub_dir: "webrtc/assets/js",
-}
-
-prebuilt_usr_share_host {
- name: "webrtc_app.js",
- src: "assets/js/app.js",
- filename: "app.js",
+ name: "webrtc_logcat.js",
+ src: "assets/js/logcat.js",
+ filename: "logcat.js",
sub_dir: "webrtc/assets/js",
}
prebuilt_usr_share_host {
- name: "webrtc_controls.js",
- src: "assets/js/controls.js",
- filename: "controls.js",
+ name: "webrtc_receive.js",
+ src: "assets/js/receive.js",
+ filename: "receive.js",
sub_dir: "webrtc/assets/js",
}
prebuilt_usr_share_host {
- name: "webrtc_rootcanal.js",
- src: "assets/js/rootcanal.js",
- filename: "rootcanal.js",
+ name: "webrtc_viewpane.js",
+ src: "assets/js/viewpane.js",
+ filename: "viewpane.js",
sub_dir: "webrtc/assets/js",
}
diff --git a/host/frontend/gcastv2/webrtc/DTLS.cpp b/host/frontend/gcastv2/webrtc/DTLS.cpp
new file mode 100644
index 000000000..6ae6c9c0b
--- /dev/null
+++ b/host/frontend/gcastv2/webrtc/DTLS.cpp
@@ -0,0 +1,463 @@
+/*
+ * 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.
+ */
+
+#include <webrtc/DTLS.h>
+
+#include <webrtc/RTPSocketHandler.h>
+
+#include <https/SafeCallbackable.h>
+#include <https/SSLSocket.h>
+#include <https/Support.h>
+
+#include <android-base/logging.h>
+
+#include <sys/socket.h>
+#include <unistd.h>
+
+#include <sstream>
+
+static int gDTLSInstanceIndex;
+
+// static
+void DTLS::Init() {
+ SSL_library_init();
+ SSL_load_error_strings();
+ OpenSSL_add_ssl_algorithms();
+
+ auto err = srtp_init();
+ CHECK_EQ(err, srtp_err_status_ok);
+
+ gDTLSInstanceIndex = SSL_get_ex_new_index(
+ 0, const_cast<char *>("DTLSInstance index"), NULL, NULL, NULL);
+
+}
+
+bool DTLS::useCertificate(std::shared_ptr<X509> cert) {
+ // I'm assuming that ownership of the certificate is transferred, so I'm
+ // adding an extra reference...
+ CHECK_EQ(1, X509_up_ref(cert.get()));
+
+ return cert != nullptr && 1 == SSL_CTX_use_certificate(mCtx, cert.get());
+}
+
+bool DTLS::usePrivateKey(std::shared_ptr<EVP_PKEY> key) {
+ // I'm assuming that ownership of the key in SSL_CTX_use_PrivateKey is
+ // transferred, so I'm adding an extra reference...
+ CHECK_EQ(1, EVP_PKEY_up_ref(key.get()));
+
+ return key != nullptr
+ && 1 == SSL_CTX_use_PrivateKey(mCtx, key.get())
+ && 1 == SSL_CTX_check_private_key(mCtx);
+}
+
+DTLS::DTLS(
+ std::shared_ptr<RTPSocketHandler> handler,
+ DTLS::Mode mode,
+ std::shared_ptr<X509> cert,
+ std::shared_ptr<EVP_PKEY> key,
+ const std::string &remoteFingerprint,
+ bool useSRTP)
+ : mState(State::UNINITIALIZED),
+ mHandler(handler),
+ mMode(mode),
+ mRemoteFingerprint(remoteFingerprint),
+ mUseSRTP(useSRTP),
+ mCtx(nullptr),
+ mSSL(nullptr),
+ mBioR(nullptr),
+ mBioW(nullptr),
+ mSRTPInbound(nullptr),
+ mSRTPOutbound(nullptr) {
+ mCtx = SSL_CTX_new(DTLSv1_2_method());
+ CHECK(mCtx);
+
+ int result = SSL_CTX_set_cipher_list(
+ mCtx, "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");
+
+ CHECK_EQ(result, 1);
+
+ SSL_CTX_set_verify(
+ mCtx,
+ SSL_VERIFY_PEER
+ | SSL_VERIFY_CLIENT_ONCE
+ | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
+ &DTLS::OnVerifyPeerCertificate);
+
+ CHECK(useCertificate(cert));
+ CHECK(usePrivateKey(key));
+
+ if (mUseSRTP) {
+ result = SSL_CTX_set_tlsext_use_srtp(mCtx, "SRTP_AES128_CM_SHA1_80");
+ CHECK_EQ(result, 0);
+ }
+
+ mSSL = SSL_new(mCtx);
+ CHECK(mSSL);
+
+ SSL_set_ex_data(mSSL, gDTLSInstanceIndex, this);
+
+ mBioR = BIO_new(BIO_s_mem());
+ CHECK(mBioR);
+
+ mBioW = BIO_new(BIO_s_mem());
+ CHECK(mBioW);
+
+ SSL_set_bio(mSSL, mBioR, mBioW);
+
+ if (mode == Mode::CONNECT) {
+ SSL_set_connect_state(mSSL);
+ } else {
+ SSL_set_accept_state(mSSL);
+ }
+}
+
+DTLS::~DTLS() {
+ if (mSRTPOutbound) {
+ srtp_dealloc(mSRTPOutbound);
+ mSRTPOutbound = nullptr;
+ }
+
+ if (mSRTPInbound) {
+ srtp_dealloc(mSRTPInbound);
+ mSRTPInbound = nullptr;
+ }
+
+ if (mSSL) {
+ SSL_shutdown(mSSL);
+ }
+
+ SSL_free(mSSL);
+ mSSL = nullptr;
+
+ mBioW = mBioR = nullptr;
+
+ SSL_CTX_free(mCtx);
+ mCtx = nullptr;
+}
+
+// static
+int DTLS::OnVerifyPeerCertificate(int /* ok */, X509_STORE_CTX *ctx) {
+ LOG(VERBOSE) << "OnVerifyPeerCertificate";
+
+ SSL *ssl = static_cast<SSL *>(X509_STORE_CTX_get_ex_data(
+ ctx, SSL_get_ex_data_X509_STORE_CTX_idx()));
+
+ DTLS *me = static_cast<DTLS *>(SSL_get_ex_data(ssl, gDTLSInstanceIndex));
+
+ std::unique_ptr<X509, std::function<void(X509 *)>> cert(
+ SSL_get_peer_certificate(ssl), X509_free);
+
+ if (!cert) {
+ LOG(ERROR) << "SSLSocket::isPeerCertificateValid no certificate.";
+
+ return 0;
+ }
+
+ auto spacePos = me->mRemoteFingerprint.find(' ');
+ CHECK(spacePos != std::string::npos);
+ auto digestName = me->mRemoteFingerprint.substr(0, spacePos);
+ CHECK(!strcasecmp(digestName.c_str(), "sha-256"));
+
+ const EVP_MD *digest = EVP_get_digestbyname("sha256");
+
+ unsigned char md[EVP_MAX_MD_SIZE];
+ unsigned int n;
+ int res = X509_digest(cert.get(), digest, md, &n);
+ CHECK_EQ(res, 1);
+
+ std::stringstream ss;
+ for (unsigned int i = 0; i < n; ++i) {
+ if (i > 0) {
+ ss << ":";
+ }
+
+ auto byte = md[i];
+
+ auto nibble = byte >> 4;
+ ss << (char)((nibble < 10) ? ('0' + nibble) : ('A' + nibble - 10));
+
+ nibble = byte & 0x0f;
+ ss << (char)((nibble < 10) ? ('0' + nibble) : ('A' + nibble - 10));
+ }
+
+ LOG(VERBOSE)
+ << "Client offered certificate w/ fingerprint "
+ << ss.str();
+
+ LOG(VERBOSE) << "should be: " << me->mRemoteFingerprint;
+
+ auto remoteFingerprintHash = me->mRemoteFingerprint.substr(spacePos + 1);
+ bool match = !strcasecmp(remoteFingerprintHash.c_str(), ss.str().c_str());
+
+ if (!match) {
+ LOG(ERROR)
+ << "The peer's certificate's fingerprint does not match that "
+ << "published in the SDP!";
+ }
+
+ return match;
+}
+
+void DTLS::connect(const sockaddr_storage &remoteAddr) {
+ CHECK_EQ(static_cast<int>(mState), static_cast<int>(State::UNINITIALIZED));
+
+ mRemoteAddr = remoteAddr;
+ mState = State::CONNECTING;
+
+ tryConnecting();
+}
+
+void DTLS::doTheThing(int res) {
+ LOG(VERBOSE) << "doTheThing(" << res << ")";
+
+ int err = SSL_get_error(mSSL, res);
+
+ switch (err) {
+ case SSL_ERROR_WANT_READ:
+ {
+ LOG(VERBOSE) << "SSL_ERROR_WANT_READ";
+
+ queueOutputDataFromDTLS();
+ break;
+ }
+
+ case SSL_ERROR_WANT_WRITE:
+ {
+ LOG(VERBOSE) << "SSL_ERROR_WANT_WRITE";
+ break;
+ }
+
+ case SSL_ERROR_NONE:
+ {
+ LOG(VERBOSE) << "SSL_ERROR_NONE";
+ break;
+ }
+
+ case SSL_ERROR_SYSCALL:
+ default:
+ {
+ LOG(ERROR)
+ << "DTLS stack returned error "
+ << err
+ << " ("
+ << SSL_state_string_long(mSSL)
+ << ")";
+ }
+ }
+}
+
+void DTLS::queueOutputDataFromDTLS() {
+ auto handler = mHandler.lock();
+
+ if (!handler) {
+ return;
+ }
+
+ int n;
+
+ do {
+ char buf[RTPSocketHandler::kMaxUDPPayloadSize];
+ n = BIO_read(mBioW, buf, sizeof(buf));
+
+ if (n > 0) {
+ LOG(VERBOSE) << "queueing " << n << " bytes of output data from DTLS.";
+
+ handler->queueDatagram(
+ mRemoteAddr, buf, static_cast<size_t>(n));
+ } else if (BIO_should_retry(mBioW)) {
+ continue;
+ } else {
+ CHECK(!"Should not be here");
+ }
+ } while (n > 0);
+}
+
+void DTLS::tryConnecting() {
+ CHECK_EQ(static_cast<int>(mState), static_cast<int>(State::CONNECTING));
+
+ int res =
+ (mMode == Mode::CONNECT)
+ ? SSL_connect(mSSL) : SSL_accept(mSSL);
+
+ if (res != 1) {
+ doTheThing(res);
+ } else {
+ queueOutputDataFromDTLS();
+
+ LOG(INFO) << "DTLS connection established.";
+ mState = State::CONNECTED;
+
+ auto handler = mHandler.lock();
+ if (handler) {
+ if (mUseSRTP) {
+ getKeyingMaterial();
+ }
+
+ handler->notifyDTLSConnected();
+ }
+ }
+}
+
+void DTLS::inject(const uint8_t *data, size_t size) {
+ LOG(VERBOSE) << "injecting " << size << " bytes into DTLS stack.";
+
+ auto n = BIO_write(mBioR, data, size);
+ CHECK_EQ(n, static_cast<int>(size));
+
+ if (mState == State::CONNECTING) {
+ if (!SSL_is_init_finished(mSSL)) {
+ tryConnecting();
+ }
+ }
+}
+
+void DTLS::getKeyingMaterial() {
+ static constexpr char kLabel[] = "EXTRACTOR-dtls_srtp";
+
+ // These correspond to the chosen option SRTP_AES128_CM_SHA1_80, passed
+ // to SSL_CTX_set_tlsext_use_srtp before. c/f RFC 5764 4.1.2
+
+ uint8_t material[(SRTP_AES_128_KEY_LEN + SRTP_SALT_LEN) * 2];
+
+ auto res = SSL_export_keying_material(
+ mSSL,
+ material,
+ sizeof(material),
+ kLabel,
+ strlen(kLabel),
+ nullptr /* context */,
+ 0 /* contextlen */,
+ 0 /* use_context */);
+
+ CHECK_EQ(res, 1);
+
+ // LOG(INFO) << "keying material:";
+ // hexdump(material, sizeof(material));
+
+ size_t offset = 0;
+ const uint8_t *clientKey = &material[offset];
+ offset += SRTP_AES_128_KEY_LEN;
+ const uint8_t *serverKey = &material[offset];
+ offset += SRTP_AES_128_KEY_LEN;
+ const uint8_t *clientSalt = &material[offset];
+ offset += SRTP_SALT_LEN;
+ const uint8_t *serverSalt = &material[offset];
+ offset += SRTP_SALT_LEN;
+
+ CHECK_EQ(offset, sizeof(material));
+
+ std::string sendKey(
+ reinterpret_cast<const char *>(clientKey), SRTP_AES_128_KEY_LEN);
+
+ sendKey.append(
+ reinterpret_cast<const char *>(clientSalt), SRTP_SALT_LEN);
+
+ std::string receiveKey(
+ reinterpret_cast<const char *>(serverKey), SRTP_AES_128_KEY_LEN);
+
+ receiveKey.append(
+ reinterpret_cast<const char *>(serverSalt), SRTP_SALT_LEN);
+
+ if (mMode == Mode::CONNECT) {
+ CreateSRTPSession(&mSRTPInbound, receiveKey, ssrc_any_inbound);
+ CreateSRTPSession(&mSRTPOutbound, sendKey, ssrc_any_outbound);
+ } else {
+ CreateSRTPSession(&mSRTPInbound, sendKey, ssrc_any_inbound);
+ CreateSRTPSession(&mSRTPOutbound, receiveKey, ssrc_any_outbound);
+ }
+}
+
+// static
+void DTLS::CreateSRTPSession(
+ srtp_t *session,
+ const std::string &keyAndSalt,
+ srtp_ssrc_type_t direction) {
+ srtp_policy_t policy;
+ memset(&policy, 0, sizeof(policy));
+
+ srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtp);
+ srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtcp);
+
+ policy.ssrc.type = direction;
+ policy.ssrc.value = 0;
+
+ policy.key =
+ const_cast<unsigned char *>(
+ reinterpret_cast<const unsigned char *>(keyAndSalt.c_str()));
+
+ policy.allow_repeat_tx = 1;
+ policy.next = nullptr;
+
+ auto ret = srtp_create(session, &policy);
+ CHECK_EQ(ret, srtp_err_status_ok);
+}
+
+size_t DTLS::protect(void *data, size_t size, bool isRTP) {
+ int len = static_cast<int>(size);
+
+ auto ret =
+ isRTP
+ ? srtp_protect(mSRTPOutbound, data, &len)
+ : srtp_protect_rtcp(mSRTPOutbound, data, &len);
+
+ CHECK_EQ(ret, srtp_err_status_ok);
+
+ return static_cast<size_t>(len);
+}
+
+size_t DTLS::unprotect(void *data, size_t size, bool isRTP) {
+ int len = static_cast<int>(size);
+
+ auto ret =
+ isRTP
+ ? srtp_unprotect(mSRTPInbound, data, &len)
+ : srtp_unprotect_rtcp(mSRTPInbound, data, &len);
+
+ if (ret == srtp_err_status_replay_fail) {
+ LOG(WARNING)
+ << "srtp_unprotect"
+ << (isRTP ? "" : "_rtcp")
+ << " returned srtp_err_status_replay_fail, ignoring packet.";
+
+ return 0;
+ }
+
+ CHECK_EQ(ret, srtp_err_status_ok);
+
+ return static_cast<size_t>(len);
+}
+
+ssize_t DTLS::readApplicationData(void *data, size_t size) {
+ auto res = SSL_read(mSSL, data, size);
+
+ if (res < 0) {
+ doTheThing(res);
+ return -1;
+ }
+
+ return res;
+}
+
+ssize_t DTLS::writeApplicationData(const void *data, size_t size) {
+ auto res = SSL_write(mSSL, data, size);
+
+ queueOutputDataFromDTLS();
+
+ // May have to queue the data and "doTheThing" on failure...
+ CHECK_EQ(res, static_cast<int>(size));
+
+ return res;
+}
diff --git a/host/frontend/gcastv2/webrtc/G711Packetizer.cpp b/host/frontend/gcastv2/webrtc/G711Packetizer.cpp
new file mode 100644
index 000000000..a112351d1
--- /dev/null
+++ b/host/frontend/gcastv2/webrtc/G711Packetizer.cpp
@@ -0,0 +1,77 @@
+/*
+ * 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.
+ */
+
+#include <webrtc/G711Packetizer.h>
+
+#include "Utils.h"
+
+#include <webrtc/RTPSocketHandler.h>
+
+#include <https/SafeCallbackable.h>
+
+using namespace android;
+
+G711Packetizer::G711Packetizer(
+ Mode mode,
+ std::shared_ptr<RunLoop> runLoop,
+ std::shared_ptr<StreamingSource> audioSource)
+ : Packetizer(runLoop, audioSource),
+ mMode(mode),
+ mFirstInTalkspurt(true) {
+}
+
+void G711Packetizer::packetize(const std::shared_ptr<SBuffer> &accessUnit, int64_t timeUs) {
+ LOG(VERBOSE) << "Received G711 frame of size " << accessUnit->size();
+
+ const uint8_t PT = (mMode == Mode::ALAW) ? 8 : 0;
+ static constexpr uint32_t SSRC = 0x8badf00d;
+
+ // XXX Retransmission packets add 2 bytes (for the original seqNum), should
+ // probably reserve that amount in the original packets so we don't exceed
+ // the MTU on retransmission.
+ static const size_t kMaxSRTPPayloadSize =
+ RTPSocketHandler::kMaxUDPPayloadSize - SRTP_MAX_TRAILER_LEN;
+
+ const uint8_t *audioData = accessUnit->data();
+ size_t size = accessUnit->size();
+
+ uint32_t rtpTime = ((timeUs - mediaStartTime()) * 8) / 1000;
+
+ CHECK_LE(12 + size, kMaxSRTPPayloadSize);
+
+ std::vector<uint8_t> packet(12 + size);
+ uint8_t *data = packet.data();
+
+ packet[0] = 0x80;
+ packet[1] = PT;
+
+ if (mFirstInTalkspurt) {
+ packet[1] |= 0x80; // (M)ark
+ mFirstInTalkspurt = false;
+ }
+
+ SET_U16(&data[2], 0); // seqNum
+ SET_U32(&data[4], rtpTime);
+ SET_U32(&data[8], SSRC);
+
+ memcpy(&data[12], audioData, size);
+
+ queueRTPDatagram(&packet);
+}
+
+uint32_t G711Packetizer::rtpNow() const {
+ return (timeSinceStart() * 8) / 1000;
+}
diff --git a/host/frontend/webrtc/lib/keyboard.cpp b/host/frontend/gcastv2/webrtc/Keyboard.cpp
index ee6b2a73f..052f30038 100644
--- a/host/frontend/webrtc/lib/keyboard.cpp
+++ b/host/frontend/gcastv2/webrtc/Keyboard.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "host/frontend/webrtc/lib/keyboard.h"
+#include <webrtc/Keyboard.h>
#include <linux/input.h>
diff --git a/host/frontend/gcastv2/webrtc/MyWebSocketHandler.cpp b/host/frontend/gcastv2/webrtc/MyWebSocketHandler.cpp
new file mode 100644
index 000000000..60fcfb1fc
--- /dev/null
+++ b/host/frontend/gcastv2/webrtc/MyWebSocketHandler.cpp
@@ -0,0 +1,721 @@
+/*
+ * 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.
+ */
+
+#include <webrtc/MyWebSocketHandler.h>
+
+#include "Utils.h"
+
+#include <json/json.h>
+
+#include <netdb.h>
+#include <openssl/rand.h>
+
+#include <webrtc/Keyboard.h>
+
+namespace {
+
+// helper method to ensure a json object has the required fields convertible
+// to the appropriate types.
+bool validateJsonObject(
+ const Json::Value &obj, const std::string &type,
+ const std::vector<std::pair<std::string, Json::ValueType>> &fields,
+ std::function<void(const std::string&)> onError) {
+ for (const auto &field_spec : fields) {
+ const auto &field_name = field_spec.first;
+ auto field_type = field_spec.second;
+ if (!(obj.isMember(field_name) &&
+ obj[field_name].isConvertibleTo(field_type))) {
+ std::string error_msg = "Expected a field named '";
+ error_msg += field_name + "' of type '";
+ error_msg += std::to_string(field_type);
+ error_msg += "'";
+ if (!type.empty()) {
+ error_msg += " in message of type '" + type + "'";
+ }
+ error_msg += ".";
+ LOG(WARNING) << error_msg;
+ onError(error_msg);
+ return false;
+ }
+ }
+ return true;
+}
+
+} // namespace
+
+MyWebSocketHandler::MyWebSocketHandler(
+ std::shared_ptr<RunLoop> runLoop,
+ std::shared_ptr<ServerState> serverState,
+ size_t handlerId)
+ : mRunLoop(runLoop),
+ mServerState(serverState),
+ mId(handlerId),
+ mOptions(OptionBits::useSingleCertificateForAllTracks),
+ mTouchSink(mServerState->getTouchSink()),
+ mKeyboardSink(mServerState->getKeyboardSink()) {
+}
+
+MyWebSocketHandler::~MyWebSocketHandler() {
+ mServerState->releaseHandlerId(mId);
+}
+
+int MyWebSocketHandler::handleMessage(
+ uint8_t /* headerByte */, const uint8_t *msg, size_t len) {
+ // android::hexdump(msg, len);
+
+ Json::Value obj;
+ Json::Reader json_reader;
+ Json::FastWriter json_writer;
+ auto str = reinterpret_cast<const char *>(msg);
+ if (!json_reader.parse(str, str + len, obj) < 0) {
+ return -EINVAL;
+ }
+
+ LOG(VERBOSE) << obj.toStyledString();
+
+ auto sendMessageOnError =
+ [this](const std::string &error_msg) {
+ auto reply = "{\"error\": \"" + error_msg + "\"}";
+ sendMessage(reply.c_str(), reply.size());
+ };
+
+ if (!validateJsonObject(obj, "", {{"type", Json::ValueType::stringValue}},
+ sendMessageOnError)) {
+ return -EINVAL;
+ }
+ std::string type = obj["type"].asString();
+
+ if (type == "greeting") {
+ Json::Value reply;
+ reply["type"] = "hello";
+ reply["reply"] = "Right back at ya!";
+
+ auto replyAsString = json_writer.write(reply);
+ sendMessage(replyAsString.c_str(), replyAsString.size());
+
+ if (obj.isMember("path")) {
+ parseOptions(obj["path"].asString());
+ }
+
+ if (mOptions & OptionBits::useSingleCertificateForAllTracks) {
+ mCertificateAndKey = CreateDTLSCertificateAndKey();
+ }
+
+ prepareSessions();
+ } else if (type == "set-remote-desc") {
+ if (!validateJsonObject(obj, type,
+ {{"sdp", Json::ValueType::stringValue}},
+ sendMessageOnError)) {
+ return -EINVAL;
+ }
+
+ int err = mOfferedSDP.setTo(obj["sdp"].asString());
+
+ if (err) {
+ LOG(ERROR) << "Offered SDP could not be parsed (" << err << ")";
+ }
+
+ for (size_t i = 0; i < mSessions.size(); ++i) {
+ const auto &session = mSessions[i];
+
+ session->setRemoteParams(
+ getRemoteUFrag(i),
+ getRemotePassword(i),
+ getRemoteFingerprint(i));
+ }
+
+ return err;
+ } else if (type == "request-offer") {
+ std::stringstream ss;
+
+ ss <<
+"v=0\r\n"
+"o=- 7794515898627856655 2 IN IP4 127.0.0.1\r\n"
+"s=-\r\n"
+"t=0 0\r\n"
+"a=msid-semantic: WMS pqWEULZNyLiJHA7lcwlUnbule9FJNk0pY0aw\r\n";
+
+ bool bundled = false;
+
+ if ((mOptions & OptionBits::bundleTracks) && countTracks() > 1) {
+ bundled = true;
+
+ ss << "a=group:BUNDLE 0";
+
+ if (!(mOptions & OptionBits::disableAudio)) {
+ ss << " 1";
+ }
+
+ if (mOptions & OptionBits::enableData) {
+ ss << " 2";
+ }
+
+ ss << "\r\n";
+
+ emitTrackIceOptionsAndFingerprint(ss, 0 /* mlineIndex */);
+ }
+
+ size_t mlineIndex = 0;
+
+ // Video track (mid = 0)
+
+ std::string videoEncodingSpecific = "a=rtpmap:96 VP8/90000\r\n";
+
+ videoEncodingSpecific +=
+"a=rtcp-fb:96 ccm fir\r\n"
+"a=rtcp-fb:96 nack\r\n"
+"a=rtcp-fb:96 nack pli\r\n";
+
+ ss <<
+"m=video 9 "
+<< ((mOptions & OptionBits::useTCP) ? "TCP" : "UDP")
+<< "/TLS/RTP/SAVPF 96 97\r\n"
+"c=IN IP4 0.0.0.0\r\n"
+"a=rtcp:9 IN IP4 0.0.0.0\r\n";
+
+ if (!bundled) {
+ emitTrackIceOptionsAndFingerprint(ss, mlineIndex++);
+ }
+
+ ss <<
+"a=setup:actpass\r\n"
+"a=mid:0\r\n"
+"a=sendonly\r\n"
+"a=rtcp-mux\r\n"
+"a=rtcp-rsize\r\n"
+"a=rtcp-xr:rcvr-rtt=all\r\n";
+
+ ss << videoEncodingSpecific <<
+"a=rtpmap:97 rtx/90000\r\n"
+"a=fmtp:97 apt=96\r\n"
+"a=ssrc-group:FID 3735928559 3405689008\r\n"
+"a=ssrc:3735928559 cname:myWebRTP\r\n"
+"a=ssrc:3735928559 msid:pqWEULZNyLiJHA7lcwlUnbule9FJNk0pY0aw 61843855-edd7-4ca9-be79-4e3ccc6cc035\r\n"
+"a=ssrc:3735928559 mslabel:pqWEULZNyLiJHA7lcwlUnbule9FJNk0pY0aw\r\n"
+"a=ssrc:3735928559 label:61843855-edd7-4ca9-be79-4e3ccc6cc035\r\n"
+"a=ssrc:3405689008 cname:myWebRTP\r\n"
+"a=ssrc:3405689008 msid:pqWEULZNyLiJHA7lcwlUnbule9FJNk0pY0aw 61843855-edd7-4ca9-be79-4e3ccc6cc035\r\n"
+"a=ssrc:3405689008 mslabel:pqWEULZNyLiJHA7lcwlUnbule9FJNk0pY0aw\r\n"
+"a=ssrc:3405689008 label:61843855-edd7-4ca9-be79-4e3ccc6cc035\r\n";
+
+ if (!(mOptions & OptionBits::disableAudio)) {
+ ss <<
+"m=audio 9 "
+<< ((mOptions & OptionBits::useTCP) ? "TCP" : "UDP")
+<< "/TLS/RTP/SAVPF 98\r\n"
+"c=IN IP4 0.0.0.0\r\n"
+"a=rtcp:9 IN IP4 0.0.0.0\r\n";
+
+ if (!bundled) {
+ emitTrackIceOptionsAndFingerprint(ss, mlineIndex++);
+ }
+
+ ss <<
+"a=setup:actpass\r\n"
+"a=mid:1\r\n"
+"a=sendonly\r\n"
+"a=msid:pqWEULZNyLiJHA7lcwlUnbule9FJNk0pY0aw 61843856-edd7-4ca9-be79-4e3ccc6cc035\r\n"
+"a=rtcp-mux\r\n"
+"a=rtcp-rsize\r\n"
+"a=rtpmap:98 opus/48000/2\r\n"
+"a=fmtp:98 minptime=10;useinbandfec=1\r\n"
+"a=ssrc-group:FID 2343432205\r\n"
+"a=ssrc:2343432205 cname:myWebRTP\r\n"
+"a=ssrc:2343432205 msid:pqWEULZNyLiJHA7lcwlUnbule9FJNk0pY0aw 61843856-edd7-4ca9-be79-4e3ccc6cc035\r\n"
+"a=ssrc:2343432205 mslabel:pqWEULZNyLiJHA7lcwlUnbule9FJNk0pY0aw\r\n"
+"a=ssrc:2343432205 label:61843856-edd7-4ca9-be79-4e3ccc6cc035\r\n";
+ }
+
+ if (mOptions & OptionBits::enableData) {
+ ss <<
+"m=application 9 "
+<< ((mOptions & OptionBits::useTCP) ? "TCP" : "UDP")
+<< "/DTLS/SCTP webrtc-datachannel\r\n"
+"c=IN IP4 0.0.0.0\r\n"
+"a=sctp-port:5000\r\n";
+
+ if (!bundled) {
+ emitTrackIceOptionsAndFingerprint(ss, mlineIndex++);
+ }
+
+ ss <<
+"a=setup:actpass\r\n"
+"a=mid:2\r\n"
+"a=sendrecv\r\n"
+"a=fmtp:webrtc-datachannel max-message-size=65536\r\n";
+ }
+
+ Json::Value reply;
+ reply["type"] = "offer";
+ reply["sdp"] = ss.str();
+
+ auto replyAsString = json_writer.write(reply);
+ sendMessage(replyAsString.c_str(), replyAsString.size());
+ } else if (type == "get-ice-candidate") {
+ if (!validateJsonObject(obj, type, {{"mid", Json::ValueType::intValue}},
+ sendMessageOnError)) {
+ return -EINVAL;
+ }
+ int32_t mid = obj["mid"].asInt();
+
+ bool success = getCandidate(mid);
+
+ if (!success) {
+ Json::Value reply;
+ reply["type"] = "ice-candidate";
+
+ auto replyAsString = json_writer.write(reply);
+ sendMessage(replyAsString.c_str(), replyAsString.size());
+ }
+ } else if (type == "set-mouse-position") {
+ if (!validateJsonObject(obj, type, {{"down", Json::ValueType::intValue},
+ {"x", Json::ValueType::intValue},
+ {"y", Json::ValueType::intValue}},
+ sendMessageOnError)) {
+ return -EINVAL;
+ }
+ int32_t down = obj["down"].asInt();
+ int32_t x = obj["x"].asInt();
+ int32_t y = obj["y"].asInt();
+
+ LOG(VERBOSE)
+ << "set-mouse-position(" << down << ", " << x << ", " << y << ")";
+
+ mTouchSink->injectTouchEvent(x, y, down != 0);
+ } else if (type == "inject-multi-touch") {
+ if (!validateJsonObject(obj, type, {{"id", Json::ValueType::intValue},
+ {"initialDown", Json::ValueType::intValue},
+ {"x", Json::ValueType::intValue},
+ {"y", Json::ValueType::intValue},
+ {"slot", Json::ValueType::intValue}},
+ sendMessageOnError)) {
+ return -EINVAL;
+ }
+ int32_t id = obj["id"].asInt();
+ int32_t initialDown = obj["initialDown"].asInt();
+ int32_t x = obj["x"].asInt();
+ int32_t y = obj["y"].asInt();
+ int32_t slot = obj["slot"].asInt();
+
+ LOG(VERBOSE)
+ << "inject-multi-touch id="
+ << id
+ << ", initialDown="
+ << initialDown
+ << ", x="
+ << x
+ << ", y="
+ << y
+ << ", slot="
+ << slot;
+
+ mTouchSink->injectMultiTouchEvent(id, slot, x, y, initialDown);
+ } else if (type == "key-event") {
+ if (!validateJsonObject(obj, type, {{"event_type", Json::ValueType::stringValue},
+ {"keycode", Json::ValueType::stringValue}},
+ sendMessageOnError)) {
+ return -EINVAL;
+ }
+ auto down = obj["event_type"].asString() == std::string("keydown");
+ auto code = DomKeyCodeToLinux(obj["keycode"].asString());
+ mKeyboardSink->injectEvent(down, code);
+ }
+
+ return 0;
+}
+
+size_t MyWebSocketHandler::countTracks() const {
+ size_t n = 1; // We always have a video track.
+
+ if (!(mOptions & OptionBits::disableAudio)) {
+ ++n;
+ }
+
+ if (mOptions & OptionBits::enableData) {
+ ++n;
+ }
+
+ return n;
+}
+
+ssize_t MyWebSocketHandler::mlineIndexForMid(int32_t mid) const {
+ switch (mid) {
+ case 0:
+ return 0;
+
+ case 1:
+ if (mOptions & OptionBits::disableAudio) {
+ return -1;
+ }
+
+ return 1;
+
+ case 2:
+ if (!(mOptions & OptionBits::enableData)) {
+ return -1;
+ }
+
+ if (mOptions & OptionBits::disableAudio) {
+ return 1;
+ }
+
+ return 2;
+
+ default:
+ return -1;
+ }
+}
+
+bool MyWebSocketHandler::getCandidate(int32_t mid) {
+ auto mlineIndex = mlineIndexForMid(mid);
+
+ if (mlineIndex < 0) {
+ return false;
+ }
+
+ if (!(mOptions & OptionBits::bundleTracks) || mRTPs.empty()) {
+ // Only allocate a local port once if we bundle tracks.
+
+ size_t sessionIndex = mlineIndex;
+
+ uint32_t trackMask = 0;
+ if (mOptions & OptionBits::bundleTracks) {
+ sessionIndex = 0; // One session for all tracks.
+
+ trackMask = RTPSocketHandler::TRACK_VIDEO;
+
+ if (!(mOptions & OptionBits::disableAudio)) {
+ trackMask |= RTPSocketHandler::TRACK_AUDIO;
+ }
+
+ if (mOptions & OptionBits::enableData) {
+ trackMask |= RTPSocketHandler::TRACK_DATA;
+ }
+ } else if (mid == 0) {
+ trackMask = RTPSocketHandler::TRACK_VIDEO;
+ } else if (mid == 1) {
+ trackMask = RTPSocketHandler::TRACK_AUDIO;
+ } else {
+ trackMask = RTPSocketHandler::TRACK_DATA;
+ }
+
+ const auto &session = mSessions[sessionIndex];
+
+ auto rtp = std::make_shared<RTPSocketHandler>(
+ mRunLoop,
+ mServerState,
+ (mOptions & OptionBits::useTCP)
+ ? RTPSocketHandler::TransportType::TCP
+ : RTPSocketHandler::TransportType::UDP,
+ PF_INET,
+ trackMask,
+ session);
+
+ rtp->run();
+
+ mRTPs.push_back(rtp);
+ }
+
+ auto rtp = mRTPs.back();
+
+ Json::Value reply;
+ reply["type"] = "ice-candidate";
+
+ auto localIPString = rtp->getLocalIPString();
+
+ std::stringstream ss;
+ ss << "candidate:0 1 ";
+
+ if (mOptions & OptionBits::useTCP) {
+ ss << "tcp";
+ } else {
+ ss << "UDP";
+ }
+
+ // see rfc8445, 5.1.2.1. for the derivation of "2122121471" below.
+ ss << " 2122121471 " << localIPString << " " << rtp->getLocalPort() << " typ host ";
+
+ if (mOptions & OptionBits::useTCP) {
+ ss << "tcptype passive ";
+ }
+
+ ss << "generation 0 ufrag " << rtp->getLocalUFrag();
+
+ reply["candidate"] = ss.str();
+ reply["mlineIndex"] = static_cast<Json::UInt64>(mlineIndex);
+
+ Json::FastWriter json_writer;
+ auto replyAsString = json_writer.write(reply);
+ sendMessage(replyAsString.c_str(), replyAsString.size());
+
+ return true;
+}
+
+std::optional<std::string> MyWebSocketHandler::getSDPValue(
+ ssize_t targetMediaIndex,
+ std::string_view key,
+ bool fallthroughToGeneralSection) const {
+
+ CHECK_GE(targetMediaIndex, -1);
+
+ if (targetMediaIndex + 1 >= mOfferedSDP.countSections()) {
+ LOG(ERROR)
+ << "getSDPValue: targetMediaIndex "
+ << targetMediaIndex
+ << " out of range (countSections()="
+ << mOfferedSDP.countSections()
+ << ")";
+
+ return std::nullopt;
+ }
+
+ const std::string prefix = "a=" + std::string(key) + ":";
+
+ auto sectionIndex = 1 + targetMediaIndex;
+ auto rangeEnd = mOfferedSDP.section_end(sectionIndex);
+
+ auto it = std::find_if(
+ mOfferedSDP.section_begin(sectionIndex),
+ rangeEnd,
+ [prefix](const auto &line) {
+ return StartsWith(line, prefix);
+ });
+
+ if (it == rangeEnd) {
+ if (fallthroughToGeneralSection) {
+ CHECK_NE(targetMediaIndex, -1);
+
+ // Oh no, scary recursion ahead.
+ return getSDPValue(
+ -1 /* targetMediaIndex */,
+ key,
+ false /* fallthroughToGeneralSection */);
+ }
+
+ LOG(WARNING)
+ << "Unable to find '"
+ << prefix
+ << "' with targetMediaIndex="
+ << targetMediaIndex;
+
+ return std::nullopt;
+ }
+
+ return (*it).substr(prefix.size());
+}
+
+std::string MyWebSocketHandler::getRemotePassword(size_t mlineIndex) const {
+ auto value = getSDPValue(
+ mlineIndex, "ice-pwd", true /* fallthroughToGeneralSection */);
+
+ return value ? *value : std::string();
+}
+
+std::string MyWebSocketHandler::getRemoteUFrag(size_t mlineIndex) const {
+ auto value = getSDPValue(
+ mlineIndex, "ice-ufrag", true /* fallthroughToGeneralSection */);
+
+ return value ? *value : std::string();
+}
+
+std::string MyWebSocketHandler::getRemoteFingerprint(size_t mlineIndex) const {
+ auto value = getSDPValue(
+ mlineIndex, "fingerprint", true /* fallthroughToGeneralSection */);
+
+ return value ? *value : std::string();
+}
+
+// static
+std::pair<std::shared_ptr<X509>, std::shared_ptr<EVP_PKEY>>
+MyWebSocketHandler::CreateDTLSCertificateAndKey() {
+ // Modeled after "https://stackoverflow.com/questions/256405/
+ // programmatically-create-x509-certificate-using-openssl".
+
+ std::shared_ptr<EVP_PKEY> pkey(EVP_PKEY_new(), EVP_PKEY_free);
+
+ std::unique_ptr<RSA, std::function<void(RSA *)>> rsa(
+ RSA_new(), RSA_free);
+
+ BIGNUM exponent;
+ BN_init(&exponent);
+ BN_set_word(&exponent, RSA_F4);
+
+ int res = RSA_generate_key_ex(
+ rsa.get() /* rsa */, 2048, &exponent, nullptr /* callback */);
+
+ CHECK_EQ(res, 1);
+
+ EVP_PKEY_assign_RSA(pkey.get(), rsa.release());
+
+ std::shared_ptr<X509> x509(X509_new(), X509_free);
+
+ ASN1_INTEGER_set(X509_get_serialNumber(x509.get()), 1);
+
+ X509_gmtime_adj(X509_get_notBefore(x509.get()), 0);
+ X509_gmtime_adj(X509_get_notAfter(x509.get()), 60 * 60 * 24 * 7); // 7 days.
+
+ X509_set_pubkey(x509.get(), pkey.get());
+
+ X509_NAME *name = X509_get_subject_name(x509.get());
+
+ X509_NAME_add_entry_by_txt(
+ name, "C", MBSTRING_ASC, (unsigned char *)"US", -1, -1, 0);
+
+ X509_NAME_add_entry_by_txt(
+ name,
+ "O",
+ MBSTRING_ASC,
+ (unsigned char *)"Beyond Aggravated",
+ -1,
+ -1,
+ 0);
+
+ X509_NAME_add_entry_by_txt(
+ name, "CN", MBSTRING_ASC, (unsigned char *)"localhost", -1, -1, 0);
+
+ X509_set_issuer_name(x509.get(), name);
+
+ auto digest = EVP_sha256();
+
+ X509_sign(x509.get(), pkey.get(), digest);
+
+ return std::make_pair(x509, pkey);
+}
+
+void MyWebSocketHandler::parseOptions(const std::string &pathAndQuery) {
+ auto separatorPos = pathAndQuery.find('?');
+
+ if (separatorPos == std::string::npos) {
+ return;
+ }
+
+ auto components = SplitString(pathAndQuery.substr(separatorPos + 1), '&');
+ for (auto name : components) {
+ bool boolValue = true;
+
+ separatorPos = name.find('=');
+ if (separatorPos != std::string::npos) {
+ boolValue = false;
+
+ auto value = name.substr(separatorPos + 1);
+ name.erase(separatorPos);
+
+ boolValue =
+ !strcasecmp("true", value.c_str())
+ || !strcasecmp("yes", value.c_str())
+ || value == "1";
+ }
+
+ if (name == "disable_audio") {
+ auto mask = OptionBits::disableAudio;
+ mOptions = (mOptions & ~mask) | (boolValue ? mask : 0);
+ } else if (name == "bundle_tracks" && boolValue) {
+ auto mask = OptionBits::bundleTracks;
+ mOptions = (mOptions & ~mask) | (boolValue ? mask : 0);
+ } else if (name == "enable_data" && boolValue) {
+ auto mask = OptionBits::enableData;
+ mOptions = (mOptions & ~mask) | (boolValue ? mask : 0);
+ } else if (name == "use_tcp" && boolValue) {
+ auto mask = OptionBits::useTCP;
+ mOptions = (mOptions & ~mask) | (boolValue ? mask : 0);
+ }
+ }
+}
+
+// static
+void MyWebSocketHandler::CreateRandomIceCharSequence(char *dst, size_t size) {
+ // Per RFC 5245 an ice-char is alphanumeric, '+' or '/', i.e. 64 distinct
+ // character values (6 bit).
+
+ CHECK_EQ(1, RAND_bytes(reinterpret_cast<unsigned char *>(dst), size));
+
+ for (size_t i = 0; i < size; ++i) {
+ char x = dst[i] & 0x3f;
+ if (x < 26) {
+ x += 'a';
+ } else if (x < 52) {
+ x += 'A' - 26;
+ } else if (x < 62) {
+ x += '0' - 52;
+ } else if (x < 63) {
+ x = '+';
+ } else {
+ x = '/';
+ }
+
+ dst[i] = x;
+ }
+}
+
+std::pair<std::string, std::string>
+MyWebSocketHandler::createUniqueUFragAndPassword() {
+ // RFC 5245, section 15.4 mandates that uFrag is at least 4 and password
+ // at least 22 ice-chars long.
+
+ char uFragChars[4];
+
+ for (;;) {
+ CreateRandomIceCharSequence(uFragChars, sizeof(uFragChars));
+
+ std::string uFrag(uFragChars, sizeof(uFragChars));
+
+ auto it = std::find_if(
+ mSessions.begin(), mSessions.end(),
+ [uFrag](const auto &session) {
+ return session->localUFrag() == uFrag;
+ });
+
+ if (it == mSessions.end()) {
+ // This uFrag is not in use yet.
+ break;
+ }
+ }
+
+ char passwordChars[22];
+ CreateRandomIceCharSequence(passwordChars, sizeof(passwordChars));
+
+ return std::make_pair(
+ std::string(uFragChars, sizeof(uFragChars)),
+ std::string(passwordChars, sizeof(passwordChars)));
+}
+
+void MyWebSocketHandler::prepareSessions() {
+ size_t numSessions =
+ (mOptions & OptionBits::bundleTracks) ? 1 : countTracks();
+
+ for (size_t i = 0; i < numSessions; ++i) {
+ auto [ufrag, password] = createUniqueUFragAndPassword();
+
+ auto [certificate, key] =
+ (mOptions & OptionBits::useSingleCertificateForAllTracks)
+ ? mCertificateAndKey : CreateDTLSCertificateAndKey();
+
+ mSessions.push_back(
+ std::make_shared<RTPSession>(
+ ufrag, password, certificate, key));
+ }
+}
+
+void MyWebSocketHandler::emitTrackIceOptionsAndFingerprint(
+ std::stringstream &ss, size_t mlineIndex) const {
+ CHECK_LT(mlineIndex, mSessions.size());
+ const auto &session = mSessions[mlineIndex];
+
+ ss << "a=ice-ufrag:" << session->localUFrag() << "\r\n";
+ ss << "a=ice-pwd:" << session->localPassword() << "\r\n";
+ ss << "a=ice-options:trickle\r\n";
+ ss << "a=fingerprint:" << session->localFingerprint() << "\r\n";
+}
diff --git a/host/frontend/gcastv2/webrtc/OpusPacketizer.cpp b/host/frontend/gcastv2/webrtc/OpusPacketizer.cpp
new file mode 100644
index 000000000..7d625894f
--- /dev/null
+++ b/host/frontend/gcastv2/webrtc/OpusPacketizer.cpp
@@ -0,0 +1,75 @@
+/*
+ * 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.
+ */
+
+#include <webrtc/OpusPacketizer.h>
+
+#include "Utils.h"
+
+#include <webrtc/RTPSocketHandler.h>
+
+#include <https/SafeCallbackable.h>
+
+using namespace android;
+
+OpusPacketizer::OpusPacketizer(
+ std::shared_ptr<RunLoop> runLoop,
+ std::shared_ptr<StreamingSource> audioSource)
+ : Packetizer(runLoop, audioSource),
+ mFirstInTalkspurt(true) {
+}
+
+void OpusPacketizer::packetize(const std::shared_ptr<SBuffer> &accessUnit, int64_t timeUs) {
+ LOG(VERBOSE) << "Received Opus frame of size " << accessUnit->size();
+
+ static constexpr uint8_t PT = 98;
+ static constexpr uint32_t SSRC = 0x8badf00d;
+
+ // XXX Retransmission packets add 2 bytes (for the original seqNum), should
+ // probably reserve that amount in the original packets so we don't exceed
+ // the MTU on retransmission.
+ static const size_t kMaxSRTPPayloadSize =
+ RTPSocketHandler::kMaxUDPPayloadSize - SRTP_MAX_TRAILER_LEN;
+
+ const uint8_t *audioData = accessUnit->data();
+ size_t size = accessUnit->size();
+
+ uint32_t rtpTime = ((timeUs - mediaStartTime()) * 48) / 1000;
+
+ CHECK_LE(12 + size, kMaxSRTPPayloadSize);
+
+ std::vector<uint8_t> packet(12 + size);
+ uint8_t *data = packet.data();
+
+ packet[0] = 0x80;
+ packet[1] = PT;
+
+ if (mFirstInTalkspurt) {
+ packet[1] |= 0x80; // (M)ark
+ mFirstInTalkspurt = false;
+ }
+
+ SET_U16(&data[2], 0); // seqNum
+ SET_U32(&data[4], rtpTime);
+ SET_U32(&data[8], SSRC);
+
+ memcpy(&data[12], audioData, size);
+
+ queueRTPDatagram(&packet);
+}
+
+uint32_t OpusPacketizer::rtpNow() const {
+ return (timeSinceStart() * 48) / 1000;
+}
diff --git a/host/frontend/gcastv2/webrtc/Packetizer.cpp b/host/frontend/gcastv2/webrtc/Packetizer.cpp
new file mode 100644
index 000000000..bbe610271
--- /dev/null
+++ b/host/frontend/gcastv2/webrtc/Packetizer.cpp
@@ -0,0 +1,113 @@
+/*
+ * 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.
+ */
+
+#include <webrtc/Packetizer.h>
+
+#include <https/SafeCallbackable.h>
+#include <webrtc/RTPSender.h>
+
+Packetizer::Packetizer(std::shared_ptr<RunLoop> runLoop,
+ std::shared_ptr<StreamingSource> source)
+ : mNumSamplesRead(0),
+ mStartTimeMedia(0),
+ mRunLoop(runLoop),
+ mStreamingSource(source) {}
+
+Packetizer::~Packetizer() {
+ if (mStreamingSource) {
+ mStreamingSource->stop();
+ }
+}
+
+void Packetizer::queueRTPDatagram(std::vector<uint8_t> *packet) {
+ auto it = mSenders.begin();
+ while (it != mSenders.end()) {
+ auto sender = it->lock();
+ if (!sender) {
+ it = mSenders.erase(it);
+ mStreamingSource->notifyStreamConsumerDisconnected();
+ continue;
+ }
+
+ sender->queueRTPDatagram(packet);
+ ++it;
+ }
+}
+
+void Packetizer::addSender(std::shared_ptr<RTPSender> sender) {
+ mSenders.push_back(sender);
+ auto weak_source = std::weak_ptr<StreamingSource>(mStreamingSource);
+ mRunLoop->post([weak_source](){
+ auto source = weak_source.lock();
+ if (!source) return;
+ source->notifyNewStreamConsumer();
+ });
+}
+
+int32_t Packetizer::requestIDRFrame() {
+ return mStreamingSource->requestIDRFrame();
+}
+
+void Packetizer::run() {
+ auto weak_this = weak_from_this();
+
+ mStreamingSource->setCallback(
+ [weak_this](const std::shared_ptr<android::SBuffer> &accessUnit) {
+ auto me = weak_this.lock();
+ if (me) {
+ me->mRunLoop->post(
+ makeSafeCallback(
+ me.get(), &Packetizer::onFrame, accessUnit));
+ }
+ });
+
+ mStreamingSource->start();
+}
+
+void Packetizer::onFrame(const std::shared_ptr<android::SBuffer>& accessUnit) {
+ if (!accessUnit) {
+ LOG(WARNING) << "Received invalid buffer in " << __FUNCTION__;
+ return;
+ }
+ int64_t timeUs = accessUnit->time_us();
+ CHECK(timeUs);
+
+ auto now = std::chrono::steady_clock::now();
+
+ if (mNumSamplesRead == 0) {
+ mStartTimeMedia = timeUs;
+ mStartTimeReal = now;
+ }
+
+ ++mNumSamplesRead;
+
+ LOG(VERBOSE)
+ << "got accessUnit of size "
+ << accessUnit->size()
+ << " at time "
+ << timeUs;
+
+ packetize(accessUnit, timeUs);
+}
+
+uint32_t Packetizer::timeSinceStart() const {
+ if (mNumSamplesRead) return 0;
+
+ auto now = std::chrono::steady_clock::now();
+ return std::chrono::duration_cast<std::chrono::microseconds>(now -
+ mStartTimeReal)
+ .count();
+}
diff --git a/host/frontend/gcastv2/webrtc/RTPSender.cpp b/host/frontend/gcastv2/webrtc/RTPSender.cpp
new file mode 100644
index 000000000..de05556da
--- /dev/null
+++ b/host/frontend/gcastv2/webrtc/RTPSender.cpp
@@ -0,0 +1,582 @@
+/*
+ * 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.
+ */
+
+#include <webrtc/RTPSender.h>
+
+#include "Utils.h"
+
+#include <webrtc/RTPSocketHandler.h>
+
+#include <https/SafeCallbackable.h>
+#include <https/Support.h>
+
+#include <random>
+#include <unordered_set>
+
+#define SIMULATE_PACKET_LOSS 0
+
+RTPSender::RTPSender(
+ std::shared_ptr<RunLoop> runLoop,
+ RTPSocketHandler *parent,
+ std::shared_ptr<Packetizer> videoPacketizer,
+ std::shared_ptr<Packetizer> audioPacketizer)
+ : mRunLoop(runLoop),
+ mParent(parent),
+ mVideoPacketizer(videoPacketizer),
+ mAudioPacketizer(audioPacketizer) {
+}
+
+void RTPSender::addSource(uint32_t ssrc) {
+ CHECK(mSources.insert(
+ std::make_pair(ssrc, SourceInfo())).second);
+}
+
+void RTPSender::addRetransInfo(
+ uint32_t ssrc, uint8_t PT, uint32_t retransSSRC, uint8_t retransPT) {
+ auto it = mSources.find(ssrc);
+ CHECK(it != mSources.end());
+
+ auto &info = it->second;
+
+ CHECK(info.mRetrans.insert(
+ std::make_pair(
+ PT, std::make_pair(retransSSRC, retransPT))).second);
+}
+
+int RTPSender::injectRTCP(uint8_t *data, size_t size) {
+ // LOG(INFO) << "RTPSender::injectRTCP";
+ // hexdump(data, size);
+
+ while (size > 0) {
+ if (size < 8) {
+ return -EINVAL;
+ }
+
+ if ((data[0] >> 6) != 2) {
+ // Wrong version.
+ return -EINVAL;
+ }
+
+ size_t lengthInWords = U16_AT(&data[2]) + 1;
+
+ bool hasPadding = (data[0] & 0x20);
+
+ size_t headerSize = 4 * lengthInWords;
+
+ if (size < headerSize) {
+ return -EINVAL;
+ }
+
+ if (hasPadding) {
+ if (size != headerSize) {
+ // Padding should only be added to the last packet in a compound
+ // packet.
+ return -EINVAL;
+ }
+
+ size_t numPadBytes = data[headerSize - 1];
+ if (numPadBytes == 0 || (numPadBytes % 4) != 0) {
+ return -EINVAL;
+ }
+
+ headerSize -= numPadBytes;
+ }
+
+ auto err = processRTCP(data, headerSize);
+
+ if (err) {
+ return err;
+ }
+
+ data += 4 * lengthInWords;
+ size -= 4 * lengthInWords;
+ }
+
+ return 0;
+}
+
+int RTPSender::processRTCP(const uint8_t *data, size_t size) {
+ static constexpr uint8_t RR = 201; // RFC 3550
+ // static constexpr uint8_t SDES = 202;
+ // static constexpr uint8_t BYE = 203;
+ // static constexpr uint8_t APP = 204;
+ static constexpr uint8_t RTPFB = 205; // RFC 4585
+ static constexpr uint8_t PSFB = 206;
+ static constexpr uint8_t XR = 207; // RFC 3611
+
+ unsigned PT = data[1];
+
+ switch (PT) {
+ case RR:
+ {
+ unsigned RC = data[0] & 0x1f;
+ if (size != 8 + RC * 6 * 4) {
+ return -EINVAL;
+ }
+
+ auto senderSSRC = U32_AT(&data[4]);
+
+ size_t offset = 8;
+ for (unsigned i = 0; i < RC; ++i) {
+ auto SSRC = U32_AT(&data[offset]);
+ auto fractionLost = data[offset + 4];
+ auto cumPacketsLost = U32_AT(&data[offset + 4]) & 0xffffff;
+
+ if (fractionLost) {
+ LOG(INFO)
+ << "sender SSRC "
+ << StringPrintf("0x%08x", senderSSRC)
+ << " reports "
+ << StringPrintf("%.2f %%", (double)fractionLost * 100.0 / 256.0)
+ << " lost, cum. total: "
+ << cumPacketsLost
+ << " from SSRC "
+ << StringPrintf("0x%08x", SSRC);
+ }
+
+ offset += 6 * 4;
+ }
+ break;
+ }
+
+ case RTPFB:
+ {
+ static constexpr uint8_t NACK = 1;
+
+ if (size < 12) {
+ return -EINVAL;
+ }
+
+ unsigned fmt = data[0] & 0x1f;
+
+ auto senderSSRC = U32_AT(&data[4]);
+ auto SSRC = U32_AT(&data[8]);
+
+ switch (fmt) {
+ case NACK:
+ {
+ size_t offset = 12;
+ size_t n = (size - offset) / 4;
+ for (size_t i = 0; i < n; ++i) {
+ auto PID = U16_AT(&data[offset]);
+ auto BLP = U16_AT(&data[offset + 2]);
+
+ LOG(INFO)
+ << "SSRC "
+ << StringPrintf("0x%08x", senderSSRC)
+ << " reports NACK w/ PID="
+ << StringPrintf("0x%04x", PID)
+ << ", BLP="
+ << StringPrintf("0x%04x", BLP)
+ << " from SSRC "
+ << StringPrintf("0x%08x", SSRC);
+
+ offset += 4;
+
+ retransmitPackets(SSRC, PID, BLP);
+ }
+ break;
+ }
+
+ default:
+ {
+ LOG(WARNING) << "RTPSender::processRTCP unhandled RTPFB.";
+ hexdump(data, size);
+ break;
+ }
+ }
+
+ break;
+ }
+
+ case PSFB:
+ {
+ static constexpr uint8_t FMT_PLI = 1;
+ static constexpr uint8_t FMT_SLI = 2;
+ static constexpr uint8_t FMT_AFB = 15;
+
+ if (size < 12) {
+ return -EINVAL;
+ }
+
+ unsigned fmt = data[0] & 0x1f;
+
+ auto SSRC = U32_AT(&data[4]);
+
+ switch (fmt) {
+ case FMT_PLI:
+ {
+ if (size != 12) {
+ return -EINVAL;
+ }
+
+ LOG(INFO)
+ << "Received PLI from SSRC "
+ << StringPrintf("0x%08x", SSRC);
+
+ if (mVideoPacketizer) {
+ mVideoPacketizer->requestIDRFrame();
+ }
+ break;
+ }
+
+ case FMT_SLI:
+ {
+ LOG(INFO)
+ << "Received SLI from SSRC "
+ << StringPrintf("0x%08x", SSRC);
+
+ break;
+ }
+
+ case FMT_AFB:
+ break;
+
+ default:
+ {
+ LOG(WARNING) << "RTPSender::processRTCP unhandled PSFB.";
+ hexdump(data, size);
+ break;
+ }
+ }
+ break;
+ }
+
+ case XR:
+ {
+ static constexpr uint8_t FMT_RRTRB = 4;
+
+ if (size < 8) {
+ return -EINVAL;
+ }
+
+ auto senderSSRC = U32_AT(&data[4]);
+
+ size_t offset = 8;
+ while (offset + 3 < size) {
+ auto fmt = data[offset];
+ auto blockLength = 4 * (1 + U16_AT(&data[offset + 2]));
+
+ if (offset + blockLength > size) {
+ LOG(WARNING) << "Found incomplete XR report block.";
+ break;
+ }
+
+ switch (fmt) {
+ case FMT_RRTRB:
+ {
+ if (blockLength != 12) {
+ LOG(WARNING)
+ << "Found XR-RRTRB block of invalid length.";
+ break;
+ }
+
+ auto ntpHi = U32_AT(&data[offset + 4]);
+ auto ntpLo = U32_AT(&data[offset + 8]);
+
+ queueDLRR(
+ 0xdeadbeef /* localSSRC */,
+ senderSSRC,
+ ntpHi,
+ ntpLo);
+ break;
+ }
+
+ default:
+ {
+ LOG(WARNING)
+ << "Ignoring unknown XR block type " << fmt;
+
+ break;
+ }
+ }
+
+ offset += blockLength;
+ }
+
+ if (offset != size) {
+ LOG(WARNING) << "Found trailing bytes in XR report.";
+ }
+ break;
+ }
+
+ default:
+ {
+ LOG(WARNING) << "RTPSender::processRTCP unhandled packet type.";
+ hexdump(data, size);
+ }
+ }
+
+ return 0;
+}
+
+void RTPSender::appendSR(std::vector<uint8_t> *buffer, uint32_t localSSRC) {
+ static constexpr uint8_t SR = 200;
+
+ auto it = mSources.find(localSSRC);
+ CHECK(it != mSources.end());
+
+ const auto &info = it->second;
+
+ const size_t kLengthInWords = 7;
+
+ auto offset = buffer->size();
+ buffer->resize(offset + kLengthInWords * sizeof(uint32_t));
+
+ uint8_t *data = buffer->data() + offset;
+
+ data[0] = 0x80;
+ data[1] = SR;
+ SET_U16(&data[2], kLengthInWords - 1);
+ SET_U32(&data[4], localSSRC);
+
+ auto now = std::chrono::system_clock::now();
+
+ auto us_since_epoch =
+ std::chrono::duration_cast<std::chrono::microseconds>(
+ now.time_since_epoch()).count();
+
+ // This assumes that sd::chrono::system_clock's epoch is unix epoch, i.e.
+ // 1/1/1970 midnight UTC.
+ // Microseconds between midnight 1/1/1970 and midnight 1/1/1900.
+ us_since_epoch += 2208988800ULL * 1000ull;
+
+ uint64_t ntpHi = us_since_epoch / 1000000ll;
+ uint64_t ntpLo = ((1LL << 32) * (us_since_epoch % 1000000LL)) / 1000000LL;
+
+ uint32_t rtpNow =
+ (localSSRC == 0xdeadbeef || localSSRC == 0xcafeb0b0)
+ ? mVideoPacketizer->rtpNow()
+ : mAudioPacketizer->rtpNow();
+
+ SET_U32(&data[8], ntpHi);
+ SET_U32(&data[12], ntpLo);
+ SET_U32(&data[16], rtpNow);
+ SET_U32(&data[20], info.mNumPacketsSent);
+ SET_U32(&data[24], info.mNumBytesSent);
+}
+
+void RTPSender::appendSDES(std::vector<uint8_t> *buffer, uint32_t localSSRC) {
+ static constexpr uint8_t SDES = 202;
+
+ static const char *const kCNAME = "myWebRTP";
+ static const size_t kCNAMELength = strlen(kCNAME);
+
+ const size_t kLengthInWords = 2 + (2 + kCNAMELength + 1 + 3) / 4;
+
+ auto offset = buffer->size();
+ buffer->resize(offset + kLengthInWords * sizeof(uint32_t));
+
+ uint8_t *data = buffer->data() + offset;
+
+ data[0] = 0x81;
+ data[1] = SDES;
+ SET_U16(&data[2], kLengthInWords - 1);
+ SET_U32(&data[4], localSSRC);
+
+ data[8] = 1; // CNAME
+ data[9] = kCNAMELength;
+ memcpy(&data[10], kCNAME, kCNAMELength);
+ data[10 + kCNAMELength] = '\0';
+}
+
+void RTPSender::queueDLRR(
+ uint32_t localSSRC,
+ uint32_t remoteSSRC,
+ uint32_t ntpHi,
+ uint32_t ntpLo) {
+ std::vector<uint8_t> buffer;
+ appendDLRR(&buffer, localSSRC, remoteSSRC, ntpHi, ntpLo);
+
+ mParent->queueRTCPDatagram(buffer.data(), buffer.size());
+}
+
+void RTPSender::appendDLRR(
+ std::vector<uint8_t> *buffer,
+ uint32_t localSSRC,
+ uint32_t remoteSSRC,
+ uint32_t ntpHi,
+ uint32_t ntpLo) {
+ static constexpr uint8_t XR = 207;
+
+ static constexpr uint8_t FMT_DLRRRB = 5;
+
+ const size_t kLengthInWords = 2 + 4;
+
+ auto offset = buffer->size();
+ buffer->resize(offset + kLengthInWords * sizeof(uint32_t));
+
+ uint8_t *data = buffer->data() + offset;
+
+ data[0] = 0x80;
+ data[1] = XR;
+ SET_U16(&data[2], kLengthInWords - 1);
+ SET_U32(&data[4], localSSRC);
+
+ data[8] = FMT_DLRRRB;
+ data[9] = 0x00;
+ SET_U16(&data[10], 3 /* block length */);
+ SET_U32(&data[12], remoteSSRC);
+ SET_U32(&data[16], (ntpHi << 16) | (ntpLo >> 16));
+ SET_U32(&data[20], 0 /* delay since last RR */);
+}
+
+void RTPSender::queueSR(uint32_t localSSRC) {
+ std::vector<uint8_t> buffer;
+ appendSR(&buffer, localSSRC);
+ // appendSDES(&buffer, localSSRC);
+
+ // LOG(INFO) << "RTPSender::queueSR";
+ // hexdump(buffer.data(), buffer.size());
+
+ mParent->queueRTCPDatagram(buffer.data(), buffer.size());
+}
+
+void RTPSender::sendSR(uint32_t localSSRC) {
+ // LOG(INFO) << "sending SR.";
+ queueSR(localSSRC);
+
+ mRunLoop->postWithDelay(
+ std::chrono::seconds(1),
+ makeSafeCallback(this, &RTPSender::sendSR, localSSRC));
+}
+
+void RTPSender::run() {
+ for (const auto &entry : mSources) {
+ sendSR(entry.first);
+ }
+}
+
+void RTPSender::queueRTPDatagram(std::vector<uint8_t> *packet) {
+ CHECK_GE(packet->size(), 12u);
+
+ uint32_t SSRC = U32_AT(&packet->data()[8]);
+
+ auto it = mSources.find(SSRC);
+ CHECK(it != mSources.end());
+
+ auto &info = it->second;
+
+ uint16_t seqNum = info.mNumPacketsSent;
+ SET_U16(packet->data() + 2, seqNum);
+
+#if SIMULATE_PACKET_LOSS
+ static std::random_device rd;
+ static std::mt19937 gen(rd());
+ static std::uniform_real_distribution<> dist(0.0, 1.0);
+ if (dist(gen) < 0.99) {
+#endif
+ mParent->queueRTPDatagram(packet->data(), packet->size());
+#if SIMULATE_PACKET_LOSS
+ } else {
+ LOG(WARNING)
+ << "dropping packet "
+ << StringPrintf("0x%04x", seqNum)
+ << " from SSRC "
+ << StringPrintf("0x%08x", SSRC);
+ }
+#endif
+
+ ++info.mNumPacketsSent;
+ info.mNumBytesSent += packet->size() - 12; // does not include RTP header.
+
+ if (!info.mRetrans.empty()) {
+ static constexpr size_t kMaxHistory = 512;
+ if (info.mRecentPackets.size() == kMaxHistory) {
+ info.mRecentPackets.pop_front();
+ }
+ // info.mRecentPackets.push_back(std::move(*packet));
+ info.mRecentPackets.push_back(*packet);
+ }
+}
+
+void RTPSender::retransmitPackets(
+ uint32_t localSSRC, uint16_t PID, uint16_t BLP) {
+ auto it = mSources.find(localSSRC);
+ CHECK(it != mSources.end());
+
+ const auto &info = it->second;
+
+ if (!info.mRecentPackets.empty()) {
+ LOG(INFO) << "Recent packets cover range ["
+ << StringPrintf(
+ "0x%04x", U16_AT(info.mRecentPackets.front().data() + 2))
+ << ";"
+ << StringPrintf(
+ "0x%04x", U16_AT(info.mRecentPackets.back().data() + 2))
+ << "]";
+ } else {
+ LOG(INFO) << "Recent packets are EMPTY!";
+ }
+
+ bool first = true;
+ while (first || BLP) {
+ if (first) {
+ first = false;
+ } else {
+ ++PID;
+ if (!(BLP & 1)) {
+ BLP = BLP >> 1;
+ continue;
+ }
+
+ BLP = BLP >> 1;
+ }
+
+ for (auto it = info.mRecentPackets.begin();
+ it != info.mRecentPackets.end();
+ ++it) {
+ const auto &origPacket = *it;
+ auto seqNum = U16_AT(origPacket.data() + 2);
+
+ if (seqNum != PID) {
+ continue;
+ }
+
+ LOG(INFO) << "Retransmitting PID " << StringPrintf("0x%04x", PID);
+
+ auto PT = origPacket[1] & 0x7f;
+ auto it2 = info.mRetrans.find(PT);
+ CHECK(it2 != info.mRetrans.end());
+
+ auto [rtxSSRC, rtxPT] = it2->second;
+
+ std::vector<uint8_t> packet(origPacket.size() + 2);
+
+ // XXX This is very simplified and assumes that the original packet
+ // started with a standard 12-byte header, no extensions and no padding!
+ memcpy(packet.data(), origPacket.data(), 12);
+
+ packet[1] = (origPacket[1] & 0x80) | (rtxPT & 0x7f);
+ SET_U32(packet.data() + 8, rtxSSRC);
+ SET_U16(packet.data() + 12, seqNum);
+
+ memcpy(packet.data() + 14,
+ origPacket.data() + 12,
+ origPacket.size() - 12);
+
+ // queueRTPDatagram will fill in the new seqNum.
+ queueRTPDatagram(&packet);
+ }
+ }
+}
+
+void RTPSender::requestIDRFrame() {
+ if (mVideoPacketizer) {
+ mVideoPacketizer->requestIDRFrame();
+ }
+}
+
diff --git a/host/frontend/gcastv2/webrtc/RTPSession.cpp b/host/frontend/gcastv2/webrtc/RTPSession.cpp
new file mode 100644
index 000000000..8eeef1f53
--- /dev/null
+++ b/host/frontend/gcastv2/webrtc/RTPSession.cpp
@@ -0,0 +1,142 @@
+/*
+ * 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.
+ */
+
+#include <webrtc/RTPSession.h>
+
+#include <android-base/logging.h>
+
+#include <sstream>
+
+RTPSession::RTPSession(
+ std::string_view localUFrag,
+ std::string_view localPassword,
+ std::shared_ptr<X509> localCertificate,
+ std::shared_ptr<EVP_PKEY> localKey)
+ : mLocalUFrag(localUFrag),
+ mLocalPassword(localPassword),
+ mLocalCertificate(localCertificate),
+ mLocalKey(localKey),
+ mPingToken(0),
+ mIsActive(false) {
+}
+
+bool RTPSession::isActive() const {
+ return mIsActive;
+}
+
+void RTPSession::setIsActive() {
+ mIsActive = true;
+}
+
+void RTPSession::schedulePing(
+ std::shared_ptr<RunLoop> runLoop,
+ RunLoop::AsyncFunction cb,
+ std::chrono::steady_clock::duration delay) {
+ CHECK_EQ(mPingToken, 0);
+
+ mPingToken = runLoop->postWithDelay(
+ delay,
+ [weak_this = std::weak_ptr<RTPSession>(shared_from_this()),
+ runLoop, cb]() {
+ auto me = weak_this.lock();
+ if (me) {
+ me->mPingToken = 0;
+ cb();
+ }
+ });
+}
+
+void RTPSession::setRemoteParams(
+ std::string_view remoteUFrag,
+ std::string_view remotePassword,
+ std::string_view remoteFingerprint) {
+ CHECK(!mRemoteUFrag && !mRemotePassword && !mRemoteFingerprint);
+
+ mRemoteUFrag = remoteUFrag;
+ mRemotePassword = remotePassword;
+ mRemoteFingerprint = remoteFingerprint;
+}
+
+std::string RTPSession::localUFrag() const {
+ return mLocalUFrag;
+}
+
+std::string RTPSession::localPassword() const {
+ return mLocalPassword;
+}
+
+std::shared_ptr<X509> RTPSession::localCertificate() const {
+ return mLocalCertificate;
+}
+
+std::shared_ptr<EVP_PKEY> RTPSession::localKey() const {
+ return mLocalKey;
+}
+
+std::string RTPSession::localFingerprint() const {
+ auto digest = EVP_sha256();
+
+ unsigned char md[EVP_MAX_MD_SIZE];
+ unsigned int n;
+ auto res = X509_digest(mLocalCertificate.get(), digest, md, &n);
+ CHECK_EQ(res, 1);
+
+ std::stringstream ss;
+ ss << "sha-256 ";
+ for (unsigned int i = 0; i < n; ++i) {
+ if (i > 0) {
+ ss << ":";
+ }
+
+ uint8_t byte = md[i];
+ uint8_t nibble = byte >> 4;
+ ss << (char)(nibble < 10 ? '0' + nibble : 'A' + nibble - 10);
+ nibble = byte & 0xf;
+ ss << (char)(nibble < 10 ? '0' + nibble : 'A' + nibble - 10);
+ }
+
+ return ss.str();
+}
+
+std::string RTPSession::remoteUFrag() const {
+ CHECK(mRemoteUFrag.has_value());
+ return *mRemoteUFrag;
+}
+
+std::string RTPSession::remotePassword() const {
+ CHECK(mRemotePassword.has_value());
+ return *mRemotePassword;
+}
+
+std::string RTPSession::remoteFingerprint() const {
+ CHECK(mRemoteFingerprint.has_value());
+ return *mRemoteFingerprint;
+}
+
+bool RTPSession::hasRemoteAddress() const {
+ return mRemoteAddr.has_value();
+}
+
+sockaddr_storage RTPSession::remoteAddress() const {
+ CHECK(hasRemoteAddress());
+ return *mRemoteAddr;
+}
+
+void RTPSession::setRemoteAddress(const sockaddr_storage &remoteAddr) {
+ CHECK(!hasRemoteAddress());
+ mRemoteAddr = remoteAddr;
+}
+
diff --git a/host/frontend/gcastv2/webrtc/RTPSocketHandler.cpp b/host/frontend/gcastv2/webrtc/RTPSocketHandler.cpp
new file mode 100644
index 000000000..3885039e9
--- /dev/null
+++ b/host/frontend/gcastv2/webrtc/RTPSocketHandler.cpp
@@ -0,0 +1,739 @@
+/*
+ * 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.
+ */
+
+#include <webrtc/RTPSocketHandler.h>
+
+#include <webrtc/MyWebSocketHandler.h>
+#include <webrtc/STUNMessage.h>
+#include <Utils.h>
+
+#include <https/PlainSocket.h>
+#include <https/SafeCallbackable.h>
+#include <https/Support.h>
+#include <android-base/logging.h>
+
+#include <netdb.h>
+#include <netinet/in.h>
+
+#include <cstring>
+#include <iostream>
+#include <set>
+
+#include <gflags/gflags.h>
+
+DECLARE_string(public_ip);
+
+// These are the ports we currently open in the firewall (15550..15557)
+static constexpr int kPortRangeBegin = 15550;
+static constexpr int kPortRangeEnd = 15558;
+static constexpr int kPortRangeEndTcp = 15551;
+
+static socklen_t getSockAddrLen(const sockaddr_storage &addr) {
+ switch (addr.ss_family) {
+ case AF_INET:
+ return sizeof(sockaddr_in);
+ case AF_INET6:
+ return sizeof(sockaddr_in6);
+ default:
+ CHECK(!"Should not be here.");
+ return 0;
+ }
+}
+
+static int acquirePort(int sockfd, int domain, bool tcp) {
+ sockaddr_storage addr;
+ uint16_t* port_ptr;
+
+ if (domain == PF_INET) {
+ sockaddr_in addrV4;
+ memset(addrV4.sin_zero, 0, sizeof(addrV4.sin_zero));
+ addrV4.sin_family = AF_INET;
+ addrV4.sin_addr.s_addr = INADDR_ANY;
+ memcpy(&addr, &addrV4, sizeof(addrV4));
+ port_ptr = &(reinterpret_cast<sockaddr_in*>(&addr)->sin_port);
+ } else {
+ CHECK_EQ(domain, PF_INET6);
+ sockaddr_in6 addrV6;
+ addrV6.sin6_family = AF_INET6;
+ addrV6.sin6_addr = in6addr_any;
+ addrV6.sin6_scope_id = 0;
+ memcpy(&addr, &addrV6, sizeof(addrV6));
+ port_ptr = &(reinterpret_cast<sockaddr_in6*>(&addr)->sin6_port);
+ }
+
+ int port = kPortRangeBegin;
+ for (;port < kPortRangeEnd; ++port) {
+ *port_ptr = htons(port);
+ errno = 0;
+ int res = bind(sockfd, reinterpret_cast<const sockaddr *>(&addr),
+ getSockAddrLen(addr));
+ if (res == 0) {
+ return port;
+ }
+ if (errno != EADDRINUSE) {
+ return -1;
+ }
+ // for now, limit to one client / one tcp port to minimize
+ // complexity for using WebRTC over TCP over ssh tunnels
+ if (tcp && port == kPortRangeEndTcp)
+ break;
+ // else try the next port
+ }
+
+ return -1;
+}
+
+RTPSocketHandler::RTPSocketHandler(
+ std::shared_ptr<RunLoop> runLoop,
+ std::shared_ptr<ServerState> serverState,
+ TransportType transportType,
+ int domain,
+ uint32_t trackMask,
+ std::shared_ptr<RTPSession> session)
+ : mRunLoop(runLoop),
+ mServerState(serverState),
+ mTransportType(transportType),
+ mTrackMask(trackMask),
+ mSession(session),
+ mSendPending(false),
+ mDTLSConnected(false),
+ mInBufferLength(0) {
+ bool tcp = mTransportType == TransportType::TCP;
+
+ int sock = socket(domain, tcp ? SOCK_STREAM : SOCK_DGRAM, 0);
+
+ if (tcp) {
+ static constexpr int yes = 1;
+ auto res = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));
+ CHECK(!res);
+ }
+
+ makeFdNonblocking(sock);
+
+ mLocalPort = acquirePort(sock, domain, tcp);
+
+ CHECK(mLocalPort > 0);
+
+ if (tcp) {
+ auto res = listen(sock, 4);
+ CHECK(!res);
+ }
+
+ auto tmp = std::make_shared<PlainSocket>(mRunLoop, sock);
+ if (tcp) {
+ mServerSocket = tmp;
+ } else {
+ mSocket = tmp;
+ }
+
+ auto videoPacketizer =
+ (trackMask & TRACK_VIDEO)
+ ? mServerState->getVideoPacketizer() : nullptr;
+
+ auto audioPacketizer =
+ (trackMask & TRACK_AUDIO)
+ ? mServerState->getAudioPacketizer() : nullptr;
+
+ mRTPSender = std::make_shared<RTPSender>(
+ mRunLoop,
+ this,
+ videoPacketizer,
+ audioPacketizer);
+
+ if (trackMask & TRACK_VIDEO) {
+ mRTPSender->addSource(0xdeadbeef);
+ mRTPSender->addSource(0xcafeb0b0);
+
+ mRTPSender->addRetransInfo(0xdeadbeef, 96, 0xcafeb0b0, 97);
+ }
+
+ if (trackMask & TRACK_AUDIO) {
+ mRTPSender->addSource(0x8badf00d);
+ }
+}
+
+uint16_t RTPSocketHandler::getLocalPort() const {
+ return mLocalPort;
+}
+
+std::string RTPSocketHandler::getLocalUFrag() const {
+ return mSession->localUFrag();
+}
+
+std::string RTPSocketHandler::getLocalIPString() const {
+ return FLAGS_public_ip;
+}
+
+void RTPSocketHandler::run() {
+ if (mTransportType == TransportType::TCP) {
+ mServerSocket->postRecv(
+ makeSafeCallback(this, &RTPSocketHandler::onTCPConnect));
+ } else {
+ mSocket->postRecv(makeSafeCallback(this, &RTPSocketHandler::onReceive));
+ }
+}
+
+void RTPSocketHandler::onTCPConnect() {
+ int sock = accept(mServerSocket->fd(), nullptr, 0);
+
+ if (sock < 0) {
+ LOG(ERROR) << "RTPSocketHandler: Failed to accept client";
+ mSocket->postRecv(makeSafeCallback(this, &RTPSocketHandler::onTCPConnect));
+ return;
+ }
+
+ LOG(INFO) << "RTPSocketHandler: Accepted client";
+
+ makeFdNonblocking(sock);
+
+ mClientAddrLen = sizeof(mClientAddr);
+
+ int res = getpeername(
+ sock, reinterpret_cast<sockaddr *>(&mClientAddr), &mClientAddrLen);
+
+ CHECK(!res);
+
+ mSocket = std::make_shared<PlainSocket>(mRunLoop, sock);
+
+ mSocket->postRecv(makeSafeCallback(this, &RTPSocketHandler::onTCPReceive));
+}
+
+void RTPSocketHandler::onTCPReceive() {
+ mInBuffer.resize(mInBuffer.size() + 8192);
+
+ auto n = mSocket->recv(
+ mInBuffer.data() + mInBufferLength, mInBuffer.size() - mInBufferLength);
+
+ if (n == 0) {
+ LOG(INFO) << "Client disconnected.";
+ return;
+ }
+
+ mInBufferLength += n;
+
+ size_t offset = 0;
+ while (offset + 1 < mInBufferLength) {
+ auto packetLength = U16_AT(mInBuffer.data() + offset);
+ offset += 2;
+
+ if (offset + packetLength > mInBufferLength) {
+ break;
+ }
+
+ onPacketReceived(
+ mClientAddr,
+ mClientAddrLen,
+ mInBuffer.data() + offset,
+ packetLength);
+
+ offset += packetLength;
+ }
+
+ if (offset > 0) {
+ mInBuffer.erase(mInBuffer.begin(), mInBuffer.begin() + offset);
+ mInBufferLength -= offset;
+ }
+
+ mSocket->postRecv(makeSafeCallback(this, &RTPSocketHandler::onTCPReceive));
+}
+
+void RTPSocketHandler::onReceive() {
+ std::vector<uint8_t> buffer(kMaxUDPPayloadSize);
+
+ uint8_t *data = buffer.data();
+
+ sockaddr_storage addr;
+ socklen_t addrLen = sizeof(addr);
+
+ auto n = mSocket->recvfrom(
+ data, buffer.size(), reinterpret_cast<sockaddr *>(&addr), &addrLen);
+
+ onPacketReceived(addr, addrLen, data, n);
+
+ mSocket->postRecv(makeSafeCallback(this, &RTPSocketHandler::onReceive));
+}
+
+void RTPSocketHandler::onPacketReceived(
+ const sockaddr_storage &addr,
+ socklen_t addrLen,
+ uint8_t *data,
+ size_t n) {
+#if 0
+ std::cout << "========================================" << std::endl;
+
+ hexdump(data, n);
+#endif
+
+ STUNMessage msg(data, n);
+ if (!msg.isValid()) {
+ if (mDTLSConnected) {
+ int err = -EINVAL;
+ if (mRTPSender) {
+ err = onSRTPReceive(data, static_cast<size_t>(n));
+ }
+
+ if (err == -EINVAL) {
+ LOG(VERBOSE) << "Sending to DTLS instead:";
+ // hexdump(data, n);
+
+ onDTLSReceive(data, static_cast<size_t>(n));
+
+ if (mTrackMask & TRACK_DATA) {
+ ssize_t n;
+
+ do {
+ uint8_t buf[kMaxUDPPayloadSize];
+ n = mDTLS->readApplicationData(buf, sizeof(buf));
+
+ if (n > 0) {
+ auto err = mSCTPHandler->inject(
+ buf, static_cast<size_t>(n));
+
+ if (err) {
+ LOG(WARNING)
+ << "SCTPHandler::inject returned error "
+ << err;
+ }
+ }
+ } while (n > 0);
+ }
+ }
+ } else {
+ onDTLSReceive(data, static_cast<size_t>(n));
+ }
+
+ return;
+ }
+
+ if (msg.type() == 0x0001 /* Binding Request */) {
+ STUNMessage response(0x0101 /* Binding Response */, msg.data() + 8);
+
+ if (!matchesSession(msg)) {
+ LOG(WARNING) << "Unknown session or no USERNAME.";
+ return;
+ }
+
+ const auto &answerPassword = mSession->localPassword();
+
+ // msg.dump(answerPassword);
+
+ if (addr.ss_family == AF_INET) {
+ uint8_t attr[8];
+ attr[0] = 0x00;
+
+ sockaddr_in addrV4;
+ CHECK_EQ(addrLen, sizeof(addrV4));
+
+ memcpy(&addrV4, &addr, addrLen);
+
+ attr[1] = 0x01; // IPv4
+
+ static constexpr uint32_t kMagicCookie = 0x2112a442;
+
+ uint16_t portHost = ntohs(addrV4.sin_port);
+ portHost ^= (kMagicCookie >> 16);
+
+ uint32_t ipHost = ntohl(addrV4.sin_addr.s_addr);
+ ipHost ^= kMagicCookie;
+
+ attr[2] = portHost >> 8;
+ attr[3] = portHost & 0xff;
+ attr[4] = ipHost >> 24;
+ attr[5] = (ipHost >> 16) & 0xff;
+ attr[6] = (ipHost >> 8) & 0xff;
+ attr[7] = ipHost & 0xff;
+
+ response.addAttribute(
+ 0x0020 /* XOR-MAPPED-ADDRESS */, attr, sizeof(attr));
+ } else {
+ uint8_t attr[20];
+ attr[0] = 0x00;
+
+ CHECK_EQ(addr.ss_family, AF_INET6);
+
+ sockaddr_in6 addrV6;
+ CHECK_EQ(addrLen, sizeof(addrV6));
+
+ memcpy(&addrV6, &addr, addrLen);
+
+ attr[1] = 0x02; // IPv6
+
+ static constexpr uint32_t kMagicCookie = 0x2112a442;
+
+ uint16_t portHost = ntohs(addrV6.sin6_port);
+ portHost ^= (kMagicCookie >> 16);
+
+ attr[2] = portHost >> 8;
+ attr[3] = portHost & 0xff;
+
+ uint8_t ipHost[16];
+
+ std::string out;
+
+ for (size_t i = 0; i < 16; ++i) {
+ ipHost[i] = addrV6.sin6_addr.s6_addr[15 - i];
+
+ if (!out.empty()) {
+ out += ":";
+ }
+ out += StringPrintf("%02x", ipHost[i]);
+
+ ipHost[i] ^= response.data()[4 + i];
+ }
+
+ // LOG(INFO) << "IP6 = " << out;
+
+ for (size_t i = 0; i < 16; ++i) {
+ attr[4 + i] = ipHost[15 - i];
+ }
+
+ response.addAttribute(
+ 0x0020 /* XOR-MAPPED-ADDRESS */, attr, sizeof(attr));
+ }
+
+ response.addMessageIntegrityAttribute(answerPassword);
+ response.addFingerprint();
+
+ // response.dump(answerPassword);
+
+ queueDatagram(addr, response.data(), response.size());
+
+ if (!mSession->isActive()) {
+ mSession->setRemoteAddress(addr);
+
+ mSession->setIsActive();
+
+ mSession->schedulePing(
+ mRunLoop,
+ makeSafeCallback(
+ this, &RTPSocketHandler::pingRemote, mSession),
+ std::chrono::seconds(0));
+ }
+
+ } else {
+ // msg.dump();
+
+ if (msg.type() == 0x0101 && !mDTLS) {
+ mDTLS = std::make_shared<DTLS>(
+ shared_from_this(),
+ DTLS::Mode::ACCEPT,
+ mSession->localCertificate(),
+ mSession->localKey(),
+ mSession->remoteFingerprint(),
+ (mTrackMask != TRACK_DATA) /* useSRTP */);
+
+ mDTLS->connect(mSession->remoteAddress());
+ }
+ }
+}
+
+bool RTPSocketHandler::matchesSession(const STUNMessage &msg) const {
+ const void *attrData;
+ size_t attrSize;
+ if (!msg.findAttribute(0x0006 /* USERNAME */, &attrData, &attrSize)) {
+ return false;
+ }
+
+ std::string uFragPair(static_cast<const char *>(attrData), attrSize);
+ auto colonPos = uFragPair.find(':');
+
+ if (colonPos == std::string::npos) {
+ return false;
+ }
+
+ std::string localUFrag(uFragPair, 0, colonPos);
+ std::string remoteUFrag(uFragPair, colonPos + 1);
+
+ if (mSession->localUFrag() != localUFrag
+ || mSession->remoteUFrag() != remoteUFrag) {
+
+ LOG(WARNING)
+ << "Unable to find session localUFrag='"
+ << localUFrag
+ << "', remoteUFrag='"
+ << remoteUFrag
+ << "'";
+
+ return false;
+ }
+
+ return true;
+}
+
+void RTPSocketHandler::pingRemote(std::shared_ptr<RTPSession> session) {
+ std::vector<uint8_t> transactionID { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
+
+ STUNMessage msg(
+ 0x0001 /* Binding Request */,
+ transactionID.data());
+
+ std::string uFragPair =
+ session->remoteUFrag() + ":" + session->localUFrag();
+
+ msg.addAttribute(
+ 0x0006 /* USERNAME */,
+ uFragPair.c_str(),
+ uFragPair.size());
+
+ uint64_t tieBreaker = 0xdeadbeefcafeb0b0; // XXX
+ msg.addAttribute(
+ 0x802a /* ICE-CONTROLLING */,
+ &tieBreaker,
+ sizeof(tieBreaker));
+
+ uint32_t priority = 0xdeadbeef;
+ msg.addAttribute(
+ 0x0024 /* PRIORITY */, &priority, sizeof(priority));
+
+ // We're the controlling agent and including the "USE-CANDIDATE" attribute
+ // below nominates this candidate.
+ msg.addAttribute(0x0025 /* USE_CANDIDATE */);
+
+ msg.addMessageIntegrityAttribute(session->remotePassword());
+ msg.addFingerprint();
+
+ queueDatagram(session->remoteAddress(), msg.data(), msg.size());
+
+ session->schedulePing(
+ mRunLoop,
+ makeSafeCallback(this, &RTPSocketHandler::pingRemote, session),
+ std::chrono::seconds(1));
+}
+
+RTPSocketHandler::Datagram::Datagram(
+ const sockaddr_storage &addr, const void *data, size_t size)
+ : mData(size),
+ mAddr(addr) {
+ memcpy(mData.data(), data, size);
+}
+
+const void *RTPSocketHandler::Datagram::data() const {
+ return mData.data();
+}
+
+size_t RTPSocketHandler::Datagram::size() const {
+ return mData.size();
+}
+
+const sockaddr_storage &RTPSocketHandler::Datagram::remoteAddress() const {
+ return mAddr;
+}
+
+void RTPSocketHandler::queueDatagram(
+ const sockaddr_storage &addr, const void *data, size_t size) {
+ if (mTransportType == TransportType::TCP) {
+ std::vector copy(
+ static_cast<const uint8_t *>(data),
+ static_cast<const uint8_t *>(data) + size);
+
+ mRunLoop->post(
+ makeSafeCallback<RTPSocketHandler>(
+ this,
+ [copy](RTPSocketHandler *me) {
+ // addr is ignored and assumed to be the connected endpoint's.
+ me->queueTCPOutputPacket(copy.data(), copy.size());
+ }));
+
+ return;
+ }
+
+ auto datagram = std::make_shared<Datagram>(addr, data, size);
+
+ CHECK_LE(size, RTPSocketHandler::kMaxUDPPayloadSize);
+
+ mRunLoop->post(
+ makeSafeCallback<RTPSocketHandler>(
+ this,
+ [datagram](RTPSocketHandler *me) {
+ me->mOutQueue.push_back(datagram);
+
+ if (!me->mSendPending) {
+ me->scheduleDrainOutQueue();
+ }
+ }));
+}
+
+void RTPSocketHandler::queueTCPOutputPacket(const uint8_t *data, size_t size) {
+ uint8_t framing[2];
+ framing[0] = size >> 8;
+ framing[1] = size & 0xff;
+
+ std::copy(framing, framing + sizeof(framing), std::back_inserter(mOutBuffer));
+ std::copy(data, data + size, std::back_inserter(mOutBuffer));
+
+ if (!mSendPending) {
+ mSendPending = true;
+
+ mSocket->postSend(
+ makeSafeCallback(this, &RTPSocketHandler::sendTCPOutputData));
+ }
+}
+
+void RTPSocketHandler::sendTCPOutputData() {
+ mSendPending = false;
+
+ const size_t size = mOutBuffer.size();
+ size_t offset = 0;
+
+ bool disconnected = false;
+
+ while (offset < size) {
+ auto n = mSocket->send(mOutBuffer.data() + offset, size - offset);
+
+ if (n < 0) {
+ if (errno == EINTR) {
+ continue;
+ }
+
+ LOG(FATAL) << "Should not be here.";
+ } else if (n == 0) {
+ offset = size;
+ disconnected = true;
+ break;
+ }
+
+ offset += static_cast<size_t>(n);
+ }
+
+ mOutBuffer.erase(mOutBuffer.begin(), mOutBuffer.begin() + offset);
+
+ if (!mOutBuffer.empty() && !disconnected) {
+ mSendPending = true;
+
+ mSocket->postSend(
+ makeSafeCallback(this, &RTPSocketHandler::sendTCPOutputData));
+ }
+}
+
+void RTPSocketHandler::scheduleDrainOutQueue() {
+ CHECK(!mSendPending);
+
+ mSendPending = true;
+ mSocket->postSend(
+ makeSafeCallback(
+ this, &RTPSocketHandler::drainOutQueue));
+}
+
+void RTPSocketHandler::drainOutQueue() {
+ mSendPending = false;
+
+ CHECK(!mOutQueue.empty());
+
+ do {
+ auto datagram = mOutQueue.front();
+
+ ssize_t n;
+ do {
+ const sockaddr_storage &remoteAddr = datagram->remoteAddress();
+
+ n = mSocket->sendto(
+ datagram->data(),
+ datagram->size(),
+ reinterpret_cast<const sockaddr *>(&remoteAddr),
+ getSockAddrLen(remoteAddr));
+ } while (n < 0 && errno == EINTR);
+
+ if (n < 0) {
+ if (errno == EAGAIN || errno == EWOULDBLOCK) {
+ break;
+ }
+
+ CHECK(!"Should not be here");
+ }
+
+ mOutQueue.pop_front();
+
+ } while (!mOutQueue.empty());
+
+ if (!mOutQueue.empty()) {
+ scheduleDrainOutQueue();
+ }
+}
+
+void RTPSocketHandler::onDTLSReceive(const uint8_t *data, size_t size) {
+ if (mDTLS) {
+ mDTLS->inject(data, size);
+ }
+}
+
+void RTPSocketHandler::notifyDTLSConnected() {
+ LOG(INFO) << "TDLS says that it's now connected.";
+
+ mDTLSConnected = true;
+
+ if (mTrackMask & TRACK_VIDEO) {
+ mServerState->getVideoPacketizer()->addSender(mRTPSender);
+ }
+
+ if (mTrackMask & TRACK_AUDIO) {
+ mServerState->getAudioPacketizer()->addSender(mRTPSender);
+ }
+
+ if (mTrackMask & TRACK_DATA) {
+ mSCTPHandler = std::make_shared<SCTPHandler>(mRunLoop, mDTLS);
+ mSCTPHandler->run();
+ }
+
+ mRTPSender->run();
+}
+
+int RTPSocketHandler::onSRTPReceive(uint8_t *data, size_t size) {
+ if (size < 2) {
+ return -EINVAL;
+ }
+
+ auto version = data[0] >> 6;
+ if (version != 2) {
+ return -EINVAL;
+ }
+
+ auto outSize = mDTLS->unprotect(data, size, false /* isRTP */);
+
+ auto err = mRTPSender->injectRTCP(data, outSize);
+ if (err) {
+ LOG(WARNING) << "RTPSender::injectRTCP returned " << err;
+ }
+
+ return err;
+}
+
+void RTPSocketHandler::queueRTCPDatagram(const void *data, size_t size) {
+ if (!mDTLSConnected) {
+ return;
+ }
+
+ std::vector<uint8_t> copy(size + SRTP_MAX_TRAILER_LEN);
+ memcpy(copy.data(), data, size);
+
+ auto outSize = mDTLS->protect(copy.data(), size, false /* isRTP */);
+ CHECK_LE(outSize, copy.size());
+
+ queueDatagram(mSession->remoteAddress(), copy.data(), outSize);
+}
+
+void RTPSocketHandler::queueRTPDatagram(const void *data, size_t size) {
+ if (!mDTLSConnected) {
+ return;
+ }
+
+ std::vector<uint8_t> copy(size + SRTP_MAX_TRAILER_LEN);
+ memcpy(copy.data(), data, size);
+
+ auto outSize = mDTLS->protect(copy.data(), size, true /* isRTP */);
+ CHECK_LE(outSize, copy.size());
+
+ queueDatagram(mSession->remoteAddress(), copy.data(), outSize);
+}
diff --git a/host/frontend/gcastv2/webrtc/SCTPHandler.cpp b/host/frontend/gcastv2/webrtc/SCTPHandler.cpp
new file mode 100644
index 000000000..c89f9252d
--- /dev/null
+++ b/host/frontend/gcastv2/webrtc/SCTPHandler.cpp
@@ -0,0 +1,529 @@
+/*
+ * 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.
+ */
+
+#include <webrtc/SCTPHandler.h>
+
+#include "Utils.h"
+
+#include <https/SafeCallbackable.h>
+#include <https/Support.h>
+
+#include <android-base/logging.h>
+
+SCTPHandler::SCTPHandler(
+ std::shared_ptr<RunLoop> runLoop,
+ std::shared_ptr<DTLS> dtls)
+ : mRunLoop(runLoop),
+ mDTLS(dtls),
+ mInitiateTag(0),
+ mSendingTSN(0),
+ mSentGreeting(false) {
+}
+
+void SCTPHandler::run() {
+}
+
+int SCTPHandler::inject(uint8_t *data, size_t size) {
+ LOG(INFO)
+ << "Received SCTP datagram of size " << size << ":";
+
+ hexdump(data, size);
+
+ if (size < 12) {
+ // Need at least the common header.
+ return -EINVAL;
+ }
+
+ auto srcPort = U16_AT(&data[0]);
+ auto dstPort = U16_AT(&data[2]);
+
+ if (dstPort != 5000) {
+ return -EINVAL;
+ }
+
+ auto checkSumIn = U32_AT(&data[8]);
+ SET_U32(&data[8], 0x00000000);
+ auto checkSum = crc32c(data, size);
+
+ if (checkSumIn != checkSum) {
+ LOG(WARNING)
+ << "SCTPHandler::inject checksum invalid."
+ << " (in: " << StringPrintf("0x%08x", checkSumIn) << ", "
+ << "computed: " << StringPrintf("0x%08x", checkSum) << ")";
+
+ return -EINVAL;
+ }
+
+ bool firstChunk = true;
+ size_t offset = 12;
+ while (offset < size) {
+ if (offset + 4 > size) {
+ return -EINVAL;
+ }
+
+ size_t chunkLength = U16_AT(&data[offset + 2]);
+
+ if (offset + chunkLength > size) {
+ return -EINVAL;
+ }
+
+ size_t paddedChunkLength = chunkLength;
+ size_t pad = chunkLength % 4;
+ if (pad) {
+ pad = 4 - pad;
+ paddedChunkLength += pad;
+ }
+
+ bool lastChunk =
+ (offset + chunkLength == size)
+ || (offset + paddedChunkLength == size);
+
+ auto err = processChunk(
+ srcPort,
+ &data[offset],
+ chunkLength,
+ firstChunk,
+ lastChunk);
+
+ if (err) {
+ return err;
+ }
+
+ firstChunk = false;
+
+ offset += chunkLength;
+
+ if (offset == size) {
+ break;
+ }
+
+ if (offset + pad > size) {
+ return -EINVAL;
+ }
+
+ offset += pad;
+ }
+
+ return 0;
+}
+
+int SCTPHandler::processChunk(
+ uint16_t srcPort,
+ const uint8_t *data,
+ size_t size,
+ bool firstChunk,
+ bool lastChunk) {
+ static constexpr uint8_t DATA = 0;
+ static constexpr uint8_t INIT = 1;
+ static constexpr uint8_t INIT_ACK = 2;
+ static constexpr uint8_t SACK = 3;
+ static constexpr uint8_t HEARTBEAT = 4;
+ static constexpr uint8_t HEARTBEAT_ACK = 5;
+ static constexpr uint8_t COOKIE_ECHO = 10;
+ static constexpr uint8_t COOKIE_ACK = 11;
+ static constexpr uint8_t SHUTDOWN_COMPLETE = 14;
+
+ static constexpr uint64_t kCookie = 0xDABBAD00DEADBAADull;
+
+ auto chunkType = data[0];
+ if ((!firstChunk || !lastChunk)
+ && (chunkType == INIT
+ || chunkType == INIT_ACK
+ || chunkType == SHUTDOWN_COMPLETE)) {
+ // These chunks must be by themselves, no other chunks must be part
+ // of the same datagram.
+
+ return -EINVAL;
+ }
+
+ switch (chunkType) {
+ case INIT:
+ {
+ if (size < 20) {
+ return -EINVAL;
+ }
+
+ mInitiateTag = U32_AT(&data[4]);
+
+ uint8_t out[12 + 24 + sizeof(kCookie)];
+ SET_U16(&out[0], 5000);
+ SET_U16(&out[2], srcPort);
+ SET_U32(&out[4], mInitiateTag);
+ SET_U32(&out[8], 0x00000000); // Checksum: to be filled in below.
+
+ size_t offset = 12;
+ out[offset++] = INIT_ACK;
+ out[offset++] = 0x00;
+
+ SET_U16(&out[offset], sizeof(out) - 12);
+ offset += 2;
+
+ SET_U32(&out[offset], 0xb0b0cafe); // initiate tag
+ offset += 4;
+
+ SET_U32(&out[offset], 0x00020000); // a_rwnd
+ offset += 4;
+
+ SET_U16(&out[offset], 1); // Number of Outbound Streams
+ offset += 2;
+
+ SET_U16(&out[offset], 1); // Number of Inbound Streams
+ offset += 2;
+
+ mSendingTSN = 0x12345678;
+
+ SET_U32(&out[offset], mSendingTSN); // Initial TSN
+ offset += 4;
+
+ SET_U16(&out[offset], 0x0007); // STATE_COOKIE
+ offset += 2;
+
+ static_assert((sizeof(kCookie) % 4) == 0);
+
+ SET_U16(&out[offset], 4 + sizeof(kCookie));
+ offset += 2;
+
+ memcpy(&out[offset], &kCookie, sizeof(kCookie));
+ offset += sizeof(kCookie);
+
+ CHECK_EQ(offset, sizeof(out));
+
+ SET_U32(&out[8], crc32c(out, sizeof(out)));
+
+ LOG(INFO) << "Sending SCTP INIT_ACK:";
+ hexdump(out, sizeof(out));
+
+ mDTLS->writeApplicationData(out, sizeof(out));
+ break;
+ }
+
+ case COOKIE_ECHO:
+ {
+ if (size != (4 + sizeof(kCookie))) {
+ return -EINVAL;
+ }
+
+ if (memcmp(&data[4], &kCookie, sizeof(kCookie))) {
+ return -EINVAL;
+ }
+
+ uint8_t out[12 + 4];
+ SET_U16(&out[0], 5000);
+ SET_U16(&out[2], srcPort);
+ SET_U32(&out[4], mInitiateTag);
+ SET_U32(&out[8], 0x00000000); // Checksum: to be filled in below.
+
+ size_t offset = 12;
+ out[offset++] = COOKIE_ACK;
+ out[offset++] = 0x00;
+ SET_U16(&out[offset], sizeof(out) - 12);
+ offset += 2;
+
+ CHECK_EQ(offset, sizeof(out));
+
+ SET_U32(&out[8], crc32c(out, sizeof(out)));
+
+ LOG(INFO) << "Sending SCTP COOKIE_ACK:";
+ hexdump(out, sizeof(out));
+
+ mDTLS->writeApplicationData(out, sizeof(out));
+ break;
+ }
+
+ case DATA:
+ {
+ if (size < 17) {
+ // Minimal size (16 bytes header + 1 byte payload), empty
+ // payloads are prohibited.
+ return -EINVAL;
+ }
+
+ auto TSN = U32_AT(&data[4]);
+
+ uint8_t out[12 + 16];
+ SET_U16(&out[0], 5000);
+ SET_U16(&out[2], srcPort);
+ SET_U32(&out[4], mInitiateTag);
+ SET_U32(&out[8], 0x00000000); // Checksum: to be filled in below.
+
+ size_t offset = 12;
+ out[offset++] = SACK;
+ out[offset++] = 0x00;
+
+ SET_U16(&out[offset], sizeof(out) - 12);
+ offset += 2;
+
+ SET_U32(&out[offset], TSN);
+ offset += 4;
+
+ SET_U32(&out[offset], 0x00020000); // a_rwnd
+ offset += 4;
+
+ SET_U16(&out[offset], 0); // Number of Gap Ack Blocks
+ offset += 2;
+
+ SET_U16(&out[offset], 0); // Number of Duplicate TSNs
+ offset += 2;
+
+ CHECK_EQ(offset, sizeof(out));
+
+ SET_U32(&out[8], crc32c(out, sizeof(out)));
+
+ LOG(INFO) << "Sending SCTP SACK:";
+ hexdump(out, sizeof(out));
+
+ mDTLS->writeApplicationData(out, sizeof(out));
+
+ if (!mSentGreeting) {
+ mRunLoop->postWithDelay(
+ std::chrono::seconds(1),
+ makeSafeCallback(
+ this,
+ &SCTPHandler::onSendGreeting,
+ srcPort,
+ (size_t)0 /* index */));
+
+ mSentGreeting = true;
+ }
+ break;
+ }
+
+ case HEARTBEAT:
+ {
+ if (size < 8) {
+ return -EINVAL;
+ }
+
+ if (U16_AT(&data[4]) != 1 /* Heartbeat Info Type */
+ || size != (U16_AT(&data[6]) + 4)) {
+ return -EINVAL;
+ }
+
+ size_t pad = size % 4;
+ if (pad) {
+ pad = 4 - pad;
+ }
+
+ std::vector<uint8_t> outVec(12 + size + pad);
+
+ uint8_t *out = outVec.data();
+ SET_U16(&out[0], 5000);
+ SET_U16(&out[2], srcPort);
+ SET_U32(&out[4], mInitiateTag);
+ SET_U32(&out[8], 0x00000000); // Checksum: to be filled in below.
+
+ size_t offset = 12;
+ out[offset++] = HEARTBEAT_ACK;
+ out[offset++] = 0x00;
+
+ SET_U16(&out[offset], outVec.size() - 12 - pad);
+ offset += 2;
+
+ memcpy(&out[offset], &data[4], size - 4);
+ offset += size - 4;
+
+ memset(&out[offset], 0x00, pad);
+ offset += pad;
+
+ CHECK_EQ(offset, outVec.size());
+
+ SET_U32(&out[8], crc32c(out, outVec.size()));
+
+ LOG(INFO) << "Sending SCTP HEARTBEAT_ACK:";
+ hexdump(out, outVec.size());
+
+ mDTLS->writeApplicationData(out, outVec.size());
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+void SCTPHandler::onSendGreeting(uint16_t srcPort, size_t index) {
+ static constexpr uint8_t DATA = 0;
+ // static constexpr uint8_t PPID_WEBRTC_CONTROL = 0x32;
+ static constexpr uint8_t PPID_WEBRTC_STRING = 0x33;
+
+ std::string message;
+ if (index == 0) {
+ message = "Howdy! How's y'all doin?";
+ } else {
+ message = "But wait... There's more!";
+ }
+
+ size_t pad = message.size() % 4;
+ if (pad) {
+ pad = 4 - pad;
+ }
+
+ std::vector<uint8_t> outVec(12 + 16 + message.size() + pad);
+
+ uint8_t *out = outVec.data();
+ SET_U16(&out[0], 5000);
+ SET_U16(&out[2], srcPort);
+ SET_U32(&out[4], mInitiateTag);
+ SET_U32(&out[8], 0x00000000); // Checksum: to be filled in below.
+
+ size_t offset = 12;
+ out[offset++] = DATA;
+ out[offset++] = 0x03; // both Beginning and End of user message.
+
+ SET_U16(&out[offset], outVec.size() - 12 - pad);
+ offset += 2;
+
+ SET_U32(&out[offset], mSendingTSN); // TSN
+ offset += 4;
+
+ ++mSendingTSN;
+
+ SET_U16(&out[offset], 0); // Stream Identifier
+ offset += 2;
+
+ SET_U16(&out[offset], index); // Stream Sequence Number
+ offset += 2;
+
+ SET_U32(&out[offset], PPID_WEBRTC_STRING); // Payload Protocol Identifier
+ offset += 4;
+
+ // https://tools.ietf.org/html/draft-ietf-rtcweb-data-protocol-08#section-5.1
+ // https://tools.ietf.org/html/draft-ietf-rtcweb-data-channel-11#section-6.5
+
+ // DATA(payload protocol=0x32 (50, WebRTC Control), sequence 0)
+ // 03 00 00 00 00 00 00 00 ........
+ // 00 0c 00 00 64 61 74 61 ....data
+ // 2d 63 68 61 6e 6e 65 6c -channel
+
+ // DATA(payload protocol=0x33 (51, WebRTC String), sequence 1)
+ // "Hello, world!"
+
+ memcpy(&out[offset], message.data(), message.size());
+ offset += message.size();
+
+ memset(&out[offset], 0x00, pad);
+ offset += pad;
+
+ CHECK_EQ(offset, outVec.size());
+
+ SET_U32(&out[8], crc32c(out, outVec.size()));
+
+ LOG(INFO) << "Sending SCTP DATA:";
+ hexdump(out, outVec.size());
+
+ mDTLS->writeApplicationData(out, outVec.size());
+
+ if (index == 0) {
+ mRunLoop->postWithDelay(
+ std::chrono::seconds(3),
+ makeSafeCallback(
+ this,
+ &SCTPHandler::onSendGreeting,
+ srcPort,
+ (size_t)1 /* index */));
+ }
+}
+
+static const uint32_t crc_c[256] = {
+ 0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4,
+ 0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB,
+ 0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B,
+ 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24,
+ 0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B,
+ 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384,
+ 0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54,
+ 0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B,
+ 0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A,
+ 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35,
+ 0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5,
+ 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA,
+ 0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45,
+ 0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A,
+ 0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A,
+ 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595,
+ 0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48,
+ 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957,
+ 0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687,
+ 0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198,
+ 0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927,
+ 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38,
+ 0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8,
+ 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7,
+ 0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096,
+ 0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789,
+ 0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859,
+ 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46,
+ 0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9,
+ 0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6,
+ 0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36,
+ 0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829,
+ 0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C,
+ 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93,
+ 0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043,
+ 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C,
+ 0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3,
+ 0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC,
+ 0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C,
+ 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033,
+ 0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652,
+ 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D,
+ 0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D,
+ 0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982,
+ 0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D,
+ 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622,
+ 0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2,
+ 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED,
+ 0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530,
+ 0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F,
+ 0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF,
+ 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0,
+ 0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F,
+ 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540,
+ 0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90,
+ 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F,
+ 0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE,
+ 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1,
+ 0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321,
+ 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E,
+ 0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81,
+ 0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E,
+ 0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E,
+ 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351,
+};
+
+#define CRC32C_POLY 0x1EDC6F41
+#define CRC32C(c,d) (c=(c>>8)^crc_c[(c^(d))&0xFF])
+
+static uint32_t swap32(uint32_t x) {
+ return (x >> 24)
+ | (((x >> 16) & 0xff) << 8)
+ | (((x >> 8) & 0xff) << 16)
+ | ((x & 0xff) << 24);
+}
+
+// static
+uint32_t SCTPHandler::crc32c(const uint8_t *data, size_t size) {
+ uint32_t crc32 = ~(uint32_t)0;
+
+ for (size_t i = 0; i < size; ++i) {
+ CRC32C(crc32, data[i]);
+ }
+
+ return ~swap32(crc32);
+}
+
diff --git a/host/frontend/gcastv2/webrtc/SDP.cpp b/host/frontend/gcastv2/webrtc/SDP.cpp
new file mode 100644
index 000000000..daedc7940
--- /dev/null
+++ b/host/frontend/gcastv2/webrtc/SDP.cpp
@@ -0,0 +1,179 @@
+/*
+ * 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.
+ */
+
+#include <webrtc/SDP.h>
+
+#include "Utils.h"
+
+#include <android-base/logging.h>
+
+#include <cerrno>
+#include <iostream>
+
+SDP::SDP()
+ : mInitCheck(-ENODEV),
+ mNewSectionEditorActive(false) {
+}
+
+int SDP::initCheck() const {
+ return mInitCheck;
+}
+
+size_t SDP::countSections() const {
+ CHECK(!mInitCheck);
+ return mLineIndexBySection.size();
+}
+
+void SDP::clear() {
+ mInitCheck = -ENODEV;
+ mLines.clear();
+ mLineIndexBySection.clear();
+}
+
+int SDP::setTo(const std::string &data) {
+ clear();
+
+ mLines = SplitString(data, "\r\n");
+
+ LOG(VERBOSE) << "SDP contained " << mLines.size() << " lines.";
+
+ mLineIndexBySection.push_back(0);
+
+ mInitCheck = 0;
+
+ for (size_t i = 0; i < mLines.size(); ++i) {
+ const auto &line = mLines[i];
+
+ LOG(VERBOSE) << "Line #" << i << ": " << line;
+
+ if (i == 0 && line != "v=0") {
+ mInitCheck = -EINVAL;
+ break;
+ }
+
+ if (line.size() < 2 || line[1] != '=') {
+ mInitCheck = -EINVAL;
+ break;
+ }
+
+ if (line[0] == 'm') {
+ mLineIndexBySection.push_back(i);
+ }
+ }
+
+ return mInitCheck;
+}
+
+void SDP::getSectionRange(
+ size_t section, size_t *lineStartIndex, size_t *lineStopIndex) const {
+ CHECK(!mInitCheck);
+ CHECK_LT(section, mLineIndexBySection.size());
+
+ if (lineStartIndex) {
+ *lineStartIndex = mLineIndexBySection[section];
+ }
+
+ if (lineStopIndex) {
+ if (section + 1 < mLineIndexBySection.size()) {
+ *lineStopIndex = mLineIndexBySection[section + 1];
+ } else {
+ *lineStopIndex = mLines.size();
+ }
+ }
+}
+
+std::vector<std::string>::const_iterator SDP::section_begin(
+ size_t section) const {
+
+ size_t startLineIndex;
+ getSectionRange(section, &startLineIndex, nullptr /* lineStopIndex */);
+
+ return mLines.cbegin() + startLineIndex;
+}
+
+std::vector<std::string>::const_iterator SDP::section_end(
+ size_t section) const {
+
+ size_t stopLineIndex;
+ getSectionRange(section, nullptr /* lineStartIndex */, &stopLineIndex);
+
+ return mLines.cbegin() + stopLineIndex;
+}
+
+SDP::SectionEditor SDP::createSection() {
+ CHECK(!mNewSectionEditorActive);
+ mNewSectionEditorActive = true;
+
+ if (mInitCheck) {
+ clear();
+ mInitCheck = 0;
+ }
+
+ return SectionEditor(this, countSections());
+}
+
+SDP::SectionEditor SDP::appendToSection(size_t section) {
+ CHECK_LT(section, countSections());
+ return SectionEditor(this, section);
+}
+
+void SDP::commitSectionEdit(
+ size_t section, const std::vector<std::string> &lines) {
+
+ CHECK_LE(section, countSections());
+
+ if (section == countSections()) {
+ // This was an edit creating a new section.
+ mLineIndexBySection.push_back(mLines.size());
+
+ mLines.insert(mLines.end(), lines.begin(), lines.end());
+
+ mNewSectionEditorActive = false;
+ return;
+ }
+
+ mLines.insert(section_end(section), lines.begin(), lines.end());
+
+ if (section + 1 < countSections()) {
+ mLineIndexBySection[section + 1] += lines.size();
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+SDP::SectionEditor::SectionEditor(SDP *sdp, size_t section)
+ : mSDP(sdp),
+ mSection(section) {
+}
+
+SDP::SectionEditor::~SectionEditor() {
+ commit();
+}
+
+SDP::SectionEditor &SDP::SectionEditor::operator<<(std::string_view s) {
+ mBuffer.append(s);
+
+ return *this;
+}
+
+void SDP::SectionEditor::commit() {
+ if (mSDP) {
+ auto lines = SplitString(mBuffer, "\r\n");
+
+ mSDP->commitSectionEdit(mSection, lines);
+ mSDP = nullptr;
+ }
+}
diff --git a/host/frontend/gcastv2/webrtc/STUNClient.cpp b/host/frontend/gcastv2/webrtc/STUNClient.cpp
new file mode 100644
index 000000000..d29c7152a
--- /dev/null
+++ b/host/frontend/gcastv2/webrtc/STUNClient.cpp
@@ -0,0 +1,175 @@
+/*
+ * 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.
+ */
+
+#include "Utils.h"
+
+#include <webrtc/STUNClient.h>
+#include <webrtc/STUNMessage.h>
+
+#include <https/SafeCallbackable.h>
+#include <https/Support.h>
+
+#include <android-base/logging.h>
+
+STUNClient::STUNClient(
+ std::shared_ptr<RunLoop> runLoop,
+ const sockaddr_in &addr,
+ Callback cb)
+ : mRunLoop(runLoop),
+ mRemoteAddr(addr),
+ mCallback(cb),
+ mTimeoutToken(0),
+ mNumRetriesLeft(kMaxNumRetries) {
+
+ int sock = socket(PF_INET, SOCK_DGRAM, 0);
+ makeFdNonblocking(sock);
+
+ sockaddr_in addrV4;
+ memset(addrV4.sin_zero, 0, sizeof(addrV4.sin_zero));
+ addrV4.sin_family = AF_INET;
+ addrV4.sin_port = 0;
+ addrV4.sin_addr.s_addr = INADDR_ANY;
+
+ int res = bind(
+ sock,
+ reinterpret_cast<const sockaddr *>(&addrV4),
+ sizeof(addrV4));
+
+ CHECK(!res);
+
+ sockaddr_in tmp;
+ socklen_t tmpLen = sizeof(tmp);
+
+ res = getsockname(sock, reinterpret_cast<sockaddr *>(&tmp), &tmpLen);
+ CHECK(!res);
+
+ LOG(VERBOSE) << "local port: " << ntohs(tmp.sin_port);
+
+ mSocket = std::make_shared<PlainSocket>(mRunLoop, sock);
+}
+
+void STUNClient::run() {
+ LOG(VERBOSE) << "STUNClient::run()";
+
+ scheduleRequest();
+}
+
+void STUNClient::onSendRequest() {
+ LOG(VERBOSE) << "STUNClient::onSendRequest";
+
+ std::vector<uint8_t> transactionID { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
+
+ STUNMessage msg(0x0001 /* Binding Request */, transactionID.data());
+ msg.addFingerprint();
+
+ ssize_t n;
+
+ do {
+ n = sendto(
+ mSocket->fd(),
+ msg.data(),
+ msg.size(),
+ 0 /* flags */,
+ reinterpret_cast<const sockaddr *>(&mRemoteAddr),
+ sizeof(mRemoteAddr));
+
+ } while (n < 0 && errno == EINTR);
+
+ CHECK_GT(n, 0);
+
+ LOG(VERBOSE) << "Sent BIND request, awaiting response";
+
+ mSocket->postRecv(
+ makeSafeCallback(this, &STUNClient::onReceiveResponse));
+}
+
+void STUNClient::onReceiveResponse() {
+ LOG(VERBOSE) << "Received STUN response";
+
+ std::vector<uint8_t> buffer(kMaxUDPPayloadSize);
+
+ uint8_t *data = buffer.data();
+
+ sockaddr_storage addr;
+ socklen_t addrLen = sizeof(addr);
+
+ auto n = mSocket->recvfrom(
+ data, buffer.size(), reinterpret_cast<sockaddr *>(&addr), &addrLen);
+
+ CHECK_GT(n, 0);
+
+ STUNMessage msg(data, n);
+ CHECK(msg.isValid());
+
+ // msg.dump();
+
+ if (msg.type() == 0x0101 /* Binding Response */) {
+ const uint8_t *data;
+ size_t size;
+ if (msg.findAttribute(
+ 0x0020 /* XOR-MAPPED-ADDRESS */,
+ reinterpret_cast<const void **>(&data),
+ &size)) {
+
+ CHECK_EQ(size, 8u);
+ CHECK_EQ(data[1], 0x01u); // We only deal with IPv4 for now.
+
+ static constexpr uint32_t kMagicCookie = 0x2112a442;
+
+ uint16_t port = U16_AT(&data[2]) ^ (kMagicCookie >> 16);
+ uint32_t ip = U32_AT(&data[4]) ^ kMagicCookie;
+
+ LOG(VERBOSE) << "translated port: " << port;
+
+ mCallback(
+ 0 /* result */,
+ StringPrintf(
+ "%u.%u.%u.%u",
+ ip >> 24,
+ (ip >> 16) & 0xff,
+ (ip >> 8) & 0xff,
+ ip & 0xff));
+
+ mRunLoop->cancelToken(mTimeoutToken);
+ mTimeoutToken = 0;
+ }
+ }
+}
+
+void STUNClient::scheduleRequest() {
+ CHECK_EQ(mTimeoutToken, 0);
+
+ mSocket->postSend(
+ makeSafeCallback(this, &STUNClient::onSendRequest));
+
+ mTimeoutToken = mRunLoop->postWithDelay(
+ kTimeoutDelay,
+ makeSafeCallback(this, &STUNClient::onTimeout));
+
+}
+
+void STUNClient::onTimeout() {
+ mTimeoutToken = 0;
+
+ if (mNumRetriesLeft == 0) {
+ mCallback(-ETIMEDOUT, "");
+ return;
+ }
+
+ --mNumRetriesLeft;
+ scheduleRequest();
+}
+
diff --git a/host/frontend/gcastv2/webrtc/STUNMessage.cpp b/host/frontend/gcastv2/webrtc/STUNMessage.cpp
new file mode 100644
index 000000000..92c3b3ea7
--- /dev/null
+++ b/host/frontend/gcastv2/webrtc/STUNMessage.cpp
@@ -0,0 +1,371 @@
+/*
+ * 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.
+ */
+
+#include <webrtc/STUNMessage.h>
+
+#include "Utils.h"
+
+#include <https/Support.h>
+#include <android-base/logging.h>
+
+#include <arpa/inet.h>
+
+#include <cstring>
+#include <iostream>
+#include <unordered_map>
+
+#include <openssl/hmac.h>
+
+static constexpr uint8_t kMagicCookie[4] = { 0x21, 0x12, 0xa4, 0x42 };
+
+STUNMessage::STUNMessage(uint16_t type, const uint8_t transactionID[12])
+ : mIsValid(true),
+ mData(20),
+ mAddedMessageIntegrity(false) {
+ CHECK((type >> 14) == 0);
+
+ mData[0] = (type >> 8) & 0x3f;
+ mData[1] = type & 0xff;
+ mData[2] = 0;
+ mData[3] = 0;
+
+ memcpy(&mData[4], kMagicCookie, sizeof(kMagicCookie));
+
+ memcpy(&mData[8], transactionID, 12);
+}
+
+STUNMessage::STUNMessage(const void *data, size_t size)
+ : mIsValid(false),
+ mData(size) {
+ memcpy(mData.data(), data, size);
+
+ validate();
+}
+
+bool STUNMessage::isValid() const {
+ return mIsValid;
+}
+
+static uint16_t UINT16_AT(const void *_data) {
+ const uint8_t *data = static_cast<const uint8_t *>(_data);
+ return static_cast<uint16_t>(data[0]) << 8 | data[1];
+}
+
+uint16_t STUNMessage::type() const {
+ return UINT16_AT(mData.data());
+}
+
+void STUNMessage::addAttribute(uint16_t type, const void *data, size_t size) {
+ CHECK(!mAddedMessageIntegrity || type == 0x8028);
+
+ size_t alignedSize = (size + 3) & ~3;
+ CHECK_LE(alignedSize, 0xffffu);
+
+ size_t offset = mData.size();
+ mData.resize(mData.size() + 4 + alignedSize);
+
+ uint8_t *ptr = mData.data() + offset;
+ ptr[0] = type >> 8;
+ ptr[1] = type & 0xff;
+ ptr[2] = (size >> 8) & 0xff;
+ ptr[3] = size & 0xff;
+
+ if (size > 0) {
+ memcpy(&ptr[4], data, size);
+ }
+}
+
+void STUNMessage::addMessageIntegrityAttribute(std::string_view password) {
+ size_t offset = mData.size();
+
+ uint16_t truncatedLength = offset + 4;
+ mData[2] = (truncatedLength >> 8);
+ mData[3] = (truncatedLength & 0xff);
+
+ uint8_t digest[20];
+ unsigned int digestLen = sizeof(digest);
+
+ HMAC(EVP_sha1(),
+ password.data(),
+ password.size(),
+ mData.data(),
+ offset,
+ digest,
+ &digestLen);
+
+ CHECK_EQ(digestLen, 20);
+ addAttribute(0x0008 /* MESSAGE-INTEGRITY */, digest, digestLen);
+
+ mAddedMessageIntegrity = true;
+}
+
+const uint8_t *STUNMessage::data() {
+ size_t size = mData.size() - 20;
+ CHECK_LE(size, 0xffffu);
+
+ mData[2] = (size >> 8) & 0xff;
+ mData[3] = size & 0xff;
+
+ return mData.data();
+}
+
+size_t STUNMessage::size() const {
+ return mData.size();
+}
+
+void STUNMessage::validate() {
+ if (mData.size() < 20) {
+ return;
+ }
+
+ const uint8_t *data = mData.data();
+
+ auto messageLength = UINT16_AT(data + 2);
+ if (messageLength != mData.size() - 20) {
+ return;
+ }
+
+ if (memcmp(kMagicCookie, &data[4], sizeof(kMagicCookie))) {
+ return;
+ }
+
+ bool sawMessageIntegrity = false;
+
+ data += 20;
+ size_t offset = 0;
+ while (offset + 4 <= messageLength) {
+ auto attrType = UINT16_AT(&data[offset]);
+
+ if (sawMessageIntegrity && attrType != 0x8028 /* FINGERPRINT */) {
+ return;
+ }
+
+ sawMessageIntegrity = (attrType == 0x0008 /* MESSAGE-INTEGRITY */);
+
+ auto attrLength = UINT16_AT(&data[offset + 2]);
+
+ if (offset + 4 + attrLength > messageLength) {
+ return;
+ }
+
+ offset += 4 + attrLength;
+ if (offset & 3) {
+ offset += 4 - (offset & 3);
+ }
+ }
+
+ if (offset != messageLength) {
+ return;
+ }
+
+ mAddedMessageIntegrity = sawMessageIntegrity;
+ mIsValid = true;
+}
+
+void STUNMessage::dump(std::optional<std::string_view> password) const {
+ CHECK(mIsValid);
+
+ const uint8_t *data = mData.data();
+
+ auto messageType = UINT16_AT(data);
+ auto messageLength = mData.size() - 20;
+
+ if (messageType == 0x0001) {
+ std::cout << "Binding Request";
+ } else if (messageType == 0x0101) {
+ std::cout << "Binding Response";
+ } else {
+ std::cout
+ << "Unknown message type "
+ << StringPrintf("0x%04x", messageType);
+ }
+
+ std::cout << std::endl;
+
+ data += 20;
+ size_t offset = 0;
+ while (offset + 4 <= messageLength) {
+ auto attrType = UINT16_AT(&data[offset]);
+ auto attrLength = UINT16_AT(&data[offset + 2]);
+
+ static const std::unordered_map<uint16_t, std::string> kAttrName {
+ { 0x0001, "MAPPED-ADDRESS" },
+ { 0x0006, "USERNAME" },
+ { 0x0008, "MESSAGE-INTEGRITY" },
+ { 0x0009, "ERROR-CODE" },
+ { 0x000A, "UNKNOWN-ATTRIBUTES" },
+ { 0x0014, "REALM" },
+ { 0x0015, "NONCE" },
+ { 0x0020, "XOR-MAPPED-ADDRESS" },
+ { 0x0024, "PRIORITY" }, // RFC8445
+ { 0x0025, "USE-CANDIDATE" }, // RFC8445
+ { 0x8022, "SOFTWARE" },
+ { 0x8023, "ALTERNATE-SERVER" },
+ { 0x8028, "FINGERPRINT" },
+ { 0x8029, "ICE-CONTROLLED" }, // RFC8445
+ { 0x802a, "ICE-CONTROLLING" }, // RFC8445
+ };
+
+ auto it = kAttrName.find(attrType);
+ if (it == kAttrName.end()) {
+ if (attrType <= 0x7fff) {
+ std::cout
+ << "Unknown mandatory attribute type "
+ << StringPrintf("0x%04x", attrType)
+ << ":"
+ << std::endl;
+ } else {
+ std::cout
+ << "Unknown optional attribute type "
+ << StringPrintf("0x%04x", attrType)
+ << ":"
+ << std::endl;
+ }
+ } else {
+ std::cout << "attribute '" << it->second << "':" << std::endl;
+ }
+
+ hexdump(&data[offset + 4], attrLength);
+
+ if (attrType == 8 /* MESSAGE_INTEGRITY */) {
+ if (attrLength != 20) {
+ LOG(WARNING)
+ << "Message integrity attribute length mismatch."
+ << " Expected 20, found "
+ << attrLength;
+ } else if (password) {
+ auto success = verifyMessageIntegrity(offset + 20, *password);
+
+ if (!success) {
+ LOG(WARNING) << "Message integrity check FAILED!";
+ }
+ }
+ } else if (attrType == 0x8028 /* FINGERPRINT */) {
+ if (attrLength != 4) {
+ LOG(WARNING)
+ << "Fingerprint attribute length mismatch."
+ << " Expected 4, found "
+ << attrLength;
+ } else {
+ auto success = verifyFingerprint(offset + 20);
+
+ if (!success) {
+ LOG(WARNING) << "Fingerprint check FAILED!";
+ }
+ }
+ }
+
+ offset += 4 + attrLength;
+ if (offset & 3) {
+ offset += 4 - (offset & 3);
+ }
+ }
+}
+
+bool STUNMessage::verifyMessageIntegrity(
+ size_t offset, std::string_view password) const {
+ // Password used as "short-term" credentials (RFC 5389).
+ // Technically the password would have to be SASLprep'ed...
+
+ std::vector<uint8_t> copy(offset);
+ memcpy(copy.data(), mData.data(), offset);
+
+ uint16_t truncatedLength = offset + 4;
+ copy[2] = (truncatedLength >> 8);
+ copy[3] = (truncatedLength & 0xff);
+
+ uint8_t digest[20];
+ unsigned int digestLen = sizeof(digest);
+
+ HMAC(EVP_sha1(),
+ password.data(),
+ password.size(),
+ copy.data(),
+ copy.size(),
+ digest,
+ &digestLen);
+
+ CHECK_EQ(digestLen, 20);
+
+ bool success = !memcmp(
+ digest,
+ &mData[offset + 4],
+ digestLen);
+
+ return success;
+}
+
+void STUNMessage::addFingerprint() {
+ size_t offset = mData.size();
+
+ // Pretend that we've added the FINGERPRINT attribute already.
+ uint16_t truncatedLength = offset + 4 + 4 - 20;
+ mData[2] = (truncatedLength >> 8);
+ mData[3] = (truncatedLength & 0xff);
+
+ uint32_t crc32 = htonl(computeCrc32(mData.data(), offset) ^ 0x5354554e);
+
+ addAttribute(0x8028 /* FINGERPRINT */, &crc32, sizeof(crc32));
+}
+
+bool STUNMessage::verifyFingerprint(size_t offset) const {
+ std::vector<uint8_t> copy(offset);
+ memcpy(copy.data(), mData.data(), offset);
+
+ copy[2] = ((mData.size() - 20) >> 8) & 0xff;
+ copy[3] = (mData.size() - 20) & 0xff;
+
+ uint32_t crc32 = htonl(computeCrc32(copy.data(), offset) ^ 0x5354554e);
+
+ // hexdump(&crc32, 4);
+
+ return !memcmp(&crc32, &mData[offset + 4], 4);
+}
+
+bool STUNMessage::findAttribute(
+ uint16_t type, const void **attrData, size_t *attrSize) const {
+ CHECK(mIsValid);
+
+ const uint8_t *data = mData.data();
+
+ auto messageLength = mData.size() - 20;
+
+ data += 20;
+ size_t offset = 0;
+ while (offset + 4 <= messageLength) {
+ auto attrType = UINT16_AT(&data[offset]);
+ auto attrLength = UINT16_AT(&data[offset + 2]);
+
+ if (attrType == type) {
+ *attrData = &data[offset + 4];
+ *attrSize = attrLength;
+
+ return true;
+ }
+
+ offset += 4 + attrLength;
+
+ if (offset & 3) {
+ offset += 4 - (offset & 3);
+ }
+ }
+
+ *attrData = nullptr;
+ *attrSize = 0;
+
+ return false;
+}
+
diff --git a/host/frontend/gcastv2/webrtc/ServerState.cpp b/host/frontend/gcastv2/webrtc/ServerState.cpp
new file mode 100644
index 000000000..1e8b1ca40
--- /dev/null
+++ b/host/frontend/gcastv2/webrtc/ServerState.cpp
@@ -0,0 +1,158 @@
+/*
+ * 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.
+ */
+
+#include <webrtc/ServerState.h>
+
+#include <webrtc/OpusPacketizer.h>
+#include <webrtc/VP8Packetizer.h>
+
+#include <source/AudioSource.h>
+#include <source/TouchSink.h>
+#include <source/FrameBufferSource.h>
+
+#include "host/libs/config/cuttlefish_config.h"
+
+#include <gflags/gflags.h>
+
+DECLARE_int32(keyboard_fd);
+DECLARE_int32(touch_fd);
+DECLARE_int32(frame_server_fd);
+DECLARE_bool(write_virtio_input);
+
+ServerState::ServerState(
+ std::shared_ptr<RunLoop> runLoop, VideoFormat videoFormat)
+ :
+ mRunLoop(runLoop),
+ mVideoFormat(videoFormat) {
+
+ auto config = vsoc::CuttlefishConfig::Get();
+
+ android::FrameBufferSource::Format fbSourceFormat;
+ switch (videoFormat) {
+ case VideoFormat::VP8:
+ fbSourceFormat = android::FrameBufferSource::Format::VP8;
+ break;
+ default:
+ LOG(FATAL) << "Should not be here.";
+ }
+
+ mFrameBufferSource =
+ std::make_shared<android::FrameBufferSource>(fbSourceFormat);
+
+ int32_t screenParams[4];
+ screenParams[0] = config->x_res();
+ screenParams[1] = config->y_res();
+ screenParams[2] = config->dpi();
+ screenParams[3] = config->refresh_rate_hz();
+
+ static_cast<android::FrameBufferSource *>(
+ mFrameBufferSource.get())->setScreenParams(screenParams);
+
+ mScreenConnector = std::shared_ptr<cvd::ScreenConnector>(
+ cvd::ScreenConnector::Get(FLAGS_frame_server_fd));
+ mScreenConnectorMonitor.reset(
+ new std::thread([this]() { MonitorScreenConnector(); }));
+
+ mAudioSource = std::make_shared<android::AudioSource>(
+ android::AudioSource::Format::OPUS);
+
+ CHECK_GE(FLAGS_touch_fd, 0);
+
+ auto touchSink = std::make_shared<android::TouchSink>(
+ mRunLoop, FLAGS_touch_fd, FLAGS_write_virtio_input);
+
+ touchSink->start();
+
+ mTouchSink = touchSink;
+
+ auto keyboardSink = std::make_shared<android::KeyboardSink>(
+ mRunLoop, FLAGS_keyboard_fd, FLAGS_write_virtio_input);
+
+ keyboardSink->start();
+
+ mKeyboardSink = keyboardSink;
+}
+
+void ServerState::MonitorScreenConnector() {
+ std::uint32_t last_frame = 0;
+ while (true) {
+ mScreenConnector->OnFrameAfter(last_frame, [this, &last_frame](
+ std::uint32_t frame_num,
+ std::uint8_t *data) {
+ mRunLoop->postAndAwait([this, data]() {
+ static_cast<android::FrameBufferSource *>(mFrameBufferSource.get())
+ ->injectFrame(data, cvd::ScreenConnector::ScreenSizeInBytes());
+ });
+ last_frame = frame_num;
+ });
+ }
+}
+
+std::shared_ptr<Packetizer> ServerState::getVideoPacketizer() {
+ auto packetizer = mVideoPacketizer.lock();
+ if (!packetizer) {
+ switch (mVideoFormat) {
+ case VideoFormat::VP8:
+ {
+ packetizer = std::make_shared<VP8Packetizer>(
+ mRunLoop, mFrameBufferSource);
+ break;
+ }
+
+ default:
+ LOG(FATAL) << "Should not be here.";
+ }
+
+ packetizer->run();
+
+ mVideoPacketizer = packetizer;
+ }
+
+ return packetizer;
+}
+
+std::shared_ptr<Packetizer> ServerState::getAudioPacketizer() {
+ auto packetizer = mAudioPacketizer.lock();
+ if (!packetizer) {
+ packetizer = std::make_shared<OpusPacketizer>(mRunLoop, mAudioSource);
+ packetizer->run();
+
+ mAudioPacketizer = packetizer;
+ }
+
+ return packetizer;
+}
+
+size_t ServerState::acquireHandlerId() {
+ size_t id = 0;
+ while (!mAllocatedHandlerIds.insert(id).second) {
+ ++id;
+ }
+
+ return id;
+}
+
+void ServerState::releaseHandlerId(size_t id) {
+ CHECK_EQ(mAllocatedHandlerIds.erase(id), 1);
+}
+
+std::shared_ptr<android::TouchSink> ServerState::getTouchSink() {
+ return mTouchSink;
+}
+
+std::shared_ptr<android::KeyboardSink> ServerState::getKeyboardSink() {
+ return mKeyboardSink;
+}
diff --git a/host/frontend/webrtc_operator/utils.cpp b/host/frontend/gcastv2/webrtc/Utils.cpp
index b4e23e317..56c615813 100644
--- a/host/frontend/webrtc_operator/utils.cpp
+++ b/host/frontend/gcastv2/webrtc/Utils.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "host/frontend/webrtc_operator/utils.h"
+#include "Utils.h"
std::vector<std::string> SplitString(const std::string &s, char c) {
return SplitString(s, std::string(1 /* count */, c));
diff --git a/host/frontend/webrtc_operator/utils.h b/host/frontend/gcastv2/webrtc/Utils.h
index 7dcc1db2c..7dcc1db2c 100644
--- a/host/frontend/webrtc_operator/utils.h
+++ b/host/frontend/gcastv2/webrtc/Utils.h
diff --git a/host/frontend/gcastv2/webrtc/VP8Packetizer.cpp b/host/frontend/gcastv2/webrtc/VP8Packetizer.cpp
new file mode 100644
index 000000000..69039b376
--- /dev/null
+++ b/host/frontend/gcastv2/webrtc/VP8Packetizer.cpp
@@ -0,0 +1,93 @@
+/*
+ * 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.
+ */
+
+#include <webrtc/VP8Packetizer.h>
+
+#include "Utils.h"
+
+#include <webrtc/RTPSocketHandler.h>
+
+#include <https/SafeCallbackable.h>
+#include <https/Support.h>
+
+using namespace android;
+
+VP8Packetizer::VP8Packetizer(
+ std::shared_ptr<RunLoop> runLoop,
+ std::shared_ptr<StreamingSource> frameBufferSource)
+ : Packetizer(runLoop, frameBufferSource) {
+}
+
+void VP8Packetizer::packetize(const std::shared_ptr<SBuffer> &accessUnit, int64_t timeUs) {
+ static constexpr uint8_t PT = 96;
+ static constexpr uint32_t SSRC = 0xdeadbeef;
+
+ // XXX Retransmission packets add 2 bytes (for the original seqNum), should
+ // probably reserve that amount in the original packets so we don't exceed
+ // the MTU on retransmission.
+ static const size_t kMaxSRTPPayloadSize =
+ RTPSocketHandler::kMaxUDPPayloadSize - SRTP_MAX_TRAILER_LEN;
+
+ const uint8_t *src = accessUnit->data();
+ size_t srcSize = accessUnit->size();
+
+ uint32_t rtpTime = ((timeUs - mediaStartTime()) * 9) / 100;
+
+ LOG(VERBOSE) << "got accessUnit of size " << srcSize;
+
+ size_t srcOffset = 0;
+ while (srcOffset < srcSize) {
+ size_t packetSize = 12; // generic RTP header
+
+ packetSize += 1; // VP8 Payload Descriptor
+
+ auto copy = std::min(srcSize - srcOffset, kMaxSRTPPayloadSize - packetSize);
+
+ packetSize += copy;
+
+ std::vector<uint8_t> packet(packetSize);
+ uint8_t *dst = packet.data();
+
+ dst[0] = 0x80;
+
+ dst[1] = PT;
+ if (srcOffset + copy == srcSize) {
+ dst[1] |= 0x80; // (M)ark
+ }
+
+ SET_U16(&dst[2], 0); // seqNum
+ SET_U32(&dst[4], rtpTime);
+ SET_U32(&dst[8], SSRC);
+
+ size_t dstOffset = 12;
+
+ // VP8 Payload Descriptor
+ dst[dstOffset++] = (srcOffset == 0) ? 0x10 : 0x00; // S
+
+ memcpy(&dst[dstOffset], &src[srcOffset], copy);
+ dstOffset += copy;
+
+ CHECK_EQ(dstOffset, packetSize);
+
+ srcOffset += copy;
+
+ queueRTPDatagram(&packet);
+ }
+}
+
+uint32_t VP8Packetizer::rtpNow() const {
+ return (timeSinceStart() * 90) / 1000;
+}
diff --git a/host/frontend/gcastv2/webrtc/assets/index.html b/host/frontend/gcastv2/webrtc/assets/index.html
new file mode 100644
index 000000000..5a249f6d2
--- /dev/null
+++ b/host/frontend/gcastv2/webrtc/assets/index.html
@@ -0,0 +1,30 @@
+<html>
+ <head>
+ <title>My Virtual Device Playground</title>
+
+ <link rel="stylesheet" type="text/css" href="style.css" >
+ </head>
+
+ <body>
+ <button id="receiveButton">Receive Media</button>
+ <button id="keyboardCaptureBtn">Capture Keyboard</button>
+ <button id="resizeButton">Resize Viewport</button>
+ <hr>
+ <section class="noscroll">
+ <div class="one" >
+ <video id="deviceScreen" autoplay width="540" height="1080" style="touch-action:none" ></video>
+ </div>
+
+ <div class="two" >
+ <textarea id="logcat" rows="55" cols="120" readonly >
+ </textarea>
+ </div>
+ </section>
+
+ <script src="js/receive.js"></script>
+ <script src="js/logcat.js"></script>
+ <script src="js/viewpane.js"></script>
+ </body>
+
+</html>
+
diff --git a/host/frontend/gcastv2/webrtc/assets/js/logcat.js b/host/frontend/gcastv2/webrtc/assets/js/logcat.js
new file mode 100644
index 000000000..aae94bc91
--- /dev/null
+++ b/host/frontend/gcastv2/webrtc/assets/js/logcat.js
@@ -0,0 +1,163 @@
+let adb_ws;
+let logcat = document.getElementById('logcat');
+
+let utf8Encoder = new TextEncoder();
+let utf8Decoder = new TextDecoder();
+
+const A_CNXN = 0x4e584e43;
+const A_OPEN = 0x4e45504f;
+const A_WRTE = 0x45545257;
+const A_OKAY = 0x59414b4f;
+
+const kLocalChannelId = 666;
+
+function setU32LE(array, offset, x) {
+ array[offset] = x & 0xff;
+ array[offset + 1] = (x >> 8) & 0xff;
+ array[offset + 2] = (x >> 16) & 0xff;
+ array[offset + 3] = x >> 24;
+}
+
+function getU32LE(array, offset) {
+ let x = array[offset]
+ | (array[offset + 1] << 8)
+ | (array[offset + 2] << 16)
+ | (array[offset + 3] << 24);
+
+ return x >>> 0; // convert signed to unsigned if necessary.
+}
+
+function computeChecksum(array) {
+ let sum = 0;
+ let i;
+ for (i = 0; i < array.length; ++i) {
+ sum = ((sum + array[i]) & 0xffffffff) >>> 0;
+ }
+
+ return sum;
+}
+
+function createAdbMessage(command, arg0, arg1, payload) {
+ let arrayBuffer = new ArrayBuffer(24 + payload.length);
+ let array = new Uint8Array(arrayBuffer);
+ setU32LE(array, 0, command);
+ setU32LE(array, 4, arg0);
+ setU32LE(array, 8, arg1);
+ setU32LE(array, 12, payload.length);
+ setU32LE(array, 16, computeChecksum(payload));
+ setU32LE(array, 20, command ^ 0xffffffff);
+ array.set(payload, 24);
+
+ return arrayBuffer;
+}
+
+function adbOpenConnection() {
+ let systemIdentity = utf8Encoder.encode("Cray_II:1234:whatever");
+
+ let arrayBuffer = createAdbMessage(
+ A_CNXN, 0x1000000, 256 * 1024, systemIdentity);
+
+ adb_ws.send(arrayBuffer);
+}
+
+function adbOpenChannel() {
+ let destination = utf8Encoder.encode("shell:logcat");
+
+ let arrayBuffer = createAdbMessage(A_OPEN, kLocalChannelId, 0, destination);
+ adb_ws.send(arrayBuffer);
+}
+
+function adbSendOkay(remoteId) {
+ let payload = new Uint8Array(0);
+
+ let arrayBuffer = createAdbMessage(
+ A_OKAY, kLocalChannelId, remoteId, payload);
+
+ adb_ws.send(arrayBuffer);
+}
+
+function adbOnMessage(ev) {
+ // console.log("adb_ws: onmessage (" + ev.data.byteLength + " bytes)");
+
+ let arrayBuffer = ev.data;
+ let array = new Uint8Array(arrayBuffer);
+
+ if (array.length < 24) {
+ console.log("adb message too short.");
+ return;
+ }
+
+ let command = getU32LE(array, 0);
+ let magic = getU32LE(array, 20);
+
+ if (command != ((magic ^ 0xffffffff) >>> 0)) {
+ console.log("command = " + command + ", magic = " + magic);
+ console.log("adb message command vs magic failed.");
+ return;
+ }
+
+ let payloadLength = getU32LE(array, 12);
+
+ if (array.length != 24 + payloadLength) {
+ console.log("adb message length mismatch.");
+ return;
+ }
+
+ let payloadChecksum = getU32LE(array, 16);
+ let checksum = computeChecksum(array.slice(24));
+
+ if (payloadChecksum != checksum) {
+ console.log("adb message checksum mismatch.");
+ return;
+ }
+
+ switch (command) {
+ case A_CNXN:
+ {
+ console.log("connected.");
+
+ adbOpenChannel();
+ break;
+ }
+
+ case A_OKAY:
+ {
+ let remoteId = getU32LE(array, 4);
+ console.log("channel created w/ remoteId " + remoteId);
+ break;
+ }
+
+ case A_WRTE:
+ {
+ let payloadText = utf8Decoder.decode(array.slice(24));
+
+ logcat.value += payloadText;
+
+ // Scroll to bottom
+ logcat.scrollTop = logcat.scrollHeight;
+
+ let remoteId = getU32LE(array, 4);
+ adbSendOkay(remoteId);
+ break;
+ }
+ }
+}
+
+function init_logcat() {
+ const wsProtocol = (location.protocol == "http:") ? "ws:" : "wss:";
+
+ adb_ws = new WebSocket(
+ wsProtocol + "//" + location.host + "/control_adb");
+
+ adb_ws.binaryType = "arraybuffer";
+
+ adb_ws.onopen = function() {
+ console.log("adb_ws: onopen");
+
+ adbOpenConnection();
+
+ logcat.style.display = "initial";
+ };
+ adb_ws.onmessage = adbOnMessage;
+}
+
diff --git a/host/frontend/gcastv2/webrtc/assets/js/receive.js b/host/frontend/gcastv2/webrtc/assets/js/receive.js
new file mode 100644
index 000000000..d47566cb8
--- /dev/null
+++ b/host/frontend/gcastv2/webrtc/assets/js/receive.js
@@ -0,0 +1,453 @@
+'use strict';
+
+const receiveButton = document.getElementById('receiveButton');
+receiveButton.addEventListener('click', onReceive);
+const keyboardCaptureButton = document.getElementById('keyboardCaptureBtn');
+keyboardCaptureButton.addEventListener('click', onKeyboardCaptureClick);
+
+const deviceScreen = document.getElementById('deviceScreen');
+
+deviceScreen.addEventListener("click", onInitialClick);
+
+function onInitialClick(e) {
+ // This stupid thing makes sure that we disable controls after the first click...
+ // Why not just disable controls altogether you ask? Because then audio won't play
+ // because these days user-interaction is required to enable audio playback...
+ console.log("onInitialClick");
+
+ deviceScreen.controls = false;
+ deviceScreen.removeEventListener("click", onInitialClick);
+}
+
+let pc1;
+let pc2;
+
+let dataChannel;
+
+let ws;
+
+let offerResolve;
+let iceCandidateResolve;
+
+let videoStream;
+
+let mouseIsDown = false;
+
+const is_chrome = navigator.userAgent.indexOf("Chrome") !== -1;
+
+function handleDataChannelStatusChange(event) {
+ console.log('handleDataChannelStatusChange state=' + dataChannel.readyState);
+
+ if (dataChannel.readyState == "open") {
+ dataChannel.send("Hello, world!");
+ }
+}
+
+function handleDataChannelMessage(event) {
+ console.log('handleDataChannelMessage data="' + event.data + '"');
+}
+
+function onKeyboardCaptureClick(e) {
+ const selectedClass = 'selected';
+ if (keyboardCaptureButton.classList.contains(selectedClass)) {
+ stopKeyboardTracking();
+ keyboardCaptureButton.classList.remove(selectedClass);
+ } else {
+ startKeyboardTracking();
+ keyboardCaptureButton.classList.add(selectedClass);
+ }
+}
+
+async function onReceive() {
+ console.log('onReceive');
+ receiveButton.disabled = true;
+
+ init_logcat();
+
+ const wsProtocol = (location.protocol == "http:") ? "ws:" : "wss:";
+
+ ws = new WebSocket(wsProtocol + "//" + location.host + "/control");
+ // temporarily disable audio to free ports in the server since it's only
+ // producing silence anyways.
+ var search = location.search + "&disable_audio=1";
+ search = '?' + search.substr(1);
+
+ ws.onopen = function() {
+ console.log("onopen");
+ ws.send('{\r\n'
+ + '"type": "greeting",\r\n'
+ + '"message": "Hello, world!",\r\n'
+ + '"path": "' + location.pathname + search + '"\r\n'
+ + '}');
+ };
+ ws.onmessage = function(e) {
+ console.log("onmessage " + e.data);
+
+ let data = JSON.parse(e.data);
+ if (data.type == "hello") {
+ kickoff();
+ } else if (data.type == "offer" && offerResolve) {
+ offerResolve(data.sdp);
+ offerResolve = undefined;
+ } else if (data.type == "ice-candidate" && iceCandidateResolve) {
+ iceCandidateResolve(data);
+
+ iceCandidateResolve = undefined;
+ }
+ };
+
+ pc2 = new RTCPeerConnection();
+ console.log('got pc2=' + pc2);
+
+ pc2.addEventListener(
+ 'icecandidate', e => onIceCandidate(pc2, e));
+
+ pc2.addEventListener(
+ 'iceconnectionstatechange', e => onIceStateChange(pc2, e));
+
+ pc2.addEventListener(
+ 'connectionstatechange', e => {
+ console.log("connection state = " + pc2.connectionState);
+ });
+
+ pc2.addEventListener('track', onGotRemoteStream);
+
+ dataChannel = pc2.createDataChannel("data-channel");
+ dataChannel.onopen = handleDataChannelStatusChange;
+ dataChannel.onclose = handleDataChannelStatusChange;
+ dataChannel.onmessage = handleDataChannelMessage;
+}
+
+async function kickoff() {
+ console.log('createOffer start');
+
+ try {
+ var offer = await getWsOffer();
+ await onCreateOfferSuccess(offer);
+ } catch (e) {
+ console.log('createOffer FAILED ');
+ }
+}
+
+async function onCreateOfferSuccess(desc) {
+ console.log(`Offer ${desc.sdp}`);
+
+ try {
+ pc2.setRemoteDescription(desc);
+ } catch (e) {
+ console.log('setRemoteDescription pc2 FAILED');
+ return;
+ }
+
+ console.log('setRemoteDescription pc2 successful.');
+
+ try {
+ setWsLocalDescription(desc);
+ } catch (e) {
+ console.log('setLocalDescription pc1 FAILED');
+ return;
+ }
+
+ console.log('setLocalDescription pc1 successful.');
+
+ try {
+ const answer = await pc2.createAnswer();
+
+ await onCreateAnswerSuccess(answer);
+ } catch (e) {
+ console.log('createAnswer FAILED');
+ }
+}
+
+function setWsRemoteDescription(desc) {
+ ws.send('{\r\n'
+ + '"type": "set-remote-desc",\r\n'
+ + '"sdp": "' + desc.sdp + '"\r\n'
+ + '}');
+}
+
+function setWsLocalDescription(desc) {
+ ws.send('{\r\n'
+ + '"type": "set-local-desc",\r\n'
+ + '"sdp": "' + desc.sdp + '"\r\n'
+ + '}');
+}
+
+async function getWsOffer() {
+ const offerPromise = new Promise(function(resolve, reject) {
+ offerResolve = resolve;
+ });
+
+ ws.send('{\r\n'
+ + '"type": "request-offer",\r\n'
+ + (is_chrome ? '"is_chrome": 1\r\n'
+ : '"is_chrome": 0\r\n')
+ + '}');
+
+ const sdp = await offerPromise;
+
+ return { type: "offer", sdp: sdp };
+}
+
+async function getWsIceCandidate(mid) {
+ console.log("getWsIceCandidate (mid=" + mid + ")");
+
+ const answerPromise = new Promise(function(resolve, reject) {
+ iceCandidateResolve = resolve;
+ });
+
+ ws.send('{\r\n'
+ + '"type": "get-ice-candidate",\r\n'
+ + '"mid": ' + mid + ',\r\n'
+ + '}');
+
+ const replyInfo = await answerPromise;
+
+ console.log("got replyInfo '" + replyInfo + "'");
+
+ if (replyInfo == undefined || replyInfo.candidate == undefined) {
+ return null;
+ }
+
+ const replyCandidate = replyInfo.candidate;
+ const mlineIndex = replyInfo.mlineIndex;
+
+ let result;
+ try {
+ result = new RTCIceCandidate(
+ {
+ sdpMid: mid,
+ sdpMLineIndex: mlineIndex,
+ candidate: replyCandidate
+ });
+ }
+ catch (e) {
+ console.log("new RTCIceCandidate FAILED. " + e);
+ return undefined;
+ }
+
+ console.log("got result " + result);
+
+ return result;
+}
+
+async function addRemoteIceCandidate(mid) {
+ const candidate = await getWsIceCandidate(mid);
+
+ if (!candidate) {
+ return false;
+ }
+
+ try {
+ await pc2.addIceCandidate(candidate);
+ } catch (e) {
+ console.log("addIceCandidate pc2 FAILED w/ " + e);
+ return false;
+ }
+
+ console.log("addIceCandidate pc2 successful. (mid="
+ + mid + ", mlineIndex=" + candidate.sdpMLineIndex + ")");
+
+ return true;
+}
+
+async function onCreateAnswerSuccess(desc) {
+ console.log(`Answer ${desc.sdp}`);
+
+ try {
+ await pc2.setLocalDescription(desc);
+ } catch (e) {
+ console.log('setLocalDescription pc2 FAILED ' + e);
+ return;
+ }
+
+ console.log('setLocalDescription pc2 successful.');
+
+ try {
+ setWsRemoteDescription(desc);
+ } catch (e) {
+ console.log('setRemoteDescription pc1 FAILED');
+ return;
+ }
+
+ console.log('setRemoteDescription pc1 successful.');
+
+ if (!await addRemoteIceCandidate(0)) {
+ return;
+ }
+ await addRemoteIceCandidate(1);
+ await addRemoteIceCandidate(2);
+}
+
+function getPcName(pc) {
+ return ((pc == pc2) ? "pc2" : "pc1");
+}
+
+async function onIceCandidate(pc, e) {
+ console.log(
+ getPcName(pc)
+ + ' onIceCandidate '
+ + (e.candidate ? ('"' + e.candidate.candidate + '"') : '(null)')
+ + " "
+ + (e.candidate ? ('sdmMid: ' + e.candidate.sdpMid) : '(null)')
+ + " "
+ + (e.candidate ? ('sdpMLineIndex: ' + e.candidate.sdpMLineIndex) : '(null)'));
+
+ if (!e.candidate) {
+ return;
+ }
+
+ let other_pc = (pc == pc2) ? pc1 : pc2;
+
+ if (other_pc) {
+ try {
+ await other_pc.addIceCandidate(e.candidate);
+ } catch (e) {
+ console.log('addIceCandidate FAILED ' + e);
+ return;
+ }
+
+ console.log('addIceCandidate successful.');
+ }
+}
+
+async function onIceStateChange(pc, e) {
+ console.log(
+ 'onIceStateChange ' + getPcName(pc) + " '" + pc.iceConnectionState + "'");
+
+ if (pc.iceConnectionState == "connected") {
+ deviceScreen.srcObject = videoStream;
+
+ startMouseTracking()
+ } else if (pc.iceConnectionState == "disconnected") {
+ stopMouseTracking()
+ }
+}
+
+async function onGotRemoteStream(e) {
+ console.log('onGotRemoteStream ' + e);
+
+ const track = e.track;
+
+ console.log('track = ' + track);
+ console.log('track.kind = ' + track.kind);
+ console.log('track.readyState = ' + track.readyState);
+ console.log('track.enabled = ' + track.enabled);
+
+ if (track.kind == "video") {
+ videoStream = e.streams[0];
+ }
+}
+
+function startMouseTracking() {
+ if (window.PointerEvent) {
+ deviceScreen.addEventListener("pointerdown", onStartDrag);
+ deviceScreen.addEventListener("pointermove", onContinueDrag);
+ deviceScreen.addEventListener("pointerup", onEndDrag);
+ } else if (window.TouchEvent) {
+ deviceScreen.addEventListener("touchstart", onStartDrag);
+ deviceScreen.addEventListener("touchmove", onContinueDrag);
+ deviceScreen.addEventListener("touchend", onEndDrag);
+ } else if (window.MouseEvent) {
+ deviceScreen.addEventListener("mousedown", onStartDrag);
+ deviceScreen.addEventListener("mousemove", onContinueDrag);
+ deviceScreen.addEventListener("mouseup", onEndDrag);
+ }
+}
+
+function stopMouseTracking() {
+ if (window.PointerEvent) {
+ deviceScreen.removeEventListener("pointerdown", onStartDrag);
+ deviceScreen.removeEventListener("pointermove", onContinueDrag);
+ deviceScreen.removeEventListener("pointerup", onEndDrag);
+ } else if (window.TouchEvent) {
+ deviceScreen.removeEventListener("touchstart", onStartDrag);
+ deviceScreen.removeEventListener("touchmove", onContinueDrag);
+ deviceScreen.removeEventListener("touchend", onEndDrag);
+ } else if (window.MouseEvent) {
+ deviceScreen.removeEventListener("mousedown", onStartDrag);
+ deviceScreen.removeEventListener("mousemove", onContinueDrag);
+ deviceScreen.removeEventListener("mouseup", onEndDrag);
+ }
+}
+
+function startKeyboardTracking() {
+ document.addEventListener('keydown', onKeyEvent);
+ document.addEventListener('keyup', onKeyEvent);
+}
+
+function stopKeyboardTracking() {
+ document.removeEventListener('keydown', onKeyEvent);
+ document.removeEventListener('keyup', onKeyEvent);
+}
+
+function onStartDrag(e) {
+ e.preventDefault();
+
+ // console.log("mousedown at " + e.pageX + " / " + e.pageY);
+ mouseIsDown = true;
+
+ sendMouseUpdate(true, e);
+}
+
+function onEndDrag(e) {
+ e.preventDefault();
+
+ // console.log("mouseup at " + e.pageX + " / " + e.pageY);
+ mouseIsDown = false;
+
+ sendMouseUpdate(false, e);
+}
+
+function onContinueDrag(e) {
+ e.preventDefault();
+
+ // console.log("mousemove at " + e.pageX + " / " + e.pageY + ", down=" + mouseIsDown);
+ if (mouseIsDown) {
+ sendMouseUpdate(true, e);
+ }
+}
+
+function sendMouseUpdate(down, e) {
+ var x = e.offsetX;
+ var y = e.offsetY;
+
+ const videoWidth = deviceScreen.videoWidth;
+ const videoHeight = deviceScreen.videoHeight;
+ const elementWidth = deviceScreen.width;
+ const elementHeight = deviceScreen.height;
+
+ // vh*ew > eh*vw? then scale h instead of w
+ const scaleHeight = videoHeight * elementWidth > videoWidth * elementHeight;
+ var elementScaling = 0, videoScaling = 0;
+ if (scaleHeight) {
+ elementScaling = elementHeight;
+ videoScaling = videoHeight;
+ } else {
+ elementScaling = elementWidth;
+ videoScaling = videoWidth;
+ }
+
+ // Substract the offset produced by the difference in aspect ratio if any.
+ if (scaleHeight) {
+ x -= (elementWidth - elementScaling * videoWidth / videoScaling) / 2;
+ } else {
+ y -= (elementHeight - elementScaling * videoHeight / videoScaling) / 2;
+ }
+
+ // Convert to coordinates relative to the video
+ x = videoScaling * x / elementScaling;
+ y = videoScaling * y / elementScaling;
+
+ ws.send('{\r\n'
+ + '"type": "set-mouse-position",\r\n'
+ + '"down": ' + (down ? "1" : "0") + ',\r\n'
+ + '"x": ' + Math.trunc(x) + ',\r\n'
+ + '"y": ' + Math.trunc(y) + '\r\n'
+ + '}');
+}
+
+function onKeyEvent(e) {
+ e.preventDefault();
+ ws.send('{"type": "key-event","keycode": "'+e.code+'", "event_type": "'+e.type+'"}');
+} \ No newline at end of file
diff --git a/host/frontend/gcastv2/webrtc/assets/js/viewpane.js b/host/frontend/gcastv2/webrtc/assets/js/viewpane.js
new file mode 100644
index 000000000..62297a4e2
--- /dev/null
+++ b/host/frontend/gcastv2/webrtc/assets/js/viewpane.js
@@ -0,0 +1,29 @@
+// Resize button will control the execution of the resizeDeviceScreen function
+const resizeButton = document.getElementById('resizeButton');
+resizeButton.addEventListener('click', resizeDeviceScreen);
+
+// This will be used to set the max size for the video element.
+// Ex. 0.9 means that the video element will be at most 90% of the windowSize
+const maxVideoRatio = 0.9;
+
+function resizeDeviceScreen() {
+ // Capture/derive all the relevant dimensions
+ var viewportHeight = window.innerHeight;
+ var viewportWidth = window.innerWidth;
+ var maxHeight = viewportHeight * maxVideoRatio;
+ var maxWidth = viewportWidth * maxVideoRatio;
+ var videoWidth = deviceScreen.videoWidth;
+ var videoHeight = deviceScreen.videoHeight;
+
+ if (videoHeight <= maxHeight && videoWidth <= maxWidth) {
+ deviceScreen.setAttribute('height', videoHeight);
+ deviceScreen.setAttribute('width', videoWidth);
+ }
+ else {
+ deviceScreen.setAttribute('height', maxHeight);
+ deviceScreen.setAttribute('width', maxWidth);
+ }
+}
+
+// Listen for the 'play' event on the primary video element
+deviceScreen.addEventListener('play', resizeDeviceScreen); \ No newline at end of file
diff --git a/host/frontend/gcastv2/webrtc/assets/style.css b/host/frontend/gcastv2/webrtc/assets/style.css
new file mode 100644
index 000000000..a782b0ace
--- /dev/null
+++ b/host/frontend/gcastv2/webrtc/assets/style.css
@@ -0,0 +1,29 @@
+body {
+ background-color:black
+},
+html {
+# position: fixed;
+}
+
+.noscroll {
+ touch-action: none;
+}
+
+.one {
+ float: left;
+}
+
+.two {
+}
+
+#logcat {
+ display: none;
+ font-family: monospace;
+ padding: 10px;
+}
+
+button.selected {
+ background-color: #aaaaaa;
+ border-style: solid;
+ border-color: #aaaaaa;
+} \ No newline at end of file
diff --git a/host/frontend/gcastv2/webrtc/certs/create_certs.sh b/host/frontend/gcastv2/webrtc/certs/create_certs.sh
new file mode 100755
index 000000000..9f85e4047
--- /dev/null
+++ b/host/frontend/gcastv2/webrtc/certs/create_certs.sh
@@ -0,0 +1,32 @@
+#!/bin/sh
+
+# As explained in
+# https://gist.github.com/darrenjs/4645f115d10aa4b5cebf57483ec82eca
+
+openssl genrsa -des3 -passout pass:x -out server.pass.key 2048
+openssl rsa -passin pass:x -in server.pass.key -out server.key
+rm -f server.pass.key
+
+openssl req \
+ -subj "/C=US/ST=California/L=Santa Clara/O=Beyond Aggravated/CN=localhost" \
+ -new -key server.key -out server.csr
+
+openssl x509 -req -sha256 -days 365 -in server.csr -signkey server.key -out server.crt
+rm -f server.csr
+
+# Now create the list of certificates we trust as a client.
+
+rm trusted.pem
+
+# For now we just trust our own server.
+openssl x509 -in server.crt -text >> trusted.pem
+
+# Also add the system standard CA cert chain.
+# cat /opt/local/etc/openssl/cert.pem >> trusted.pem
+
+# Convert .pem to .der
+# openssl x509 -outform der -in trusted.pem -out trusted.der
+
+# Convert .crt and .key to .p12 for use by Security.framework
+# Enter password "foo"!
+openssl pkcs12 -export -inkey server.key -in server.crt -name localhost -out server.p12
diff --git a/host/frontend/gcastv2/webrtc/certs/server.crt b/host/frontend/gcastv2/webrtc/certs/server.crt
new file mode 100644
index 000000000..0b9aa369e
--- /dev/null
+++ b/host/frontend/gcastv2/webrtc/certs/server.crt
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDVzCCAj8CFBXBydw0e/7l31d9fzO7vrBxAw4yMA0GCSqGSIb3DQEBCwUAMGgx
+CzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRQwEgYDVQQHDAtTYW50
+YSBDbGFyYTEaMBgGA1UECgwRQmV5b25kIEFnZ3JhdmF0ZWQxEjAQBgNVBAMMCWxv
+Y2FsaG9zdDAeFw0yMDA1MDcyMTMzMDFaFw0yMTA1MDcyMTMzMDFaMGgxCzAJBgNV
+BAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRQwEgYDVQQHDAtTYW50YSBDbGFy
+YTEaMBgGA1UECgwRQmV5b25kIEFnZ3JhdmF0ZWQxEjAQBgNVBAMMCWxvY2FsaG9z
+dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPdz0Tom1NSujwxYFhG2
+MnqTTU5F9E5OwnO9svlXchXozJSoYpuFG43ZI/9exVmhQKZ4WwJUX74beYuZh611
+S1v9nAiAX+w3lpaiH/9gNH9PaR6kyOTveS9DtHqHlsHm9Ahuls/6mIlHVLsfGVcS
+DDIu5eYqBU0Xq1RYm3+9EUtEOLPQGfcaSUTnI6AkZ55TcJiKhq0CIoTpv/I+7mlw
+zsqPi2f2G7kI47bz1aiXeh34jelKR321fKl1/DW3F0CLSj0/u4gMgNIgPB/tHIKj
+GiNnvJTE7ZDSV34oUmqKhKkUixwjFHUFpMislpIJTsefzaKE4NLa57g5qgAnaofw
+m1UCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEASZx0QGNR5DT8vUgEBTMD1OKG3rFw
+zXLI1Lsn5nIMSGkL7aIlx7D8lbdvy0OS+Cg8jE256yiM7cZTF07rKwUeI2v/wDrX
+KP9qfMhonICrbQyKlZ6J4hLVV9wCkYQnMqwS+uSH1l1X+qr3ZCcamgTZ2hrhJFy4
+HEeoC4qdL0+uM2NhrjmPBvqMq9hYWe3nAREmRjSAxBMawjThldLqQCooyvtMskkn
+QAzPte/qvP4kWRpI+KQEv9Rc8iI9PNCF9+W4zl6pIyRDRVYWx3C1PSdniaTc/yDQ
+FL5UbuZ5ujUOdvMy1yAlcTiDVo+Ke7ybAK9FhEBxMPELyTFTY0GVKI46QA==
+-----END CERTIFICATE-----
diff --git a/host/frontend/gcastv2/webrtc/certs/server.key b/host/frontend/gcastv2/webrtc/certs/server.key
new file mode 100644
index 000000000..616a4ce7b
--- /dev/null
+++ b/host/frontend/gcastv2/webrtc/certs/server.key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpgIBAAKCAQEA93PROibU1K6PDFgWEbYyepNNTkX0Tk7Cc72y+VdyFejMlKhi
+m4Ubjdkj/17FWaFApnhbAlRfvht5i5mHrXVLW/2cCIBf7DeWlqIf/2A0f09pHqTI
+5O95L0O0eoeWweb0CG6Wz/qYiUdUux8ZVxIMMi7l5ioFTRerVFibf70RS0Q4s9AZ
+9xpJROcjoCRnnlNwmIqGrQIihOm/8j7uaXDOyo+LZ/YbuQjjtvPVqJd6HfiN6UpH
+fbV8qXX8NbcXQItKPT+7iAyA0iA8H+0cgqMaI2e8lMTtkNJXfihSaoqEqRSLHCMU
+dQWkyKyWkglOx5/NooTg0trnuDmqACdqh/CbVQIDAQABAoIBAQCnBGrxvwfjzTYL
+9OBgcAM+LHH/JMQynoIssJs+JEGCfDCpHcYAhiUE5syfLo4xYt9J/O4gcmZ04AJ3
+sNacwxBsNI6+Rjd4LkTbwu2p5ntIeobPAhX+P4wh1KbaFO4yTfnkPxBXrCKMdbLA
+4cqutCW7MWBGq5IMaK9hLLU30Jr9muiEIQ8tnexghJ4SiHnpju471KD9N77dRVZp
+TmUnIlJLqYMNoPj0nLwy6p1isq1KSg56j27OooL8piqOp2cy82GqjNeCfFcW74dJ
+lYmxILLseJiJvM2nlfFdSOvSOtaBkSG5oKsOO1K56u3cXhwSXChu5b8ewNjG5d+Y
+KY5obpV5AoGBAP/nJGxv7ljsg/pAqfWOwR5g6Iz9JxpgweubVt9fvnS+2Pj4akrJ
+1NZZCB/9zFbYf2Of2VMBdrNw7eS2+QDwj2TYPBjIH3WMPSByyyQaNna47b26Sxu2
+kCMhkoEMvwXEEQrLZ7I/sHgzYIEGg/9yLUJmzfdqpACU4bA1zkzKQ6tnAoGBAPeL
+2qn7ch3vlVLK46tm99Jkbw2SxoJajlZ4p2kpe/EexyqInfZJ58IKQNonqYNWMOwg
+aLeoyf+XsWgnuS4njMBPLmGTa/Pibs2b/0jrHP3mp2LVrRaL+wOUDM/gzmt7NeD+
+zZ8fD4Lsj8lXLfys5M5HrosF8c3TT8odFALjLwnjAoGBAKmH3qh8CsIchl6O4knM
+tgHDH6zvtS0TdsT4lzfKfSlomeNu5zP+vCL4vpo7EFlkehhs+JO1/4ZnRSLlWNcX
+h1e+rSmZwsWkD4bkpdGYEAbdAptTxJhqfNjZT+5wnEhcmRG2qU78RJONLdysjVv4
+ryUzaDYGDvpXp6CONMrIoMX3AoGBAJV/bbg4dauklD6i7yoFjmcOZo8A9EenHs0U
+Iq588jAlUUzbouIpsgBapt3ZFCOQOw1vaS55jjyAxRBM5SX9lqBRcYZWPNzWA+rC
+akMEUsb3tGEZAGZcdWSs1av5bVA14c0WtOGDJaAA87k5oDk3xRra6YtmNKkEE+zQ
+8NPple/XAoGBAJMpXdSP+Hgakv//HaQaBcenHk1f8v4b8t48NnXjou3ojfO8Wzgr
+odwlninHk1PaQD0XnFIISMVD9d2aSX8X1YQVHUQ9IQiA4hLy2lxZbP2K+LEaVKDm
+r7cjRKixJTIGm6vZK8pr1l5XD3657fQte4YLei5XA+i/UgFZyIA0KsKo
+-----END RSA PRIVATE KEY-----
diff --git a/host/frontend/gcastv2/webrtc/certs/server.p12 b/host/frontend/gcastv2/webrtc/certs/server.p12
new file mode 100644
index 000000000..87a94c583
--- /dev/null
+++ b/host/frontend/gcastv2/webrtc/certs/server.p12
Binary files differ
diff --git a/host/frontend/gcastv2/webrtc/certs/trusted.pem b/host/frontend/gcastv2/webrtc/certs/trusted.pem
new file mode 100644
index 000000000..8097b1639
--- /dev/null
+++ b/host/frontend/gcastv2/webrtc/certs/trusted.pem
@@ -0,0 +1,70 @@
+Certificate:
+ Data:
+ Version: 1 (0x0)
+ Serial Number:
+ 15:c1:c9:dc:34:7b:fe:e5:df:57:7d:7f:33:bb:be:b0:71:03:0e:32
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C = US, ST = California, L = Santa Clara, O = Beyond Aggravated, CN = localhost
+ Validity
+ Not Before: May 7 21:33:01 2020 GMT
+ Not After : May 7 21:33:01 2021 GMT
+ Subject: C = US, ST = California, L = Santa Clara, O = Beyond Aggravated, CN = localhost
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (2048 bit)
+ Modulus:
+ 00:f7:73:d1:3a:26:d4:d4:ae:8f:0c:58:16:11:b6:
+ 32:7a:93:4d:4e:45:f4:4e:4e:c2:73:bd:b2:f9:57:
+ 72:15:e8:cc:94:a8:62:9b:85:1b:8d:d9:23:ff:5e:
+ c5:59:a1:40:a6:78:5b:02:54:5f:be:1b:79:8b:99:
+ 87:ad:75:4b:5b:fd:9c:08:80:5f:ec:37:96:96:a2:
+ 1f:ff:60:34:7f:4f:69:1e:a4:c8:e4:ef:79:2f:43:
+ b4:7a:87:96:c1:e6:f4:08:6e:96:cf:fa:98:89:47:
+ 54:bb:1f:19:57:12:0c:32:2e:e5:e6:2a:05:4d:17:
+ ab:54:58:9b:7f:bd:11:4b:44:38:b3:d0:19:f7:1a:
+ 49:44:e7:23:a0:24:67:9e:53:70:98:8a:86:ad:02:
+ 22:84:e9:bf:f2:3e:ee:69:70:ce:ca:8f:8b:67:f6:
+ 1b:b9:08:e3:b6:f3:d5:a8:97:7a:1d:f8:8d:e9:4a:
+ 47:7d:b5:7c:a9:75:fc:35:b7:17:40:8b:4a:3d:3f:
+ bb:88:0c:80:d2:20:3c:1f:ed:1c:82:a3:1a:23:67:
+ bc:94:c4:ed:90:d2:57:7e:28:52:6a:8a:84:a9:14:
+ 8b:1c:23:14:75:05:a4:c8:ac:96:92:09:4e:c7:9f:
+ cd:a2:84:e0:d2:da:e7:b8:39:aa:00:27:6a:87:f0:
+ 9b:55
+ Exponent: 65537 (0x10001)
+ Signature Algorithm: sha256WithRSAEncryption
+ 49:9c:74:40:63:51:e4:34:fc:bd:48:04:05:33:03:d4:e2:86:
+ de:b1:70:cd:72:c8:d4:bb:27:e6:72:0c:48:69:0b:ed:a2:25:
+ c7:b0:fc:95:b7:6f:cb:43:92:f8:28:3c:8c:4d:b9:eb:28:8c:
+ ed:c6:53:17:4e:eb:2b:05:1e:23:6b:ff:c0:3a:d7:28:ff:6a:
+ 7c:c8:68:9c:80:ab:6d:0c:8a:95:9e:89:e2:12:d5:57:dc:02:
+ 91:84:27:32:ac:12:fa:e4:87:d6:5d:57:fa:aa:f7:64:27:1a:
+ 9a:04:d9:da:1a:e1:24:5c:b8:1c:47:a8:0b:8a:9d:2f:4f:ae:
+ 33:63:61:ae:39:8f:06:fa:8c:ab:d8:58:59:ed:e7:01:11:26:
+ 46:34:80:c4:13:1a:c2:34:e1:95:d2:ea:40:2a:28:ca:fb:4c:
+ b2:49:27:40:0c:cf:b5:ef:ea:bc:fe:24:59:1a:48:f8:a4:04:
+ bf:d4:5c:f2:22:3d:3c:d0:85:f7:e5:b8:ce:5e:a9:23:24:43:
+ 45:56:16:c7:70:b5:3d:27:67:89:a4:dc:ff:20:d0:14:be:54:
+ 6e:e6:79:ba:35:0e:76:f3:32:d7:20:25:71:38:83:56:8f:8a:
+ 7b:bc:9b:00:af:45:84:40:71:30:f1:0b:c9:31:53:63:41:95:
+ 28:8e:3a:40
+-----BEGIN CERTIFICATE-----
+MIIDVzCCAj8CFBXBydw0e/7l31d9fzO7vrBxAw4yMA0GCSqGSIb3DQEBCwUAMGgx
+CzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRQwEgYDVQQHDAtTYW50
+YSBDbGFyYTEaMBgGA1UECgwRQmV5b25kIEFnZ3JhdmF0ZWQxEjAQBgNVBAMMCWxv
+Y2FsaG9zdDAeFw0yMDA1MDcyMTMzMDFaFw0yMTA1MDcyMTMzMDFaMGgxCzAJBgNV
+BAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRQwEgYDVQQHDAtTYW50YSBDbGFy
+YTEaMBgGA1UECgwRQmV5b25kIEFnZ3JhdmF0ZWQxEjAQBgNVBAMMCWxvY2FsaG9z
+dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPdz0Tom1NSujwxYFhG2
+MnqTTU5F9E5OwnO9svlXchXozJSoYpuFG43ZI/9exVmhQKZ4WwJUX74beYuZh611
+S1v9nAiAX+w3lpaiH/9gNH9PaR6kyOTveS9DtHqHlsHm9Ahuls/6mIlHVLsfGVcS
+DDIu5eYqBU0Xq1RYm3+9EUtEOLPQGfcaSUTnI6AkZ55TcJiKhq0CIoTpv/I+7mlw
+zsqPi2f2G7kI47bz1aiXeh34jelKR321fKl1/DW3F0CLSj0/u4gMgNIgPB/tHIKj
+GiNnvJTE7ZDSV34oUmqKhKkUixwjFHUFpMislpIJTsefzaKE4NLa57g5qgAnaofw
+m1UCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEASZx0QGNR5DT8vUgEBTMD1OKG3rFw
+zXLI1Lsn5nIMSGkL7aIlx7D8lbdvy0OS+Cg8jE256yiM7cZTF07rKwUeI2v/wDrX
+KP9qfMhonICrbQyKlZ6J4hLVV9wCkYQnMqwS+uSH1l1X+qr3ZCcamgTZ2hrhJFy4
+HEeoC4qdL0+uM2NhrjmPBvqMq9hYWe3nAREmRjSAxBMawjThldLqQCooyvtMskkn
+QAzPte/qvP4kWRpI+KQEv9Rc8iI9PNCF9+W4zl6pIyRDRVYWx3C1PSdniaTc/yDQ
+FL5UbuZ5ujUOdvMy1yAlcTiDVo+Ke7ybAK9FhEBxMPELyTFTY0GVKI46QA==
+-----END CERTIFICATE-----
diff --git a/host/frontend/gcastv2/webrtc/include/webrtc/AdbWebSocketHandler.h b/host/frontend/gcastv2/webrtc/include/webrtc/AdbWebSocketHandler.h
new file mode 100644
index 000000000..0a622b238
--- /dev/null
+++ b/host/frontend/gcastv2/webrtc/include/webrtc/AdbWebSocketHandler.h
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <https/WebSocketHandler.h>
+#include <https/RunLoop.h>
+
+#include <memory>
+
+struct AdbWebSocketHandler
+ : public WebSocketHandler,
+ public std::enable_shared_from_this<AdbWebSocketHandler> {
+
+ explicit AdbWebSocketHandler(
+ std::shared_ptr<RunLoop> runLoop,
+ const std::string &adb_host_and_port);
+
+ ~AdbWebSocketHandler() override;
+
+ void run();
+
+ int handleMessage(
+ uint8_t headerByte, const uint8_t *msg, size_t len) override;
+
+private:
+ struct AdbConnection;
+
+ std::shared_ptr<RunLoop> mRunLoop;
+ std::shared_ptr<AdbConnection> mAdbConnection;
+
+ int mSocket;
+
+ int setupSocket(const std::string &adb_host_and_port);
+};
+
diff --git a/host/frontend/gcastv2/webrtc/include/webrtc/DTLS.h b/host/frontend/gcastv2/webrtc/include/webrtc/DTLS.h
new file mode 100644
index 000000000..fc8738ffa
--- /dev/null
+++ b/host/frontend/gcastv2/webrtc/include/webrtc/DTLS.h
@@ -0,0 +1,101 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <https/RunLoop.h>
+
+#include <openssl/bio.h>
+#include <openssl/ssl.h>
+
+#include <functional>
+#include <memory>
+#include <netinet/in.h>
+#include <optional>
+#include <vector>
+
+#include <srtp2/srtp.h>
+
+struct RTPSocketHandler;
+
+struct DTLS : public std::enable_shared_from_this<DTLS> {
+ static void Init();
+
+ enum class Mode {
+ ACCEPT,
+ CONNECT
+ };
+
+ explicit DTLS(
+ std::shared_ptr<RTPSocketHandler> handler,
+ Mode mode,
+ std::shared_ptr<X509> certificate,
+ std::shared_ptr<EVP_PKEY> key,
+ const std::string &remoteFingerprint,
+ bool useSRTP);
+
+ ~DTLS();
+
+ void connect(const sockaddr_storage &remoteAddr);
+ void inject(const uint8_t *data, size_t size);
+
+ size_t protect(void *data, size_t size, bool isRTP);
+ size_t unprotect(void *data, size_t size, bool isRTP);
+
+ // Returns -EAGAIN if no data is currently available.
+ ssize_t readApplicationData(void *data, size_t size);
+
+ ssize_t writeApplicationData(const void *data, size_t size);
+
+private:
+ enum class State {
+ UNINITIALIZED,
+ CONNECTING,
+ CONNECTED,
+
+ } mState;
+
+ std::weak_ptr<RTPSocketHandler> mHandler;
+ Mode mMode;
+ std::string mRemoteFingerprint;
+ bool mUseSRTP;
+
+ SSL_CTX *mCtx;
+ SSL *mSSL;
+
+ // These are owned by the SSL object.
+ BIO *mBioR, *mBioW;
+
+ sockaddr_storage mRemoteAddr;
+
+ srtp_t mSRTPInbound, mSRTPOutbound;
+
+ static int OnVerifyPeerCertificate(int ok, X509_STORE_CTX *ctx);
+
+ void doTheThing(int res);
+ void queueOutputDataFromDTLS();
+ void tryConnecting();
+
+ void getKeyingMaterial();
+
+ static void CreateSRTPSession(
+ srtp_t *session,
+ const std::string &keyAndSalt,
+ srtp_ssrc_type_t direction);
+
+ bool useCertificate(std::shared_ptr<X509> certificate);
+ bool usePrivateKey(std::shared_ptr<EVP_PKEY> key);
+};
diff --git a/host/frontend/gcastv2/webrtc/include/webrtc/G711Packetizer.h b/host/frontend/gcastv2/webrtc/include/webrtc/G711Packetizer.h
new file mode 100644
index 000000000..82fcb4c07
--- /dev/null
+++ b/host/frontend/gcastv2/webrtc/include/webrtc/G711Packetizer.h
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include "Packetizer.h"
+
+#include <https/RunLoop.h>
+
+#include <memory>
+
+#include <source/StreamingSource.h>
+
+struct G711Packetizer : public Packetizer {
+
+ using StreamingSource = android::StreamingSource;
+
+ enum class Mode {
+ ALAW,
+ ULAW
+ };
+ explicit G711Packetizer(
+ Mode mode,
+ std::shared_ptr<RunLoop> runLoop,
+ std::shared_ptr<StreamingSource> audioSource);
+
+ uint32_t rtpNow() const override;
+
+private:
+ using SBuffer = android::SBuffer;
+
+ Mode mMode;
+ std::shared_ptr<RunLoop> mRunLoop;
+
+ bool mFirstInTalkspurt;
+
+ void packetize(const std::shared_ptr<SBuffer> &accessUnit, int64_t timeUs);
+};
+
+
diff --git a/host/frontend/webrtc/lib/keyboard.h b/host/frontend/gcastv2/webrtc/include/webrtc/Keyboard.h
index 84c48769a..84c48769a 100644
--- a/host/frontend/webrtc/lib/keyboard.h
+++ b/host/frontend/gcastv2/webrtc/include/webrtc/Keyboard.h
diff --git a/host/frontend/gcastv2/webrtc/include/webrtc/MyWebSocketHandler.h b/host/frontend/gcastv2/webrtc/include/webrtc/MyWebSocketHandler.h
new file mode 100644
index 000000000..f22de5581
--- /dev/null
+++ b/host/frontend/gcastv2/webrtc/include/webrtc/MyWebSocketHandler.h
@@ -0,0 +1,111 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <webrtc/RTPSession.h>
+#include <webrtc/RTPSocketHandler.h>
+#include <webrtc/SDP.h>
+#include <webrtc/ServerState.h>
+
+#include <https/WebSocketHandler.h>
+#include <https/RunLoop.h>
+#include <source/KeyboardSink.h>
+#include <source/TouchSink.h>
+
+#include <memory>
+#include <optional>
+#include <sstream>
+#include <string>
+#include <vector>
+
+struct MyWebSocketHandler
+ : public WebSocketHandler,
+ public std::enable_shared_from_this<MyWebSocketHandler> {
+
+ explicit MyWebSocketHandler(
+ std::shared_ptr<RunLoop> runLoop,
+ std::shared_ptr<ServerState> serverState,
+ size_t handlerId);
+
+ ~MyWebSocketHandler() override;
+
+ int handleMessage(
+ uint8_t headerByte, const uint8_t *msg, size_t len) override;
+
+private:
+ enum OptionBits : uint32_t {
+ disableAudio = 1,
+ bundleTracks = 2,
+ enableData = 4,
+ useSingleCertificateForAllTracks = 8,
+ useTCP = 16,
+ };
+
+ using TouchSink = android::TouchSink;
+ using KeyboardSink = android::KeyboardSink;
+
+ std::shared_ptr<RunLoop> mRunLoop;
+ std::shared_ptr<ServerState> mServerState;
+ size_t mId;
+ uint32_t mOptions;
+
+ // Vector has the same ordering as the media entries in the SDP, i.e.
+ // vector index is "mlineIndex". (unless we are bundling, in which case
+ // there is only a single session).
+ std::vector<std::shared_ptr<RTPSession>> mSessions;
+
+ SDP mOfferedSDP;
+ std::vector<std::shared_ptr<RTPSocketHandler>> mRTPs;
+
+ std::shared_ptr<TouchSink> mTouchSink;
+ std::shared_ptr<KeyboardSink> mKeyboardSink;
+
+ std::pair<std::shared_ptr<X509>, std::shared_ptr<EVP_PKEY>>
+ mCertificateAndKey;
+
+ // Pass -1 for mlineIndex to access the "general" section.
+ std::optional<std::string> getSDPValue(
+ ssize_t mlineIndex,
+ std::string_view key,
+ bool fallthroughToGeneralSection) const;
+
+ std::string getRemotePassword(size_t mlineIndex) const;
+ std::string getRemoteUFrag(size_t mlineIndex) const;
+ std::string getRemoteFingerprint(size_t mlineIndex) const;
+
+ bool getCandidate(int32_t mid);
+
+ static std::pair<std::shared_ptr<X509>, std::shared_ptr<EVP_PKEY>>
+ CreateDTLSCertificateAndKey();
+
+ std::pair<std::string, std::string> createUniqueUFragAndPassword();
+
+ void parseOptions(const std::string &pathAndQuery);
+ size_t countTracks() const;
+
+ void prepareSessions();
+
+ void emitTrackIceOptionsAndFingerprint(
+ std::stringstream &ss, size_t mlineIndex) const;
+
+ // Returns -1 on error.
+ ssize_t mlineIndexForMid(int32_t mid) const;
+
+ static void CreateRandomIceCharSequence(char *dst, size_t size);
+};
+
+
diff --git a/host/frontend/gcastv2/webrtc/include/webrtc/OpusPacketizer.h b/host/frontend/gcastv2/webrtc/include/webrtc/OpusPacketizer.h
new file mode 100644
index 000000000..269cf421c
--- /dev/null
+++ b/host/frontend/gcastv2/webrtc/include/webrtc/OpusPacketizer.h
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include "Packetizer.h"
+
+#include <https/RunLoop.h>
+
+#include <memory>
+
+#include <source/StreamingSource.h>
+
+struct OpusPacketizer : public Packetizer {
+
+ using StreamingSource = android::StreamingSource;
+
+ explicit OpusPacketizer(
+ std::shared_ptr<RunLoop> runLoop,
+ std::shared_ptr<StreamingSource> audioSource);
+
+ uint32_t rtpNow() const override;
+
+private:
+ using SBuffer = android::SBuffer;
+
+ std::shared_ptr<RunLoop> mRunLoop;
+
+ bool mFirstInTalkspurt;
+
+ void packetize(const std::shared_ptr<SBuffer> &accessUnit, int64_t timeUs);
+};
+
+
diff --git a/host/frontend/gcastv2/webrtc/include/webrtc/Packetizer.h b/host/frontend/gcastv2/webrtc/include/webrtc/Packetizer.h
new file mode 100644
index 000000000..e584085ab
--- /dev/null
+++ b/host/frontend/gcastv2/webrtc/include/webrtc/Packetizer.h
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <stdint.h>
+
+#include <chrono>
+#include <memory>
+#include <vector>
+
+#include <https/RunLoop.h>
+#include <source/StreamingSource.h>
+
+struct RTPSender;
+
+struct Packetizer : public std::enable_shared_from_this<Packetizer> {
+
+ using StreamingSource = android::StreamingSource;
+
+ explicit Packetizer(std::shared_ptr<RunLoop> runLoop,
+ std::shared_ptr<StreamingSource> source);
+ virtual ~Packetizer();
+
+ virtual void run();
+ virtual uint32_t rtpNow() const = 0;
+ int32_t requestIDRFrame();
+
+ virtual void queueRTPDatagram(std::vector<uint8_t> *packet);
+
+ virtual void addSender(std::shared_ptr<RTPSender> sender);
+
+ virtual void onFrame(const std::shared_ptr<android::SBuffer>& accessUnit);
+
+ protected:
+ virtual void packetize(const std::shared_ptr<android::SBuffer>& accessUnit,
+ int64_t timeUs) = 0;
+
+ uint32_t timeSinceStart() const;
+
+ int64_t mediaStartTime() const { return mStartTimeMedia; }
+
+ private:
+ size_t mNumSamplesRead;
+ std::chrono::time_point<std::chrono::steady_clock> mStartTimeReal;
+ int64_t mStartTimeMedia;
+
+ std::shared_ptr<RunLoop> mRunLoop;
+
+ std::shared_ptr<StreamingSource> mStreamingSource;
+
+ std::vector<std::weak_ptr<RTPSender>> mSenders;
+};
diff --git a/host/frontend/gcastv2/webrtc/include/webrtc/RTPSender.h b/host/frontend/gcastv2/webrtc/include/webrtc/RTPSender.h
new file mode 100644
index 000000000..3473fe421
--- /dev/null
+++ b/host/frontend/gcastv2/webrtc/include/webrtc/RTPSender.h
@@ -0,0 +1,98 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include "Packetizer.h"
+
+#include <https/RunLoop.h>
+
+#include <memory>
+#include <optional>
+#include <unordered_map>
+#include <vector>
+
+struct RTPSocketHandler;
+
+struct RTPSender : public std::enable_shared_from_this<RTPSender> {
+
+ explicit RTPSender(
+ std::shared_ptr<RunLoop> runLoop,
+ RTPSocketHandler *parent,
+ std::shared_ptr<Packetizer> videoPacketizer,
+ std::shared_ptr<Packetizer> audioPacketizer);
+
+ void addSource(uint32_t ssrc);
+
+ void addRetransInfo(
+ uint32_t ssrc, uint8_t PT, uint32_t retransSSRC, uint8_t retransPT);
+
+ int injectRTCP(uint8_t *data, size_t size);
+ void queueRTPDatagram(std::vector<uint8_t> *packet);
+
+ void run();
+
+ void requestIDRFrame();
+
+private:
+ struct SourceInfo {
+ explicit SourceInfo()
+ : mNumPacketsSent(0),
+ mNumBytesSent(0) {
+ }
+
+ size_t mNumPacketsSent;
+ size_t mNumBytesSent;
+
+ // (ssrc, PT) by PT.
+ std::unordered_map<uint8_t, std::pair<uint32_t, uint8_t>> mRetrans;
+
+ std::deque<std::vector<uint8_t>> mRecentPackets;
+ };
+
+ std::shared_ptr<RunLoop> mRunLoop;
+ RTPSocketHandler *mParent;
+
+ // Sources by ssrc.
+ std::unordered_map<uint32_t, SourceInfo> mSources;
+
+ std::shared_ptr<Packetizer> mVideoPacketizer;
+ std::shared_ptr<Packetizer> mAudioPacketizer;
+
+ void appendSR(std::vector<uint8_t> *buffer, uint32_t localSSRC);
+ void appendSDES(std::vector<uint8_t> *buffer, uint32_t localSSRC);
+
+ void queueSR(uint32_t localSSRC);
+ void sendSR(uint32_t localSSRC);
+
+ void queueDLRR(
+ uint32_t localSSRC,
+ uint32_t remoteSSRC,
+ uint32_t ntpHi,
+ uint32_t ntpLo);
+
+ void appendDLRR(
+ std::vector<uint8_t> *buffer,
+ uint32_t localSSRC,
+ uint32_t remoteSSRC,
+ uint32_t ntpHi,
+ uint32_t ntpLo);
+
+ int processRTCP(const uint8_t *data, size_t size);
+
+ void retransmitPackets(uint32_t localSSRC, uint16_t PID, uint16_t BLP);
+};
+
diff --git a/host/frontend/gcastv2/webrtc/include/webrtc/RTPSession.h b/host/frontend/gcastv2/webrtc/include/webrtc/RTPSession.h
new file mode 100644
index 000000000..4faeb42a5
--- /dev/null
+++ b/host/frontend/gcastv2/webrtc/include/webrtc/RTPSession.h
@@ -0,0 +1,76 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <https/RunLoop.h>
+
+#include <memory>
+#include <optional>
+#include <string_view>
+
+#include <netinet/in.h>
+#include <openssl/ssl.h>
+
+struct RTPSession : std::enable_shared_from_this<RTPSession> {
+ explicit RTPSession(
+ std::string_view localUFrag,
+ std::string_view localPassword,
+ std::shared_ptr<X509> localCertificate,
+ std::shared_ptr<EVP_PKEY> localKey);
+
+ bool isActive() const;
+ void setIsActive();
+
+ void setRemoteParams(
+ std::string_view remoteUFrag,
+ std::string_view remotePassword,
+ std::string_view remoteFingerprint);
+
+ std::string localUFrag() const;
+ std::string localPassword() const;
+ std::shared_ptr<X509> localCertificate() const;
+ std::shared_ptr<EVP_PKEY> localKey() const;
+ std::string localFingerprint() const;
+
+ std::string remoteUFrag() const;
+ std::string remotePassword() const;
+ std::string remoteFingerprint() const;
+
+ bool hasRemoteAddress() const;
+ sockaddr_storage remoteAddress() const;
+ void setRemoteAddress(const sockaddr_storage &remoteAddr);
+
+ void schedulePing(
+ std::shared_ptr<RunLoop> runLoop,
+ RunLoop::AsyncFunction cb,
+ std::chrono::steady_clock::duration delay);
+
+private:
+ std::string mLocalUFrag;
+ std::string mLocalPassword;
+ std::shared_ptr<X509> mLocalCertificate;
+ std::shared_ptr<EVP_PKEY> mLocalKey;
+
+ std::optional<std::string> mRemoteUFrag;
+ std::optional<std::string> mRemotePassword;
+ std::optional<std::string> mRemoteFingerprint;
+ std::optional<sockaddr_storage> mRemoteAddr;
+
+ RunLoop::Token mPingToken;
+
+ bool mIsActive;
+};
diff --git a/host/frontend/gcastv2/webrtc/include/webrtc/RTPSocketHandler.h b/host/frontend/gcastv2/webrtc/include/webrtc/RTPSocketHandler.h
new file mode 100644
index 000000000..f1dc4a221
--- /dev/null
+++ b/host/frontend/gcastv2/webrtc/include/webrtc/RTPSocketHandler.h
@@ -0,0 +1,137 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <https/PlainSocket.h>
+#include <https/RunLoop.h>
+#include <webrtc/DTLS.h>
+#include <webrtc/RTPSender.h>
+#include <webrtc/RTPSession.h>
+#include <webrtc/SCTPHandler.h>
+#include <webrtc/ServerState.h>
+#include <webrtc/STUNMessage.h>
+
+#include <memory>
+#include <string_view>
+#include <vector>
+
+struct MyWebSocketHandler;
+
+struct RTPSocketHandler
+ : public std::enable_shared_from_this<RTPSocketHandler> {
+
+ static constexpr size_t kMaxUDPPayloadSize = 1536;
+
+ static constexpr uint32_t TRACK_VIDEO = 1;
+ static constexpr uint32_t TRACK_AUDIO = 2;
+ static constexpr uint32_t TRACK_DATA = 4;
+
+ enum class TransportType {
+ UDP,
+ TCP,
+ };
+
+ explicit RTPSocketHandler(
+ std::shared_ptr<RunLoop> runLoop,
+ std::shared_ptr<ServerState> serverState,
+ TransportType type,
+ int domain,
+ uint32_t trackMask,
+ std::shared_ptr<RTPSession> session);
+
+ uint16_t getLocalPort() const;
+ std::string getLocalUFrag() const;
+ std::string getLocalIPString() const;
+
+ void run();
+
+ void queueDatagram(
+ const sockaddr_storage &addr, const void *data, size_t size);
+
+ void queueRTCPDatagram(const void *data, size_t size);
+ void queueRTPDatagram(const void *data, size_t size);
+
+ void notifyDTLSConnected();
+
+private:
+ struct Datagram {
+ explicit Datagram(
+ const sockaddr_storage &addr, const void *data, size_t size);
+
+ const void *data() const;
+ size_t size() const;
+
+ const sockaddr_storage &remoteAddress() const;
+
+ private:
+ std::vector<uint8_t> mData;
+ sockaddr_storage mAddr;
+ };
+
+ std::shared_ptr<RunLoop> mRunLoop;
+ std::shared_ptr<ServerState> mServerState;
+ TransportType mTransportType;
+ uint16_t mLocalPort;
+ uint32_t mTrackMask;
+ std::shared_ptr<RTPSession> mSession;
+
+ std::shared_ptr<BufferedSocket> mSocket;
+ std::shared_ptr<DTLS> mDTLS;
+ std::shared_ptr<SCTPHandler> mSCTPHandler;
+
+ std::deque<std::shared_ptr<Datagram>> mOutQueue;
+ bool mSendPending;
+ bool mDTLSConnected;
+
+ std::shared_ptr<RTPSender> mRTPSender;
+
+ // for TransportType TCP:
+ std::shared_ptr<PlainSocket> mServerSocket;
+ sockaddr_storage mClientAddr;
+ socklen_t mClientAddrLen;
+
+ std::vector<uint8_t> mInBuffer;
+ size_t mInBufferLength;
+
+ std::vector<uint8_t> mOutBuffer;
+
+ void onReceive();
+ void onDTLSReceive(const uint8_t *data, size_t size);
+
+ void pingRemote(std::shared_ptr<RTPSession> session);
+
+ bool matchesSession(const STUNMessage &msg) const;
+
+ void scheduleDrainOutQueue();
+ void drainOutQueue();
+
+ int onSRTPReceive(uint8_t *data, size_t size);
+
+ void onTCPConnect();
+ void onTCPReceive();
+
+ void onPacketReceived(
+ const sockaddr_storage &addr,
+ socklen_t addrLen,
+ uint8_t *data,
+ size_t size);
+
+ void queueTCPOutputPacket(const uint8_t *data, size_t size);
+ void sendTCPOutputData();
+};
+
+
diff --git a/host/frontend/gcastv2/webrtc/include/webrtc/SCTPHandler.h b/host/frontend/gcastv2/webrtc/include/webrtc/SCTPHandler.h
new file mode 100644
index 000000000..af1b11c66
--- /dev/null
+++ b/host/frontend/gcastv2/webrtc/include/webrtc/SCTPHandler.h
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <webrtc/DTLS.h>
+
+#include <https/RunLoop.h>
+
+#include <memory>
+
+struct SCTPHandler : public std::enable_shared_from_this<SCTPHandler> {
+ explicit SCTPHandler(
+ std::shared_ptr<RunLoop> runLoop,
+ std::shared_ptr<DTLS> dtls);
+
+ void run();
+
+ int inject(uint8_t *data, size_t size);
+
+private:
+ std::shared_ptr<RunLoop> mRunLoop;
+ std::shared_ptr<DTLS> mDTLS;
+
+ uint32_t mInitiateTag;
+ uint32_t mSendingTSN;
+ bool mSentGreeting;
+
+ int processChunk(
+ uint16_t srcPort,
+ const uint8_t *data,
+ size_t size,
+ bool firstChunk,
+ bool lastChunk);
+
+ static uint32_t crc32c(const uint8_t *data, size_t size);
+
+ void onSendGreeting(uint16_t srcPort, size_t index);
+};
diff --git a/host/frontend/gcastv2/webrtc/include/webrtc/SDP.h b/host/frontend/gcastv2/webrtc/include/webrtc/SDP.h
new file mode 100644
index 000000000..b531d6df1
--- /dev/null
+++ b/host/frontend/gcastv2/webrtc/include/webrtc/SDP.h
@@ -0,0 +1,79 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <string>
+#include <vector>
+
+struct SDP {
+ explicit SDP();
+
+ int initCheck() const;
+
+ void clear();
+ int setTo(const std::string &data);
+
+ // Section 0 is reserved for top-level attributes, section indices >= 1
+ // correspond to each media section starting with an "m=" line.
+ size_t countSections() const;
+
+ std::vector<std::string>::const_iterator section_begin(
+ size_t section) const;
+
+ std::vector<std::string>::const_iterator section_end(
+ size_t section) const;
+
+ struct SectionEditor {
+ ~SectionEditor();
+
+ SectionEditor &operator<<(std::string_view s);
+
+ void commit();
+
+ private:
+ friend struct SDP;
+
+ explicit SectionEditor(SDP *sdp, size_t section);
+
+ SDP *mSDP;
+ size_t mSection;
+
+ std::string mBuffer;
+ };
+
+ SectionEditor createSection();
+ SectionEditor appendToSection(size_t section);
+
+ static void Test();
+
+private:
+ int mInitCheck;
+ std::vector<std::string> mLines;
+
+ std::vector<size_t> mLineIndexBySection;
+
+ bool mNewSectionEditorActive;
+
+ void getSectionRange(
+ size_t section,
+ size_t *lineStartIndex,
+ size_t *lineStopIndex) const;
+
+ void commitSectionEdit(
+ size_t section, const std::vector<std::string> &lines);
+};
+
diff --git a/host/frontend/gcastv2/webrtc/include/webrtc/STUNClient.h b/host/frontend/gcastv2/webrtc/include/webrtc/STUNClient.h
new file mode 100644
index 000000000..87bce72a5
--- /dev/null
+++ b/host/frontend/gcastv2/webrtc/include/webrtc/STUNClient.h
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <https/PlainSocket.h>
+#include <https/RunLoop.h>
+#include <memory>
+
+#include <arpa/inet.h>
+
+struct STUNClient : public std::enable_shared_from_this<STUNClient> {
+ using Callback = std::function<void(int, const std::string &)>;
+
+ explicit STUNClient(
+ std::shared_ptr<RunLoop> runLoop,
+ const sockaddr_in &addr,
+ Callback cb);
+
+ void run();
+
+private:
+ static constexpr size_t kMaxUDPPayloadSize = 1536;
+ static constexpr size_t kMaxNumRetries = 5;
+
+ static constexpr std::chrono::duration kTimeoutDelay =
+ std::chrono::seconds(1);
+
+ std::shared_ptr<RunLoop> mRunLoop;
+ sockaddr_in mRemoteAddr;
+ Callback mCallback;
+
+ std::shared_ptr<PlainSocket> mSocket;
+
+ RunLoop::Token mTimeoutToken;
+ size_t mNumRetriesLeft;
+
+ void onSendRequest();
+ void onReceiveResponse();
+
+ void scheduleRequest();
+ void onTimeout();
+};
diff --git a/host/frontend/gcastv2/webrtc/include/webrtc/STUNMessage.h b/host/frontend/gcastv2/webrtc/include/webrtc/STUNMessage.h
new file mode 100644
index 000000000..1498f590b
--- /dev/null
+++ b/host/frontend/gcastv2/webrtc/include/webrtc/STUNMessage.h
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <optional>
+#include <string_view>
+#include <vector>
+
+struct STUNMessage {
+ explicit STUNMessage(uint16_t type, const uint8_t transactionID[12]);
+ explicit STUNMessage(const void *data, size_t size);
+
+ bool isValid() const;
+
+ uint16_t type() const;
+
+ void addAttribute(uint16_t type) {
+ addAttribute(type, nullptr, 0);
+ }
+
+ void addAttribute(uint16_t type, const void *data, size_t size);
+ void addMessageIntegrityAttribute(std::string_view password);
+ void addFingerprint();
+
+ bool findAttribute(uint16_t type, const void **data, size_t *size) const;
+
+ const uint8_t *data();
+ size_t size() const;
+
+ void dump(std::optional<std::string_view> password = std::nullopt) const;
+
+private:
+ bool mIsValid;
+ std::vector<uint8_t> mData;
+ bool mAddedMessageIntegrity;
+
+ void validate();
+
+ bool verifyMessageIntegrity(size_t offset, std::string_view password) const;
+ bool verifyFingerprint(size_t offset) const;
+};
diff --git a/host/frontend/gcastv2/webrtc/include/webrtc/ServerState.h b/host/frontend/gcastv2/webrtc/include/webrtc/ServerState.h
new file mode 100644
index 000000000..b98a3f432
--- /dev/null
+++ b/host/frontend/gcastv2/webrtc/include/webrtc/ServerState.h
@@ -0,0 +1,79 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include "Packetizer.h"
+
+#include <https/RunLoop.h>
+
+#include <source/HostToGuestComms.h>
+
+#include <source/KeyboardSink.h>
+#include <source/TouchSink.h>
+#include <source/StreamingSource.h>
+
+#include <memory>
+#include <mutex>
+#include <set>
+
+#include <host/libs/screen_connector/screen_connector.h>
+
+struct ServerState {
+ using TouchSink = android::TouchSink;
+ using KeyboardSink = android::KeyboardSink;
+
+ enum class VideoFormat {
+ VP8,
+ };
+ explicit ServerState(
+ std::shared_ptr<RunLoop> runLoop,
+ VideoFormat videoFormat);
+
+ std::shared_ptr<Packetizer> getVideoPacketizer();
+ std::shared_ptr<Packetizer> getAudioPacketizer();
+ std::shared_ptr<TouchSink> getTouchSink();
+ std::shared_ptr<KeyboardSink> getKeyboardSink();
+
+ VideoFormat videoFormat() const { return mVideoFormat; }
+
+ size_t acquireHandlerId();
+ void releaseHandlerId(size_t id);
+
+private:
+ using StreamingSource = android::StreamingSource;
+
+ std::shared_ptr<RunLoop> mRunLoop;
+
+ VideoFormat mVideoFormat;
+
+ std::weak_ptr<Packetizer> mVideoPacketizer;
+ std::weak_ptr<Packetizer> mAudioPacketizer;
+
+ std::shared_ptr<StreamingSource> mFrameBufferSource;
+
+ std::shared_ptr<StreamingSource> mAudioSource;
+
+ std::shared_ptr<cvd::ScreenConnector> mScreenConnector;
+ std::shared_ptr<std::thread> mScreenConnectorMonitor;
+
+ std::shared_ptr<TouchSink> mTouchSink;
+ std::shared_ptr<KeyboardSink> mKeyboardSink;
+
+ std::set<size_t> mAllocatedHandlerIds;
+
+ void MonitorScreenConnector();
+};
diff --git a/host/frontend/gcastv2/webrtc/include/webrtc/VP8Packetizer.h b/host/frontend/gcastv2/webrtc/include/webrtc/VP8Packetizer.h
new file mode 100644
index 000000000..fa0a9b93f
--- /dev/null
+++ b/host/frontend/gcastv2/webrtc/include/webrtc/VP8Packetizer.h
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include "Packetizer.h"
+
+#include <https/RunLoop.h>
+#include <source/StreamingSource.h>
+
+#include <memory>
+
+struct VP8Packetizer : public Packetizer {
+
+ using StreamingSource = android::StreamingSource;
+
+ explicit VP8Packetizer(
+ std::shared_ptr<RunLoop> runLoop,
+ std::shared_ptr<StreamingSource> frameBufferSource);
+
+ uint32_t rtpNow() const override;
+
+private:
+ using SBuffer = android::SBuffer;
+
+ void packetize(const std::shared_ptr<SBuffer> &accessUnit, int64_t timeUs);
+};
diff --git a/host/frontend/gcastv2/webrtc/makefile b/host/frontend/gcastv2/webrtc/makefile
new file mode 100644
index 000000000..e2c5b7d79
--- /dev/null
+++ b/host/frontend/gcastv2/webrtc/makefile
@@ -0,0 +1,42 @@
+LOCAL_PATH := $(PWD)
+
+all: out/webRTC
+
+include ../build/defaults
+
+TARGET := webRTC
+
+C++FLAGS := \
+ -I../https/include \
+
+C++FLAGS += -O0 -g -Wall -Wextra -DTARGET_MAC=1
+
+C++FLAGS += -Wno-gnu-anonymous-struct -Wno-nested-anon-types
+C++FLAGS += -fno-rtti
+
+LDFLAGS += \
+ -framework CoreFoundation \
+ -framework Security \
+
+C++FLAGS += -I/usr/local/opt/openssl/include
+LDFLAGS += -L/usr/local/opt/openssl/lib -lssl -lcrypto
+
+C++FLAGS += -I/usr/local/opt/srtp/include
+LDFLAGS += -L/usr/local/opt/srtp/lib -lsrtp2
+
+STATIC_LIBS := libhttps.a
+
+SRCS := \
+ DTLS.cpp \
+ MyWebSocketHandler.cpp \
+ RTPReceiver.cpp \
+ RTPSender.cpp \
+ RTPSession.cpp \
+ RTPSocketHandler.cpp \
+ STUNMessage.cpp \
+ webRTC.cpp \
+
+include ../build/build_executable
+include ../build/clear
+
+include ../https/local.mak
diff --git a/host/frontend/gcastv2/webrtc/webRTC.cpp b/host/frontend/gcastv2/webrtc/webRTC.cpp
new file mode 100644
index 000000000..12f977b97
--- /dev/null
+++ b/host/frontend/gcastv2/webrtc/webRTC.cpp
@@ -0,0 +1,197 @@
+/*
+ * 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.
+ */
+
+#include <host/libs/config/logging.h>
+
+#include "Utils.h"
+
+#include <webrtc/AdbWebSocketHandler.h>
+#include <webrtc/DTLS.h>
+#include <webrtc/MyWebSocketHandler.h>
+#include <webrtc/RTPSocketHandler.h>
+#include <webrtc/ServerState.h>
+#include <webrtc/STUNClient.h>
+#include <webrtc/STUNMessage.h>
+
+#include <https/HTTPServer.h>
+#include <https/PlainSocket.h>
+#include <https/RunLoop.h>
+#include <https/SafeCallbackable.h>
+#include <https/SSLSocket.h>
+#include <https/Support.h>
+
+#include <iostream>
+#include <unordered_map>
+
+#include <netdb.h>
+
+#include <gflags/gflags.h>
+
+DEFINE_int32(http_server_port, 8443, "The port for the http server.");
+DEFINE_bool(use_secure_http, true, "Whether to use HTTPS or HTTP.");
+DEFINE_string(
+ public_ip,
+ "0.0.0.0",
+ "Public IPv4 address of your server, a.b.c.d format");
+DEFINE_string(
+ assets_dir,
+ "webrtc",
+ "Directory with location of webpage assets.");
+DEFINE_string(
+ certs_dir,
+ "webrtc/certs",
+ "Directory to certificates.");
+
+DEFINE_int32(touch_fd, -1, "An fd to listen on for touch connections.");
+DEFINE_int32(keyboard_fd, -1, "An fd to listen on for keyboard connections.");
+DEFINE_int32(frame_server_fd, -1, "An fd to listen on for frame updates");
+DEFINE_bool(write_virtio_input, false, "Whether to send input events in virtio format.");
+
+DEFINE_string(adb, "", "Interface:port of local adb service.");
+
+DEFINE_string(
+ stun_server,
+ "stun.l.google.com:19302",
+ "host:port of STUN server to use for public address resolution");
+
+int main(int argc, char **argv) {
+ cvd::DefaultSubprocessLogging(argv);
+ ::gflags::ParseCommandLineFlags(&argc, &argv, true);
+
+ SSLSocket::Init();
+ DTLS::Init();
+
+ if (FLAGS_public_ip.empty() || FLAGS_public_ip == "0.0.0.0") {
+ // NOTE: We only contact the external STUN server once upon startup
+ // to determine our own public IP.
+ // This only works if NAT does not remap ports, i.e. a local port 15550
+ // is visible to the outside world on port 15550 as well.
+ // If this condition is not met, this code will have to be modified
+ // and a STUN request made for each locally bound socket before
+ // fulfilling a "MyWebSocketHandler::getCandidate" ICE request.
+
+ const addrinfo kHints = {
+ AI_ADDRCONFIG,
+ PF_INET,
+ SOCK_DGRAM,
+ IPPROTO_UDP,
+ 0, // ai_addrlen
+ nullptr, // ai_addr
+ nullptr, // ai_canonname
+ nullptr // ai_next
+ };
+
+ auto pieces = SplitString(FLAGS_stun_server, ':');
+ CHECK_EQ(pieces.size(), 2u);
+
+ addrinfo *infos;
+ CHECK(!getaddrinfo(pieces[0].c_str(), pieces[1].c_str(), &kHints, &infos));
+
+ sockaddr_storage stunAddr;
+ memcpy(&stunAddr, infos->ai_addr, infos->ai_addrlen);
+
+ freeaddrinfo(infos);
+ infos = nullptr;
+
+ CHECK_EQ(stunAddr.ss_family, AF_INET);
+
+ std::mutex lock;
+ std::condition_variable cond;
+ bool done = false;
+
+ auto runLoop = std::make_shared<RunLoop>("STUN");
+
+ auto stunClient = std::make_shared<STUNClient>(
+ runLoop,
+ reinterpret_cast<const sockaddr_in &>(stunAddr),
+ [&lock, &cond, &done](int result, const std::string &myPublicIp) {
+ CHECK(!result);
+ LOG(INFO)
+ << "STUN-discovered public IP: " << myPublicIp;
+
+ FLAGS_public_ip = myPublicIp;
+
+ std::lock_guard autoLock(lock);
+ done = true;
+ cond.notify_all();
+ });
+
+ stunClient->run();
+
+ std::unique_lock autoLock(lock);
+ while (!done) {
+ cond.wait(autoLock);
+ }
+ }
+
+ auto runLoop = RunLoop::main();
+
+ auto state = std::make_shared<ServerState>(
+ runLoop, ServerState::VideoFormat::VP8);
+
+ auto port = FLAGS_http_server_port;
+
+ auto httpd = std::make_shared<HTTPServer>(
+ runLoop,
+ "0.0.0.0",
+ port,
+ FLAGS_use_secure_http
+ ? ServerSocket::TransportType::TLS
+ : ServerSocket::TransportType::TCP,
+ FLAGS_certs_dir + "/server.crt",
+ FLAGS_certs_dir + "/server.key");
+
+ const std::string index_html = FLAGS_assets_dir + "/index.html";
+ const std::string logcat_js = FLAGS_assets_dir + "/js/logcat.js";
+ const std::string receive_js = FLAGS_assets_dir + "/js/receive.js";
+ const std::string viewpane_js = FLAGS_assets_dir + "/js/viewpane.js";
+ const std::string style_css = FLAGS_assets_dir + "/style.css";
+
+ httpd->addStaticFile("/index.html", index_html.c_str());
+ httpd->addStaticFile("/js/logcat.js", logcat_js.c_str());
+ httpd->addStaticFile("/js/receive.js", receive_js.c_str());
+ httpd->addStaticFile("/js/viewpane.js", viewpane_js.c_str());
+ httpd->addStaticFile("/style.css", style_css.c_str());
+
+ httpd->addWebSocketHandlerFactory(
+ "/control",
+ [runLoop, state]{
+ auto id = state->acquireHandlerId();
+
+ auto handler =
+ std::make_shared<MyWebSocketHandler>(runLoop, state, id);
+
+ return std::make_pair(0 /* OK */, handler);
+ });
+
+ if (!FLAGS_adb.empty()) {
+ httpd->addWebSocketHandlerFactory(
+ "/control_adb",
+ [runLoop]{
+ auto handler = std::make_shared<AdbWebSocketHandler>(
+ runLoop, FLAGS_adb);
+
+ handler->run();
+
+ return std::make_pair(0 /* OK */, handler);
+ });
+ }
+
+ httpd->run();
+ runLoop->run();
+
+ return 0;
+}
diff --git a/host/frontend/vnc_server/Android.bp b/host/frontend/vnc_server/Android.bp
index bfb556152..68fae3289 100644
--- a/host/frontend/vnc_server/Android.bp
+++ b/host/frontend/vnc_server/Android.bp
@@ -13,11 +13,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-cc_binary {
+cc_binary_host {
name: "vnc_server",
srcs: [
"blackboard.cpp",
@@ -32,27 +28,20 @@ cc_binary {
shared_libs: [
"libcuttlefish_fs",
"libcuttlefish_utils",
+ "cuttlefish_tcp_socket",
"libbase",
- "libjsoncpp",
"liblog",
],
- header_libs: [
- "libcuttlefish_confui_host_headers",
- ],
static_libs: [
"libcuttlefish_host_config",
"libcuttlefish_screen_connector",
"libcuttlefish_wayland_server",
- "libcuttlefish_confui",
- "libcuttlefish_confui_host",
- "libft2.nodep",
- "libteeui",
- "libteeui_localization",
"libffi",
+ "libjsoncpp",
"libjpeg",
"libgflags",
"libwayland_server",
"libwayland_extension_server_protocols",
],
- defaults: ["cuttlefish_host"],
+ defaults: ["cuttlefish_host_only"],
}
diff --git a/host/frontend/vnc_server/blackboard.cpp b/host/frontend/vnc_server/blackboard.cpp
index 91a8d1ec3..0790b4950 100644
--- a/host/frontend/vnc_server/blackboard.cpp
+++ b/host/frontend/vnc_server/blackboard.cpp
@@ -29,10 +29,10 @@ DEFINE_bool(debug_blackboard, false,
#define DLOG(LEVEL) \
if (FLAGS_debug_blackboard) LOG(LEVEL)
-using cuttlefish::vnc::BlackBoard;
-using cuttlefish::vnc::Stripe;
+using cvd::vnc::BlackBoard;
+using cvd::vnc::Stripe;
-cuttlefish::vnc::SeqNumberVec cuttlefish::vnc::MakeSeqNumberVec() {
+cvd::vnc::SeqNumberVec cvd::vnc::MakeSeqNumberVec() {
return SeqNumberVec(FrameBufferWatcher::StripesPerFrame());
}
@@ -75,7 +75,7 @@ bool BlackBoard::NoNewStripesFor(const SeqNumberVec& seq_nums) const {
return true;
}
-cuttlefish::vnc::StripePtrVec BlackBoard::WaitForSenderWork(
+cvd::vnc::StripePtrVec BlackBoard::WaitForSenderWork(
const VncClientConnection* conn) {
std::unique_lock<std::mutex> guard(m_);
auto& state = GetStateForClient(conn);
@@ -139,7 +139,7 @@ void BlackBoard::StopWaiting(const VncClientConnection* conn) {
}
void BlackBoard::set_frame_buffer_watcher(
- cuttlefish::vnc::FrameBufferWatcher* frame_buffer_watcher) {
+ cvd::vnc::FrameBufferWatcher* frame_buffer_watcher) {
std::lock_guard<std::mutex> guard(m_);
frame_buffer_watcher_ = frame_buffer_watcher;
}
diff --git a/host/frontend/vnc_server/blackboard.h b/host/frontend/vnc_server/blackboard.h
index af4baea94..1119dd3c1 100644
--- a/host/frontend/vnc_server/blackboard.h
+++ b/host/frontend/vnc_server/blackboard.h
@@ -22,10 +22,10 @@
#include <mutex>
#include <unordered_map>
-#include "common/libs/concurrency/thread_annotations.h"
+#include "common/libs/threads/thread_annotations.h"
#include "host/frontend/vnc_server/vnc_utils.h"
-namespace cuttlefish {
+namespace cvd {
namespace vnc {
class VncClientConnection;
@@ -110,4 +110,4 @@ class BlackBoard {
};
} // namespace vnc
-} // namespace cuttlefish
+} // namespace cvd
diff --git a/host/frontend/vnc_server/frame_buffer_watcher.cpp b/host/frontend/vnc_server/frame_buffer_watcher.cpp
index 3cc39c0f2..02f1d6eee 100644
--- a/host/frontend/vnc_server/frame_buffer_watcher.cpp
+++ b/host/frontend/vnc_server/frame_buffer_watcher.cpp
@@ -27,12 +27,12 @@
#include <android-base/logging.h>
#include "host/frontend/vnc_server/vnc_utils.h"
+#include "host/libs/screen_connector/screen_connector.h"
-using cuttlefish::vnc::FrameBufferWatcher;
+using cvd::vnc::FrameBufferWatcher;
-FrameBufferWatcher::FrameBufferWatcher(BlackBoard* bb,
- ScreenConnector& screen_connector)
- : bb_{bb}, hwcomposer{bb_, screen_connector} {
+FrameBufferWatcher::FrameBufferWatcher(BlackBoard* bb)
+ : bb_{bb}, hwcomposer{bb_} {
for (auto& stripes_vec : stripes_) {
std::generate_n(std::back_inserter(stripes_vec),
SimulatedHWComposer::NumberOfStripes(),
@@ -60,7 +60,7 @@ bool FrameBufferWatcher::closed() const {
return closed_;
}
-cuttlefish::vnc::Stripe FrameBufferWatcher::Rotated(Stripe stripe) {
+cvd::vnc::Stripe FrameBufferWatcher::Rotated(Stripe stripe) {
if (stripe.orientation == ScreenOrientation::Landscape) {
LOG(FATAL) << "Rotating a landscape stripe, this is a mistake";
}
@@ -71,17 +71,17 @@ cuttlefish::vnc::Stripe FrameBufferWatcher::Rotated(Stripe stripe) {
Message rotated(raw.size(), 0xAA);
for (std::uint16_t i = 0; i < w; ++i) {
for (std::uint16_t j = 0; j < h; ++j) {
- size_t to = (i * h + j) * ScreenConnectorInfo::BytesPerPixel();
- size_t from = (w - (i + 1)) * ScreenConnectorInfo::BytesPerPixel() + s * j;
+ size_t to = (i * h + j) * ScreenConnector::BytesPerPixel();
+ size_t from = (w - (i + 1)) * ScreenConnector::BytesPerPixel() + s * j;
CHECK(from < raw.size());
CHECK(to < rotated.size());
- std::memcpy(&rotated[to], &raw[from], ScreenConnectorInfo::BytesPerPixel());
+ std::memcpy(&rotated[to], &raw[from], ScreenConnector::BytesPerPixel());
}
}
std::swap(stripe.x, stripe.y);
std::swap(stripe.width, stripe.height);
// The new stride after rotating is the height, as it is not aligned again.
- stripe.stride = stripe.width * ScreenConnectorInfo::BytesPerPixel();
+ stripe.stride = stripe.width * ScreenConnector::BytesPerPixel();
stripe.raw_data = std::move(rotated);
stripe.orientation = ScreenOrientation::Landscape;
return stripe;
@@ -92,7 +92,7 @@ bool FrameBufferWatcher::StripeIsDifferentFromPrevious(
return Stripes(stripe.orientation)[stripe.index]->raw_data != stripe.raw_data;
}
-cuttlefish::vnc::StripePtrVec FrameBufferWatcher::StripesNewerThan(
+cvd::vnc::StripePtrVec FrameBufferWatcher::StripesNewerThan(
ScreenOrientation orientation, const SeqNumberVec& seq_numbers) const {
std::lock_guard<std::mutex> guard(stripes_lock_);
const auto& stripes = Stripes(orientation);
@@ -106,12 +106,12 @@ cuttlefish::vnc::StripePtrVec FrameBufferWatcher::StripesNewerThan(
return new_stripes;
}
-cuttlefish::vnc::StripePtrVec& FrameBufferWatcher::Stripes(
+cvd::vnc::StripePtrVec& FrameBufferWatcher::Stripes(
ScreenOrientation orientation) {
return stripes_[static_cast<int>(orientation)];
}
-const cuttlefish::vnc::StripePtrVec& FrameBufferWatcher::Stripes(
+const cvd::vnc::StripePtrVec& FrameBufferWatcher::Stripes(
ScreenOrientation orientation) const {
return stripes_[static_cast<int>(orientation)];
}
@@ -190,11 +190,3 @@ void FrameBufferWatcher::Worker() {
int FrameBufferWatcher::StripesPerFrame() {
return SimulatedHWComposer::NumberOfStripes();
}
-
-void FrameBufferWatcher::IncClientCount() {
- hwcomposer.ReportClientsConnected();
-}
-
-void FrameBufferWatcher::DecClientCount() {
- // Do nothing
-}
diff --git a/host/frontend/vnc_server/frame_buffer_watcher.h b/host/frontend/vnc_server/frame_buffer_watcher.h
index 9b559b68c..40ab27055 100644
--- a/host/frontend/vnc_server/frame_buffer_watcher.h
+++ b/host/frontend/vnc_server/frame_buffer_watcher.h
@@ -22,27 +22,22 @@
#include <utility>
#include <vector>
-#include "common/libs/concurrency/thread_annotations.h"
+#include "common/libs/threads/thread_annotations.h"
#include "host/frontend/vnc_server/blackboard.h"
#include "host/frontend/vnc_server/jpeg_compressor.h"
#include "host/frontend/vnc_server/simulated_hw_composer.h"
-#include "host/libs/screen_connector/screen_connector.h"
-namespace cuttlefish {
+namespace cvd {
namespace vnc {
class FrameBufferWatcher {
public:
- explicit FrameBufferWatcher(BlackBoard* bb,
- ScreenConnector& screen_connector);
+ explicit FrameBufferWatcher(BlackBoard* bb);
FrameBufferWatcher(const FrameBufferWatcher&) = delete;
FrameBufferWatcher& operator=(const FrameBufferWatcher&) = delete;
~FrameBufferWatcher();
StripePtrVec StripesNewerThan(ScreenOrientation orientation,
const SeqNumberVec& seq_num) const;
- void IncClientCount();
- void DecClientCount();
-
static int StripesPerFrame();
private:
@@ -74,8 +69,8 @@ class FrameBufferWatcher {
mutable std::mutex m_;
bool closed_ GUARDED_BY(m_){};
BlackBoard* bb_{};
- SimulatedHWComposer hwcomposer;
+ SimulatedHWComposer hwcomposer{bb_};
};
} // namespace vnc
-} // namespace cuttlefish
+} // namespace cvd
diff --git a/host/frontend/vnc_server/jpeg_compressor.cpp b/host/frontend/vnc_server/jpeg_compressor.cpp
index 05013eb4e..270283eae 100644
--- a/host/frontend/vnc_server/jpeg_compressor.cpp
+++ b/host/frontend/vnc_server/jpeg_compressor.cpp
@@ -22,7 +22,7 @@
#include "host/frontend/vnc_server/vnc_utils.h"
#include "host/libs/screen_connector/screen_connector.h"
-using cuttlefish::vnc::JpegCompressor;
+using cvd::vnc::JpegCompressor;
namespace {
void InitCinfo(jpeg_compress_struct* cinfo, jpeg_error_mgr* err,
@@ -32,7 +32,7 @@ void InitCinfo(jpeg_compress_struct* cinfo, jpeg_error_mgr* err,
cinfo->image_width = width;
cinfo->image_height = height;
- cinfo->input_components = cuttlefish::ScreenConnectorInfo::BytesPerPixel();
+ cinfo->input_components = cvd::ScreenConnector::BytesPerPixel();
cinfo->in_color_space = JCS_EXT_RGBX;
jpeg_set_defaults(cinfo);
@@ -40,7 +40,7 @@ void InitCinfo(jpeg_compress_struct* cinfo, jpeg_error_mgr* err,
}
} // namespace
-cuttlefish::Message JpegCompressor::Compress(const Message& frame,
+cvd::Message JpegCompressor::Compress(const Message& frame,
int jpeg_quality, std::uint16_t x,
std::uint16_t y, std::uint16_t width,
std::uint16_t height,
@@ -58,7 +58,7 @@ cuttlefish::Message JpegCompressor::Compress(const Message& frame,
auto row = static_cast<JSAMPROW>(const_cast<std::uint8_t*>(
&frame[(y * stride) +
(cinfo.next_scanline * stride) +
- (x * cuttlefish::ScreenConnectorInfo::BytesPerPixel())]));
+ (x * cvd::ScreenConnector::BytesPerPixel())]));
jpeg_write_scanlines(&cinfo, &row, 1);
}
jpeg_finish_compress(&cinfo);
diff --git a/host/frontend/vnc_server/jpeg_compressor.h b/host/frontend/vnc_server/jpeg_compressor.h
index b6ef487a0..ae3af18ae 100644
--- a/host/frontend/vnc_server/jpeg_compressor.h
+++ b/host/frontend/vnc_server/jpeg_compressor.h
@@ -22,7 +22,7 @@
#include "host/frontend/vnc_server/vnc_utils.h"
-namespace cuttlefish {
+namespace cvd {
namespace vnc {
// libjpeg-turbo with jpeg_mem_dest (using memory as a destination) is funky.
@@ -49,4 +49,4 @@ class JpegCompressor {
};
} // namespace vnc
-} // namespace cuttlefish
+} // namespace cvd
diff --git a/host/frontend/vnc_server/keysyms.h b/host/frontend/vnc_server/keysyms.h
index ddcc0e4cf..41ff7c76e 100644
--- a/host/frontend/vnc_server/keysyms.h
+++ b/host/frontend/vnc_server/keysyms.h
@@ -18,7 +18,7 @@
#include <cstdint>
-namespace cuttlefish {
+namespace cvd {
namespace xk {
constexpr uint32_t BackSpace = 0xff08, Tab = 0xff09, Return = 0xff0d,
@@ -51,4 +51,4 @@ constexpr uint32_t BackSpace = 0xff08, Tab = 0xff09, Return = 0xff0d,
VNCMenu = 0xffed; // VNC seems to translate MENU to this
} // namespace xk
-} // namespace cuttlefish
+} // namespace cvd
diff --git a/host/frontend/vnc_server/main.cpp b/host/frontend/vnc_server/main.cpp
index e036b4036..add947480 100644
--- a/host/frontend/vnc_server/main.cpp
+++ b/host/frontend/vnc_server/main.cpp
@@ -15,40 +15,21 @@
*/
#include <algorithm>
-#include <memory>
#include <string>
#include <gflags/gflags.h>
-#include "host/frontend/vnc_server/simulated_hw_composer.h"
#include "host/frontend/vnc_server/vnc_server.h"
#include "host/frontend/vnc_server/vnc_utils.h"
#include "host/libs/config/logging.h"
-#include "host/libs/confui/host_mode_ctrl.h"
-#include "host/libs/confui/host_server.h"
DEFINE_bool(agressive, false, "Whether to use agressive server");
-DEFINE_int32(frame_server_fd, -1, "");
DEFINE_int32(port, 6444, "Port where to listen for connections");
int main(int argc, char* argv[]) {
- cuttlefish::DefaultSubprocessLogging(argv);
+ cvd::DefaultSubprocessLogging(argv);
google::ParseCommandLineFlags(&argc, &argv, true);
- auto& host_mode_ctrl = cuttlefish::HostModeCtrl::Get();
- auto screen_connector_ptr = cuttlefish::vnc::ScreenConnector::Get(
- FLAGS_frame_server_fd, host_mode_ctrl);
- auto& screen_connector = *(screen_connector_ptr.get());
-
- // create confirmation UI service, giving host_mode_ctrl and
- // screen_connector
- // keep this singleton object alive until the webRTC process ends
- static auto& host_confui_server =
- cuttlefish::confui::HostServer::Get(host_mode_ctrl, screen_connector);
-
- host_confui_server.Start();
- // lint does not like the spelling of "agressive", so needs NOTYPO
- cuttlefish::vnc::VncServer vnc_server(FLAGS_port, FLAGS_agressive, // NOTYPO
- screen_connector, host_confui_server);
+ cvd::vnc::VncServer vnc_server(FLAGS_port, FLAGS_agressive);
vnc_server.MainLoop();
}
diff --git a/host/frontend/vnc_server/simulated_hw_composer.cpp b/host/frontend/vnc_server/simulated_hw_composer.cpp
index 15bcd8b96..7b478f417 100644
--- a/host/frontend/vnc_server/simulated_hw_composer.cpp
+++ b/host/frontend/vnc_server/simulated_hw_composer.cpp
@@ -16,23 +16,24 @@
#include "host/frontend/vnc_server/simulated_hw_composer.h"
+#include <gflags/gflags.h>
+
#include "host/frontend/vnc_server/vnc_utils.h"
#include "host/libs/config/cuttlefish_config.h"
-using cuttlefish::vnc::SimulatedHWComposer;
-using ScreenConnector = cuttlefish::vnc::ScreenConnector;
+DEFINE_int32(frame_server_fd, -1, "");
+
+using cvd::vnc::SimulatedHWComposer;
-SimulatedHWComposer::SimulatedHWComposer(BlackBoard* bb,
- ScreenConnector& screen_connector)
+SimulatedHWComposer::SimulatedHWComposer(BlackBoard* bb)
:
#ifdef FUZZ_TEST_VNC
engine_{std::random_device{}()},
#endif
bb_{bb},
stripes_(kMaxQueueElements, &SimulatedHWComposer::EraseHalfOfElements),
- screen_connector_(screen_connector) {
+ screen_connector_(ScreenConnector::Get(FLAGS_frame_server_fd)) {
stripe_maker_ = std::thread(&SimulatedHWComposer::MakeStripes, this);
- screen_connector_.SetCallback(std::move(GetScreenConnectorCallback()));
}
SimulatedHWComposer::~SimulatedHWComposer() {
@@ -40,7 +41,7 @@ SimulatedHWComposer::~SimulatedHWComposer() {
stripe_maker_.join();
}
-cuttlefish::vnc::Stripe SimulatedHWComposer::GetNewStripe() {
+cvd::vnc::Stripe SimulatedHWComposer::GetNewStripe() {
auto s = stripes_.Pop();
#ifdef FUZZ_TEST_VNC
if (random_(engine_)) {
@@ -71,111 +72,57 @@ void SimulatedHWComposer::EraseHalfOfElements(
q->erase(q->begin(), std::next(q->begin(), kMaxQueueElements / 2));
}
-SimulatedHWComposer::GenerateProcessedFrameCallback
-SimulatedHWComposer::GetScreenConnectorCallback() {
- return [](std::uint32_t display_number, std::uint8_t* frame_pixels,
- cuttlefish::vnc::VncScProcessedFrame& processed_frame) {
- processed_frame.display_number_ = display_number;
- // TODO(171305898): handle multiple displays.
- if (display_number != 0) {
- // BUG 186580833: display_number comes from surface_id in crosvm
- // create_surface from virtio_gpu.rs set_scanout. We cannot use it as
- // the display number. Either crosvm virtio-gpu is incorrectly ignoring
- // scanout id and instead using a monotonically increasing surface id
- // number as the scanout resource is replaced over time, or frontend code
- // here is incorrectly assuming surface id == display id.
- display_number = 0;
- }
- const std::uint32_t display_w =
- ScreenConnector::ScreenWidth(display_number);
- const std::uint32_t display_h =
- ScreenConnector::ScreenHeight(display_number);
- const std::uint32_t display_stride_bytes =
- ScreenConnector::ScreenStrideBytes(display_number);
- const std::uint32_t display_bpp = ScreenConnector::BytesPerPixel();
- const std::uint32_t display_size_bytes =
- ScreenConnector::ScreenSizeInBytes(display_number);
-
- auto& raw_screen = processed_frame.raw_screen_;
- raw_screen.assign(frame_pixels, frame_pixels + display_size_bytes);
+void SimulatedHWComposer::MakeStripes() {
+ std::uint32_t previous_frame_number = 0;
+ auto screen_height = ScreenConnector::ScreenHeight();
+ Message raw_screen;
+ std::uint64_t stripe_seq_num = 1;
- static std::uint32_t next_frame_number = 0;
+ const FrameCallback frame_callback = [&](uint32_t frame_number,
+ uint8_t* frame_pixels) {
+ raw_screen.assign(frame_pixels,
+ frame_pixels + ScreenConnector::ScreenSizeInBytes());
- const auto num_stripes = SimulatedHWComposer::kNumStripes;
- for (int i = 0; i < num_stripes; ++i) {
- std::uint16_t y = (display_h / num_stripes) * i;
+ for (int i = 0; i < kNumStripes; ++i) {
+ ++stripe_seq_num;
+ std::uint16_t y = (screen_height / kNumStripes) * i;
// Last frames on the right and/or bottom handle extra pixels
// when a screen dimension is not evenly divisible by Frame::kNumSlots.
std::uint16_t height =
- display_h / num_stripes +
- (i + 1 == num_stripes ? display_h % num_stripes : 0);
- const auto* raw_start = &raw_screen[y * display_w * display_bpp];
- const auto* raw_end = raw_start + (height * display_w * display_bpp);
+ screen_height / kNumStripes +
+ (i + 1 == kNumStripes ? screen_height % kNumStripes : 0);
+ const auto* raw_start = &raw_screen[y * ScreenConnector::ScreenWidth() *
+ ScreenConnector::BytesPerPixel()];
+ const auto* raw_end =
+ raw_start + (height * ScreenConnector::ScreenWidth() *
+ ScreenConnector::BytesPerPixel());
// creating a named object and setting individual data members in order
// to make klp happy
// TODO (haining) construct this inside the call when not compiling
// on klp
Stripe s{};
s.index = i;
+ s.frame_id = frame_number;
s.x = 0;
s.y = y;
- s.width = display_w;
- s.stride = display_stride_bytes;
+ s.width = ScreenConnector::ScreenWidth();
+ s.stride = ScreenConnector::ScreenStride();
s.height = height;
- s.frame_id = next_frame_number++;
s.raw_data.assign(raw_start, raw_end);
+ s.seq_number = StripeSeqNumber{stripe_seq_num};
s.orientation = ScreenOrientation::Portrait;
- processed_frame.stripes_.push_back(std::move(s));
+ stripes_.Push(std::move(s));
}
- processed_frame.display_number_ = display_number;
- processed_frame.is_success_ = true;
+ previous_frame_number = frame_number;
};
-}
-void SimulatedHWComposer::MakeStripes() {
- std::uint64_t stripe_seq_num = 1;
- /*
- * callback should be set before the first WaitForAtLeastOneClientConnection()
- * (b/178504150) and the first OnFrameAfter().
- */
- if (!screen_connector_.IsCallbackSet()) {
- LOG(FATAL) << "ScreenConnector callback hasn't been set before MakeStripes";
- }
while (!closed()) {
bb_->WaitForAtLeastOneClientConnection();
- auto sim_hw_processed_frame = screen_connector_.OnNextFrame();
- // sim_hw_processed_frame has display number from the guest
- if (!sim_hw_processed_frame.is_success_) {
- continue;
- }
- while (!sim_hw_processed_frame.stripes_.empty()) {
- /*
- * ScreenConnector that supplies the frames into the queue
- * cannot be aware of stripe_seq_num. The callback was set at the
- * ScreenConnector creation time. ScreenConnector calls the callback
- * function autonomously to make the processed frames to supply the
- * queue with.
- *
- * Besides, ScreenConnector is not VNC specific. Thus, stripe_seq_num,
- * a VNC specific information, is maintained here.
- *
- * OnFrameAfter returns a sim_hw_processed_frame, that contains N consecutive stripes.
- * each stripe s has an invalid seq_number, default-initialzed
- * We set the field properly, and push to the stripes_
- */
- auto& s = sim_hw_processed_frame.stripes_.front();
- stripe_seq_num++;
- s.seq_number = StripeSeqNumber{stripe_seq_num};
- stripes_.Push(std::move(s));
- sim_hw_processed_frame.stripes_.pop_front();
- }
+
+ screen_connector_->OnFrameAfter(previous_frame_number, frame_callback);
}
}
int SimulatedHWComposer::NumberOfStripes() { return kNumStripes; }
-
-void SimulatedHWComposer::ReportClientsConnected() {
- screen_connector_.ReportClientsConnected(true);
-}
diff --git a/host/frontend/vnc_server/simulated_hw_composer.h b/host/frontend/vnc_server/simulated_hw_composer.h
index 9d62e3e8f..4a51f78ce 100644
--- a/host/frontend/vnc_server/simulated_hw_composer.h
+++ b/host/frontend/vnc_server/simulated_hw_composer.h
@@ -22,30 +22,23 @@
#include <random>
#endif
#include <thread>
-#include <deque>
-#include "common/libs/concurrency/thread_annotations.h"
-#include "common/libs/concurrency/thread_safe_queue.h"
+#include "common/libs/thread_safe_queue/thread_safe_queue.h"
+#include "common/libs/threads/thread_annotations.h"
#include "host/frontend/vnc_server/blackboard.h"
-#include "host/frontend/vnc_server/vnc_utils.h"
-#include "host/libs/config/cuttlefish_config.h"
#include "host/libs/screen_connector/screen_connector.h"
-namespace cuttlefish {
+namespace cvd {
namespace vnc {
class SimulatedHWComposer {
public:
- using GenerateProcessedFrameCallback = ScreenConnector::GenerateProcessedFrameCallback;
-
- SimulatedHWComposer(BlackBoard* bb, ScreenConnector& screen_connector);
+ SimulatedHWComposer(BlackBoard* bb);
SimulatedHWComposer(const SimulatedHWComposer&) = delete;
SimulatedHWComposer& operator=(const SimulatedHWComposer&) = delete;
~SimulatedHWComposer();
Stripe GetNewStripe();
- void ReportClientsConnected();
-
// NOTE not constexpr on purpose
static int NumberOfStripes();
@@ -54,7 +47,6 @@ class SimulatedHWComposer {
void close();
static void EraseHalfOfElements(ThreadSafeQueue<Stripe>::QueueImpl* q);
void MakeStripes();
- GenerateProcessedFrameCallback GetScreenConnectorCallback();
#ifdef FUZZ_TEST_VNC
std::default_random_engine engine_;
@@ -68,7 +60,7 @@ class SimulatedHWComposer {
BlackBoard* bb_{};
ThreadSafeQueue<Stripe> stripes_;
std::thread stripe_maker_;
- ScreenConnector& screen_connector_;
+ std::shared_ptr<ScreenConnector> screen_connector_;
};
} // namespace vnc
-} // namespace cuttlefish
+} // namespace cvd
diff --git a/host/frontend/vnc_server/virtual_inputs.cpp b/host/frontend/vnc_server/virtual_inputs.cpp
index 35fda8081..444136cff 100644
--- a/host/frontend/vnc_server/virtual_inputs.cpp
+++ b/host/frontend/vnc_server/virtual_inputs.cpp
@@ -15,7 +15,6 @@
*/
#include "host/frontend/vnc_server/virtual_inputs.h"
-
#include <gflags/gflags.h>
#include <android-base/logging.h>
#include <linux/input.h>
@@ -26,12 +25,10 @@
#include <thread>
#include "keysyms.h"
-#include "common/libs/confui/confui.h"
-#include "common/libs/fs/shared_select.h"
-#include "host/libs/config/cuttlefish_config.h"
-#include "host/libs/config/logging.h"
+#include <common/libs/fs/shared_select.h>
+#include <host/libs/config/cuttlefish_config.h>
-using cuttlefish::vnc::VirtualInputs;
+using cvd::vnc::VirtualInputs;
DEFINE_int32(touch_fd, -1,
"A fd for a socket where to accept touch connections");
@@ -52,24 +49,24 @@ struct virtio_input_event {
};
void AddKeyMappings(std::map<uint32_t, uint16_t>* key_mapping) {
- (*key_mapping)[cuttlefish::xk::AltLeft] = KEY_LEFTALT;
- (*key_mapping)[cuttlefish::xk::ControlLeft] = KEY_LEFTCTRL;
- (*key_mapping)[cuttlefish::xk::ShiftLeft] = KEY_LEFTSHIFT;
- (*key_mapping)[cuttlefish::xk::AltRight] = KEY_RIGHTALT;
- (*key_mapping)[cuttlefish::xk::ControlRight] = KEY_RIGHTCTRL;
- (*key_mapping)[cuttlefish::xk::ShiftRight] = KEY_RIGHTSHIFT;
- (*key_mapping)[cuttlefish::xk::MetaLeft] = KEY_LEFTMETA;
- (*key_mapping)[cuttlefish::xk::MetaRight] = KEY_RIGHTMETA;
- (*key_mapping)[cuttlefish::xk::MultiKey] = KEY_COMPOSE;
-
- (*key_mapping)[cuttlefish::xk::CapsLock] = KEY_CAPSLOCK;
- (*key_mapping)[cuttlefish::xk::NumLock] = KEY_NUMLOCK;
- (*key_mapping)[cuttlefish::xk::ScrollLock] = KEY_SCROLLLOCK;
-
- (*key_mapping)[cuttlefish::xk::BackSpace] = KEY_BACKSPACE;
- (*key_mapping)[cuttlefish::xk::Tab] = KEY_TAB;
- (*key_mapping)[cuttlefish::xk::Return] = KEY_ENTER;
- (*key_mapping)[cuttlefish::xk::Escape] = KEY_ESC;
+ (*key_mapping)[cvd::xk::AltLeft] = KEY_LEFTALT;
+ (*key_mapping)[cvd::xk::ControlLeft] = KEY_LEFTCTRL;
+ (*key_mapping)[cvd::xk::ShiftLeft] = KEY_LEFTSHIFT;
+ (*key_mapping)[cvd::xk::AltRight] = KEY_RIGHTALT;
+ (*key_mapping)[cvd::xk::ControlRight] = KEY_RIGHTCTRL;
+ (*key_mapping)[cvd::xk::ShiftRight] = KEY_RIGHTSHIFT;
+ (*key_mapping)[cvd::xk::MetaLeft] = KEY_LEFTMETA;
+ (*key_mapping)[cvd::xk::MetaRight] = KEY_RIGHTMETA;
+ (*key_mapping)[cvd::xk::MultiKey] = KEY_COMPOSE;
+
+ (*key_mapping)[cvd::xk::CapsLock] = KEY_CAPSLOCK;
+ (*key_mapping)[cvd::xk::NumLock] = KEY_NUMLOCK;
+ (*key_mapping)[cvd::xk::ScrollLock] = KEY_SCROLLLOCK;
+
+ (*key_mapping)[cvd::xk::BackSpace] = KEY_BACKSPACE;
+ (*key_mapping)[cvd::xk::Tab] = KEY_TAB;
+ (*key_mapping)[cvd::xk::Return] = KEY_ENTER;
+ (*key_mapping)[cvd::xk::Escape] = KEY_ESC;
(*key_mapping)[' '] = KEY_SPACE;
(*key_mapping)['!'] = KEY_1;
@@ -169,75 +166,75 @@ void AddKeyMappings(std::map<uint32_t, uint16_t>* key_mapping) {
(*key_mapping)['}'] = KEY_RIGHTBRACE;
(*key_mapping)['~'] = KEY_GRAVE;
- (*key_mapping)[cuttlefish::xk::F1] = KEY_F1;
- (*key_mapping)[cuttlefish::xk::F2] = KEY_F2;
- (*key_mapping)[cuttlefish::xk::F3] = KEY_F3;
- (*key_mapping)[cuttlefish::xk::F4] = KEY_F4;
- (*key_mapping)[cuttlefish::xk::F5] = KEY_F5;
- (*key_mapping)[cuttlefish::xk::F6] = KEY_F6;
- (*key_mapping)[cuttlefish::xk::F7] = KEY_F7;
- (*key_mapping)[cuttlefish::xk::F8] = KEY_F8;
- (*key_mapping)[cuttlefish::xk::F9] = KEY_F9;
- (*key_mapping)[cuttlefish::xk::F10] = KEY_F10;
- (*key_mapping)[cuttlefish::xk::F11] = KEY_F11;
- (*key_mapping)[cuttlefish::xk::F12] = KEY_F12;
- (*key_mapping)[cuttlefish::xk::F13] = KEY_F13;
- (*key_mapping)[cuttlefish::xk::F14] = KEY_F14;
- (*key_mapping)[cuttlefish::xk::F15] = KEY_F15;
- (*key_mapping)[cuttlefish::xk::F16] = KEY_F16;
- (*key_mapping)[cuttlefish::xk::F17] = KEY_F17;
- (*key_mapping)[cuttlefish::xk::F18] = KEY_F18;
- (*key_mapping)[cuttlefish::xk::F19] = KEY_F19;
- (*key_mapping)[cuttlefish::xk::F20] = KEY_F20;
- (*key_mapping)[cuttlefish::xk::F21] = KEY_F21;
- (*key_mapping)[cuttlefish::xk::F22] = KEY_F22;
- (*key_mapping)[cuttlefish::xk::F23] = KEY_F23;
- (*key_mapping)[cuttlefish::xk::F24] = KEY_F24;
-
- (*key_mapping)[cuttlefish::xk::Keypad0] = KEY_KP0;
- (*key_mapping)[cuttlefish::xk::Keypad1] = KEY_KP1;
- (*key_mapping)[cuttlefish::xk::Keypad2] = KEY_KP2;
- (*key_mapping)[cuttlefish::xk::Keypad3] = KEY_KP3;
- (*key_mapping)[cuttlefish::xk::Keypad4] = KEY_KP4;
- (*key_mapping)[cuttlefish::xk::Keypad5] = KEY_KP5;
- (*key_mapping)[cuttlefish::xk::Keypad6] = KEY_KP6;
- (*key_mapping)[cuttlefish::xk::Keypad7] = KEY_KP7;
- (*key_mapping)[cuttlefish::xk::Keypad8] = KEY_KP8;
- (*key_mapping)[cuttlefish::xk::Keypad9] = KEY_KP9;
- (*key_mapping)[cuttlefish::xk::KeypadMultiply] = KEY_KPASTERISK;
- (*key_mapping)[cuttlefish::xk::KeypadSubtract] = KEY_KPMINUS;
- (*key_mapping)[cuttlefish::xk::KeypadAdd] = KEY_KPPLUS;
- (*key_mapping)[cuttlefish::xk::KeypadDecimal] = KEY_KPDOT;
- (*key_mapping)[cuttlefish::xk::KeypadEnter] = KEY_KPENTER;
- (*key_mapping)[cuttlefish::xk::KeypadDivide] = KEY_KPSLASH;
- (*key_mapping)[cuttlefish::xk::KeypadEqual] = KEY_KPEQUAL;
- (*key_mapping)[cuttlefish::xk::PlusMinus] = KEY_KPPLUSMINUS;
-
- (*key_mapping)[cuttlefish::xk::SysReq] = KEY_SYSRQ;
- (*key_mapping)[cuttlefish::xk::LineFeed] = KEY_LINEFEED;
- (*key_mapping)[cuttlefish::xk::Home] = KEY_HOME;
- (*key_mapping)[cuttlefish::xk::Up] = KEY_UP;
- (*key_mapping)[cuttlefish::xk::PageUp] = KEY_PAGEUP;
- (*key_mapping)[cuttlefish::xk::Left] = KEY_LEFT;
- (*key_mapping)[cuttlefish::xk::Right] = KEY_RIGHT;
- (*key_mapping)[cuttlefish::xk::End] = KEY_END;
- (*key_mapping)[cuttlefish::xk::Down] = KEY_DOWN;
- (*key_mapping)[cuttlefish::xk::PageDown] = KEY_PAGEDOWN;
- (*key_mapping)[cuttlefish::xk::Insert] = KEY_INSERT;
- (*key_mapping)[cuttlefish::xk::Delete] = KEY_DELETE;
- (*key_mapping)[cuttlefish::xk::Pause] = KEY_PAUSE;
- (*key_mapping)[cuttlefish::xk::KeypadSeparator] = KEY_KPCOMMA;
- (*key_mapping)[cuttlefish::xk::Yen] = KEY_YEN;
- (*key_mapping)[cuttlefish::xk::Cancel] = KEY_STOP;
- (*key_mapping)[cuttlefish::xk::Redo] = KEY_AGAIN;
- (*key_mapping)[cuttlefish::xk::Undo] = KEY_UNDO;
- (*key_mapping)[cuttlefish::xk::Find] = KEY_FIND;
- (*key_mapping)[cuttlefish::xk::Print] = KEY_PRINT;
- (*key_mapping)[cuttlefish::xk::VolumeDown] = KEY_VOLUMEDOWN;
- (*key_mapping)[cuttlefish::xk::Mute] = KEY_MUTE;
- (*key_mapping)[cuttlefish::xk::VolumeUp] = KEY_VOLUMEUP;
- (*key_mapping)[cuttlefish::xk::Menu] = KEY_MENU;
- (*key_mapping)[cuttlefish::xk::VNCMenu] = KEY_MENU;
+ (*key_mapping)[cvd::xk::F1] = KEY_F1;
+ (*key_mapping)[cvd::xk::F2] = KEY_F2;
+ (*key_mapping)[cvd::xk::F3] = KEY_F3;
+ (*key_mapping)[cvd::xk::F4] = KEY_F4;
+ (*key_mapping)[cvd::xk::F5] = KEY_F5;
+ (*key_mapping)[cvd::xk::F6] = KEY_F6;
+ (*key_mapping)[cvd::xk::F7] = KEY_F7;
+ (*key_mapping)[cvd::xk::F8] = KEY_F8;
+ (*key_mapping)[cvd::xk::F9] = KEY_F9;
+ (*key_mapping)[cvd::xk::F10] = KEY_F10;
+ (*key_mapping)[cvd::xk::F11] = KEY_F11;
+ (*key_mapping)[cvd::xk::F12] = KEY_F12;
+ (*key_mapping)[cvd::xk::F13] = KEY_F13;
+ (*key_mapping)[cvd::xk::F14] = KEY_F14;
+ (*key_mapping)[cvd::xk::F15] = KEY_F15;
+ (*key_mapping)[cvd::xk::F16] = KEY_F16;
+ (*key_mapping)[cvd::xk::F17] = KEY_F17;
+ (*key_mapping)[cvd::xk::F18] = KEY_F18;
+ (*key_mapping)[cvd::xk::F19] = KEY_F19;
+ (*key_mapping)[cvd::xk::F20] = KEY_F20;
+ (*key_mapping)[cvd::xk::F21] = KEY_F21;
+ (*key_mapping)[cvd::xk::F22] = KEY_F22;
+ (*key_mapping)[cvd::xk::F23] = KEY_F23;
+ (*key_mapping)[cvd::xk::F24] = KEY_F24;
+
+ (*key_mapping)[cvd::xk::Keypad0] = KEY_KP0;
+ (*key_mapping)[cvd::xk::Keypad1] = KEY_KP1;
+ (*key_mapping)[cvd::xk::Keypad2] = KEY_KP2;
+ (*key_mapping)[cvd::xk::Keypad3] = KEY_KP3;
+ (*key_mapping)[cvd::xk::Keypad4] = KEY_KP4;
+ (*key_mapping)[cvd::xk::Keypad5] = KEY_KP5;
+ (*key_mapping)[cvd::xk::Keypad6] = KEY_KP6;
+ (*key_mapping)[cvd::xk::Keypad7] = KEY_KP7;
+ (*key_mapping)[cvd::xk::Keypad8] = KEY_KP8;
+ (*key_mapping)[cvd::xk::Keypad9] = KEY_KP9;
+ (*key_mapping)[cvd::xk::KeypadMultiply] = KEY_KPASTERISK;
+ (*key_mapping)[cvd::xk::KeypadSubtract] = KEY_KPMINUS;
+ (*key_mapping)[cvd::xk::KeypadAdd] = KEY_KPPLUS;
+ (*key_mapping)[cvd::xk::KeypadDecimal] = KEY_KPDOT;
+ (*key_mapping)[cvd::xk::KeypadEnter] = KEY_KPENTER;
+ (*key_mapping)[cvd::xk::KeypadDivide] = KEY_KPSLASH;
+ (*key_mapping)[cvd::xk::KeypadEqual] = KEY_KPEQUAL;
+ (*key_mapping)[cvd::xk::PlusMinus] = KEY_KPPLUSMINUS;
+
+ (*key_mapping)[cvd::xk::SysReq] = KEY_SYSRQ;
+ (*key_mapping)[cvd::xk::LineFeed] = KEY_LINEFEED;
+ (*key_mapping)[cvd::xk::Home] = KEY_HOME;
+ (*key_mapping)[cvd::xk::Up] = KEY_UP;
+ (*key_mapping)[cvd::xk::PageUp] = KEY_PAGEUP;
+ (*key_mapping)[cvd::xk::Left] = KEY_LEFT;
+ (*key_mapping)[cvd::xk::Right] = KEY_RIGHT;
+ (*key_mapping)[cvd::xk::End] = KEY_END;
+ (*key_mapping)[cvd::xk::Down] = KEY_DOWN;
+ (*key_mapping)[cvd::xk::PageDown] = KEY_PAGEDOWN;
+ (*key_mapping)[cvd::xk::Insert] = KEY_INSERT;
+ (*key_mapping)[cvd::xk::Delete] = KEY_DELETE;
+ (*key_mapping)[cvd::xk::Pause] = KEY_PAUSE;
+ (*key_mapping)[cvd::xk::KeypadSeparator] = KEY_KPCOMMA;
+ (*key_mapping)[cvd::xk::Yen] = KEY_YEN;
+ (*key_mapping)[cvd::xk::Cancel] = KEY_STOP;
+ (*key_mapping)[cvd::xk::Redo] = KEY_AGAIN;
+ (*key_mapping)[cvd::xk::Undo] = KEY_UNDO;
+ (*key_mapping)[cvd::xk::Find] = KEY_FIND;
+ (*key_mapping)[cvd::xk::Print] = KEY_PRINT;
+ (*key_mapping)[cvd::xk::VolumeDown] = KEY_VOLUMEDOWN;
+ (*key_mapping)[cvd::xk::Mute] = KEY_MUTE;
+ (*key_mapping)[cvd::xk::VolumeUp] = KEY_VOLUMEUP;
+ (*key_mapping)[cvd::xk::Menu] = KEY_MENU;
+ (*key_mapping)[cvd::xk::VNCMenu] = KEY_MENU;
}
void InitInputEvent(struct input_event* evt, uint16_t type, uint16_t code,
@@ -283,7 +280,7 @@ class SocketVirtualInputs : public VirtualInputs {
private:
template<size_t num_events>
- void SendEvents(cuttlefish::SharedFD socket, struct input_event (&event_buffer)[num_events]) {
+ void SendEvents(cvd::SharedFD socket, struct input_event (&event_buffer)[num_events]) {
std::lock_guard<std::mutex> lock(socket_mutex_);
if (!socket->IsOpen()) {
// This is unlikely as it would only happen between the start of the vnc
@@ -315,96 +312,41 @@ class SocketVirtualInputs : public VirtualInputs {
}
void ClientConnectorLoop() {
- auto touch_server = cuttlefish::SharedFD::Dup(FLAGS_touch_fd);
+ auto touch_server = cvd::SharedFD::Dup(FLAGS_touch_fd);
close(FLAGS_touch_fd);
FLAGS_touch_fd = -1;
- auto keyboard_server = cuttlefish::SharedFD::Dup(FLAGS_keyboard_fd);
+ auto keyboard_server = cvd::SharedFD::Dup(FLAGS_keyboard_fd);
close(FLAGS_keyboard_fd);
FLAGS_keyboard_fd = -1;
- LOG(DEBUG) << "Input socket host accepting connections...";
+ LOG(INFO) << "Input socket host accepting connections...";
while (1) {
- cuttlefish::SharedFDSet read_set;
+ cvd::SharedFDSet read_set;
read_set.Set(touch_server);
read_set.Set(keyboard_server);
- cuttlefish::Select(&read_set, nullptr, nullptr, nullptr);
+ cvd::Select(&read_set, nullptr, nullptr, nullptr);
{
std::lock_guard<std::mutex> lock(socket_mutex_);
if (read_set.IsSet(touch_server)) {
- touch_socket_ = cuttlefish::SharedFD::Accept(*touch_server);
- LOG(DEBUG) << "connected to touch";
+ touch_socket_ = cvd::SharedFD::Accept(*touch_server);
+ LOG(INFO) << "connected to touch";
}
if (read_set.IsSet(keyboard_server)) {
- keyboard_socket_ = cuttlefish::SharedFD::Accept(*keyboard_server);
- LOG(DEBUG) << "connected to keyboard";
+ keyboard_socket_ = cvd::SharedFD::Accept(*keyboard_server);
+ LOG(INFO) << "connected to keyboard";
}
}
}
}
- cuttlefish::SharedFD touch_socket_;
- cuttlefish::SharedFD keyboard_socket_;
+ cvd::SharedFD touch_socket_;
+ cvd::SharedFD keyboard_socket_;
std::thread client_connector_;
std::mutex socket_mutex_;
};
VirtualInputs::VirtualInputs() { AddKeyMappings(&keymapping_); }
-/**
- * Depending on the host mode (e.g. android, confirmation ui(tee), etc)
- * deliver the inputs to the right input implementation
- * e.g. ConfUI's input or regular socket based input
- */
-class VirtualInputDemux : public VirtualInputs {
- public:
- VirtualInputDemux(cuttlefish::confui::HostVirtualInput& confui_input)
- : confui_input_{confui_input} {}
- virtual ~VirtualInputDemux() = default;
-
- virtual void GenerateKeyPressEvent(int code, bool down) override;
- virtual void PressPowerButton(bool down) override;
- virtual void HandlePointerEvent(bool touch_down, int x, int y) override;
-
- private:
- SocketVirtualInputs socket_virtual_input_;
- cuttlefish::confui::HostVirtualInput& confui_input_;
-};
-
-void VirtualInputDemux::GenerateKeyPressEvent(int code, bool down) {
- // confui input is active only in the confirmation UI
- // also, socket virtual input should be inactive in the confirmation
- // UI session
- if (confui_input_.IsConfUiActive()) {
- if (code == cuttlefish::xk::Menu) {
- // release menu button in confirmation UI means for now cancel
- confui_input_.PressCancelButton(down);
- }
- ConfUiLog(DEBUG) << "the key" << code << "ignored."
- << "currently confirmation UI handles"
- << "menu and power only.";
- return;
- }
- socket_virtual_input_.GenerateKeyPressEvent(code, down);
-}
-
-void VirtualInputDemux::PressPowerButton(bool down) {
- if (confui_input_.IsConfUiActive()) {
- confui_input_.PressConfirmButton(down);
- return;
- }
- socket_virtual_input_.PressPowerButton(down);
-}
-
-void VirtualInputDemux::HandlePointerEvent(bool touch_down, int x, int y) {
- if (confui_input_.IsConfUiActive()) {
- ConfUiLog(DEBUG) << "currently confirmation UI ignores pointer events at ("
- << x << ", " << y << ")";
- return;
- }
- socket_virtual_input_.HandlePointerEvent(touch_down, x, y);
-}
-
-std::shared_ptr<VirtualInputs> VirtualInputs::Get(
- cuttlefish::confui::HostVirtualInput& confui_input) {
- return std::make_shared<VirtualInputDemux>(confui_input);
+VirtualInputs* VirtualInputs::Get() {
+ return new SocketVirtualInputs();
}
diff --git a/host/frontend/vnc_server/virtual_inputs.h b/host/frontend/vnc_server/virtual_inputs.h
index f30202ed1..7aca3eb38 100644
--- a/host/frontend/vnc_server/virtual_inputs.h
+++ b/host/frontend/vnc_server/virtual_inputs.h
@@ -16,20 +16,17 @@
* limitations under the License.
*/
+#include "vnc_utils.h"
+
#include <map>
-#include <memory>
#include <mutex>
-#include "host/libs/confui/host_virtual_input.h"
-#include "vnc_utils.h"
-
-namespace cuttlefish {
+namespace cvd {
namespace vnc {
class VirtualInputs {
public:
- static std::shared_ptr<VirtualInputs> Get(
- cuttlefish::confui::HostVirtualInput& confui_input);
+ static VirtualInputs* Get();
virtual ~VirtualInputs() = default;
@@ -44,4 +41,4 @@ class VirtualInputs {
};
} // namespace vnc
-} // namespace cuttlefish
+} // namespace cvd
diff --git a/host/frontend/vnc_server/vnc_client_connection.cpp b/host/frontend/vnc_server/vnc_client_connection.cpp
index ce16ec8f0..8e2e32cd5 100644
--- a/host/frontend/vnc_server/vnc_client_connection.cpp
+++ b/host/frontend/vnc_server/vnc_client_connection.cpp
@@ -32,17 +32,17 @@
#include <gflags/gflags.h>
#include <android-base/logging.h>
-#include "common/libs/utils/tcp_socket.h"
+#include "common/libs/tcp_socket/tcp_socket.h"
#include "host/frontend/vnc_server/keysyms.h"
#include "host/frontend/vnc_server/mocks.h"
#include "host/frontend/vnc_server/vnc_utils.h"
#include "host/libs/config/cuttlefish_config.h"
#include "host/libs/screen_connector/screen_connector.h"
-using cuttlefish::Message;
-using cuttlefish::vnc::Stripe;
-using cuttlefish::vnc::StripePtrVec;
-using cuttlefish::vnc::VncClientConnection;
+using cvd::Message;
+using cvd::vnc::Stripe;
+using cvd::vnc::StripePtrVec;
+using cvd::vnc::VncClientConnection;
struct ScreenRegionView {
using Pixel = uint32_t;
@@ -88,7 +88,7 @@ constexpr size_t kPointerEventLength = 5;
constexpr size_t kClientCutTextLength = 7; // more bytes follow
std::string HostName() {
- auto config = cuttlefish::CuttlefishConfig::Get();
+ auto config = vsoc::CuttlefishConfig::Get();
auto instance = config->ForDefaultInstance();
return !config || instance.device_title().empty() ? std::string{"localhost"}
: instance.device_title();
@@ -130,7 +130,7 @@ std::uint32_t GreenVal(std::uint32_t pixel) {
((0x1 << ScreenRegionView::kGreenBits) - 1);
}
} // namespace
-namespace cuttlefish {
+namespace cvd {
namespace vnc {
bool operator==(const VncClientConnection::FrameBufferUpdateRequest& lhs,
const VncClientConnection::FrameBufferUpdateRequest& rhs) {
@@ -143,7 +143,7 @@ bool operator!=(const VncClientConnection::FrameBufferUpdateRequest& lhs,
return !(lhs == rhs);
}
} // namespace vnc
-} // namespace cuttlefish
+} // namespace cvd
VncClientConnection::VncClientConnection(
ClientSocket client, std::shared_ptr<VirtualInputs> virtual_inputs,
@@ -258,7 +258,7 @@ void VncClientConnection::GetClientInit() {
void VncClientConnection::SendServerInit() {
const std::string server_name = HostName();
std::lock_guard<std::mutex> guard(m_);
- auto server_init = cuttlefish::CreateMessage(
+ auto server_init = cvd::CreateMessage(
static_cast<std::uint16_t>(ScreenWidth()),
static_cast<std::uint16_t>(ScreenHeight()), pixel_format_.bits_per_pixel,
pixel_format_.depth, pixel_format_.big_endian, pixel_format_.true_color,
@@ -272,7 +272,7 @@ void VncClientConnection::SendServerInit() {
Message VncClientConnection::MakeFrameBufferUpdateHeader(
std::uint16_t num_stripes) {
- return cuttlefish::CreateMessage(std::uint8_t{0}, // message-type
+ return cvd::CreateMessage(std::uint8_t{0}, // message-type
std::uint8_t{}, // padding
std::uint16_t{num_stripes});
}
@@ -280,7 +280,7 @@ Message VncClientConnection::MakeFrameBufferUpdateHeader(
void VncClientConnection::AppendRawStripeHeader(Message* frame_buffer_update,
const Stripe& stripe) {
static constexpr int32_t kRawEncoding = 0;
- cuttlefish::AppendToMessage(frame_buffer_update, std::uint16_t{stripe.x},
+ cvd::AppendToMessage(frame_buffer_update, std::uint16_t{stripe.x},
std::uint16_t{stripe.y}, std::uint16_t{stripe.width},
std::uint16_t{stripe.height}, kRawEncoding);
}
@@ -292,11 +292,11 @@ void VncClientConnection::AppendJpegSize(Message* frame_buffer_update,
constexpr size_t kJpegSizeThreeByteMax = 4194303;
if (jpeg_size <= kJpegSizeOneByteMax) {
- cuttlefish::AppendToMessage(frame_buffer_update,
+ cvd::AppendToMessage(frame_buffer_update,
static_cast<std::uint8_t>(jpeg_size));
} else if (jpeg_size <= kJpegSizeTwoByteMax) {
auto sz = static_cast<std::uint32_t>(jpeg_size);
- cuttlefish::AppendToMessage(frame_buffer_update,
+ cvd::AppendToMessage(frame_buffer_update,
static_cast<std::uint8_t>((sz & 0x7F) | 0x80),
static_cast<std::uint8_t>((sz >> 7) & 0xFF));
} else {
@@ -305,7 +305,7 @@ void VncClientConnection::AppendJpegSize(Message* frame_buffer_update,
<< kJpegSizeThreeByteMax;
}
const auto sz = static_cast<std::uint32_t>(jpeg_size);
- cuttlefish::AppendToMessage(frame_buffer_update,
+ cvd::AppendToMessage(frame_buffer_update,
static_cast<std::uint8_t>((sz & 0x7F) | 0x80),
static_cast<std::uint8_t>(((sz >> 7) & 0x7F) | 0x80),
static_cast<std::uint8_t>((sz >> 14) & 0xFF));
@@ -353,7 +353,7 @@ Message VncClientConnection::MakeRawFrameBufferUpdate(
void VncClientConnection::AppendJpegStripeHeader(Message* frame_buffer_update,
const Stripe& stripe) {
static constexpr std::uint8_t kJpegEncoding = 0x90;
- cuttlefish::AppendToMessage(frame_buffer_update, stripe.x, stripe.y, stripe.width,
+ cvd::AppendToMessage(frame_buffer_update, stripe.x, stripe.y, stripe.width,
stripe.height, kTightEncoding, kJpegEncoding);
AppendJpegSize(frame_buffer_update, stripe.jpeg_data.size());
}
@@ -411,7 +411,7 @@ void VncClientConnection::FrameBufferUpdateRequestHandler(bool aggressive) {
void VncClientConnection::SendDesktopSizeUpdate() {
static constexpr int32_t kDesktopSizeEncoding = -223;
- client_.SendNoSignal(cuttlefish::CreateMessage(
+ client_.SendNoSignal(cvd::CreateMessage(
std::uint8_t{0}, // message-type,
std::uint8_t{}, // padding
std::uint16_t{1}, // one pseudo rectangle
@@ -504,7 +504,7 @@ void VncClientConnection::HandlePointerEvent() {
std::lock_guard<std::mutex> guard(m_);
if (current_orientation_ == ScreenOrientation::Landscape) {
std::tie(x_pos, y_pos) =
- std::make_pair(ScreenConnectorInfo::ScreenWidth(0) - y_pos, x_pos);
+ std::make_pair(ScreenConnector::ScreenWidth() - y_pos, x_pos);
}
}
virtual_inputs_->HandlePointerEvent(button_mask, x_pos, y_pos);
@@ -534,14 +534,14 @@ VncClientConnection::Coordinates VncClientConnection::CoordinatesForOrientation(
int VncClientConnection::ScreenWidth() const {
return current_orientation_ == ScreenOrientation::Portrait
- ? ScreenConnectorInfo::ScreenWidth(0)
- : ScreenConnectorInfo::ScreenHeight(0);
+ ? ScreenConnector::ScreenWidth()
+ : ScreenConnector::ScreenHeight();
}
int VncClientConnection::ScreenHeight() const {
return current_orientation_ == ScreenOrientation::Portrait
- ? ScreenConnectorInfo::ScreenHeight(0)
- : ScreenConnectorInfo::ScreenWidth(0);
+ ? ScreenConnector::ScreenHeight()
+ : ScreenConnector::ScreenWidth();
}
void VncClientConnection::SetScreenOrientation(ScreenOrientation orientation) {
@@ -574,13 +574,13 @@ bool VncClientConnection::RotateIfIsRotationCommand(std::uint32_t key) {
return false;
}
switch (key) {
- case cuttlefish::xk::Right:
- case cuttlefish::xk::F12:
+ case cvd::xk::Right:
+ case cvd::xk::F12:
DLOG(INFO) << "switching to portrait";
SetScreenOrientation(ScreenOrientation::Portrait);
break;
- case cuttlefish::xk::Left:
- case cuttlefish::xk::F11:
+ case cvd::xk::Left:
+ case cvd::xk::F11:
DLOG(INFO) << "switching to landscape";
SetScreenOrientation(ScreenOrientation::Landscape);
break;
@@ -599,18 +599,18 @@ void VncClientConnection::HandleKeyEvent() {
auto key = uint32_tAt(&msg[3]);
bool key_down = msg[0];
switch (key) {
- case cuttlefish::xk::ControlLeft:
- case cuttlefish::xk::ControlRight:
+ case cvd::xk::ControlLeft:
+ case cvd::xk::ControlRight:
control_key_down_ = key_down;
break;
- case cuttlefish::xk::MetaLeft:
- case cuttlefish::xk::MetaRight:
+ case cvd::xk::MetaLeft:
+ case cvd::xk::MetaRight:
meta_key_down_ = key_down;
break;
- case cuttlefish::xk::F5:
- key = cuttlefish::xk::Menu;
+ case cvd::xk::F5:
+ key = cvd::xk::Menu;
break;
- case cuttlefish::xk::F7:
+ case cvd::xk::F7:
virtual_inputs_->PressPowerButton(key_down);
return;
default:
diff --git a/host/frontend/vnc_server/vnc_client_connection.h b/host/frontend/vnc_server/vnc_client_connection.h
index b26cf865d..9f4fb96bc 100644
--- a/host/frontend/vnc_server/vnc_client_connection.h
+++ b/host/frontend/vnc_server/vnc_client_connection.h
@@ -16,8 +16,8 @@
* limitations under the License.
*/
-#include "common/libs/concurrency/thread_annotations.h"
#include "common/libs/fs/shared_fd.h"
+#include "common/libs/threads/thread_annotations.h"
#include <cstdint>
#include <memory>
@@ -25,12 +25,12 @@
#include <thread>
#include <vector>
-#include "common/libs/utils/tcp_socket.h"
+#include "common/libs/tcp_socket/tcp_socket.h"
#include "host/frontend/vnc_server/blackboard.h"
#include "host/frontend/vnc_server/virtual_inputs.h"
#include "host/frontend/vnc_server/vnc_utils.h"
-namespace cuttlefish {
+namespace cvd {
namespace vnc {
class VncClientConnection {
@@ -170,4 +170,4 @@ class VncClientConnection {
};
} // namespace vnc
-} // namespace cuttlefish
+} // namespace cvd
diff --git a/host/frontend/vnc_server/vnc_server.cpp b/host/frontend/vnc_server/vnc_server.cpp
index eff0d5763..84e1d8bbc 100644
--- a/host/frontend/vnc_server/vnc_server.cpp
+++ b/host/frontend/vnc_server/vnc_server.cpp
@@ -16,10 +16,8 @@
#include "host/frontend/vnc_server/vnc_server.h"
-#include <memory>
-
#include <android-base/logging.h>
-#include "common/libs/utils/tcp_socket.h"
+#include "common/libs/tcp_socket/tcp_socket.h"
#include "host/frontend/vnc_server/blackboard.h"
#include "host/frontend/vnc_server/frame_buffer_watcher.h"
#include "host/frontend/vnc_server/jpeg_compressor.h"
@@ -27,21 +25,19 @@
#include "host/frontend/vnc_server/vnc_client_connection.h"
#include "host/frontend/vnc_server/vnc_utils.h"
-using cuttlefish::vnc::VncServer;
+using cvd::vnc::VncServer;
-VncServer::VncServer(int port, bool aggressive,
- cuttlefish::vnc::ScreenConnector& screen_connector,
- cuttlefish::confui::HostVirtualInput& confui_input)
+VncServer::VncServer(int port, bool aggressive)
: server_(port),
- virtual_inputs_(VirtualInputs::Get(confui_input)),
- frame_buffer_watcher_{&bb_, screen_connector},
- aggressive_{aggressive} {}
+ virtual_inputs_(VirtualInputs::Get()),
+ frame_buffer_watcher_{&bb_},
+ aggressive_{aggressive} {}
void VncServer::MainLoop() {
while (true) {
- LOG(DEBUG) << "Awaiting connections";
+ LOG(INFO) << "Awaiting connections";
auto connection = server_.Accept();
- LOG(DEBUG) << "Accepted a client connection";
+ LOG(INFO) << "Accepted a client connection";
StartClient(std::move(connection));
}
}
@@ -57,9 +53,7 @@ void VncServer::StartClientThread(ClientSocket sock) {
// data members. In the current setup, if the VncServer is destroyed with
// clients still running, the clients will all be left with dangling
// pointers.
- frame_buffer_watcher_.IncClientCount();
VncClientConnection client(std::move(sock), virtual_inputs_, &bb_,
aggressive_);
client.StartSession();
- frame_buffer_watcher_.DecClientCount();
}
diff --git a/host/frontend/vnc_server/vnc_server.h b/host/frontend/vnc_server/vnc_server.h
index 2751fd1b0..66e17e05e 100644
--- a/host/frontend/vnc_server/vnc_server.h
+++ b/host/frontend/vnc_server/vnc_server.h
@@ -21,25 +21,20 @@
#include <thread>
#include <utility>
-#include "common/libs/utils/tcp_socket.h"
+#include "common/libs/tcp_socket/tcp_socket.h"
#include "host/frontend/vnc_server/blackboard.h"
#include "host/frontend/vnc_server/frame_buffer_watcher.h"
#include "host/frontend/vnc_server/jpeg_compressor.h"
#include "host/frontend/vnc_server/virtual_inputs.h"
#include "host/frontend/vnc_server/vnc_client_connection.h"
#include "host/frontend/vnc_server/vnc_utils.h"
-#include "host/libs/confui/host_mode_ctrl.h"
-#include "host/libs/confui/host_virtual_input.h"
-#include "host/libs/screen_connector/screen_connector.h"
-namespace cuttlefish {
+namespace cvd {
namespace vnc {
class VncServer {
public:
- explicit VncServer(int port, bool aggressive,
- ScreenConnector& screen_connector,
- cuttlefish::confui::HostVirtualInput& confui_input);
+ explicit VncServer(int port, bool aggressive);
VncServer(const VncServer&) = delete;
VncServer& operator=(const VncServer&) = delete;
@@ -52,13 +47,11 @@ class VncServer {
void StartClientThread(ClientSocket sock);
ServerSocket server_;
-
std::shared_ptr<VirtualInputs> virtual_inputs_;
BlackBoard bb_;
-
FrameBufferWatcher frame_buffer_watcher_;
bool aggressive_{};
};
} // namespace vnc
-} // namespace cuttlefish
+} // namespace cvd
diff --git a/host/frontend/vnc_server/vnc_utils.h b/host/frontend/vnc_server/vnc_utils.h
index 7ec19f70f..7a8051835 100644
--- a/host/frontend/vnc_server/vnc_utils.h
+++ b/host/frontend/vnc_server/vnc_utils.h
@@ -18,16 +18,14 @@
#include <array>
#include <cstdint>
-#include <memory>
#include <utility>
#include <vector>
#include "common/libs/utils/size_utils.h"
-#include "common/libs/utils/tcp_socket.h"
+#include "common/libs/tcp_socket/tcp_socket.h"
#include "host/libs/config/cuttlefish_config.h"
-#include "host/libs/screen_connector/screen_connector.h"
-namespace cuttlefish {
+namespace cvd {
namespace vnc {
// TODO(haining) when the hwcomposer gives a sequence number type, use that
@@ -65,26 +63,5 @@ struct Stripe {
ScreenOrientation orientation{};
};
-/**
- * ScreenConnectorImpl will generate this, and enqueue
- *
- * It's basically a (processed) frame, so it:
- * must be efficiently std::move-able
- * Also, for the sake of algorithm simplicity:
- * must be default-constructable & assignable
- *
- */
-struct VncScProcessedFrame : public ScreenConnectorFrameInfo {
- Message raw_screen_;
- std::deque<Stripe> stripes_;
- std::unique_ptr<VncScProcessedFrame> Clone() {
- VncScProcessedFrame* cloned_frame = new VncScProcessedFrame();
- cloned_frame->raw_screen_ = raw_screen_;
- cloned_frame->stripes_ = stripes_;
- return std::unique_ptr<VncScProcessedFrame>(cloned_frame);
- }
-};
-using ScreenConnector = cuttlefish::ScreenConnector<VncScProcessedFrame>;
-
} // namespace vnc
-} // namespace cuttlefish
+} // namespace cvd
diff --git a/host/frontend/webrtc/Android.bp b/host/frontend/webrtc/Android.bp
deleted file mode 100644
index f03a589d7..000000000
--- a/host/frontend/webrtc/Android.bp
+++ /dev/null
@@ -1,140 +0,0 @@
-//
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-cc_library_static {
- name: "libcuttlefish_webrtc",
- srcs: [
- "lib/audio_device.cpp",
- "lib/audio_track_source_impl.cpp",
- "lib/client_handler.cpp",
- "lib/keyboard.cpp",
- "lib/local_recorder.cpp",
- "lib/port_range_socket_factory.cpp",
- "lib/streamer.cpp",
- "lib/utils.cpp",
- "lib/video_track_source_impl.cpp",
- "lib/vp8only_encoder_factory.cpp",
- "lib/ws_connection.cpp",
- ],
- cflags: [
- // libwebrtc headers need this
- "-Wno-unused-parameter",
- "-DWEBRTC_POSIX",
- "-DWEBRTC_LINUX",
- ],
- header_libs: [
- "webrtc_signaling_headers",
- "libwebrtc_absl_headers",
- ],
- static_libs: [
- "libsrtp2",
- "libcuttlefish_host_config",
- "libcuttlefish_screen_connector",
- "libcuttlefish_wayland_server",
- "libgflags",
- "libdrm",
- "libffi",
- "libwayland_server",
- "libwayland_extension_server_protocols",
- "libwebsockets",
- "libcap",
- "libcuttlefish_utils",
- "libwebrtc",
- "libwebrtc_absl_base",
- "libwebrtc_absl_types",
- ],
- shared_libs: [
- "libssl",
- "libbase",
- "libcuttlefish_fs",
- "libjsoncpp",
- "libwebm_mkvmuxer",
- ],
- defaults: ["cuttlefish_buildhost_only"],
-}
-
-cc_binary_host {
- name: "webRTC",
- srcs: [
- "adb_handler.cpp",
- "audio_handler.cpp",
- "bluetooth_handler.cpp",
- "connection_observer.cpp",
- "cvd_video_frame_buffer.cpp",
- "display_handler.cpp",
- "kernel_log_events_handler.cpp",
- "main.cpp",
- ],
- header_libs: [
- "webrtc_signaling_headers",
- "libwebrtc_absl_headers",
- "libcuttlefish_confui_host_headers",
- ],
- static_libs: [
- "libwebrtc_absl_base",
- "libwebrtc_absl_container",
- "libwebrtc_absl_debugging",
- "libwebrtc_absl_flags",
- "libwebrtc_absl_hash",
- "libwebrtc_absl_numeric",
- "libwebrtc_absl_status",
- "libwebrtc_absl_strings",
- "libwebrtc_absl_synchronization",
- "libwebrtc_absl_time",
- "libwebrtc_absl_types",
- "libaom",
- "libcap",
- "libcuttlefish_audio_connector",
- "libcuttlefish_host_config",
- "libcuttlefish_screen_connector",
- "libcuttlefish_utils",
- "libcuttlefish_wayland_server",
- "libcuttlefish_confui",
- "libcuttlefish_confui_host",
- "libft2.nodep",
- "libteeui",
- "libteeui_localization",
- "libdrm",
- "libevent",
- "libffi",
- "libgflags",
- "libopus",
- "libsrtp2",
- "libvpx",
- "libwayland_extension_server_protocols",
- "libwayland_server",
- "libwebrtc",
- "libcuttlefish_webrtc",
- "libwebsockets",
- "libyuv",
- ],
- shared_libs: [
- "libbase",
- "libcrypto",
- "libcuttlefish_fs",
- "libcuttlefish_kernel_log_monitor_utils",
- "libjsoncpp",
- "libopus",
- "libssl",
- "libvpx",
- "libyuv",
- "libwebm_mkvmuxer",
- ],
- defaults: ["cuttlefish_buildhost_only"],
-}
diff --git a/host/frontend/webrtc/adb_handler.cpp b/host/frontend/webrtc/adb_handler.cpp
deleted file mode 100644
index c580f657f..000000000
--- a/host/frontend/webrtc/adb_handler.cpp
+++ /dev/null
@@ -1,113 +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.
- */
-
-#include "host/frontend/webrtc/adb_handler.h"
-
-#include <unistd.h>
-
-#include <android-base/logging.h>
-
-using namespace android;
-
-namespace cuttlefish {
-namespace webrtc_streaming {
-
-namespace {
-
-SharedFD SetupAdbSocket(const std::string &adb_host_and_port) {
- auto colonPos = adb_host_and_port.find(':');
- if (colonPos == std::string::npos) {
- return SharedFD();
- }
-
- auto host = adb_host_and_port.substr(0, colonPos);
-
- const char *portString = adb_host_and_port.c_str() + colonPos + 1;
- char *end;
- unsigned long port = strtoul(portString, &end, 10);
-
- if (end == portString || *end != '\0' || port > 65535) {
- return SharedFD();
- }
-
- auto local_client = SharedFD::SocketLocalClient(port, SOCK_STREAM);
- CHECK(local_client->IsOpen()) << "Failed to connect to adb socket: " << local_client->StrError();
- return local_client;
-}
-
-} // namespace
-
-AdbHandler::AdbHandler(
- const std::string &adb_host_and_port,
- std::function<void(const uint8_t *, size_t)> send_to_client)
- : send_to_client_(send_to_client),
- adb_socket_(SetupAdbSocket(adb_host_and_port)),
- shutdown_(SharedFD::Event(0,0))
-{
- std::thread loop([this]() { ReadLoop(); });
- read_thread_.swap(loop);
-}
-
-
-AdbHandler::~AdbHandler() {
- // Send a message to the looper to shut down.
- uint64_t v = 1;
- shutdown_->Write(&v, sizeof(v));
- // Shut down the socket as well. Not srictly necessary.
- adb_socket_->Shutdown(SHUT_RDWR);
- read_thread_.join();
-}
-
-void AdbHandler::ReadLoop() {
- while (1) {
- uint8_t buffer[4096];
-
- read_set_.Set(shutdown_);
- read_set_.Set(adb_socket_);
- Select(&read_set_, nullptr, nullptr, nullptr);
-
- if (read_set_.IsSet(adb_socket_)) {
- auto read = adb_socket_->Read(buffer, sizeof(buffer));
- if (read < 0) {
- LOG(ERROR) << "Error on reading from ADB socket: " << strerror(adb_socket_->GetErrno());
- break;
- }
- if (read) {
- send_to_client_(buffer, read);
- }
- }
-
- if (read_set_.IsSet(shutdown_)) {
- LOG(INFO) << "AdbHandler is shutting down.";
- break;
- }
- }
-}
-
-void AdbHandler::handleMessage(const uint8_t *msg, size_t len) {
- size_t sent = 0;
- while (sent < len) {
- auto this_sent = adb_socket_->Write(&msg[sent], len - sent);
- if (this_sent < 0) {
- LOG(FATAL) << "Error writing to adb socket: " << adb_socket_->StrError();
- return;
- }
- sent += this_sent;
- }
-}
-
-} // namespace webrtc_streaming
-} // namespace cuttlefish
diff --git a/host/frontend/webrtc/audio_handler.cpp b/host/frontend/webrtc/audio_handler.cpp
deleted file mode 100644
index 40469958e..000000000
--- a/host/frontend/webrtc/audio_handler.cpp
+++ /dev/null
@@ -1,481 +0,0 @@
-/*
- * Copyright (C) 2020 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 "host/frontend/webrtc/audio_handler.h"
-
-#include <algorithm>
-#include <chrono>
-
-#include <android-base/logging.h>
-#include <rtc_base/time_utils.h>
-
-namespace cuttlefish {
-namespace {
-
-const virtio_snd_pcm_info STREAMS[] = {{
- .hdr =
- {
- .hda_fn_nid = Le32(0),
- },
- .features = Le32(0),
- // webrtc's api is quite primitive and doesn't allow for many different
- // formats: It only takes the bits_per_sample as a parameter and assumes
- // the underlying format to be one of the following:
- .formats = Le64(
- (((uint64_t)1) << (uint8_t)AudioStreamFormat::VIRTIO_SND_PCM_FMT_U8) |
- (((uint64_t)1) << (uint8_t)AudioStreamFormat::VIRTIO_SND_PCM_FMT_U16) |
- (((uint64_t)1) << (uint8_t)AudioStreamFormat::VIRTIO_SND_PCM_FMT_U24) |
- (((uint64_t)1) << (uint8_t)AudioStreamFormat::VIRTIO_SND_PCM_FMT_U32)),
- .rates = Le64(
- (((uint64_t)1) << (uint8_t)AudioStreamRate::VIRTIO_SND_PCM_RATE_5512) |
- (((uint64_t)1) << (uint8_t)AudioStreamRate::VIRTIO_SND_PCM_RATE_8000) |
- (((uint64_t)1) << (uint8_t)AudioStreamRate::VIRTIO_SND_PCM_RATE_11025) |
- (((uint64_t)1) << (uint8_t)AudioStreamRate::VIRTIO_SND_PCM_RATE_16000) |
- (((uint64_t)1) << (uint8_t)AudioStreamRate::VIRTIO_SND_PCM_RATE_22050) |
- (((uint64_t)1) << (uint8_t)AudioStreamRate::VIRTIO_SND_PCM_RATE_32000) |
- (((uint64_t)1) << (uint8_t)AudioStreamRate::VIRTIO_SND_PCM_RATE_44100) |
- (((uint64_t)1) << (uint8_t)AudioStreamRate::VIRTIO_SND_PCM_RATE_48000) |
- (((uint64_t)1) << (uint8_t)AudioStreamRate::VIRTIO_SND_PCM_RATE_64000) |
- (((uint64_t)1) << (uint8_t)AudioStreamRate::VIRTIO_SND_PCM_RATE_88200) |
- (((uint64_t)1) << (uint8_t)AudioStreamRate::VIRTIO_SND_PCM_RATE_96000) |
- (((uint64_t)1) << (uint8_t)
- AudioStreamRate::VIRTIO_SND_PCM_RATE_176400) |
- (((uint64_t)1) << (uint8_t)
- AudioStreamRate::VIRTIO_SND_PCM_RATE_192000) |
- (((uint64_t)1) << (uint8_t)
- AudioStreamRate::VIRTIO_SND_PCM_RATE_384000)),
- .direction = (uint8_t)AudioStreamDirection::VIRTIO_SND_D_OUTPUT,
- .channels_min = 1,
- .channels_max = 2,
-}, {
- .hdr =
- {
- .hda_fn_nid = Le32(0),
- },
- .features = Le32(0),
- // webrtc's api is quite primitive and doesn't allow for many different
- // formats: It only takes the bits_per_sample as a parameter and assumes
- // the underlying format to be one of the following:
- .formats = Le64(
- (((uint64_t)1) << (uint8_t)AudioStreamFormat::VIRTIO_SND_PCM_FMT_U8) |
- (((uint64_t)1) << (uint8_t)AudioStreamFormat::VIRTIO_SND_PCM_FMT_U16) |
- (((uint64_t)1) << (uint8_t)AudioStreamFormat::VIRTIO_SND_PCM_FMT_U24) |
- (((uint64_t)1) << (uint8_t)AudioStreamFormat::VIRTIO_SND_PCM_FMT_U32)),
- .rates = Le64(
- (((uint64_t)1) << (uint8_t)AudioStreamRate::VIRTIO_SND_PCM_RATE_5512) |
- (((uint64_t)1) << (uint8_t)AudioStreamRate::VIRTIO_SND_PCM_RATE_8000) |
- (((uint64_t)1) << (uint8_t)AudioStreamRate::VIRTIO_SND_PCM_RATE_11025) |
- (((uint64_t)1) << (uint8_t)AudioStreamRate::VIRTIO_SND_PCM_RATE_16000) |
- (((uint64_t)1) << (uint8_t)AudioStreamRate::VIRTIO_SND_PCM_RATE_22050) |
- (((uint64_t)1) << (uint8_t)AudioStreamRate::VIRTIO_SND_PCM_RATE_32000) |
- (((uint64_t)1) << (uint8_t)AudioStreamRate::VIRTIO_SND_PCM_RATE_44100) |
- (((uint64_t)1) << (uint8_t)AudioStreamRate::VIRTIO_SND_PCM_RATE_48000) |
- (((uint64_t)1) << (uint8_t)AudioStreamRate::VIRTIO_SND_PCM_RATE_64000) |
- (((uint64_t)1) << (uint8_t)AudioStreamRate::VIRTIO_SND_PCM_RATE_88200) |
- (((uint64_t)1) << (uint8_t)AudioStreamRate::VIRTIO_SND_PCM_RATE_96000) |
- (((uint64_t)1) << (uint8_t)
- AudioStreamRate::VIRTIO_SND_PCM_RATE_176400) |
- (((uint64_t)1) << (uint8_t)
- AudioStreamRate::VIRTIO_SND_PCM_RATE_192000) |
- (((uint64_t)1) << (uint8_t)
- AudioStreamRate::VIRTIO_SND_PCM_RATE_384000)),
- .direction = (uint8_t)AudioStreamDirection::VIRTIO_SND_D_INPUT,
- .channels_min = 1,
- .channels_max = 2,
-}};
-constexpr uint32_t NUM_STREAMS = sizeof(STREAMS) / sizeof(STREAMS[0]);
-
-bool IsCapture(uint32_t stream_id) {
- CHECK(stream_id < NUM_STREAMS) << "Invalid stream id: " << stream_id;
- return STREAMS[stream_id].direction ==
- (uint8_t)AudioStreamDirection::VIRTIO_SND_D_INPUT;
-}
-
-class CvdAudioFrameBuffer : public webrtc_streaming::AudioFrameBuffer {
- public:
- CvdAudioFrameBuffer(const uint8_t* buffer, int bits_per_sample,
- int sample_rate, int channels, int frames)
- : buffer_(buffer),
- bits_per_sample_(bits_per_sample),
- sample_rate_(sample_rate),
- channels_(channels),
- frames_(frames) {}
-
- int bits_per_sample() const override { return bits_per_sample_; }
-
- int sample_rate() const override { return sample_rate_; }
-
- int channels() const override { return channels_; }
-
- int frames() const override { return frames_; }
-
- const uint8_t* data() const override { return buffer_; }
-
- private:
- const uint8_t* buffer_;
- int bits_per_sample_;
- int sample_rate_;
- int channels_;
- int frames_;
-};
-
-int BitsPerSample(uint8_t virtio_format) {
- switch (virtio_format) {
- /* analog formats (width / physical width) */
- case (uint8_t)AudioStreamFormat::VIRTIO_SND_PCM_FMT_IMA_ADPCM:
- /* 4 / 4 bits */
- return 4;
- case (uint8_t)AudioStreamFormat::VIRTIO_SND_PCM_FMT_MU_LAW:
- /* 8 / 8 bits */
- return 8;
- case (uint8_t)AudioStreamFormat::VIRTIO_SND_PCM_FMT_A_LAW:
- /* 8 / 8 bits */
- return 8;
- case (uint8_t)AudioStreamFormat::VIRTIO_SND_PCM_FMT_S8:
- /* 8 / 8 bits */
- return 8;
- case (uint8_t)AudioStreamFormat::VIRTIO_SND_PCM_FMT_U8:
- /* 8 / 8 bits */
- return 8;
- case (uint8_t)AudioStreamFormat::VIRTIO_SND_PCM_FMT_S16:
- /* 16 / 16 bits */
- return 16;
- case (uint8_t)AudioStreamFormat::VIRTIO_SND_PCM_FMT_U16:
- /* 16 / 16 bits */
- return 16;
- case (uint8_t)AudioStreamFormat::VIRTIO_SND_PCM_FMT_S18_3:
- /* 18 / 24 bits */
- return 24;
- case (uint8_t)AudioStreamFormat::VIRTIO_SND_PCM_FMT_U18_3:
- /* 18 / 24 bits */
- return 24;
- case (uint8_t)AudioStreamFormat::VIRTIO_SND_PCM_FMT_S20_3:
- /* 20 / 24 bits */
- return 24;
- case (uint8_t)AudioStreamFormat::VIRTIO_SND_PCM_FMT_U20_3:
- /* 20 / 24 bits */
- return 24;
- case (uint8_t)AudioStreamFormat::VIRTIO_SND_PCM_FMT_S24_3:
- /* 24 / 24 bits */
- return 24;
- case (uint8_t)AudioStreamFormat::VIRTIO_SND_PCM_FMT_U24_3:
- /* 24 / 24 bits */
- return 24;
- case (uint8_t)AudioStreamFormat::VIRTIO_SND_PCM_FMT_S20:
- /* 20 / 32 bits */
- return 32;
- case (uint8_t)AudioStreamFormat::VIRTIO_SND_PCM_FMT_U20:
- /* 20 / 32 bits */
- return 32;
- case (uint8_t)AudioStreamFormat::VIRTIO_SND_PCM_FMT_S24:
- /* 24 / 32 bits */
- return 32;
- case (uint8_t)AudioStreamFormat::VIRTIO_SND_PCM_FMT_U24:
- /* 24 / 32 bits */
- return 32;
- case (uint8_t)AudioStreamFormat::VIRTIO_SND_PCM_FMT_S32:
- /* 32 / 32 bits */
- return 32;
- case (uint8_t)AudioStreamFormat::VIRTIO_SND_PCM_FMT_U32:
- /* 32 / 32 bits */
- return 32;
- case (uint8_t)AudioStreamFormat::VIRTIO_SND_PCM_FMT_FLOAT:
- /* 32 / 32 bits */
- return 32;
- case (uint8_t)AudioStreamFormat::VIRTIO_SND_PCM_FMT_FLOAT64:
- /* 64 / 64 bits */
- return 64;
- /* digital formats (width / physical width) */
- case (uint8_t)AudioStreamFormat::VIRTIO_SND_PCM_FMT_DSD_U8:
- /* 8 / 8 bits */
- return 8;
- case (uint8_t)AudioStreamFormat::VIRTIO_SND_PCM_FMT_DSD_U16:
- /* 16 / 16 bits */
- return 16;
- case (uint8_t)AudioStreamFormat::VIRTIO_SND_PCM_FMT_DSD_U32:
- /* 32 / 32 bits */
- return 32;
- case (uint8_t)AudioStreamFormat::VIRTIO_SND_PCM_FMT_IEC958_SUBFRAME:
- /* 32 / 32 bits */
- return 32;
- default:
- LOG(ERROR) << "Unknown virtio-snd audio format: " << virtio_format;
- return -1;
- }
-}
-
-int SampleRate(uint8_t virtio_rate) {
- switch (virtio_rate) {
- case (uint8_t)AudioStreamRate::VIRTIO_SND_PCM_RATE_5512:
- return 5512;
- case (uint8_t)AudioStreamRate::VIRTIO_SND_PCM_RATE_8000:
- return 8000;
- case (uint8_t)AudioStreamRate::VIRTIO_SND_PCM_RATE_11025:
- return 11025;
- case (uint8_t)AudioStreamRate::VIRTIO_SND_PCM_RATE_16000:
- return 16000;
- case (uint8_t)AudioStreamRate::VIRTIO_SND_PCM_RATE_22050:
- return 22050;
- case (uint8_t)AudioStreamRate::VIRTIO_SND_PCM_RATE_32000:
- return 32000;
- case (uint8_t)AudioStreamRate::VIRTIO_SND_PCM_RATE_44100:
- return 44100;
- case (uint8_t)AudioStreamRate::VIRTIO_SND_PCM_RATE_48000:
- return 48000;
- case (uint8_t)AudioStreamRate::VIRTIO_SND_PCM_RATE_64000:
- return 64000;
- case (uint8_t)AudioStreamRate::VIRTIO_SND_PCM_RATE_88200:
- return 88200;
- case (uint8_t)AudioStreamRate::VIRTIO_SND_PCM_RATE_96000:
- return 96000;
- case (uint8_t)AudioStreamRate::VIRTIO_SND_PCM_RATE_176400:
- return 176400;
- case (uint8_t)AudioStreamRate::VIRTIO_SND_PCM_RATE_192000:
- return 192000;
- case (uint8_t)AudioStreamRate::VIRTIO_SND_PCM_RATE_384000:
- return 384000;
- default:
- LOG(ERROR) << "Unknown virtio-snd sample rate: " << virtio_rate;
- return -1;
- }
-}
-
-} // namespace
-
-AudioHandler::AudioHandler(
- std::unique_ptr<AudioServer> audio_server,
- std::shared_ptr<webrtc_streaming::AudioSink> audio_sink,
- std::shared_ptr<webrtc_streaming::AudioSource> audio_source)
- : audio_sink_(audio_sink),
- audio_server_(std::move(audio_server)),
- stream_descs_(NUM_STREAMS),
- audio_source_(audio_source) {}
-
-void AudioHandler::Start() {
- server_thread_ = std::thread([this]() { Loop(); });
-}
-
-[[noreturn]] void AudioHandler::Loop() {
- for (;;) {
- auto audio_client = audio_server_->AcceptClient(
- NUM_STREAMS, 0 /* num_jacks, */, 0 /* num_chmaps, */,
- 262144 /* tx_shm_len */, 262144 /* rx_shm_len */);
- CHECK(audio_client) << "Failed to create audio client connection instance";
-
- std::thread playback_thread([this, &audio_client]() {
- while (audio_client->ReceivePlayback(*this)) {
- }
- });
- std::thread capture_thread([this, &audio_client]() {
- while (audio_client->ReceiveCapture(*this)) {
- }
- });
- // Wait for the client to do something
- while (audio_client->ReceiveCommands(*this)) {
- }
- playback_thread.join();
- capture_thread.join();
- }
-}
-
-void AudioHandler::StreamsInfo(StreamInfoCommand& cmd) {
- if (cmd.start_id() >= NUM_STREAMS ||
- cmd.start_id() + cmd.count() > NUM_STREAMS) {
- cmd.Reply(AudioStatus::VIRTIO_SND_S_BAD_MSG, {});
- return;
- }
- std::vector<virtio_snd_pcm_info> stream_info(
- &STREAMS[cmd.start_id()], &STREAMS[0] + cmd.start_id() + cmd.count());
- cmd.Reply(AudioStatus::VIRTIO_SND_S_OK, stream_info);
-}
-
-void AudioHandler::SetStreamParameters(StreamSetParamsCommand& cmd) {
- if (cmd.stream_id() >= NUM_STREAMS) {
- cmd.Reply(AudioStatus::VIRTIO_SND_S_BAD_MSG);
- return;
- }
- const auto& stream_info = STREAMS[cmd.stream_id()];
- auto bits_per_sample = BitsPerSample(cmd.format());
- auto sample_rate = SampleRate(cmd.rate());
- auto channels = cmd.channels();
- if (bits_per_sample < 0 || sample_rate < 0 ||
- channels < stream_info.channels_min ||
- channels > stream_info.channels_max) {
- cmd.Reply(AudioStatus::VIRTIO_SND_S_BAD_MSG);
- return;
- }
- {
- std::lock_guard<std::mutex> lock(stream_descs_[cmd.stream_id()].mtx);
- stream_descs_[cmd.stream_id()].bits_per_sample = bits_per_sample;
- stream_descs_[cmd.stream_id()].sample_rate = sample_rate;
- stream_descs_[cmd.stream_id()].channels = channels;
- auto len10ms = (channels * (sample_rate / 100) * bits_per_sample) / 8;
- stream_descs_[cmd.stream_id()].buffer.Reset(len10ms);
- }
- cmd.Reply(AudioStatus::VIRTIO_SND_S_OK);
-}
-
-void AudioHandler::PrepareStream(StreamControlCommand& cmd) {
- if (cmd.stream_id() >= NUM_STREAMS) {
- cmd.Reply(AudioStatus::VIRTIO_SND_S_BAD_MSG);
- return;
- }
- cmd.Reply(AudioStatus::VIRTIO_SND_S_OK);
-}
-
-void AudioHandler::ReleaseStream(StreamControlCommand& cmd) {
- if (cmd.stream_id() >= NUM_STREAMS) {
- cmd.Reply(AudioStatus::VIRTIO_SND_S_BAD_MSG);
- return;
- }
- cmd.Reply(AudioStatus::VIRTIO_SND_S_OK);
-}
-
-void AudioHandler::StartStream(StreamControlCommand& cmd) {
- if (cmd.stream_id() >= NUM_STREAMS) {
- cmd.Reply(AudioStatus::VIRTIO_SND_S_BAD_MSG);
- return;
- }
- stream_descs_[cmd.stream_id()].active = true;
- cmd.Reply(AudioStatus::VIRTIO_SND_S_OK);
-}
-
-void AudioHandler::StopStream(StreamControlCommand& cmd) {
- if (cmd.stream_id() >= NUM_STREAMS) {
- cmd.Reply(AudioStatus::VIRTIO_SND_S_BAD_MSG);
- return;
- }
- stream_descs_[cmd.stream_id()].active = false;
- cmd.Reply(AudioStatus::VIRTIO_SND_S_OK);
-}
-
-void AudioHandler::OnPlaybackBuffer(TxBuffer buffer) {
- auto stream_id = buffer.stream_id();
- auto& stream_desc = stream_descs_[stream_id];
- {
- std::lock_guard<std::mutex> lock(stream_desc.mtx);
- auto& holding_buffer = stream_descs_[stream_id].buffer;
- // Invalid or capture streams shouldn't send tx buffers
- if (stream_id >= NUM_STREAMS || IsCapture(stream_id)) {
- buffer.SendStatus(AudioStatus::VIRTIO_SND_S_BAD_MSG, 0, 0);
- return;
- }
- // A buffer may be received for an inactive stream if we were slow to
- // process it and the other side stopped the stream. Quitely ignore it in
- // that case
- if (!stream_desc.active) {
- buffer.SendStatus(AudioStatus::VIRTIO_SND_S_OK, 0, buffer.len());
- return;
- }
- // Webrtc will silently ignore any buffer with a length different than 10ms,
- // so we must split any buffer bigger than that and temporarily store any
- // remaining frames that are less than that size.
- auto current_time = rtc::TimeMillis();
- // The timestamp of the first 10ms chunk to be sent so that the last one
- // will have the current time
- auto base_time =
- current_time - ((buffer.len() - 1) / holding_buffer.buffer.size()) * 10;
- // number of frames in a 10 ms buffer
- const int frames = stream_desc.sample_rate / 100;
- size_t pos = 0;
- while (pos < buffer.len()) {
- if (holding_buffer.empty() &&
- buffer.len() - pos >= holding_buffer.buffer.size()) {
- // Avoid the extra copy into holding buffer
- // This casts away volatility of the pointer, necessary because the
- // webrtc api doesn't expect volatile memory. This should be safe though
- // because webrtc will use the contents of the buffer before returning
- // and only then we release it.
- auto audio_frame_buffer = std::make_shared<CvdAudioFrameBuffer>(
- const_cast<const uint8_t*>(&buffer.get()[pos]),
- stream_desc.bits_per_sample, stream_desc.sample_rate,
- stream_desc.channels, frames);
- audio_sink_->OnFrame(audio_frame_buffer, base_time);
- pos += holding_buffer.buffer.size();
- } else {
- pos += holding_buffer.Add(buffer.get() + pos, buffer.len() - pos);
- if (holding_buffer.full()) {
- auto buffer_ptr = const_cast<const uint8_t*>(holding_buffer.data());
- auto audio_frame_buffer = std::make_shared<CvdAudioFrameBuffer>(
- buffer_ptr, stream_desc.bits_per_sample,
- stream_desc.sample_rate, stream_desc.channels, frames);
- audio_sink_->OnFrame(audio_frame_buffer, base_time);
- holding_buffer.count = 0;
- }
- }
- base_time += 10;
- }
- }
- buffer.SendStatus(AudioStatus::VIRTIO_SND_S_OK, 0, buffer.len());
-}
-
-void AudioHandler::OnCaptureBuffer(RxBuffer buffer) {
- auto stream_id = buffer.stream_id();
- auto& stream_desc = stream_descs_[stream_id];
- {
- std::lock_guard<std::mutex> lock(stream_desc.mtx);
- // Invalid or playback streams shouldn't send rx buffers
- if (stream_id >= NUM_STREAMS || !IsCapture(stream_id)) {
- LOG(ERROR) << "Received capture buffers on playback stream " << stream_id;
- buffer.SendStatus(AudioStatus::VIRTIO_SND_S_BAD_MSG, 0, 0);
- return;
- }
- // A buffer may be received for an inactive stream if we were slow to
- // process it and the other side stopped the stream. Quitely ignore it in
- // that case
- if (!stream_desc.active) {
- buffer.SendStatus(AudioStatus::VIRTIO_SND_S_OK, 0, buffer.len());
- return;
- }
- auto bytes_per_sample = stream_desc.bits_per_sample / 8;
- auto samples_per_channel =
- buffer.len() / stream_desc.channels / bytes_per_sample;
- bool muted = false;
- auto res = audio_source_->GetMoreAudioData(
- const_cast<uint8_t*>(buffer.get()), bytes_per_sample,
- samples_per_channel, stream_desc.channels, stream_desc.sample_rate,
- muted);
- if (res < 0) {
- // This is likely a recoverable error, log the error but don't let the VMM
- // know about it so that it doesn't crash.
- LOG(ERROR) << "Failed to receive audio data from client";
- }
- }
- buffer.SendStatus(AudioStatus::VIRTIO_SND_S_OK, 0, buffer.len());
-}
-
-void AudioHandler::HoldingBuffer::Reset(size_t size) {
- buffer.resize(size);
- count = 0;
-}
-
-size_t AudioHandler::HoldingBuffer::Add(const volatile uint8_t* data,
- size_t max_len) {
- auto added_len = std::min(max_len, buffer.size() - count);
- std::copy(data, data + added_len, &buffer[count]);
- count += added_len;
- return added_len;
-}
-
-bool AudioHandler::HoldingBuffer::empty() const { return count == 0; }
-
-bool AudioHandler::HoldingBuffer::full() const {
- return count == buffer.size();
-}
-
-uint8_t* AudioHandler::HoldingBuffer::data() { return buffer.data(); }
-
-} // namespace cuttlefish
diff --git a/host/frontend/webrtc/audio_handler.h b/host/frontend/webrtc/audio_handler.h
deleted file mode 100644
index 380205292..000000000
--- a/host/frontend/webrtc/audio_handler.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2020 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 <memory>
-#include <mutex>
-#include <thread>
-#include <vector>
-
-#include "host/frontend/webrtc/lib/audio_sink.h"
-#include "host/frontend/webrtc/lib/audio_source.h"
-#include "host/libs/audio_connector/server.h"
-
-namespace cuttlefish {
-class AudioHandler : public AudioServerExecutor {
- // TODO(jemoreira): This can probably be avoided if playback goes through the
- // audio device instead.
- struct HoldingBuffer {
- std::vector<uint8_t> buffer;
- size_t count;
-
- void Reset(size_t size);
- size_t Add(const volatile uint8_t* data, size_t max_len);
- bool empty() const;
- bool full() const;
- uint8_t* data();
- };
- struct StreamDesc {
- std::mutex mtx;
- int bits_per_sample = -1;
- int sample_rate = -1;
- int channels = -1;
- bool active = false;
- HoldingBuffer buffer;
- };
-
- public:
- AudioHandler(std::unique_ptr<AudioServer> audio_server,
- std::shared_ptr<webrtc_streaming::AudioSink> audio_sink,
- std::shared_ptr<webrtc_streaming::AudioSource> audio_source);
- ~AudioHandler() override = default;
-
- void Start();
-
- // AudioServerExecutor implementation
- void StreamsInfo(StreamInfoCommand& cmd) override;
- void SetStreamParameters(StreamSetParamsCommand& cmd) override;
- void PrepareStream(StreamControlCommand& cmd) override;
- void ReleaseStream(StreamControlCommand& cmd) override;
- void StartStream(StreamControlCommand& cmd) override;
- void StopStream(StreamControlCommand& cmd) override;
-
- void OnPlaybackBuffer(TxBuffer buffer) override;
- void OnCaptureBuffer(RxBuffer buffer) override;
-
- private:
- [[noreturn]] void Loop();
-
- std::shared_ptr<webrtc_streaming::AudioSink> audio_sink_;
- std::unique_ptr<AudioServer> audio_server_;
- std::thread server_thread_;
- std::vector<StreamDesc> stream_descs_ = {};
- std::shared_ptr<webrtc_streaming::AudioSource> audio_source_;
-};
-} // namespace cuttlefish
diff --git a/host/frontend/webrtc/bluetooth_handler.cpp b/host/frontend/webrtc/bluetooth_handler.cpp
deleted file mode 100644
index 219c36e96..000000000
--- a/host/frontend/webrtc/bluetooth_handler.cpp
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (C) 2021 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 "host/frontend/webrtc/bluetooth_handler.h"
-
-#include <unistd.h>
-
-#include <android-base/logging.h>
-
-using namespace android;
-
-namespace cuttlefish {
-namespace webrtc_streaming {
-
-BluetoothHandler::BluetoothHandler(
- const int rootCanalTestPort,
- std::function<void(const uint8_t *, size_t)> send_to_client)
- : send_to_client_(send_to_client),
- rootcanal_socket_(
- SharedFD::SocketLocalClient(rootCanalTestPort, SOCK_STREAM)),
- shutdown_(SharedFD::Event(0, 0)) {
- std::thread loop([this]() { ReadLoop(); });
- read_thread_.swap(loop);
-}
-
-BluetoothHandler::~BluetoothHandler() {
- // Send a message to the looper to shut down.
- uint64_t v = 1;
- shutdown_->Write(&v, sizeof(v));
- // Shut down the socket as well. Not strictly necessary.
- rootcanal_socket_->Shutdown(SHUT_RDWR);
- read_thread_.join();
-}
-
-void BluetoothHandler::ReadLoop() {
- while (1) {
- uint8_t buffer[4096];
-
- read_set_.Set(shutdown_);
- read_set_.Set(rootcanal_socket_);
- Select(&read_set_, nullptr, nullptr, nullptr);
-
- if (read_set_.IsSet(rootcanal_socket_)) {
- auto read = rootcanal_socket_->Read(buffer, sizeof(buffer));
- if (read < 0) {
- PLOG(ERROR) << "Error on reading from RootCanal socket.";
- break;
- }
- if (read) {
- send_to_client_(buffer, read);
- }
- }
-
- if (read_set_.IsSet(shutdown_)) {
- LOG(INFO) << "BluetoothHandler is shutting down.";
- break;
- }
- }
-}
-
-void BluetoothHandler::handleMessage(const uint8_t *msg, size_t len) {
- size_t sent = 0;
- while (sent < len) {
- auto this_sent = rootcanal_socket_->Write(&msg[sent], len - sent);
- if (this_sent < 0) {
- PLOG(FATAL) << "Error writing to rootcanal socket.";
- return;
- }
- sent += this_sent;
- }
-}
-
-} // namespace webrtc_streaming
-} // namespace cuttlefish
diff --git a/host/frontend/webrtc/bluetooth_handler.h b/host/frontend/webrtc/bluetooth_handler.h
deleted file mode 100644
index 72248cf8b..000000000
--- a/host/frontend/webrtc/bluetooth_handler.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2021 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 <memory>
-#include <thread>
-
-#include "common/libs/fs/shared_fd.h"
-#include "common/libs/fs/shared_select.h"
-
-namespace cuttlefish {
-namespace webrtc_streaming {
-
-struct BluetoothHandler {
- explicit BluetoothHandler(
- const int rootCanalTestPort,
- std::function<void(const uint8_t *, size_t)> send_to_client);
-
- ~BluetoothHandler();
-
- void handleMessage(const uint8_t *msg, size_t len);
-
- private:
- std::function<void(const uint8_t *, size_t)> send_to_client_;
-
- void ReadLoop();
-
- SharedFD rootcanal_socket_;
- SharedFD shutdown_;
- SharedFDSet read_set_;
- std::thread read_thread_;
-};
-
-} // namespace webrtc_streaming
-} // namespace cuttlefish
diff --git a/host/frontend/webrtc/connection_observer.cpp b/host/frontend/webrtc/connection_observer.cpp
deleted file mode 100644
index 9f1154455..000000000
--- a/host/frontend/webrtc/connection_observer.cpp
+++ /dev/null
@@ -1,470 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "ConnectionObserver"
-
-#include "host/frontend/webrtc/connection_observer.h"
-
-#include <linux/input.h>
-
-#include <chrono>
-#include <map>
-#include <set>
-#include <thread>
-#include <vector>
-
-#include <json/json.h>
-
-#include <android-base/logging.h>
-#include <gflags/gflags.h>
-
-#include "common/libs/confui/confui.h"
-#include "common/libs/fs/shared_buf.h"
-#include "host/frontend/webrtc/adb_handler.h"
-#include "host/frontend/webrtc/bluetooth_handler.h"
-#include "host/frontend/webrtc/lib/utils.h"
-#include "host/libs/config/cuttlefish_config.h"
-
-DECLARE_bool(write_virtio_input);
-
-namespace cuttlefish {
-
-// TODO (b/147511234): de-dup this from vnc server and here
-struct virtio_input_event {
- uint16_t type;
- uint16_t code;
- int32_t value;
-};
-
-struct multitouch_slot {
- int32_t id;
- int32_t slot;
- int32_t x;
- int32_t y;
-};
-
-struct InputEventBuffer {
- virtual ~InputEventBuffer() = default;
- virtual void AddEvent(uint16_t type, uint16_t code, int32_t value) = 0;
- virtual size_t size() const = 0;
- virtual const void *data() const = 0;
-};
-
-template <typename T>
-struct InputEventBufferImpl : public InputEventBuffer {
- InputEventBufferImpl() {
- buffer_.reserve(6); // 6 is usually enough
- }
- void AddEvent(uint16_t type, uint16_t code, int32_t value) override {
- buffer_.push_back({.type = type, .code = code, .value = value});
- }
- T *data() { return buffer_.data(); }
- const void *data() const override { return buffer_.data(); }
- std::size_t size() const override { return buffer_.size() * sizeof(T); }
-
- private:
- std::vector<T> buffer_;
-};
-
-// TODO: we could add an arg here to specify whether we want the multitouch buffer?
-std::unique_ptr<InputEventBuffer> GetEventBuffer() {
- if (FLAGS_write_virtio_input) {
- return std::unique_ptr<InputEventBuffer>(
- new InputEventBufferImpl<virtio_input_event>());
- } else {
- return std::unique_ptr<InputEventBuffer>(
- new InputEventBufferImpl<input_event>());
- }
-}
-
-/**
- * connection observer implementation for regular android mode.
- * i.e. when it is not in the confirmation UI mode (or TEE),
- * the control flow will fall back to this ConnectionObserverForAndroid
- */
-class ConnectionObserverForAndroid
- : public cuttlefish::webrtc_streaming::ConnectionObserver {
- public:
- ConnectionObserverForAndroid(
- cuttlefish::InputSockets &input_sockets,
- cuttlefish::KernelLogEventsHandler *kernel_log_events_handler,
- std::map<std::string, cuttlefish::SharedFD>
- commands_to_custom_action_servers,
- std::weak_ptr<DisplayHandler> display_handler)
- : input_sockets_(input_sockets),
- kernel_log_events_handler_(kernel_log_events_handler),
- commands_to_custom_action_servers_(commands_to_custom_action_servers),
- weak_display_handler_(display_handler) {}
- virtual ~ConnectionObserverForAndroid() {
- auto display_handler = weak_display_handler_.lock();
- if (display_handler) {
- display_handler->DecClientCount();
- }
- if (kernel_log_subscription_id_ != -1) {
- kernel_log_events_handler_->Unsubscribe(kernel_log_subscription_id_);
- }
- }
-
- void OnConnected(std::function<void(const uint8_t *, size_t, bool)>
- /*ctrl_msg_sender*/) override {
- auto display_handler = weak_display_handler_.lock();
- if (display_handler) {
- display_handler->IncClientCount();
- std::thread th([this]() {
- // The encoder in libwebrtc won't drop 5 consecutive frames due to frame
- // size, so we make sure at least 5 frames are sent every time a client
- // connects to ensure they receive at least one.
- constexpr int kNumFrames = 5;
- constexpr int kMillisPerFrame = 16;
- for (int i = 0; i < kNumFrames; ++i) {
- auto display_handler = weak_display_handler_.lock();
- display_handler->SendLastFrame();
- if (i < kNumFrames - 1) {
- std::this_thread::sleep_for(std::chrono::milliseconds(kMillisPerFrame));
- }
- }
- });
- th.detach();
- }
- }
-
- void OnTouchEvent(const std::string & /*display_label*/, int x, int y,
- bool down) override {
-
- auto buffer = GetEventBuffer();
- if (!buffer) {
- LOG(ERROR) << "Failed to allocate event buffer";
- return;
- }
- buffer->AddEvent(EV_ABS, ABS_X, x);
- buffer->AddEvent(EV_ABS, ABS_Y, y);
- buffer->AddEvent(EV_KEY, BTN_TOUCH, down);
- buffer->AddEvent(EV_SYN, SYN_REPORT, 0);
- cuttlefish::WriteAll(input_sockets_.touch_client,
- reinterpret_cast<const char *>(buffer->data()),
- buffer->size());
- }
-
- void OnMultiTouchEvent(const std::string & /*display_label*/, Json::Value id,
- Json::Value slot, Json::Value x, Json::Value y,
- bool down, int size) override {
-
- auto buffer = GetEventBuffer();
- if (!buffer) {
- LOG(ERROR) << "Failed to allocate event buffer";
- return;
- }
-
- for (int i=0; i<size; i++) {
- auto this_slot = slot[i].asInt();
- auto this_id = id[i].asInt();
- auto this_x = x[i].asInt();
- auto this_y = y[i].asInt();
- buffer->AddEvent(EV_ABS, ABS_MT_SLOT, this_slot);
- if (down) {
- bool is_new = active_touch_slots_.insert(this_slot).second;
- if (is_new) {
- buffer->AddEvent(EV_ABS, ABS_MT_TRACKING_ID, this_id);
- if (active_touch_slots_.size() == 1) {
- buffer->AddEvent(EV_KEY, BTN_TOUCH, 1);
- }
- }
- buffer->AddEvent(EV_ABS, ABS_MT_POSITION_X, this_x);
- buffer->AddEvent(EV_ABS, ABS_MT_POSITION_Y, this_y);
- // send ABS_X and ABS_Y for single-touch compatibility
- buffer->AddEvent(EV_ABS, ABS_X, this_x);
- buffer->AddEvent(EV_ABS, ABS_Y, this_y);
- } else {
- // released touch
- buffer->AddEvent(EV_ABS, ABS_MT_TRACKING_ID, this_id);
- active_touch_slots_.erase(this_slot);
- if (active_touch_slots_.empty()) {
- buffer->AddEvent(EV_KEY, BTN_TOUCH, 0);
- }
- }
- }
-
- buffer->AddEvent(EV_SYN, SYN_REPORT, 0);
- cuttlefish::WriteAll(input_sockets_.touch_client,
- reinterpret_cast<const char *>(buffer->data()),
- buffer->size());
- }
-
- void OnKeyboardEvent(uint16_t code, bool down) override {
- auto buffer = GetEventBuffer();
- if (!buffer) {
- LOG(ERROR) << "Failed to allocate event buffer";
- return;
- }
- buffer->AddEvent(EV_KEY, code, down);
- buffer->AddEvent(EV_SYN, SYN_REPORT, 0);
- cuttlefish::WriteAll(input_sockets_.keyboard_client,
- reinterpret_cast<const char *>(buffer->data()),
- buffer->size());
- }
-
- void OnSwitchEvent(uint16_t code, bool state) override {
- auto buffer = GetEventBuffer();
- if (!buffer) {
- LOG(ERROR) << "Failed to allocate event buffer";
- return;
- }
- buffer->AddEvent(EV_SW, code, state);
- buffer->AddEvent(EV_SYN, SYN_REPORT, 0);
- cuttlefish::WriteAll(input_sockets_.switches_client,
- reinterpret_cast<const char *>(buffer->data()),
- buffer->size());
- }
-
- void OnAdbChannelOpen(std::function<bool(const uint8_t *, size_t)>
- adb_message_sender) override {
- LOG(VERBOSE) << "Adb Channel open";
- adb_handler_.reset(new cuttlefish::webrtc_streaming::AdbHandler(
- cuttlefish::CuttlefishConfig::Get()
- ->ForDefaultInstance()
- .adb_ip_and_port(),
- adb_message_sender));
- }
- void OnAdbMessage(const uint8_t *msg, size_t size) override {
- adb_handler_->handleMessage(msg, size);
- }
- void OnControlChannelOpen(std::function<bool(const Json::Value)>
- control_message_sender) override {
- LOG(VERBOSE) << "Control Channel open";
- kernel_log_subscription_id_ =
- kernel_log_events_handler_->AddSubscriber(control_message_sender);
- }
- void OnControlMessage(const uint8_t* msg, size_t size) override {
- Json::Value evt;
- const char* msg_str = reinterpret_cast<const char*>(msg);
- Json::CharReaderBuilder builder;
- std::unique_ptr<Json::CharReader> json_reader(builder.newCharReader());
- std::string errorMessage;
- if (!json_reader->parse(msg_str, msg_str + size, &evt, &errorMessage)) {
- LOG(ERROR) << "Received invalid JSON object over control channel: " << errorMessage;
- return;
- }
-
- auto result = webrtc_streaming::ValidationResult::ValidateJsonObject(
- evt, "command",
- /*required_fields=*/{{"command", Json::ValueType::stringValue}},
- /*optional_fields=*/
- {
- {"button_state", Json::ValueType::stringValue},
- {"lid_switch_open", Json::ValueType::booleanValue},
- {"hinge_angle_value", Json::ValueType::intValue},
- });
- if (!result.ok()) {
- LOG(ERROR) << result.error();
- return;
- }
- auto command = evt["command"].asString();
-
- if (command == "device_state") {
- if (evt.isMember("lid_switch_open")) {
- // InputManagerService treats a value of 0 as open and 1 as closed, so
- // invert the lid_switch_open value that is sent to the input device.
- OnSwitchEvent(SW_LID, !evt["lid_switch_open"].asBool());
- }
- if (evt.isMember("hinge_angle_value")) {
- // TODO(b/181157794) Propagate hinge angle sensor data using a custom
- // Sensor HAL.
- }
- return;
- }
-
- auto button_state = evt["button_state"].asString();
- LOG(VERBOSE) << "Control command: " << command << " (" << button_state
- << ")";
- if (command == "power") {
- OnKeyboardEvent(KEY_POWER, button_state == "down");
- } else if (command == "home") {
- OnKeyboardEvent(KEY_HOMEPAGE, button_state == "down");
- } else if (command == "menu") {
- OnKeyboardEvent(KEY_MENU, button_state == "down");
- } else if (command == "volumemute") {
- OnKeyboardEvent(KEY_MUTE, button_state == "down");
- } else if (command == "volumedown") {
- OnKeyboardEvent(KEY_VOLUMEDOWN, button_state == "down");
- } else if (command == "volumeup") {
- OnKeyboardEvent(KEY_VOLUMEUP, button_state == "down");
- } else if (commands_to_custom_action_servers_.find(command) !=
- commands_to_custom_action_servers_.end()) {
- // Simple protocol for commands forwarded to action servers:
- // - Always 128 bytes
- // - Format: command:button_state
- // - Example: my_button:down
- std::string action_server_message = command + ":" + button_state;
- cuttlefish::WriteAll(commands_to_custom_action_servers_[command],
- action_server_message.c_str(), 128);
- } else {
- LOG(WARNING) << "Unsupported control command: " << command << " ("
- << button_state << ")";
- }
- }
-
- void OnBluetoothChannelOpen(std::function<bool(const uint8_t *, size_t)>
- bluetooth_message_sender) override {
- LOG(VERBOSE) << "Bluetooth channel open";
- bluetooth_handler_.reset(new cuttlefish::webrtc_streaming::BluetoothHandler(
- cuttlefish::CuttlefishConfig::Get()
- ->ForDefaultInstance()
- .rootcanal_test_port(),
- bluetooth_message_sender));
- }
-
- void OnBluetoothMessage(const uint8_t *msg, size_t size) override {
- bluetooth_handler_->handleMessage(msg, size);
- }
-
- private:
- cuttlefish::InputSockets& input_sockets_;
- cuttlefish::KernelLogEventsHandler* kernel_log_events_handler_;
- int kernel_log_subscription_id_ = -1;
- std::shared_ptr<cuttlefish::webrtc_streaming::AdbHandler> adb_handler_;
- std::shared_ptr<cuttlefish::webrtc_streaming::BluetoothHandler>
- bluetooth_handler_;
- std::map<std::string, cuttlefish::SharedFD> commands_to_custom_action_servers_;
- std::weak_ptr<DisplayHandler> weak_display_handler_;
- std::set<int32_t> active_touch_slots_;
-};
-
-class ConnectionObserverDemuxer
- : public cuttlefish::webrtc_streaming::ConnectionObserver {
- public:
- ConnectionObserverDemuxer(
- /* params for the base class */
- cuttlefish::InputSockets &input_sockets,
- cuttlefish::KernelLogEventsHandler *kernel_log_events_handler,
- std::map<std::string, cuttlefish::SharedFD>
- commands_to_custom_action_servers,
- std::weak_ptr<DisplayHandler> display_handler,
- /* params for this class */
- cuttlefish::confui::HostVirtualInput &confui_input)
- : android_input_(input_sockets, kernel_log_events_handler,
- commands_to_custom_action_servers, display_handler),
- confui_input_{confui_input} {}
- virtual ~ConnectionObserverDemuxer() = default;
-
- void OnConnected(std::function<void(const uint8_t *, size_t, bool)>
- ctrl_msg_sender) override {
- android_input_.OnConnected(ctrl_msg_sender);
- }
-
- void OnTouchEvent(const std::string &label, int x, int y,
- bool down) override {
- if (confui_input_.IsConfUiActive()) {
- ConfUiLog(DEBUG) << "touch event ignored in confirmation UI mode";
- return;
- }
- android_input_.OnTouchEvent(label, x, y, down);
- }
-
- void OnMultiTouchEvent(const std::string &label, Json::Value id,
- Json::Value slot, Json::Value x, Json::Value y,
- bool down, int size) override {
- if (confui_input_.IsConfUiActive()) {
- ConfUiLog(DEBUG) << "multi-touch event ignored in confirmation UI mode";
- return;
- }
- android_input_.OnMultiTouchEvent(label, id, slot, x, y, down, size);
- }
-
- void OnKeyboardEvent(uint16_t code, bool down) override {
- if (confui_input_.IsConfUiActive()) {
- switch (code) {
- case KEY_POWER:
- confui_input_.PressConfirmButton(down);
- break;
- case KEY_MENU:
- confui_input_.PressCancelButton(down);
- break;
- default:
- ConfUiLog(DEBUG) << "key" << code
- << "is ignored in confirmation UI mode";
- break;
- }
- return;
- }
- android_input_.OnKeyboardEvent(code, down);
- }
-
- void OnSwitchEvent(uint16_t code, bool state) override {
- android_input_.OnSwitchEvent(code, state);
- }
-
- void OnAdbChannelOpen(std::function<bool(const uint8_t *, size_t)>
- adb_message_sender) override {
- android_input_.OnAdbChannelOpen(adb_message_sender);
- }
-
- void OnAdbMessage(const uint8_t *msg, size_t size) override {
- android_input_.OnAdbMessage(msg, size);
- }
-
- void OnControlChannelOpen(
- std::function<bool(const Json::Value)> control_message_sender) override {
- android_input_.OnControlChannelOpen(control_message_sender);
- }
-
- void OnControlMessage(const uint8_t *msg, size_t size) override {
- android_input_.OnControlMessage(msg, size);
- }
-
- void OnBluetoothChannelOpen(std::function<bool(const uint8_t *, size_t)>
- bluetooth_message_sender) override {
- android_input_.OnBluetoothChannelOpen(bluetooth_message_sender);
- }
-
- void OnBluetoothMessage(const uint8_t *msg, size_t size) override {
- android_input_.OnBluetoothMessage(msg, size);
- }
-
- private:
- ConnectionObserverForAndroid android_input_;
- cuttlefish::confui::HostVirtualInput &confui_input_;
-};
-
-CfConnectionObserverFactory::CfConnectionObserverFactory(
- cuttlefish::InputSockets &input_sockets,
- cuttlefish::KernelLogEventsHandler* kernel_log_events_handler,
- cuttlefish::confui::HostVirtualInput &confui_input)
- : input_sockets_(input_sockets),
- kernel_log_events_handler_(kernel_log_events_handler),
- confui_input_{confui_input} {}
-
-std::shared_ptr<cuttlefish::webrtc_streaming::ConnectionObserver>
-CfConnectionObserverFactory::CreateObserver() {
- return std::shared_ptr<cuttlefish::webrtc_streaming::ConnectionObserver>(
- new ConnectionObserverDemuxer(input_sockets_, kernel_log_events_handler_,
- commands_to_custom_action_servers_,
- weak_display_handler_, confui_input_));
-}
-
-void CfConnectionObserverFactory::AddCustomActionServer(
- cuttlefish::SharedFD custom_action_server_fd,
- const std::vector<std::string>& commands) {
- for (const std::string& command : commands) {
- LOG(DEBUG) << "Action server is listening to command: " << command;
- commands_to_custom_action_servers_[command] = custom_action_server_fd;
- }
-}
-
-void CfConnectionObserverFactory::SetDisplayHandler(
- std::weak_ptr<DisplayHandler> display_handler) {
- weak_display_handler_ = display_handler;
-}
-} // namespace cuttlefish
diff --git a/host/frontend/webrtc/connection_observer.h b/host/frontend/webrtc/connection_observer.h
deleted file mode 100644
index abf18842e..000000000
--- a/host/frontend/webrtc/connection_observer.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2020 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 <map>
-#include <memory>
-
-#include "common/libs/fs/shared_fd.h"
-#include "host/frontend/webrtc/display_handler.h"
-#include "host/frontend/webrtc/kernel_log_events_handler.h"
-#include "host/frontend/webrtc/lib/connection_observer.h"
-#include "host/libs/confui/host_virtual_input.h"
-
-namespace cuttlefish {
-
-struct InputSockets {
- SharedFD touch_server;
- SharedFD touch_client;
- SharedFD keyboard_server;
- SharedFD keyboard_client;
- SharedFD switches_server;
- SharedFD switches_client;
-};
-
-class CfConnectionObserverFactory
- : public webrtc_streaming::ConnectionObserverFactory {
- public:
- CfConnectionObserverFactory(
- cuttlefish::InputSockets& input_sockets,
- KernelLogEventsHandler* kernel_log_events_handler,
- cuttlefish::confui::HostVirtualInput& confui_input);
- ~CfConnectionObserverFactory() override = default;
-
- std::shared_ptr<webrtc_streaming::ConnectionObserver> CreateObserver()
- override;
-
- void AddCustomActionServer(SharedFD custom_action_server_fd,
- const std::vector<std::string>& commands);
-
- void SetDisplayHandler(std::weak_ptr<DisplayHandler> display_handler);
-
- private:
- InputSockets& input_sockets_;
- KernelLogEventsHandler* kernel_log_events_handler_;
- std::map<std::string, SharedFD>
- commands_to_custom_action_servers_;
- std::weak_ptr<DisplayHandler> weak_display_handler_;
- cuttlefish::confui::HostVirtualInput& confui_input_;
-};
-
-} // namespace cuttlefish
diff --git a/host/frontend/webrtc/cvd_video_frame_buffer.cpp b/host/frontend/webrtc/cvd_video_frame_buffer.cpp
deleted file mode 100644
index 8d0aeea3e..000000000
--- a/host/frontend/webrtc/cvd_video_frame_buffer.cpp
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2020 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 "host/frontend/webrtc/cvd_video_frame_buffer.h"
-
-#include <map>
-#include <mutex>
-#include <vector>
-#include "common/libs/utils/size_utils.h"
-
-namespace cuttlefish {
-
-namespace {
-constexpr int kPlanePadding = 1024;
-constexpr int kLogAlignment = 6; // multiple of 2^6
-
-inline int AlignStride(int width) {
- return AlignToPowerOf2(width, kLogAlignment);
-}
-
-std::multimap<int, std::vector<uint8_t>> pool;
-std::mutex pool_mutex;
-std::vector<uint8_t> FromPool(int size) {
- {
- std::lock_guard<std::mutex> lock(pool_mutex);
- auto it = pool.find(size);
- if (it != pool.end()) {
- auto ret = std::move(it->second);
- pool.erase(it);
- return ret;
- }
- }
- return std::vector<uint8_t>(size);
-}
-
-void BackToPool(std::vector<uint8_t> item) {
- std::lock_guard<std::mutex> lock(pool_mutex);
- pool.insert({item.size(), std::move(item)});
-}
-
-} // namespace
-
-CvdVideoFrameBuffer::CvdVideoFrameBuffer(int width, int height)
- : width_(width),
- height_(height),
- y_(FromPool(AlignStride(width) * height + kPlanePadding)),
- u_(FromPool(AlignStride((width + 1) / 2) * ((height + 1) / 2) +
- kPlanePadding)),
- v_(FromPool(AlignStride((width + 1) / 2) * ((height + 1) / 2) +
- kPlanePadding)) {}
-
-CvdVideoFrameBuffer::~CvdVideoFrameBuffer() {
- BackToPool(std::move(y_));
- BackToPool(std::move(u_));
- BackToPool(std::move(v_));
-}
-
-int CvdVideoFrameBuffer::width() const { return width_; }
-int CvdVideoFrameBuffer::height() const { return height_; }
-
-int CvdVideoFrameBuffer::StrideY() const { return AlignStride(width_); }
-int CvdVideoFrameBuffer::StrideU() const {
- return AlignStride((width_ + 1) / 2);
-}
-int CvdVideoFrameBuffer::StrideV() const {
- return AlignStride((width_ + 1) / 2);
-}
-
-const uint8_t *CvdVideoFrameBuffer::DataY() const { return y_.data(); }
-const uint8_t *CvdVideoFrameBuffer::DataU() const { return u_.data(); }
-const uint8_t *CvdVideoFrameBuffer::DataV() const { return v_.data(); }
-
-} // namespace cuttlefish
diff --git a/host/frontend/webrtc/cvd_video_frame_buffer.h b/host/frontend/webrtc/cvd_video_frame_buffer.h
deleted file mode 100644
index 84b494605..000000000
--- a/host/frontend/webrtc/cvd_video_frame_buffer.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2020 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 <vector>
-
-#include "host/frontend/webrtc/lib/video_frame_buffer.h"
-
-namespace cuttlefish {
-
-class CvdVideoFrameBuffer : public webrtc_streaming::VideoFrameBuffer {
- public:
- CvdVideoFrameBuffer(int width, int height);
- CvdVideoFrameBuffer(CvdVideoFrameBuffer&& cvd_frame_buf) = default;
- CvdVideoFrameBuffer(const CvdVideoFrameBuffer& cvd_frame_buf) = default;
- CvdVideoFrameBuffer& operator=(CvdVideoFrameBuffer&& cvd_frame_buf) = default;
- CvdVideoFrameBuffer& operator=(const CvdVideoFrameBuffer& cvd_frame_buf) = default;
- CvdVideoFrameBuffer() = delete;
-
- ~CvdVideoFrameBuffer() override;
-
- int width() const override;
- int height() const override;
-
- int StrideY() const override;
- int StrideU() const override;
- int StrideV() const override;
-
- const uint8_t *DataY() const override;
- const uint8_t *DataU() const override;
- const uint8_t *DataV() const override;
-
- uint8_t *DataY() { return y_.data(); }
- uint8_t *DataU() { return u_.data(); }
- uint8_t *DataV() { return v_.data(); }
-
- private:
- const int width_;
- const int height_;
- std::vector<std::uint8_t> y_;
- std::vector<std::uint8_t> u_;
- std::vector<std::uint8_t> v_;
-};
-
-}
diff --git a/host/frontend/webrtc/display_handler.cpp b/host/frontend/webrtc/display_handler.cpp
deleted file mode 100644
index 1b3bfd84e..000000000
--- a/host/frontend/webrtc/display_handler.cpp
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright (C) 2020 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 "host/frontend/webrtc/display_handler.h"
-
-#include <chrono>
-#include <functional>
-#include <memory>
-
-#include <libyuv.h>
-
-namespace cuttlefish {
-DisplayHandler::DisplayHandler(
- std::shared_ptr<webrtc_streaming::VideoSink> display_sink,
- ScreenConnector& screen_connector)
- : display_sink_(display_sink), screen_connector_(screen_connector) {
- screen_connector_.SetCallback(std::move(GetScreenConnectorCallback()));
-}
-
-DisplayHandler::GenerateProcessedFrameCallback DisplayHandler::GetScreenConnectorCallback() {
- // only to tell the producer how to create a ProcessedFrame to cache into the queue
- DisplayHandler::GenerateProcessedFrameCallback callback =
- [](std::uint32_t display_number, std::uint8_t* frame_pixels,
- WebRtcScProcessedFrame& processed_frame) {
- processed_frame.display_number_ = display_number;
- // TODO(171305898): handle multiple displays.
- if (display_number != 0) {
- // BUG 186580833: display_number comes from surface_id in crosvm
- // create_surface from virtio_gpu.rs set_scanout. We cannot use it as
- // the display number. Either crosvm virtio-gpu is incorrectly ignoring
- // scanout id and instead using a monotonically increasing surface id
- // number as the scanout resource is replaced over time, or frontend code
- // here is incorrectly assuming surface id == display id.
- display_number = 0;
- }
- const int display_w =
- ScreenConnectorInfo::ScreenWidth(display_number);
- const int display_h =
- ScreenConnectorInfo::ScreenHeight(display_number);
- const int display_stride_bytes =
- ScreenConnectorInfo::ScreenStrideBytes(display_number);
- processed_frame.display_number_ = display_number;
- processed_frame.buf_ =
- std::make_unique<CvdVideoFrameBuffer>(display_w, display_h);
- libyuv::ABGRToI420(
- frame_pixels, display_stride_bytes, processed_frame.buf_->DataY(),
- processed_frame.buf_->StrideY(), processed_frame.buf_->DataU(),
- processed_frame.buf_->StrideU(), processed_frame.buf_->DataV(),
- processed_frame.buf_->StrideV(), display_w, display_h);
- processed_frame.is_success_ = true;
- };
- return callback;
-}
-
-[[noreturn]] void DisplayHandler::Loop() {
- for (;;) {
- auto processed_frame = screen_connector_.OnNextFrame();
- // processed_frame has display number from the guest
- {
- std::lock_guard<std::mutex> lock(last_buffer_mutex_);
- std::shared_ptr<CvdVideoFrameBuffer> buffer = std::move(processed_frame.buf_);
- last_buffer_ =
- std::static_pointer_cast<webrtc_streaming::VideoFrameBuffer>(buffer);
- }
- if (processed_frame.is_success_) {
- SendLastFrame();
- }
- }
-}
-
-void DisplayHandler::SendLastFrame() {
- std::shared_ptr<webrtc_streaming::VideoFrameBuffer> buffer;
- {
- std::lock_guard<std::mutex> lock(last_buffer_mutex_);
- buffer = last_buffer_;
- }
- if (!buffer) {
- // If a connection request arrives before the first frame is available don't
- // send any frame.
- return;
- }
- {
- // SendLastFrame can be called from multiple threads simultaneously, locking
- // here avoids injecting frames with the timestamps in the wrong order.
- std::lock_guard<std::mutex> lock(next_frame_mutex_);
- int64_t time_stamp =
- std::chrono::duration_cast<std::chrono::microseconds>(
- std::chrono::system_clock::now().time_since_epoch())
- .count();
- display_sink_->OnFrame(buffer, time_stamp);
- }
-}
-
-void DisplayHandler::IncClientCount() {
- client_count_++;
- if (client_count_ == 1) {
- screen_connector_.ReportClientsConnected(true);
- }
-}
-
-void DisplayHandler::DecClientCount() {
- client_count_--;
- if (client_count_ == 0) {
- screen_connector_.ReportClientsConnected(false);
- }
-}
-
-} // namespace cuttlefish
diff --git a/host/frontend/webrtc/display_handler.h b/host/frontend/webrtc/display_handler.h
deleted file mode 100644
index aed38a106..000000000
--- a/host/frontend/webrtc/display_handler.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2020 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 <mutex>
-#include <memory>
-
-#include "host/frontend/webrtc/cvd_video_frame_buffer.h"
-#include "host/frontend/webrtc/lib/video_sink.h"
-#include "host/libs/screen_connector/screen_connector.h"
-
-namespace cuttlefish {
-/**
- * ScreenConnectorImpl will generate this, and enqueue
- *
- * It's basically a (processed) frame, so it:
- * must be efficiently std::move-able
- * Also, for the sake of algorithm simplicity:
- * must be default-constructable & assignable
- *
- */
-struct WebRtcScProcessedFrame : public ScreenConnectorFrameInfo {
- // must support move semantic
- std::unique_ptr<CvdVideoFrameBuffer> buf_;
- std::unique_ptr<WebRtcScProcessedFrame> Clone() {
- // copy internal buffer, not move
- CvdVideoFrameBuffer* new_buffer = new CvdVideoFrameBuffer(*(buf_.get()));
- auto cloned_frame = std::make_unique<WebRtcScProcessedFrame>();
- cloned_frame->buf_ =
- std::move(std::unique_ptr<CvdVideoFrameBuffer>(new_buffer));
- return std::move(cloned_frame);
- }
-};
-
-class DisplayHandler {
- public:
- using ScreenConnector = cuttlefish::ScreenConnector<WebRtcScProcessedFrame>;
- using GenerateProcessedFrameCallback = ScreenConnector::GenerateProcessedFrameCallback;
-
- DisplayHandler(std::shared_ptr<webrtc_streaming::VideoSink> display_sink,
- ScreenConnector& screen_connector);
- ~DisplayHandler() = default;
-
- [[noreturn]] void Loop();
- void SendLastFrame();
-
- void IncClientCount();
- void DecClientCount();
-
- private:
- GenerateProcessedFrameCallback GetScreenConnectorCallback();
- std::shared_ptr<webrtc_streaming::VideoSink> display_sink_;
- ScreenConnector& screen_connector_;
- std::shared_ptr<webrtc_streaming::VideoFrameBuffer> last_buffer_;
- std::mutex last_buffer_mutex_;
- std::mutex next_frame_mutex_;
- int client_count_ = 0;
-};
-} // namespace cuttlefish
diff --git a/host/frontend/webrtc/kernel_log_events_handler.cpp b/host/frontend/webrtc/kernel_log_events_handler.cpp
deleted file mode 100644
index ca14e6f05..000000000
--- a/host/frontend/webrtc/kernel_log_events_handler.cpp
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (C) 2020 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 "host/frontend/webrtc/kernel_log_events_handler.h"
-
-#include <android-base/logging.h>
-
-#include <common/libs/fs/shared_select.h>
-#include <host/commands/kernel_log_monitor/kernel_log_server.h>
-#include <host/commands/kernel_log_monitor/utils.h>
-#include <host/libs/config/cuttlefish_config.h>
-
-using namespace android;
-
-namespace cuttlefish {
-
-KernelLogEventsHandler::KernelLogEventsHandler(
- SharedFD kernel_log_fd)
- : kernel_log_fd_(kernel_log_fd),
- eventfd_(SharedFD::Event()),
- running_(true),
- read_thread_([this]() { ReadLoop(); }) {}
-
-KernelLogEventsHandler::~KernelLogEventsHandler() {
- running_ = false;
- eventfd_->EventfdWrite(1);
- read_thread_.join();
-}
-
-void KernelLogEventsHandler::ReadLoop() {
- CHECK(eventfd_->IsOpen()) << "Failed to create event fd: "
- << eventfd_->StrError();
- while (running_) {
- SharedFDSet read_set;
- read_set.Set(eventfd_);
- read_set.Set(kernel_log_fd_);
- auto select_ret = Select(&read_set, nullptr, nullptr, nullptr);
- if (select_ret < 0) {
- LOG(ERROR) << "Error on select call";
- break;
- }
- if (read_set.IsSet(eventfd_)) {
- eventfd_t evt;
- (void)eventfd_->EventfdRead(&evt);
- if (!running_) {
- // There won't be anyone listening for kernel log events if the thread
- // was asked to stop, so break out of the loop without reading.
- break;
- }
- }
- if (read_set.IsSet(kernel_log_fd_)) {
- std::optional<monitor::ReadEventResult> read_result =
- monitor::ReadEvent(kernel_log_fd_);
- if (!read_result) {
- LOG(ERROR) << "Failed to read kernel log event: "
- << kernel_log_fd_->StrError();
- break;
- }
-
- if (read_result->event == monitor::Event::BootStarted) {
- Json::Value message;
- message["event"] = kBootStartedMessage;
- DeliverEvent(message);
- }
- if (read_result->event == monitor::Event::BootCompleted) {
- Json::Value message;
- message["event"] = kBootCompletedMessage;
- DeliverEvent(message);
- }
- if (read_result->event == monitor::Event::ScreenChanged) {
- Json::Value message;
- message["event"] = kScreenChangedMessage;
- message["metadata"] = read_result->metadata;
- DeliverEvent(message);
- }
- }
- }
-}
-
-int KernelLogEventsHandler::AddSubscriber(
- std::function<void(const Json::Value&)> subscriber) {
- std::lock_guard<std::mutex> lock(subscribers_mtx_);
- subscribers_[++last_subscriber_id_] = subscriber;
- return last_subscriber_id_;
-}
-
-void KernelLogEventsHandler::Unsubscribe(int subscriber_id) {
- std::lock_guard<std::mutex> lock(subscribers_mtx_);
- subscribers_.erase(subscriber_id);
-}
-
-void KernelLogEventsHandler::DeliverEvent(const Json::Value& event) {
- std::lock_guard<std::mutex> lock(subscribers_mtx_);
- for (const auto& entry : subscribers_) {
- entry.second(event);
- }
-}
-
-} // namespace cuttlefish
diff --git a/host/frontend/webrtc/kernel_log_events_handler.h b/host/frontend/webrtc/kernel_log_events_handler.h
deleted file mode 100644
index 5ce99aa36..000000000
--- a/host/frontend/webrtc/kernel_log_events_handler.h
+++ /dev/null
@@ -1,52 +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.
- */
-
-#pragma once
-
-#include <atomic>
-#include <memory>
-#include <mutex>
-#include <thread>
-#include <map>
-
-#include <json/json.h>
-
-#include "common/libs/fs/shared_fd.h"
-
-namespace cuttlefish {
-
-// Listen to kernel log events and report them to clients.
-struct KernelLogEventsHandler {
- explicit KernelLogEventsHandler(SharedFD kernel_log_fd);
-
- ~KernelLogEventsHandler();
-
- int AddSubscriber(std::function<void(const Json::Value&)> subscriber);
- void Unsubscribe(int subscriber_id);
- private:
- void ReadLoop();
- void DeliverEvent(const Json::Value& event);
-
- SharedFD kernel_log_fd_;
- SharedFD eventfd_;
- std::atomic<bool> running_;
- std::thread read_thread_;
- std::map<int, std::function<void(const Json::Value&)>> subscribers_;
- int last_subscriber_id_ = 0;
- std::mutex subscribers_mtx_;
-};
-
-} // namespace cuttlefish
diff --git a/host/frontend/webrtc/lib/audio_device.cpp b/host/frontend/webrtc/lib/audio_device.cpp
deleted file mode 100644
index 2d96f7230..000000000
--- a/host/frontend/webrtc/lib/audio_device.cpp
+++ /dev/null
@@ -1,247 +0,0 @@
-/*
- * Copyright (C) 2021 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 "host/frontend/webrtc/lib/audio_device.h"
-
-#include <string.h>
-
-#include <android-base/logging.h>
-
-#include <chrono>
-#include <thread>
-
-namespace cuttlefish {
-namespace webrtc_streaming {
-
-CfAudioDeviceModule::CfAudioDeviceModule() {}
-
-int CfAudioDeviceModule::GetMoreAudioData(void* data, int bytes_per_sample,
- int samples_per_channel,
- int num_channels, int sample_rate,
- bool& muted) {
- muted = !playing_ || !audio_callback_;
- if (muted) {
- return 0;
- }
-
- size_t read_samples;
- int64_t elapsed_time;
- int64_t ntp_time_ms;
- auto res = audio_callback_->NeedMorePlayData(
- samples_per_channel, bytes_per_sample, num_channels, sample_rate, data,
- read_samples, &elapsed_time, &ntp_time_ms);
- if (res != 0) {
- return res;
- }
- return read_samples / num_channels;
-}
-
-// Retrieve the currently utilized audio layer
-int32_t CfAudioDeviceModule::ActiveAudioLayer(AudioLayer* audioLayer) const {
- return -1;
-}
-
-// Full-duplex transportation of PCM audio
-int32_t CfAudioDeviceModule::RegisterAudioCallback(
- webrtc::AudioTransport* audio_callback) {
- audio_callback_ = audio_callback;
- return 0;
-}
-
-// Main initialization and termination
-int32_t CfAudioDeviceModule::Init() { return 0; }
-int32_t CfAudioDeviceModule::Terminate() { return 0; }
-bool CfAudioDeviceModule::Initialized() const { return true; }
-
-// Device enumeration
-int16_t CfAudioDeviceModule::PlayoutDevices() { return 1; }
-int16_t CfAudioDeviceModule::RecordingDevices() { return 1; }
-int32_t CfAudioDeviceModule::PlayoutDeviceName(
- uint16_t index, char name[webrtc::kAdmMaxDeviceNameSize],
- char guid[webrtc::kAdmMaxGuidSize]) {
- if (index != 0) {
- return -1;
- }
- constexpr auto device_name = "Cuttlefish Webrtc Audio";
- constexpr auto device_guid = "Cuttlefish Webrtc Audio Device Id";
- strncpy(name, device_name, webrtc::kAdmMaxDeviceNameSize);
- name[webrtc::kAdmMaxDeviceNameSize - 1] = '\0';
- strncpy(guid, device_guid, webrtc::kAdmMaxGuidSize);
- guid[webrtc::kAdmMaxGuidSize - 1] = '\0';
- return 0;
-}
-int32_t CfAudioDeviceModule::RecordingDeviceName(
- uint16_t index, char name[webrtc::kAdmMaxDeviceNameSize],
- char guid[webrtc::kAdmMaxGuidSize]) {
- if (index != 0) {
- return -1;
- }
- constexpr auto device_name = "Cuttlefish Webrtc Audio";
- constexpr auto device_guid = "Cuttlefish Webrtc Audio Device Id";
- strncpy(name, device_name, webrtc::kAdmMaxDeviceNameSize);
- name[webrtc::kAdmMaxDeviceNameSize - 1] = '\0';
- strncpy(guid, device_guid, webrtc::kAdmMaxGuidSize);
- guid[webrtc::kAdmMaxGuidSize - 1] = '\0';
- return 0;
-}
-
-// Device selection
-int32_t CfAudioDeviceModule::SetPlayoutDevice(uint16_t index) { return 0; }
-int32_t CfAudioDeviceModule::SetPlayoutDevice(WindowsDeviceType device) {
- return -1;
-}
-int32_t CfAudioDeviceModule::SetRecordingDevice(uint16_t index) { return 0; }
-int32_t CfAudioDeviceModule::SetRecordingDevice(WindowsDeviceType device) {
- return -1;
-}
-
-// Audio transport initialization
-int32_t CfAudioDeviceModule::PlayoutIsAvailable(bool* available) {
- *available = true;
- return 0;
-}
-int32_t CfAudioDeviceModule::InitPlayout() { return 0; }
-bool CfAudioDeviceModule::PlayoutIsInitialized() const { return true; }
-int32_t CfAudioDeviceModule::RecordingIsAvailable(bool* available) {
- *available = 0;
- return 0;
-}
-int32_t CfAudioDeviceModule::InitRecording() { return 0; }
-bool CfAudioDeviceModule::RecordingIsInitialized() const { return true; }
-
-// Audio transport control
-int32_t CfAudioDeviceModule::StartPlayout() {
- playing_ = true;
- return 0;
-}
-int32_t CfAudioDeviceModule::StopPlayout() {
- playing_ = false;
- return 0;
-}
-bool CfAudioDeviceModule::Playing() const { return playing_; }
-int32_t CfAudioDeviceModule::StartRecording() {
- recording_ = true;
- return 0;
-}
-int32_t CfAudioDeviceModule::StopRecording() {
- recording_ = false;
- return 0;
-}
-bool CfAudioDeviceModule::Recording() const { return recording_; }
-
-// Audio mixer initialization
-int32_t CfAudioDeviceModule::InitSpeaker() { return -1; }
-bool CfAudioDeviceModule::SpeakerIsInitialized() const { return false; }
-int32_t CfAudioDeviceModule::InitMicrophone() { return 0; }
-bool CfAudioDeviceModule::MicrophoneIsInitialized() const { return true; }
-
-// Speaker volume controls
-int32_t CfAudioDeviceModule::SpeakerVolumeIsAvailable(bool* available) {
- *available = false;
- return 0;
-}
-int32_t CfAudioDeviceModule::SetSpeakerVolume(uint32_t volume) { return -1; }
-int32_t CfAudioDeviceModule::SpeakerVolume(uint32_t* volume) const {
- return -1;
-}
-int32_t CfAudioDeviceModule::MaxSpeakerVolume(uint32_t* maxVolume) const {
- return -1;
-}
-int32_t CfAudioDeviceModule::MinSpeakerVolume(uint32_t* minVolume) const {
- return -1;
-}
-
-// Microphone volume controls
-int32_t CfAudioDeviceModule::MicrophoneVolumeIsAvailable(bool* available) {
- *available = false;
- return 0;
-}
-int32_t CfAudioDeviceModule::SetMicrophoneVolume(uint32_t volume) { return -1; }
-int32_t CfAudioDeviceModule::MicrophoneVolume(uint32_t* volume) const {
- return -1;
-}
-int32_t CfAudioDeviceModule::MaxMicrophoneVolume(uint32_t* maxVolume) const {
- return -1;
-}
-int32_t CfAudioDeviceModule::MinMicrophoneVolume(uint32_t* minVolume) const {
- return -1;
-}
-
-// Speaker mute control
-int32_t CfAudioDeviceModule::SpeakerMuteIsAvailable(bool* available) {
- *available = false;
- return 0;
-}
-int32_t CfAudioDeviceModule::SetSpeakerMute(bool enable) { return -1; }
-int32_t CfAudioDeviceModule::SpeakerMute(bool* enabled) const { return -1; }
-
-// Microphone mute control
-int32_t CfAudioDeviceModule::MicrophoneMuteIsAvailable(bool* available) {
- *available = false;
- return 0;
-}
-int32_t CfAudioDeviceModule::SetMicrophoneMute(bool enable) { return -1; }
-int32_t CfAudioDeviceModule::MicrophoneMute(bool* enabled) const { return -1; }
-
-// Stereo support
-int32_t CfAudioDeviceModule::StereoPlayoutIsAvailable(bool* available) const {
- *available = true;
- return 0;
-}
-int32_t CfAudioDeviceModule::SetStereoPlayout(bool enable) {
- stereo_playout_enabled_ = enable;
- return 0;
-}
-int32_t CfAudioDeviceModule::StereoPlayout(bool* enabled) const {
- *enabled = stereo_playout_enabled_;
- return 0;
-}
-int32_t CfAudioDeviceModule::StereoRecordingIsAvailable(bool* available) const {
- *available = true;
- return 0;
-}
-int32_t CfAudioDeviceModule::SetStereoRecording(bool enable) {
- stereo_recording_enabled_ = enable;
- return 0;
-}
-int32_t CfAudioDeviceModule::StereoRecording(bool* enabled) const {
- *enabled = stereo_recording_enabled_;
- return 0;
-}
-
-// Playout delay
-int32_t CfAudioDeviceModule::PlayoutDelay(uint16_t* delayMS) const {
- // There is currently no way to estimate the real delay for thiese streams.
- // Given that 10ms buffers are used almost everywhere in the pipeline we know
- // the delay is at least 10ms, so that's the best guess here.
- *delayMS = 10;
- return 0;
-}
-
-// Only supported on Android.
-bool CfAudioDeviceModule::BuiltInAECIsAvailable() const { return false; }
-bool CfAudioDeviceModule::BuiltInAGCIsAvailable() const { return false; }
-bool CfAudioDeviceModule::BuiltInNSIsAvailable() const { return false; }
-
-// Enables the built-in audio effects. Only supported on Android.
-int32_t CfAudioDeviceModule::EnableBuiltInAEC(bool enable) { return -1; }
-int32_t CfAudioDeviceModule::EnableBuiltInAGC(bool enable) { return -1; }
-int32_t CfAudioDeviceModule::EnableBuiltInNS(bool enable) { return -1; }
-
-int32_t CfAudioDeviceModule::GetPlayoutUnderrunCount() const { return -1; }
-
-} // namespace webrtc_streaming
-} // namespace cuttlefish
diff --git a/host/frontend/webrtc/lib/audio_device.h b/host/frontend/webrtc/lib/audio_device.h
deleted file mode 100644
index 9b675ee1b..000000000
--- a/host/frontend/webrtc/lib/audio_device.h
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright (C) 2021 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 <modules/audio_device/include/audio_device.h>
-
-#include <atomic>
-
-#include "host/frontend/webrtc/lib/audio_source.h"
-
-namespace cuttlefish {
-namespace webrtc_streaming {
-
-class CfAudioDeviceModule : public webrtc::AudioDeviceModule,
- public AudioSource {
- public:
- CfAudioDeviceModule();
- ~CfAudioDeviceModule() override = default;
-
- // Returns number of frames if there is data available, 0 if the stream is not
- // playing (no clients or the streams are muted), -1 on error.
- int GetMoreAudioData(void* data, int bytes_per_samples, int samples_per_channel,
- int num_channels, int sample_rate, bool& muted) override;
-
- // Retrieve the currently utilized audio layer
- int32_t ActiveAudioLayer(AudioLayer* audioLayer) const override;
-
- // Full-duplex transportation of PCM audio
- int32_t RegisterAudioCallback(webrtc::AudioTransport* audioCallback) override;
-
- // Main initialization and termination
- int32_t Init() override;
- int32_t Terminate() override;
- bool Initialized() const override;
-
- // Device enumeration
- int16_t PlayoutDevices() override;
- int16_t RecordingDevices() override;
- int32_t PlayoutDeviceName(uint16_t index,
- char name[webrtc::kAdmMaxDeviceNameSize],
- char guid[webrtc::kAdmMaxGuidSize]) override;
- int32_t RecordingDeviceName(uint16_t index,
- char name[webrtc::kAdmMaxDeviceNameSize],
- char guid[webrtc::kAdmMaxGuidSize]) override;
-
- // Device selection
- int32_t SetPlayoutDevice(uint16_t index) override;
- int32_t SetPlayoutDevice(WindowsDeviceType device) override;
- int32_t SetRecordingDevice(uint16_t index) override;
- int32_t SetRecordingDevice(WindowsDeviceType device) override;
-
- // Audio transport initialization
- int32_t PlayoutIsAvailable(bool* available) override;
- int32_t InitPlayout() override;
- bool PlayoutIsInitialized() const override;
- int32_t RecordingIsAvailable(bool* available) override;
- int32_t InitRecording() override;
- bool RecordingIsInitialized() const override;
-
- // Audio transport control
- int32_t StartPlayout() override;
- int32_t StopPlayout() override;
- bool Playing() const override;
- int32_t StartRecording() override;
- int32_t StopRecording() override;
- bool Recording() const override;
-
- // Audio mixer initialization
- int32_t InitSpeaker() override;
- bool SpeakerIsInitialized() const override;
- int32_t InitMicrophone() override;
- bool MicrophoneIsInitialized() const override;
-
- // Speaker volume controls
- int32_t SpeakerVolumeIsAvailable(bool* available) override;
- int32_t SetSpeakerVolume(uint32_t volume) override;
- int32_t SpeakerVolume(uint32_t* volume) const override;
- int32_t MaxSpeakerVolume(uint32_t* maxVolume) const override;
- int32_t MinSpeakerVolume(uint32_t* minVolume) const override;
-
- // Microphone volume controls
- int32_t MicrophoneVolumeIsAvailable(bool* available) override;
- int32_t SetMicrophoneVolume(uint32_t volume) override;
- int32_t MicrophoneVolume(uint32_t* volume) const override;
- int32_t MaxMicrophoneVolume(uint32_t* maxVolume) const override;
- int32_t MinMicrophoneVolume(uint32_t* minVolume) const override;
-
- // Speaker mute control
- int32_t SpeakerMuteIsAvailable(bool* available) override;
- int32_t SetSpeakerMute(bool enable) override;
- int32_t SpeakerMute(bool* enabled) const override;
-
- // Microphone mute control
- int32_t MicrophoneMuteIsAvailable(bool* available) override;
- int32_t SetMicrophoneMute(bool enable) override;
- int32_t MicrophoneMute(bool* enabled) const override;
-
- // Stereo support
- int32_t StereoPlayoutIsAvailable(bool* available) const override;
- int32_t SetStereoPlayout(bool enable) override;
- int32_t StereoPlayout(bool* enabled) const override;
- int32_t StereoRecordingIsAvailable(bool* available) const override;
- int32_t SetStereoRecording(bool enable) override;
- int32_t StereoRecording(bool* enabled) const override;
-
- // Playout delay
- int32_t PlayoutDelay(uint16_t* delayMS) const override;
-
- // Only supported on Android.
- bool BuiltInAECIsAvailable() const override;
- bool BuiltInAGCIsAvailable() const override;
- bool BuiltInNSIsAvailable() const override;
-
- // Enables the built-in audio effects. Only supported on Android.
- int32_t EnableBuiltInAEC(bool enable) override;
- int32_t EnableBuiltInAGC(bool enable) override;
- int32_t EnableBuiltInNS(bool enable) override;
-
- // Play underrun count. Only supported on Android (guest).
- int32_t GetPlayoutUnderrunCount() const override;
-
- private:
- webrtc::AudioTransport* audio_callback_ = nullptr;
- bool stereo_playout_enabled_ = true;
- bool stereo_recording_enabled_ = true;
- std::atomic<bool> playing_ = false;
- std::atomic<bool> recording_ = false;
-};
-} // namespace webrtc_streaming
-} // namespace cuttlefish
diff --git a/host/frontend/webrtc/lib/audio_source.h b/host/frontend/webrtc/lib/audio_source.h
deleted file mode 100644
index 09de0201a..000000000
--- a/host/frontend/webrtc/lib/audio_source.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2021 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 <stddef.h>
-
-namespace cuttlefish {
-
-namespace webrtc_streaming {
-
-// Interface to provide access to a stream originated on the client.
-class AudioSource {
- public:
- // Returns the number of bytes read or a negative number in case of errors. If
- // muted is set to true, the contents of data should be considered to be all
- // 0s.
- virtual int GetMoreAudioData(void* data, int bytes_per_sample,
- int samples_per_channel, int num_channels,
- int sample_rate, bool& muted) = 0;
-
- protected:
- virtual ~AudioSource() = default;
-};
-
-} // namespace webrtc_streaming
-} // namespace cuttlefish
diff --git a/host/frontend/webrtc/lib/audio_track_source_impl.cpp b/host/frontend/webrtc/lib/audio_track_source_impl.cpp
deleted file mode 100644
index 334cbb547..000000000
--- a/host/frontend/webrtc/lib/audio_track_source_impl.cpp
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2020 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 "host/frontend/webrtc/lib/audio_track_source_impl.h"
-
-#include <android-base/logging.h>
-
-namespace cuttlefish {
-namespace webrtc_streaming {
-
-void AudioTrackSourceImpl::SetVolume(double volume) {
- std::lock_guard<std::mutex> lock(observers_mutex_);
- for (auto observer : audio_observers_) {
- observer->OnSetVolume(volume);
- }
-}
-
-void AudioTrackSourceImpl::RegisterAudioObserver(AudioObserver* observer) {
- std::lock_guard<std::mutex> lock(observers_mutex_);
- audio_observers_.insert(observer);
-}
-void AudioTrackSourceImpl::UnregisterAudioObserver(AudioObserver* observer) {
- std::lock_guard<std::mutex> lock(observers_mutex_);
- audio_observers_.erase(observer);
-}
-
-void AudioTrackSourceImpl::AddSink(webrtc::AudioTrackSinkInterface* sink) {
- std::lock_guard<std::mutex> lock(sinks_mutex_);
- sinks_.insert(sink);
-}
-
-void AudioTrackSourceImpl::RemoveSink(webrtc::AudioTrackSinkInterface* sink) {
- std::lock_guard<std::mutex> lock(sinks_mutex_);
- sinks_.erase(sink);
-}
-
-const cricket::AudioOptions AudioTrackSourceImpl::options() const {
- return cricket::AudioOptions();
-}
-
-void AudioTrackSourceImpl::OnFrame(std::shared_ptr<AudioFrameBuffer> frame,
- int64_t timestamp_ms) {
- std::lock_guard<std::mutex> lock(sinks_mutex_);
- for (auto sink : sinks_) {
- sink->OnData(frame->data(), frame->bits_per_sample(),
- frame->sample_rate(), frame->channels(), frame->frames(),
- timestamp_ms);
- }
-}
-
-AudioTrackSourceImpl::SourceState AudioTrackSourceImpl::state() const {
- return SourceState::kLive;
-}
-
-bool AudioTrackSourceImpl::remote() const { return false; }
-
-void AudioTrackSourceImpl::RegisterObserver(
- webrtc::ObserverInterface* /*observer*/) {}
-
-void AudioTrackSourceImpl::UnregisterObserver(
- webrtc::ObserverInterface* /*observer*/) {}
-
-} // namespace webrtc_streaming
-} // namespace cuttlefish
diff --git a/host/frontend/webrtc/lib/audio_track_source_impl.h b/host/frontend/webrtc/lib/audio_track_source_impl.h
deleted file mode 100644
index 0a72fe443..000000000
--- a/host/frontend/webrtc/lib/audio_track_source_impl.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (C) 2020 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 <mutex>
-#include <set>
-
-#include <api/media_stream_interface.h>
-
-#include "host/frontend/webrtc/lib/audio_sink.h"
-
-namespace cuttlefish {
-namespace webrtc_streaming {
-
-class AudioTrackSourceImpl : public webrtc::AudioSourceInterface {
- public:
- AudioTrackSourceImpl() = default;
-
- // Sets the volume of the source. |volume| is in the range of [0, 10].
- void SetVolume(double volume) override;
-
- void RegisterAudioObserver(AudioObserver* observer) override;
- void UnregisterAudioObserver(AudioObserver* observer) override;
-
- void AddSink(webrtc::AudioTrackSinkInterface* sink) override;
- void RemoveSink(webrtc::AudioTrackSinkInterface* sink) override;
-
- // Returns options for the AudioSource.
- // (for some of the settings this approach is broken, e.g. setting
- // audio network adaptation on the source is the wrong layer of abstraction).
- virtual const cricket::AudioOptions options() const;
-
- void OnFrame(std::shared_ptr<AudioFrameBuffer> frame, int64_t timestamp_ms);
-
- // MediaSourceInterface implementation
- SourceState state() const override;
- bool remote() const override;
-
- // NotifierInterface implementation
- void RegisterObserver(webrtc::ObserverInterface* observer) override;
- void UnregisterObserver(webrtc::ObserverInterface* observer) override;
-
- private:
- std::set<AudioObserver*> audio_observers_;
- std::mutex observers_mutex_;
- std::set<webrtc::AudioTrackSinkInterface*> sinks_;
- std::mutex sinks_mutex_;
-};
-
-// Wraps an AudioTrackSourceImpl as an implementation of the AudioSink
-// interface. This is needed as the AudioTrackSourceImpl is a reference counted
-// object that should only be referenced by rtc::scoped_refptr pointers, but the
-// AudioSink interface is not a reference counted object and therefore not
-// compatible with that kind of pointers. This class can be referenced by a
-// shared pointer and it in turn holds a scoped_refptr to the wrapped object.
-class AudioTrackSourceImplSinkWrapper : public AudioSink {
- public:
- virtual ~AudioTrackSourceImplSinkWrapper() = default;
-
- AudioTrackSourceImplSinkWrapper(rtc::scoped_refptr<AudioTrackSourceImpl> obj)
- : track_source_impl_(obj) {}
-
- void OnFrame(std::shared_ptr<AudioFrameBuffer> frame,
- int64_t timestamp_ms) override {
- track_source_impl_->OnFrame(frame, timestamp_ms);
- }
-
- private:
- rtc::scoped_refptr<AudioTrackSourceImpl> track_source_impl_;
-};
-
-} // namespace webrtc_streaming
-} // namespace cuttlefish
diff --git a/host/frontend/webrtc/lib/client_handler.cpp b/host/frontend/webrtc/lib/client_handler.cpp
deleted file mode 100644
index 31fd50b95..000000000
--- a/host/frontend/webrtc/lib/client_handler.cpp
+++ /dev/null
@@ -1,767 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "ClientHandler"
-
-#include "host/frontend/webrtc/lib/client_handler.h"
-
-#include <vector>
-
-#include <json/json.h>
-#include <json/writer.h>
-#include <netdb.h>
-#include <openssl/rand.h>
-
-#include <android-base/logging.h>
-
-#include "host/frontend/webrtc/lib/keyboard.h"
-#include "host/frontend/webrtc/lib/utils.h"
-#include "host/libs/config/cuttlefish_config.h"
-
-namespace cuttlefish {
-namespace webrtc_streaming {
-
-namespace {
-
-static constexpr auto kInputChannelLabel = "input-channel";
-static constexpr auto kAdbChannelLabel = "adb-channel";
-static constexpr auto kBluetoothChannelLabel = "bluetooth-channel";
-
-class CvdCreateSessionDescriptionObserver
- : public webrtc::CreateSessionDescriptionObserver {
- public:
- CvdCreateSessionDescriptionObserver(
- std::weak_ptr<ClientHandler> client_handler)
- : client_handler_(client_handler) {}
-
- void OnSuccess(webrtc::SessionDescriptionInterface *desc) override {
- auto client_handler = client_handler_.lock();
- if (client_handler) {
- client_handler->OnCreateSDPSuccess(desc);
- }
- }
- void OnFailure(webrtc::RTCError error) override {
- auto client_handler = client_handler_.lock();
- if (client_handler) {
- client_handler->OnCreateSDPFailure(error);
- }
- }
-
- private:
- std::weak_ptr<ClientHandler> client_handler_;
-};
-
-class CvdSetSessionDescriptionObserver
- : public webrtc::SetSessionDescriptionObserver {
- public:
- CvdSetSessionDescriptionObserver(std::weak_ptr<ClientHandler> client_handler)
- : client_handler_(client_handler) {}
-
- void OnSuccess() override {
- // local description set, nothing else to do
- }
- void OnFailure(webrtc::RTCError error) override {
- auto client_handler = client_handler_.lock();
- if (client_handler) {
- client_handler->OnSetSDPFailure(error);
- }
- }
-
- private:
- std::weak_ptr<ClientHandler> client_handler_;
-};
-
-class CvdOnSetRemoteDescription
- : public webrtc::SetRemoteDescriptionObserverInterface {
- public:
- CvdOnSetRemoteDescription(
- std::function<void(webrtc::RTCError error)> on_error)
- : on_error_(on_error) {}
-
- void OnSetRemoteDescriptionComplete(webrtc::RTCError error) override {
- on_error_(error);
- }
-
- private:
- std::function<void(webrtc::RTCError error)> on_error_;
-};
-
-} // namespace
-
-class InputChannelHandler : public webrtc::DataChannelObserver {
- public:
- InputChannelHandler(
- rtc::scoped_refptr<webrtc::DataChannelInterface> input_channel,
- std::shared_ptr<ConnectionObserver> observer);
- ~InputChannelHandler() override;
-
- void OnStateChange() override;
- void OnMessage(const webrtc::DataBuffer &msg) override;
-
- private:
- rtc::scoped_refptr<webrtc::DataChannelInterface> input_channel_;
- std::shared_ptr<ConnectionObserver> observer_;
-};
-
-class AdbChannelHandler : public webrtc::DataChannelObserver {
- public:
- AdbChannelHandler(
- rtc::scoped_refptr<webrtc::DataChannelInterface> adb_channel,
- std::shared_ptr<ConnectionObserver> observer);
- ~AdbChannelHandler() override;
-
- void OnStateChange() override;
- void OnMessage(const webrtc::DataBuffer &msg) override;
-
- private:
- rtc::scoped_refptr<webrtc::DataChannelInterface> adb_channel_;
- std::shared_ptr<ConnectionObserver> observer_;
- bool channel_open_reported_ = false;
-};
-
-class ControlChannelHandler : public webrtc::DataChannelObserver {
- public:
- ControlChannelHandler(
- rtc::scoped_refptr<webrtc::DataChannelInterface> control_channel,
- std::shared_ptr<ConnectionObserver> observer);
- ~ControlChannelHandler() override;
-
- void OnStateChange() override;
- void OnMessage(const webrtc::DataBuffer &msg) override;
-
- void Send(const Json::Value &message);
- void Send(const uint8_t *msg, size_t size, bool binary);
-
- private:
- rtc::scoped_refptr<webrtc::DataChannelInterface> control_channel_;
- std::shared_ptr<ConnectionObserver> observer_;
-};
-
-class BluetoothChannelHandler : public webrtc::DataChannelObserver {
- public:
- BluetoothChannelHandler(
- rtc::scoped_refptr<webrtc::DataChannelInterface> bluetooth_channel,
- std::shared_ptr<ConnectionObserver> observer);
- ~BluetoothChannelHandler() override;
-
- void OnStateChange() override;
- void OnMessage(const webrtc::DataBuffer &msg) override;
-
- private:
- rtc::scoped_refptr<webrtc::DataChannelInterface> bluetooth_channel_;
- std::shared_ptr<ConnectionObserver> observer_;
- bool channel_open_reported_ = false;
-};
-
-InputChannelHandler::InputChannelHandler(
- rtc::scoped_refptr<webrtc::DataChannelInterface> input_channel,
- std::shared_ptr<ConnectionObserver> observer)
- : input_channel_(input_channel), observer_(observer) {
- input_channel->RegisterObserver(this);
-}
-
-InputChannelHandler::~InputChannelHandler() {
- input_channel_->UnregisterObserver();
-}
-
-void InputChannelHandler::OnStateChange() {
- LOG(VERBOSE) << "Input channel state changed to "
- << webrtc::DataChannelInterface::DataStateString(
- input_channel_->state());
-}
-
-void InputChannelHandler::OnMessage(const webrtc::DataBuffer &msg) {
- if (msg.binary) {
- // TODO (jemoreira) consider binary protocol to avoid JSON parsing overhead
- LOG(ERROR) << "Received invalid (binary) data on input channel";
- return;
- }
- auto size = msg.size();
-
- Json::Value evt;
- Json::CharReaderBuilder builder;
- std::unique_ptr<Json::CharReader> json_reader(builder.newCharReader());
- std::string errorMessage;
- auto str = msg.data.cdata<char>();
- if (!json_reader->parse(str, str + size, &evt, &errorMessage) < 0) {
- LOG(ERROR) << "Received invalid JSON object over input channel: "
- << errorMessage;
- return;
- }
- if (!evt.isMember("type") || !evt["type"].isString()) {
- LOG(ERROR) << "Input event doesn't have a valid 'type' field: "
- << evt.toStyledString();
- return;
- }
- auto event_type = evt["type"].asString();
- if (event_type == "mouse") {
- auto result =
- ValidationResult::ValidateJsonObject(evt, "mouse",
- {{"down", Json::ValueType::intValue},
- {"x", Json::ValueType::intValue},
- {"y", Json::ValueType::intValue},
- {"display_label", Json::ValueType::stringValue}});
- if (!result.ok()) {
- LOG(ERROR) << result.error();
- return;
- }
- auto label = evt["display_label"].asString();
- int32_t down = evt["down"].asInt();
- int32_t x = evt["x"].asInt();
- int32_t y = evt["y"].asInt();
-
- observer_->OnTouchEvent(label, x, y, down);
- } else if (event_type == "multi-touch") {
- auto result =
- ValidationResult::ValidateJsonObject(evt, "multi-touch",
- {{"id", Json::ValueType::arrayValue},
- {"down", Json::ValueType::intValue},
- {"x", Json::ValueType::arrayValue},
- {"y", Json::ValueType::arrayValue},
- {"slot", Json::ValueType::arrayValue},
- {"display_label", Json::ValueType::stringValue}});
- if (!result.ok()) {
- LOG(ERROR) << result.error();
- return;
- }
-
- auto label = evt["display_label"].asString();
- auto idArr = evt["id"];
- int32_t down = evt["down"].asInt();
- auto xArr = evt["x"];
- auto yArr = evt["y"];
- auto slotArr = evt["slot"];
- int size = evt["id"].size();
-
- observer_->OnMultiTouchEvent(label, idArr, slotArr, xArr, yArr, down, size);
- } else if (event_type == "keyboard") {
- auto result =
- ValidationResult::ValidateJsonObject(evt, "keyboard",
- {{"event_type", Json::ValueType::stringValue},
- {"keycode", Json::ValueType::stringValue}});
- if (!result.ok()) {
- LOG(ERROR) << result.error();
- return;
- }
- auto down = evt["event_type"].asString() == std::string("keydown");
- auto code = DomKeyCodeToLinux(evt["keycode"].asString());
- observer_->OnKeyboardEvent(code, down);
- } else {
- LOG(ERROR) << "Unrecognized event type: " << event_type;
- return;
- }
-}
-
-AdbChannelHandler::AdbChannelHandler(
- rtc::scoped_refptr<webrtc::DataChannelInterface> adb_channel,
- std::shared_ptr<ConnectionObserver> observer)
- : adb_channel_(adb_channel), observer_(observer) {
- adb_channel->RegisterObserver(this);
-}
-
-AdbChannelHandler::~AdbChannelHandler() { adb_channel_->UnregisterObserver(); }
-
-void AdbChannelHandler::OnStateChange() {
- LOG(VERBOSE) << "Adb channel state changed to "
- << webrtc::DataChannelInterface::DataStateString(
- adb_channel_->state());
-}
-
-void AdbChannelHandler::OnMessage(const webrtc::DataBuffer &msg) {
- // Report the adb channel as open on the first message received instead of at
- // channel open, this avoids unnecessarily connecting to the adb daemon for
- // clients that don't use ADB.
- if (!channel_open_reported_) {
- observer_->OnAdbChannelOpen([this](const uint8_t *msg, size_t size) {
- webrtc::DataBuffer buffer(rtc::CopyOnWriteBuffer(msg, size),
- true /*binary*/);
- // TODO (b/185832105): When the SCTP channel is congested data channel
- // messages are buffered up to 16MB, when the buffer is full the channel
- // is abruptly closed. Keep track of the buffered data to avoid losing the
- // adb data channel.
- adb_channel_->Send(buffer);
- return true;
- });
- channel_open_reported_ = true;
- }
- observer_->OnAdbMessage(msg.data.cdata(), msg.size());
-}
-
-ControlChannelHandler::ControlChannelHandler(
- rtc::scoped_refptr<webrtc::DataChannelInterface> control_channel,
- std::shared_ptr<ConnectionObserver> observer)
- : control_channel_(control_channel), observer_(observer) {
- control_channel->RegisterObserver(this);
- observer_->OnControlChannelOpen([this](const Json::Value& message) {
- this->Send(message);
- return true;
- });
-}
-
-ControlChannelHandler::~ControlChannelHandler() {
- control_channel_->UnregisterObserver();
-}
-
-void ControlChannelHandler::OnStateChange() {
- LOG(VERBOSE) << "Control channel state changed to "
- << webrtc::DataChannelInterface::DataStateString(
- control_channel_->state());
-}
-
-void ControlChannelHandler::OnMessage(const webrtc::DataBuffer &msg) {
- observer_->OnControlMessage(msg.data.cdata(), msg.size());
-}
-
-void ControlChannelHandler::Send(const Json::Value& message) {
- Json::StreamWriterBuilder factory;
- std::string message_string = Json::writeString(factory, message);
- Send(reinterpret_cast<const uint8_t*>(message_string.c_str()),
- message_string.size(), /*binary=*/false);
-}
-
-void ControlChannelHandler::Send(const uint8_t *msg, size_t size, bool binary) {
- webrtc::DataBuffer buffer(rtc::CopyOnWriteBuffer(msg, size), binary);
- control_channel_->Send(buffer);
-}
-
-BluetoothChannelHandler::BluetoothChannelHandler(
- rtc::scoped_refptr<webrtc::DataChannelInterface> bluetooth_channel,
- std::shared_ptr<ConnectionObserver> observer)
- : bluetooth_channel_(bluetooth_channel), observer_(observer) {
- bluetooth_channel_->RegisterObserver(this);
-}
-
-BluetoothChannelHandler::~BluetoothChannelHandler() {
- bluetooth_channel_->UnregisterObserver();
-}
-
-void BluetoothChannelHandler::OnStateChange() {
- LOG(VERBOSE) << "Bluetooth channel state changed to "
- << webrtc::DataChannelInterface::DataStateString(
- bluetooth_channel_->state());
-}
-
-void BluetoothChannelHandler::OnMessage(const webrtc::DataBuffer &msg) {
- // Notify bluetooth channel opening when actually using the channel,
- // it has the same reason with AdbChannelHandler::OnMessage,
- // to avoid unnecessarily connection for Rootcanal.
- if (channel_open_reported_ == false) {
- channel_open_reported_ = true;
- observer_->OnBluetoothChannelOpen([this](const uint8_t *msg, size_t size) {
- webrtc::DataBuffer buffer(rtc::CopyOnWriteBuffer(msg, size),
- true /*binary*/);
- // TODO (b/185832105): When the SCTP channel is congested data channel
- // messages are buffered up to 16MB, when the buffer is full the channel
- // is abruptly closed. Keep track of the buffered data to avoid losing the
- // adb data channel.
- bluetooth_channel_->Send(buffer);
- return true;
- });
- }
-
- observer_->OnBluetoothMessage(msg.data.cdata(), msg.size());
-}
-
-std::shared_ptr<ClientHandler> ClientHandler::Create(
- int client_id, std::shared_ptr<ConnectionObserver> observer,
- std::function<void(const Json::Value &)> send_to_client_cb,
- std::function<void()> on_connection_closed_cb) {
- return std::shared_ptr<ClientHandler>(new ClientHandler(
- client_id, observer, send_to_client_cb, on_connection_closed_cb));
-}
-
-ClientHandler::ClientHandler(
- int client_id, std::shared_ptr<ConnectionObserver> observer,
- std::function<void(const Json::Value &)> send_to_client_cb,
- std::function<void()> on_connection_closed_cb)
- : client_id_(client_id),
- observer_(observer),
- send_to_client_(send_to_client_cb),
- on_connection_closed_cb_(on_connection_closed_cb) {}
-
-ClientHandler::~ClientHandler() {
- for (auto &data_channel : data_channels_) {
- data_channel->UnregisterObserver();
- }
-}
-
-bool ClientHandler::SetPeerConnection(
- rtc::scoped_refptr<webrtc::PeerConnectionInterface> peer_connection) {
- peer_connection_ = peer_connection;
-
- // libwebrtc configures the video encoder with a start bitrate of just 300kbs
- // which causes it to drop the first 4 frames it receives. Any value over 2Mbs
- // will be capped at 2Mbs when passed to the encoder by the peer_connection
- // object, so we pass the maximum possible value here.
- webrtc::BitrateSettings bitrate_settings;
- bitrate_settings.start_bitrate_bps = 2000000; // 2Mbs
- peer_connection_->SetBitrate(bitrate_settings);
- // At least one data channel needs to be created on the side that makes the
- // SDP offer (the device) for data channels to be enabled at all.
- // This channel is meant to carry control commands from the client.
- auto control_channel = peer_connection_->CreateDataChannel(
- "device-control", nullptr /* config */);
- if (!control_channel) {
- LOG(ERROR) << "Failed to create control data channel";
- return false;
- }
- control_handler_.reset(new ControlChannelHandler(control_channel, observer_));
- return true;
-}
-
-bool ClientHandler::AddDisplay(
- rtc::scoped_refptr<webrtc::VideoTrackInterface> video_track,
- const std::string &label) {
- // Send each track as part of a different stream with the label as id
- auto err_or_sender =
- peer_connection_->AddTrack(video_track, {label} /* stream_id */);
- if (!err_or_sender.ok()) {
- LOG(ERROR) << "Failed to add video track to the peer connection";
- return false;
- }
- // TODO (b/154138394): use the returned sender (err_or_sender.value()) to
- // remove the display from the connection.
- return true;
-}
-
-bool ClientHandler::AddAudio(
- rtc::scoped_refptr<webrtc::AudioTrackInterface> audio_track,
- const std::string &label) {
- // Send each track as part of a different stream with the label as id
- auto err_or_sender =
- peer_connection_->AddTrack(audio_track, {label} /* stream_id */);
- if (!err_or_sender.ok()) {
- LOG(ERROR) << "Failed to add video track to the peer connection";
- return false;
- }
- return true;
-}
-
-void ClientHandler::LogAndReplyError(const std::string &error_msg) const {
- LOG(ERROR) << error_msg;
- Json::Value reply;
- reply["type"] = "error";
- reply["error"] = error_msg;
- send_to_client_(reply);
-}
-
-void ClientHandler::OnCreateSDPSuccess(
- webrtc::SessionDescriptionInterface *desc) {
- std::string offer_str;
- desc->ToString(&offer_str);
- peer_connection_->SetLocalDescription(
- // The peer connection wraps this raw pointer with a scoped_refptr, so
- // it's guaranteed to be deleted at some point
- new rtc::RefCountedObject<CvdSetSessionDescriptionObserver>(
- weak_from_this()),
- desc);
- // The peer connection takes ownership of the description so it should not be
- // used after this
- desc = nullptr;
-
- Json::Value reply;
- reply["type"] = "offer";
- reply["sdp"] = offer_str;
-
- state_ = State::kAwaitingAnswer;
- send_to_client_(reply);
-}
-
-void ClientHandler::OnCreateSDPFailure(webrtc::RTCError error) {
- state_ = State::kFailed;
- LogAndReplyError(error.message());
- Close();
-}
-
-void ClientHandler::OnSetSDPFailure(webrtc::RTCError error) {
- state_ = State::kFailed;
- LogAndReplyError(error.message());
- LOG(ERROR) << "Error setting local description: Either there is a bug in "
- "libwebrtc or the local description was (incorrectly) modified "
- "after creating it";
- Close();
-}
-
-void ClientHandler::HandleMessage(const Json::Value &message) {
- {
- auto result = ValidationResult::ValidateJsonObject(message, "",
- {{"type", Json::ValueType::stringValue}});
- if (!result.ok()) {
- LogAndReplyError(result.error());
- return;
- }
- }
- auto type = message["type"].asString();
- if (type == "request-offer") {
- // Can't check for state being different that kNew because renegotiation can
- // start in any state after the answer is returned.
- if (state_ == State::kCreatingOffer) {
- // An offer has been requested already
- LogAndReplyError("Multiple requests for offer received from single client");
- return;
- }
- state_ = State::kCreatingOffer;
- peer_connection_->CreateOffer(
- // No memory leak here because this is a ref counted objects and the
- // peer connection immediately wraps it with a scoped_refptr
- new rtc::RefCountedObject<CvdCreateSessionDescriptionObserver>(
- weak_from_this()),
- webrtc::PeerConnectionInterface::RTCOfferAnswerOptions());
- // The created offer wil be sent to the client on
- // OnSuccess(webrtc::SessionDescriptionInterface* desc)
- } else if (type == "answer") {
- if (state_ != State::kAwaitingAnswer) {
- LogAndReplyError("Received unexpected SDP answer");
- return;
- }
- auto result = ValidationResult::ValidateJsonObject(message, type,
- {{"sdp", Json::ValueType::stringValue}});
- if (!result.ok()) {
- LogAndReplyError(result.error());
- return;
- }
- auto remote_desc_str = message["sdp"].asString();
- auto remote_desc = webrtc::CreateSessionDescription(
- webrtc::SdpType::kAnswer, remote_desc_str, nullptr /*error*/);
- if (!remote_desc) {
- LogAndReplyError("Failed to parse answer.");
- return;
- }
- rtc::scoped_refptr<webrtc::SetRemoteDescriptionObserverInterface> observer(
- new rtc::RefCountedObject<CvdOnSetRemoteDescription>(
- [this](webrtc::RTCError error) {
- if (!error.ok()) {
- LogAndReplyError(error.message());
- // The remote description was rejected, this client can't be
- // trusted anymore.
- Close();
- }
- }));
- peer_connection_->SetRemoteDescription(std::move(remote_desc), observer);
- state_ = State::kConnecting;
-
- } else if (type == "ice-candidate") {
- {
- auto result = ValidationResult::ValidateJsonObject(
- message, type, {{"candidate", Json::ValueType::objectValue}});
- if (!result.ok()) {
- LogAndReplyError(result.error());
- return;
- }
- }
- auto candidate_json = message["candidate"];
- {
- auto result =
- ValidationResult::ValidateJsonObject(candidate_json,
- "ice-candidate/candidate",
- {
- {"sdpMid", Json::ValueType::stringValue},
- {"candidate", Json::ValueType::stringValue},
- {"sdpMLineIndex", Json::ValueType::intValue},
- });
- if (!result.ok()) {
- LogAndReplyError(result.error());
- return;
- }
- }
- auto mid = candidate_json["sdpMid"].asString();
- auto candidate_sdp = candidate_json["candidate"].asString();
- auto line_index = candidate_json["sdpMLineIndex"].asInt();
-
- std::unique_ptr<webrtc::IceCandidateInterface> candidate(
- webrtc::CreateIceCandidate(mid, line_index, candidate_sdp,
- nullptr /*error*/));
- if (!candidate) {
- LogAndReplyError("Failed to parse ICE candidate");
- return;
- }
- peer_connection_->AddIceCandidate(std::move(candidate),
- [this](webrtc::RTCError error) {
- if (!error.ok()) {
- LogAndReplyError(error.message());
- }
- });
- } else {
- LogAndReplyError("Unknown client message type: " + type);
- return;
- }
-}
-
-void ClientHandler::Close() {
- // We can't simply call peer_connection_->Close() here because this method
- // could be called from one of the PeerConnectionObserver callbacks and that
- // would lead to a deadlock (Close eventually tries to destroy an object that
- // will then wait for the callback to return -> deadlock). Destroying the
- // peer_connection_ has the same effect. The only alternative is to postpone
- // that operation until after the callback returns.
- on_connection_closed_cb_();
-}
-
-void ClientHandler::OnConnectionChange(
- webrtc::PeerConnectionInterface::PeerConnectionState new_state) {
- switch (new_state) {
- case webrtc::PeerConnectionInterface::PeerConnectionState::kNew:
- break;
- case webrtc::PeerConnectionInterface::PeerConnectionState::kConnecting:
- break;
- case webrtc::PeerConnectionInterface::PeerConnectionState::kConnected:
- LOG(VERBOSE) << "Client " << client_id_ << ": WebRTC connected";
- state_ = State::kConnected;
- observer_->OnConnected(
- [this](const uint8_t *msg, size_t size, bool binary) {
- control_handler_->Send(msg, size, binary);
- return true;
- });
- break;
- case webrtc::PeerConnectionInterface::PeerConnectionState::kDisconnected:
- LOG(VERBOSE) << "Client " << client_id_ << ": Connection disconnected";
- Close();
- break;
- case webrtc::PeerConnectionInterface::PeerConnectionState::kFailed:
- LOG(ERROR) << "Client " << client_id_ << ": Connection failed";
- Close();
- break;
- case webrtc::PeerConnectionInterface::PeerConnectionState::kClosed:
- LOG(VERBOSE) << "Client " << client_id_ << ": Connection closed";
- Close();
- break;
- }
-}
-
-void ClientHandler::OnIceCandidate(
- const webrtc::IceCandidateInterface *candidate) {
- std::string candidate_sdp;
- candidate->ToString(&candidate_sdp);
- auto sdp_mid = candidate->sdp_mid();
- auto line_index = candidate->sdp_mline_index();
-
- Json::Value reply;
- reply["type"] = "ice-candidate";
- reply["mid"] = sdp_mid;
- reply["mLineIndex"] = static_cast<Json::UInt64>(line_index);
- reply["candidate"] = candidate_sdp;
-
- send_to_client_(reply);
-}
-
-void ClientHandler::OnDataChannel(
- rtc::scoped_refptr<webrtc::DataChannelInterface> data_channel) {
- auto label = data_channel->label();
- if (label == kInputChannelLabel) {
- input_handler_.reset(new InputChannelHandler(data_channel, observer_));
- } else if (label == kAdbChannelLabel) {
- adb_handler_.reset(new AdbChannelHandler(data_channel, observer_));
- } else if (label == kBluetoothChannelLabel) {
- bluetooth_handler_.reset(
- new BluetoothChannelHandler(data_channel, observer_));
- } else {
- LOG(VERBOSE) << "Data channel connected: " << label;
- data_channels_.push_back(data_channel);
- }
-}
-
-void ClientHandler::OnRenegotiationNeeded() {
- state_ = State::kNew;
- LOG(VERBOSE) << "Client " << client_id_ << " needs renegotiation";
-}
-
-void ClientHandler::OnIceGatheringChange(
- webrtc::PeerConnectionInterface::IceGatheringState new_state) {
- std::string state_str;
- switch (new_state) {
- case webrtc::PeerConnectionInterface::IceGatheringState::kIceGatheringNew:
- state_str = "NEW";
- break;
- case webrtc::PeerConnectionInterface::IceGatheringState::
- kIceGatheringGathering:
- state_str = "GATHERING";
- break;
- case webrtc::PeerConnectionInterface::IceGatheringState::
- kIceGatheringComplete:
- state_str = "COMPLETE";
- break;
- default:
- state_str = "UNKNOWN";
- }
- LOG(VERBOSE) << "Client " << client_id_
- << ": ICE Gathering state set to: " << state_str;
-}
-
-void ClientHandler::OnIceCandidateError(const std::string &host_candidate,
- const std::string &url, int error_code,
- const std::string &error_text) {
- LOG(VERBOSE) << "Gathering of an ICE candidate (host candidate: "
- << host_candidate << ", url: " << url
- << ") failed: " << error_text;
-}
-
-void ClientHandler::OnIceCandidateError(const std::string &address, int port,
- const std::string &url, int error_code,
- const std::string &error_text) {
- LOG(VERBOSE) << "Gathering of an ICE candidate (address: " << address
- << ", port: " << port << ", url: " << url
- << ") failed: " << error_text;
-}
-
-void ClientHandler::OnSignalingChange(
- webrtc::PeerConnectionInterface::SignalingState new_state) {
- // ignore
-}
-void ClientHandler::OnStandardizedIceConnectionChange(
- webrtc::PeerConnectionInterface::IceConnectionState new_state) {
- switch (new_state) {
- case webrtc::PeerConnectionInterface::kIceConnectionNew:
- LOG(DEBUG) << "ICE connection state: New";
- break;
- case webrtc::PeerConnectionInterface::kIceConnectionChecking:
- LOG(DEBUG) << "ICE connection state: Checking";
- break;
- case webrtc::PeerConnectionInterface::kIceConnectionConnected:
- LOG(DEBUG) << "ICE connection state: Connected";
- break;
- case webrtc::PeerConnectionInterface::kIceConnectionCompleted:
- LOG(DEBUG) << "ICE connection state: Completed";
- break;
- case webrtc::PeerConnectionInterface::kIceConnectionFailed:
- state_ = State::kFailed;
- LOG(DEBUG) << "ICE connection state: Failed";
- break;
- case webrtc::PeerConnectionInterface::kIceConnectionDisconnected:
- LOG(DEBUG) << "ICE connection state: Disconnected";
- break;
- case webrtc::PeerConnectionInterface::kIceConnectionClosed:
- LOG(DEBUG) << "ICE connection state: Closed";
- break;
- case webrtc::PeerConnectionInterface::kIceConnectionMax:
- LOG(DEBUG) << "ICE connection state: Max";
- break;
- }
-}
-void ClientHandler::OnIceCandidatesRemoved(
- const std::vector<cricket::Candidate> &candidates) {
- // ignore
-}
-void ClientHandler::OnTrack(
- rtc::scoped_refptr<webrtc::RtpTransceiverInterface> transceiver) {
- // ignore
-}
-void ClientHandler::OnRemoveTrack(
- rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver) {
- // ignore
-}
-
-} // namespace webrtc_streaming
-} // namespace cuttlefish
diff --git a/host/frontend/webrtc/lib/client_handler.h b/host/frontend/webrtc/lib/client_handler.h
deleted file mode 100644
index c85f169a2..000000000
--- a/host/frontend/webrtc/lib/client_handler.h
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright (C) 2020 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 <functional>
-#include <memory>
-#include <optional>
-#include <sstream>
-#include <string>
-#include <vector>
-
-#include <json/json.h>
-
-#include <api/peer_connection_interface.h>
-#include <pc/video_track_source.h>
-
-#include "host/frontend/webrtc/lib/connection_observer.h"
-
-namespace cuttlefish {
-namespace webrtc_streaming {
-
-class InputChannelHandler;
-class AdbChannelHandler;
-class ControlChannelHandler;
-class BluetoothChannelHandler;
-
-class ClientHandler : public webrtc::PeerConnectionObserver,
- public std::enable_shared_from_this<ClientHandler> {
- public:
- static std::shared_ptr<ClientHandler> Create(
- int client_id, std::shared_ptr<ConnectionObserver> observer,
- std::function<void(const Json::Value&)> send_client_cb,
- std::function<void()> on_connection_closed_cb);
- ~ClientHandler() override;
-
- bool SetPeerConnection(
- rtc::scoped_refptr<webrtc::PeerConnectionInterface> peer_connection);
-
- bool AddDisplay(rtc::scoped_refptr<webrtc::VideoTrackInterface> track,
- const std::string& label);
-
- bool AddAudio(rtc::scoped_refptr<webrtc::AudioTrackInterface> track,
- const std::string& label);
-
- void HandleMessage(const Json::Value& client_message);
-
- // CreateSessionDescriptionObserver implementation
- void OnCreateSDPSuccess(webrtc::SessionDescriptionInterface* desc);
- void OnCreateSDPFailure(webrtc::RTCError error);
-
- // SetSessionDescriptionObserver implementation
- void OnSetSDPFailure(webrtc::RTCError error);
-
- // PeerConnectionObserver implementation
- void OnSignalingChange(
- webrtc::PeerConnectionInterface::SignalingState new_state) override;
- void OnDataChannel(
- rtc::scoped_refptr<webrtc::DataChannelInterface> data_channel) override;
- void OnRenegotiationNeeded() override;
- void OnStandardizedIceConnectionChange(
- webrtc::PeerConnectionInterface::IceConnectionState new_state) override;
- void OnConnectionChange(
- webrtc::PeerConnectionInterface::PeerConnectionState new_state) override;
- void OnIceGatheringChange(
- webrtc::PeerConnectionInterface::IceGatheringState new_state) override;
- void OnIceCandidate(const webrtc::IceCandidateInterface* candidate) override;
- // Gathering of an ICE candidate failed.
- // See https://w3c.github.io/webrtc-pc/#event-icecandidateerror
- // |host_candidate| is a stringified socket address.
- void OnIceCandidateError(const std::string& host_candidate,
- const std::string& url, int error_code,
- const std::string& error_text) override;
- // Gathering of an ICE candidate failed.
- // See https://w3c.github.io/webrtc-pc/#event-icecandidateerror
- void OnIceCandidateError(const std::string& address, int port,
- const std::string& url, int error_code,
- const std::string& error_text) override;
- void OnIceCandidatesRemoved(
- const std::vector<cricket::Candidate>& candidates) override;
- void OnTrack(
- rtc::scoped_refptr<webrtc::RtpTransceiverInterface> transceiver) override;
- void OnRemoveTrack(
- rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver) override;
-
- private:
- enum class State {
- kNew,
- kCreatingOffer,
- kAwaitingAnswer,
- kConnecting,
- kConnected,
- kFailed,
- };
- ClientHandler(int client_id, std::shared_ptr<ConnectionObserver> observer,
- std::function<void(const Json::Value&)> send_client_cb,
- std::function<void()> on_connection_closed_cb);
-
- // Intentionally private, disconnect the client by destroying the object.
- void Close();
-
- void LogAndReplyError(const std::string& error_msg) const;
-
- int client_id_;
- State state_ = State::kNew;
- std::shared_ptr<ConnectionObserver> observer_;
- std::function<void(const Json::Value&)> send_to_client_;
- std::function<void()> on_connection_closed_cb_;
- rtc::scoped_refptr<webrtc::PeerConnectionInterface> peer_connection_;
- std::vector<rtc::scoped_refptr<webrtc::DataChannelInterface>> data_channels_;
- std::unique_ptr<InputChannelHandler> input_handler_;
- std::unique_ptr<AdbChannelHandler> adb_handler_;
- std::unique_ptr<ControlChannelHandler> control_handler_;
- std::unique_ptr<BluetoothChannelHandler> bluetooth_handler_;
-};
-
-} // namespace webrtc_streaming
-} // namespace cuttlefish
diff --git a/host/frontend/webrtc/lib/connection_observer.h b/host/frontend/webrtc/lib/connection_observer.h
deleted file mode 100644
index be6fc13a3..000000000
--- a/host/frontend/webrtc/lib/connection_observer.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2020 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 <functional>
-
-#include <json/json.h>
-
-namespace cuttlefish {
-namespace webrtc_streaming {
-
-class ConnectionObserver {
- public:
- ConnectionObserver() = default;
- virtual ~ConnectionObserver() = default;
-
- virtual void OnConnected(
- std::function<void(const uint8_t*, size_t, bool)> ctrl_msg_sender) = 0;
- virtual void OnTouchEvent(const std::string& display_label, int x, int y,
- bool down) = 0;
- virtual void OnMultiTouchEvent(const std::string& label, Json::Value id, Json::Value slot,
- Json::Value x, Json::Value y, bool down, int size) = 0;
- virtual void OnKeyboardEvent(uint16_t keycode, bool down) = 0;
- virtual void OnSwitchEvent(uint16_t code, bool state) = 0;
- virtual void OnAdbChannelOpen(
- std::function<bool(const uint8_t*, size_t)> adb_message_sender) = 0;
- virtual void OnAdbMessage(const uint8_t* msg, size_t size) = 0;
- virtual void OnControlChannelOpen(
- std::function<bool(const Json::Value)> control_message_sender) = 0;
- virtual void OnControlMessage(const uint8_t* msg, size_t size) = 0;
- virtual void OnBluetoothChannelOpen(
- std::function<bool(const uint8_t*, size_t)> bluetooth_message_sender) = 0;
- virtual void OnBluetoothMessage(const uint8_t* msg, size_t size) = 0;
-};
-
-class ConnectionObserverFactory {
- public:
- virtual ~ConnectionObserverFactory() = default;
- // Called when a new connection is requested
- virtual std::shared_ptr<ConnectionObserver> CreateObserver() = 0;
-};
-
-} // namespace webrtc_streaming
-} // namespace cuttlefish
diff --git a/host/frontend/webrtc/lib/local_recorder.cpp b/host/frontend/webrtc/lib/local_recorder.cpp
deleted file mode 100644
index 28f71b04c..000000000
--- a/host/frontend/webrtc/lib/local_recorder.cpp
+++ /dev/null
@@ -1,288 +0,0 @@
-/*
- * Copyright (C) 2020 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 "host/frontend/webrtc/lib/local_recorder.h"
-
-#include <atomic>
-#include <chrono>
-#include <list>
-#include <mutex>
-#include <thread>
-#include <vector>
-
-#include <android-base/logging.h>
-#include <api/media_stream_interface.h>
-#include <api/rtp_parameters.h>
-#include <api/task_queue/default_task_queue_factory.h>
-#include <api/video/builtin_video_bitrate_allocator_factory.h>
-#include <api/video/video_stream_encoder_create.h>
-#include <api/video/video_stream_encoder_interface.h>
-#include <api/video_codecs/builtin_video_encoder_factory.h>
-#include <mkvmuxer/mkvmuxer.h>
-#include <mkvmuxer/mkvwriter.h>
-#include <system_wrappers/include/clock.h>
-
-namespace cuttlefish {
-namespace webrtc_streaming {
-
-constexpr double kRtpTicksPerSecond = 90000.;
-constexpr double kRtpTicksPerMs = kRtpTicksPerSecond / 1000.;
-constexpr double kRtpTicksPerUs = kRtpTicksPerMs / 1000.;
-constexpr double kRtpTicksPerNs = kRtpTicksPerUs / 1000.;
-
-class LocalRecorder::Display
- : public webrtc::EncodedImageCallback
- , public rtc::VideoSinkInterface<webrtc::VideoFrame> {
-public:
- Display(LocalRecorder::Impl& impl);
-
- void EncoderLoop();
- void Stop();
-
- // VideoSinkInterface
- virtual void OnFrame(const webrtc::VideoFrame& frame) override;
-
- // EncodedImageCallback
- virtual webrtc::EncodedImageCallback::Result OnEncodedImage(
- const webrtc::EncodedImage& encoded_image,
- const webrtc::CodecSpecificInfo* codec_specific_info,
- const webrtc::RTPFragmentationHeader* fragmentation) override;
-
- LocalRecorder::Impl& impl_;
- std::shared_ptr<webrtc::VideoTrackSourceInterface> source_;
- std::unique_ptr<webrtc::VideoEncoder> video_encoder_;
- uint64_t video_track_number_;
-
- // TODO(schuffelen): Use a WebRTC task queue?
- std::thread encoder_thread_;
- std::condition_variable encoder_queue_signal_;
- std::mutex encode_queue_mutex_;
- std::list<webrtc::VideoFrame> encode_queue_;
- std::atomic_bool encoder_running_ = true;
-};
-
-class LocalRecorder::Impl {
-public:
- mkvmuxer::MkvWriter file_writer_;
- mkvmuxer::Segment segment_;
- std::unique_ptr<webrtc::VideoEncoderFactory> encoder_factory_;
- std::mutex mkv_mutex_;
- std::vector<std::unique_ptr<Display>> displays_;
-};
-
-/* static */
-std::unique_ptr<LocalRecorder> LocalRecorder::Create(
- const std::string& filename) {
- std::unique_ptr<Impl> impl(new Impl());
-
- if (!impl->file_writer_.Open(filename.c_str())) {
- LOG(ERROR) << "Failed to open \"" << filename << "\" to write a webm";
- return {};
- }
-
- if (!impl->segment_.Init(&impl->file_writer_)) {
- LOG(ERROR) << "Failed to initialize the mkvkmuxer segment";
- return {};
- }
-
- impl->segment_.AccurateClusterDuration(true);
- impl->segment_.set_estimate_file_duration(true);
-
- impl->encoder_factory_ = webrtc::CreateBuiltinVideoEncoderFactory();
- if (!impl->encoder_factory_) {
- LOG(ERROR) << "Failed to create webRTC built-in video encoder factory";
- return {};
- }
-
- return std::unique_ptr<LocalRecorder>(new LocalRecorder(std::move(impl)));
-}
-
-LocalRecorder::LocalRecorder(std::unique_ptr<LocalRecorder::Impl> impl)
- : impl_(std::move(impl)) {
-}
-
-LocalRecorder::~LocalRecorder() = default;
-
-void LocalRecorder::AddDisplay(
- size_t width,
- size_t height,
- std::shared_ptr<webrtc::VideoTrackSourceInterface> source) {
- std::unique_ptr<Display> display(new Display(*impl_));
- display->source_ = source;
-
- display->video_encoder_ =
- impl_->encoder_factory_->CreateVideoEncoder(webrtc::SdpVideoFormat("VP8"));
- if (!display->video_encoder_) {
- LOG(ERROR) << "Could not create vp8 video encoder";
- return;
- }
- auto rc =
- display->video_encoder_->RegisterEncodeCompleteCallback(display.get());
- if (rc != 0) {
- LOG(ERROR) << "Could not register encode complete callback";
- return;
- }
- source->AddOrUpdateSink(display.get(), rtc::VideoSinkWants{});
-
- webrtc::VideoCodec codec {};
- memset(&codec, 0, sizeof(codec));
- codec.codecType = webrtc::kVideoCodecVP8;
- codec.width = width;
- codec.height = height;
- codec.startBitrate = 1000; // kilobits/sec
- codec.maxBitrate = 2000;
- codec.minBitrate = 0;
- codec.maxFramerate = 60;
- codec.active = true;
- codec.qpMax = 56; // kDefaultMaxQp from simulcast_encoder_adapter.cc
- codec.mode = webrtc::VideoCodecMode::kScreensharing;
- codec.expect_encode_from_texture = false;
- *codec.VP8() = webrtc::VideoEncoder::GetDefaultVp8Settings();
-
- webrtc::VideoEncoder::Capabilities capabilities(false);
- webrtc::VideoEncoder::Settings settings(capabilities, 1, 1 << 20);
-
- rc = display->video_encoder_->InitEncode(&codec, settings);
- if (rc != 0) {
- LOG(ERROR) << "Failed to InitEncode";
- return;
- }
-
- display->encoder_running_ = true;
- display->encoder_thread_ = std::thread([](Display* display) {
- display->EncoderLoop();
- }, display.get());
-
- std::lock_guard lock(impl_->mkv_mutex_);
- display->video_track_number_ =
- impl_->segment_.AddVideoTrack(width, height, 0);
- if (display->video_track_number_ == 0) {
- LOG(ERROR) << "Failed to add video track to webm muxer";
- return;
- }
-
- impl_->displays_.emplace_back(std::move(display));
-}
-
-void LocalRecorder::Stop() {
- for (auto& display : impl_->displays_) {
- display->Stop();
- }
- impl_->displays_.clear();
-
- std::lock_guard lock(impl_->mkv_mutex_);
- impl_->segment_.Finalize();
-}
-
-LocalRecorder::Display::Display(LocalRecorder::Impl& impl) : impl_(impl) {
-}
-
-void LocalRecorder::Display::OnFrame(const webrtc::VideoFrame& frame) {
- std::lock_guard queue_lock(encode_queue_mutex_);
- static int kMaxQueuedFrames = 10;
- if (encode_queue_.size() >= kMaxQueuedFrames) {
- LOG(VERBOSE) << "Dropped frame, encoder queue too long";
- return;
- }
- encode_queue_.push_back(frame);
- encoder_queue_signal_.notify_one();
-}
-
-void LocalRecorder::Display::EncoderLoop() {
- int frames_since_keyframe = 0;
- std::chrono::time_point<std::chrono::steady_clock> start_timestamp;
- auto last_keyframe_time = std::chrono::steady_clock::now();
- while (encoder_running_) {
- std::unique_ptr<webrtc::VideoFrame> frame;
- {
- std::unique_lock queue_lock(encode_queue_mutex_);
- while (encode_queue_.size() == 0 && encoder_running_) {
- encoder_queue_signal_.wait(queue_lock);
- }
- if (!encoder_running_) {
- break;
- }
- frame = std::make_unique<webrtc::VideoFrame>(
- std::move(encode_queue_.front()));
- encode_queue_.pop_front();
- }
-
- auto now = std::chrono::steady_clock::now();
- if (start_timestamp.time_since_epoch().count() == 0) {
- start_timestamp = now;
- }
- auto timestamp_diff =
- std::chrono::duration_cast<std::chrono::microseconds>(
- now - start_timestamp);
- frame->set_timestamp_us(timestamp_diff.count());
- frame->set_timestamp(timestamp_diff.count() * kRtpTicksPerUs);
-
- std::vector<webrtc::VideoFrameType> types;
- auto time_since_keyframe = now - last_keyframe_time;
- const auto min_keyframe_time = std::chrono::seconds(10);
- if (frames_since_keyframe > 60 || time_since_keyframe > min_keyframe_time) {
- last_keyframe_time = now;
- frames_since_keyframe = 0;
- types.push_back(webrtc::VideoFrameType::kVideoFrameKey);
- } else {
- types.push_back(webrtc::VideoFrameType::kVideoFrameDelta);
- }
- auto rc = video_encoder_->Encode(*frame, &types);
- if (rc != 0) {
- LOG(ERROR) << "Failed to encode frame";
- }
- }
-}
-
-void LocalRecorder::Display::Stop() {
- encoder_running_ = false;
- encoder_queue_signal_.notify_all();
- if (encoder_thread_.joinable()) {
- encoder_thread_.join();
- }
-}
-
-webrtc::EncodedImageCallback::Result LocalRecorder::Display::OnEncodedImage(
- const webrtc::EncodedImage& encoded_image,
- const webrtc::CodecSpecificInfo* codec_specific_info,
- const webrtc::RTPFragmentationHeader* fragmentation) {
- uint64_t timestamp = encoded_image.Timestamp() / kRtpTicksPerNs;
-
- std::lock_guard(impl_.mkv_mutex_);
-
- bool is_key =
- encoded_image._frameType == webrtc::VideoFrameType::kVideoFrameKey;
- bool success = impl_.segment_.AddFrame(
- encoded_image.data(),
- encoded_image.size(),
- video_track_number_,
- timestamp,
- is_key);
-
- webrtc::EncodedImageCallback::Result result(
- success
- ? webrtc::EncodedImageCallback::Result::Error::OK
- : webrtc::EncodedImageCallback::Result::Error::ERROR_SEND_FAILED);
-
- if (success) {
- result.frame_id = encoded_image.Timestamp();
- }
- return result;
-}
-
-} // namespace webrtc_streaming
-} // namespace cuttlefish
-
diff --git a/host/frontend/webrtc/lib/local_recorder.h b/host/frontend/webrtc/lib/local_recorder.h
deleted file mode 100644
index a18c978c6..000000000
--- a/host/frontend/webrtc/lib/local_recorder.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2020 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 <memory>
-#include <string>
-
-namespace webrtc {
-class VideoTrackSourceInterface;
-}
-
-namespace cuttlefish {
-namespace webrtc_streaming {
-
-class VideoTrackSourceImpl;
-
-class LocalRecorder {
-public:
- ~LocalRecorder();
-
- static std::unique_ptr<LocalRecorder> Create(const std::string& filename);
-
- void AddDisplay(
- size_t width,
- size_t height,
- std::shared_ptr<webrtc::VideoTrackSourceInterface> video);
-
- void Stop();
-private:
- class Display;
- class Impl;
-
- LocalRecorder(std::unique_ptr<Impl>);
-
- std::unique_ptr<Impl> impl_;
-};
-
-} // namespace webrtc_streaming
-} // namespace cuttlefish
diff --git a/host/frontend/webrtc/lib/port_range_socket_factory.cpp b/host/frontend/webrtc/lib/port_range_socket_factory.cpp
deleted file mode 100644
index c997cbcfe..000000000
--- a/host/frontend/webrtc/lib/port_range_socket_factory.cpp
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (C) 2020 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 "host/frontend/webrtc/lib/port_range_socket_factory.h"
-
-#include <android-base/logging.h>
-
-namespace cuttlefish {
-namespace webrtc_streaming {
-
-namespace {
-
-std::pair<uint16_t, uint16_t> IntersectPortRanges(
- std::pair<uint16_t, uint16_t> own_range, uint16_t min_port,
- uint16_t max_port) {
- if (own_range.first == own_range.second && own_range.first == 0) {
- // No range configured
- return {min_port, max_port};
- }
- if (min_port == max_port && max_port == 0) {
- // No range requested, use configured
- return own_range;
- }
- uint16_t own_min_port = own_range.first;
- uint16_t own_max_port = own_range.second;
-
- if (min_port > own_max_port || max_port < own_min_port) {
- // Ranges don't intersect
- LOG(WARNING) << "Port ranges don't intersect: requested=[" << min_port
- << "," << max_port << "], configured=[" << own_min_port << ","
- << own_max_port << "]";
- }
- return {std::max(min_port, own_min_port), std::min(max_port, own_max_port)};
-}
-
-} // namespace
-
-PortRangeSocketFactory::PortRangeSocketFactory(
- rtc::Thread* thread, std::pair<uint16_t, uint16_t> udp_port_range,
- std::pair<uint16_t, uint16_t> tcp_port_range)
- : rtc::BasicPacketSocketFactory(thread),
- udp_port_range_(udp_port_range),
- tcp_port_range_(tcp_port_range) {}
-
-rtc::AsyncPacketSocket* PortRangeSocketFactory::CreateUdpSocket(
- const rtc::SocketAddress& local_address, uint16_t min_port,
- uint16_t max_port) {
- auto port_range = IntersectPortRanges(udp_port_range_, min_port, max_port);
- if (port_range.second < port_range.first) {
- // Own range doesn't intersect with requested range
- return nullptr;
- }
- return rtc::BasicPacketSocketFactory::CreateUdpSocket(
- local_address, port_range.first, port_range.second);
-}
-
-rtc::AsyncPacketSocket* PortRangeSocketFactory::CreateServerTcpSocket(
- const rtc::SocketAddress& local_address, uint16_t min_port,
- uint16_t max_port, int opts) {
- auto port_range = IntersectPortRanges(tcp_port_range_, min_port, max_port);
- if (port_range.second < port_range.first) {
- // Own range doesn't intersect with requested range
- return nullptr;
- }
-
- return rtc::BasicPacketSocketFactory::CreateServerTcpSocket(
- local_address, port_range.first, port_range.second, opts);
-}
-
-} // namespace webrtc_streaming
-} // namespace cuttlefish
diff --git a/host/frontend/webrtc/lib/port_range_socket_factory.h b/host/frontend/webrtc/lib/port_range_socket_factory.h
deleted file mode 100644
index c5a34a1cf..000000000
--- a/host/frontend/webrtc/lib/port_range_socket_factory.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2020 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 <cinttypes>
-#include <utility>
-
-// This is not part of the webrtc api and therefore subject to change
-#include <p2p/base/basic_packet_socket_factory.h>
-
-namespace cuttlefish {
-namespace webrtc_streaming {
-
-// rtc::BasicPacketSocketFactory is not part of the webrtc api so only functions
-// from its upper class should be overridden here.
-class PortRangeSocketFactory : public rtc::BasicPacketSocketFactory {
- public:
- PortRangeSocketFactory(rtc::Thread* thread,
- std::pair<uint16_t, uint16_t> udp_port_range,
- std::pair<uint16_t, uint16_t> tcp_port_range);
-
- rtc::AsyncPacketSocket* CreateUdpSocket(
- const rtc::SocketAddress& local_address, uint16_t min_port,
- uint16_t max_port) override;
-
- rtc::AsyncPacketSocket* CreateServerTcpSocket(
- const rtc::SocketAddress& local_address, uint16_t min_port,
- uint16_t max_port, int opts) override;
-
- private:
- std::pair<uint16_t, uint16_t> udp_port_range_;
- std::pair<uint16_t, uint16_t> tcp_port_range_;
-};
-
-} // namespace webrtc_streaming
-} // namespace cuttlefish
diff --git a/host/frontend/webrtc/lib/streamer.cpp b/host/frontend/webrtc/lib/streamer.cpp
deleted file mode 100644
index 7fee1de71..000000000
--- a/host/frontend/webrtc/lib/streamer.cpp
+++ /dev/null
@@ -1,645 +0,0 @@
-/*
- * Copyright (C) 2020 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 "host/frontend/webrtc/lib/streamer.h"
-
-#include <android-base/logging.h>
-#include <json/json.h>
-
-#include <api/audio_codecs/audio_decoder_factory.h>
-#include <api/audio_codecs/audio_encoder_factory.h>
-#include <api/audio_codecs/builtin_audio_decoder_factory.h>
-#include <api/audio_codecs/builtin_audio_encoder_factory.h>
-#include <api/create_peerconnection_factory.h>
-#include <api/peer_connection_interface.h>
-#include <api/video_codecs/builtin_video_decoder_factory.h>
-#include <api/video_codecs/builtin_video_encoder_factory.h>
-#include <api/video_codecs/video_decoder_factory.h>
-#include <api/video_codecs/video_encoder_factory.h>
-#include <media/base/video_broadcaster.h>
-#include <pc/video_track_source.h>
-
-#include "host/frontend/webrtc/lib/audio_device.h"
-#include "host/frontend/webrtc/lib/audio_track_source_impl.h"
-#include "host/frontend/webrtc/lib/client_handler.h"
-#include "host/frontend/webrtc/lib/port_range_socket_factory.h"
-#include "host/frontend/webrtc/lib/video_track_source_impl.h"
-#include "host/frontend/webrtc/lib/vp8only_encoder_factory.h"
-#include "host/frontend/webrtc_operator/constants/signaling_constants.h"
-
-namespace cuttlefish {
-namespace webrtc_streaming {
-namespace {
-
-constexpr auto kStreamIdField = "stream_id";
-constexpr auto kXResField = "x_res";
-constexpr auto kYResField = "y_res";
-constexpr auto kDpiField = "dpi";
-constexpr auto kIsTouchField = "is_touch";
-constexpr auto kDisplaysField = "displays";
-constexpr auto kAudioStreamsField = "audio_streams";
-constexpr auto kHardwareField = "hardware";
-constexpr auto kControlPanelButtonCommand = "command";
-constexpr auto kControlPanelButtonTitle = "title";
-constexpr auto kControlPanelButtonIconName = "icon_name";
-constexpr auto kControlPanelButtonShellCommand = "shell_command";
-constexpr auto kControlPanelButtonDeviceStates = "device_states";
-constexpr auto kControlPanelButtonLidSwitchOpen = "lid_switch_open";
-constexpr auto kControlPanelButtonHingeAngleValue = "hinge_angle_value";
-constexpr auto kCustomControlPanelButtonsField = "custom_control_panel_buttons";
-
-void SendJson(WsConnection* ws_conn, const Json::Value& data) {
- Json::StreamWriterBuilder factory;
- auto data_str = Json::writeString(factory, data);
- ws_conn->Send(reinterpret_cast<const uint8_t*>(data_str.c_str()),
- data_str.size());
-}
-
-bool ParseMessage(const uint8_t* data, size_t length, Json::Value* msg_out) {
- auto str = reinterpret_cast<const char*>(data);
- Json::CharReaderBuilder builder;
- std::unique_ptr<Json::CharReader> json_reader(builder.newCharReader());
- std::string errorMessage;
- return json_reader->parse(str, str + length, msg_out, &errorMessage);
-}
-
-std::unique_ptr<rtc::Thread> CreateAndStartThread(const std::string& name) {
- auto thread = rtc::Thread::CreateWithSocketServer();
- if (!thread) {
- LOG(ERROR) << "Failed to create " << name << " thread";
- return nullptr;
- }
- thread->SetName(name, nullptr);
- if (!thread->Start()) {
- LOG(ERROR) << "Failed to start " << name << " thread";
- return nullptr;
- }
- return thread;
-}
-
-struct DisplayDescriptor {
- int width;
- int height;
- int dpi;
- bool touch_enabled;
- rtc::scoped_refptr<webrtc::VideoTrackSourceInterface> source;
-};
-
-struct ControlPanelButtonDescriptor {
- std::string command;
- std::string title;
- std::string icon_name;
- std::optional<std::string> shell_command;
- std::vector<DeviceState> device_states;
-};
-
-// TODO (jemoreira): move to a place in common with the signaling server
-struct OperatorServerConfig {
- std::vector<webrtc::PeerConnectionInterface::IceServer> servers;
-};
-
-// Wraps a scoped_refptr pointer to an audio device module
-class AudioDeviceModuleWrapper : public AudioSource {
- public:
- AudioDeviceModuleWrapper(
- rtc::scoped_refptr<CfAudioDeviceModule> device_module)
- : device_module_(device_module) {}
- int GetMoreAudioData(void* data, int bytes_per_sample,
- int samples_per_channel, int num_channels,
- int sample_rate, bool& muted) override {
- return device_module_->GetMoreAudioData(data, bytes_per_sample,
- samples_per_channel, num_channels,
- sample_rate, muted);
- }
-
- rtc::scoped_refptr<CfAudioDeviceModule> device_module() {
- return device_module_;
- }
-
- private:
- rtc::scoped_refptr<CfAudioDeviceModule> device_module_;
-};
-
-} // namespace
-
-class Streamer::Impl : public WsConnectionObserver {
- public:
- std::shared_ptr<ClientHandler> CreateClientHandler(int client_id);
-
- void SendMessageToClient(int client_id, const Json::Value& msg);
- void DestroyClientHandler(int client_id);
-
- // WsObserver
- void OnOpen() override;
- void OnClose() override;
- void OnError(const std::string& error) override;
- void OnReceive(const uint8_t* msg, size_t length, bool is_binary) override;
-
- void HandleConfigMessage(const Json::Value& msg);
- void HandleClientMessage(const Json::Value& server_message);
-
- // All accesses to these variables happen from the signal_thread, so there is
- // no need for extra synchronization mechanisms (mutex)
- StreamerConfig config_;
- OperatorServerConfig operator_config_;
- std::shared_ptr<WsConnection> server_connection_;
- std::shared_ptr<ConnectionObserverFactory> connection_observer_factory_;
- rtc::scoped_refptr<webrtc::PeerConnectionFactoryInterface>
- peer_connection_factory_;
- std::unique_ptr<rtc::Thread> network_thread_;
- std::unique_ptr<rtc::Thread> worker_thread_;
- std::unique_ptr<rtc::Thread> signal_thread_;
- std::map<std::string, DisplayDescriptor> displays_;
- std::map<std::string, rtc::scoped_refptr<AudioTrackSourceImpl>>
- audio_sources_;
- std::map<int, std::shared_ptr<ClientHandler>> clients_;
- std::weak_ptr<OperatorObserver> operator_observer_;
- std::map<std::string, std::string> hardware_;
- std::vector<ControlPanelButtonDescriptor> custom_control_panel_buttons_;
- std::shared_ptr<AudioDeviceModuleWrapper> audio_device_module_;
-};
-
-Streamer::Streamer(std::unique_ptr<Streamer::Impl> impl)
- : impl_(std::move(impl)) {}
-
-/* static */
-std::unique_ptr<Streamer> Streamer::Create(
- const StreamerConfig& cfg,
- std::shared_ptr<ConnectionObserverFactory> connection_observer_factory) {
-
- rtc::LogMessage::LogToDebug(rtc::LS_ERROR);
-
- std::unique_ptr<Streamer::Impl> impl(new Streamer::Impl());
- impl->config_ = cfg;
- impl->connection_observer_factory_ = connection_observer_factory;
-
- impl->network_thread_ = CreateAndStartThread("network-thread");
- impl->worker_thread_ = CreateAndStartThread("work-thread");
- impl->signal_thread_ = CreateAndStartThread("signal-thread");
- if (!impl->network_thread_ || !impl->worker_thread_ ||
- !impl->signal_thread_) {
- return nullptr;
- }
-
- impl->audio_device_module_ = std::make_shared<AudioDeviceModuleWrapper>(
- rtc::scoped_refptr<CfAudioDeviceModule>(
- new rtc::RefCountedObject<CfAudioDeviceModule>()));
-
- impl->peer_connection_factory_ = webrtc::CreatePeerConnectionFactory(
- impl->network_thread_.get(), impl->worker_thread_.get(),
- impl->signal_thread_.get(), impl->audio_device_module_->device_module(),
- webrtc::CreateBuiltinAudioEncoderFactory(),
- webrtc::CreateBuiltinAudioDecoderFactory(),
- std::make_unique<VP8OnlyEncoderFactory>(
- webrtc::CreateBuiltinVideoEncoderFactory()),
- webrtc::CreateBuiltinVideoDecoderFactory(), nullptr /* audio_mixer */,
- nullptr /* audio_processing */);
-
- if (!impl->peer_connection_factory_) {
- LOG(ERROR) << "Failed to create peer connection factory";
- return nullptr;
- }
-
- webrtc::PeerConnectionFactoryInterface::Options options;
- // By default the loopback network is ignored, but generating candidates for
- // it is useful when using TCP port forwarding.
- options.network_ignore_mask = 0;
- impl->peer_connection_factory_->SetOptions(options);
-
- return std::unique_ptr<Streamer>(new Streamer(std::move(impl)));
-}
-
-std::shared_ptr<VideoSink> Streamer::AddDisplay(const std::string& label,
- int width, int height, int dpi,
- bool touch_enabled) {
- // Usually called from an application thread
- return impl_->signal_thread_->Invoke<std::shared_ptr<VideoSink>>(
- RTC_FROM_HERE,
- [this, &label, width, height, dpi,
- touch_enabled]() -> std::shared_ptr<VideoSink> {
- if (impl_->displays_.count(label)) {
- LOG(ERROR) << "Display with same label already exists: " << label;
- return nullptr;
- }
- rtc::scoped_refptr<VideoTrackSourceImpl> source(
- new rtc::RefCountedObject<VideoTrackSourceImpl>(width, height));
- impl_->displays_[label] = {width, height, dpi, touch_enabled, source};
- return std::shared_ptr<VideoSink>(
- new VideoTrackSourceImplSinkWrapper(source));
- });
-}
-
-std::shared_ptr<AudioSink> Streamer::AddAudioStream(const std::string& label) {
- // Usually called from an application thread
- return impl_->signal_thread_->Invoke<std::shared_ptr<AudioSink>>(
- RTC_FROM_HERE, [this, &label]() -> std::shared_ptr<AudioSink> {
- if (impl_->audio_sources_.count(label)) {
- LOG(ERROR) << "Audio stream with same label already exists: "
- << label;
- return nullptr;
- }
- rtc::scoped_refptr<AudioTrackSourceImpl> source(
- new rtc::RefCountedObject<AudioTrackSourceImpl>());
- impl_->audio_sources_[label] = source;
- return std::shared_ptr<AudioSink>(
- new AudioTrackSourceImplSinkWrapper(source));
- });
-}
-
-std::shared_ptr<AudioSource> Streamer::GetAudioSource() {
- return impl_->audio_device_module_;
-}
-
-void Streamer::SetHardwareSpec(std::string key, std::string value) {
- impl_->hardware_.emplace(key, value);
-}
-
-void Streamer::AddCustomControlPanelButton(const std::string& command,
- const std::string& title,
- const std::string& icon_name) {
- ControlPanelButtonDescriptor button = {
- .command = command, .title = title, .icon_name = icon_name};
- impl_->custom_control_panel_buttons_.push_back(button);
-}
-
-void Streamer::AddCustomControlPanelButtonWithShellCommand(
- const std::string& command, const std::string& title,
- const std::string& icon_name, const std::string& shell_command) {
- ControlPanelButtonDescriptor button = {
- .command = command, .title = title, .icon_name = icon_name};
- button.shell_command = shell_command;
- impl_->custom_control_panel_buttons_.push_back(button);
-}
-
-void Streamer::AddCustomControlPanelButtonWithDeviceStates(
- const std::string& command, const std::string& title,
- const std::string& icon_name,
- const std::vector<DeviceState>& device_states) {
- ControlPanelButtonDescriptor button = {
- .command = command, .title = title, .icon_name = icon_name};
- button.device_states = device_states;
- impl_->custom_control_panel_buttons_.push_back(button);
-}
-
-void Streamer::Register(std::weak_ptr<OperatorObserver> observer) {
- // Usually called from an application thread
- // No need to block the calling thread on this, the observer will be notified
- // when the connection is established.
- impl_->signal_thread_->PostTask(RTC_FROM_HERE, [this, observer]() {
- impl_->operator_observer_ = observer;
- // This can be a local variable since the connection object will keep a
- // reference to it.
- auto ws_context = WsConnectionContext::Create();
- CHECK(ws_context) << "Failed to create websocket context";
- impl_->server_connection_ = ws_context->CreateConnection(
- impl_->config_.operator_server.port,
- impl_->config_.operator_server.addr,
- impl_->config_.operator_server.path,
- impl_->config_.operator_server.security, impl_,
- impl_->config_.operator_server.http_headers);
-
- CHECK(impl_->server_connection_)
- << "Unable to create websocket connection object";
-
- impl_->server_connection_->Connect();
- });
-}
-
-void Streamer::Unregister() {
- // Usually called from an application thread.
- impl_->signal_thread_->PostTask(
- RTC_FROM_HERE, [this]() { impl_->server_connection_.reset(); });
-}
-
-void Streamer::RecordDisplays(LocalRecorder& recorder) {
- for (auto& [key, display] : impl_->displays_) {
- rtc::scoped_refptr<webrtc::VideoTrackSourceInterface> source =
- display.source;
- auto deleter = [](webrtc::VideoTrackSourceInterface* source) {
- source->Release();
- };
- std::shared_ptr<webrtc::VideoTrackSourceInterface> source_shared(
- source.release(), deleter);
- recorder.AddDisplay(display.width, display.height, source_shared);
- }
-}
-
-void Streamer::Impl::OnOpen() {
- // Called from the websocket thread.
- // Connected to operator.
- signal_thread_->PostTask(RTC_FROM_HERE, [this]() {
- Json::Value register_obj;
- register_obj[cuttlefish::webrtc_signaling::kTypeField] =
- cuttlefish::webrtc_signaling::kRegisterType;
- register_obj[cuttlefish::webrtc_signaling::kDeviceIdField] =
- config_.device_id;
-
- Json::Value device_info;
- Json::Value displays(Json::ValueType::arrayValue);
- // No need to synchronize with other accesses to display_ because all
- // happens on signal_thread.
- for (auto& entry : displays_) {
- Json::Value display;
- display[kStreamIdField] = entry.first;
- display[kXResField] = entry.second.width;
- display[kYResField] = entry.second.height;
- display[kDpiField] = entry.second.dpi;
- display[kIsTouchField] = true;
- displays.append(display);
- }
- device_info[kDisplaysField] = displays;
- Json::Value audio_streams(Json::ValueType::arrayValue);
- for (auto& entry : audio_sources_) {
- Json::Value audio;
- audio[kStreamIdField] = entry.first;
- audio_streams.append(audio);
- }
- device_info[kAudioStreamsField] = audio_streams;
- Json::Value hardware;
- for (const auto& [k, v] : hardware_) {
- hardware[k] = v;
- }
- device_info[kHardwareField] = hardware;
- Json::Value custom_control_panel_buttons(Json::arrayValue);
- for (const auto& button : custom_control_panel_buttons_) {
- Json::Value button_entry;
- button_entry[kControlPanelButtonCommand] = button.command;
- button_entry[kControlPanelButtonTitle] = button.title;
- button_entry[kControlPanelButtonIconName] = button.icon_name;
- if (button.shell_command) {
- button_entry[kControlPanelButtonShellCommand] = *(button.shell_command);
- } else if (!button.device_states.empty()) {
- Json::Value device_states(Json::arrayValue);
- for (const DeviceState& device_state : button.device_states) {
- Json::Value device_state_entry;
- if (device_state.lid_switch_open) {
- device_state_entry[kControlPanelButtonLidSwitchOpen] =
- *device_state.lid_switch_open;
- }
- if (device_state.hinge_angle_value) {
- device_state_entry[kControlPanelButtonHingeAngleValue] =
- *device_state.hinge_angle_value;
- }
- device_states.append(device_state_entry);
- }
- button_entry[kControlPanelButtonDeviceStates] = device_states;
- }
- custom_control_panel_buttons.append(button_entry);
- }
- device_info[kCustomControlPanelButtonsField] = custom_control_panel_buttons;
- register_obj[cuttlefish::webrtc_signaling::kDeviceInfoField] = device_info;
- SendJson(server_connection_.get(), register_obj);
- // Do this last as OnRegistered() is user code and may take some time to
- // complete (although it shouldn't...)
- auto observer = operator_observer_.lock();
- if (observer) {
- observer->OnRegistered();
- }
- });
-}
-
-void Streamer::Impl::OnClose() {
- // Called from websocket thread
- // The operator shouldn't close the connection with the client, it's up to the
- // device to decide when to disconnect.
- LOG(WARNING) << "Websocket closed unexpectedly";
- signal_thread_->PostTask(RTC_FROM_HERE, [this]() {
- auto observer = operator_observer_.lock();
- if (observer) {
- observer->OnClose();
- }
- });
-}
-
-void Streamer::Impl::OnError(const std::string& error) {
- // Called from websocket thread.
- LOG(ERROR) << "Error on connection with the operator: " << error;
- signal_thread_->PostTask(RTC_FROM_HERE, [this]() {
- auto observer = operator_observer_.lock();
- if (observer) {
- observer->OnError();
- }
- });
-}
-
-void Streamer::Impl::HandleConfigMessage(const Json::Value& server_message) {
- CHECK(signal_thread_->IsCurrent())
- << __FUNCTION__ << " called from the wrong thread";
- if (server_message.isMember("ice_servers") &&
- server_message["ice_servers"].isArray()) {
- auto servers = server_message["ice_servers"];
- operator_config_.servers.clear();
- for (int server_idx = 0; server_idx < servers.size(); server_idx++) {
- auto server = servers[server_idx];
- webrtc::PeerConnectionInterface::IceServer ice_server;
- if (!server.isMember("urls") || !server["urls"].isArray()) {
- // The urls field is required
- LOG(WARNING)
- << "Invalid ICE server specification obtained from server: "
- << server.toStyledString();
- continue;
- }
- auto urls = server["urls"];
- for (int url_idx = 0; url_idx < urls.size(); url_idx++) {
- auto url = urls[url_idx];
- if (!url.isString()) {
- LOG(WARNING) << "Non string 'urls' field in ice server: "
- << url.toStyledString();
- continue;
- }
- ice_server.urls.push_back(url.asString());
- if (server.isMember("credential") && server["credential"].isString()) {
- ice_server.password = server["credential"].asString();
- }
- if (server.isMember("username") && server["username"].isString()) {
- ice_server.username = server["username"].asString();
- }
- operator_config_.servers.push_back(ice_server);
- }
- }
- }
-}
-
-void Streamer::Impl::HandleClientMessage(const Json::Value& server_message) {
- CHECK(signal_thread_->IsCurrent())
- << __FUNCTION__ << " called from the wrong thread";
- if (!server_message.isMember(cuttlefish::webrtc_signaling::kClientIdField) ||
- !server_message[cuttlefish::webrtc_signaling::kClientIdField].isInt()) {
- LOG(ERROR) << "Client message received without valid client id";
- return;
- }
- auto client_id =
- server_message[cuttlefish::webrtc_signaling::kClientIdField].asInt();
- if (!server_message.isMember(cuttlefish::webrtc_signaling::kPayloadField)) {
- LOG(WARNING) << "Received empty client message";
- return;
- }
- auto client_message =
- server_message[cuttlefish::webrtc_signaling::kPayloadField];
- if (clients_.count(client_id) == 0) {
- auto client_handler = CreateClientHandler(client_id);
- if (!client_handler) {
- LOG(ERROR) << "Failed to create a new client handler";
- return;
- }
- clients_.emplace(client_id, client_handler);
- }
- auto client_handler = clients_[client_id];
-
- client_handler->HandleMessage(client_message);
-}
-
-void Streamer::Impl::OnReceive(const uint8_t* msg, size_t length,
- bool is_binary) {
- // Usually called from websocket thread.
- Json::Value server_message;
- // Once OnReceive returns the buffer can be destroyed/recycled at any time, so
- // parse the data into a JSON object while still on the websocket thread.
- if (is_binary || !ParseMessage(msg, length, &server_message)) {
- LOG(ERROR) << "Received invalid JSON from server: '"
- << (is_binary ? std::string("(binary_data)")
- : std::string(msg, msg + length))
- << "'";
- return;
- }
- // Transition to the signal thread before member variables are accessed.
- signal_thread_->PostTask(RTC_FROM_HERE, [this, server_message]() {
- if (!server_message.isMember(cuttlefish::webrtc_signaling::kTypeField) ||
- !server_message[cuttlefish::webrtc_signaling::kTypeField].isString()) {
- LOG(ERROR) << "No message_type field from server";
- // Notify the caller
- OnError(
- "Invalid message received from operator: no message type field "
- "present");
- return;
- }
- auto type =
- server_message[cuttlefish::webrtc_signaling::kTypeField].asString();
- if (type == cuttlefish::webrtc_signaling::kConfigType) {
- HandleConfigMessage(server_message);
- } else if (type == cuttlefish::webrtc_signaling::kClientDisconnectType) {
- if (!server_message.isMember(
- cuttlefish::webrtc_signaling::kClientIdField) ||
- !server_message.isMember(
- cuttlefish::webrtc_signaling::kClientIdField)) {
- LOG(ERROR) << "Invalid disconnect message received from server";
- // Notify the caller
- OnError("Invalid disconnect message: client_id is required");
- return;
- }
- auto client_id =
- server_message[cuttlefish::webrtc_signaling::kClientIdField].asInt();
- LOG(INFO) << "Client " << client_id << " has disconnected.";
- DestroyClientHandler(client_id);
- } else if (type == cuttlefish::webrtc_signaling::kClientMessageType) {
- HandleClientMessage(server_message);
- } else {
- LOG(ERROR) << "Unknown message type: " << type;
- // Notify the caller
- OnError("Invalid message received from operator: unknown message type");
- return;
- }
- });
-}
-
-std::shared_ptr<ClientHandler> Streamer::Impl::CreateClientHandler(
- int client_id) {
- CHECK(signal_thread_->IsCurrent())
- << __FUNCTION__ << " called from the wrong thread";
- auto observer = connection_observer_factory_->CreateObserver();
-
- auto client_handler = ClientHandler::Create(
- client_id, observer,
- [this, client_id](const Json::Value& msg) {
- SendMessageToClient(client_id, msg);
- },
- [this, client_id] { DestroyClientHandler(client_id); });
-
- webrtc::PeerConnectionInterface::RTCConfiguration config;
- config.sdp_semantics = webrtc::SdpSemantics::kUnifiedPlan;
- config.enable_dtls_srtp = true;
- config.servers.insert(config.servers.end(), operator_config_.servers.begin(),
- operator_config_.servers.end());
- webrtc::PeerConnectionDependencies dependencies(client_handler.get());
- // PortRangeSocketFactory's super class' constructor needs to be called on the
- // network thread or have it as a parameter
- dependencies.packet_socket_factory.reset(new PortRangeSocketFactory(
- network_thread_.get(), config_.udp_port_range, config_.tcp_port_range));
- auto peer_connection = peer_connection_factory_->CreatePeerConnection(
- config, std::move(dependencies));
-
- if (!peer_connection) {
- LOG(ERROR) << "Failed to create peer connection";
- return nullptr;
- }
-
- if (!client_handler->SetPeerConnection(std::move(peer_connection))) {
- return nullptr;
- }
-
- for (auto& entry : displays_) {
- auto& label = entry.first;
- auto& video_source = entry.second.source;
-
- auto video_track =
- peer_connection_factory_->CreateVideoTrack(label, video_source.get());
- client_handler->AddDisplay(video_track, label);
- }
-
- for (auto& entry : audio_sources_) {
- auto& label = entry.first;
- auto& audio_stream = entry.second;
- auto audio_track =
- peer_connection_factory_->CreateAudioTrack(label, audio_stream.get());
- client_handler->AddAudio(audio_track, label);
- }
-
- return client_handler;
-}
-
-void Streamer::Impl::SendMessageToClient(int client_id,
- const Json::Value& msg) {
- LOG(VERBOSE) << "Sending to client: " << msg.toStyledString();
- CHECK(signal_thread_->IsCurrent())
- << __FUNCTION__ << " called from the wrong thread";
- Json::Value wrapper;
- wrapper[cuttlefish::webrtc_signaling::kPayloadField] = msg;
- wrapper[cuttlefish::webrtc_signaling::kTypeField] =
- cuttlefish::webrtc_signaling::kForwardType;
- wrapper[cuttlefish::webrtc_signaling::kClientIdField] = client_id;
- // This is safe to call from the webrtc threads because
- // WsConnection is thread safe
- SendJson(server_connection_.get(), wrapper);
-}
-
-void Streamer::Impl::DestroyClientHandler(int client_id) {
- // Usually called from signal thread, could be called from websocket thread or
- // an application thread.
- signal_thread_->PostTask(RTC_FROM_HERE, [this, client_id]() {
- // This needs to be 'posted' to the thread instead of 'invoked'
- // immediately for two reasons:
- // * The client handler is destroyed by this code, it's generally a
- // bad idea (though not necessarily wrong) to return to a member
- // function of a destroyed object.
- // * The client handler may call this from within a peer connection
- // observer callback, destroying the client handler there leads to a
- // deadlock.
- clients_.erase(client_id);
- });
-}
-
-} // namespace webrtc_streaming
-} // namespace cuttlefish
diff --git a/host/frontend/webrtc/lib/streamer.h b/host/frontend/webrtc/lib/streamer.h
deleted file mode 100644
index 0628e7d80..000000000
--- a/host/frontend/webrtc/lib/streamer.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright (C) 2020 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 <functional>
-#include <memory>
-#include <mutex>
-#include <optional>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include "host/libs/config/custom_actions.h"
-
-#include "host/frontend/webrtc/lib/audio_sink.h"
-#include "host/frontend/webrtc/lib/audio_source.h"
-#include "host/frontend/webrtc/lib/connection_observer.h"
-#include "host/frontend/webrtc/lib/local_recorder.h"
-#include "host/frontend/webrtc/lib/video_sink.h"
-#include "host/frontend/webrtc/lib/ws_connection.h"
-
-namespace cuttlefish {
-namespace webrtc_streaming {
-
-class ClientHandler;
-
-struct StreamerConfig {
- // The id with which to register with the operator server.
- std::string device_id;
- struct {
- // The ip address or domain name of the operator server.
- std::string addr;
- int port;
- // The path component of the operator server's register url.
- std::string path;
- // The security level to use when connecting to the operator server.
- WsConnection::Security security;
- // A list of key value pairs to include as HTTP handshake headers when
- // connecting to the operator.
- std::vector<std::pair<std::string, std::string>> http_headers;
- } operator_server;
- // The port ranges webrtc is allowed to use.
- // [0,0] means all ports
- std::pair<uint16_t, uint16_t> udp_port_range = {15550, 15558};
- std::pair<uint16_t, uint16_t> tcp_port_range = {15550, 15558};
-};
-
-class OperatorObserver {
- public:
- virtual ~OperatorObserver() = default;
- // Called when the websocket connection with the operator is established.
- virtual void OnRegistered() = 0;
- // Called when the websocket connection with the operator is closed.
- virtual void OnClose() = 0;
- // Called when an error is encountered in the connection to the operator.
- virtual void OnError() = 0;
-};
-
-class Streamer {
- public:
- // The observer_factory will be used to create an observer for every new
- // client connection. Unregister() needs to be called to stop accepting
- // connections.
- static std::unique_ptr<Streamer> Create(
- const StreamerConfig& cfg,
- std::shared_ptr<ConnectionObserverFactory> factory);
- ~Streamer() = default;
-
- std::shared_ptr<VideoSink> AddDisplay(const std::string& label, int width,
- int height, int dpi,
- bool touch_enabled);
-
- void SetHardwareSpec(std::string key, std::string value);
-
- template <typename V>
- void SetHardwareSpec(std::string key, V value) {
- SetHardwareSpec(key, std::to_string(value));
- }
-
- std::shared_ptr<AudioSink> AddAudioStream(const std::string& label);
- // Grants access to streams originating on the client side. If there are
- // multiple streams (either because one client sends more than one or there
- // are several clients) the audio will be mixed and provided as a single
- // stream here.
- std::shared_ptr<AudioSource> GetAudioSource();
-
- // Add a custom button to the control panel.
- void AddCustomControlPanelButton(const std::string& command,
- const std::string& title,
- const std::string& icon_name);
- void AddCustomControlPanelButtonWithShellCommand(
- const std::string& command, const std::string& title,
- const std::string& icon_name, const std::string& shell_command);
- void AddCustomControlPanelButtonWithDeviceStates(
- const std::string& command, const std::string& title,
- const std::string& icon_name,
- const std::vector<DeviceState>& device_states);
-
- // Register with the operator.
- void Register(std::weak_ptr<OperatorObserver> operator_observer);
- void Unregister();
-
- void RecordDisplays(LocalRecorder& recorder);
- private:
- /*
- * Private Implementation idiom.
- * https://en.cppreference.com/w/cpp/language/pimpl
- */
- class Impl;
-
- Streamer(std::unique_ptr<Impl> impl);
- std::shared_ptr<Impl> impl_;
-};
-
-} // namespace webrtc_streaming
-} // namespace cuttlefish
diff --git a/host/frontend/webrtc/lib/utils.cpp b/host/frontend/webrtc/lib/utils.cpp
deleted file mode 100644
index 78460c38e..000000000
--- a/host/frontend/webrtc/lib/utils.cpp
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2020 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 "host/frontend/webrtc/lib/utils.h"
-
-#include <map>
-
-#include <json/json.h>
-
-namespace cuttlefish {
-namespace webrtc_streaming {
-
-namespace {
-
-std::string ValidateField(const Json::Value &obj, const std::string &type,
- const std::string &field_name,
- const Json::ValueType &field_type, bool required) {
- if (!obj.isMember(field_name) && !required) {
- return "";
- }
- if (!(obj.isMember(field_name) &&
- obj[field_name].isConvertibleTo(field_type))) {
- std::string error_msg = "Expected a field named '";
- error_msg += field_name + "' of type '";
- error_msg += std::to_string(field_type);
- error_msg += "'";
- if (!type.empty()) {
- error_msg += " in message of type '" + type + "'";
- }
- error_msg += ".";
- return error_msg;
- }
- return "";
-}
-
-} // namespace
-
-ValidationResult ValidationResult::ValidateJsonObject(
- const Json::Value &obj, const std::string &type,
- const std::map<std::string, Json::ValueType> &required_fields,
- const std::map<std::string, Json::ValueType> &optional_fields) {
- for (const auto &field_spec : required_fields) {
- auto result =
- ValidateField(obj, type, field_spec.first, field_spec.second, true);
- if (!result.empty()) {
- return {result};
- }
- }
- for (const auto &field_spec : optional_fields) {
- auto result =
- ValidateField(obj, type, field_spec.first, field_spec.second, false);
- if (!result.empty()) {
- return {result};
- }
- }
- return {};
-}
-
-} // namespace webrtc_streaming
-} // namespace cuttlefish
diff --git a/host/frontend/webrtc/lib/utils.h b/host/frontend/webrtc/lib/utils.h
deleted file mode 100644
index 169221cd8..000000000
--- a/host/frontend/webrtc/lib/utils.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2020 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 <map>
-#include <optional>
-
-#include <json/json.h>
-
-namespace cuttlefish {
-namespace webrtc_streaming {
-
-class ValidationResult {
- public:
- ValidationResult() = default;
- ValidationResult(const std::string &error) : error_(error) {}
-
- // Helper method to ensure a json object has the required fields convertible
- // to the appropriate types.
- static ValidationResult ValidateJsonObject(
- const Json::Value &obj, const std::string &type,
- const std::map<std::string, Json::ValueType> &required_fields,
- const std::map<std::string, Json::ValueType> &optional_fields = {});
-
- bool ok() const { return !error_.has_value(); }
- std::string error() const { return error_.value_or(""); }
-
- private:
- std::optional<std::string> error_;
-};
-
-} // namespace webrtc_streaming
-} // namespace cuttlefish
diff --git a/host/frontend/webrtc/lib/video_frame_buffer.h b/host/frontend/webrtc/lib/video_frame_buffer.h
deleted file mode 100644
index b8240585a..000000000
--- a/host/frontend/webrtc/lib/video_frame_buffer.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2020 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 <cinttypes>
-
-namespace cuttlefish {
-namespace webrtc_streaming {
-
-class VideoFrameBuffer {
- public:
- virtual ~VideoFrameBuffer() = default;
-
- virtual int width() const = 0;
- virtual int height() const = 0;
- virtual int StrideY() const = 0;
- virtual int StrideU() const = 0;
- virtual int StrideV() const = 0;
- virtual const uint8_t* DataY() const = 0;
- virtual const uint8_t* DataU() const = 0;
- virtual const uint8_t* DataV() const = 0;
-};
-
-} // namespace webrtc_streaming
-} // namespace cuttlefish
diff --git a/host/frontend/webrtc/lib/video_sink.h b/host/frontend/webrtc/lib/video_sink.h
deleted file mode 100644
index 118a7c2a0..000000000
--- a/host/frontend/webrtc/lib/video_sink.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2020 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 <memory>
-
-#include "host/frontend/webrtc/lib/video_frame_buffer.h"
-
-namespace cuttlefish {
-namespace webrtc_streaming {
-
-class VideoSink {
- public:
- virtual ~VideoSink() = default;
- virtual void OnFrame(std::shared_ptr<VideoFrameBuffer> frame,
- int64_t timestamp_us) = 0;
-};
-
-} // namespace webrtc_streaming
-} // namespace cuttlefish
diff --git a/host/frontend/webrtc/lib/video_track_source_impl.cpp b/host/frontend/webrtc/lib/video_track_source_impl.cpp
deleted file mode 100644
index 6785e1523..000000000
--- a/host/frontend/webrtc/lib/video_track_source_impl.cpp
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2020 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 "host/frontend/webrtc/lib/video_track_source_impl.h"
-
-#include <api/video/video_frame_buffer.h>
-
-namespace cuttlefish {
-namespace webrtc_streaming {
-
-namespace {
-
-class VideoFrameWrapper : public webrtc::I420BufferInterface {
- public:
- VideoFrameWrapper(
- std::shared_ptr<::cuttlefish::webrtc_streaming::VideoFrameBuffer>
- frame_buffer)
- : frame_buffer_(frame_buffer) {}
- ~VideoFrameWrapper() override = default;
- // From VideoFrameBuffer
- int width() const override { return frame_buffer_->width(); }
- int height() const override { return frame_buffer_->height(); }
-
- // From class PlanarYuvBuffer
- int StrideY() const override { return frame_buffer_->StrideY(); }
- int StrideU() const override { return frame_buffer_->StrideU(); }
- int StrideV() const override { return frame_buffer_->StrideV(); }
-
- // From class PlanarYuv8Buffer
- const uint8_t *DataY() const override { return frame_buffer_->DataY(); }
- const uint8_t *DataU() const override { return frame_buffer_->DataU(); }
- const uint8_t *DataV() const override { return frame_buffer_->DataV(); }
-
- private:
- std::shared_ptr<::cuttlefish::webrtc_streaming::VideoFrameBuffer>
- frame_buffer_;
-};
-
-} // namespace
-
-VideoTrackSourceImpl::VideoTrackSourceImpl(int width, int height)
- : webrtc::VideoTrackSource(false), width_(width), height_(height) {}
-
-void VideoTrackSourceImpl::OnFrame(std::shared_ptr<VideoFrameBuffer> frame,
- int64_t timestamp_us) {
- auto video_frame =
- webrtc::VideoFrame::Builder()
- .set_video_frame_buffer(
- new rtc::RefCountedObject<VideoFrameWrapper>(frame))
- .set_timestamp_us(timestamp_us)
- .build();
- broadcaster_.OnFrame(video_frame);
-}
-
-bool VideoTrackSourceImpl::GetStats(Stats *stats) {
- stats->input_height = height_;
- stats->input_width = width_;
- return true;
-}
-
-bool VideoTrackSourceImpl::SupportsEncodedOutput() const { return false; }
-rtc::VideoSourceInterface<webrtc::VideoFrame> *VideoTrackSourceImpl::source() {
- return &broadcaster_;
-}
-
-} // namespace webrtc_streaming
-} // namespace cuttlefish
diff --git a/host/frontend/webrtc/lib/video_track_source_impl.h b/host/frontend/webrtc/lib/video_track_source_impl.h
deleted file mode 100644
index b3861aca2..000000000
--- a/host/frontend/webrtc/lib/video_track_source_impl.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2020 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 <media/base/video_broadcaster.h>
-#include <pc/video_track_source.h>
-
-#include "host/frontend/webrtc/lib/video_sink.h"
-
-namespace cuttlefish {
-namespace webrtc_streaming {
-
-class VideoTrackSourceImpl : public webrtc::VideoTrackSource {
- public:
- VideoTrackSourceImpl(int width, int height);
-
- void OnFrame(std::shared_ptr<VideoFrameBuffer> frame, int64_t timestamp_us);
-
- // Returns false if no stats are available, e.g, for a remote source, or a
- // source which has not seen its first frame yet.
- //
- // Implementation should avoid blocking.
- bool GetStats(Stats* stats) override;
-
- bool SupportsEncodedOutput() const override;
- void GenerateKeyFrame() override {}
- void AddEncodedSink(
- rtc::VideoSinkInterface<webrtc::RecordableEncodedFrame>* sink) override {}
- void RemoveEncodedSink(
- rtc::VideoSinkInterface<webrtc::RecordableEncodedFrame>* sink) override {}
-
- rtc::VideoSourceInterface<webrtc::VideoFrame>* source() override;
-
- private:
- int width_;
- int height_;
- rtc::VideoBroadcaster broadcaster_;
-};
-
-// Wraps a VideoTrackSourceImpl as an implementation of the VideoSink interface.
-// This is needed as the VideoTrackSourceImpl is a reference counted object that
-// should only be referenced by rtc::scoped_refptr pointers, but the
-// VideoSink interface is not a reference counted object and therefore not
-// compatible with that kind of pointers. This class can be referenced by a
-// shared pointer and it in turn holds a scoped_refptr to the wrapped object.
-class VideoTrackSourceImplSinkWrapper : public VideoSink {
- public:
- virtual ~VideoTrackSourceImplSinkWrapper() = default;
-
- VideoTrackSourceImplSinkWrapper(rtc::scoped_refptr<VideoTrackSourceImpl> obj)
- : track_source_impl_(obj) {}
-
- void OnFrame(std::shared_ptr<VideoFrameBuffer> frame,
- int64_t timestamp_us) override {
- track_source_impl_->OnFrame(frame, timestamp_us);
- }
-
- private:
- rtc::scoped_refptr<VideoTrackSourceImpl> track_source_impl_;
-};
-
-} // namespace webrtc_streaming
-} // namespace cuttlefish
diff --git a/host/frontend/webrtc/lib/vp8only_encoder_factory.cpp b/host/frontend/webrtc/lib/vp8only_encoder_factory.cpp
deleted file mode 100644
index ef69cfa44..000000000
--- a/host/frontend/webrtc/lib/vp8only_encoder_factory.cpp
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2020 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 "host/frontend/webrtc/lib/vp8only_encoder_factory.h"
-
-namespace cuttlefish {
-namespace webrtc_streaming {
-VP8OnlyEncoderFactory::VP8OnlyEncoderFactory(
- std::unique_ptr<webrtc::VideoEncoderFactory> inner)
- : inner_(std::move(inner)) {}
-
-std::vector<webrtc::SdpVideoFormat> VP8OnlyEncoderFactory::GetSupportedFormats()
- const {
- std::vector<webrtc::SdpVideoFormat> ret;
- // Allow only VP8
- for (auto& format : inner_->GetSupportedFormats()) {
- if (format.name == "VP8") {
- ret.push_back(format);
- }
- }
- return ret;
-}
-
-webrtc::VideoEncoderFactory::CodecInfo VP8OnlyEncoderFactory::QueryVideoEncoder(
- const webrtc::SdpVideoFormat& format) const {
- return inner_->QueryVideoEncoder(format);
-}
-
-std::unique_ptr<webrtc::VideoEncoder> VP8OnlyEncoderFactory::CreateVideoEncoder(
- const webrtc::SdpVideoFormat& format) {
- return inner_->CreateVideoEncoder(format);
-}
-
-std::unique_ptr<webrtc::VideoEncoderFactory::EncoderSelectorInterface>
-VP8OnlyEncoderFactory::GetEncoderSelector() const {
- return inner_->GetEncoderSelector();
-}
-
-} // namespace webrtc_streaming
-} // namespace cuttlefish
diff --git a/host/frontend/webrtc/lib/vp8only_encoder_factory.h b/host/frontend/webrtc/lib/vp8only_encoder_factory.h
deleted file mode 100644
index fcbdaebd0..000000000
--- a/host/frontend/webrtc/lib/vp8only_encoder_factory.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2020 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 <api/video_codecs/video_encoder_factory.h>
-#include <api/video_codecs/video_encoder.h>
-
-namespace cuttlefish {
-namespace webrtc_streaming {
-
-class VP8OnlyEncoderFactory : public webrtc::VideoEncoderFactory {
- public:
- VP8OnlyEncoderFactory(std::unique_ptr<webrtc::VideoEncoderFactory> inner);
-
- std::vector<webrtc::SdpVideoFormat> GetSupportedFormats() const override;
-
- CodecInfo QueryVideoEncoder(
- const webrtc::SdpVideoFormat& format) const override;
-
- std::unique_ptr<webrtc::VideoEncoder> CreateVideoEncoder(
- const webrtc::SdpVideoFormat& format) override;
-
- std::unique_ptr<EncoderSelectorInterface> GetEncoderSelector() const override;
-
- private:
- std::unique_ptr<webrtc::VideoEncoderFactory> inner_;
-};
-
-} // namespace webrtc_streaming
-} // namespace cuttlefish
diff --git a/host/frontend/webrtc/lib/ws_connection.cpp b/host/frontend/webrtc/lib/ws_connection.cpp
deleted file mode 100644
index 5303c21fb..000000000
--- a/host/frontend/webrtc/lib/ws_connection.cpp
+++ /dev/null
@@ -1,446 +0,0 @@
-//
-// Copyright (C) 2020 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
-//
-
-#include "host/frontend/webrtc/lib/ws_connection.h"
-
-#include <android-base/logging.h>
-#include <libwebsockets.h>
-
-class WsConnectionContextImpl;
-
-class WsConnectionImpl : public WsConnection,
- public std::enable_shared_from_this<WsConnectionImpl> {
- public:
- struct CreateConnectionSul {
- lws_sorted_usec_list_t sul = {};
- std::weak_ptr<WsConnectionImpl> weak_this;
- };
-
- WsConnectionImpl(
- int port, const std::string& addr, const std::string& path,
- Security secure,
- const std::vector<std::pair<std::string, std::string>>& headers,
- std::weak_ptr<WsConnectionObserver> observer,
- std::shared_ptr<WsConnectionContextImpl> context);
-
- ~WsConnectionImpl() override;
-
- void Connect() override;
- void ConnectInner();
-
- bool Send(const uint8_t* data, size_t len, bool binary = false) override;
-
- void OnError(const std::string& error);
- void OnReceive(const uint8_t* data, size_t len, bool is_binary);
- void OnOpen();
- void OnClose();
- void OnWriteable();
-
- void AddHttpHeaders(unsigned char** p, unsigned char* end) const;
-
- private:
- struct WsBuffer {
- WsBuffer() = default;
- WsBuffer(const uint8_t* data, size_t len, bool binary)
- : buffer_(LWS_PRE + len), is_binary_(binary) {
- memcpy(&buffer_[LWS_PRE], data, len);
- }
-
- uint8_t* data() { return &buffer_[LWS_PRE]; }
- bool is_binary() const { return is_binary_; }
- size_t size() const { return buffer_.size() - LWS_PRE; }
-
- private:
- std::vector<uint8_t> buffer_;
- bool is_binary_;
- };
-
- CreateConnectionSul extended_sul_;
- struct lws* wsi_;
- const int port_;
- const std::string addr_;
- const std::string path_;
- const Security security_;
- const std::vector<std::pair<std::string, std::string>> headers_;
-
- std::weak_ptr<WsConnectionObserver> observer_;
-
- // each element contains the data to be sent and whether it's binary or not
- std::deque<WsBuffer> write_queue_;
- std::mutex write_queue_mutex_;
- // The connection object should not outlive the context object. This reference
- // guarantees it.
- std::shared_ptr<WsConnectionContextImpl> context_;
-};
-
-class WsConnectionContextImpl
- : public WsConnectionContext,
- public std::enable_shared_from_this<WsConnectionContextImpl> {
- public:
- WsConnectionContextImpl(struct lws_context* lws_ctx);
- ~WsConnectionContextImpl() override;
-
- std::shared_ptr<WsConnection> CreateConnection(
- int port, const std::string& addr, const std::string& path,
- WsConnection::Security secure,
- std::weak_ptr<WsConnectionObserver> observer,
- const std::vector<std::pair<std::string, std::string>>& headers) override;
-
- void RememberConnection(void*, std::weak_ptr<WsConnectionImpl>);
- void ForgetConnection(void*);
- std::shared_ptr<WsConnectionImpl> GetConnection(void*);
-
- struct lws_context* lws_context() {
- return lws_context_;
- }
-
- private:
- void Start();
-
- std::map<void*, std::weak_ptr<WsConnectionImpl>> weak_by_ptr_;
- std::mutex map_mutex_;
- struct lws_context* lws_context_;
- std::thread message_loop_;
-};
-
-int LwsCallback(struct lws* wsi, enum lws_callback_reasons reason, void* user,
- void* in, size_t len);
-void CreateConnectionCallback(lws_sorted_usec_list_t* sul);
-
-namespace {
-
-constexpr char kProtocolName[] = "cf-webrtc-device";
-constexpr int kBufferSize = 65536;
-
-const uint32_t backoff_ms[] = {1000, 2000, 3000, 4000, 5000};
-
-const lws_retry_bo_t kRetry = {
- .retry_ms_table = backoff_ms,
- .retry_ms_table_count = LWS_ARRAY_SIZE(backoff_ms),
- .conceal_count = LWS_ARRAY_SIZE(backoff_ms),
-
- .secs_since_valid_ping = 3, /* force PINGs after secs idle */
- .secs_since_valid_hangup = 10, /* hangup after secs idle */
-
- .jitter_percent = 20,
-};
-
-const struct lws_protocols kProtocols[2] = {
- {kProtocolName, LwsCallback, 0, kBufferSize, 0, NULL, 0},
- {NULL, NULL, 0, 0, 0, NULL, 0}};
-
-} // namespace
-
-std::shared_ptr<WsConnectionContext> WsConnectionContext::Create() {
- struct lws_context_creation_info context_info = {};
- context_info.port = CONTEXT_PORT_NO_LISTEN;
- context_info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
- context_info.protocols = kProtocols;
- struct lws_context* lws_ctx = lws_create_context(&context_info);
- if (!lws_ctx) {
- return nullptr;
- }
- return std::shared_ptr<WsConnectionContext>(
- new WsConnectionContextImpl(lws_ctx));
-}
-
-WsConnectionContextImpl::WsConnectionContextImpl(struct lws_context* lws_ctx)
- : lws_context_(lws_ctx) {
- Start();
-}
-
-WsConnectionContextImpl::~WsConnectionContextImpl() {
- lws_context_destroy(lws_context_);
- if (message_loop_.joinable()) {
- message_loop_.join();
- }
-}
-
-void WsConnectionContextImpl::Start() {
- message_loop_ = std::thread([this]() {
- for (;;) {
- if (lws_service(lws_context_, 0) < 0) {
- break;
- }
- }
- });
-}
-
-std::shared_ptr<WsConnection> WsConnectionContextImpl::CreateConnection(
- int port, const std::string& addr, const std::string& path,
- WsConnection::Security security,
- std::weak_ptr<WsConnectionObserver> observer,
- const std::vector<std::pair<std::string, std::string>>& headers) {
- return std::shared_ptr<WsConnection>(new WsConnectionImpl(
- port, addr, path, security, headers, observer, shared_from_this()));
-}
-
-std::shared_ptr<WsConnectionImpl> WsConnectionContextImpl::GetConnection(
- void* raw) {
- std::shared_ptr<WsConnectionImpl> connection;
- {
- std::lock_guard<std::mutex> lock(map_mutex_);
- if (weak_by_ptr_.count(raw) == 0) {
- return nullptr;
- }
- connection = weak_by_ptr_[raw].lock();
- if (!connection) {
- weak_by_ptr_.erase(raw);
- }
- }
- return connection;
-}
-
-void WsConnectionContextImpl::RememberConnection(
- void* raw, std::weak_ptr<WsConnectionImpl> conn) {
- std::lock_guard<std::mutex> lock(map_mutex_);
- weak_by_ptr_.emplace(
- std::pair<void*, std::weak_ptr<WsConnectionImpl>>(raw, conn));
-}
-
-void WsConnectionContextImpl::ForgetConnection(void* raw) {
- std::lock_guard<std::mutex> lock(map_mutex_);
- weak_by_ptr_.erase(raw);
-}
-
-WsConnectionImpl::WsConnectionImpl(
- int port, const std::string& addr, const std::string& path,
- Security security,
- const std::vector<std::pair<std::string, std::string>>& headers,
- std::weak_ptr<WsConnectionObserver> observer,
- std::shared_ptr<WsConnectionContextImpl> context)
- : port_(port),
- addr_(addr),
- path_(path),
- security_(security),
- headers_(headers),
- observer_(observer),
- context_(context) {}
-
-WsConnectionImpl::~WsConnectionImpl() {
- context_->ForgetConnection(this);
- // This will cause the callback to be called which will drop the connection
- // after seeing the context doesn't remember this object
- lws_callback_on_writable(wsi_);
-}
-
-void WsConnectionImpl::Connect() {
- memset(&extended_sul_.sul, 0, sizeof(extended_sul_.sul));
- extended_sul_.weak_this = weak_from_this();
- lws_sul_schedule(context_->lws_context(), 0, &extended_sul_.sul,
- CreateConnectionCallback, 1);
-}
-
-void WsConnectionImpl::AddHttpHeaders(unsigned char** p,
- unsigned char* end) const {
- for (const auto& header_entry: headers_) {
- const auto& name = header_entry.first;
- const auto& value = header_entry.second;
- auto res = lws_add_http_header_by_name(
- wsi_, reinterpret_cast<const unsigned char*>(name.c_str()),
- reinterpret_cast<const unsigned char*>(value.c_str()), value.size(), p,
- end);
- if (res != 0) {
- LOG(ERROR) << "Unable to add header: " << name;
- }
- }
- if (!headers_.empty()) {
- // Let LWS know we added some headers.
- lws_client_http_body_pending(wsi_, 1);
- }
-}
-
-void WsConnectionImpl::OnError(const std::string& error) {
- auto observer = observer_.lock();
- if (observer) {
- observer->OnError(error);
- }
-}
-void WsConnectionImpl::OnReceive(const uint8_t* data, size_t len,
- bool is_binary) {
- auto observer = observer_.lock();
- if (observer) {
- observer->OnReceive(data, len, is_binary);
- }
-}
-void WsConnectionImpl::OnOpen() {
- auto observer = observer_.lock();
- if (observer) {
- observer->OnOpen();
- }
-}
-void WsConnectionImpl::OnClose() {
- auto observer = observer_.lock();
- if (observer) {
- observer->OnClose();
- }
-}
-
-void WsConnectionImpl::OnWriteable() {
- WsBuffer buffer;
- {
- std::lock_guard<std::mutex> lock(write_queue_mutex_);
- if (write_queue_.size() == 0) {
- return;
- }
- buffer = std::move(write_queue_.front());
- write_queue_.pop_front();
- }
- auto flags = lws_write_ws_flags(
- buffer.is_binary() ? LWS_WRITE_BINARY : LWS_WRITE_TEXT, true, true);
- auto res = lws_write(wsi_, buffer.data(), buffer.size(),
- (enum lws_write_protocol)flags);
- if (res != buffer.size()) {
- LOG(WARNING) << "Unable to send the entire message!";
- }
-}
-
-bool WsConnectionImpl::Send(const uint8_t* data, size_t len, bool binary) {
- if (!wsi_) {
- LOG(WARNING) << "Send called on an uninitialized connection!!";
- return false;
- }
- WsBuffer buffer(data, len, binary);
- {
- std::lock_guard<std::mutex> lock(write_queue_mutex_);
- write_queue_.emplace_back(std::move(buffer));
- }
-
- lws_callback_on_writable(wsi_);
- return true;
-}
-
-int LwsCallback(struct lws* wsi, enum lws_callback_reasons reason, void* user,
- void* in, size_t len) {
- constexpr int DROP = -1;
- constexpr int OK = 0;
-
- // For some values of `reason`, `user` doesn't point to the value provided
- // when the connection was created. This function object should be used with
- // care.
- auto with_connection =
- [wsi, user](std::function<void(std::shared_ptr<WsConnectionImpl>)> cb) {
- auto context = reinterpret_cast<WsConnectionContextImpl*>(user);
- auto connection = context->GetConnection(wsi);
- if (!connection) {
- return DROP;
- }
- cb(connection);
- return OK;
- };
-
- switch (reason) {
- case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
- return with_connection(
- [in](std::shared_ptr<WsConnectionImpl> connection) {
- connection->OnError(in ? (char*)in : "(null)");
- });
-
- case LWS_CALLBACK_CLIENT_RECEIVE:
- return with_connection(
- [in, len, wsi](std::shared_ptr<WsConnectionImpl> connection) {
- connection->OnReceive((const uint8_t*)in, len,
- lws_frame_is_binary(wsi));
- });
-
- case LWS_CALLBACK_CLIENT_ESTABLISHED:
- return with_connection([](std::shared_ptr<WsConnectionImpl> connection) {
- connection->OnOpen();
- });
-
- case LWS_CALLBACK_CLIENT_CLOSED:
- return with_connection([](std::shared_ptr<WsConnectionImpl> connection) {
- connection->OnClose();
- });
-
- case LWS_CALLBACK_CLIENT_WRITEABLE:
- return with_connection([](std::shared_ptr<WsConnectionImpl> connection) {
- connection->OnWriteable();
- });
-
- case LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER:
- return with_connection(
- [in, len](std::shared_ptr<WsConnectionImpl> connection) {
- auto p = reinterpret_cast<unsigned char**>(in);
- auto end = (*p) + len;
- connection->AddHttpHeaders(p, end);
- });
-
- case LWS_CALLBACK_CLIENT_HTTP_WRITEABLE:
- // This callback is only called when we add additional HTTP headers, let
- // LWS know we're done modifying the HTTP request.
- lws_client_http_body_pending(wsi, 0);
- return 0;
-
- default:
- LOG(VERBOSE) << "Unhandled value: " << reason;
- return lws_callback_http_dummy(wsi, reason, user, in, len);
- }
-}
-
-void CreateConnectionCallback(lws_sorted_usec_list_t* sul) {
- std::shared_ptr<WsConnectionImpl> connection =
- reinterpret_cast<WsConnectionImpl::CreateConnectionSul*>(sul)
- ->weak_this.lock();
- if (!connection) {
- LOG(WARNING) << "The object was already destroyed by the time of the first "
- << "connection attempt. That's unusual.";
- return;
- }
- connection->ConnectInner();
-}
-
-void WsConnectionImpl::ConnectInner() {
- struct lws_client_connect_info connect_info;
-
- memset(&connect_info, 0, sizeof(connect_info));
-
- connect_info.context = context_->lws_context();
- connect_info.port = port_;
- connect_info.address = addr_.c_str();
- connect_info.path = path_.c_str();
- connect_info.host = connect_info.address;
- connect_info.origin = connect_info.address;
- switch (security_) {
- case Security::kAllowSelfSigned:
- connect_info.ssl_connection = LCCSCF_ALLOW_SELFSIGNED |
- LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK |
- LCCSCF_USE_SSL;
- break;
- case Security::kStrict:
- connect_info.ssl_connection = LCCSCF_USE_SSL;
- break;
- case Security::kInsecure:
- connect_info.ssl_connection = 0;
- break;
- }
- connect_info.protocol = "webrtc-operator";
- connect_info.local_protocol_name = kProtocolName;
- connect_info.pwsi = &wsi_;
- connect_info.retry_and_idle_policy = &kRetry;
- // There is no guarantee the connection object still exists when the callback
- // is called. Put the context instead as the user data which is guaranteed to
- // still exist and holds a weak ptr to the connection.
- connect_info.userdata = context_.get();
-
- if (lws_client_connect_via_info(&connect_info)) {
- // wsi_ is not initialized until after the call to
- // lws_client_connect_via_info(). Luckily, this is guaranteed to run before
- // the protocol callback is called because it runs in the same loop.
- context_->RememberConnection(wsi_, weak_from_this());
- } else {
- LOG(ERROR) << "Connection failed!";
- }
-}
diff --git a/host/frontend/webrtc/lib/ws_connection.h b/host/frontend/webrtc/lib/ws_connection.h
deleted file mode 100644
index 1c03265f1..000000000
--- a/host/frontend/webrtc/lib/ws_connection.h
+++ /dev/null
@@ -1,72 +0,0 @@
-//
-// Copyright (C) 2020 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
-//
-
-#pragma once
-
-#include <string.h>
-
-#include <deque>
-#include <functional>
-#include <map>
-#include <memory>
-#include <mutex>
-#include <string>
-#include <thread>
-#include <vector>
-
-#include <libwebsockets.h>
-
-class WsConnectionObserver {
- public:
- virtual ~WsConnectionObserver() = default;
- virtual void OnOpen() = 0;
- virtual void OnClose() = 0;
- virtual void OnError(const std::string& error) = 0;
- virtual void OnReceive(const uint8_t* msg, size_t length, bool is_binary) = 0;
-};
-
-class WsConnection {
- public:
- enum class Security {
- kInsecure,
- kAllowSelfSigned,
- kStrict,
- };
-
- virtual ~WsConnection() = default;
-
- virtual void Connect() = 0;
-
- virtual bool Send(const uint8_t* data, size_t len, bool binary = false) = 0;
-
- protected:
- WsConnection() = default;
-};
-
-class WsConnectionContext {
- public:
- static std::shared_ptr<WsConnectionContext> Create();
-
- virtual ~WsConnectionContext() = default;
-
- virtual std::shared_ptr<WsConnection> CreateConnection(
- int port, const std::string& addr, const std::string& path,
- WsConnection::Security secure,
- std::weak_ptr<WsConnectionObserver> observer,
- const std::vector<std::pair<std::string, std::string>>& headers = {}) = 0;
-
- protected:
- WsConnectionContext() = default;
-};
diff --git a/host/frontend/webrtc/main.cpp b/host/frontend/webrtc/main.cpp
deleted file mode 100644
index 007c405b1..000000000
--- a/host/frontend/webrtc/main.cpp
+++ /dev/null
@@ -1,360 +0,0 @@
-/*
- * Copyright (C) 2020 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 <linux/input.h>
-
-#include <memory>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include <android-base/logging.h>
-#include <android-base/strings.h>
-#include <gflags/gflags.h>
-#include <libyuv.h>
-
-#include "common/libs/fs/shared_buf.h"
-#include "common/libs/fs/shared_fd.h"
-#include "common/libs/utils/files.h"
-#include "host/frontend/webrtc/audio_handler.h"
-#include "host/frontend/webrtc/connection_observer.h"
-#include "host/frontend/webrtc/display_handler.h"
-#include "host/frontend/webrtc/kernel_log_events_handler.h"
-#include "host/frontend/webrtc/lib/local_recorder.h"
-#include "host/frontend/webrtc/lib/streamer.h"
-#include "host/libs/audio_connector/server.h"
-#include "host/libs/config/cuttlefish_config.h"
-#include "host/libs/config/logging.h"
-#include "host/libs/confui/host_mode_ctrl.h"
-#include "host/libs/confui/host_server.h"
-#include "host/libs/screen_connector/screen_connector.h"
-
-DEFINE_int32(touch_fd, -1, "An fd to listen on for touch connections.");
-DEFINE_int32(keyboard_fd, -1, "An fd to listen on for keyboard connections.");
-DEFINE_int32(switches_fd, -1, "An fd to listen on for switch connections.");
-DEFINE_int32(frame_server_fd, -1, "An fd to listen on for frame updates");
-DEFINE_int32(kernel_log_events_fd, -1,
- "An fd to listen on for kernel log events.");
-DEFINE_int32(command_fd, -1, "An fd to listen to for control messages");
-DEFINE_string(action_servers, "",
- "A comma-separated list of server_name:fd pairs, "
- "where each entry corresponds to one custom action server.");
-DEFINE_bool(write_virtio_input, true,
- "Whether to send input events in virtio format.");
-DEFINE_int32(audio_server_fd, -1, "An fd to listen on for audio frames");
-
-using cuttlefish::AudioHandler;
-using cuttlefish::CfConnectionObserverFactory;
-using cuttlefish::DisplayHandler;
-using cuttlefish::KernelLogEventsHandler;
-using cuttlefish::webrtc_streaming::LocalRecorder;
-using cuttlefish::webrtc_streaming::Streamer;
-using cuttlefish::webrtc_streaming::StreamerConfig;
-
-class CfOperatorObserver
- : public cuttlefish::webrtc_streaming::OperatorObserver {
- public:
- virtual ~CfOperatorObserver() = default;
- virtual void OnRegistered() override {
- LOG(VERBOSE) << "Registered with Operator";
- }
- virtual void OnClose() override {
- LOG(ERROR) << "Connection with Operator unexpectedly closed";
- }
- virtual void OnError() override {
- LOG(ERROR) << "Error encountered in connection with Operator";
- }
-};
-
-static std::vector<std::pair<std::string, std::string>> ParseHttpHeaders(
- const std::string& path) {
- auto fd = cuttlefish::SharedFD::Open(path, O_RDONLY);
- if (!fd->IsOpen()) {
- LOG(WARNING) << "Unable to open operator (signaling server) headers file, "
- "connecting to the operator will probably fail: "
- << fd->StrError();
- return {};
- }
- std::string raw_headers;
- auto res = cuttlefish::ReadAll(fd, &raw_headers);
- if (res < 0) {
- LOG(WARNING) << "Unable to open operator (signaling server) headers file, "
- "connecting to the operator will probably fail: "
- << fd->StrError();
- return {};
- }
- std::vector<std::pair<std::string, std::string>> headers;
- std::size_t raw_index = 0;
- while (raw_index < raw_headers.size()) {
- auto colon_pos = raw_headers.find(':', raw_index);
- if (colon_pos == std::string::npos) {
- LOG(ERROR)
- << "Expected to find ':' in each line of the operator headers file";
- break;
- }
- auto eol_pos = raw_headers.find('\n', colon_pos);
- if (eol_pos == std::string::npos) {
- eol_pos = raw_headers.size();
- }
- // If the file uses \r\n as line delimiters exclude the \r too.
- auto eov_pos = raw_headers[eol_pos - 1] == '\r'? eol_pos - 1: eol_pos;
- headers.emplace_back(
- raw_headers.substr(raw_index, colon_pos + 1 - raw_index),
- raw_headers.substr(colon_pos + 1, eov_pos - colon_pos - 1));
- raw_index = eol_pos + 1;
- }
- return headers;
-}
-
-std::unique_ptr<cuttlefish::AudioServer> CreateAudioServer() {
- cuttlefish::SharedFD audio_server_fd =
- cuttlefish::SharedFD::Dup(FLAGS_audio_server_fd);
- close(FLAGS_audio_server_fd);
- return std::make_unique<cuttlefish::AudioServer>(audio_server_fd);
-}
-
-int main(int argc, char** argv) {
- cuttlefish::DefaultSubprocessLogging(argv);
- ::gflags::ParseCommandLineFlags(&argc, &argv, true);
-
- cuttlefish::InputSockets input_sockets;
-
- input_sockets.touch_server = cuttlefish::SharedFD::Dup(FLAGS_touch_fd);
- input_sockets.keyboard_server = cuttlefish::SharedFD::Dup(FLAGS_keyboard_fd);
- input_sockets.switches_server = cuttlefish::SharedFD::Dup(FLAGS_switches_fd);
- auto control_socket = cuttlefish::SharedFD::Dup(FLAGS_command_fd);
- close(FLAGS_touch_fd);
- close(FLAGS_keyboard_fd);
- close(FLAGS_switches_fd);
- close(FLAGS_command_fd);
- // Accepting on these sockets here means the device won't register with the
- // operator as soon as it could, but rather wait until crosvm's input display
- // devices have been initialized. That's OK though, because without those
- // devices there is no meaningful interaction the user can have with the
- // device.
- input_sockets.touch_client =
- cuttlefish::SharedFD::Accept(*input_sockets.touch_server);
- input_sockets.keyboard_client =
- cuttlefish::SharedFD::Accept(*input_sockets.keyboard_server);
- input_sockets.switches_client =
- cuttlefish::SharedFD::Accept(*input_sockets.switches_server);
-
- std::thread touch_accepter([&input_sockets]() {
- for (;;) {
- input_sockets.touch_client =
- cuttlefish::SharedFD::Accept(*input_sockets.touch_server);
- }
- });
- std::thread keyboard_accepter([&input_sockets]() {
- for (;;) {
- input_sockets.keyboard_client =
- cuttlefish::SharedFD::Accept(*input_sockets.keyboard_server);
- }
- });
- std::thread switches_accepter([&input_sockets]() {
- for (;;) {
- input_sockets.switches_client =
- cuttlefish::SharedFD::Accept(*input_sockets.switches_server);
- }
- });
-
- auto kernel_log_events_client =
- cuttlefish::SharedFD::Dup(FLAGS_kernel_log_events_fd);
- close(FLAGS_kernel_log_events_fd);
-
- auto cvd_config = cuttlefish::CuttlefishConfig::Get();
- auto instance = cvd_config->ForDefaultInstance();
- auto& host_mode_ctrl = cuttlefish::HostModeCtrl::Get();
- auto screen_connector_ptr = cuttlefish::DisplayHandler::ScreenConnector::Get(
- FLAGS_frame_server_fd, host_mode_ctrl);
- auto& screen_connector = *(screen_connector_ptr.get());
-
- // create confirmation UI service, giving host_mode_ctrl and
- // screen_connector
- // keep this singleton object alive until the webRTC process ends
- static auto& host_confui_server =
- cuttlefish::confui::HostServer::Get(host_mode_ctrl, screen_connector);
-
- StreamerConfig streamer_config;
-
- streamer_config.device_id = instance.webrtc_device_id();
- streamer_config.tcp_port_range = cvd_config->webrtc_tcp_port_range();
- streamer_config.udp_port_range = cvd_config->webrtc_udp_port_range();
- streamer_config.operator_server.addr = cvd_config->sig_server_address();
- streamer_config.operator_server.port = cvd_config->sig_server_port();
- streamer_config.operator_server.path = cvd_config->sig_server_path();
- streamer_config.operator_server.security =
- cvd_config->sig_server_strict()
- ? WsConnection::Security::kStrict
- : WsConnection::Security::kAllowSelfSigned;
-
- if (!cvd_config->sig_server_headers_path().empty()) {
- streamer_config.operator_server.http_headers =
- ParseHttpHeaders(cvd_config->sig_server_headers_path());
- }
-
- KernelLogEventsHandler kernel_logs_event_handler(kernel_log_events_client);
- auto observer_factory = std::make_shared<CfConnectionObserverFactory>(
- input_sockets, &kernel_logs_event_handler, host_confui_server);
-
- auto streamer = Streamer::Create(streamer_config, observer_factory);
- CHECK(streamer) << "Could not create streamer";
-
- auto display_0 = streamer->AddDisplay(
- "display_0", screen_connector.ScreenWidth(0),
- screen_connector.ScreenHeight(0), cvd_config->dpi(), true);
- auto display_handler = std::shared_ptr<DisplayHandler>(
- new DisplayHandler(display_0, screen_connector));
-
- std::unique_ptr<cuttlefish::webrtc_streaming::LocalRecorder> local_recorder;
- if (cvd_config->record_screen()) {
- int recording_num = 0;
- std::string recording_path;
- do {
- recording_path = instance.PerInstancePath("recording/recording_");
- recording_path += std::to_string(recording_num);
- recording_path += ".webm";
- recording_num++;
- } while (cuttlefish::FileExists(recording_path));
- local_recorder = LocalRecorder::Create(recording_path);
- CHECK(local_recorder) << "Could not create local recorder";
-
- streamer->RecordDisplays(*local_recorder);
- display_handler->IncClientCount();
- }
-
- observer_factory->SetDisplayHandler(display_handler);
-
- streamer->SetHardwareSpec("CPUs", cvd_config->cpus());
- streamer->SetHardwareSpec("RAM", std::to_string(cvd_config->memory_mb()) + " mb");
-
- std::string user_friendly_gpu_mode;
- if (cvd_config->gpu_mode() == cuttlefish::kGpuModeGuestSwiftshader) {
- user_friendly_gpu_mode = "SwiftShader (Guest CPU Rendering)";
- } else if (cvd_config->gpu_mode() == cuttlefish::kGpuModeDrmVirgl) {
- user_friendly_gpu_mode = "VirglRenderer (Accelerated Host GPU Rendering)";
- } else if (cvd_config->gpu_mode() == cuttlefish::kGpuModeGfxStream) {
- user_friendly_gpu_mode = "Gfxstream (Accelerated Host GPU Rendering)";
- } else {
- user_friendly_gpu_mode = cvd_config->gpu_mode();
- }
- streamer->SetHardwareSpec("GPU Mode", user_friendly_gpu_mode);
-
- std::shared_ptr<AudioHandler> audio_handler;
- if (cvd_config->enable_audio()) {
- auto audio_stream = streamer->AddAudioStream("audio");
- auto audio_server = CreateAudioServer();
- auto audio_source = streamer->GetAudioSource();
- audio_handler = std::make_shared<AudioHandler>(std::move(audio_server),
- audio_stream, audio_source);
- }
-
- // Parse the -action_servers flag, storing a map of action server name -> fd
- std::map<std::string, int> action_server_fds;
- for (const std::string& action_server :
- android::base::Split(FLAGS_action_servers, ",")) {
- if (action_server.empty()) {
- continue;
- }
- const std::vector<std::string> server_and_fd =
- android::base::Split(action_server, ":");
- CHECK(server_and_fd.size() == 2)
- << "Wrong format for action server flag: " << action_server;
- std::string server = server_and_fd[0];
- int fd = std::stoi(server_and_fd[1]);
- action_server_fds[server] = fd;
- }
-
- for (const auto& custom_action : cvd_config->custom_actions()) {
- if (custom_action.shell_command) {
- if (custom_action.buttons.size() != 1) {
- LOG(FATAL) << "Expected exactly one button for custom action command: "
- << *(custom_action.shell_command);
- }
- const auto button = custom_action.buttons[0];
- streamer->AddCustomControlPanelButtonWithShellCommand(
- button.command, button.title, button.icon_name,
- *(custom_action.shell_command));
- } else if (custom_action.server) {
- if (action_server_fds.find(*(custom_action.server)) !=
- action_server_fds.end()) {
- LOG(INFO) << "Connecting to custom action server "
- << *(custom_action.server);
-
- int fd = action_server_fds[*(custom_action.server)];
- cuttlefish::SharedFD custom_action_server = cuttlefish::SharedFD::Dup(fd);
- close(fd);
-
- if (custom_action_server->IsOpen()) {
- std::vector<std::string> commands_for_this_server;
- for (const auto& button : custom_action.buttons) {
- streamer->AddCustomControlPanelButton(button.command, button.title,
- button.icon_name);
- commands_for_this_server.push_back(button.command);
- }
- observer_factory->AddCustomActionServer(custom_action_server,
- commands_for_this_server);
- } else {
- LOG(ERROR) << "Error connecting to custom action server: "
- << *(custom_action.server);
- }
- } else {
- LOG(ERROR) << "Custom action server not provided as command line flag: "
- << *(custom_action.server);
- }
- } else if (!custom_action.device_states.empty()) {
- if (custom_action.buttons.size() != 1) {
- LOG(FATAL)
- << "Expected exactly one button for custom action device states.";
- }
- const auto button = custom_action.buttons[0];
- streamer->AddCustomControlPanelButtonWithDeviceStates(
- button.command, button.title, button.icon_name,
- custom_action.device_states);
- }
- }
-
- std::shared_ptr<cuttlefish::webrtc_streaming::OperatorObserver> operator_observer(
- new CfOperatorObserver());
- streamer->Register(operator_observer);
-
- std::thread control_thread([control_socket, &local_recorder]() {
- if (!local_recorder) {
- return;
- }
- std::string message = "_";
- int read_ret;
- while ((read_ret = cuttlefish::ReadExact(control_socket, &message)) > 0) {
- LOG(VERBOSE) << "received control message: " << message;
- if (message[0] == 'C') {
- LOG(DEBUG) << "Finalizing screen recording...";
- local_recorder->Stop();
- LOG(INFO) << "Finalized screen recording.";
- message = "Y";
- cuttlefish::WriteAll(control_socket, message);
- }
- }
- LOG(DEBUG) << "control socket closed";
- });
-
- if (audio_handler) {
- audio_handler->Start();
- }
- host_confui_server.Start();
- display_handler->Loop();
-
- return 0;
-}
diff --git a/host/frontend/webrtc_operator/Readme.md b/host/frontend/webrtc_operator/Readme.md
deleted file mode 100644
index df8b03773..000000000
--- a/host/frontend/webrtc_operator/Readme.md
+++ /dev/null
@@ -1,88 +0,0 @@
-This signaling server defines a very simple protocol to allow the establishing
-of a WebRTC connection between clients and devices. It should only be used for
-development purposes or for very simple applications with no security, privacy
-or scalability requirements.
-
-Serious applications should build their own signaling server, implementing the
-protocol exactly as defined below (any modifications would likely require
-modifications to the client and/or device which will then not be maintained by
-the cuttlefish team).
-
-The signaling server MUST expose two (different) websocket endpoints:
-
-* wss://<addr>/register_device
-* wss://<addr>/connect_client
-
-Additional endpoints are allowed and are up to the specific applications.
-Extending the messages below with additional fields should be done with extreme
-care, prefixing the field names with an applciation specific word is strongly
-recommended. The same holds true for creating new message types.
-
-Devices connect to the *register_device* endpoint and send these types of
-messages:
-
-* {"message_type": "register", "device_id": <String>, "device_info": <Any>}
-
-* {"message_type": "forward", "client_id": <Integer>, "payload": <Any>}
-
-The server sends the device these types of messages:
-
-* {"message_type": "config", "ice_servers": <Array of IceServer dictionaries>,
-...}
-
-* {"message_type": "client_msg", "client_id": <Integer>, "payload": <Any>}
-
-* {"message_type": "client_disconnected", "client_id": <Integer>}
-
-* {"error": <String>}
-
-Clients connect to the *connect_client* endpoint and send these types of
-messages:
-
-* {"message_type": "connect", "device_id": <String>}
-
-* {"message_type": "forward", "payload": <Any>}
-
-The server sends the clients these types of messages:
-
-* {"message_type": "config", "ice_servers": <Array of IceServer dictionaries>,
-...}
-
-* {"message_type": "device_info", "device_info": <Any>}
-
-* {"message_type": "device_msg", "payload": <Any>}
-
-* {"error": <String>}
-
-A typical application flow looks like this:
-
-* **Device** connects to *register_device*
-
-* **Device** sends **register** message
-
-* **Server** sends **config** message to **Device**
-
-* **Client** connects to *connect_client*
-
-* **Client** sends **connect** message
-
-* **Server** sends **config** message to **Client**
-
-* **Server** sends **device_info** message to **Client**
-
-* **Client** sends **forward** message
-
-* **Server** sends **client_msg** message to **Device** (at this point the
-device knows about the client and cand send **forward** messages intended for
-it)
-
-* **Device** sends **forward** message
-
-* **Server** sends **device_msg** message to client
-
-* ...
-
-In an alternative flow, not supported by this implementation but allowed by the
-design, the **Client** connects first and only receives a **config** message
-from the **Server**, only after the **Device** has sent the **register** message
-the **Server** sends the **device_info** messaage to the **Client**.
diff --git a/host/frontend/webrtc_operator/assets/controls.css b/host/frontend/webrtc_operator/assets/controls.css
deleted file mode 100644
index a2dce53f2..000000000
--- a/host/frontend/webrtc_operator/assets/controls.css
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2021 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.
- */
-
-.toggle-control {
- padding-left: 2px;
- padding-right: 7px;
- border-radius: 10px;
- background-color: #5f6368; /* Google grey 700 */
- width: 80px;
- height: 44px;
-}
-
-.toggle-control .toggle-control-icon {
- position: relative;
- display: inline-block;
- float: left;
- font-size: 44px;
- color: #e8eaed;
-}
-
-.toggle-control .toggle-control-switch {
- position: relative;
- display: inline-block;
- float:left;
- width: 36px;
- height: 21px;
- top: 11px;
-}
-
-.toggle-control .toggle-control-switch input {
- opacity: 0;
- width: 0;
- height: 0;
-}
-
-.toggle-control .toggle-control-slider {
- position: absolute;
- cursor: pointer;
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
- -webkit-transition: .4s;
- transition: .4s;
- border-radius: 21px;
- border: solid 4px;
- border-color: #e8eaed;
-}
-
-.toggle-control .toggle-control-slider:before {
- position: absolute;
- content: "";
- height: 12px;
- width: 12px;
- left: 1px;
- bottom: 1px;
- background-color: #e8eaed;
- -webkit-transition: .4s;
- transition: .4s;
- border-radius: 50%;
-}
-
-.toggle-control input:checked + .toggle-control-slider {
- background-color: #1c4587;
-}
-
-.toggle-control input:focus + .toggle-control-slider {
- box-shadow: 0 0 1px #2196F3;
-}
-
-.toggle-control input:checked + .toggle-control-slider:before {
- -webkit-transform: translateX(15px);
- -ms-transform: translateX(15px);
- transform: translateX(15px);
-}
diff --git a/host/frontend/webrtc_operator/assets/index.html b/host/frontend/webrtc_operator/assets/index.html
deleted file mode 100644
index 1eae8932a..000000000
--- a/host/frontend/webrtc_operator/assets/index.html
+++ /dev/null
@@ -1,85 +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.
- -->
-
-<html>
- <head>
- <title>My Virtual Device Playground</title>
-
- <link rel="stylesheet" type="text/css" href="style.css" >
- <link rel="stylesheet" type="text/css" href="controls.css" >
- <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons+Outlined">
- <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
- </head>
-
- <body>
- <section id='device-selector'>
- <h1>Available devices <span id='refresh-list'>&#8635;</span></h1>
- <ul id="device-list"></ul>
- </section>
- <section id='device-connection'>
- <div id='header'>
- <div id='app-controls'>
- <div id="keyboard-capture-control" title="Capture Keyboard"></div>
- <div id="mic-capture-control" title="Capture Microphone"></div>
- <audio autoplay controls id="device-audio"></audio>
- </div>
- <div id='status-div'>
- <h3 id='status-message' class='connecting'>Connecting to device</h3>
- </div>
- </div>
- <div id='controls-and-screens'>
- <div id='control-panel-default-buttons' class='control-panel-column'>
- <button id='device-details-button' title='Device Details' class='material-icons'>
- settings
- </button>
- <button id='bluetooth-console-button' title='Bluetooth console' class='material-icons'>
- settings_bluetooth
- </button>
- </div>
- <div id='control-panel-custom-buttons' class='control-panel-column'></div>
- <div id='screens'>
- <video id="device-screen" autoplay ></video>
- </div>
- </div>
- </section>
- <div id='device-details-modal' class='modal'>
- <div id='device-details-modal-header' class='modal-header'>
- <h2>Device Details</h2>
- <button id='device-details-close' title='Close' class='material-icons modal-close'>close</button>
- </div>
- <hr>
- <h3>Hardware Configuration</h3>
- <span id='device-details-hardware'>unknown</span>
- </div>
- <div id='bluetooth-console-modal' class='modal'>
- <div id='bluetooth-console-modal-header' class='modal-header'>
- <h2>Bluetooth Console</h2>
- <button id='bluetooth-console-close' title='Close' class='material-icons modal-close'>close</button>
- </div>
- <div>
- <table>
- <tr><td colspan='2'><textarea id='bluetooth-console-view' readonly rows='10' cols='60'></textarea></td></tr>
- <tr><td width='1'><p id='bluetooth-console-cmd-label'>Command:</p></td><td width='100'><input id='bluetooth-console-input' type='text'></input></td></tr>
- </table>
- </div>
- </div>
- <script src="js/adb.js"></script>
- <script src="js/rootcanal.js"></script>
- <script src="js/cf_webrtc.js" type="module"></script>
- <script src="js/controls.js"></script>
- <script src="js/app.js"></script>
- </body>
-</html>
diff --git a/host/frontend/webrtc_operator/assets/js/adb.js b/host/frontend/webrtc_operator/assets/js/adb.js
deleted file mode 100644
index 75540ae0c..000000000
--- a/host/frontend/webrtc_operator/assets/js/adb.js
+++ /dev/null
@@ -1,204 +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.
- */
-
-let adb_ws;
-
-let utf8Encoder = new TextEncoder();
-let utf8Decoder = new TextDecoder();
-
-const A_CNXN = 0x4e584e43;
-const A_OPEN = 0x4e45504f;
-const A_WRTE = 0x45545257;
-const A_OKAY = 0x59414b4f;
-
-const kLocalChannelId = 666;
-
-let array = new Uint8Array();
-
-function setU32LE(array, offset, x) {
- array[offset] = x & 0xff;
- array[offset + 1] = (x >> 8) & 0xff;
- array[offset + 2] = (x >> 16) & 0xff;
- array[offset + 3] = x >> 24;
-}
-
-function getU32LE(array, offset) {
- let x = array[offset]
- | (array[offset + 1] << 8)
- | (array[offset + 2] << 16)
- | (array[offset + 3] << 24);
-
- return x >>> 0; // convert signed to unsigned if necessary.
-}
-
-function computeChecksum(array) {
- let sum = 0;
- let i;
- for (i = 0; i < array.length; ++i) {
- sum = ((sum + array[i]) & 0xffffffff) >>> 0;
- }
-
- return sum;
-}
-
-function createAdbMessage(command, arg0, arg1, payload) {
- let arrayBuffer = new ArrayBuffer(24 + payload.length);
- let array = new Uint8Array(arrayBuffer);
- setU32LE(array, 0, command);
- setU32LE(array, 4, arg0);
- setU32LE(array, 8, arg1);
- setU32LE(array, 12, payload.length);
- setU32LE(array, 16, computeChecksum(payload));
- setU32LE(array, 20, command ^ 0xffffffff);
- array.set(payload, 24);
-
- return arrayBuffer;
-}
-
-function adbOpenConnection() {
- let systemIdentity = utf8Encoder.encode("Cray_II:1234:whatever");
-
- let arrayBuffer = createAdbMessage(
- A_CNXN, 0x1000000, 256 * 1024, systemIdentity);
-
- adb_ws.send(arrayBuffer);
-}
-
-function adbShell(command) {
- let destination = utf8Encoder.encode("shell:" + command);
-
- let arrayBuffer = createAdbMessage(A_OPEN, kLocalChannelId, 0, destination);
- adb_ws.send(arrayBuffer);
- awaitConnection();
-}
-
-function adbSendOkay(remoteId) {
- let payload = new Uint8Array(0);
-
- let arrayBuffer = createAdbMessage(
- A_OKAY, kLocalChannelId, remoteId, payload);
-
- adb_ws.send(arrayBuffer);
-}
-
-function JoinArrays(arr1, arr2) {
- let arr = new Uint8Array(arr1.length + arr2.length);
- arr.set(arr1, 0);
- arr.set(arr2, arr1.length);
- return arr;
-}
-
-// Simple lifecycle management that executes callbacks based on connection state.
-//
-// Any attempt to initiate a command (e.g. creating a connection, sending a message)
-// (re)starts a timer. Any response back from any command stops that timer.
-const timeoutMs = 3000;
-let connectedCb;
-let disconnectedCb;
-let disconnectedTimeout;
-function awaitConnection() {
- clearTimeout(disconnectedTimeout);
- if (disconnectedCb) {
- disconnectedTimeout = setTimeout(disconnectedCb, timeoutMs);
- }
-}
-function connected() {
- if (disconnectedTimeout) {
- clearTimeout(disconnectedTimeout);
- }
- if (connectedCb) {
- connectedCb();
- }
-}
-
-function adbOnMessage(arrayBuffer) {
- // console.log("adb_ws: onmessage (" + arrayBuffer.byteLength + " bytes)");
- array = JoinArrays(array, new Uint8Array(arrayBuffer));
-
- while (array.length > 0) {
- if (array.length < 24) {
- // Incomplete package, must wait for more data.
- return;
- }
-
- let command = getU32LE(array, 0);
- let magic = getU32LE(array, 20);
-
- if (command != ((magic ^ 0xffffffff) >>> 0)) {
- console.log("command = " + command + ", magic = " + magic);
- console.log("adb message command vs magic failed.");
- return;
- }
-
- let payloadLength = getU32LE(array, 12);
-
- if (array.length < 24 + payloadLength) {
- // Incomplete package, must wait for more data.
- return;
- }
-
- let payloadChecksum = getU32LE(array, 16);
- let checksum = computeChecksum(array.slice(24));
-
- if (payloadChecksum != checksum) {
- console.log("adb message checksum mismatch.");
- // This can happen if a shell command executes while another
- // channel is receiving data.
- }
-
- switch (command) {
- case A_CNXN:
- {
- console.log("WebRTC adb connected.");
- connected();
- break;
- }
-
- case A_OKAY:
- {
- let remoteId = getU32LE(array, 4);
- console.log("WebRTC adb channel created w/ remoteId " + remoteId);
- connected();
- break;
- }
-
- case A_WRTE:
- {
- let remoteId = getU32LE(array, 4);
- adbSendOkay(remoteId);
- break;
- }
- }
- array = array.subarray(24 + payloadLength, array.length);
- }
-}
-
-function init_adb(devConn, ccb = connectedCb, dcb = disconnectedCb) {
- if (adb_ws) return;
-
- adb_ws = {
- send: function(buffer) {
- devConn.sendAdbMessage(buffer);
- }
- };
- connectedCb = ccb;
- disconnectedCb = dcb;
- awaitConnection();
-
- devConn.onAdbMessage(msg => adbOnMessage(msg));
-
- adbOpenConnection();
-}
diff --git a/host/frontend/webrtc_operator/assets/js/app.js b/host/frontend/webrtc_operator/assets/js/app.js
deleted file mode 100644
index 441df004c..000000000
--- a/host/frontend/webrtc_operator/assets/js/app.js
+++ /dev/null
@@ -1,793 +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.
- */
-
-'use strict';
-
-function ConnectToDevice(device_id) {
- console.log('ConnectToDevice ', device_id);
- const keyboardCaptureCtrl = document.getElementById('keyboard-capture-control');
- createToggleControl(keyboardCaptureCtrl, "keyboard", onKeyboardCaptureToggle);
- const micCaptureCtrl = document.getElementById('mic-capture-control');
- createToggleControl(micCaptureCtrl, "mic", onMicCaptureToggle);
-
- const deviceScreen = document.getElementById('device-screen');
- const deviceAudio = document.getElementById('device-audio');
- const statusMessage = document.getElementById('status-message');
-
- let connectionAttemptDuration = 0;
- const intervalMs = 500;
- let deviceStatusEllipsisCount = 0;
- let animateDeviceStatusMessage = setInterval(function() {
- connectionAttemptDuration += intervalMs;
- if (connectionAttemptDuration > 30000) {
- statusMessage.className = 'error';
- statusMessage.textContent = 'Connection should have occurred by now. ' +
- 'Please attempt to restart the guest device.';
- } else {
- if (connectionAttemptDuration > 15000) {
- statusMessage.textContent = 'Connection is taking longer than expected';
- } else {
- statusMessage.textContent = 'Connecting to device';
- }
- deviceStatusEllipsisCount = (deviceStatusEllipsisCount + 1) % 4;
- statusMessage.textContent += '.'.repeat(deviceStatusEllipsisCount);
- }
- }, intervalMs);
-
- deviceScreen.addEventListener('loadeddata', (evt) => {
- clearInterval(animateDeviceStatusMessage);
- statusMessage.textContent = 'Awaiting adb connection...';
- resizeDeviceView();
- deviceScreen.style.visibility = 'visible';
- // Enable the buttons after the screen is visible.
- for (const [_, button] of Object.entries(buttons)) {
- if (!button.adb) {
- button.button.disabled = false;
- }
- }
- // Start the adb connection if it is not already started.
- initializeAdb();
- });
-
- let videoStream;
- let display_label;
- let buttons = {};
- let mouseIsDown = false;
- let deviceConnection;
- let touchIdSlotMap = new Map();
- let touchSlots = new Array();
- let deviceStateLidSwitchOpen = null;
- let deviceStateHingeAngleValue = null;
-
- function showAdbConnected() {
- // Screen changed messages are not reported until after boot has completed.
- // Certain default adb buttons change screen state, so wait for boot
- // completion before enabling these buttons.
- statusMessage.className = 'connected';
- statusMessage.textContent =
- 'adb connection established successfully.';
- setTimeout(function() {
- statusMessage.style.visibility = 'hidden';
- }, 5000);
- for (const [_, button] of Object.entries(buttons)) {
- if (button.adb) {
- button.button.disabled = false;
- }
- }
- }
-
- function initializeAdb() {
- init_adb(
- deviceConnection,
- showAdbConnected,
- function() {
- statusMessage.className = 'error';
- statusMessage.textContent = 'adb connection failed.';
- statusMessage.style.visibility = 'visible';
- for (const [_, button] of Object.entries(buttons)) {
- if (button.adb) {
- button.button.disabled = true;
- }
- }
- });
- }
-
- let currentRotation = 0;
- let currentDisplayDetails;
- function onControlMessage(message) {
- let message_data = JSON.parse(message.data);
- console.log(message_data)
- let metadata = message_data.metadata;
- if (message_data.event == 'VIRTUAL_DEVICE_BOOT_STARTED') {
- // Start the adb connection after receiving the BOOT_STARTED message.
- // (This is after the adbd start message. Attempting to connect
- // immediately after adbd starts causes issues.)
- initializeAdb();
- }
- if (message_data.event == 'VIRTUAL_DEVICE_SCREEN_CHANGED') {
- if (metadata.rotation != currentRotation) {
- // Animate the screen rotation.
- deviceScreen.style.transition = 'transform 1s';
- } else {
- // Don't animate screen resizes, since these appear as odd sliding
- // animations if the screen is rotated due to the translateY.
- deviceScreen.style.transition = '';
- }
-
- currentRotation = metadata.rotation;
- updateDeviceDisplayDetails({
- dpi: metadata.dpi,
- x_res: metadata.width,
- y_res: metadata.height
- });
-
- resizeDeviceView();
- }
- }
-
- const screensDiv = document.getElementById('screens');
- function resizeDeviceView() {
- // Auto-scale the screen based on window size.
- // Max window width of 70%, allowing space for the control panel.
- let ww = screensDiv.offsetWidth * 0.7;
- let wh = screensDiv.offsetHeight;
- let vw = currentDisplayDetails.x_res;
- let vh = currentDisplayDetails.y_res;
- let scaling = vw * wh > vh * ww ? ww / vw : wh / vh;
- if (currentRotation == 0) {
- deviceScreen.style.transform = null;
- deviceScreen.style.width = vw * scaling;
- deviceScreen.style.height = vh * scaling;
- } else if (currentRotation == 1) {
- deviceScreen.style.transform =
- `rotateZ(-90deg) translateY(-${vh * scaling}px)`;
- // When rotated, w and h are swapped.
- deviceScreen.style.width = vh * scaling;
- deviceScreen.style.height = vw * scaling;
- }
- }
- window.onresize = resizeDeviceView;
-
- function createControlPanelButton(command, title, icon_name,
- listener=onControlPanelButton,
- parent_id='control-panel-default-buttons') {
- let button = document.createElement('button');
- document.getElementById(parent_id).appendChild(button);
- button.title = title;
- button.dataset.command = command;
- button.disabled = true;
- // Capture mousedown/up/out commands instead of click to enable
- // hold detection. mouseout is used to catch if the user moves the
- // mouse outside the button while holding down.
- button.addEventListener('mousedown', listener);
- button.addEventListener('mouseup', listener);
- button.addEventListener('mouseout', listener);
- // Set the button image using Material Design icons.
- // See http://google.github.io/material-design-icons
- // and https://material.io/resources/icons
- button.classList.add('material-icons');
- button.innerHTML = icon_name;
- buttons[command] = { 'button': button }
- return buttons[command];
- }
- createControlPanelButton('power', 'Power', 'power_settings_new');
- createControlPanelButton('home', 'Home', 'home');
- createControlPanelButton('menu', 'Menu', 'menu');
- createControlPanelButton('rotate', 'Rotate', 'screen_rotation', onRotateButton);
- buttons['rotate'].adb = true;
- createControlPanelButton('volumemute', 'Volume Mute', 'volume_mute');
- createControlPanelButton('volumedown', 'Volume Down', 'volume_down');
- createControlPanelButton('volumeup', 'Volume Up', 'volume_up');
-
- let modalOffsets = {}
- function createModalButton(button_id, modal_id, close_id) {
- const modalButton = document.getElementById(button_id);
- const modalDiv = document.getElementById(modal_id);
- const modalHeader = modalDiv.querySelector('.modal-header');
- const modalClose = document.getElementById(close_id);
-
- // Position the modal to the right of the show modal button.
- modalDiv.style.top = modalButton.offsetTop;
- modalDiv.style.left = modalButton.offsetWidth + 30;
-
- function showHideModal(show) {
- if (show) {
- modalButton.classList.add('modal-button-opened')
- modalDiv.style.display = 'block';
- } else {
- modalButton.classList.remove('modal-button-opened')
- modalDiv.style.display = 'none';
- }
- }
- // Allow the show modal button to toggle the modal,
- modalButton.addEventListener('click',
- evt => showHideModal(modalDiv.style.display != 'block'));
- // but the close button always closes.
- modalClose.addEventListener('click',
- evt => showHideModal(false));
-
- // Allow the modal to be dragged by the header.
- modalOffsets[modal_id] = {
- midDrag: false,
- mouseDownOffsetX: null,
- mouseDownOffsetY: null,
- }
- modalHeader.addEventListener('mousedown',
- evt => {
- modalOffsets[modal_id].midDrag = true;
- // Store the offset of the mouse location from the
- // modal's current location.
- modalOffsets[modal_id].mouseDownOffsetX =
- parseInt(modalDiv.style.left) - evt.clientX;
- modalOffsets[modal_id].mouseDownOffsetY =
- parseInt(modalDiv.style.top) - evt.clientY;
- });
- modalHeader.addEventListener('mousemove',
- evt => {
- let offsets = modalOffsets[modal_id];
- if (offsets.midDrag) {
- // Move the modal to the mouse location plus the
- // offset calculated on the initial mouse-down.
- modalDiv.style.left =
- evt.clientX + offsets.mouseDownOffsetX;
- modalDiv.style.top =
- evt.clientY + offsets.mouseDownOffsetY;
- }
- });
- document.addEventListener('mouseup',
- evt => {
- modalOffsets[modal_id].midDrag = false;
- });
- }
-
- createModalButton(
- 'device-details-button', 'device-details-modal', 'device-details-close');
- createModalButton(
- 'bluetooth-console-button', 'bluetooth-console-modal', 'bluetooth-console-close');
-
- let options = {
- wsUrl: ((location.protocol == 'http:') ? 'ws://' : 'wss://') +
- location.host + '/connect_client',
- };
-
- function showWebrtcError() {
- statusMessage.className = 'error';
- statusMessage.textContent = 'No connection to the guest device. ' +
- 'Please ensure the WebRTC process on the host machine is active.';
- statusMessage.style.visibility = 'visible';
- deviceScreen.style.display = 'none';
- for (const [_, button] of Object.entries(buttons)) {
- button.button.disabled = true;
- }
- }
-
- import('./cf_webrtc.js')
- .then(webrtcModule => webrtcModule.Connect(device_id, options))
- .then(devConn => {
- deviceConnection = devConn;
- // TODO(b/143667633): get multiple display configuration from the
- // description object
- console.log(deviceConnection.description);
- let stream_id = devConn.description.displays[0].stream_id;
- devConn.getStream(stream_id).then(stream => {
- videoStream = stream;
- display_label = stream_id;
- deviceScreen.srcObject = videoStream;
- }).catch(e => console.error('Unable to get display stream: ', e));
- for (const audio_desc of devConn.description.audio_streams) {
- let stream_id = audio_desc.stream_id;
- devConn.getStream(stream_id).then(stream => {
- deviceAudio.srcObject = stream;
- }).catch(e => console.error('Unable to get audio stream: ', e));
- }
- startMouseTracking(); // TODO stopMouseTracking() when disconnected
- updateDeviceHardwareDetails(deviceConnection.description.hardware);
- updateDeviceDisplayDetails(deviceConnection.description.displays[0]);
- if (deviceConnection.description.custom_control_panel_buttons.length > 0) {
- document.getElementById('control-panel-custom-buttons').style.display = 'flex';
- for (const button of deviceConnection.description.custom_control_panel_buttons) {
- if (button.shell_command) {
- // This button's command is handled by sending an ADB shell command.
- createControlPanelButton(button.command, button.title, button.icon_name,
- e => onCustomShellButton(button.shell_command, e),
- 'control-panel-custom-buttons');
- buttons[button.command].adb = true;
- } else if (button.device_states) {
- // This button corresponds to variable hardware device state(s).
- createControlPanelButton(button.command, button.title, button.icon_name,
- getCustomDeviceStateButtonCb(button.device_states),
- 'control-panel-custom-buttons');
- for (const device_state of button.device_states) {
- // hinge_angle is currently injected via an adb shell command that
- // triggers a guest binary.
- if ('hinge_angle_value' in device_state) {
- buttons[button.command].adb = true;
- }
- }
- } else {
- // This button's command is handled by custom action server.
- createControlPanelButton(button.command, button.title, button.icon_name,
- onControlPanelButton,
- 'control-panel-custom-buttons');
- }
- }
- }
- deviceConnection.onControlMessage(msg => onControlMessage(msg));
- // Start the screen as hidden. Only show when data is ready.
- deviceScreen.style.visibility = 'hidden';
- // Show the error message and disable buttons when the WebRTC connection fails.
- deviceConnection.onConnectionStateChange(state => {
- if (state == 'disconnected' || state == 'failed') {
- showWebrtcError();
- }
- });
- deviceConnection.onBluetoothMessage(msg => {
- bluetoothConsole.addLine(decodeRootcanalMessage(msg));
- });
- }, rejection => {
- console.error('Unable to connect: ', rejection);
- showWebrtcError();
- });
-
- let hardwareDetailsText = '';
- let displayDetailsText = '';
- let deviceStateDetailsText = '';
- function updateDeviceDetailsText() {
- document.getElementById('device-details-hardware').textContent = [
- hardwareDetailsText,
- deviceStateDetailsText,
- displayDetailsText,
- ].filter(e => e /*remove empty*/).join('\n');
- }
- function updateDeviceHardwareDetails(hardware) {
- let hardwareDetailsTextLines = [];
- Object.keys(hardware).forEach(function(key) {
- let value = hardware[key];
- hardwareDetailsTextLines.push(`${key} - ${value}`);
- });
-
- hardwareDetailsText = hardwareDetailsTextLines.join('\n');
- updateDeviceDetailsText();
- }
- function updateDeviceDisplayDetails(display) {
- currentDisplayDetails = display;
- let dpi = display.dpi;
- let x_res = display.x_res;
- let y_res = display.y_res;
- let rotated = currentRotation == 1 ? ' (Rotated)' : '';
- displayDetailsText = `Display - ${x_res}x${y_res} (${dpi}DPI)${rotated}`;
- updateDeviceDetailsText();
- }
- function updateDeviceStateDetails() {
- let deviceStateDetailsTextLines = [];
- if (deviceStateLidSwitchOpen != null) {
- let state = deviceStateLidSwitchOpen ? 'Opened' : 'Closed';
- deviceStateDetailsTextLines.push(`Lid Switch - ${state}`);
- }
- if (deviceStateHingeAngleValue != null) {
- deviceStateDetailsTextLines.push(`Hinge Angle - ${deviceStateHingeAngleValue}`);
- }
- deviceStateDetailsText = deviceStateDetailsTextLines.join('\n');
- updateDeviceDetailsText();
- }
-
- function onKeyboardCaptureToggle(enabled) {
- if (enabled) {
- startKeyboardTracking();
- } else {
- stopKeyboardTracking();
- }
- }
-
- function onMicCaptureToggle(enabled) {
- deviceConnection.useMic(enabled);
- }
-
- function cmdConsole(consoleViewName, consoleInputName) {
- let consoleView = document.getElementById(consoleViewName);
-
- let addString = function(str) {
- consoleView.value += str;
- consoleView.scrollTop = consoleView.scrollHeight;
- }
-
- let addLine = function(line) {
- addString(line + "\r\n");
- }
-
- let commandCallbacks = [];
-
- let addCommandListener = function(f) {
- commandCallbacks.push(f);
- }
-
- let onCommand = function(cmd) {
- cmd = cmd.trim();
-
- if (cmd.length == 0) return;
-
- commandCallbacks.forEach(f => {
- f(cmd);
- })
- }
-
- addCommandListener(cmd => addLine(">> " + cmd));
-
- let consoleInput = document.getElementById(consoleInputName);
-
- consoleInput.addEventListener('keydown', e => {
- if ((e.key && e.key == 'Enter') || e.keyCode == 13) {
- let command = e.target.value;
-
- e.target.value = '';
-
- onCommand(command);
- }
- })
-
- return {
- consoleView: consoleView,
- consoleInput: consoleInput,
- addLine: addLine,
- addString: addString,
- addCommandListener: addCommandListener,
- };
- }
-
- var bluetoothConsole = cmdConsole(
- 'bluetooth-console-view', 'bluetooth-console-input');
-
- bluetoothConsole.addCommandListener(cmd => {
- let inputArr = cmd.split(' ');
- let command = inputArr[0];
- inputArr.shift();
- let args = inputArr;
- deviceConnection.sendBluetoothMessage(createRootcanalMessage(command, args));
- })
-
- function onControlPanelButton(e) {
- if (e.type == 'mouseout' && e.which == 0) {
- // Ignore mouseout events if no mouse button is pressed.
- return;
- }
- deviceConnection.sendControlMessage(JSON.stringify({
- command: e.target.dataset.command,
- button_state: e.type == 'mousedown' ? "down" : "up",
- }));
- }
-
- function onRotateButton(e) {
- // Attempt to init adb again, in case the initial connection failed.
- // This succeeds immediately if already connected.
- initializeAdb();
- if (e.type == 'mousedown') {
- adbShell(
- '/vendor/bin/cuttlefish_sensor_injection rotate ' +
- (currentRotation == 0 ? 'landscape' : 'portrait'))
- }
- }
-
- function onCustomShellButton(shell_command, e) {
- // Attempt to init adb again, in case the initial connection failed.
- // This succeeds immediately if already connected.
- initializeAdb();
- if (e.type == 'mousedown') {
- adbShell(shell_command);
- }
- }
-
- function getCustomDeviceStateButtonCb(device_states) {
- let states = device_states;
- let index = 0;
- return e => {
- if (e.type == 'mousedown') {
- // Reset any overridden device state.
- adbShell('cmd device_state state reset');
- // Send a device_state message for the current state.
- let message = {
- command: 'device_state',
- ...states[index],
- };
- deviceConnection.sendControlMessage(JSON.stringify(message));
- console.log(JSON.stringify(message));
- if ('lid_switch_open' in states[index]) {
- deviceStateLidSwitchOpen = states[index].lid_switch_open;
- }
- if ('hinge_angle_value' in states[index]) {
- deviceStateHingeAngleValue = states[index].hinge_angle_value;
- // TODO(b/181157794): Use a custom Sensor HAL for hinge_angle injection
- // instead of this guest binary.
- adbShell(
- '/vendor/bin/cuttlefish_sensor_injection hinge_angle ' +
- states[index].hinge_angle_value);
- }
- // Update the Device Details view.
- updateDeviceStateDetails();
- // Cycle to the next state.
- index = (index + 1) % states.length;
- }
- }
- }
-
- function startMouseTracking() {
- if (window.PointerEvent) {
- deviceScreen.addEventListener('pointerdown', onStartDrag);
- deviceScreen.addEventListener('pointermove', onContinueDrag);
- deviceScreen.addEventListener('pointerup', onEndDrag);
- } else if (window.TouchEvent) {
- deviceScreen.addEventListener('touchstart', onStartDrag);
- deviceScreen.addEventListener('touchmove', onContinueDrag);
- deviceScreen.addEventListener('touchend', onEndDrag);
- } else if (window.MouseEvent) {
- deviceScreen.addEventListener('mousedown', onStartDrag);
- deviceScreen.addEventListener('mousemove', onContinueDrag);
- deviceScreen.addEventListener('mouseup', onEndDrag);
- }
- }
-
- function stopMouseTracking() {
- if (window.PointerEvent) {
- deviceScreen.removeEventListener('pointerdown', onStartDrag);
- deviceScreen.removeEventListener('pointermove', onContinueDrag);
- deviceScreen.removeEventListener('pointerup', onEndDrag);
- } else if (window.TouchEvent) {
- deviceScreen.removeEventListener('touchstart', onStartDrag);
- deviceScreen.removeEventListener('touchmove', onContinueDrag);
- deviceScreen.removeEventListener('touchend', onEndDrag);
- } else if (window.MouseEvent) {
- deviceScreen.removeEventListener('mousedown', onStartDrag);
- deviceScreen.removeEventListener('mousemove', onContinueDrag);
- deviceScreen.removeEventListener('mouseup', onEndDrag);
- }
- }
-
- function startKeyboardTracking() {
- document.addEventListener('keydown', onKeyEvent);
- document.addEventListener('keyup', onKeyEvent);
- }
-
- function stopKeyboardTracking() {
- document.removeEventListener('keydown', onKeyEvent);
- document.removeEventListener('keyup', onKeyEvent);
- }
-
- function onStartDrag(e) {
- e.preventDefault();
-
- // console.log("mousedown at " + e.pageX + " / " + e.pageY);
- mouseIsDown = true;
-
- sendEventUpdate(true, e);
- }
-
- function onEndDrag(e) {
- e.preventDefault();
-
- // console.log("mouseup at " + e.pageX + " / " + e.pageY);
- mouseIsDown = false;
-
- sendEventUpdate(false, e);
- }
-
- function onContinueDrag(e) {
- e.preventDefault();
-
- // console.log("mousemove at " + e.pageX + " / " + e.pageY + ", down=" +
- // mouseIsDown);
- if (mouseIsDown) {
- sendEventUpdate(true, e);
- }
- }
-
- function sendEventUpdate(down, e) {
- console.assert(deviceConnection, 'Can\'t send mouse update without device');
- var eventType = e.type.substring(0, 5);
-
- // Before the first video frame arrives there is no way to know width and
- // height of the device's screen, so turn every click into a click at 0x0.
- // A click at that position is not more dangerous than anywhere else since
- // the user is clicking blind anyways.
- const videoWidth = deviceScreen.videoWidth? deviceScreen.videoWidth: 1;
- const videoHeight = deviceScreen.videoHeight? deviceScreen.videoHeight: 1;
- const elementWidth = deviceScreen.offsetWidth? deviceScreen.offsetWidth: 1;
- const elementHeight = deviceScreen.offsetHeight? deviceScreen.offsetHeight: 1;
-
- // vh*ew > eh*vw? then scale h instead of w
- const scaleHeight = videoHeight * elementWidth > videoWidth * elementHeight;
- var elementScaling = 0, videoScaling = 0;
- if (scaleHeight) {
- elementScaling = elementHeight;
- videoScaling = videoHeight;
- } else {
- elementScaling = elementWidth;
- videoScaling = videoWidth;
- }
-
- // The screen uses the 'object-fit: cover' property in order to completely
- // fill the element while maintaining the screen content's aspect ratio.
- // Therefore:
- // - If vh*ew > eh*vw, w is scaled so that content width == element width
- // - Otherwise, h is scaled so that content height == element height
- const scaleWidth = videoHeight * elementWidth > videoWidth * elementHeight;
-
- // Convert to coordinates relative to the video by scaling.
- // (This matches the scaling used by 'object-fit: cover'.)
- //
- // This scaling is needed to translate from the in-browser x/y to the
- // on-device x/y.
- // - When the device screen has not been resized, this is simple: scale
- // the coordinates based on the ratio between the input video size and
- // the in-browser size.
- // - When the device screen has been resized, this scaling is still needed
- // even though the in-browser size and device size are identical. This
- // is due to the way WindowManager handles a resized screen, resized via
- // `adb shell wm size`:
- // - The ABS_X and ABS_Y max values of the screen retain their
- // original values equal to the value set when launching the device
- // (which equals the video size here).
- // - The sent ABS_X and ABS_Y values need to be scaled based on the
- // ratio between the max size (video size) and in-browser size.
- const scaling = scaleWidth ? videoWidth / elementWidth : videoHeight / elementHeight;
-
- var xArr = [];
- var yArr = [];
- var idArr = [];
- var slotArr = [];
-
- if (eventType == "mouse" || eventType == "point") {
- xArr.push(e.offsetX);
- yArr.push(e.offsetY);
-
- let thisId = -1;
- if (eventType == "point") {
- thisId = e.pointerId;
- }
-
- slotArr.push(0);
- idArr.push(thisId);
- } else if (eventType == "touch") {
- // touchstart: list of touch points that became active
- // touchmove: list of touch points that changed
- // touchend: list of touch points that were removed
- let changes = e.changedTouches;
- let rect = e.target.getBoundingClientRect();
- for (var i=0; i < changes.length; i++) {
- xArr.push(changes[i].pageX - rect.left);
- yArr.push(changes[i].pageY - rect.top);
- if (touchIdSlotMap.has(changes[i].identifier)) {
- let slot = touchIdSlotMap.get(changes[i].identifier);
-
- slotArr.push(slot);
- if (e.type == 'touchstart') {
- // error
- console.error('touchstart when already have slot');
- return;
- } else if (e.type == 'touchmove') {
- idArr.push(changes[i].identifier);
- } else if (e.type == 'touchend') {
- touchSlots[slot] = false;
- touchIdSlotMap.delete(changes[i].identifier);
- idArr.push(-1);
- }
- } else {
- if (e.type == 'touchstart') {
- let slot = -1;
- for (var j=0; j < touchSlots.length; j++) {
- if (!touchSlots[j]) {
- slot = j;
- break;
- }
- }
- if (slot == -1) {
- slot = touchSlots.length;
- touchSlots.push(true);
- }
- slotArr.push(slot);
- touchSlots[slot] = true;
- touchIdSlotMap.set(changes[i].identifier, slot);
- idArr.push(changes[i].identifier);
- } else if (e.type == 'touchmove') {
- // error
- console.error('touchmove when no slot');
- return;
- } else if (e.type == 'touchend') {
- // error
- console.error('touchend when no slot');
- return;
- }
- }
- }
- }
-
- for (var i=0; i < xArr.length; i++) {
- xArr[i] = xArr[i] * scaling;
- yArr[i] = yArr[i] * scaling;
-
- // Substract the offset produced by the difference in aspect ratio, if any.
- if (scaleWidth) {
- // Width was scaled, leaving excess content height, so subtract from y.
- yArr[i] -= (elementHeight * scaling - videoHeight) / 2;
- } else {
- // Height was scaled, leaving excess content width, so subtract from x.
- xArr[i] -= (elementWidth * scaling - videoWidth) / 2;
- }
-
- xArr[i] = Math.trunc(xArr[i]);
- yArr[i] = Math.trunc(yArr[i]);
- }
-
- // NOTE: Rotation is handled automatically because the CSS rotation through
- // transforms also rotates the coordinates of events on the object.
-
- deviceConnection.sendMultiTouch(
- {idArr, xArr, yArr, down, slotArr, display_label});
- }
-
- function onKeyEvent(e) {
- e.preventDefault();
- console.assert(deviceConnection, 'Can\'t send key event without device');
- deviceConnection.sendKeyEvent(e.code, e.type);
- }
-}
-
-/******************************************************************************/
-
-function ConnectDeviceCb(dev_id) {
- console.log('Connect: ' + dev_id);
- // Hide the device selection screen
- document.getElementById('device-selector').style.display = 'none';
- // Show the device control screen
- document.getElementById('device-connection').style.visibility = 'visible';
- ConnectToDevice(dev_id);
-}
-
-function ShowNewDeviceList(device_ids) {
- let ul = document.getElementById('device-list');
- ul.innerHTML = "";
- let count = 1;
- let device_to_button_map = {};
- for (const dev_id of device_ids) {
- const button_id = 'connect_' + count++;
- ul.innerHTML += ('<li class="device_entry" title="Connect to ' + dev_id
- + '">' + dev_id + '<button id="' + button_id
- + '" >Connect</button></li>');
- device_to_button_map[dev_id] = button_id;
- }
-
- for (const [dev_id, button_id] of Object.entries(device_to_button_map)) {
- document.getElementById(button_id).addEventListener(
- 'click', evt => ConnectDeviceCb(dev_id));
- }
-}
-
-function UpdateDeviceList() {
- let url = ((location.protocol == 'http:') ? 'ws:' : 'wss:') + location.host +
- '/list_devices';
- let ws = new WebSocket(url);
- ws.onopen = () => {
- ws.send("give me those device ids");
- };
- ws.onmessage = msg => {
- let device_ids = JSON.parse(msg.data);
- ShowNewDeviceList(device_ids);
- };
-}
-
-// Get any devices that are already connected
-UpdateDeviceList();
-// Update the list at the user's request
-document.getElementById('refresh-list')
- .addEventListener('click', evt => UpdateDeviceList());
diff --git a/host/frontend/webrtc_operator/assets/js/cf_webrtc.js b/host/frontend/webrtc_operator/assets/js/cf_webrtc.js
deleted file mode 100644
index c9d82132c..000000000
--- a/host/frontend/webrtc_operator/assets/js/cf_webrtc.js
+++ /dev/null
@@ -1,460 +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.
- */
-
-function createDataChannel(pc, label, onMessage) {
- console.log('creating data channel: ' + label);
- let dataChannel = pc.createDataChannel(label);
- // Return an object with a send function like that of the dataChannel, but
- // that only actually sends over the data channel once it has connected.
- return {
- channelPromise: new Promise((resolve, reject) => {
- dataChannel.onopen = (event) => {
- resolve(dataChannel);
- };
- dataChannel.onclose = () => {
- console.log(
- 'Data channel=' + label + ' state=' + dataChannel.readyState);
- };
- dataChannel.onmessage = onMessage ? onMessage : (msg) => {
- console.log('Data channel=' + label + ' data="' + msg.data + '"');
- };
- dataChannel.onerror = err => {
- reject(err);
- };
- }),
- send: function(msg) {
- this.channelPromise = this.channelPromise.then(channel => {
- channel.send(msg);
- return channel;
- })
- },
- };
-}
-
-function awaitDataChannel(pc, label, onMessage) {
- console.log('expecting data channel: ' + label);
- // Return an object with a send function like that of the dataChannel, but
- // that only actually sends over the data channel once it has connected.
- return {
- channelPromise: new Promise((resolve, reject) => {
- let prev_ondatachannel = pc.ondatachannel;
- pc.ondatachannel = ev => {
- let dataChannel = ev.channel;
- if (dataChannel.label == label) {
- dataChannel.onopen = (event) => {
- resolve(dataChannel);
- };
- dataChannel.onclose = () => {
- console.log(
- 'Data channel=' + label + ' state=' + dataChannel.readyState);
- };
- dataChannel.onmessage = onMessage ? onMessage : (msg) => {
- console.log('Data channel=' + label + ' data="' + msg.data + '"');
- };
- dataChannel.onerror = err => {
- reject(err);
- };
- } else if (prev_ondatachannel) {
- prev_ondatachannel(ev);
- }
- };
- }),
- send: function(msg) {
- this.channelPromise = this.channelPromise.then(channel => {
- channel.send(msg);
- return channel;
- })
- },
- };
-}
-
-class DeviceConnection {
- constructor(pc, control, audio_stream) {
- this._pc = pc;
- this._control = control;
- this._audio_stream = audio_stream;
- // Disable the microphone by default
- this.useMic(false);
- this._inputChannel = createDataChannel(pc, 'input-channel');
- this._adbChannel = createDataChannel(pc, 'adb-channel', (msg) => {
- if (this._onAdbMessage) {
- this._onAdbMessage(msg.data);
- } else {
- console.error('Received unexpected ADB message');
- }
- });
- this._controlChannel = awaitDataChannel(pc, 'device-control', (msg) => {
- if (this._onControlMessage) {
- this._onControlMessage(msg);
- } else {
- console.error('Received unexpected Control message');
- }
- });
- this._bluetoothChannel = createDataChannel(pc, 'bluetooth-channel', (msg) => {
- if (this._onBluetoothMessage) {
- this._onBluetoothMessage(msg.data);
- } else {
- console.error('Received unexpected Bluetooth message');
- }
- });
- this._streams = {};
- this._streamPromiseResolvers = {};
-
- pc.addEventListener('track', e => {
- console.log('Got remote stream: ', e);
- for (const stream of e.streams) {
- this._streams[stream.id] = stream;
- if (this._streamPromiseResolvers[stream.id]) {
- for (let resolver of this._streamPromiseResolvers[stream.id]) {
- resolver();
- }
- delete this._streamPromiseResolvers[stream.id];
- }
- }
- });
- }
-
- set description(desc) {
- this._description = desc;
- }
-
- get description() {
- return this._description;
- }
-
- getStream(stream_id) {
- return new Promise((resolve, reject) => {
- if (this._streams[stream_id]) {
- resolve(this._streams[stream_id]);
- } else {
- if (!this._streamPromiseResolvers[stream_id]) {
- this._streamPromiseResolvers[stream_id] = [];
- }
- this._streamPromiseResolvers[stream_id].push(resolve);
- }
- });
- }
-
- _sendJsonInput(evt) {
- this._inputChannel.send(JSON.stringify(evt));
- }
-
- sendMousePosition({x, y, down, display_label}) {
- this._sendJsonInput({
- type: 'mouse',
- down: down ? 1 : 0,
- x,
- y,
- display_label,
- });
- }
-
- // TODO (b/124121375): This should probably be an array of pointer events and
- // have different properties.
- sendMultiTouch({idArr, xArr, yArr, down, slotArr, display_label}) {
- this._sendJsonInput({
- type: 'multi-touch',
- id: idArr,
- x: xArr,
- y: yArr,
- down: down ? 1 : 0,
- slot: slotArr,
- display_label: display_label,
- });
- }
-
- sendKeyEvent(code, type) {
- this._sendJsonInput({type: 'keyboard', keycode: code, event_type: type});
- }
-
- disconnect() {
- this._pc.close();
- }
-
- // Sends binary data directly to the in-device adb daemon (skipping the host)
- sendAdbMessage(msg) {
- this._adbChannel.send(msg);
- }
-
- // Provide a callback to receive data from the in-device adb daemon
- onAdbMessage(cb) {
- this._onAdbMessage = cb;
- }
-
- // Send control commands to the device
- sendControlMessage(msg) {
- this._controlChannel.send(msg);
- }
-
- useMic(in_use) {
- if (this._audio_stream) {
- this._audio_stream.getTracks().forEach(track => track.enabled = in_use);
- }
- }
-
- // Provide a callback to receive control-related comms from the device
- onControlMessage(cb) {
- this._onControlMessage = cb;
- }
-
- sendBluetoothMessage(msg) {
- this._bluetoothChannel.send(msg);
- }
-
- onBluetoothMessage(cb) {
- this._onBluetoothMessage = cb;
- }
-
- // Provide a callback to receive connectionstatechange states.
- onConnectionStateChange(cb) {
- this._pc.addEventListener(
- 'connectionstatechange',
- evt => cb(this._pc.connectionState));
- }
-}
-
-
-class WebRTCControl {
- constructor({
- wsUrl = '',
- }) {
- /*
- * Private attributes:
- *
- * _wsPromise: promises the underlying websocket, should resolve when the
- * socket passes to OPEN state, will be rejecte/replaced by a
- * rejected promise if an error is detected on the socket.
- *
- * _onOffer
- * _onIceCandidate
- */
-
- this._promiseResolvers = {};
-
- this._wsPromise = new Promise((resolve, reject) => {
- let ws = new WebSocket(wsUrl);
- ws.onopen = () => {
- console.info(`Connected to ${wsUrl}`);
- resolve(ws);
- };
- ws.onerror = evt => {
- console.error('WebSocket error:', evt);
- reject(evt);
- // If the promise was already resolved the previous line has no effect
- this._wsPromise = Promise.reject(new Error(evt));
- };
- ws.onmessage = e => {
- let data = JSON.parse(e.data);
- this._onWebsocketMessage(data);
- };
- });
- }
-
- _onWebsocketMessage(message) {
- const type = message.message_type;
- if (message.error) {
- console.error(message.error);
- this._on_connection_failed(message.error);
- return;
- }
- switch (type) {
- case 'config':
- this._infra_config = message;
- break;
- case 'device_info':
- if (this._on_device_available) {
- this._on_device_available(message.device_info);
- delete this._on_device_available;
- } else {
- console.error('Received unsolicited device info');
- }
- break;
- case 'device_msg':
- this._onDeviceMessage(message.payload);
- break;
- default:
- console.error('Unrecognized message type from server: ', type);
- this._on_connection_failed('Unrecognized message type from server: ' + type);
- console.error(message);
- }
- }
-
- _onDeviceMessage(message) {
- let type = message.type;
- switch (type) {
- case 'offer':
- if (this._onOffer) {
- this._onOffer({type: 'offer', sdp: message.sdp});
- } else {
- console.error('Receive offer, but nothing is wating for it');
- }
- break;
- case 'ice-candidate':
- if (this._onIceCandidate) {
- this._onIceCandidate(new RTCIceCandidate({
- sdpMid: message.mid,
- sdpMLineIndex: message.mLineIndex,
- candidate: message.candidate
- }));
- } else {
- console.error('Received ice candidate but nothing is waiting for it');
- }
- break;
- default:
- console.error('Unrecognized message type from device: ', type);
- }
- }
-
- async _wsSendJson(obj) {
- let ws = await this._wsPromise;
- return ws.send(JSON.stringify(obj));
- }
- async _sendToDevice(payload) {
- this._wsSendJson({message_type: 'forward', payload});
- }
-
- onOffer(cb) {
- this._onOffer = cb;
- }
-
- onIceCandidate(cb) {
- this._onIceCandidate = cb;
- }
-
- async requestDevice(device_id) {
- return new Promise((resolve, reject) => {
- this._on_device_available = (deviceInfo) => resolve({
- deviceInfo,
- infraConfig: this._infra_config,
- });
- this._on_connection_failed = (error) => reject(error);
- this._wsSendJson({
- message_type: 'connect',
- device_id,
- });
- });
- }
-
- ConnectDevice() {
- console.log('ConnectDevice');
- this._sendToDevice({type: 'request-offer'});
- }
-
- /**
- * Sends a remote description to the device.
- */
- async sendClientDescription(desc) {
- console.log('sendClientDescription');
- this._sendToDevice({type: 'answer', sdp: desc.sdp});
- }
-
- /**
- * Sends an ICE candidate to the device
- */
- async sendIceCandidate(candidate) {
- this._sendToDevice({type: 'ice-candidate', candidate});
- }
-}
-
-function createPeerConnection(infra_config) {
- let pc_config = {iceServers: []};
- for (const stun of infra_config.ice_servers) {
- pc_config.iceServers.push({urls: 'stun:' + stun});
- }
- let pc = new RTCPeerConnection(pc_config);
-
- pc.addEventListener('icecandidate', evt => {
- console.log('Local ICE Candidate: ', evt.candidate);
- });
- pc.addEventListener('iceconnectionstatechange', evt => {
- console.log(`ICE State Change: ${pc.iceConnectionState}`);
- });
- pc.addEventListener(
- 'connectionstatechange',
- evt =>
- console.log(`WebRTC Connection State Change: ${pc.connectionState}`));
- return pc;
-}
-
-export async function Connect(deviceId, options) {
- let control = new WebRTCControl(options);
- let requestRet = await control.requestDevice(deviceId);
- let deviceInfo = requestRet.deviceInfo;
- let infraConfig = requestRet.infraConfig;
- console.log('Device available:');
- console.log(deviceInfo);
- let pc_config = {iceServers: []};
- if (infraConfig.ice_servers && infraConfig.ice_servers.length > 0) {
- for (const server of infraConfig.ice_servers) {
- pc_config.iceServers.push(server);
- }
- }
- let pc = createPeerConnection(infraConfig, control);
-
- let audioStream;
- try {
- audioStream =
- await navigator.mediaDevices.getUserMedia({video: false, audio: true});
- const audioTracks = audioStream.getAudioTracks();
- if (audioTracks.length > 0) {
- console.log(`Using Audio device: ${audioTracks[0].label}, with ${
- audioTracks.length} tracks`);
- audioTracks.forEach(track => pc.addTrack(track, audioStream));
- }
- } catch (e) {
- console.error("Failed to open audio device: ", e);
- }
-
- let deviceConnection = new DeviceConnection(pc, control, audioStream);
- deviceConnection.description = deviceInfo;
- async function acceptOfferAndReplyAnswer(offer) {
- try {
- await pc.setRemoteDescription(offer);
- let answer = await pc.createAnswer();
- console.log('Answer: ', answer);
- await pc.setLocalDescription(answer);
- await control.sendClientDescription(answer);
- } catch (e) {
- console.error('Error establishing WebRTC connection: ', e)
- throw e;
- }
- }
- control.onOffer(desc => {
- console.log('Offer: ', desc);
- acceptOfferAndReplyAnswer(desc);
- });
- control.onIceCandidate(iceCandidate => {
- console.log(`Remote ICE Candidate: `, iceCandidate);
- pc.addIceCandidate(iceCandidate);
- });
-
- pc.addEventListener('icecandidate', evt => {
- if (evt.candidate) control.sendIceCandidate(evt.candidate);
- });
- let connected_promise = new Promise((resolve, reject) => {
- pc.addEventListener('connectionstatechange', evt => {
- let state = pc.connectionState;
- if (state == 'connected') {
- resolve(deviceConnection);
- } else if (state == 'failed') {
- reject(evt);
- }
- });
- });
- control.ConnectDevice();
-
- return connected_promise;
-}
diff --git a/host/frontend/webrtc_operator/assets/js/controls.js b/host/frontend/webrtc_operator/assets/js/controls.js
deleted file mode 100644
index 31db04656..000000000
--- a/host/frontend/webrtc_operator/assets/js/controls.js
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2021 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.
- */
-
-function createToggleControl(elm, iconName, onChangeCb) {
- let icon = document.createElement("span");
- icon.classList.add("toggle-control-icon");
- icon.classList.add("material-icons-outlined");
- if (iconName) {
- icon.appendChild(document.createTextNode(iconName));
- }
- elm.appendChild(icon);
- let toggle = document.createElement("label");
- toggle.classList.add("toggle-control-switch");
- let input = document.createElement("input");
- input.type = "checkbox";
- toggle.appendChild(input);
- let slider = document.createElement("span");
- slider.classList.add("toggle-control-slider");
- toggle.appendChild(slider);
- elm.classList.add("toggle-control");
- elm.appendChild(toggle);
- if (onChangeCb) {
- input.onchange = e => onChangeCb(e.target.checked);
- }
-}
diff --git a/host/frontend/webrtc_operator/assets/js/rootcanal.js b/host/frontend/webrtc_operator/assets/js/rootcanal.js
deleted file mode 100644
index 4443bcde0..000000000
--- a/host/frontend/webrtc_operator/assets/js/rootcanal.js
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2021 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.
- */
-
-'use strict';
-
-function rootCanalCalculateMessageSize(name, args) {
- let result = 0;
-
- result += 1 + name.length; // length of name + it's data
- result += 1; // count of args
-
- for(let i = 0; i < args.length; i++) {
- result += 1; // length of args[i]
- result += args[i].length; // data of args[i]
- }
-
- return result;
-}
-
-function rootCanalAddU8(array, pos, val) {
- array[pos] = val & 0xff;
-
- return pos + 1;
-}
-
-function rootCanalAddPayload(array, pos, payload) {
- array.set(payload, pos);
-
- return pos + payload.length;
-}
-
-function rootCanalAddString(array, pos, val) {
- let curPos = pos;
-
- curPos = rootCanalAddU8(array, curPos, val.length);
-
- return rootCanalAddPayload(array, curPos, utf8Encoder.encode(val));
-}
-
-function createRootcanalMessage(command, args) {
- let messageSize = rootCanalCalculateMessageSize(command, args);
- let arrayBuffer = new ArrayBuffer(messageSize);
- let array = new Uint8Array(arrayBuffer);
- let pos = 0;
-
- pos = rootCanalAddString(array, pos, command);
- pos = rootCanalAddU8(array, pos, args.length);
-
- for(let i = 0; i < args.length; i++) {
- pos = rootCanalAddString(array, pos, args[i]);
- }
-
- return array;
-}
-
-function decodeRootcanalMessage(array) {
- let size = array[0];
- let message = array.slice(1);
-
- return utf8Decoder.decode(message);
-} \ No newline at end of file
diff --git a/host/frontend/webrtc_operator/assets/style.css b/host/frontend/webrtc_operator/assets/style.css
deleted file mode 100644
index 5d59b34c7..000000000
--- a/host/frontend/webrtc_operator/assets/style.css
+++ /dev/null
@@ -1,177 +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.
- */
-
-body {
- background-color:black;
- margin: 0;
-}
-
-#device-selector {
- color: whitesmoke;
-}
-#device-selector li.device-entry {
- cursor: pointer;
-}
-
-#refresh-list {
- cursor: pointer;
-}
-
-#device-list .device-entry button {
- margin-left: 10px;
-}
-
-#device-connection {
- visibility: hidden;
- max-height: 100vh;
-}
-
-
-/* Top header row. */
-
-#header {
- height: 64px;
- /* Items inside this use a row Flexbox.*/
- display: flex;
- align-items: center;
-}
-
-#app-controls {
- margin-left: 10px;
-}
-#app-controls > div {
- display: inline-block;
- position: relative;
- margin-right: 6px;
-}
-#device-audio {
- height: 44px;
-}
-
-#status-div {
- flex-grow: 1;
-}
-#status-message {
- color: white;
- font-family: 'Open Sans', sans-serif;
- padding: 10px;
- margin: 10px;
-}
-#status-message.connecting {
- /* dark yellow */
- background-color: #927836;
-}
-#status-message.error {
- /* dark red */
- background-color: #900000;
-}
-#status-message.connected {
- /* dark green */
- background-color: #007000;
-}
-
-/* Control panel buttons and device screen(s). */
-
-#controls-and-screens {
- height: calc(100% - 84px);
-
- /* Items inside this use a row Flexbox.*/
- display: flex;
-}
-#controls-and-screens div {
- margin-left: 5px;
- margin-right: 5px;
-}
-
-.modal {
- /* Start out hidden, and use absolute positioning. */
- display: none;
- position: absolute;
-
- border-radius: 10px;
- padding: 20px;
- padding-top: 1px;
-
- background-color: #5f6368ea; /* Semi-transparent Google grey 500 */
- color: white;
- font-family: 'Open Sans', sans-serif;
-}
-.modal-header {
- cursor: move;
- /* Items inside this use a row Flexbox.*/
- display: flex;
- justify-content: space-between;
-}
-.modal-close {
- color: white;
- border: none;
- outline: none;
- background-color: transparent;
-}
-#device-details-modal span {
- white-space: pre;
-}
-#bluetooth-console-input {
- width: 100%;
-}
-#bluetooth-console-cmd-label {
- color: white;
-}
-
-.control-panel-column {
- width: 50px;
- /* Items inside this use a column Flexbox.*/
- display: flex;
- flex-direction: column;
-}
-#control-panel-custom-buttons {
- display: none;
- /* Give the custom buttons column a blue background. */
- background-color: #1c4587ff;
- height: fit-content;
- border-radius: 10px;
-}
-
-.control-panel-column button {
- margin: 0px 0px 5px 0px;
- height: 50px;
- font-size: 32px;
-
- color: #e8eaed; /* Google grey 200 */
- border: none;
- outline: none;
- background-color: transparent;
-}
-.control-panel-column button:disabled {
- color: #9aa0a6; /* Google grey 500 */
-}
-.control-panel-column button.modal-button-opened {
- border-radius: 10px;
- background-color: #5f6368; /* Google grey 700 */
-}
-
-#screens {
- /* Take up the remaining width of the window.*/
- flex-grow: 1;
- /* Don't grow taller than the window.*/
- max-height: 100vh;
-}
-
-#device-screen {
- touch-action: none;
- transform-origin: top right;
- object-fit: cover;
-}
diff --git a/host/frontend/webrtc_operator/certs/server.crt b/host/frontend/webrtc_operator/certs/server.crt
deleted file mode 100644
index f871fcbe8..000000000
--- a/host/frontend/webrtc_operator/certs/server.crt
+++ /dev/null
@@ -1,20 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIDWTCCAkECFFsSgyQAZHRltRAdi9SrK2ZHRa1/MA0GCSqGSIb3DQEBCwUAMGgx
-CzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRQwEgYDVQQHDAtTYW50
-YSBDbGFyYTEaMBgGA1UECgwRQmV5b25kIEFnZ3JhdmF0ZWQxEjAQBgNVBAMMCWxv
-Y2FsaG9zdDAgFw0yMTA1MDgwNjUwMDBaGA8yMjk1MDIyMDA2NTAwMFowaDELMAkG
-A1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFDASBgNVBAcMC1NhbnRhIENs
-YXJhMRowGAYDVQQKDBFCZXlvbmQgQWdncmF2YXRlZDESMBAGA1UEAwwJbG9jYWxo
-b3N0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxijHKeNl7nlYwn3f
-6CG8MP3XDVI3bc4v+XIJElH2mrNz8AUd0I9FoJVEdCDnRIO1Vb7sN/Wn9fxMQQv2
-ReHE56kR36Ca19G5VFo789gt7268ibpV7QQ117aoeEdw7kpOukKUG87Q7bZWlsZ3
-FX/nxSv1Hnv5BABxo0uyM8tv5KGXWwR8bsmFCCEr8i2AtglOnyVSV3Ey18Vb/mgt
-+E4YE6WobTAiP8UdEKTPdnBms9IcHNknTB+ux910xDH4z9fWv8+4Bp4mH43xvbrt
-GJEzDl1xQ+Mrzc7Hk0FJqUlT6WHuyM9Tk7jspmhXxggtecy0CGB/hSo//urrUu2L
-EUABgQIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQBKNKU5S6HmO6atYLFmBfBk2ms/
-ZkDNHtDxnKLmsX3CFthRI3mGz1oEaMzYb2G2ufDxzh4/x2DM4iffRgj2knHSGlun
-3NYClZLM18/KTpXF26bycnixVGVw26jG0WHQTSdCS5VLz8CSg1O/487aEC5sKtoe
-LSk4KMpDFzD0+Esbkf/1aw0VyxsxjHRnxIMheK4cUt3y5I5qIKS2qK0W9ZuWr1Er
-dkYKCVumZKxVuMhHVOck6zLC5lZjefkFtTtyLe2nKIvXNWcHyuKqmLfafhEVSlKP
-Idg90Qo9+TY4bwQ8sMRVcVlnnChGvDtmeBXz4xwyFg8Pzhvwa86PlwMISi/m
------END CERTIFICATE-----
diff --git a/host/frontend/webrtc_operator/certs/server.key b/host/frontend/webrtc_operator/certs/server.key
deleted file mode 100644
index a6b8f9f22..000000000
--- a/host/frontend/webrtc_operator/certs/server.key
+++ /dev/null
@@ -1,27 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-MIIEpQIBAAKCAQEAxijHKeNl7nlYwn3f6CG8MP3XDVI3bc4v+XIJElH2mrNz8AUd
-0I9FoJVEdCDnRIO1Vb7sN/Wn9fxMQQv2ReHE56kR36Ca19G5VFo789gt7268ibpV
-7QQ117aoeEdw7kpOukKUG87Q7bZWlsZ3FX/nxSv1Hnv5BABxo0uyM8tv5KGXWwR8
-bsmFCCEr8i2AtglOnyVSV3Ey18Vb/mgt+E4YE6WobTAiP8UdEKTPdnBms9IcHNkn
-TB+ux910xDH4z9fWv8+4Bp4mH43xvbrtGJEzDl1xQ+Mrzc7Hk0FJqUlT6WHuyM9T
-k7jspmhXxggtecy0CGB/hSo//urrUu2LEUABgQIDAQABAoIBAQCt5QsiT1QcOpER
-3LSpWTF1LM2T+xp5Wf/vv4sGcLcge2q6r0LCy3gmu9ceseFB1vNDFBDn6sRCse2Z
-B45PNRk+0rfEr4Qy8PDafXUvP/7PpzX9B3BwVsmJS9n783W/J6Z+/f5LiOsAMIs8
-NV47l8sk1LZ+0fxs7pbK3pq7qUPANiEgKQ2F6PBkJkORuHmfhccC/a+qhAdsqwVB
-DjjwY0e5A/4fWqLiIUJGBopv0+df1TWsqfTq4lwaSDPY6dyI9E3MYVxKiYpbqgQ/
-N7QtjDjut6Zuw10bCgYyuEgy3Ab5Pmx6Hs6VGuYI6Hge4JeZ6TzZJ/cNnONZvGTF
-3356FYABAoGBAPgA+JYHDgXl4W6n9uMYQ4ZXL1UrYVxe8B1wWgt7DKD98/fD+Jj1
-KuRRUB2wLv/Jis+48QlAwLHQIL35WGpGm9C9j9dS3NO199BLrDY4fteSr67NrG9P
-Q0H+3F/7Dx7Scg5LNRYe6ZNvdfUD+9zoiaNHa9MMriK0ffc4O08RkA3BAoGBAMyM
-Y6c83Wek6GzPu5GCSMxEGBdqbx8T3iyEo4J23N3WAcfdIgSWZcjB2wNdNqa/RuHW
-QH6Gns5DLO3pYLU7R9DgLK5VE/Nq4nF0o7D57DnRkT+sZ3gYPdC7LiG3d5c+J7k1
-3pKL8yh7t2AgMpopfaY70wV4gL1K2qOLYfxbVGPBAoGBAK/Y2GpghDPwZOD2Xdt2
-R+LIjPpB8R3y/ySQlnhPfovkpYlHvkyOgiQz96+lTh32ROO2ycn6zOcHoT+yvltU
-x4TB9G0EBypie12JWolzk5S9IK68jQi71f/Ee3Pe60C6jT7PWsvdjVcKEERz17Ey
-fO12ZeDWu95Fxo91orAUzuTBAoGAC2xbtF9Fzh/7ivge9YVdI2s6HTSoeAfYBIxz
-xTl2JD1rZAoJeFAd5xRMcuelwbI09y/L8kT6YXKG89JwwC5LWHLsi9/ceV+ivctR
-yPRsKN53SiMKtD5GVX3ematxVlT2SvWjNHP0ZHJkT039BXcDuWDl7AxKxEeF5lRG
-aJ2BHQECgYEA0y67wxrbrgLGnur1J3nMN/sXmaTp6aDg/fTJyaaYhAzt+EUIn3MC
-nqVrWC35lpD5TO1fo8kfyaQH94zQxkywVb018caXHotjHC+EN6VnrG8cXmEvXU8E
-rUmEzHAxy548ZAgV6I/2kIrDEzijElvq7Geq2MzBkOUnFpD2y030iQ0=
------END RSA PRIVATE KEY-----
diff --git a/host/frontend/webrtc_operator/certs/server.p12 b/host/frontend/webrtc_operator/certs/server.p12
deleted file mode 100644
index 80920ba6e..000000000
--- a/host/frontend/webrtc_operator/certs/server.p12
+++ /dev/null
Binary files differ
diff --git a/host/frontend/webrtc_operator/certs/trusted.pem b/host/frontend/webrtc_operator/certs/trusted.pem
deleted file mode 100644
index 0c5057868..000000000
--- a/host/frontend/webrtc_operator/certs/trusted.pem
+++ /dev/null
@@ -1,70 +0,0 @@
-Certificate:
- Data:
- Version: 1 (0x0)
- Serial Number:
- 5b:12:83:24:00:64:74:65:b5:10:1d:8b:d4:ab:2b:66:47:45:ad:7f
- Signature Algorithm: sha256WithRSAEncryption
- Issuer: C = US, ST = California, L = Santa Clara, O = Beyond Aggravated, CN = localhost
- Validity
- Not Before: May 8 06:50:00 2021 GMT
- Not After : Feb 20 06:50:00 2295 GMT
- Subject: C = US, ST = California, L = Santa Clara, O = Beyond Aggravated, CN = localhost
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- RSA Public-Key: (2048 bit)
- Modulus:
- 00:c6:28:c7:29:e3:65:ee:79:58:c2:7d:df:e8:21:
- bc:30:fd:d7:0d:52:37:6d:ce:2f:f9:72:09:12:51:
- f6:9a:b3:73:f0:05:1d:d0:8f:45:a0:95:44:74:20:
- e7:44:83:b5:55:be:ec:37:f5:a7:f5:fc:4c:41:0b:
- f6:45:e1:c4:e7:a9:11:df:a0:9a:d7:d1:b9:54:5a:
- 3b:f3:d8:2d:ef:6e:bc:89:ba:55:ed:04:35:d7:b6:
- a8:78:47:70:ee:4a:4e:ba:42:94:1b:ce:d0:ed:b6:
- 56:96:c6:77:15:7f:e7:c5:2b:f5:1e:7b:f9:04:00:
- 71:a3:4b:b2:33:cb:6f:e4:a1:97:5b:04:7c:6e:c9:
- 85:08:21:2b:f2:2d:80:b6:09:4e:9f:25:52:57:71:
- 32:d7:c5:5b:fe:68:2d:f8:4e:18:13:a5:a8:6d:30:
- 22:3f:c5:1d:10:a4:cf:76:70:66:b3:d2:1c:1c:d9:
- 27:4c:1f:ae:c7:dd:74:c4:31:f8:cf:d7:d6:bf:cf:
- b8:06:9e:26:1f:8d:f1:bd:ba:ed:18:91:33:0e:5d:
- 71:43:e3:2b:cd:ce:c7:93:41:49:a9:49:53:e9:61:
- ee:c8:cf:53:93:b8:ec:a6:68:57:c6:08:2d:79:cc:
- b4:08:60:7f:85:2a:3f:fe:ea:eb:52:ed:8b:11:40:
- 01:81
- Exponent: 65537 (0x10001)
- Signature Algorithm: sha256WithRSAEncryption
- 4a:34:a5:39:4b:a1:e6:3b:a6:ad:60:b1:66:05:f0:64:da:6b:
- 3f:66:40:cd:1e:d0:f1:9c:a2:e6:b1:7d:c2:16:d8:51:23:79:
- 86:cf:5a:04:68:cc:d8:6f:61:b6:b9:f0:f1:ce:1e:3f:c7:60:
- cc:e2:27:df:46:08:f6:92:71:d2:1a:5b:a7:dc:d6:02:95:92:
- cc:d7:cf:ca:4e:95:c5:db:a6:f2:72:78:b1:54:65:70:db:a8:
- c6:d1:61:d0:4d:27:42:4b:95:4b:cf:c0:92:83:53:bf:e3:ce:
- da:10:2e:6c:2a:da:1e:2d:29:38:28:ca:43:17:30:f4:f8:4b:
- 1b:91:ff:f5:6b:0d:15:cb:1b:31:8c:74:67:c4:83:21:78:ae:
- 1c:52:dd:f2:e4:8e:6a:20:a4:b6:a8:ad:16:f5:9b:96:af:51:
- 2b:76:46:0a:09:5b:a6:64:ac:55:b8:c8:47:54:e7:24:eb:32:
- c2:e6:56:63:79:f9:05:b5:3b:72:2d:ed:a7:28:8b:d7:35:67:
- 07:ca:e2:aa:98:b7:da:7e:11:15:4a:52:8f:21:d8:3d:d1:0a:
- 3d:f9:36:38:6f:04:3c:b0:c4:55:71:59:67:9c:28:46:bc:3b:
- 66:78:15:f3:e3:1c:32:16:0f:0f:ce:1b:f0:6b:ce:8f:97:03:
- 08:4a:2f:e6
------BEGIN CERTIFICATE-----
-MIIDWTCCAkECFFsSgyQAZHRltRAdi9SrK2ZHRa1/MA0GCSqGSIb3DQEBCwUAMGgx
-CzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRQwEgYDVQQHDAtTYW50
-YSBDbGFyYTEaMBgGA1UECgwRQmV5b25kIEFnZ3JhdmF0ZWQxEjAQBgNVBAMMCWxv
-Y2FsaG9zdDAgFw0yMTA1MDgwNjUwMDBaGA8yMjk1MDIyMDA2NTAwMFowaDELMAkG
-A1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFDASBgNVBAcMC1NhbnRhIENs
-YXJhMRowGAYDVQQKDBFCZXlvbmQgQWdncmF2YXRlZDESMBAGA1UEAwwJbG9jYWxo
-b3N0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxijHKeNl7nlYwn3f
-6CG8MP3XDVI3bc4v+XIJElH2mrNz8AUd0I9FoJVEdCDnRIO1Vb7sN/Wn9fxMQQv2
-ReHE56kR36Ca19G5VFo789gt7268ibpV7QQ117aoeEdw7kpOukKUG87Q7bZWlsZ3
-FX/nxSv1Hnv5BABxo0uyM8tv5KGXWwR8bsmFCCEr8i2AtglOnyVSV3Ey18Vb/mgt
-+E4YE6WobTAiP8UdEKTPdnBms9IcHNknTB+ux910xDH4z9fWv8+4Bp4mH43xvbrt
-GJEzDl1xQ+Mrzc7Hk0FJqUlT6WHuyM9Tk7jspmhXxggtecy0CGB/hSo//urrUu2L
-EUABgQIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQBKNKU5S6HmO6atYLFmBfBk2ms/
-ZkDNHtDxnKLmsX3CFthRI3mGz1oEaMzYb2G2ufDxzh4/x2DM4iffRgj2knHSGlun
-3NYClZLM18/KTpXF26bycnixVGVw26jG0WHQTSdCS5VLz8CSg1O/487aEC5sKtoe
-LSk4KMpDFzD0+Esbkf/1aw0VyxsxjHRnxIMheK4cUt3y5I5qIKS2qK0W9ZuWr1Er
-dkYKCVumZKxVuMhHVOck6zLC5lZjefkFtTtyLe2nKIvXNWcHyuKqmLfafhEVSlKP
-Idg90Qo9+TY4bwQ8sMRVcVlnnChGvDtmeBXz4xwyFg8Pzhvwa86PlwMISi/m
------END CERTIFICATE-----
diff --git a/host/frontend/webrtc_operator/client_handler.cpp b/host/frontend/webrtc_operator/client_handler.cpp
deleted file mode 100644
index 7b631a6fe..000000000
--- a/host/frontend/webrtc_operator/client_handler.cpp
+++ /dev/null
@@ -1,125 +0,0 @@
-//
-// Copyright (C) 2020 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 "host/frontend/webrtc_operator/client_handler.h"
-
-#include <android-base/logging.h>
-
-#include "host/frontend/webrtc_operator/constants/signaling_constants.h"
-#include "host/frontend/webrtc_operator/device_handler.h"
-
-namespace cuttlefish {
-
-ClientHandler::ClientHandler(struct lws* wsi, DeviceRegistry* registry,
- const ServerConfig& server_config)
- : SignalHandler(wsi, registry, server_config),
- device_handler_(),
- client_id_(0) {}
-
-void ClientHandler::OnClosed() {
- auto device_handler = device_handler_.lock();
- if (device_handler) {
- device_handler->SendClientDisconnectMessage(client_id_);
- }
-}
-
-void ClientHandler::SendDeviceMessage(const Json::Value& device_message) {
- Json::Value message;
- message[webrtc_signaling::kTypeField] = webrtc_signaling::kDeviceMessageType;
- message[webrtc_signaling::kPayloadField] = device_message;
- Reply(message);
-}
-
-void ClientHandler::handleMessage(const std::string& type,
- const Json::Value& message) {
- if (type == webrtc_signaling::kConnectType) {
- handleConnectionRequest(message);
- } else if (type == webrtc_signaling::kForwardType) {
- handleForward(message);
- } else {
- LogAndReplyError("Unknown message type: " + type);
- }
-}
-
-void ClientHandler::handleConnectionRequest(const Json::Value& message) {
- if (client_id_ > 0) {
- LogAndReplyError(
- "Attempt to connect to multiple devices over same websocket");
- Close();
- return;
- }
- if (!message.isMember(webrtc_signaling::kDeviceIdField) ||
- !message[webrtc_signaling::kDeviceIdField].isString()) {
- LogAndReplyError("Invalid connection request: Missing device id");
- Close();
- return;
- }
- auto device_id = message[webrtc_signaling::kDeviceIdField].asString();
- // Always send the server config back, even if the requested device is not
- // registered. Applications may put clients on hold until the device is ready
- // to connect.
- SendServerConfig();
-
- auto device_handler = registry_->GetDevice(device_id);
- if (!device_handler) {
- LogAndReplyError("Connection failed: Device not found: '" + device_id +
- "'");
- Close();
- return;
- }
-
- client_id_ = device_handler->RegisterClient(shared_from_this());
- device_handler_ = device_handler;
- Json::Value device_info_reply;
- device_info_reply[webrtc_signaling::kTypeField] =
- webrtc_signaling::kDeviceInfoType;
- device_info_reply[webrtc_signaling::kDeviceInfoField] =
- device_handler->device_info();
- Reply(device_info_reply);
-}
-
-void ClientHandler::handleForward(const Json::Value& message) {
- if (client_id_ == 0) {
- LogAndReplyError("Forward failed: No device asociated to client");
- Close();
- return;
- }
- if (!message.isMember(webrtc_signaling::kPayloadField)) {
- LogAndReplyError("Forward failed: No payload present in message");
- Close();
- return;
- }
- auto device_handler = device_handler_.lock();
- if (!device_handler) {
- LogAndReplyError("Forward failed: Device disconnected");
- // Disconnect this client since the device is gone
- Close();
- return;
- }
- device_handler->SendClientMessage(client_id_,
- message[webrtc_signaling::kPayloadField]);
-}
-
-ClientHandlerFactory::ClientHandlerFactory(DeviceRegistry* registry,
- const ServerConfig& server_config)
- : registry_(registry),
- server_config_(server_config) {}
-
-std::shared_ptr<WebSocketHandler> ClientHandlerFactory::Build(struct lws* wsi) {
- return std::shared_ptr<WebSocketHandler>(
- new ClientHandler(wsi, registry_, server_config_));
-}
-
-} // namespace cuttlefish
diff --git a/host/frontend/webrtc_operator/client_handler.h b/host/frontend/webrtc_operator/client_handler.h
deleted file mode 100644
index b10f3e857..000000000
--- a/host/frontend/webrtc_operator/client_handler.h
+++ /dev/null
@@ -1,63 +0,0 @@
-//
-// Copyright (C) 2020 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 <memory>
-#include <string>
-
-#include <json/json.h>
-
-#include "host/frontend/webrtc_operator/device_registry.h"
-#include "host/frontend/webrtc_operator/server_config.h"
-#include "host/frontend/webrtc_operator/signal_handler.h"
-#include "host/libs/websocket/websocket_handler.h"
-
-namespace cuttlefish {
-class DeviceHandler;
-class ClientHandler : public SignalHandler,
- public std::enable_shared_from_this<ClientHandler> {
- public:
- ClientHandler(struct lws* wsi, DeviceRegistry* registry,
- const ServerConfig& server_config);
- void SendDeviceMessage(const Json::Value& message);
-
- void OnClosed() override;
-
- protected:
- void handleMessage(const std::string& type,
- const Json::Value& message) override;
-
- private:
- void handleConnectionRequest(const Json::Value& message);
- void handleForward(const Json::Value& message);
-
- std::weak_ptr<DeviceHandler> device_handler_;
- // The device handler assigns this to each client to be able to differentiate
- // them.
- size_t client_id_;
-};
-
-class ClientHandlerFactory : public WebSocketHandlerFactory {
- public:
- ClientHandlerFactory(DeviceRegistry* registry,
- const ServerConfig& server_config);
- std::shared_ptr<WebSocketHandler> Build(struct lws* wsi) override;
-
- private:
- DeviceRegistry* registry_;
- const ServerConfig& server_config_;
-};
-} // namespace cuttlefish
diff --git a/host/frontend/webrtc_operator/constants/signaling_constants.h b/host/frontend/webrtc_operator/constants/signaling_constants.h
deleted file mode 100644
index ecd3a3d48..000000000
--- a/host/frontend/webrtc_operator/constants/signaling_constants.h
+++ /dev/null
@@ -1,43 +0,0 @@
-//
-// Copyright (C) 2020 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
-
-namespace cuttlefish {
-namespace webrtc_signaling {
-
-constexpr auto kTypeField = "message_type";
-constexpr auto kDeviceInfoField = "device_info";
-constexpr auto kDeviceIdField = "device_id";
-constexpr auto kClientIdField = "client_id";
-constexpr auto kPayloadField = "payload";
-constexpr auto kServersField = "ice_servers";
-// These are defined in the IceServer dictionary
-constexpr auto kUrlsField = "urls";
-constexpr auto kUsernameField = "username";
-constexpr auto kCredentialField = "credential";
-constexpr auto kCredentialTypeField = "credentialType";
-
-constexpr auto kRegisterType = "register";
-constexpr auto kForwardType = "forward";
-constexpr auto kConfigType = "config";
-constexpr auto kConnectType = "connect";
-constexpr auto kDeviceInfoType = "device_info";
-constexpr auto kClientMessageType = "client_msg";
-constexpr auto kClientDisconnectType = "client_disconnected";
-constexpr auto kDeviceMessageType = "device_msg";
-
-} // namespace webrtc_signaling
-} // namespace cuttlefish
diff --git a/host/frontend/webrtc_operator/device_handler.cpp b/host/frontend/webrtc_operator/device_handler.cpp
deleted file mode 100644
index af503d4bd..000000000
--- a/host/frontend/webrtc_operator/device_handler.cpp
+++ /dev/null
@@ -1,131 +0,0 @@
-//
-// Copyright (C) 2020 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 "host/frontend/webrtc_operator/device_handler.h"
-
-#include <android-base/logging.h>
-
-#include "host/frontend/webrtc_operator/client_handler.h"
-#include "host/frontend/webrtc_operator/constants/signaling_constants.h"
-
-namespace cuttlefish {
-
-DeviceHandler::DeviceHandler(struct lws* wsi, DeviceRegistry* registry,
- const ServerConfig& server_config)
- : SignalHandler(wsi, registry, server_config), device_info_(), clients_() {}
-
-void DeviceHandler::OnClosed() {
- if (!device_id_.empty() && registry_) {
- registry_->UnRegisterDevice(device_id_);
- }
-}
-
-size_t DeviceHandler::RegisterClient(
- std::shared_ptr<ClientHandler> client_handler) {
- clients_.emplace_back(client_handler);
- return clients_.size();
-}
-
-void DeviceHandler::handleMessage(const std::string& type,
- const Json::Value& message) {
- if (type == webrtc_signaling::kRegisterType) {
- HandleRegistrationRequest(message);
- } else if (type == webrtc_signaling::kForwardType) {
- HandleForward(message);
- } else {
- LogAndReplyError("Unknown message type: " + type);
- }
-}
-
-void DeviceHandler::HandleRegistrationRequest(const Json::Value& message) {
- if (!device_id_.empty()) {
- LogAndReplyError("Device already registered: " + device_id_);
- Close();
- return;
- }
- if (!message.isMember(webrtc_signaling::kDeviceIdField) ||
- !message[webrtc_signaling::kDeviceIdField].isString() ||
- message[webrtc_signaling::kDeviceIdField].asString().empty()) {
- LogAndReplyError("Missing device id in registration request");
- Close();
- return;
- }
- device_id_ = message[webrtc_signaling::kDeviceIdField].asString();
- if (message.isMember(webrtc_signaling::kDeviceInfoField)) {
- device_info_ = message[webrtc_signaling::kDeviceInfoField];
- }
- if (!registry_->RegisterDevice(device_id_, weak_from_this())) {
- LOG(ERROR) << "Device registration failed";
- Close();
- return;
- }
-
- SendServerConfig();
-}
-
-void DeviceHandler::HandleForward(const Json::Value& message) {
- if (!message.isMember(webrtc_signaling::kClientIdField) ||
- !message[webrtc_signaling::kClientIdField].isInt()) {
- LogAndReplyError("Forward failed: Missing or invalid client id");
- Close();
- return;
- }
- size_t client_id = message[webrtc_signaling::kClientIdField].asInt();
- if (!message.isMember(webrtc_signaling::kPayloadField)) {
- LogAndReplyError("Forward failed: Missing payload");
- Close();
- return;
- }
- if (client_id <= 0 || client_id > clients_.size()) {
- LogAndReplyError("Forward failed: Unknown client " +
- std::to_string(client_id));
- return;
- }
- auto client_index = client_id - 1;
- auto client_handler = clients_[client_index].lock();
- if (!client_handler) {
- SendClientDisconnectMessage(client_id);
- return;
- }
- client_handler->SendDeviceMessage(message[webrtc_signaling::kPayloadField]);
- return;
-}
-
-void DeviceHandler::SendClientMessage(size_t client_id,
- const Json::Value& client_message) {
- Json::Value msg;
- msg[webrtc_signaling::kTypeField] = webrtc_signaling::kClientMessageType;
- msg[webrtc_signaling::kClientIdField] = static_cast<Json::UInt>(client_id);
- msg[webrtc_signaling::kPayloadField] = client_message;
- Reply(msg);
-}
-
-void DeviceHandler::SendClientDisconnectMessage(size_t client_id) {
- Json::Value msg;
- msg[webrtc_signaling::kTypeField] = webrtc_signaling::kClientDisconnectType;
- msg[webrtc_signaling::kClientIdField] = static_cast<Json::UInt>(client_id);
- Reply(msg);
-}
-
-DeviceHandlerFactory::DeviceHandlerFactory(DeviceRegistry* registry,
- const ServerConfig& server_config)
- : registry_(registry),
- server_config_(server_config) {}
-
-std::shared_ptr<WebSocketHandler> DeviceHandlerFactory::Build(struct lws* wsi) {
- return std::shared_ptr<WebSocketHandler>(
- new DeviceHandler(wsi, registry_, server_config_));
-}
-} // namespace cuttlefish
diff --git a/host/frontend/webrtc_operator/device_handler.h b/host/frontend/webrtc_operator/device_handler.h
deleted file mode 100644
index 1e17994ee..000000000
--- a/host/frontend/webrtc_operator/device_handler.h
+++ /dev/null
@@ -1,70 +0,0 @@
-//
-// Copyright (C) 2020 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 <memory>
-#include <string>
-#include <vector>
-
-#include <json/json.h>
-
-#include "host/frontend/webrtc_operator/device_registry.h"
-#include "host/frontend/webrtc_operator/server_config.h"
-#include "host/frontend/webrtc_operator/signal_handler.h"
-#include "host/libs/websocket/websocket_handler.h"
-
-namespace cuttlefish {
-
-class ClientHandler;
-
-class DeviceHandler : public SignalHandler,
- public std::enable_shared_from_this<DeviceHandler> {
- public:
- DeviceHandler(struct lws* wsi, DeviceRegistry* registry,
- const ServerConfig& server_config);
-
- Json::Value device_info() const { return device_info_; }
-
- size_t RegisterClient(std::shared_ptr<ClientHandler> client_handler);
- void SendClientMessage(size_t client_id, const Json::Value& message);
- void SendClientDisconnectMessage(size_t client_id);
-
- void OnClosed() override;
-
- protected:
- void handleMessage(const std::string& type,
- const Json::Value& message) override;
-
- private:
- void HandleRegistrationRequest(const Json::Value& message);
- void HandleForward(const Json::Value& message);
-
- std::string device_id_;
- Json::Value device_info_;
- std::vector<std::weak_ptr<ClientHandler>> clients_;
-};
-
-class DeviceHandlerFactory : public WebSocketHandlerFactory {
- public:
- DeviceHandlerFactory(DeviceRegistry* registry,
- const ServerConfig& server_config);
- std::shared_ptr<WebSocketHandler> Build(struct lws* wsi) override;
-
- private:
- DeviceRegistry* registry_;
- const ServerConfig& server_config_;
-};
-} // namespace cuttlefish
diff --git a/host/frontend/webrtc_operator/device_list_handler.cpp b/host/frontend/webrtc_operator/device_list_handler.cpp
deleted file mode 100644
index 314feea36..000000000
--- a/host/frontend/webrtc_operator/device_list_handler.cpp
+++ /dev/null
@@ -1,48 +0,0 @@
-//
-// Copyright (C) 2020 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 "host/frontend/webrtc_operator/device_list_handler.h"
-
-namespace cuttlefish {
-
-DeviceListHandler::DeviceListHandler(struct lws* wsi,
- const DeviceRegistry& registry)
- : WebSocketHandler(wsi), registry_(registry) {}
-
-void DeviceListHandler::OnReceive(const uint8_t* /*msg*/, size_t /*len*/,
- bool /*binary*/) {
- // Ignore the message, just send the reply
- Json::Value reply(Json::ValueType::arrayValue);
-
- for (const auto& id : registry_.ListDeviceIds()) {
- reply.append(id);
- }
- Json::StreamWriterBuilder json_factory;
- auto replyAsString = Json::writeString(json_factory, reply);
- EnqueueMessage(replyAsString.c_str(), replyAsString.size());
- Close();
-}
-
-void DeviceListHandler::OnConnected() {}
-
-void DeviceListHandler::OnClosed() {}
-
-DeviceListHandlerFactory::DeviceListHandlerFactory(const DeviceRegistry& registry)
- : registry_(registry) {}
-
-std::shared_ptr<WebSocketHandler> DeviceListHandlerFactory::Build(struct lws* wsi) {
- return std::shared_ptr<WebSocketHandler>(new DeviceListHandler(wsi, registry_));
-}
-} // namespace cuttlefish
diff --git a/host/frontend/webrtc_operator/device_list_handler.h b/host/frontend/webrtc_operator/device_list_handler.h
deleted file mode 100644
index 99d1f9cf9..000000000
--- a/host/frontend/webrtc_operator/device_list_handler.h
+++ /dev/null
@@ -1,48 +0,0 @@
-//
-// Copyright (C) 2020 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 <memory>
-#include <string>
-
-#include <json/json.h>
-
-#include "host/libs/websocket/websocket_handler.h"
-#include "host/frontend/webrtc_operator/device_registry.h"
-
-namespace cuttlefish {
-
-class DeviceListHandler : public WebSocketHandler {
- public:
- DeviceListHandler(struct lws* wsi, const DeviceRegistry& registry);
-
- void OnReceive(const uint8_t* msg, size_t len, bool binary) override;
- void OnConnected() override;
- void OnClosed() override;
-
- private:
- const DeviceRegistry& registry_;
-};
-
-class DeviceListHandlerFactory : public WebSocketHandlerFactory {
- public:
- DeviceListHandlerFactory(const DeviceRegistry& registry);
- std::shared_ptr<WebSocketHandler> Build(struct lws* wsi) override;
-
- private:
- const DeviceRegistry& registry_;
-};
-} // namespace cuttlefish
diff --git a/host/frontend/webrtc_operator/device_registry.cpp b/host/frontend/webrtc_operator/device_registry.cpp
deleted file mode 100644
index 9ca938e14..000000000
--- a/host/frontend/webrtc_operator/device_registry.cpp
+++ /dev/null
@@ -1,71 +0,0 @@
-//
-// Copyright (C) 2020 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 "host/frontend/webrtc_operator/device_registry.h"
-
-#include <android-base/logging.h>
-
-#include "host/frontend/webrtc_operator/device_handler.h"
-
-namespace cuttlefish {
-
-bool DeviceRegistry::RegisterDevice(
- const std::string& device_id,
- std::weak_ptr<DeviceHandler> device_handler) {
- if (devices_.count(device_id) > 0) {
- LOG(ERROR) << "Device '" << device_id << "' is already registered";
- return false;
- }
-
- devices_.try_emplace(device_id, device_handler);
- LOG(INFO) << "Registered device: '" << device_id << "'";
- return true;
-}
-
-void DeviceRegistry::UnRegisterDevice(const std::string& device_id) {
- auto record = devices_.find(device_id);
- if (record == devices_.end()) {
- LOG(WARNING) << "Requested to unregister an unkwnown device: '" << device_id
- << "'";
- return;
- }
- devices_.erase(record);
- LOG(INFO) << "Unregistered device: '" << device_id << "'";
-}
-
-std::shared_ptr<DeviceHandler> DeviceRegistry::GetDevice(
- const std::string& device_id) {
- if (devices_.count(device_id) == 0) {
- LOG(INFO) << "Requested device (" << device_id << ") is not registered";
- return nullptr;
- }
- auto device_handler = devices_[device_id].lock();
- if (!device_handler) {
- LOG(WARNING) << "Destroyed device handler detected for device '"
- << device_id << "'";
- UnRegisterDevice(device_id);
- }
- return device_handler;
-}
-
-std::vector<std::string> DeviceRegistry::ListDeviceIds() const {
- std::vector<std::string> ret;
- for (const auto& entry: devices_) {
- ret.push_back(entry.first);
- }
- return ret;
-}
-
-} // namespace cuttlefish
diff --git a/host/frontend/webrtc_operator/device_registry.h b/host/frontend/webrtc_operator/device_registry.h
deleted file mode 100644
index 8cccb901d..000000000
--- a/host/frontend/webrtc_operator/device_registry.h
+++ /dev/null
@@ -1,45 +0,0 @@
-//
-// Copyright (C) 2020 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 <cinttypes>
-
-#include <map>
-#include <memory>
-#include <string>
-#include <vector>
-
-#include <json/json.h>
-
-namespace cuttlefish {
-
-class DeviceHandler;
-
-class DeviceRegistry {
- public:
- bool RegisterDevice(const std::string& device_id,
- std::weak_ptr<DeviceHandler> device_handler);
- void UnRegisterDevice(const std::string& device_id);
-
- std::shared_ptr<DeviceHandler> GetDevice(const std::string& device_id);
-
- std::vector<std::string> ListDeviceIds() const;
-
- private:
- std::map<std::string, std::weak_ptr<DeviceHandler>> devices_;
-};
-
-} // namespace cuttlefish
diff --git a/host/frontend/webrtc_operator/server.cpp b/host/frontend/webrtc_operator/server.cpp
deleted file mode 100644
index 565676a70..000000000
--- a/host/frontend/webrtc_operator/server.cpp
+++ /dev/null
@@ -1,71 +0,0 @@
-//
-// Copyright (C) 2020 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 <map>
-#include <string>
-
-#include <android-base/logging.h>
-#include <gflags/gflags.h>
-
-#include "host/frontend/webrtc_operator/client_handler.h"
-#include "host/frontend/webrtc_operator/device_handler.h"
-#include "host/frontend/webrtc_operator/device_list_handler.h"
-#include "host/libs/websocket/websocket_handler.h"
-#include "host/libs/websocket/websocket_server.h"
-
-#include "host/libs/config/logging.h"
-
-DEFINE_int32(http_server_port, 8443, "The port for the http server.");
-DEFINE_bool(use_secure_http, true, "Whether to use HTTPS or HTTP.");
-DEFINE_string(assets_dir, "webrtc",
- "Directory with location of webpage assets.");
-DEFINE_string(certs_dir, "webrtc/certs", "Directory to certificates.");
-DEFINE_string(stun_server, "stun.l.google.com:19302",
- "host:port of STUN server to use for public address resolution");
-
-namespace {
-
-constexpr auto kRegisterDeviceUriPath = "/register_device";
-constexpr auto kConnectClientUriPath = "/connect_client";
-constexpr auto kListDevicesUriPath = "/list_devices";
-
-} // namespace
-
-int main(int argc, char** argv) {
- cuttlefish::DefaultSubprocessLogging(argv);
- ::gflags::ParseCommandLineFlags(&argc, &argv, true);
-
- cuttlefish::DeviceRegistry device_registry;
- cuttlefish::ServerConfig server_config({FLAGS_stun_server});
-
- cuttlefish::WebSocketServer wss(
- "webrtc-operator", FLAGS_certs_dir, FLAGS_assets_dir, FLAGS_http_server_port);
-
- auto device_handler_factory_p =
- std::unique_ptr<cuttlefish::WebSocketHandlerFactory>(
- new cuttlefish::DeviceHandlerFactory(&device_registry, server_config));
- wss.RegisterHandlerFactory(kRegisterDeviceUriPath, std::move(device_handler_factory_p));
- auto client_handler_factory_p =
- std::unique_ptr<cuttlefish::WebSocketHandlerFactory>(
- new cuttlefish::ClientHandlerFactory(&device_registry, server_config));
- wss.RegisterHandlerFactory(kConnectClientUriPath, std::move(client_handler_factory_p));
- auto device_list_handler_factory_p =
- std::unique_ptr<cuttlefish::WebSocketHandlerFactory>(
- new cuttlefish::DeviceListHandlerFactory(device_registry));
- wss.RegisterHandlerFactory(kListDevicesUriPath, std::move(device_list_handler_factory_p));
-
- wss.Serve();
- return 0;
-}
diff --git a/host/frontend/webrtc_operator/server_config.cpp b/host/frontend/webrtc_operator/server_config.cpp
deleted file mode 100644
index b49509cd4..000000000
--- a/host/frontend/webrtc_operator/server_config.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-//
-// Copyright (C) 2020 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 "host/frontend/webrtc_operator/server_config.h"
-
-#include <android-base/strings.h>
-
-using android::base::StartsWith;
-
-namespace cuttlefish {
-
-namespace {
- constexpr auto kStunPrefix = "stun:";
-}
-
-ServerConfig::ServerConfig(const std::vector<std::string>& stuns)
- : stun_servers_(stuns) {}
-
-Json::Value ServerConfig::ToJson() const {
- Json::Value ice_servers(Json::ValueType::arrayValue);
- for (const auto& str : stun_servers_) {
- Json::Value server;
- Json::Value urls(Json::ValueType::arrayValue);
- urls.append(StartsWith(str, kStunPrefix)? str: kStunPrefix + str);
- server["urls"] = urls;
- ice_servers.append(server);
- }
- Json::Value server_config;
- server_config["ice_servers"] = ice_servers;
- return server_config;
-}
-
-} // namespace cuttlefish
diff --git a/host/frontend/webrtc_operator/server_config.h b/host/frontend/webrtc_operator/server_config.h
deleted file mode 100644
index 19831282a..000000000
--- a/host/frontend/webrtc_operator/server_config.h
+++ /dev/null
@@ -1,33 +0,0 @@
-//
-// Copyright (C) 2020 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 <json/json.h>
-
-namespace cuttlefish {
-class ServerConfig {
- public:
- ServerConfig(const std::vector<std::string>& stuns);
-
- Json::Value ToJson() const;
-
- private:
- std::vector<std::string> stun_servers_;
-};
-} // namespace cuttlefish
diff --git a/host/frontend/webrtc_operator/signal_handler.cpp b/host/frontend/webrtc_operator/signal_handler.cpp
deleted file mode 100644
index 92ceb26ea..000000000
--- a/host/frontend/webrtc_operator/signal_handler.cpp
+++ /dev/null
@@ -1,100 +0,0 @@
-//
-// Copyright (C) 2020 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 "host/frontend/webrtc_operator/signal_handler.h"
-
-#include <android-base/logging.h>
-#include <json/json.h>
-
-#include "host/frontend/webrtc_operator/constants/signaling_constants.h"
-
-namespace cuttlefish {
-
-SignalHandler::SignalHandler(struct lws* wsi, DeviceRegistry* registry,
- const ServerConfig& server_config)
- : WebSocketHandler(wsi),
- registry_(registry),
- server_config_(server_config) {}
-
-void SignalHandler::OnConnected() {}
-
-void SignalHandler::OnReceive(const uint8_t* msg, size_t len, bool binary) {
- if (binary) {
- LogAndReplyError("Received a binary message");
- Close();
- return;
- }
- Json::Value json_message;
- Json::CharReaderBuilder builder;
- std::unique_ptr<Json::CharReader> json_reader(builder.newCharReader());
- std::string errorMessage;
- auto str = reinterpret_cast<const char*>(msg);
- if (!json_reader->parse(str, str + len, &json_message, &errorMessage)) {
- LogAndReplyError("Received Invalid JSON");
- // Rate limiting would be a good idea here
- Close();
- return;
- }
- if (!json_message.isMember(webrtc_signaling::kTypeField) ||
- !json_message[webrtc_signaling::kTypeField].isString()) {
- LogAndReplyError("Invalid message format: '" + std::string(msg, msg + len) +
- "'");
- // Rate limiting would be a good idea here
- Close();
- return;
- }
-
- auto type = json_message[webrtc_signaling::kTypeField].asString();
- handleMessage(type, json_message);
-}
-
-void SignalHandler::OnReceive(const uint8_t* msg, size_t len, bool binary,
- bool is_final) {
- if (is_final) {
- if (receive_buffer_.empty()) {
- // no previous data - receive as-is
- OnReceive(msg, len, binary);
- } else {
- // concatenate to previous data and receive
- receive_buffer_.insert(receive_buffer_.end(), msg, msg + len);
- OnReceive(receive_buffer_.data(), receive_buffer_.size(), binary);
- receive_buffer_.clear();
- }
- } else {
- // buffer up incomplete messages
- receive_buffer_.insert(receive_buffer_.end(), msg, msg + len);
- }
-}
-
-void SignalHandler::SendServerConfig() {
- // Call every time to allow config changes?
- auto reply = server_config_.ToJson();
- reply[webrtc_signaling::kTypeField] = webrtc_signaling::kConfigType;
- Reply(reply);
-}
-
-void SignalHandler::LogAndReplyError(const std::string& error_message) {
- LOG(ERROR) << error_message;
- auto reply_str = "{\"error\":\"" + error_message + "\"}";
- EnqueueMessage(reply_str.c_str(), reply_str.size());
-}
-
-void SignalHandler::Reply(const Json::Value& json) {
- Json::StreamWriterBuilder factory;
- auto replyAsString = Json::writeString(factory, json);
- EnqueueMessage(replyAsString.c_str(), replyAsString.size());
-}
-
-} // namespace cuttlefish
diff --git a/host/frontend/webrtc_operator/signal_handler.h b/host/frontend/webrtc_operator/signal_handler.h
deleted file mode 100644
index a0e813c28..000000000
--- a/host/frontend/webrtc_operator/signal_handler.h
+++ /dev/null
@@ -1,50 +0,0 @@
-//
-// Copyright (C) 2020 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 <memory>
-#include <string>
-
-#include <json/json.h>
-
-#include "host/frontend/webrtc_operator/device_registry.h"
-#include "host/frontend/webrtc_operator/server_config.h"
-#include "host/libs/websocket/websocket_handler.h"
-
-namespace cuttlefish {
-
-class SignalHandler : public WebSocketHandler {
- public:
- void OnReceive(const uint8_t* msg, size_t len, bool binary) override;
- void OnReceive(const uint8_t* msg, size_t len, bool binary,
- bool is_final) override;
- void OnConnected() override;
- protected:
- SignalHandler(struct lws* wsi, DeviceRegistry* registry,
- const ServerConfig& server_config);
-
- virtual void handleMessage(const std::string& message_type,
- const Json::Value& message) = 0;
- void SendServerConfig();
-
- void LogAndReplyError(const std::string& message);
- void Reply(const Json::Value& json);
-
- DeviceRegistry* registry_;
- const ServerConfig& server_config_;
- std::vector<uint8_t> receive_buffer_;
-};
-} // namespace cuttlefish
diff --git a/host/libs/Android.bp b/host/libs/Android.bp
new file mode 100644
index 000000000..169507c4a
--- /dev/null
+++ b/host/libs/Android.bp
@@ -0,0 +1,21 @@
+//
+// 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.
+
+subdirs = [
+ "adb_connection_maintainer",
+ "config",
+ "wayland",
+ "vm_manager",
+]
diff --git a/host/libs/allocd/Android.bp b/host/libs/allocd/Android.bp
deleted file mode 100644
index 3c5250799..000000000
--- a/host/libs/allocd/Android.bp
+++ /dev/null
@@ -1,75 +0,0 @@
-//
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-cc_library {
- name: "libcuttlefish_allocd_utils",
- srcs: [
- "utils.cpp",
- ],
- shared_libs: [
- "libbase",
- "libcuttlefish_utils",
- "libcuttlefish_fs",
- "libjsoncpp",
- "liblog",
- ],
- defaults: ["cuttlefish_host"],
-}
-
-cc_binary {
- name: "allocd",
- srcs: [
- "allocd.cpp",
- "alloc_utils.cpp",
- "resource_manager.cpp",
- "resource.cpp",
- ],
- shared_libs: [
- "libbase",
- "libcuttlefish_fs",
- "libcuttlefish_utils",
- "libcuttlefish_allocd_utils",
- "libjsoncpp",
- "liblog",
- ],
- static_libs: [
- "libgflags",
- ],
- defaults: ["cuttlefish_host"],
-}
-
-cc_binary {
- name: "allocd_client",
- srcs: [
- "test/client.cpp",
- ],
- shared_libs: [
- "libbase",
- "libcuttlefish_allocd_utils",
- "libcuttlefish_fs",
- "libcuttlefish_utils",
- "liblog",
- "libjsoncpp",
- ],
- static_libs: [
- "libcuttlefish_host_config",
- "libgflags",
- ],
- defaults: ["cuttlefish_host"],
-}
diff --git a/host/libs/allocd/alloc_utils.cpp b/host/libs/allocd/alloc_utils.cpp
deleted file mode 100644
index 8c9168640..000000000
--- a/host/libs/allocd/alloc_utils.cpp
+++ /dev/null
@@ -1,482 +0,0 @@
-#include "host/libs/allocd/alloc_utils.h"
-
-#include <cstdint>
-#include <fstream>
-
-#include "android-base/logging.h"
-
-namespace cuttlefish {
-
-int RunExternalCommand(const std::string& command) {
- FILE* fp;
- LOG(INFO) << "Running external command: " << command;
- fp = popen(command.c_str(), "r");
-
- if (fp == nullptr) {
- LOG(WARNING) << "Error running external command";
- return -1;
- }
-
- int status = pclose(fp);
- int ret = -1;
- if (status == -1) {
- LOG(WARNING) << "pclose error";
- } else {
- if (WIFEXITED(status)) {
- LOG(INFO) << "child process exited normally";
- ret = WEXITSTATUS(status);
- } else if (WIFSIGNALED(status)) {
- LOG(WARNING) << "child process was terminated by a signal";
- } else {
- LOG(WARNING) << "child process did not terminate normally";
- }
- }
- return ret;
-}
-
-bool AddTapIface(const std::string& name) {
- std::stringstream ss;
- ss << "ip tuntap add dev " << name << " mode tap group cvdnetwork vnet_hdr";
- auto add_command = ss.str();
- LOG(INFO) << "Create tap interface: " << add_command;
- int status = RunExternalCommand(add_command);
- return status == 0;
-}
-
-bool ShutdownIface(const std::string& name) {
- std::stringstream ss;
- ss << "ip link set dev " << name << " down";
- auto link_command = ss.str();
- LOG(INFO) << "Shutdown tap interface: " << link_command;
- int status = RunExternalCommand(link_command);
-
- return status == 0;
-}
-
-bool BringUpIface(const std::string& name) {
- std::stringstream ss;
- ss << "ip link set dev " << name << " up";
- auto link_command = ss.str();
- LOG(INFO) << "Bring up tap interface: " << link_command;
- int status = RunExternalCommand(link_command);
-
- return status == 0;
-}
-
-bool CreateEthernetIface(const std::string& name, const std::string& bridge_name,
- bool has_ipv4_bridge, bool has_ipv6_bridge,
- bool use_ebtables_legacy) {
- // assume bridge exists
-
- EthernetNetworkConfig config{false, false, false};
-
- if (!CreateTap(name)) {
- return false;
- }
-
- config.has_tap = true;
-
- if (!LinkTapToBridge(name, bridge_name)) {
- CleanupEthernetIface(name, config);
- return false;
- }
-
- if (!has_ipv4_bridge) {
- if (!CreateEbtables(name, true, use_ebtables_legacy)) {
- CleanupEthernetIface(name, config);
- return false;
- }
- config.has_broute_ipv4 = true;
- }
-
- if (!has_ipv6_bridge) {
- if (CreateEbtables(name, false, use_ebtables_legacy)) {
- CleanupEthernetIface(name, config);
- return false;
- }
- config.has_broute_ipv6 = true;
- }
-
- return true;
-}
-
-std::string MobileGatewayName(const std::string& ipaddr, uint16_t id) {
- std::stringstream ss;
- ss << ipaddr << "." << (4 * id + 1);
- return ss.str();
-}
-
-std::string MobileNetworkName(const std::string& ipaddr,
- const std::string& netmask, uint16_t id) {
- std::stringstream ss;
- ss << ipaddr << "." << (4 * id) << netmask;
- return ss.str();
-}
-
-bool CreateMobileIface(const std::string& name, uint16_t id,
- const std::string& ipaddr) {
- if (id > kMaxIfaceNameId) {
- LOG(ERROR) << "ID exceeds maximum value to assign a netmask: " << id;
- return false;
- }
-
- auto netmask = "/30";
- auto gateway = MobileGatewayName(ipaddr, id);
- auto network = MobileNetworkName(ipaddr, netmask, id);
-
- if (!CreateTap(name)) {
- return false;
- }
-
- if (!AddGateway(name, gateway, netmask)) {
- DestroyIface(name);
- }
-
- if (!IptableConfig(network, true)) {
- DestroyGateway(name, gateway, netmask);
- DestroyIface(name);
- return false;
- };
-
- return true;
-}
-
-bool DestroyMobileIface(const std::string& name, uint16_t id,
- const std::string& ipaddr) {
- if (id > 63) {
- LOG(ERROR) << "ID exceeds maximum value to assign a netmask: " << id;
- return false;
- }
-
- auto netmask = "/30";
- auto gateway = MobileGatewayName(ipaddr, id);
- auto network = MobileNetworkName(ipaddr, netmask, id);
-
- IptableConfig(network, false);
- DestroyGateway(name, gateway, netmask);
- return DestroyIface(name);
-}
-
-bool AddGateway(const std::string& name, const std::string& gateway,
- const std::string& netmask) {
- std::stringstream ss;
- ss << "ip addr add " << gateway << netmask << " broadcast + dev " << name;
- auto command = ss.str();
- LOG(INFO) << "setup gateway: " << command;
- int status = RunExternalCommand(command);
-
- return status == 0;
-}
-
-bool DestroyGateway(const std::string& name, const std::string& gateway,
- const std::string& netmask) {
- std::stringstream ss;
- ss << "ip addr del " << gateway << netmask << " broadcast + dev " << name;
- auto command = ss.str();
- LOG(INFO) << "removing gateway: " << command;
- int status = RunExternalCommand(command);
-
- return status == 0;
-}
-
-bool DestroyEthernetIface(const std::string& name, bool has_ipv4_bridge,
- bool has_ipv6_bridge, bool use_ebtables_legacy) {
- if (!has_ipv6_bridge) {
- DestroyEbtables(name, false, use_ebtables_legacy);
- }
-
- if (!has_ipv4_bridge) {
- DestroyEbtables(name, true, use_ebtables_legacy);
- }
-
- return DestroyIface(name);
-}
-
-void CleanupEthernetIface(const std::string& name,
- const EthernetNetworkConfig& config) {
- if (config.has_broute_ipv6) {
- DestroyEbtables(name, false, config.use_ebtables_legacy);
- }
-
- if (config.has_broute_ipv4) {
- DestroyEbtables(name, true, config.use_ebtables_legacy);
- }
-
- if (config.has_tap) {
- DestroyIface(name);
- }
-}
-
-bool CreateEbtables(const std::string& name, bool use_ipv4,
- bool use_ebtables_legacy) {
- return EbtablesBroute(name, use_ipv4, true, use_ebtables_legacy) &&
- EbtablesFilter(name, use_ipv4, true, use_ebtables_legacy);
-}
-
-bool DestroyEbtables(const std::string& name, bool use_ipv4,
- bool use_ebtables_legacy) {
- return EbtablesBroute(name, use_ipv4, false, use_ebtables_legacy) &&
- EbtablesFilter(name, use_ipv4, false, use_ebtables_legacy);
-}
-
-bool EbtablesBroute(const std::string& name, bool use_ipv4, bool add,
- bool use_ebtables_legacy) {
- std::stringstream ss;
- // we don't know the name of the ebtables program, but since we're going to
- // exec this program name, make sure they can only choose between the two
- // options we currently support, and not something they can overwrite
- if (use_ebtables_legacy) {
- ss << kEbtablesLegacyName;
- } else {
- ss << kEbtablesName;
- }
-
- ss << " -t broute " << (add ? "-A" : "-D") << " BROUTING -p "
- << (use_ipv4 ? "ipv4" : "ipv6") << " --in-if " << name << " -j DROP";
- auto command = ss.str();
- int status = RunExternalCommand(command);
-
- return status == 0;
-}
-
-bool EbtablesFilter(const std::string& name, bool use_ipv4, bool add,
- bool use_ebtables_legacy) {
- std::stringstream ss;
- if (use_ebtables_legacy) {
- ss << kEbtablesLegacyName;
- } else {
- ss << kEbtablesName;
- }
-
- ss << " -t filter " << (add ? "-A" : "-D") << " FORWARD -p "
- << (use_ipv4 ? "ipv4" : "ipv6") << " --out-if " << name << " -j DROP";
- auto command = ss.str();
- int status = RunExternalCommand(command);
-
- return status == 0;
-}
-
-bool LinkTapToBridge(const std::string& tap_name,
- const std::string& bridge_name) {
- std::stringstream ss;
- ss << "ip link set dev " << tap_name << " master " << bridge_name;
- auto command = ss.str();
- int status = RunExternalCommand(command);
-
- return status == 0;
-}
-
-bool CreateTap(const std::string& name) {
- LOG(INFO) << "Attempt to create tap interface: " << name;
- if (!AddTapIface(name)) {
- LOG(WARNING) << "Failed to create tap interface: " << name;
- return false;
- }
-
- if (!BringUpIface(name)) {
- LOG(WARNING) << "Failed to bring up tap interface: " << name;
- DeleteIface(name);
- return false;
- }
-
- return true;
-}
-
-bool DeleteIface(const std::string& name) {
- std::stringstream ss;
- ss << "ip link delete " << name;
- auto link_command = ss.str();
- LOG(INFO) << "Delete tap interface: " << link_command;
- int status = RunExternalCommand(link_command);
-
- return status == 0;
-}
-
-bool DestroyIface(const std::string& name) {
- if (!ShutdownIface(name)) {
- LOG(WARNING) << "Failed to shutdown tap interface: " << name;
- // the interface might have already shutdown ... so ignore and try to remove
- // the interface. In the future we could read from the pipe and handle this
- // case more elegantly
- }
-
- if (!DeleteIface(name)) {
- LOG(WARNING) << "Failed to delete tap interface: " << name;
- return false;
- }
-
- return true;
-}
-
-std::optional<std::string> GetUserName(uid_t uid) {
- passwd* pw = getpwuid(uid);
- if (pw) {
- std::string ret(pw->pw_name);
- return ret;
- }
- return std::nullopt;
-}
-
-bool CreateBridge(const std::string& name) {
- std::stringstream ss;
- ss << "ip link add name " << name
- << " type bridge forward_delay 0 stp_state 0";
-
- auto command = ss.str();
- LOG(INFO) << "create bridge: " << command;
- int status = RunExternalCommand(command);
-
- if (status != 0) {
- return false;
- }
-
- return BringUpIface(name);
-}
-
-bool DestroyBridge(const std::string& name) { return DeleteIface(name); }
-
-bool SetupBridgeGateway(const std::string& bridge_name,
- const std::string& ipaddr) {
- GatewayConfig config{false, false, false};
- auto gateway = ipaddr + ".1";
- auto netmask = "/24";
- auto network = ipaddr + ".0" + netmask;
- auto dhcp_range = ipaddr + ".2," + ipaddr + ".255";
-
- if (!AddGateway(bridge_name, gateway, netmask)) {
- return false;
- }
-
- config.has_gateway = true;
-
- if (StartDnsmasq(bridge_name, gateway, dhcp_range)) {
- CleanupBridgeGateway(bridge_name, ipaddr, config);
- return false;
- }
-
- config.has_dnsmasq = true;
-
- auto ret = IptableConfig(network, true);
- if (!ret) {
- CleanupBridgeGateway(bridge_name, ipaddr, config);
- LOG(WARNING) << "Failed to setup ip tables";
- }
-
- return ret;
-}
-
-void CleanupBridgeGateway(const std::string& name, const std::string& ipaddr,
- const GatewayConfig& config) {
- auto gateway = ipaddr + ".1";
- auto netmask = "/24";
- auto network = ipaddr + ".0" + netmask;
- auto dhcp_range = ipaddr + ".2," + ipaddr + ".255";
-
- if (config.has_iptable) {
- IptableConfig(network, false);
- }
-
- if (config.has_dnsmasq) {
- StopDnsmasq(name);
- }
-
- if (config.has_gateway) {
- DestroyGateway(name, gateway, netmask);
- }
-}
-
-bool StartDnsmasq(const std::string& bridge_name, const std::string& gateway,
- const std::string& dhcp_range) {
- auto dns_servers = "8.8.8.8,8.8.4.4";
- auto dns6_servers = "2001:4860:4860::8888,2001:4860:4860::8844";
- std::stringstream ss;
-
- // clang-format off
- ss <<
- "dnsmasq"
- " --port=0"
- " --strict-order"
- " --except-interface=lo"
- " --interface=" << bridge_name <<
- " --listen-address=" << gateway <<
- " --bind-interfaces"
- " --dhcp-range=" << dhcp_range <<
- " --dhcp-option=\"option:dns-server," << dns_servers << "\""
- " --dhcp-option=\"option6:dns-server," << dns6_servers << "\""
- " --conf-file=\"\""
- " --pid-file=/var/run/cuttlefish-dnsmasq-" << bridge_name << ".pid"
- " --dhcp-leasefile=/var/run/cuttlefish-dnsmasq-" << bridge_name << ".leases"
- " --dhcp-no-override ";
- // clang-format on
-
- auto command = ss.str();
- LOG(INFO) << "start_dnsmasq: " << command;
- int status = RunExternalCommand(command);
-
- return status == 0;
-}
-
-bool StopDnsmasq(const std::string& name) {
- std::ifstream file;
- std::string filename = "/var/run/cuttlefish-dnsmasq-" + name + ".pid";
- LOG(INFO) << "stopping dsnmasq for interface: " << name;
- file.open(filename);
- if (file.is_open()) {
- LOG(INFO) << "dnsmasq file:" << filename
- << " could not be opened, assume dnsmaq has already stopped";
- return true;
- }
-
- std::string pid;
- file >> pid;
- file.close();
- std::string command = "kill " + pid;
- int status = RunExternalCommand(command);
- auto ret = (status == 0);
-
- if (ret) {
- LOG(INFO) << "dsnmasq for:" << name << "successfully stopped";
- } else {
- LOG(WARNING) << "Failed to stop dsnmasq for:" << name;
- }
- return ret;
-}
-
-bool IptableConfig(const std::string& network, bool add) {
- std::stringstream ss;
- ss << "iptables -t nat " << (add ? "-A" : "-D") << " POSTROUTING -s "
- << network << " -j MASQUERADE";
-
- auto command = ss.str();
- LOG(INFO) << "iptable_config: " << command;
- int status = RunExternalCommand(command);
-
- return status == 0;
-}
-
-bool CreateEthernetBridgeIface(const std::string& name,
- const std::string& ipaddr) {
- if (!CreateBridge(name)) {
- return false;
- }
-
- if (!SetupBridgeGateway(name, ipaddr)) {
- DestroyBridge(name);
- return false;
- }
-
- return true;
-}
-
-bool DestroyEthernetBridgeIface(const std::string& name,
- const std::string& ipaddr) {
- GatewayConfig config{true, true, true};
-
- // Don't need to check if removing some part of the config failed, we need to
- // remove the entire interface, so just ignore any error until the end
- CleanupBridgeGateway(name, ipaddr, config);
-
- return DestroyBridge(name);
-}
-
-} // namespace cuttlefish
diff --git a/host/libs/allocd/alloc_utils.h b/host/libs/allocd/alloc_utils.h
deleted file mode 100644
index 63f6d2653..000000000
--- a/host/libs/allocd/alloc_utils.h
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright (C) 2020 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 <pwd.h>
-#include <sys/wait.h>
-#include <unistd.h>
-
-#include <atomic>
-#include <optional>
-#include <sstream>
-
-#include "common/libs/fs/shared_fd.h"
-#include "host/libs/allocd/request.h"
-
-namespace cuttlefish {
-
-constexpr char kEbtablesName[] = "ebtables";
-constexpr char kEbtablesLegacyName[] = "ebtables-legacy";
-
-// Wireless network prefix
-constexpr char kWirelessIp[] = "192.168.96";
-// Mobile network prefix
-constexpr char kMobileIp[] = "192.168.97";
-// Ethernet network prefix
-constexpr char kEthernetIp[] = "192.168.98";
-// permission bits for socket
-constexpr int kSocketMode = 0666;
-
-// Max ID an interface can have
-// Note: Interface names only have 2 digits in addition to the username prefix
-// Additionally limited by available netmask values in MobileNetworkName
-// Exceeding 63 would result in an overflow when calculating the netmask
-constexpr uint32_t kMaxIfaceNameId = 63;
-
-// struct for managing configuration state
-struct EthernetNetworkConfig {
- bool has_broute_ipv4 = false;
- bool has_broute_ipv6 = false;
- bool has_tap = false;
- bool use_ebtables_legacy = false;
-};
-
-// struct for managing configuration state
-struct GatewayConfig {
- bool has_gateway = false;
- bool has_dnsmasq = false;
- bool has_iptable = false;
-};
-
-int RunExternalCommand(const std::string& command);
-std::optional<std::string> GetUserName(uid_t uid);
-
-bool AddTapIface(const std::string& name);
-bool CreateTap(const std::string& name);
-
-bool BringUpIface(const std::string& name);
-bool ShutdownIface(const std::string& name);
-
-bool DestroyIface(const std::string& name);
-bool DeleteIface(const std::string& name);
-
-bool CreateBridge(const std::string& name);
-bool DestroyBridge(const std::string& name);
-
-bool CreateEbtables(const std::string& name, bool use_ipv,
- bool use_ebtables_legacy);
-bool DestroyEbtables(const std::string& name, bool use_ipv4,
- bool use_ebtables_legacy);
-bool EbtablesBroute(const std::string& name, bool use_ipv4, bool add,
- bool use_ebtables_legacy);
-bool EbtablesFilter(const std::string& name, bool use_ipv4, bool add,
- bool use_ebtables_legacy);
-
-bool CreateMobileIface(const std::string& name, uint16_t id,
- const std::string& ipaddr);
-bool DestroyMobileIface(const std::string& name, uint16_t id,
- const std::string& ipaddr);
-
-bool CreateEthernetIface(const std::string& name, const std::string& bridge_name,
- bool has_ipv4_bridge, bool has_ipv6_bridge,
- bool use_ebtables_legacy);
-bool DestroyEthernetIface(const std::string& name,
- bool has_ipv4_bridge, bool use_ipv6,
- bool use_ebtables_legacy);
-void CleanupEthernetIface(const std::string& name,
- const EthernetNetworkConfig& config);
-
-bool IptableConfig(const std::string& network, bool add);
-
-bool LinkTapToBridge(const std::string& tap_name,
- const std::string& bridge_name);
-
-bool SetupBridgeGateway(const std::string& name, const std::string& ipaddr);
-void CleanupBridgeGateway(const std::string& name, const std::string& ipaddr,
- const GatewayConfig& config);
-
-bool CreateEthernetBridgeIface(const std::string& name,
- const std::string &ipaddr);
-bool DestroyEthernetBridgeIface(const std::string& name,
- const std::string &ipaddr);
-
-bool AddGateway(const std::string& name, const std::string& gateway,
- const std::string& netmask);
-bool DestroyGateway(const std::string& name, const std::string& gateway,
- const std::string& netmask);
-
-bool StartDnsmasq(const std::string& bridge_name, const std::string& gateway,
- const std::string& dhcp_range);
-bool StopDnsmasq(const std::string& name);
-
-} // namespace cuttlefish
diff --git a/host/libs/allocd/allocd.cpp b/host/libs/allocd/allocd.cpp
deleted file mode 100644
index 6025daba4..000000000
--- a/host/libs/allocd/allocd.cpp
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2020 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 <android-base/logging.h>
-#include <asm-generic/socket.h>
-#include <gflags/gflags.h>
-#include <pwd.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <unistd.h>
-
-#include <atomic>
-#include <cstdint>
-#include <cstdlib>
-#include <iomanip>
-#include <iostream>
-#include <optional>
-#include <set>
-#include <sstream>
-#include <thread>
-
-#include "common/libs/fs/shared_fd.h"
-#include "host/libs/allocd/alloc_utils.h"
-#include "host/libs/allocd/request.h"
-#include "host/libs/allocd/resource_manager.h"
-#include "host/libs/config/logging.h"
-
-DEFINE_string(socket_path, cuttlefish::kDefaultLocation, "Socket path");
-DEFINE_bool(ebtables_legacy, false, "use ebtables-legacy instead of ebtables");
-
-int main(int argc, char* argv[]) {
- ::android::base::InitLogging(argv, android::base::StderrLogger);
-
- google::ParseCommandLineFlags(&argc, &argv, true);
-
- cuttlefish::SharedFD FinalFD;
- {
- cuttlefish::ResourceManager m;
- m.SetSocketLocation(FLAGS_socket_path);
- m.SetUseEbtablesLegacy(FLAGS_ebtables_legacy);
- m.JsonServer();
- }
-
- return 0; // EXIT_SUCCESS? or status
-}
diff --git a/host/libs/allocd/request.h b/host/libs/allocd/request.h
deleted file mode 100644
index bb088d51f..000000000
--- a/host/libs/allocd/request.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2020 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 <android-base/logging.h>
-#include <json/json.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-
-#include <algorithm>
-#include <cstdint>
-#include <map>
-#include <memory>
-#include <optional>
-#include <string>
-
-namespace cuttlefish {
-
-/// Defines operations supported by allocd
-enum class RequestType : uint16_t {
- Invalid = 0, // Invalid Request
- ID, // Allocate and return a new Session ID
- CreateInterface, // Request to create new network interface
- DestroyInterface, // Request to destroy a managed network interface
- StopSession, // Request all resources within a session be released
- Shutdown, // request allocd to shutdown and clean up all resources
-};
-
-/// Defines interface types supported by allocd
-enum class IfaceType : uint16_t {
- Invalid = 0, // an invalid interface
- mtap, // mobile tap
- wtap, // wireless tap
- etap, // ethernet tap
- wbr, // wireless bridge
- ebr // ethernet bridge
-};
-
-enum class RequestStatus : uint16_t {
- Invalid = 0, // Invalid status
- Pending, // Request which has not been attempted
- Success, // Request was satisfied
- Failure // Request failed
-};
-
-/// Defines the format for allocd Request messages
-struct RequestHeader {
- uint16_t version; /// used to differentiate between allocd feature sets
- uint16_t len; /// length in bytes of the message payload
-};
-
-/// Provides a wrapper around libjson's Reader to additionally log errors
-class JsonRequestReader {
- public:
- JsonRequestReader() = default;
-
- ~JsonRequestReader() = default;
-
- std::optional<Json::Value> parse(std::string msg) {
- Json::Value ret;
- std::unique_ptr<Json::CharReader> reader(reader_builder.newCharReader());
- std::string errorMessage;
- if (!reader->parse(&*msg.begin(), &*msg.end(), &ret, &errorMessage)) {
- LOG(WARNING) << "Received invalid JSON object in input channel: "
- << errorMessage;
- LOG(INFO) << "Invalid JSON: " << msg;
- return std::nullopt;
- }
- return ret;
- }
-
- private:
- Json::CharReaderBuilder reader_builder;
-};
-
-} // namespace cuttlefish
diff --git a/host/libs/allocd/resource.h b/host/libs/allocd/resource.h
deleted file mode 100644
index c30e9cc5c..000000000
--- a/host/libs/allocd/resource.h
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright (C) 2020 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 <sys/types.h>
-
-#include <cstdint>
-#include <string>
-
-namespace cuttlefish {
-
-enum class ResourceType {
- Invalid = 0,
- MobileIface,
- EthernetIface,
- EthernetBridge,
-};
-
-class StaticResource {
- public:
- StaticResource() = default;
- StaticResource(const std::string& name, uid_t uid, ResourceType ty,
- uint32_t global_id)
- : name_(name), uid_(uid), global_id_(global_id), ty_(ty){};
- virtual ~StaticResource() = default;
- virtual bool ReleaseResource() = 0;
- virtual bool AcquireResource() = 0;
-
- std::string GetName() { return name_; }
- uid_t GetUid() { return uid_; }
- ResourceType GetResourceType() { return ty_; }
- uint32_t GetGlobalID() { return global_id_; }
-
- private:
- std::string name_{};
- uid_t uid_{};
- uint32_t global_id_{};
- ResourceType ty_ = ResourceType::Invalid;
-};
-
-class MobileIface : public StaticResource {
- public:
- MobileIface() = default;
- ~MobileIface() = default;
- MobileIface(const std::string& name, uid_t uid, uint16_t iface_id,
- uint32_t global_id, std::string ipaddr)
- : StaticResource(name, uid, ResourceType::MobileIface, global_id),
- iface_id_(iface_id),
- ipaddr_(ipaddr) {}
-
- bool ReleaseResource() override;
- bool AcquireResource() override;
-
- uint16_t GetIfaceId() { return iface_id_; }
- std::string GetIpAddr() { return ipaddr_; }
-
- static constexpr char kNetmask[] = "/30";
-
- private:
- uint16_t iface_id_;
- std::string ipaddr_;
-};
-
-class EthernetIface : public StaticResource {
- public:
- EthernetIface() = default;
- ~EthernetIface() = default;
-
- EthernetIface(const std::string& name, uid_t uid, uint16_t iface_id,
- uint32_t global_id, std::string bridge_name,
- std::string ipaddr)
- : StaticResource(name, uid, ResourceType::MobileIface, global_id),
- iface_id_(iface_id),
- bridge_name_(bridge_name),
- ipaddr_(ipaddr) {}
-
- bool ReleaseResource() override;
- bool AcquireResource() override;
-
- uint16_t GetIfaceId() { return iface_id_; }
-
- std::string GetBridgeName() { return bridge_name_; }
- std::string GetIpAddr() { return ipaddr_; }
-
- void SetHasIpv4(bool ipv4) { has_ipv4_ = ipv4; }
- void SetHasIpv6(bool ipv6) { has_ipv6_ = ipv6; }
- void SetUseEbtablesLegacy(bool use_legacy) {
- use_ebtables_legacy_ = use_legacy;
- }
-
- bool GetHasIpv4() { return has_ipv4_; }
- bool GetHasIpv6() { return has_ipv6_; }
- bool GetUseEbtablesLegacy() { return use_ebtables_legacy_; }
-
- private:
- static constexpr char kNetmask[] = "/24";
- uint16_t iface_id_;
- std::string bridge_name_;
- std::string ipaddr_;
- bool has_ipv4_ = true;
- bool has_ipv6_ = true;
- bool use_ebtables_legacy_ = false;
-};
-
-} // namespace cuttlefish
diff --git a/host/libs/allocd/resource_manager.cpp b/host/libs/allocd/resource_manager.cpp
deleted file mode 100644
index aaa8fe015..000000000
--- a/host/libs/allocd/resource_manager.cpp
+++ /dev/null
@@ -1,619 +0,0 @@
-/*
- * Copyright (C) 2020 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 "host/libs/allocd/resource_manager.h"
-
-#include <android-base/logging.h>
-#include <pwd.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <unistd.h>
-
-#include <atomic>
-#include <cstdint>
-#include <cstdlib>
-#include <iomanip>
-#include <memory>
-#include <optional>
-#include <sstream>
-#include <string>
-
-#include "common/libs/fs/shared_fd.h"
-#include "host/libs/allocd/alloc_utils.h"
-#include "host/libs/allocd/request.h"
-#include "host/libs/allocd/utils.h"
-#include "json/forwards.h"
-#include "json/value.h"
-#include "json/writer.h"
-
-namespace cuttlefish {
-
-uid_t GetUserIDFromSock(SharedFD client_socket);
-
-ResourceManager::~ResourceManager() {
- bool success = true;
- for (auto& res : managed_sessions_) {
- success &= res.second->ReleaseAllResources();
- }
-
- Json::Value resp;
- resp["request_type"] = "shutdown";
- auto status = success ? RequestStatus::Success : RequestStatus::Failure;
- resp["request_status"] = StatusToStr(status);
- SendJsonMsg(shutdown_socket_, resp);
- LOG(INFO) << "Daemon Shutdown complete";
- unlink(location.c_str());
-}
-
-void ResourceManager::SetSocketLocation(const std::string& sock_name) {
- location = sock_name;
-}
-
-void ResourceManager::SetUseEbtablesLegacy(bool use_legacy) {
- use_ebtables_legacy_ = use_legacy;
-}
-
-uint32_t ResourceManager::AllocateResourceID() {
- return global_resource_id_.fetch_add(1, std::memory_order_relaxed);
-}
-
-uint32_t ResourceManager::AllocateSessionID() {
- return session_id_.fetch_add(1, std::memory_order_relaxed);
-}
-
-bool ResourceManager::AddInterface(const std::string& iface, IfaceType ty,
- uint32_t resource_id, uid_t uid) {
- bool allocatedIface = false;
- std::shared_ptr<StaticResource> res = nullptr;
-
- bool didInsert = active_interfaces_.insert(iface).second;
- if (didInsert) {
- const char* idp = iface.c_str() + (iface.size() - 3);
- int small_id = atoi(idp);
- switch (ty) {
- case IfaceType::mtap:
- res = std::make_shared<MobileIface>(iface, uid, small_id, resource_id,
- kMobileIp);
- allocatedIface = res->AcquireResource();
- pending_add_.insert({resource_id, res});
- break;
- case IfaceType::wtap: {
- // TODO (paulkirth): change this to cvd-wbr, to test w/ today's
- // debian package, this is required since the number of wireless
- // bridges provided by the debian package has gone from 10 down to
- // 1, but our debian packages in cloudtop are not up to date
- auto w = std::make_shared<EthernetIface>(iface, uid, small_id,
- resource_id, "cvd-wbr-01",
- kWirelessIp);
- w->SetUseEbtablesLegacy(use_ebtables_legacy_);
- w->SetHasIpv4(use_ipv4_bridge_);
- w->SetHasIpv6(use_ipv6_bridge_);
- res = w;
- allocatedIface = res->AcquireResource();
- pending_add_.insert({resource_id, res});
- break;
- }
- case IfaceType::etap: {
- auto w = std::make_shared<EthernetIface>(iface, uid, small_id,
- resource_id, "cvd-ebr",
- kEthernetIp);
- w->SetUseEbtablesLegacy(use_ebtables_legacy_);
- w->SetHasIpv4(use_ipv4_bridge_);
- w->SetHasIpv6(use_ipv6_bridge_);
- res = w;
- allocatedIface = res->AcquireResource();
- pending_add_.insert({resource_id, res});
- break;
- }
- case IfaceType::wbr:
- case IfaceType::ebr:
- allocatedIface = CreateBridge(iface);
- break;
- case IfaceType::Invalid:
- break;
- }
- } else {
- LOG(WARNING) << "Interface already in use: " << iface;
- }
-
- if (didInsert && !allocatedIface) {
- LOG(WARNING) << "Failed to allocate interface: " << iface;
- active_interfaces_.erase(iface);
- auto it = pending_add_.find(resource_id);
- it->second->ReleaseResource();
- pending_add_.erase(it);
- }
-
- LOG(INFO) << "Finish CreateInterface Request";
-
- return allocatedIface;
-}
-
-bool ResourceManager::RemoveInterface(const std::string& iface, IfaceType ty) {
- bool isManagedIface = active_interfaces_.erase(iface) > 0;
- bool removedIface = false;
- if (isManagedIface) {
- switch (ty) {
- case IfaceType::mtap: {
- const char* idp = iface.c_str() + (iface.size() - 3);
- int id = atoi(idp);
- removedIface = DestroyMobileIface(iface, id, kMobileIp);
- break;
- }
- case IfaceType::wtap:
- case IfaceType::etap:
- removedIface = DestroyEthernetIface(
- iface, use_ipv4_bridge_, use_ipv6_bridge_, use_ebtables_legacy_);
- break;
- case IfaceType::wbr:
- case IfaceType::ebr:
- removedIface = DestroyBridge(iface);
- break;
- case IfaceType::Invalid:
- break;
- }
-
- } else {
- LOG(WARNING) << "Interface not managed: " << iface;
- }
-
- if (isManagedIface) {
- LOG(INFO) << "Removed interface: " << iface;
- } else {
- LOG(WARNING) << "Could not remove interface: " << iface;
- }
-
- return isManagedIface;
-}
-
-bool ResourceManager::ValidateRequestList(const Json::Value& config) {
- if (!config.isMember("request_list") || !config["request_list"].isArray()) {
- LOG(WARNING) << "Request has invalid 'request_list' field";
- return false;
- }
-
- auto request_list = config["request_list"];
-
- Json::ArrayIndex size = request_list.size();
- if (size == 0) {
- LOG(WARNING) << "Request has empty 'request_list' field";
- return false;
- }
-
- for (Json::ArrayIndex i = 0; i < size; ++i) {
- if (!ValidateRequest(request_list[i])) {
- return false;
- }
- }
-
- return true;
-}
-
-bool ResourceManager::ValidateConfigRequest(const Json::Value& config) {
- if (!config.isMember("config_request") ||
- !config["config_request"].isObject()) {
- LOG(WARNING) << "Request has invalid 'config_request' field";
- return false;
- }
-
- Json::Value config_request = config["config_request"];
-
- return ValidateRequestList(config_request);
-}
-
-bool ResourceManager::ValidateRequest(const Json::Value& request) {
- if (!request.isMember("request_type") ||
- !request["request_type"].isString() ||
- StrToReqTy(request["request_type"].asString()) == RequestType::Invalid) {
- LOG(WARNING) << "Request has invalid 'request_type' field";
- return false;
- }
- return true;
-}
-
-void ResourceManager::JsonServer() {
- LOG(INFO) << "Starting server on " << kDefaultLocation;
- auto server = SharedFD::SocketLocalServer(kDefaultLocation, false,
- SOCK_STREAM, kSocketMode);
- CHECK(server->IsOpen()) << "Could not start server at " << kDefaultLocation;
- LOG(INFO) << "Accepting client connections";
-
- while (true) {
- auto client_socket = SharedFD::Accept(*server);
- CHECK(client_socket->IsOpen()) << "Error creating client socket";
-
- struct timeval timeout;
- timeout.tv_sec = 10;
- timeout.tv_usec = 0;
-
- int err = client_socket->SetSockOpt(SOL_SOCKET, SO_RCVTIMEO, &timeout,
- sizeof(timeout));
- if (err < 0) {
- LOG(WARNING) << "Could not set socket timeout";
- continue;
- }
-
- auto req_opt = RecvJsonMsg(client_socket);
-
- if (!req_opt) {
- LOG(WARNING) << "Invalid JSON Request, closing connection";
- continue;
- }
-
- Json::Value req = req_opt.value();
-
- if (!ValidateConfigRequest(req)) {
- continue;
- }
-
- Json::Value req_list = req["config_request"]["request_list"];
-
- Json::Value config_response;
- Json::Value response_list;
- Json::ArrayIndex req_list_size = req_list.size();
-
- // sentinel value, so we can populate the list of responses correctly
- // without trying to satisfy requests that will be aborted
- bool transaction_failed = false;
-
- for (Json::ArrayIndex i = 0; i < req_list_size; ++i) {
- LOG(INFO) << "Processing Request: " << i;
- auto req = req_list[i];
- auto req_ty_str = req["request_type"].asString();
- auto req_ty = StrToReqTy(req_ty_str);
-
- Json::Value response;
- if (transaction_failed) {
- response["request_type"] = req_ty_str;
- response["request_status"] = "pending";
- response["error"] = "";
- response_list.append(response);
- continue;
- }
-
- switch (req_ty) {
- case RequestType::ID: {
- response = JsonHandleIdRequest();
- break;
- }
- case RequestType::Shutdown: {
- if (i != 0 || req_list_size != 1) {
- response["request_type"] = req_ty_str;
- response["request_status"] = "failed";
- response["error"] =
- "Shutdown requests cannot be processed with other "
- "configuration requests";
- response_list.append(response);
- break;
- } else {
- response = JsonHandleShutdownRequest(client_socket);
- response_list.append(response);
- return;
- }
- }
- case RequestType::CreateInterface: {
- response = JsonHandleCreateInterfaceRequest(client_socket, req);
- break;
- }
- case RequestType::DestroyInterface: {
- response = JsonHandleDestroyInterfaceRequest(req);
- break;
- }
- case RequestType::StopSession: {
- response = JsonHandleStopSessionRequest(
- req, GetUserIDFromSock(client_socket));
- break;
- }
- case RequestType::Invalid: {
- LOG(WARNING) << "Invalid Request Type: " << req["request_type"];
- break;
- }
- }
-
- response_list.append(response);
- if (!(response["request_status"].asString() ==
- StatusToStr(RequestStatus::Success))) {
- LOG(INFO) << "Request failed:" << req;
- transaction_failed = true;
- continue;
- }
- }
-
- config_response["response_list"] = response_list;
-
- auto status =
- transaction_failed ? RequestStatus::Failure : RequestStatus::Success;
- config_response["config_status"] = StatusToStr(status);
-
- if (!transaction_failed) {
- auto session_id = AllocateSessionID();
- config_response["session_id"] = session_id;
- auto s = std::make_shared<Session>(session_id,
- GetUserIDFromSock(client_socket));
-
- // commit the resources
- s->Insert(pending_add_);
- pending_add_.clear();
- managed_sessions_.insert({session_id, s});
- } else {
- // be sure to release anything we've acquired if the transaction failed
- for (auto& droped_resource : pending_add_) {
- droped_resource.second->ReleaseResource();
- }
- }
-
- SendJsonMsg(client_socket, config_response);
- LOG(INFO) << "Closing connection to client";
- client_socket->Close();
- }
- server->Close();
-}
-
-uid_t GetUserIDFromSock(SharedFD client_socket) {
- struct ucred ucred {};
- socklen_t len = sizeof(struct ucred);
-
- if (-1 == client_socket->GetSockOpt(SOL_SOCKET, SO_PEERCRED, &ucred, &len)) {
- LOG(WARNING) << "Failed to get Socket Credentials";
- return -1;
- }
-
- return ucred.uid;
-}
-
-bool ResourceManager::CheckCredentials(SharedFD client_socket, uid_t uid) {
- uid_t sock_uid = GetUserIDFromSock(client_socket);
-
- if (sock_uid == -1) {
- LOG(WARNING) << "Invalid Socket UID: " << uid;
- return false;
- }
-
- if (uid != sock_uid) {
- LOG(WARNING) << "Message UID: " << uid
- << " does not match socket's EUID: " << sock_uid;
- return false;
- }
-
- return true;
-}
-
-Json::Value ResourceManager::JsonHandleIdRequest() {
- Json::Value resp;
- resp["request_type"] = "allocate_id";
- resp["request_status"] = StatusToStr(RequestStatus::Success);
- resp["id"] = AllocateSessionID();
- return resp;
-}
-
-Json::Value ResourceManager::JsonHandleShutdownRequest(SharedFD client_socket) {
- LOG(INFO) << "Received Shutdown Request";
- shutdown_socket_ = client_socket;
-
- Json::Value resp;
- resp["request_type"] = "shutdown";
- resp["request_status"] = "pending";
- resp["error"] = "";
-
- return resp;
-}
-
-Json::Value ResourceManager::JsonHandleCreateInterfaceRequest(
- SharedFD client_socket, const Json::Value& request) {
- LOG(INFO) << "Received CreateInterface Request";
-
- Json::Value resp;
- resp["request_type"] = "create_interface";
- resp["iface_name"] = "";
- resp["request_status"] = StatusToStr(RequestStatus::Failure);
- resp["error"] = "unknown";
-
- if (!request.isMember("uid") || !request["uid"].isUInt()) {
- auto err_msg = "Input event doesn't have a valid 'uid' field";
- LOG(WARNING) << err_msg;
- resp["error"] = err_msg;
- return resp;
- }
-
- if (!request.isMember("iface_type") || !request["iface_type"].isString()) {
- auto err_msg = "Input event doesn't have a valid 'iface_type' field";
- LOG(WARNING) << err_msg;
- resp["error"] = err_msg;
- return resp;
- }
-
- auto uid = request["uid"].asUInt();
-
- if (!CheckCredentials(client_socket, uid)) {
- auto err_msg = "Credential check failed";
- LOG(WARNING) << err_msg;
- resp["error"] = err_msg;
- return resp;
- }
-
- auto user_opt = GetUserName(uid);
-
- bool addedIface = false;
- std::stringstream ss;
- if (!user_opt) {
- auto err_msg = "UserName could not be matched to UID";
- LOG(WARNING) << err_msg;
- resp["error"] = err_msg;
- return resp;
- } else {
- auto iface_ty_name = request["iface_type"].asString();
- resp["iface_type"] = iface_ty_name;
- auto iface_type = StrToIfaceTy(iface_ty_name);
- auto attempts = kMaxIfaceNameId;
- do {
- auto id = AllocateResourceID();
- resp["resource_id"] = id;
- ss << "cvd-" << iface_ty_name << "-" << user_opt.value().substr(0, 4)
- << std::setfill('0') << std::setw(2) << (id % kMaxIfaceNameId);
- addedIface = AddInterface(ss.str(), iface_type, id, uid);
- --attempts;
- } while (!addedIface && (attempts > 0));
- }
-
- if (addedIface) {
- resp["request_status"] = StatusToStr(RequestStatus::Success);
- resp["iface_name"] = ss.str();
- resp["error"] = "";
- }
-
- return resp;
-}
-
-Json::Value ResourceManager::JsonHandleDestroyInterfaceRequest(
- const Json::Value& request) {
- Json::Value resp;
- resp["request_type"] = "destroy_interface";
- resp["request_status"] = StatusToStr(RequestStatus::Failure);
- if (!request.isMember("iface_name") || !request["iface_name"].isString()) {
- auto err_msg = "Input event doesn't have a valid 'iface_name' field";
- LOG(WARNING) << err_msg;
- resp["error"] = err_msg;
- return resp;
- }
-
- auto iface_name = request["iface_name"].asString();
-
- bool isManagedIface = active_interfaces_.erase(iface_name) > 0;
-
- if (!isManagedIface) {
- auto msg = "Interface not managed: " + iface_name;
- LOG(WARNING) << msg;
- resp["error"] = msg;
- return resp;
- }
-
- if (!request.isMember("session_id") || !request["session_id"].isUInt()) {
- auto err_msg = "Input event doesn't have a valid 'session_id' field";
- LOG(WARNING) << err_msg;
- resp["error"] = err_msg;
- return resp;
- }
-
- auto session_id = request["session_id"].asUInt();
-
- auto resource_id = request["resource_id"].asUInt();
-
- LOG(INFO) << "Received DestroyInterface Request for " << iface_name
- << " in session: " << session_id
- << ", resource_id: " << resource_id;
-
- auto sess_opt = FindSession(session_id);
- if (!sess_opt) {
- auto msg = "Interface " + iface_name +
- " was not managed in session: " + std::to_string(session_id) +
- " with resource_id: " + std::to_string(resource_id);
- LOG(WARNING) << msg;
- resp["error"] = msg;
- return resp;
- }
-
- auto s = sess_opt.value();
-
- // while we could wait to see if any acquisitions fail and delay releasing
- // resources until they are all finished, this operation is inherently
- // destructive, so should a release operation fail, there is no satisfactory
- // method for aborting the transaction. Instead, we try to release the
- // resource and then can signal to the rest of the transaction the failure
- // state, which can then just stop the transaction, and revert any newly
- // acquired resources, but any successful drop requests will persist
- auto did_drop_resource = s->ReleaseResource(resource_id);
-
- if (did_drop_resource) {
- resp["request_status"] = StatusToStr(RequestStatus::Success);
- } else {
- auto msg = "Interface " + iface_name +
- " was not managed in session: " + std::to_string(session_id) +
- " with resource_id: " + std::to_string(resource_id);
- LOG(WARNING) << msg;
- resp["error"] = msg;
- }
-
- return resp;
-}
-
-Json::Value ResourceManager::JsonHandleStopSessionRequest(
- const Json::Value& request, uid_t uid) {
- Json::Value resp;
- resp["request_type"] = ReqTyToStr(RequestType::StopSession);
- resp["request_status"] = StatusToStr(RequestStatus::Failure);
- if (!request.isMember("session_id") || !request["session_id"].isUInt()) {
- auto err_msg = "Input event doesn't have a valid 'session_id' field";
- LOG(WARNING) << err_msg;
- resp["error"] = err_msg;
- return resp;
- }
-
- auto session_id = request["session_id"].asUInt();
- LOG(INFO) << "Received StopSession Request for Session ID: " << session_id;
-
- auto it = managed_sessions_.find(session_id);
- if (it == managed_sessions_.end()) {
- auto msg = "Session not managed: " + std::to_string(session_id);
- LOG(WARNING) << msg;
- resp["error"] = msg;
- return resp;
- }
-
- if (it->second->GetUID() != uid) {
- auto msg = "Effective user ID does not match session owner. socket uid: " +
- std::to_string(uid);
- LOG(WARNING) << msg;
- resp["error"] = msg;
- return resp;
- }
-
- // while we could wait to see if any acquisitions fail and delay releasing
- // resources until they are all finished, this operation is inherently
- // destructive, so should a release operation fail, there is no satisfactory
- // method for aborting the transaction. Instead, we try to release the
- // resource and then can signal to the rest of the transaction the failure
- // state
- auto success = it->second->ReleaseAllResources();
-
- // release the names from the global list for reuse in future requests
- for (auto& iface : it->second->GetActiveInterfaces()) {
- active_interfaces_.erase(iface);
- }
-
- if (success) {
- managed_sessions_.erase(it);
- resp["request_status"] = StatusToStr(RequestStatus::Success);
- } else {
- resp["error"] =
- "unknown, allocd experienced an error ending the session id: " +
- std::to_string(session_id);
- }
-
- return resp;
-}
-
-std::optional<std::shared_ptr<Session>> ResourceManager::FindSession(
- uint32_t id) {
- auto it = managed_sessions_.find(id);
- if (it == managed_sessions_.end()) {
- return std::nullopt;
- } else {
- return it->second;
- }
-}
-
-} // namespace cuttlefish
diff --git a/host/libs/allocd/resource_manager.h b/host/libs/allocd/resource_manager.h
deleted file mode 100644
index 32f06cf88..000000000
--- a/host/libs/allocd/resource_manager.h
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Copyright (C) 2020 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 <sys/types.h>
-
-#include <atomic>
-#include <cstdint>
-#include <map>
-#include <memory>
-#include <optional>
-#include <set>
-
-#include "common/libs/fs/shared_fd.h"
-#include "host/libs/allocd/alloc_utils.h"
-#include "host/libs/allocd/request.h"
-#include "host/libs/allocd/resource.h"
-#include "host/libs/allocd/utils.h"
-
-namespace cuttlefish {
-
-class Session {
- public:
- explicit Session(uint32_t session_id, uid_t uid)
- : session_id_(session_id), uid_(uid) {}
- ~Session() { ReleaseAllResources(); }
-
- uint32_t GetSessionID() { return session_id_; }
- uid_t GetUID() { return uid_; }
-
- const std::set<std::string>& GetActiveInterfaces() {
- return active_interfaces_;
- }
-
- void Insert(
- const std::map<uint32_t, std::shared_ptr<StaticResource>>& resources) {
- managed_resources_.insert(resources.begin(), resources.end());
- }
-
- bool ReleaseAllResources() {
- bool success = true;
- for (auto& res : managed_resources_) {
- success &= res.second->ReleaseResource();
- }
- managed_resources_.clear();
-
- return success;
- }
-
- bool ReleaseResource(uint32_t resource_id) {
- auto it = managed_resources_.find(resource_id);
- if (it == managed_resources_.end()) {
- return false;
- }
-
- auto success = it->second->ReleaseResource();
- if (success) {
- managed_resources_.erase(it);
- }
-
- return success;
- }
-
- private:
- uint32_t session_id_{};
- uid_t uid_{};
- std::set<std::string> active_interfaces_;
- std::map<uint32_t, std::shared_ptr<StaticResource>> managed_resources_;
-};
-
-/* Manages static resources while the daemon is running.
- * When resources, such as network interfaces are requested the ResourceManager
- * allocates the resources and takes ownership of them. It will keep maintain
- * the resource, until requested to release it(i.e. destroy it and/or tear down
- * related config). When the daemon is stopped, it will walk its list of owned
- * resources, and deallocate them from the system.
- *
- * Clients can request new resources by connecting to a socket, and sending a
- * JSON request, detailing the type of resource required.
- */
-struct ResourceManager {
- public:
- ResourceManager() = default;
-
- ~ResourceManager();
-
- void SetSocketLocation(const std::string& sock_name);
-
- void SetUseEbtablesLegacy(bool use_legacy);
-
- void JsonServer();
-
- private:
- uint32_t AllocateResourceID();
- uint32_t AllocateSessionID();
-
- bool AddInterface(const std::string& iface, IfaceType ty, uint32_t id,
- uid_t uid);
-
- bool RemoveInterface(const std::string& iface, IfaceType ty);
-
- bool ValidateRequest(const Json::Value& request);
-
- bool ValidateRequestList(const Json::Value& config);
-
- bool ValidateConfigRequest(const Json::Value& config);
-
- Json::Value JsonHandleIdRequest();
-
- Json::Value JsonHandleShutdownRequest(SharedFD client_socket);
-
- Json::Value JsonHandleCreateInterfaceRequest(SharedFD client_socket,
- const Json::Value& request);
-
- Json::Value JsonHandleDestroyInterfaceRequest(const Json::Value& request);
-
- Json::Value JsonHandleStopSessionRequest(const Json::Value& request,
- uid_t uid);
-
- bool CheckCredentials(SharedFD client_socket, uid_t uid);
-
- void SetUseIpv4Bridge(bool ipv4) { use_ipv4_bridge_ = ipv4; }
-
- void SetUseIpv6Bridge(bool ipv6) { use_ipv6_bridge_ = ipv6; }
-
- std::optional<std::shared_ptr<Session>> FindSession(uint32_t id);
-
- private:
- std::atomic_uint32_t global_resource_id_ = 0;
- std::atomic_uint32_t session_id_ = 0;
- std::set<std::string> active_interfaces_;
- std::map<uint32_t, std::shared_ptr<Session>> managed_sessions_;
- std::map<uint32_t, std::shared_ptr<StaticResource>> pending_add_;
- std::string location = kDefaultLocation;
- bool use_ipv4_bridge_ = true;
- bool use_ipv6_bridge_ = true;
- bool use_ebtables_legacy_ = false;
- cuttlefish::SharedFD shutdown_socket_;
-};
-
-} // namespace cuttlefish
diff --git a/host/libs/allocd/test/client.cpp b/host/libs/allocd/test/client.cpp
deleted file mode 100644
index 235f52122..000000000
--- a/host/libs/allocd/test/client.cpp
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * Copyright (C) 2020 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 <android-base/logging.h>
-#include <gflags/gflags.h>
-#include <json/json.h>
-#include <unistd.h>
-
-#include <iostream>
-
-#include "common/libs/fs/shared_fd.h"
-#include "host/libs/allocd/request.h"
-#include "host/libs/allocd/utils.h"
-#include "host/libs/config/logging.h"
-
-using namespace cuttlefish;
-
-DEFINE_string(socket_path, kDefaultLocation, "Socket path");
-DEFINE_bool(id, false, "Request new UUID");
-DEFINE_bool(ifcreate, false, "Request a new Interface");
-DEFINE_bool(shutdown, false, "Shutdown Resource Allocation Server");
-DEFINE_bool(stop_session, false, "Remove all resources from session");
-DEFINE_string(ifdestroy, "", "Request an interface be destroyed");
-DEFINE_uint32(ifid, -1, "Global Resource ID");
-DEFINE_uint32(session, -1, "Session ID");
-
-int main(int argc, char* argv[]) {
- cuttlefish::DefaultSubprocessLogging(argv);
- google::ParseCommandLineFlags(&argc, &argv, true);
-
- SharedFD monitor_socket = cuttlefish::SharedFD::SocketLocalClient(
- FLAGS_socket_path, false, SOCK_STREAM);
- if (!monitor_socket->IsOpen()) {
- LOG(ERROR) << "Unable to connect to launcher monitor on "
- << FLAGS_socket_path << ": " << monitor_socket->StrError();
- return 1;
- }
-
- if (FLAGS_id) {
- Json::Value req;
- req["request_type"] = "allocate_id";
- SendJsonMsg(monitor_socket, req);
-
- auto resp_opt = RecvJsonMsg(monitor_socket);
- if (!resp_opt.has_value()) {
- std::cout << "Bad Response from server\n";
- return -1;
- }
-
- auto resp = resp_opt.value();
- std::cout << resp << "\n";
- std::cout << "New ID operation: " << resp["request_status"] << std::endl;
- std::cout << "New ID: " << resp["id"] << std::endl;
- }
-
- Json::Value config;
- Json::Value request_list;
-
- if (FLAGS_ifcreate) {
- Json::Value req;
- req["request_type"] = "create_interface";
- req["uid"] = geteuid();
- req["iface_type"] = "mtap";
- request_list.append(req);
- req["iface_type"] = "wtap";
-
- request_list.append(req);
- config["config_request"]["request_list"] = request_list;
-
- std::cout << config << "\n";
- SendJsonMsg(monitor_socket, config);
-
- auto resp_opt = RecvJsonMsg(monitor_socket);
- if (!resp_opt.has_value()) {
- std::cout << "Bad Response from server\n";
- return -1;
- }
-
- auto resp = resp_opt.value();
-
- std::cout << resp << "\n";
- std::cout << "Create Interface operation: " << resp["request_status"]
- << std::endl;
- std::cout << resp["iface_name"] << std::endl;
- }
-
- if (!FLAGS_ifdestroy.empty() && (FLAGS_ifid != -1) && (FLAGS_session != -1)) {
- Json::Value req;
- req["request_type"] = "destroy_interface";
- req["iface_name"] = FLAGS_ifdestroy;
- req["resource_id"] = FLAGS_ifid;
- req["session_id"] = FLAGS_session;
- request_list.append(req);
- config["config_request"]["request_list"] = request_list;
- SendJsonMsg(monitor_socket, config);
-
- LOG(INFO) << "Request Interface : '" << FLAGS_ifdestroy << "' be removed";
-
- auto resp_opt = RecvJsonMsg(monitor_socket);
- if (!resp_opt.has_value()) {
- std::cout << "Bad Response from server\n";
- return -1;
- }
-
- auto resp = resp_opt.value();
-
- std::cout << resp << "\n";
-
- std::cout << "Destroy Interface operation: " << resp["request_status"]
- << std::endl;
- std::cout << resp["iface_name"] << std::endl;
- }
-
- if (FLAGS_stop_session && (FLAGS_session != -1)) {
- Json::Value req;
- req["request_type"] = "stop_session";
- req["session_id"] = FLAGS_session;
- request_list.append(req);
- config["config_request"]["request_list"] = request_list;
- SendJsonMsg(monitor_socket, config);
-
- LOG(INFO) << "Request Session : '" << FLAGS_session << "' be stopped";
-
- auto resp_opt = RecvJsonMsg(monitor_socket);
- if (!resp_opt.has_value()) {
- std::cout << "Bad Response from server\n";
- return -1;
- }
-
- auto resp = resp_opt.value();
-
- std::cout << resp << "\n";
- std::cout << "Stop Session operation: " << resp["config_status"];
- }
-
- if (FLAGS_shutdown) {
- Json::Value req;
- req["request_type"] = "shutdown";
-
- request_list.append(req);
- config["config_request"]["request_list"] = request_list;
- cuttlefish::SendJsonMsg(monitor_socket, config);
-
- auto resp_opt = cuttlefish::RecvJsonMsg(monitor_socket);
- if (!resp_opt.has_value()) {
- std::cout << "Bad Response from server\n";
- return -1;
- }
-
- auto resp = resp_opt.value();
-
- std::cout << resp << "\n";
- std::cout << "Shutdown operation: " << resp["request_status"] << std::endl;
- }
-
- return 0;
-}
diff --git a/host/libs/allocd/utils.cpp b/host/libs/allocd/utils.cpp
deleted file mode 100644
index 64eb127e7..000000000
--- a/host/libs/allocd/utils.cpp
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * Copyright (C) 2020 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 "host/libs/allocd/utils.h"
-
-#include <cstdint>
-#include <optional>
-
-#include "common/libs/fs/shared_buf.h"
-#include "common/libs/fs/shared_fd.h"
-#include "host/libs/allocd/request.h"
-
-namespace cuttlefish {
-
-// While the JSON schema and payload structure are designed to be extensible,
-// and avoid version incompatibility. However, should project requirements
-// change, it is necessary that we have a mechanism to handle incompatibilities
-// that arise over time. If an incompatibility should come about, the
-// kMinHeaderVersion constant should be increased to match the new minimal set
-// of features that are supported.
-
-/// Current supported Header version number
-constexpr uint16_t kCurHeaderVersion = 1;
-
-/// Oldest compatible header version number
-constexpr uint16_t kMinHeaderVersion = 1;
-
-const std::map<RequestType, const char*> RequestTyToStrMap = {
- {RequestType::ID, "alloc_id"},
- {RequestType::CreateInterface, "create_interface"},
- {RequestType::DestroyInterface, "destroy_interface"},
- {RequestType::StopSession, "stop_session"},
- {RequestType::Shutdown, "shutdown"},
- {RequestType::Invalid, "invalid"}};
-
-const std::map<std::string, RequestType> StrToRequestTyMap = {
- {"alloc_id", RequestType::ID},
- {"create_interface", RequestType::CreateInterface},
- {"destroy_interface", RequestType::DestroyInterface},
- {"stop_session", RequestType::StopSession},
- {"shutdown", RequestType::Shutdown},
- {"invalid", RequestType::Invalid}};
-
-const std::map<std::string, IfaceType> StrToIfaceTyMap = {
- {"invalid", IfaceType::Invalid},
- {"mtap", IfaceType::mtap},
- {"wtap", IfaceType::wtap},
- {"etap", IfaceType::etap},
- {"wbr", IfaceType::wbr},
- {"ebr", IfaceType::ebr}};
-
-const std::map<IfaceType, std::string> IfaceTyToStrMap = {
- {IfaceType::Invalid, "invalid"},
- {IfaceType::mtap, "mtap"},
- {IfaceType::wtap, "wtap"},
- {IfaceType::etap, "etap"},
- {IfaceType::wbr, "wbr"},
- {IfaceType::ebr, "ebr"}};
-
-const std::map<RequestStatus, std::string> ReqStatusToStrMap = {
- {RequestStatus::Invalid, "invalid"},
- {RequestStatus::Pending, "pending"},
- {RequestStatus::Failure, "failure"},
- {RequestStatus::Success, "success"}};
-
-const std::map<std::string, RequestStatus> StrToReqStatusMap = {
- {"invalid", RequestStatus::Invalid},
- {"pending", RequestStatus::Pending},
- {"failure", RequestStatus::Failure},
- {"success", RequestStatus::Success}};
-
-bool SendJsonMsg(SharedFD client_socket, const Json::Value& resp) {
- LOG(INFO) << "Sending JSON message";
- Json::StreamWriterBuilder factory;
- auto resp_str = Json::writeString(factory, resp);
-
- std::string header_buff(sizeof(RequestHeader), 0);
-
- // fill in header
- RequestHeader* header = reinterpret_cast<RequestHeader*>(header_buff.data());
- header->len = resp_str.size();
- header->version = kCurHeaderVersion;
-
- auto payload = header_buff + resp_str;
-
- return SendAll(client_socket, payload);
-}
-
-std::optional<Json::Value> RecvJsonMsg(SharedFD client_socket) {
- LOG(INFO) << "Receiving JSON message";
- RequestHeader header;
- client_socket->Recv(&header, sizeof(header), kRecvFlags);
-
- if (header.version < kMinHeaderVersion) {
- LOG(WARNING) << "bad request header version: " << header.version;
- return std::nullopt;
- }
-
- std::string payload = RecvAll(client_socket, header.len);
-
- JsonRequestReader reader;
- return reader.parse(payload);
-}
-
-std::string ReqTyToStr(RequestType req_ty) {
- switch (req_ty) {
- case RequestType::Invalid:
- return "invalid";
- case RequestType::Shutdown:
- return "shutdown";
- case RequestType::StopSession:
- return "stop_session";
- case RequestType::DestroyInterface:
- return "destroy_interface";
- case RequestType::CreateInterface:
- return "create_interface";
- case RequestType::ID:
- return "id";
- }
-}
-
-RequestType StrToReqTy(const std::string& req) {
- auto it = StrToRequestTyMap.find(req);
- if (it == StrToRequestTyMap.end()) {
- return RequestType::Invalid;
- } else {
- return it->second;
- }
-}
-
-RequestStatus StrToStatus(const std::string& st) {
- auto it = StrToReqStatusMap.find(st);
- if (it == StrToReqStatusMap.end()) {
- return RequestStatus::Invalid;
- } else {
- return it->second;
- }
-}
-
-std::string StatusToStr(RequestStatus st) {
- switch (st) {
- case RequestStatus::Invalid:
- return "invalid";
- case RequestStatus::Pending:
- return "pending";
- case RequestStatus::Success:
- return "success";
- case RequestStatus::Failure:
- return "failure";
- }
-}
-
-std::string IfaceTyToStr(IfaceType iface) {
- switch (iface) {
- case IfaceType::Invalid:
- return "invalid";
- case IfaceType::mtap:
- return "mtap";
- case IfaceType::wtap:
- return "wtap";
- case IfaceType::etap:
- return "etap";
- case IfaceType::wbr:
- return "wbr";
- case IfaceType::ebr:
- return "ebr";
- }
-}
-
-IfaceType StrToIfaceTy(const std::string& iface) {
- auto it = StrToIfaceTyMap.find(iface);
- if (it == StrToIfaceTyMap.end()) {
- return IfaceType::Invalid;
- } else {
- return it->second;
- }
-}
-
-} // namespace cuttlefish
diff --git a/host/libs/allocd/utils.h b/host/libs/allocd/utils.h
deleted file mode 100644
index f17393547..000000000
--- a/host/libs/allocd/utils.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2020 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 <android-base/logging.h>
-#include <json/json.h>
-
-#include <optional>
-#include <string>
-
-#include "common/libs/fs/shared_fd.h"
-#include "host/libs/allocd/request.h"
-#include "host/libs/config/logging.h"
-
-namespace cuttlefish {
-
-constexpr char kDefaultLocation[] =
- "/var/run/cuttlefish/cuttlefish_allocd.sock";
-
-// Default flags for send and receive.
-static constexpr int kSendFlags = 0;
-static constexpr int kRecvFlags = 0;
-
-/// Sends a Json value over client_socket
-///
-/// returns true if successfully sent the whole JSON object
-/// returns false otherwise
-bool SendJsonMsg(cuttlefish::SharedFD client_socket, const Json::Value& resp);
-
-/// Receives a single Json value over client_socket
-///
-/// The returned option will contain the JSON object when successful,
-/// or an std::nullopt if an error is reported
-std::optional<Json::Value> RecvJsonMsg(cuttlefish::SharedFD client_socket);
-
-// Helper functions mapping between Enum types and std::string
-
-RequestType StrToReqTy(const std::string& req);
-
-std::string ReqTyToStr(RequestType req_ty);
-
-IfaceType StrToIfaceTy(const std::string& iface);
-
-std::string IfaceTyToStr(IfaceType iface);
-
-RequestStatus StrToStatus(const std::string& st);
-
-std::string StatusToStr(RequestStatus st);
-
-} // namespace cuttlefish
diff --git a/host/libs/audio_connector/buffers.cpp b/host/libs/audio_connector/buffers.cpp
deleted file mode 100644
index 29804cadf..000000000
--- a/host/libs/audio_connector/buffers.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-//
-// Copyright (C) 2020 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 "host/libs/audio_connector/buffers.h"
-
-#include <android-base/logging.h>
-
-namespace cuttlefish {
-
-ShmBuffer::ShmBuffer(ShmBuffer&& other)
- : header_(std::move(other.header_)),
- len_(std::move(other.len_)),
- on_consumed_(std::move(other.on_consumed_)),
- status_sent_(other.status_sent_) {
- // It's now this buffer's responsibility to send the status.
- other.status_sent_ = true;
-}
-
-ShmBuffer::~ShmBuffer() {
- CHECK(status_sent_) << "Disposing of ShmBuffer before setting status";
-}
-
-uint32_t ShmBuffer::stream_id() const { return header_.stream_id.as_uint32_t(); }
-
-void ShmBuffer::SendStatus(AudioStatus status, uint32_t latency_bytes,
- uint32_t consumed_len) {
- on_consumed_(status, latency_bytes, consumed_len);
- status_sent_ = true;
-}
-
-} // namespace cuttlefish
diff --git a/host/libs/audio_connector/buffers.h b/host/libs/audio_connector/buffers.h
deleted file mode 100644
index a92fd83f9..000000000
--- a/host/libs/audio_connector/buffers.h
+++ /dev/null
@@ -1,92 +0,0 @@
-//
-// Copyright (C) 2020 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 <cinttypes>
-#include <functional>
-
-#include "host/libs/audio_connector/shm_layout.h"
-
-namespace cuttlefish {
-
-enum class Status : uint32_t {
- Ok = 0x8000,
- BadMessage,
- NotSupported,
- IOError,
-};
-
-using OnConsumedCb = std::function<void(AudioStatus, uint32_t /*latency*/,
- uint32_t /*consumed length*/)>;
-
-// Wraps and provides access to audio buffers sent by the client.
-// Objects of this class can only be moved, not copied. Destroying a buffer
-// without sending the status to the client is a bug so the program aborts in
-// those cases.
-class ShmBuffer {
- public:
- ShmBuffer(const virtio_snd_pcm_xfer& header, uint32_t len,
- OnConsumedCb on_consumed)
- : header_(header), len_(len), on_consumed_(on_consumed) {}
- ShmBuffer(const ShmBuffer& other) = delete;
- ShmBuffer(ShmBuffer&& other);
- ShmBuffer& operator=(const ShmBuffer& other) = delete;
-
- ~ShmBuffer();
-
- uint32_t stream_id() const;
- uint32_t len() const { return len_; }
-
- void SendStatus(AudioStatus status, uint32_t latency_bytes,
- uint32_t consumed_len);
-
- private:
- const virtio_snd_pcm_xfer header_;
- const uint32_t len_;
- OnConsumedCb on_consumed_;
- bool status_sent_ = false;
-};
-
-class TxBuffer : public ShmBuffer {
- public:
- TxBuffer(const virtio_snd_pcm_xfer& header, const volatile uint8_t* buffer,
- uint32_t len, OnConsumedCb on_consumed)
- : ShmBuffer(header, len, on_consumed), buffer_(buffer) {}
- TxBuffer(const TxBuffer& other) = delete;
- TxBuffer(TxBuffer&& other) = default;
- TxBuffer& operator=(const TxBuffer& other) = delete;
-
- const volatile uint8_t* get() const { return buffer_; }
-
- private:
- const volatile uint8_t* const buffer_;
-};
-
-class RxBuffer : public ShmBuffer {
- public:
- RxBuffer(const virtio_snd_pcm_xfer& header, volatile uint8_t* buffer,
- uint32_t len, OnConsumedCb on_consumed)
- : ShmBuffer(header, len, on_consumed), buffer_(buffer) {}
- RxBuffer(const RxBuffer& other) = delete;
- RxBuffer(RxBuffer&& other) = default;
- RxBuffer& operator=(const RxBuffer& other) = delete;
-
- volatile uint8_t* get() const { return buffer_; }
-
- private:
- volatile uint8_t* const buffer_;
-};
-
-} // namespace cuttlefish
diff --git a/host/libs/audio_connector/commands.cpp b/host/libs/audio_connector/commands.cpp
deleted file mode 100644
index 42536d59b..000000000
--- a/host/libs/audio_connector/commands.cpp
+++ /dev/null
@@ -1,79 +0,0 @@
-//
-// Copyright (C) 2020 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 "host/libs/audio_connector/commands.h"
-
-#include <android-base/logging.h>
-
-#include "host/libs/audio_connector/shm_layout.h"
-
-namespace cuttlefish {
-
-AudioCommand::~AudioCommand() {
- CHECK(status_ != AudioStatus::NOT_SET)
- << "A command of type " << static_cast<uint32_t>(type())
- << " went out of scope without reply";
-}
-
-StreamInfoCommand::StreamInfoCommand(uint32_t start_id, size_t count,
- virtio_snd_pcm_info* pcm_info)
- : InfoCommand(AudioCommandType::VIRTIO_SND_R_PCM_INFO, start_id, count,
- pcm_info) {}
-
-void StreamInfoCommand::Reply(AudioStatus status,
- const std::vector<virtio_snd_pcm_info>& reply) {
- MarkReplied(status);
- if (status != AudioStatus::VIRTIO_SND_S_OK) {
- return;
- }
- CHECK(reply.size() == count())
- << "Returned unmatching info count: " << reply.size() << " vs "
- << count();
- for (int i = 0; i < reply.size(); ++i) {
- info_reply()[i].hdr.hda_fn_nid = Le32(reply[i].hdr.hda_fn_nid);
- info_reply()[i].features = Le32(reply[i].features);
- info_reply()[i].formats = Le64(reply[i].formats);
- info_reply()[i].rates = Le64(reply[i].rates);
- info_reply()[i].direction = reply[i].direction;
- info_reply()[i].channels_min = reply[i].channels_min;
- info_reply()[i].channels_max = reply[i].channels_max;
- // pcm_info[i].padding is supposed to be all zeros in virtio-snd but here we
- // can just ignore it.
- }
-}
-
-StreamControlCommand::StreamControlCommand(AudioCommandType type,
- uint32_t stream_id)
- : AudioCommand(type), stream_id_(stream_id) {}
-
-void StreamControlCommand::Reply(AudioStatus status) {
- // These commands don't expect a reply, this method just forces
- // acknowledgement of the command.
- MarkReplied(status);
-}
-
-StreamSetParamsCommand::StreamSetParamsCommand(
- uint32_t stream_id, uint32_t buffer_bytes, uint32_t period_bytes,
- uint32_t features, uint8_t channels, uint8_t format, uint8_t rate)
- : StreamControlCommand(AudioCommandType::VIRTIO_SND_R_PCM_SET_PARAMS,
- stream_id),
- buffer_bytes_(buffer_bytes),
- period_bytes_(period_bytes),
- features_(features),
- channels_(channels),
- format_(format),
- rate_(rate) {}
-
-} // namespace cuttlefish
diff --git a/host/libs/audio_connector/commands.h b/host/libs/audio_connector/commands.h
deleted file mode 100644
index 849dc1276..000000000
--- a/host/libs/audio_connector/commands.h
+++ /dev/null
@@ -1,107 +0,0 @@
-//
-// Copyright (C) 2020 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 <vector>
-
-#include "host/libs/audio_connector/shm_layout.h"
-
-namespace cuttlefish {
-
-class AudioCommand {
- public:
- virtual ~AudioCommand();
-
- AudioCommandType type() const { return type_; }
- AudioStatus status() const { return status_; }
-
- protected:
- AudioCommand(AudioCommandType type) : type_(type) {}
-
- void MarkReplied(AudioStatus status) { status_ = status; }
-
- private:
- AudioStatus status_ = AudioStatus::NOT_SET;
- const AudioCommandType type_;
-};
-
-template <typename R>
-class InfoCommand : public AudioCommand {
- public:
- InfoCommand(AudioCommandType type, uint32_t start_id, size_t count, R* reply)
- : AudioCommand(type),
- start_id_(start_id),
- count_(count),
- info_reply_(reply) {}
-
- uint32_t start_id() const { return start_id_; }
- uint32_t count() const { return count_; }
-
- protected:
- R* info_reply() { return info_reply_; }
-
- private:
- const uint32_t start_id_;
- const size_t count_;
- R* info_reply_;
-};
-
-class StreamInfoCommand : public InfoCommand<virtio_snd_pcm_info> {
- public:
- StreamInfoCommand(uint32_t start_id, size_t count,
- virtio_snd_pcm_info* pcm_info);
-
- void Reply(AudioStatus status, const std::vector<virtio_snd_pcm_info>& reply);
-};
-
-// Serves the START, STOP, PREPARE and RELEASE commands. It's also the
-// superclass of the class handling SET_PARAMS
-struct StreamControlCommand : public AudioCommand {
- public:
- StreamControlCommand(AudioCommandType type, uint32_t stream_id);
-
- uint32_t stream_id() const { return stream_id_; }
-
- void Reply(AudioStatus status);
-
- private:
- const uint32_t stream_id_;
-};
-
-struct StreamSetParamsCommand : public StreamControlCommand {
- public:
- StreamSetParamsCommand(uint32_t stream_id, uint32_t buffer_bytes,
- uint32_t period_bytes, uint32_t features,
- uint8_t channels, uint8_t format, uint8_t rate);
-
- uint32_t buffer_bytes() const { return buffer_bytes_; }
- uint32_t period_bytes() const { return period_bytes_; }
- uint32_t features() const { return features_; }
- uint8_t channels() const { return channels_; }
- uint8_t format() const { return format_; }
- uint8_t rate() const { return rate_; }
-
- private:
- const uint32_t buffer_bytes_;
- const uint32_t period_bytes_;
- const uint32_t features_;
- const uint8_t channels_;
- const uint8_t format_;
- const uint8_t rate_;
-};
-
-} // namespace cuttlefish
diff --git a/host/libs/audio_connector/server.cpp b/host/libs/audio_connector/server.cpp
deleted file mode 100644
index b925cdd35..000000000
--- a/host/libs/audio_connector/server.cpp
+++ /dev/null
@@ -1,357 +0,0 @@
-//
-// Copyright (C) 2020 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 "host/libs/audio_connector/server.h"
-
-#include <errno.h>
-#include <fcntl.h>
-#include <strings.h>
-#include <unistd.h>
-
-#include <utility>
-
-#include <android-base/logging.h>
-
-#include "common/libs/fs/shared_select.h"
-
-namespace cuttlefish {
-
-namespace {
-
-ScopedMMap AllocateShm(size_t size, const std::string& name, SharedFD* shm_fd) {
- *shm_fd = SharedFD::MemfdCreate(name, 0);
- if (!(*shm_fd)->IsOpen()) {
- LOG(FATAL) << "Unable to allocate create file for " << name << ": "
- << (*shm_fd)->StrError();
- return ScopedMMap();
- }
-
- auto truncate_ret = (*shm_fd)->Truncate(size);
- if (truncate_ret != 0) {
- LOG(FATAL) << "Unable to resize " << name << " to " << size
- << " bytes: " << (*shm_fd)->StrError();
- return ScopedMMap();
- }
-
- auto mmap_res = (*shm_fd)->MMap(NULL /* addr */, size, PROT_READ | PROT_WRITE,
- MAP_SHARED, 0 /*offset*/);
- if (!mmap_res) {
- LOG(FATAL) << "Unable to memory map " << name << ": "
- << (*shm_fd)->StrError();
- }
- return mmap_res;
-}
-
-bool CreateSocketPair(SharedFD* local, SharedFD* remote) {
- auto ret = SharedFD::SocketPair(AF_UNIX, SOCK_SEQPACKET, 0, local, remote);
- if (!ret) {
- LOG(ERROR) << "Unable to create socket pair for audio IO signaling: "
- << (*local)->StrError();
- }
- return ret;
-}
-
-std::function<void(AudioStatus, uint32_t, uint32_t)> SendStatusCallback(
- uint32_t buffer_offset, SharedFD socket) {
- // Consumption of an audio buffer is an asynchronous event, which could
- // trigger after the client disconnected. A WeakFD ensures that the response
- // will only be sent if there is still a client available.
- auto weak_socket = WeakFD(socket);
- return
- [buffer_offset, weak_socket](AudioStatus status, uint32_t latency_bytes,
- uint32_t consumed_length) {
- auto socket = weak_socket.lock();
- if (!socket->IsOpen()) {
- return;
- }
- IoStatusMsg reply;
- reply.status.status = Le32(static_cast<uint32_t>(status));
- reply.status.latency_bytes = Le32(latency_bytes);
- reply.buffer_offset = buffer_offset;
- reply.consumed_length = consumed_length;
- // Send the acknowledgment non-blockingly to avoid a slow client from
- // blocking the server.
- auto sent = socket->Send(&reply, sizeof(reply), MSG_DONTWAIT);
- if (sent < sizeof(reply)) {
- LOG(ERROR) << "Failed to send entire reply: " << socket->StrError();
- }
- };
-}
-
-} // namespace
-
-std::unique_ptr<AudioClientConnection> AudioServer::AcceptClient(
- uint32_t num_streams, uint32_t num_jacks, uint32_t num_chmaps,
- size_t tx_shm_len, size_t rx_shm_len) {
- auto conn_fd = SharedFD::Accept(*server_socket_, nullptr, 0);
- if (!conn_fd->IsOpen()) {
- LOG(ERROR) << "Connection failed on audio server: " << conn_fd->StrError();
- return nullptr;
- }
- return AudioClientConnection::Create(conn_fd, num_streams, num_jacks,
- num_chmaps, tx_shm_len, rx_shm_len);
-}
-
-/* static */
-std::unique_ptr<AudioClientConnection> AudioClientConnection::Create(
- SharedFD client_socket, uint32_t num_streams, uint32_t num_jacks,
- uint32_t num_chmaps, size_t tx_shm_len, size_t rx_shm_len) {
- SharedFD event_socket, event_pair;
- SharedFD tx_socket, tx_pair;
- SharedFD rx_socket, rx_pair;
-
- bool pairs_created = true;
- pairs_created &= CreateSocketPair(&event_socket, &event_pair);
- pairs_created &= CreateSocketPair(&tx_socket, &tx_pair);
- pairs_created &= CreateSocketPair(&rx_socket, &rx_pair);
- if (!pairs_created) {
- return nullptr;
- }
-
- SharedFD tx_shm_fd, rx_shm_fd;
- auto tx_shm =
- AllocateShm(tx_shm_len, "vios_audio_server_tx_queue", &tx_shm_fd);
- if (!tx_shm) {
- return nullptr;
- }
- auto rx_shm =
- AllocateShm(rx_shm_len, "vios_audio_server_rx_queue", &rx_shm_fd);
- if (!rx_shm) {
- return nullptr;
- }
-
- VioSConfig welcome_msg = {
- .version = VIOS_VERSION,
- .jacks = num_jacks,
- .streams = num_streams,
- .chmaps = num_chmaps,
- };
-
- auto sent = client_socket->SendFileDescriptors(
- &welcome_msg, sizeof(welcome_msg), event_pair, tx_pair, rx_pair,
- tx_shm_fd, rx_shm_fd);
- if (sent < 0) {
- LOG(ERROR) << "Failed to send file descriptors to client: "
- << client_socket->StrError();
- return nullptr;
- }
-
- return std::unique_ptr<AudioClientConnection>(new AudioClientConnection(
- std::move(tx_shm), std::move(rx_shm), client_socket,
- event_socket, tx_socket, rx_socket));
-}
-
-bool AudioClientConnection::ReceiveCommands(AudioServerExecutor& executor) {
- // The largest msg the client will send is 24 bytes long, using uint64_t
- // guarantees it's aligned to 64 bits.
- uint64_t recv_buffer[3];
- auto recv_size =
- ReceiveMsg(control_socket_, &recv_buffer, sizeof(recv_buffer));
- if (recv_size <= 0) {
- return false;
- }
- const auto cmd_hdr = reinterpret_cast<const virtio_snd_hdr*>(&recv_buffer[0]);
- if (recv_size < sizeof(virtio_snd_hdr)) {
- LOG(ERROR) << "Received control message is too small: " << recv_size;
- return false;
- }
- switch (static_cast<AudioCommandType>(cmd_hdr->code.as_uint32_t())) {
- case AudioCommandType::VIRTIO_SND_R_PCM_INFO: {
- if (recv_size < sizeof(virtio_snd_query_info)) {
- LOG(ERROR) << "Received QUERY_INFO message is too small: " << recv_size;
- return false;
- }
- auto query_info = reinterpret_cast<const virtio_snd_query_info*>(cmd_hdr);
- auto info_count = query_info->count.as_uint32_t();
- auto start_id = query_info->start_id.as_uint32_t();
- std::unique_ptr<virtio_snd_pcm_info[]> reply(
- new virtio_snd_pcm_info[info_count]);
- StreamInfoCommand cmd(start_id, info_count, reply.get());
-
- executor.StreamsInfo(cmd);
- return CmdReply(cmd.status(), reply.get(),
- info_count * sizeof(reply[0]));
- }
- case AudioCommandType::VIRTIO_SND_R_PCM_SET_PARAMS: {
- if (recv_size < sizeof(virtio_snd_pcm_set_params)) {
- LOG(ERROR) << "Received SET_PARAMS message is too small: " << recv_size;
- return false;
- }
- auto set_param_msg =
- reinterpret_cast<const virtio_snd_pcm_set_params*>(cmd_hdr);
- StreamSetParamsCommand cmd(set_param_msg->hdr.stream_id.as_uint32_t(),
- set_param_msg->buffer_bytes.as_uint32_t(),
- set_param_msg->period_bytes.as_uint32_t(),
- set_param_msg->features.as_uint32_t(),
- set_param_msg->channels, set_param_msg->format,
- set_param_msg->rate);
- executor.SetStreamParameters(cmd);
- return CmdReply(cmd.status());
- }
- case AudioCommandType::VIRTIO_SND_R_PCM_PREPARE: {
- if (recv_size < sizeof(virtio_snd_pcm_hdr)) {
- LOG(ERROR) << "Received PREPARE message is too small: " << recv_size;
- return false;
- }
- auto pcm_op_msg = reinterpret_cast<const virtio_snd_pcm_hdr*>(cmd_hdr);
- StreamControlCommand cmd(AudioCommandType::VIRTIO_SND_R_PCM_PREPARE,
- pcm_op_msg->stream_id.as_uint32_t());
- executor.PrepareStream(cmd);
- return CmdReply(cmd.status());
- }
- case AudioCommandType::VIRTIO_SND_R_PCM_RELEASE: {
- if (recv_size < sizeof(virtio_snd_pcm_hdr)) {
- LOG(ERROR) << "Received RELEASE message is too small: " << recv_size;
- return false;
- }
- auto pcm_op_msg = reinterpret_cast<const virtio_snd_pcm_hdr*>(cmd_hdr);
- StreamControlCommand cmd(AudioCommandType::VIRTIO_SND_R_PCM_RELEASE,
- pcm_op_msg->stream_id.as_uint32_t());
- executor.ReleaseStream(cmd);
- return CmdReply(cmd.status());
- }
- case AudioCommandType::VIRTIO_SND_R_PCM_START: {
- if (recv_size < sizeof(virtio_snd_pcm_hdr)) {
- LOG(ERROR) << "Received START message is too small: " << recv_size;
- return false;
- }
- auto pcm_op_msg = reinterpret_cast<const virtio_snd_pcm_hdr*>(cmd_hdr);
- StreamControlCommand cmd(AudioCommandType::VIRTIO_SND_R_PCM_START,
- pcm_op_msg->stream_id.as_uint32_t());
- executor.StartStream(cmd);
- return CmdReply(cmd.status());
- }
- case AudioCommandType::VIRTIO_SND_R_PCM_STOP: {
- if (recv_size < sizeof(virtio_snd_pcm_hdr)) {
- LOG(ERROR) << "Received STOP message is too small: " << recv_size;
- return false;
- }
- auto pcm_op_msg = reinterpret_cast<const virtio_snd_pcm_hdr*>(cmd_hdr);
- StreamControlCommand cmd(AudioCommandType::VIRTIO_SND_R_PCM_STOP,
- pcm_op_msg->stream_id.as_uint32_t());
- executor.StopStream(cmd);
- return CmdReply(cmd.status());
- }
- case AudioCommandType::VIRTIO_SND_R_CHMAP_INFO:
- case AudioCommandType::VIRTIO_SND_R_JACK_INFO:
- case AudioCommandType::VIRTIO_SND_R_JACK_REMAP:
- LOG(ERROR) << "Unsupported command type: " << cmd_hdr->code.as_uint32_t();
- return CmdReply(AudioStatus::VIRTIO_SND_S_NOT_SUPP);
- default:
- LOG(ERROR) << "Unknown command type: " << cmd_hdr->code.as_uint32_t();
- return CmdReply(AudioStatus::VIRTIO_SND_S_BAD_MSG);
- }
- return true;
-}
-
-bool AudioClientConnection::ReceivePlayback(AudioServerExecutor& executor) {
- // The largest msg the client will send is 12 bytes long, using uint32_t
- // guarantees it's aligned to 32 bits.
- uint32_t recv_buffer[3];
- auto recv_size = ReceiveMsg(tx_socket_, &recv_buffer, sizeof(recv_buffer));
- if (recv_size <= 0) {
- return false;
- }
- const auto msg_hdr = reinterpret_cast<const IoTransferMsg*>(&recv_buffer[0]);
-
- if (recv_size < sizeof(IoTransferMsg)) {
- LOG(ERROR) << "Received PCM_XFER message is too small: " << recv_size;
- return false;
- }
- TxBuffer buffer(msg_hdr->io_xfer,
- TxBufferAt(msg_hdr->buffer_offset, msg_hdr->buffer_len),
- msg_hdr->buffer_len,
- SendStatusCallback(msg_hdr->buffer_offset, tx_socket_));
- executor.OnPlaybackBuffer(std::move(buffer));
- return true;
-}
-
-bool AudioClientConnection::ReceiveCapture(AudioServerExecutor& executor) {
- uint32_t recv_buffer[3];
- auto recv_size = ReceiveMsg(rx_socket_, &recv_buffer, sizeof(recv_buffer));
- if (recv_size <= 0) {
- return false;
- }
- const auto msg_hdr = reinterpret_cast<const IoTransferMsg*>(&recv_buffer[0]);
- if (recv_size < sizeof(IoTransferMsg)) {
- LOG(ERROR) << "Received PCM_XFER message is too small: " << recv_size;
- return false;
- }
- RxBuffer buffer(msg_hdr->io_xfer,
- RxBufferAt(msg_hdr->buffer_offset, msg_hdr->buffer_len),
- msg_hdr->buffer_len,
- SendStatusCallback(msg_hdr->buffer_offset, rx_socket_));
- executor.OnCaptureBuffer(std::move(buffer));
- return true;
-}
-
-bool AudioClientConnection::CmdReply(AudioStatus status, const void* data,
- size_t size) {
- virtio_snd_hdr vio_status = {
- .code = Le32(static_cast<uint32_t>(status)),
- };
- auto status_sent = control_socket_->Send(&vio_status, sizeof(vio_status), 0);
- if (status_sent < sizeof(vio_status)) {
- LOG(ERROR) << "Failed to send entire command status: "
- << control_socket_->StrError();
- return false;
- }
- if (status != AudioStatus::VIRTIO_SND_S_OK || size == 0) {
- return true;
- }
- auto payload_sent = control_socket_->Send(data, size, 0);
- if (payload_sent < size) {
- LOG(ERROR) << "Failed to send entire command response payload: "
- << control_socket_->StrError();
- return false;
- }
- return true;
-}
-
-const volatile uint8_t* AudioClientConnection::TxBufferAt(size_t offset,
- size_t len) const {
- CHECK(offset < tx_shm_.len() && tx_shm_.len() - offset > len)
- << "Tx buffer bounds outside the buffer area: " << offset << " " << len;
- const void* ptr = tx_shm_.get();
- return &reinterpret_cast<const volatile uint8_t*>(ptr)[offset];
-}
-
-volatile uint8_t* AudioClientConnection::RxBufferAt(size_t offset,
- size_t len) {
- CHECK(offset < rx_shm_.len() && rx_shm_.len() - offset > len)
- << "Rx buffer bounds outside the buffer area: " << offset << " " << len;
- void* ptr = rx_shm_.get();
- return &reinterpret_cast<volatile uint8_t*>(ptr)[offset];
-}
-
-bool AudioClientConnection::SendEvent(/*TODO*/) { return false; }
-
-ssize_t AudioClientConnection::ReceiveMsg(SharedFD socket, void* buffer,
- size_t size) {
- auto read = socket->Recv(buffer, size, MSG_TRUNC);
- CHECK(read < 0 || read <= size)
- << "Received a msg bigger than the buffer, msg was truncated: " << read
- << " vs " << size;
- if (read == 0) {
- LOG(ERROR) << "Client closed the connection";
- }
- if (read < 0) {
- LOG(ERROR) << "Error receiving messages from client: "
- << socket->StrError();
- }
- return read;
-}
-
-} // namespace cuttlefish
diff --git a/host/libs/audio_connector/server.h b/host/libs/audio_connector/server.h
deleted file mode 100644
index 4ba2e7c16..000000000
--- a/host/libs/audio_connector/server.h
+++ /dev/null
@@ -1,113 +0,0 @@
-//
-// Copyright (C) 2020 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 <cinttypes>
-
-#include <functional>
-#include <memory>
-
-#include "common/libs/fs/shared_fd.h"
-#include "host/libs/audio_connector/buffers.h"
-#include "host/libs/audio_connector/commands.h"
-#include "host/libs/audio_connector/shm_layout.h"
-
-namespace cuttlefish {
-
-// Callbacks into objects implementing this interface will be made from the same
-// thread that handles the connection fd. Implementations should make every
-// effort to return immediately to avoid blocking the server's main loop.
-class AudioServerExecutor {
- public:
- virtual ~AudioServerExecutor() = default;
-
- // Implementations must ensure each command is replied to before returning
- // from these functions. Failure to do so causes the program to abort.
- virtual void StreamsInfo(StreamInfoCommand& cmd) = 0;
- virtual void SetStreamParameters(StreamSetParamsCommand& cmd) = 0;
- virtual void PrepareStream(StreamControlCommand& cmd) = 0;
- virtual void ReleaseStream(StreamControlCommand& cmd) = 0;
- virtual void StartStream(StreamControlCommand& cmd) = 0;
- virtual void StopStream(StreamControlCommand& cmd) = 0;
-
- // Implementations must call buffer.SendStatus() before destroying the buffer
- // to notify the other side of the release of the buffer. Failure to do so
- // will cause the program to abort.
- virtual void OnPlaybackBuffer(TxBuffer buffer) = 0;
- virtual void OnCaptureBuffer(RxBuffer buffer) = 0;
-};
-
-class AudioClientConnection {
- public:
- static std::unique_ptr<AudioClientConnection> Create(
- SharedFD client_socket, uint32_t num_streams, uint32_t num_jacks,
- uint32_t num_chmaps, size_t tx_shm_len, size_t rx_shm_len);
-
- AudioClientConnection() = delete;
- AudioClientConnection(const AudioClientConnection&) = delete;
-
- AudioClientConnection& operator=(const AudioClientConnection&) = delete;
-
- // Allows the caller to react to commands sent by the client.
- bool ReceiveCommands(AudioServerExecutor& executor);
- // Allows the caller to react to IO buffers sent by the client.
- bool ReceivePlayback(AudioServerExecutor& executor);
- bool ReceiveCapture(AudioServerExecutor& executor);
-
- bool SendEvent(/*TODO*/);
-
- private:
- AudioClientConnection(ScopedMMap tx_shm, ScopedMMap rx_shm,
- SharedFD control_socket, SharedFD event_socket,
- SharedFD tx_socket, SharedFD rx_socket)
- : tx_shm_(std::move(tx_shm)),
- rx_shm_(std::move(rx_shm)),
- control_socket_(control_socket),
- event_socket_(event_socket),
- tx_socket_(tx_socket),
- rx_socket_(rx_socket) {}
-
- bool CmdReply(AudioStatus status, const void* data = nullptr,
- size_t size = 0);
- bool WithCommand(const virtio_snd_hdr* msg, size_t msg_len,
- AudioServerExecutor& executor);
-
- ssize_t ReceiveMsg(SharedFD socket, void* buffer, size_t size);
- const volatile uint8_t* TxBufferAt(size_t offset, size_t len) const;
- volatile uint8_t* RxBufferAt(size_t offset, size_t len);
-
- const ScopedMMap tx_shm_;
- ScopedMMap rx_shm_;
- SharedFD control_socket_;
- SharedFD event_socket_;
- SharedFD tx_socket_;
- SharedFD rx_socket_;
-};
-
-class AudioServer {
- public:
- AudioServer(SharedFD server_socket) : server_socket_(server_socket) {}
-
- std::unique_ptr<AudioClientConnection> AcceptClient(uint32_t num_streams,
- uint32_t num_jacks,
- uint32_t num_chmaps,
- size_t tx_shm_len,
- size_t rx_shm_len);
-
- private:
- SharedFD server_socket_;
-};
-
-} // namespace cuttlefish
diff --git a/host/libs/audio_connector/shm_layout.h b/host/libs/audio_connector/shm_layout.h
deleted file mode 100644
index 9148cb80f..000000000
--- a/host/libs/audio_connector/shm_layout.h
+++ /dev/null
@@ -1,192 +0,0 @@
-//
-// Copyright (C) 2020 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 <atomic>
-#include <type_traits>
-
-#include "common/libs/utils/cf_endian.h"
-
-namespace cuttlefish {
-// TODO (b/175151042): get these from the kernel headers when available
-
-enum class AudioCommandType : uint32_t {
- /* jack control request types */
- VIRTIO_SND_R_JACK_INFO = 1,
- VIRTIO_SND_R_JACK_REMAP,
-
- /* PCM control request types */
- VIRTIO_SND_R_PCM_INFO = 0x0100,
- VIRTIO_SND_R_PCM_SET_PARAMS,
- VIRTIO_SND_R_PCM_PREPARE,
- VIRTIO_SND_R_PCM_RELEASE,
- VIRTIO_SND_R_PCM_START,
- VIRTIO_SND_R_PCM_STOP,
-
- /* channel map control request types */
- VIRTIO_SND_R_CHMAP_INFO = 0x0200,
-};
-
-enum class AudioStatus : uint32_t {
- /* common status codes */
- VIRTIO_SND_S_OK = 0x8000,
- VIRTIO_SND_S_BAD_MSG,
- VIRTIO_SND_S_NOT_SUPP,
- VIRTIO_SND_S_IO_ERR,
- // Not a virtio constant, but it's only used internally as an invalid value so
- // it's safe.
- NOT_SET = static_cast<uint32_t>(-1),
-};
-
-enum class AudioStreamDirection : uint32_t {
- VIRTIO_SND_D_OUTPUT = 0,
- VIRTIO_SND_D_INPUT
-};
-
-enum class AudioStreamFormat : uint8_t {
- /* analog formats (width / physical width) */
- VIRTIO_SND_PCM_FMT_IMA_ADPCM = 0, /* 4 / 4 bits */
- VIRTIO_SND_PCM_FMT_MU_LAW, /* 8 / 8 bits */
- VIRTIO_SND_PCM_FMT_A_LAW, /* 8 / 8 bits */
- VIRTIO_SND_PCM_FMT_S8, /* 8 / 8 bits */
- VIRTIO_SND_PCM_FMT_U8, /* 8 / 8 bits */
- VIRTIO_SND_PCM_FMT_S16, /* 16 / 16 bits */
- VIRTIO_SND_PCM_FMT_U16, /* 16 / 16 bits */
- VIRTIO_SND_PCM_FMT_S18_3, /* 18 / 24 bits */
- VIRTIO_SND_PCM_FMT_U18_3, /* 18 / 24 bits */
- VIRTIO_SND_PCM_FMT_S20_3, /* 20 / 24 bits */
- VIRTIO_SND_PCM_FMT_U20_3, /* 20 / 24 bits */
- VIRTIO_SND_PCM_FMT_S24_3, /* 24 / 24 bits */
- VIRTIO_SND_PCM_FMT_U24_3, /* 24 / 24 bits */
- VIRTIO_SND_PCM_FMT_S20, /* 20 / 32 bits */
- VIRTIO_SND_PCM_FMT_U20, /* 20 / 32 bits */
- VIRTIO_SND_PCM_FMT_S24, /* 24 / 32 bits */
- VIRTIO_SND_PCM_FMT_U24, /* 24 / 32 bits */
- VIRTIO_SND_PCM_FMT_S32, /* 32 / 32 bits */
- VIRTIO_SND_PCM_FMT_U32, /* 32 / 32 bits */
- VIRTIO_SND_PCM_FMT_FLOAT, /* 32 / 32 bits */
- VIRTIO_SND_PCM_FMT_FLOAT64, /* 64 / 64 bits */
- /* digital formats (width / physical width) */
- VIRTIO_SND_PCM_FMT_DSD_U8, /* 8 / 8 bits */
- VIRTIO_SND_PCM_FMT_DSD_U16, /* 16 / 16 bits */
- VIRTIO_SND_PCM_FMT_DSD_U32, /* 32 / 32 bits */
- VIRTIO_SND_PCM_FMT_IEC958_SUBFRAME /* 32 / 32 bits */
-};
-
-/* supported PCM frame rates */
-enum AudioStreamRate : uint8_t {
- VIRTIO_SND_PCM_RATE_5512 = 0,
- VIRTIO_SND_PCM_RATE_8000,
- VIRTIO_SND_PCM_RATE_11025,
- VIRTIO_SND_PCM_RATE_16000,
- VIRTIO_SND_PCM_RATE_22050,
- VIRTIO_SND_PCM_RATE_32000,
- VIRTIO_SND_PCM_RATE_44100,
- VIRTIO_SND_PCM_RATE_48000,
- VIRTIO_SND_PCM_RATE_64000,
- VIRTIO_SND_PCM_RATE_88200,
- VIRTIO_SND_PCM_RATE_96000,
- VIRTIO_SND_PCM_RATE_176400,
- VIRTIO_SND_PCM_RATE_192000,
- VIRTIO_SND_PCM_RATE_384000
-};
-
-struct virtio_snd_hdr {
- Le32 code;
-};
-
-struct virtio_snd_query_info {
- struct virtio_snd_hdr hdr;
- Le32 start_id;
- Le32 count;
- Le32 size; // unused
-};
-
-struct virtio_snd_info {
- Le32 hda_fn_nid;
-};
-
-struct virtio_snd_pcm_info {
- struct virtio_snd_info hdr;
- Le32 features; /* 1 << VIRTIO_SND_PCM_F_XXX */
- Le64 formats; /* 1 << VIRTIO_SND_PCM_FMT_XXX */
- Le64 rates; /* 1 << VIRTIO_SND_PCM_RATE_XXX */
- uint8_t direction;
- uint8_t channels_min;
- uint8_t channels_max;
-
- uint8_t padding[5];
-};
-
-struct virtio_snd_pcm_hdr {
- struct virtio_snd_hdr hdr;
- Le32 stream_id;
-};
-
-struct virtio_snd_pcm_set_params {
- struct virtio_snd_pcm_hdr hdr;
- Le32 buffer_bytes;
- Le32 period_bytes;
- Le32 features; /* 1 << VIRTIO_SND_PCM_F_XXX */
- uint8_t channels;
- uint8_t format;
- uint8_t rate;
- uint8_t padding;
-};
-
-struct virtio_snd_pcm_xfer {
- Le32 stream_id;
-};
-
-struct virtio_snd_pcm_status {
- Le32 status;
- Le32 latency_bytes;
-};
-
-// Update this value when the msg layouts change
-const uint32_t VIOS_VERSION = 1;
-
-struct VioSConfig {
- uint32_t version;
- uint32_t jacks;
- uint32_t streams;
- uint32_t chmaps;
-};
-
-struct IoTransferMsg {
- virtio_snd_pcm_xfer io_xfer;
- uint32_t buffer_offset;
- uint32_t buffer_len;
-};
-
-struct IoStatusMsg {
- virtio_snd_pcm_status status;
- uint32_t buffer_offset;
- uint32_t consumed_length;
-};
-
-// Ensure all message structs have predictable sizes
-#define ASSERT_VALID_MSG_TYPE(T, size) \
- static_assert(sizeof(T) == (size), #T " has the wrong size")
-ASSERT_VALID_MSG_TYPE(virtio_snd_query_info, 16);
-ASSERT_VALID_MSG_TYPE(virtio_snd_pcm_info, 32);
-ASSERT_VALID_MSG_TYPE(virtio_snd_pcm_set_params, 24);
-ASSERT_VALID_MSG_TYPE(virtio_snd_pcm_hdr, 8);
-ASSERT_VALID_MSG_TYPE(IoTransferMsg, 12);
-ASSERT_VALID_MSG_TYPE(IoStatusMsg, 16);
-#undef ASSERT_VALID_MSG_TYPE
-
-} // namespace cuttlefish \ No newline at end of file
diff --git a/host/libs/config/Android.bp b/host/libs/config/Android.bp
index 3697f4e34..e6e91b7ec 100644
--- a/host/libs/config/Android.bp
+++ b/host/libs/config/Android.bp
@@ -13,22 +13,11 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-cc_library_static {
+cc_library_host_static {
name: "libcuttlefish_host_config",
srcs: [
- "bootconfig_args.cpp",
- "custom_actions.cpp",
"cuttlefish_config.cpp",
- "cuttlefish_config_instance.cpp",
- "data_image.cpp",
"fetcher_config.cpp",
- "host_tools_version.cpp",
- "kernel_args.cpp",
- "known_paths.cpp",
"logging.cpp",
],
shared_libs: [
@@ -36,8 +25,10 @@ cc_library_static {
"libcuttlefish_utils",
"libbase",
"libgflags",
+ ],
+ static_libs: [
+ "libxml2",
"libjsoncpp",
- "libz",
],
- defaults: ["cuttlefish_host"],
+ defaults: ["cuttlefish_host_only"],
}
diff --git a/host/libs/config/bootconfig_args.cpp b/host/libs/config/bootconfig_args.cpp
deleted file mode 100644
index c2bc1ebf1..000000000
--- a/host/libs/config/bootconfig_args.cpp
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * Copyright (C) 2021 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 "host/libs/config/bootconfig_args.h"
-
-#include <array>
-#include <sstream>
-#include <string>
-#include <vector>
-
-#include "common/libs/utils/environment.h"
-#include "common/libs/utils/files.h"
-#include "host/libs/config/cuttlefish_config.h"
-#include "host/libs/vm_manager/crosvm_manager.h"
-#include "host/libs/vm_manager/qemu_manager.h"
-#include "host/libs/vm_manager/vm_manager.h"
-
-namespace cuttlefish {
-
-using vm_manager::CrosvmManager;
-using vm_manager::QemuManager;
-
-namespace {
-
-template <typename T>
-void AppendVector(std::vector<T>* destination, const std::vector<T>& source) {
- destination->insert(destination->end(), source.begin(), source.end());
-}
-
-template <typename S, typename T>
-std::string concat(const S& s, const T& t) {
- std::ostringstream os;
- os << s << t;
- return os.str();
-}
-
-std::string mac_to_str(const std::array<unsigned char, 6>& mac) {
- std::ostringstream stream;
- stream << std::hex << (int)mac[0];
- for (int i = 1; i < 6; i++) {
- stream << ":" << std::hex << (int)mac[i];
- }
- return stream.str();
-}
-
-// TODO(schuffelen): Move more of this into host/libs/vm_manager, as a
-// substitute for the vm_manager comparisons.
-std::vector<std::string> VmManagerBootconfig(const CuttlefishConfig& config) {
- std::vector<std::string> vm_manager_cmdline;
- if (config.console()) {
- vm_manager_cmdline.push_back("androidboot.console=" + config.console_dev());
- } else {
- // Specify an invalid path under /dev, so the init process will disable the
- // console service due to the console not being found. On physical devices,
- // it is enough to not specify androidboot.console= *and* not specify the
- // console= kernel command line parameter, because the console and kernel
- // dmesg are muxed. However, on cuttlefish, we don't need to mux, and would
- // prefer to retain the kernel dmesg logging, so we must work around init
- // falling back to the check for /dev/console (which we'll always have).
- vm_manager_cmdline.push_back("androidboot.console=invalid");
- }
- return vm_manager_cmdline;
-}
-
-} // namespace
-
-std::vector<std::string> BootconfigArgsFromConfig(
- const CuttlefishConfig& config,
- const CuttlefishConfig::InstanceSpecific& instance) {
- std::vector<std::string> bootconfig_args;
-
- AppendVector(&bootconfig_args, VmManagerBootconfig(config));
- auto vmm = vm_manager::GetVmManager(config.vm_manager(), config.target_arch());
- bootconfig_args.push_back(
- vmm->ConfigureBootDevices(instance.virtual_disk_paths().size()));
- AppendVector(&bootconfig_args, vmm->ConfigureGpuMode(config.gpu_mode()));
-
- bootconfig_args.push_back(
- concat("androidboot.serialno=", instance.serial_number()));
- bootconfig_args.push_back(concat("androidboot.lcd_density=", config.dpi()));
- bootconfig_args.push_back(
- concat("androidboot.setupwizard_mode=", config.setupwizard_mode()));
- if (!config.guest_enforce_security()) {
- bootconfig_args.push_back("androidboot.selinux=permissive");
- }
-
- if (instance.tombstone_receiver_port()) {
- bootconfig_args.push_back(concat("androidboot.vsock_tombstone_port=",
- instance.tombstone_receiver_port()));
- }
-
- if (instance.config_server_port()) {
- bootconfig_args.push_back(
- concat("androidboot.cuttlefish_config_server_port=",
- instance.config_server_port()));
- }
-
- if (instance.keyboard_server_port()) {
- bootconfig_args.push_back(concat("androidboot.vsock_keyboard_port=",
- instance.keyboard_server_port()));
- }
-
- if (instance.touch_server_port()) {
- bootconfig_args.push_back(
- concat("androidboot.vsock_touch_port=", instance.touch_server_port()));
- }
-
- if (config.enable_vehicle_hal_grpc_server() &&
- instance.vehicle_hal_server_port() &&
- FileExists(config.vehicle_hal_grpc_server_binary())) {
- constexpr int vehicle_hal_server_cid = 2;
- bootconfig_args.push_back(concat(
- "androidboot.vendor.vehiclehal.server.cid=", vehicle_hal_server_cid));
- bootconfig_args.push_back(
- concat("androidboot.vendor.vehiclehal.server.port=",
- instance.vehicle_hal_server_port()));
- }
-
- if (instance.audiocontrol_server_port()) {
- bootconfig_args.push_back(
- concat("androidboot.vendor.audiocontrol.server.cid=",
- instance.vsock_guest_cid()));
- bootconfig_args.push_back(
- concat("androidboot.vendor.audiocontrol.server.port=",
- instance.audiocontrol_server_port()));
- }
-
- if (instance.frames_server_port()) {
- bootconfig_args.push_back(concat("androidboot.vsock_frames_port=",
- instance.frames_server_port()));
- }
-
- if (config.enable_modem_simulator() &&
- instance.modem_simulator_ports() != "") {
- bootconfig_args.push_back(concat("androidboot.modem_simulator_ports=",
- instance.modem_simulator_ports()));
- }
-
- // TODO(b/158131610): Set this in crosvm instead
- bootconfig_args.push_back(concat("androidboot.wifi_mac_address=",
- mac_to_str(instance.wifi_mac_address())));
-
- bootconfig_args.push_back("androidboot.verifiedbootstate=orange");
-
- // Non-native architecture implies a significantly slower execution speed, so
- // set a large timeout multiplier.
- if (!IsHostCompatible(config.target_arch())) {
- bootconfig_args.push_back("androidboot.hw_timeout_multiplier=50");
- }
-
- // TODO(b/173815685): Create an extra_bootconfig flag and add it to bootconfig
-
- return bootconfig_args;
-}
-
-} // namespace cuttlefish
diff --git a/host/libs/config/custom_actions.cpp b/host/libs/config/custom_actions.cpp
deleted file mode 100644
index 1cc2e066e..000000000
--- a/host/libs/config/custom_actions.cpp
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Copyright (C) 2020 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 "host/libs/config/custom_actions.h"
-
-#include <android-base/logging.h>
-#include <json/json.h>
-
-#include <optional>
-#include <string>
-#include <vector>
-
-#include "host/libs/config/cuttlefish_config.h"
-
-namespace cuttlefish {
-namespace {
-
-const char* kCustomActionShellCommand = "shell_command";
-const char* kCustomActionServer = "server";
-const char* kCustomActionDeviceStates = "device_states";
-const char* kCustomActionDeviceStateLidSwitchOpen = "lid_switch_open";
-const char* kCustomActionDeviceStateHingeAngleValue = "hinge_angle_value";
-const char* kCustomActionButton = "button";
-const char* kCustomActionButtons = "buttons";
-const char* kCustomActionButtonCommand = "command";
-const char* kCustomActionButtonTitle = "title";
-const char* kCustomActionButtonIconName = "icon_name";
-
-} //namespace
-
-
-CustomActionConfig::CustomActionConfig(const Json::Value& dictionary) {
- if (dictionary.isMember(kCustomActionShellCommand) +
- dictionary.isMember(kCustomActionServer) +
- dictionary.isMember(kCustomActionDeviceStates) !=
- 1) {
- LOG(FATAL) << "Custom action must contain exactly one of shell_command, "
- << "server, or device_states";
- return;
- }
- if (dictionary.isMember(kCustomActionShellCommand)) {
- // Shell command with one button.
- Json::Value button_entry = dictionary[kCustomActionButton];
- buttons = {{button_entry[kCustomActionButtonCommand].asString(),
- button_entry[kCustomActionButtonTitle].asString(),
- button_entry[kCustomActionButtonIconName].asString()}};
- shell_command = dictionary[kCustomActionShellCommand].asString();
- } else if (dictionary.isMember(kCustomActionServer)) {
- // Action server with possibly multiple buttons.
- for (const Json::Value& button_entry : dictionary[kCustomActionButtons]) {
- ControlPanelButton button = {
- button_entry[kCustomActionButtonCommand].asString(),
- button_entry[kCustomActionButtonTitle].asString(),
- button_entry[kCustomActionButtonIconName].asString()};
- buttons.push_back(button);
- }
- server = dictionary[kCustomActionServer].asString();
- } else if (dictionary.isMember(kCustomActionDeviceStates)) {
- // Device state(s) with one button.
- // Each button press cycles to the next state, then repeats to the first.
- Json::Value button_entry = dictionary[kCustomActionButton];
- buttons = {{button_entry[kCustomActionButtonCommand].asString(),
- button_entry[kCustomActionButtonTitle].asString(),
- button_entry[kCustomActionButtonIconName].asString()}};
- for (const Json::Value& device_state_entry :
- dictionary[kCustomActionDeviceStates]) {
- DeviceState state;
- if (device_state_entry.isMember(kCustomActionDeviceStateLidSwitchOpen)) {
- state.lid_switch_open =
- device_state_entry[kCustomActionDeviceStateLidSwitchOpen].asBool();
- }
- if (device_state_entry.isMember(
- kCustomActionDeviceStateHingeAngleValue)) {
- state.hinge_angle_value =
- device_state_entry[kCustomActionDeviceStateHingeAngleValue].asInt();
- }
- device_states.push_back(state);
- }
- } else {
- LOG(FATAL) << "Unknown custom action type.";
- }
-}
-
-Json::Value CustomActionConfig::ToJson() const {
- Json::Value custom_action;
- if (shell_command) {
- // Shell command with one button.
- custom_action[kCustomActionShellCommand] = *shell_command;
- custom_action[kCustomActionButton] = Json::Value();
- custom_action[kCustomActionButton][kCustomActionButtonCommand] =
- buttons[0].command;
- custom_action[kCustomActionButton][kCustomActionButtonTitle] =
- buttons[0].title;
- custom_action[kCustomActionButton][kCustomActionButtonIconName] =
- buttons[0].icon_name;
- } else if (server) {
- // Action server with possibly multiple buttons.
- custom_action[kCustomActionServer] = *server;
- custom_action[kCustomActionButtons] = Json::Value(Json::arrayValue);
- for (const auto& button : buttons) {
- Json::Value button_entry;
- button_entry[kCustomActionButtonCommand] = button.command;
- button_entry[kCustomActionButtonTitle] = button.title;
- button_entry[kCustomActionButtonIconName] = button.icon_name;
- custom_action[kCustomActionButtons].append(button_entry);
- }
- } else if (!device_states.empty()) {
- // Device state(s) with one button.
- custom_action[kCustomActionDeviceStates] = Json::Value(Json::arrayValue);
- for (const auto& device_state : device_states) {
- Json::Value device_state_entry;
- if (device_state.lid_switch_open) {
- device_state_entry[kCustomActionDeviceStateLidSwitchOpen] =
- *device_state.lid_switch_open;
- }
- if (device_state.hinge_angle_value) {
- device_state_entry[kCustomActionDeviceStateHingeAngleValue] =
- *device_state.hinge_angle_value;
- }
- custom_action[kCustomActionDeviceStates].append(device_state_entry);
- }
- custom_action[kCustomActionButton] = Json::Value();
- custom_action[kCustomActionButton][kCustomActionButtonCommand] =
- buttons[0].command;
- custom_action[kCustomActionButton][kCustomActionButtonTitle] =
- buttons[0].title;
- custom_action[kCustomActionButton][kCustomActionButtonIconName] =
- buttons[0].icon_name;
- } else {
- LOG(FATAL) << "Unknown custom action type.";
- }
- return custom_action;
-}
-
-} // namespace cuttlefish
diff --git a/host/libs/config/custom_actions.h b/host/libs/config/custom_actions.h
deleted file mode 100644
index 627940154..000000000
--- a/host/libs/config/custom_actions.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2020 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 <json/json.h>
-
-#include <optional>
-#include <string>
-#include <vector>
-
-namespace cuttlefish {
-
-struct ControlPanelButton {
- std::string command;
- std::string title;
- std::string icon_name;
-};
-
-struct DeviceState {
- std::optional<bool> lid_switch_open;
- std::optional<int> hinge_angle_value;
-};
-
-struct CustomActionConfig {
- CustomActionConfig(const Json::Value&);
- Json::Value ToJson() const;
-
- std::vector<ControlPanelButton> buttons;
- std::optional<std::string> shell_command;
- std::optional<std::string> server;
- std::vector<DeviceState> device_states;
-};
-
-} // namespace cuttlefish
diff --git a/host/libs/config/cuttlefish_config.cpp b/host/libs/config/cuttlefish_config.cpp
index c04faaebf..6beacc349 100644
--- a/host/libs/config/cuttlefish_config.cpp
+++ b/host/libs/config/cuttlefish_config.cpp
@@ -18,7 +18,6 @@
#include <algorithm>
#include <climits>
-#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <fstream>
@@ -34,10 +33,9 @@
#include "common/libs/utils/environment.h"
#include "common/libs/utils/files.h"
-#include "host/libs/vm_manager/crosvm_manager.h"
#include "host/libs/vm_manager/qemu_manager.h"
-namespace cuttlefish {
+
namespace {
int InstanceFromEnvironment() {
@@ -45,38 +43,130 @@ int InstanceFromEnvironment() {
static constexpr int kDefaultInstance = 1;
// CUTTLEFISH_INSTANCE environment variable
- std::string instance_str = StringFromEnv(kInstanceEnvironmentVariable, "");
- if (instance_str.empty()) {
+ const char* instance_str = std::getenv(kInstanceEnvironmentVariable);
+ if (!instance_str) {
// Try to get it from the user instead
- instance_str = StringFromEnv("USER", "");
+ instance_str = std::getenv("USER");
- if (instance_str.empty()) {
- LOG(DEBUG) << "CUTTLEFISH_INSTANCE and USER unset, using instance id "
- << kDefaultInstance;
- return kDefaultInstance;
- }
- if (!android::base::StartsWith(instance_str, kVsocUserPrefix)) {
+ if (!instance_str || std::strncmp(instance_str, vsoc::kVsocUserPrefix,
+ sizeof(vsoc::kVsocUserPrefix) - 1)) {
// No user or we don't recognize this user
- LOG(DEBUG) << "Non-vsoc user, using instance id " << kDefaultInstance;
+ LOG(WARNING) << "No user or non-vsoc user, returning default config";
return kDefaultInstance;
}
- instance_str = instance_str.substr(std::string(kVsocUserPrefix).size());
+ instance_str += sizeof(vsoc::kVsocUserPrefix) - 1;
+
+ // Set the environment variable so that child processes see it
+ setenv(kInstanceEnvironmentVariable, instance_str, 0);
}
- int instance = std::stoi(instance_str);
+
+ int instance = std::atoi(instance_str);
if (instance <= 0) {
- LOG(INFO) << "Failed to interpret \"" << instance_str << "\" as an id, "
- << "using instance id " << kDefaultInstance;
- return kDefaultInstance;
+ instance = kDefaultInstance;
}
+
return instance;
}
const char* kInstances = "instances";
+const char* kAssemblyDir = "assembly_dir";
+const char* kSerialNumber = "serial_number";
+const char* kInstanceDir = "instance_dir";
+const char* kVmManager = "vm_manager";
+const char* const kGpuMode = "gpu_mode";
+const char* const kWaylandSocket = "wayland_socket";
+const char* const kXDisplay = "x_display";
+const char* kDeviceTitle = "device_title";
+
+const char* kCpus = "cpus";
+const char* kMemoryMb = "memory_mb";
+const char* kDpi = "dpi";
+const char* kXRes = "x_res";
+const char* kYRes = "y_res";
+const char* kRefreshRateHz = "refresh_rate_hz";
+
+const char* kKernelImagePath = "kernel_image_path";
+const char* kUseUnpackedKernel = "use_unpacked_kernel";
+const char* kDecompressedKernelImagePath = "decompressed_kernel_image_path";
+const char* kDecompressKernel = "decompress_kernel";
+const char* kGdbFlag = "gdb_flag";
+const char* kRamdiskImagePath = "ramdisk_image_path";
+const char* kInitramfsPath = "initramfs_path";
+const char* kFinalRamdiskPath = "final_ramdisk_path";
+const char* kVendorRamdiskImagePath = "vendor_ramdisk_image_path";
+
+const char* kVirtualDiskPaths = "virtual_disk_paths";
+const char* kDeprecatedBootCompleted = "deprecated_boot_completed";
+
+const char* kMobileBridgeName = "mobile_bridge_name";
+const char* kMobileTapName = "mobile_tap_name";
+const char* kWifiTapName = "wifi_tap_name";
+const char* kVsockGuestCid = "vsock_guest_cid";
+
+const char* kUuid = "uuid";
+const char* kCuttlefishEnvPath = "cuttlefish_env_path";
+
+const char* kAdbMode = "adb_mode";
+const char* kHostPort = "host_port";
+const char* kAdbIPAndPort = "adb_ip_and_port";
+const char* kSetupWizardMode = "setupwizard_mode";
+
+const char* kQemuBinary = "qemu_binary";
+const char* kCrosvmBinary = "crosvm_binary";
+const char* kConsoleForwarderBinary = "console_forwarder_binary";
+const char* kKernelLogMonitorBinary = "kernel_log_monitor_binary";
+
+const char* kEnableVncServer = "enable_vnc_server";
+const char* kVncServerBinary = "vnc_server_binary";
+const char* kVncServerPort = "vnc_server_port";
+
+const char* kEnableWebRTC = "enable_webrtc";
+const char* kWebRTCBinary = "webrtc_binary";
+const char* kWebRTCAssetsDir = "webrtc_assets_dir";
+const char* kWebRTCPublicIP = "webrtc_public_ip";
+const char* kWebRTCEnableADBWebSocket = "webrtc_enable_adb_websocket";
+
+const char* kEnableVehicleHalServer = "enable_vehicle_hal_server";
+const char* kVehicleHalServerBinary = "vehicle_hal_server_binary";
+const char* kVehicleHalServerPort = "vehicle_hal_server_port";
+
+const char* kRestartSubprocesses = "restart_subprocesses";
+const char* kRunAdbConnector = "run_adb_connector";
+const char* kAdbConnectorBinary = "adb_connector_binary";
+const char* kSocketVsockProxyBinary = "socket_vsock_proxy_binary";
+
+const char* kRunAsDaemon = "run_as_daemon";
+
+const char* kDataPolicy = "data_policy";
+const char* kBlankDataImageMb = "blank_data_image_mb";
+const char* kBlankDataImageFmt = "blank_data_image_fmt";
+
+const char* kLogcatMode = "logcat_mode";
+const char* kLogcatReceiverBinary = "logcat_receiver_binary";
+const char* kConfigServerBinary = "config_server_binary";
+
+const char* kRunTombstoneReceiver = "enable_tombstone_logger";
+const char* kTombstoneReceiverBinary = "tombstone_receiver_binary";
+
+const char* kWebRTCCertsDir = "webrtc_certs_dir";
+
+const char* kBootloader = "bootloader";
+const char* kUseBootloader = "use_bootloader";
+
+const char* kBootSlot = "boot_slot";
+
+const char* kLoopMaxPart = "loop_max_part";
+const char* kGuestEnforceSecurity = "guest_enforce_security";
+const char* kGuestAuditSecurity = "guest_audit_security";
+const char* kGuestForceNormalBoot = "guest_force_normal_boot";
+const char* kBootImageKernelCmdline = "boot_image_kernel_cmdline";
+const char* kExtraKernelCmdline = "extra_kernel_cmdline";
-
+const char* kWifiMacAddress = "wifi_mac_address";
} // namespace
-const char* const kGpuModeAuto = "auto";
+namespace vsoc {
+
const char* const kGpuModeGuestSwiftshader = "guest_swiftshader";
const char* const kGpuModeDrmVirgl = "drm_virgl";
const char* const kGpuModeGfxStream = "gfxstream";
@@ -84,10 +174,17 @@ const char* const kGpuModeGfxStream = "gfxstream";
std::string DefaultEnvironmentPath(const char* environment_key,
const char* default_value,
const char* subpath) {
- return StringFromEnv(environment_key, default_value) + "/" + subpath;
+ return cvd::StringFromEnv(environment_key, default_value) + "/" + subpath;
+}
+
+Json::Value* CuttlefishConfig::MutableInstanceSpecific::Dictionary() {
+ return &(*config_->dictionary_)[kInstances][id_];
+}
+
+const Json::Value* CuttlefishConfig::InstanceSpecific::Dictionary() const {
+ return &(*config_->dictionary_)[kInstances][id_];
}
-static constexpr char kAssemblyDir[] = "assembly_dir";
std::string CuttlefishConfig::assembly_dir() const {
return (*dictionary_)[kAssemblyDir].asString();
}
@@ -95,7 +192,18 @@ void CuttlefishConfig::set_assembly_dir(const std::string& assembly_dir) {
(*dictionary_)[kAssemblyDir] = assembly_dir;
}
-static constexpr char kVmManager[] = "vm_manager";
+std::string CuttlefishConfig::InstanceSpecific::instance_dir() const {
+ return (*Dictionary())[kInstanceDir].asString();
+}
+void CuttlefishConfig::MutableInstanceSpecific::set_instance_dir(
+ const std::string& instance_dir) {
+ (*Dictionary())[kInstanceDir] = instance_dir;
+}
+
+std::string CuttlefishConfig::InstanceSpecific::instance_internal_dir() const {
+ return PerInstancePath(kInternalDirName);
+}
+
std::string CuttlefishConfig::vm_manager() const {
return (*dictionary_)[kVmManager].asString();
}
@@ -103,7 +211,6 @@ void CuttlefishConfig::set_vm_manager(const std::string& name) {
(*dictionary_)[kVmManager] = name;
}
-static constexpr char kGpuMode[] = "gpu_mode";
std::string CuttlefishConfig::gpu_mode() const {
return (*dictionary_)[kGpuMode].asString();
}
@@ -111,11 +218,32 @@ void CuttlefishConfig::set_gpu_mode(const std::string& name) {
(*dictionary_)[kGpuMode] = name;
}
-static constexpr char kCpus[] = "cpus";
+std::string CuttlefishConfig::wayland_socket() const {
+ // Don't use SetPath here: the path is already fully formed.
+ return (*dictionary_)[kWaylandSocket].asString();
+}
+void CuttlefishConfig::set_wayland_socket(const std::string& path) {
+ (*dictionary_)[kWaylandSocket] = path;
+}
+
+std::string CuttlefishConfig::x_display() const {
+ return (*dictionary_)[kXDisplay].asString();
+}
+void CuttlefishConfig::set_x_display(const std::string& address) {
+ (*dictionary_)[kXDisplay] = address;
+}
+
+std::string CuttlefishConfig::InstanceSpecific::serial_number() const {
+ return (*Dictionary())[kSerialNumber].asString();
+}
+void CuttlefishConfig::MutableInstanceSpecific::set_serial_number(
+ const std::string& serial_number) {
+ (*Dictionary())[kSerialNumber] = serial_number;
+}
+
int CuttlefishConfig::cpus() const { return (*dictionary_)[kCpus].asInt(); }
void CuttlefishConfig::set_cpus(int cpus) { (*dictionary_)[kCpus] = cpus; }
-static constexpr char kMemoryMb[] = "memory_mb";
int CuttlefishConfig::memory_mb() const {
return (*dictionary_)[kMemoryMb].asInt();
}
@@ -123,39 +251,15 @@ void CuttlefishConfig::set_memory_mb(int memory_mb) {
(*dictionary_)[kMemoryMb] = memory_mb;
}
-static constexpr char kDpi[] = "dpi";
int CuttlefishConfig::dpi() const { return (*dictionary_)[kDpi].asInt(); }
void CuttlefishConfig::set_dpi(int dpi) { (*dictionary_)[kDpi] = dpi; }
-static constexpr char kDisplayConfigs[] = "display_configs";
-static constexpr char kXRes[] = "x_res";
-static constexpr char kYRes[] = "y_res";
-std::vector<CuttlefishConfig::DisplayConfig>
-CuttlefishConfig::display_configs() const {
- std::vector<DisplayConfig> display_configs;
- for (auto& display_config_json : (*dictionary_)[kDisplayConfigs]) {
- DisplayConfig display_config = {};
- display_config.width = display_config_json[kXRes].asInt();
- display_config.height = display_config_json[kYRes].asInt();
- display_configs.emplace_back(std::move(display_config));
- }
- return display_configs;
-}
-void CuttlefishConfig::set_display_configs(
- const std::vector<DisplayConfig>& display_configs) {
- Json::Value display_configs_json(Json::arrayValue);
+int CuttlefishConfig::x_res() const { return (*dictionary_)[kXRes].asInt(); }
+void CuttlefishConfig::set_x_res(int x_res) { (*dictionary_)[kXRes] = x_res; }
- for (const DisplayConfig& display_configs : display_configs) {
- Json::Value display_config_json(Json::objectValue);
- display_config_json[kXRes] = display_configs.width;
- display_config_json[kYRes] = display_configs.height;
- display_configs_json.append(display_config_json);
- }
-
- (*dictionary_)[kDisplayConfigs] = display_configs_json;
-}
+int CuttlefishConfig::y_res() const { return (*dictionary_)[kYRes].asInt(); }
+void CuttlefishConfig::set_y_res(int y_res) { (*dictionary_)[kYRes] = y_res; }
-static constexpr char kRefreshRateHz[] = "refresh_rate_hz";
int CuttlefishConfig::refresh_rate_hz() const {
return (*dictionary_)[kRefreshRateHz].asInt();
}
@@ -163,22 +267,109 @@ void CuttlefishConfig::set_refresh_rate_hz(int refresh_rate_hz) {
(*dictionary_)[kRefreshRateHz] = refresh_rate_hz;
}
+std::string CuttlefishConfig::kernel_image_path() const {
+ return (*dictionary_)[kKernelImagePath].asString();
+}
+
void CuttlefishConfig::SetPath(const std::string& key,
const std::string& path) {
if (!path.empty()) {
- (*dictionary_)[key] = AbsolutePath(path);
+ (*dictionary_)[key] = cvd::AbsolutePath(path);
}
}
-static constexpr char kGdbPort[] = "gdb_port";
-int CuttlefishConfig::gdb_port() const {
- return (*dictionary_)[kGdbPort].asInt();
+void CuttlefishConfig::set_kernel_image_path(
+ const std::string& kernel_image_path) {
+ SetPath(kKernelImagePath, kernel_image_path);
}
-void CuttlefishConfig::set_gdb_port(int port) {
- (*dictionary_)[kGdbPort] = port;
+
+bool CuttlefishConfig::use_unpacked_kernel() const {
+ return (*dictionary_)[kUseUnpackedKernel].asBool();
+}
+
+void CuttlefishConfig::set_use_unpacked_kernel(bool use_unpacked_kernel) {
+ (*dictionary_)[kUseUnpackedKernel] = use_unpacked_kernel;
+}
+
+bool CuttlefishConfig::decompress_kernel() const {
+ return (*dictionary_)[kDecompressKernel].asBool();
+}
+void CuttlefishConfig::set_decompress_kernel(bool decompress_kernel) {
+ (*dictionary_)[kDecompressKernel] = decompress_kernel;
+}
+
+std::string CuttlefishConfig::decompressed_kernel_image_path() const {
+ return (*dictionary_)[kDecompressedKernelImagePath].asString();
+}
+void CuttlefishConfig::set_decompressed_kernel_image_path(
+ const std::string& path) {
+ SetPath(kDecompressedKernelImagePath, path);
+}
+
+std::string CuttlefishConfig::gdb_flag() const {
+ return (*dictionary_)[kGdbFlag].asString();
+}
+
+void CuttlefishConfig::set_gdb_flag(const std::string& device) {
+ (*dictionary_)[kGdbFlag] = device;
+}
+
+std::string CuttlefishConfig::ramdisk_image_path() const {
+ return (*dictionary_)[kRamdiskImagePath].asString();
+}
+void CuttlefishConfig::set_ramdisk_image_path(
+ const std::string& ramdisk_image_path) {
+ SetPath(kRamdiskImagePath, ramdisk_image_path);
+}
+
+std::string CuttlefishConfig::initramfs_path() const {
+ return (*dictionary_)[kInitramfsPath].asString();
+}
+void CuttlefishConfig::set_initramfs_path(const std::string& initramfs_path) {
+ SetPath(kInitramfsPath, initramfs_path);
+}
+
+std::string CuttlefishConfig::final_ramdisk_path() const {
+ return (*dictionary_)[kFinalRamdiskPath].asString();
+}
+void CuttlefishConfig::set_final_ramdisk_path(
+ const std::string& final_ramdisk_path) {
+ SetPath(kFinalRamdiskPath, final_ramdisk_path);
+}
+
+std::string CuttlefishConfig::vendor_ramdisk_image_path() const {
+ return (*dictionary_)[kVendorRamdiskImagePath].asString();
+}
+void CuttlefishConfig::set_vendor_ramdisk_image_path(
+ const std::string& vendor_ramdisk_image_path) {
+ SetPath(kVendorRamdiskImagePath, vendor_ramdisk_image_path);
+}
+
+std::vector<std::string> CuttlefishConfig::InstanceSpecific::virtual_disk_paths() const {
+ std::vector<std::string> virtual_disks;
+ auto virtual_disks_json_obj = (*Dictionary())[kVirtualDiskPaths];
+ for (const auto& disk : virtual_disks_json_obj) {
+ virtual_disks.push_back(disk.asString());
+ }
+ return virtual_disks;
+}
+void CuttlefishConfig::MutableInstanceSpecific::set_virtual_disk_paths(
+ const std::vector<std::string>& virtual_disk_paths) {
+ Json::Value virtual_disks_json_obj(Json::arrayValue);
+ for (const auto& arg : virtual_disk_paths) {
+ virtual_disks_json_obj.append(arg);
+ }
+ (*Dictionary())[kVirtualDiskPaths] = virtual_disks_json_obj;
+}
+
+std::string CuttlefishConfig::InstanceSpecific::kernel_log_pipe_name() const {
+ return cvd::AbsolutePath(PerInstanceInternalPath("kernel-log-pipe"));
+}
+
+std::string CuttlefishConfig::InstanceSpecific::console_pipe_name() const {
+ return cvd::AbsolutePath(PerInstanceInternalPath("console-pipe"));
}
-static constexpr char kDeprecatedBootCompleted[] = "deprecated_boot_completed";
bool CuttlefishConfig::deprecated_boot_completed() const {
return (*dictionary_)[kDeprecatedBootCompleted].asBool();
}
@@ -187,7 +378,71 @@ void CuttlefishConfig::set_deprecated_boot_completed(
(*dictionary_)[kDeprecatedBootCompleted] = deprecated_boot_completed;
}
-static constexpr char kCuttlefishEnvPath[] = "cuttlefish_env_path";
+std::string CuttlefishConfig::InstanceSpecific::access_kregistry_path() const {
+ return cvd::AbsolutePath(PerInstancePath("access-kregistry"));
+}
+
+std::string CuttlefishConfig::InstanceSpecific::console_path() const {
+ return cvd::AbsolutePath(PerInstancePath("console"));
+}
+
+std::string CuttlefishConfig::InstanceSpecific::logcat_path() const {
+ return cvd::AbsolutePath(PerInstancePath("logcat"));
+}
+
+std::string CuttlefishConfig::InstanceSpecific::launcher_monitor_socket_path()
+ const {
+ return cvd::AbsolutePath(PerInstancePath("launcher_monitor.sock"));
+}
+
+std::string CuttlefishConfig::InstanceSpecific::launcher_log_path() const {
+ return cvd::AbsolutePath(PerInstancePath("launcher.log"));
+}
+
+std::string CuttlefishConfig::InstanceSpecific::sdcard_path() const {
+ return cvd::AbsolutePath(PerInstancePath("sdcard.img"));
+}
+
+std::string CuttlefishConfig::InstanceSpecific::mobile_bridge_name() const {
+ return (*Dictionary())[kMobileBridgeName].asString();
+}
+void CuttlefishConfig::MutableInstanceSpecific::set_mobile_bridge_name(
+ const std::string& mobile_bridge_name) {
+ (*Dictionary())[kMobileBridgeName] = mobile_bridge_name;
+}
+
+std::string CuttlefishConfig::InstanceSpecific::mobile_tap_name() const {
+ return (*Dictionary())[kMobileTapName].asString();
+}
+void CuttlefishConfig::MutableInstanceSpecific::set_mobile_tap_name(
+ const std::string& mobile_tap_name) {
+ (*Dictionary())[kMobileTapName] = mobile_tap_name;
+}
+
+std::string CuttlefishConfig::InstanceSpecific::wifi_tap_name() const {
+ return (*Dictionary())[kWifiTapName].asString();
+}
+void CuttlefishConfig::MutableInstanceSpecific::set_wifi_tap_name(
+ const std::string& wifi_tap_name) {
+ (*Dictionary())[kWifiTapName] = wifi_tap_name;
+}
+
+int CuttlefishConfig::InstanceSpecific::vsock_guest_cid() const {
+ return (*Dictionary())[kVsockGuestCid].asInt();
+}
+
+void CuttlefishConfig::MutableInstanceSpecific::set_vsock_guest_cid(
+ int vsock_guest_cid) {
+ (*Dictionary())[kVsockGuestCid] = vsock_guest_cid;
+}
+
+std::string CuttlefishConfig::InstanceSpecific::uuid() const {
+ return (*Dictionary())[kUuid].asString();
+}
+void CuttlefishConfig::MutableInstanceSpecific::set_uuid(const std::string& uuid) {
+ (*Dictionary())[kUuid] = uuid;
+}
+
void CuttlefishConfig::set_cuttlefish_env_path(const std::string& path) {
SetPath(kCuttlefishEnvPath, path);
}
@@ -208,7 +463,6 @@ static AdbMode stringToAdbMode(std::string mode) {
}
}
-static constexpr char kAdbMode[] = "adb_mode";
std::set<AdbMode> CuttlefishConfig::adb_mode() const {
std::set<AdbMode> args_set;
for (auto& mode : (*dictionary_)[kAdbMode]) {
@@ -216,6 +470,7 @@ std::set<AdbMode> CuttlefishConfig::adb_mode() const {
}
return args_set;
}
+
void CuttlefishConfig::set_adb_mode(const std::set<std::string>& mode) {
Json::Value mode_json_obj(Json::arrayValue);
for (const auto& arg : mode) {
@@ -224,350 +479,329 @@ void CuttlefishConfig::set_adb_mode(const std::set<std::string>& mode) {
(*dictionary_)[kAdbMode] = mode_json_obj;
}
-static SecureHal StringToSecureHal(std::string mode) {
- std::transform(mode.begin(), mode.end(), mode.begin(), ::tolower);
- if (mode == "keymint") {
- return SecureHal::Keymint;
- } else if (mode == "gatekeeper") {
- return SecureHal::Gatekeeper;
- } else {
- return SecureHal::Unknown;
- }
+int CuttlefishConfig::InstanceSpecific::host_port() const {
+ return (*Dictionary())[kHostPort].asInt();
}
-static constexpr char kSecureHals[] = "secure_hals";
-std::set<SecureHal> CuttlefishConfig::secure_hals() const {
- std::set<SecureHal> args_set;
- for (auto& hal : (*dictionary_)[kSecureHals]) {
- args_set.insert(StringToSecureHal(hal.asString()));
- }
- return args_set;
+void CuttlefishConfig::MutableInstanceSpecific::set_host_port(int host_port) {
+ (*Dictionary())[kHostPort] = host_port;
+}
+
+std::string CuttlefishConfig::InstanceSpecific::adb_ip_and_port() const {
+ return (*Dictionary())[kAdbIPAndPort].asString();
+}
+
+void CuttlefishConfig::MutableInstanceSpecific::set_adb_ip_and_port(
+ const std::string& ip_port) {
+ (*Dictionary())[kAdbIPAndPort] = ip_port;
}
-void CuttlefishConfig::set_secure_hals(const std::set<std::string>& hals) {
- Json::Value hals_json_obj(Json::arrayValue);
- for (const auto& hal : hals) {
- hals_json_obj.append(hal);
+
+std::string CuttlefishConfig::InstanceSpecific::adb_device_name() const {
+ if (adb_ip_and_port() != "") {
+ return adb_ip_and_port();
}
- (*dictionary_)[kSecureHals] = hals_json_obj;
+ LOG(ERROR) << "no adb_mode found, returning bad device name";
+ return "NO_ADB_MODE_SET_NO_VALID_DEVICE_NAME";
+}
+
+std::string CuttlefishConfig::InstanceSpecific::device_title() const {
+ return (*Dictionary())[kDeviceTitle].asString();
+}
+
+void CuttlefishConfig::MutableInstanceSpecific::set_device_title(
+ const std::string& title) {
+ (*Dictionary())[kDeviceTitle] = title;
}
-static constexpr char kSetupWizardMode[] = "setupwizard_mode";
std::string CuttlefishConfig::setupwizard_mode() const {
return (*dictionary_)[kSetupWizardMode].asString();
}
+
void CuttlefishConfig::set_setupwizard_mode(const std::string& mode) {
(*dictionary_)[kSetupWizardMode] = mode;
}
-static constexpr char kQemuBinaryDir[] = "qemu_binary_dir";
-std::string CuttlefishConfig::qemu_binary_dir() const {
- return (*dictionary_)[kQemuBinaryDir].asString();
+std::string CuttlefishConfig::qemu_binary() const {
+ return (*dictionary_)[kQemuBinary].asString();
}
-void CuttlefishConfig::set_qemu_binary_dir(const std::string& qemu_binary_dir) {
- (*dictionary_)[kQemuBinaryDir] = qemu_binary_dir;
+
+void CuttlefishConfig::set_qemu_binary(const std::string& qemu_binary) {
+ (*dictionary_)[kQemuBinary] = qemu_binary;
}
-static constexpr char kCrosvmBinary[] = "crosvm_binary";
std::string CuttlefishConfig::crosvm_binary() const {
return (*dictionary_)[kCrosvmBinary].asString();
}
+
void CuttlefishConfig::set_crosvm_binary(const std::string& crosvm_binary) {
(*dictionary_)[kCrosvmBinary] = crosvm_binary;
}
-static constexpr char kTpmDevice[] = "tpm_device";
-std::string CuttlefishConfig::tpm_device() const {
- return (*dictionary_)[kTpmDevice].asString();
+std::string CuttlefishConfig::console_forwarder_binary() const {
+ return (*dictionary_)[kConsoleForwarderBinary].asString();
}
-void CuttlefishConfig::set_tpm_device(const std::string& tpm_device) {
- (*dictionary_)[kTpmDevice] = tpm_device;
+
+void CuttlefishConfig::set_console_forwarder_binary(
+ const std::string& binary) {
+ (*dictionary_)[kConsoleForwarderBinary] = binary;
}
-static constexpr char kEnableGnssGrpcProxy[] = "enable_gnss_grpc_proxy";
-void CuttlefishConfig::set_enable_gnss_grpc_proxy(const bool enable_gnss_grpc_proxy) {
- (*dictionary_)[kEnableGnssGrpcProxy] = enable_gnss_grpc_proxy;
+std::string CuttlefishConfig::kernel_log_monitor_binary() const {
+ return (*dictionary_)[kKernelLogMonitorBinary].asString();
}
-bool CuttlefishConfig::enable_gnss_grpc_proxy() const {
- return (*dictionary_)[kEnableGnssGrpcProxy].asBool();
+
+void CuttlefishConfig::set_kernel_log_monitor_binary(
+ const std::string& kernel_log_monitor_binary) {
+ (*dictionary_)[kKernelLogMonitorBinary] = kernel_log_monitor_binary;
}
-static constexpr char kEnableVncServer[] = "enable_vnc_server";
bool CuttlefishConfig::enable_vnc_server() const {
return (*dictionary_)[kEnableVncServer].asBool();
}
+
void CuttlefishConfig::set_enable_vnc_server(bool enable_vnc_server) {
(*dictionary_)[kEnableVncServer] = enable_vnc_server;
}
-static constexpr char kEnableSandbox[] = "enable_sandbox";
-void CuttlefishConfig::set_enable_sandbox(const bool enable_sandbox) {
- (*dictionary_)[kEnableSandbox] = enable_sandbox;
+std::string CuttlefishConfig::vnc_server_binary() const {
+ return (*dictionary_)[kVncServerBinary].asString();
}
-bool CuttlefishConfig::enable_sandbox() const {
- return (*dictionary_)[kEnableSandbox].asBool();
+
+void CuttlefishConfig::set_vnc_server_binary(
+ const std::string& vnc_server_binary) {
+ (*dictionary_)[kVncServerBinary] = vnc_server_binary;
}
-static constexpr char kSeccompPolicyDir[] = "seccomp_policy_dir";
-void CuttlefishConfig::set_seccomp_policy_dir(const std::string& seccomp_policy_dir) {
- if (seccomp_policy_dir.empty()) {
- (*dictionary_)[kSeccompPolicyDir] = seccomp_policy_dir;
- return;
- }
- SetPath(kSeccompPolicyDir, seccomp_policy_dir);
+int CuttlefishConfig::InstanceSpecific::vnc_server_port() const {
+ return (*Dictionary())[kVncServerPort].asInt();
}
-std::string CuttlefishConfig::seccomp_policy_dir() const {
- return (*dictionary_)[kSeccompPolicyDir].asString();
+
+void CuttlefishConfig::MutableInstanceSpecific::set_vnc_server_port(int vnc_server_port) {
+ (*Dictionary())[kVncServerPort] = vnc_server_port;
+}
+
+int CuttlefishConfig::InstanceSpecific::vehicle_hal_server_port() const {
+ return (*Dictionary())[kVehicleHalServerPort].asInt();
+}
+
+void CuttlefishConfig::MutableInstanceSpecific::set_vehicle_hal_server_port(int vehicle_hal_server_port) {
+ (*Dictionary())[kVehicleHalServerPort] = vehicle_hal_server_port;
}
-static constexpr char kEnableWebRTC[] = "enable_webrtc";
void CuttlefishConfig::set_enable_webrtc(bool enable_webrtc) {
(*dictionary_)[kEnableWebRTC] = enable_webrtc;
}
+
bool CuttlefishConfig::enable_webrtc() const {
return (*dictionary_)[kEnableWebRTC].asBool();
}
-static constexpr char kEnableVehicleHalServer[] = "enable_vehicle_hal_server";
+void CuttlefishConfig::set_webrtc_binary(const std::string& webrtc_binary) {
+ (*dictionary_)[kWebRTCBinary] = webrtc_binary;
+}
+
+std::string CuttlefishConfig::webrtc_binary() const {
+ return (*dictionary_)[kWebRTCBinary].asString();
+}
+
void CuttlefishConfig::set_enable_vehicle_hal_grpc_server(bool enable_vehicle_hal_grpc_server) {
(*dictionary_)[kEnableVehicleHalServer] = enable_vehicle_hal_grpc_server;
}
+
bool CuttlefishConfig::enable_vehicle_hal_grpc_server() const {
return (*dictionary_)[kEnableVehicleHalServer].asBool();
}
-static constexpr char kVehicleHalServerBinary[] = "vehicle_hal_server_binary";
void CuttlefishConfig::set_vehicle_hal_grpc_server_binary(const std::string& vehicle_hal_server_binary) {
(*dictionary_)[kVehicleHalServerBinary] = vehicle_hal_server_binary;
}
+
std::string CuttlefishConfig::vehicle_hal_grpc_server_binary() const {
return (*dictionary_)[kVehicleHalServerBinary].asString();
}
-static constexpr char kCustomActions[] = "custom_actions";
-void CuttlefishConfig::set_custom_actions(const std::vector<CustomActionConfig>& actions) {
- Json::Value actions_array(Json::arrayValue);
- for (const auto& action : actions) {
- actions_array.append(action.ToJson());
- }
- (*dictionary_)[kCustomActions] = actions_array;
-}
-std::vector<CustomActionConfig> CuttlefishConfig::custom_actions() const {
- std::vector<CustomActionConfig> result;
- for (Json::Value custom_action : (*dictionary_)[kCustomActions]) {
- result.push_back(CustomActionConfig(custom_action));
- }
- return result;
-}
-
-static constexpr char kWebRTCAssetsDir[] = "webrtc_assets_dir";
void CuttlefishConfig::set_webrtc_assets_dir(const std::string& webrtc_assets_dir) {
(*dictionary_)[kWebRTCAssetsDir] = webrtc_assets_dir;
}
+
std::string CuttlefishConfig::webrtc_assets_dir() const {
return (*dictionary_)[kWebRTCAssetsDir].asString();
}
-static constexpr char kWebRTCEnableADBWebSocket[] =
- "webrtc_enable_adb_websocket";
+void CuttlefishConfig::set_webrtc_public_ip(
+ const std::string& webrtc_public_ip) {
+ (*dictionary_)[kWebRTCPublicIP] = webrtc_public_ip;
+}
+
+std::string CuttlefishConfig::webrtc_public_ip() const {
+ return (*dictionary_)[kWebRTCPublicIP].asString();
+}
+
void CuttlefishConfig::set_webrtc_enable_adb_websocket(bool enable) {
(*dictionary_)[kWebRTCEnableADBWebSocket] = enable;
}
+
bool CuttlefishConfig::webrtc_enable_adb_websocket() const {
return (*dictionary_)[kWebRTCEnableADBWebSocket].asBool();
}
-static constexpr char kRestartSubprocesses[] = "restart_subprocesses";
bool CuttlefishConfig::restart_subprocesses() const {
return (*dictionary_)[kRestartSubprocesses].asBool();
}
+
void CuttlefishConfig::set_restart_subprocesses(bool restart_subprocesses) {
(*dictionary_)[kRestartSubprocesses] = restart_subprocesses;
}
-static constexpr char kRunAdbConnector[] = "run_adb_connector";
bool CuttlefishConfig::run_adb_connector() const {
return (*dictionary_)[kRunAdbConnector].asBool();
}
+
void CuttlefishConfig::set_run_adb_connector(bool run_adb_connector) {
(*dictionary_)[kRunAdbConnector] = run_adb_connector;
}
-static constexpr char kRunAsDaemon[] = "run_as_daemon";
+std::string CuttlefishConfig::adb_connector_binary() const {
+ return (*dictionary_)[kAdbConnectorBinary].asString();
+}
+
+void CuttlefishConfig::set_adb_connector_binary(
+ const std::string& adb_connector_binary) {
+ (*dictionary_)[kAdbConnectorBinary] = adb_connector_binary;
+}
+
+std::string CuttlefishConfig::socket_vsock_proxy_binary() const {
+ return (*dictionary_)[kSocketVsockProxyBinary].asString();
+}
+
+void CuttlefishConfig::set_socket_vsock_proxy_binary(
+ const std::string& socket_vsock_proxy_binary) {
+ (*dictionary_)[kSocketVsockProxyBinary] = socket_vsock_proxy_binary;
+}
+
bool CuttlefishConfig::run_as_daemon() const {
return (*dictionary_)[kRunAsDaemon].asBool();
}
+
void CuttlefishConfig::set_run_as_daemon(bool run_as_daemon) {
(*dictionary_)[kRunAsDaemon] = run_as_daemon;
}
-
-static constexpr char kDataPolicy[] = "data_policy";
std::string CuttlefishConfig::data_policy() const {
return (*dictionary_)[kDataPolicy].asString();
}
+
void CuttlefishConfig::set_data_policy(const std::string& data_policy) {
(*dictionary_)[kDataPolicy] = data_policy;
}
-static constexpr char kBlankDataImageMb[] = "blank_data_image_mb";
int CuttlefishConfig::blank_data_image_mb() const {
return (*dictionary_)[kBlankDataImageMb].asInt();
}
+
void CuttlefishConfig::set_blank_data_image_mb(int blank_data_image_mb) {
(*dictionary_)[kBlankDataImageMb] = blank_data_image_mb;
}
-static constexpr char kBlankDataImageFmt[] = "blank_data_image_fmt";
std::string CuttlefishConfig::blank_data_image_fmt() const {
return (*dictionary_)[kBlankDataImageFmt].asString();
}
+
void CuttlefishConfig::set_blank_data_image_fmt(const std::string& blank_data_image_fmt) {
(*dictionary_)[kBlankDataImageFmt] = blank_data_image_fmt;
}
-static constexpr char kBootloader[] = "bootloader";
-std::string CuttlefishConfig::bootloader() const {
- return (*dictionary_)[kBootloader].asString();
-}
-void CuttlefishConfig::set_bootloader(const std::string& bootloader) {
- SetPath(kBootloader, bootloader);
-}
-static constexpr char kBootSlot[] = "boot_slot";
-void CuttlefishConfig::set_boot_slot(const std::string& boot_slot) {
- (*dictionary_)[kBootSlot] = boot_slot;
-}
-std::string CuttlefishConfig::boot_slot() const {
- return (*dictionary_)[kBootSlot].asString();
+void CuttlefishConfig::set_logcat_mode(const std::string& mode) {
+ (*dictionary_)[kLogcatMode] = mode;
}
-static constexpr char kWebRTCCertsDir[] = "webrtc_certs_dir";
-void CuttlefishConfig::set_webrtc_certs_dir(const std::string& certs_dir) {
- (*dictionary_)[kWebRTCCertsDir] = certs_dir;
-}
-std::string CuttlefishConfig::webrtc_certs_dir() const {
- return (*dictionary_)[kWebRTCCertsDir].asString();
+std::string CuttlefishConfig::logcat_mode() const {
+ return (*dictionary_)[kLogcatMode].asString();
}
-static constexpr char kSigServerPort[] = "webrtc_sig_server_port";
-void CuttlefishConfig::set_sig_server_port(int port) {
- (*dictionary_)[kSigServerPort] = port;
-}
-int CuttlefishConfig::sig_server_port() const {
- return (*dictionary_)[kSigServerPort].asInt();
+void CuttlefishConfig::set_logcat_receiver_binary(const std::string& binary) {
+ SetPath(kLogcatReceiverBinary, binary);
}
-static constexpr char kWebrtcUdpPortRange[] = "webrtc_udp_port_range";
-void CuttlefishConfig::set_webrtc_udp_port_range(
- std::pair<uint16_t, uint16_t> range) {
- Json::Value arr(Json::ValueType::arrayValue);
- arr[0] = range.first;
- arr[1] = range.second;
- (*dictionary_)[kWebrtcUdpPortRange] = arr;
+std::string CuttlefishConfig::logcat_receiver_binary() const {
+ return (*dictionary_)[kLogcatReceiverBinary].asString();
}
-std::pair<uint16_t, uint16_t> CuttlefishConfig::webrtc_udp_port_range() const {
- std::pair<uint16_t, uint16_t> ret;
- ret.first = (*dictionary_)[kWebrtcUdpPortRange][0].asInt();
- ret.second = (*dictionary_)[kWebrtcUdpPortRange][1].asInt();
- return ret;
+
+void CuttlefishConfig::set_config_server_binary(const std::string& binary) {
+ SetPath(kConfigServerBinary, binary);
}
-static constexpr char kWebrtcTcpPortRange[] = "webrtc_tcp_port_range";
-void CuttlefishConfig::set_webrtc_tcp_port_range(
- std::pair<uint16_t, uint16_t> range) {
- Json::Value arr(Json::ValueType::arrayValue);
- arr[0] = range.first;
- arr[1] = range.second;
- (*dictionary_)[kWebrtcTcpPortRange] = arr;
+std::string CuttlefishConfig::config_server_binary() const {
+ return (*dictionary_)[kConfigServerBinary].asString();
}
-std::pair<uint16_t, uint16_t> CuttlefishConfig::webrtc_tcp_port_range() const {
- std::pair<uint16_t, uint16_t> ret;
- ret.first = (*dictionary_)[kWebrtcTcpPortRange][0].asInt();
- ret.second = (*dictionary_)[kWebrtcTcpPortRange][1].asInt();
- return ret;
+
+bool CuttlefishConfig::enable_tombstone_receiver() const {
+ return (*dictionary_)[kRunTombstoneReceiver].asBool();
}
-static constexpr char kSigServerAddress[] = "webrtc_sig_server_addr";
-void CuttlefishConfig::set_sig_server_address(const std::string& addr) {
- (*dictionary_)[kSigServerAddress] = addr;
+void CuttlefishConfig::set_enable_tombstone_receiver(bool enable_tombstone_receiver) {
+ (*dictionary_)[kRunTombstoneReceiver] = enable_tombstone_receiver;
}
-std::string CuttlefishConfig::sig_server_address() const {
- return (*dictionary_)[kSigServerAddress].asString();
+
+std::string CuttlefishConfig::tombstone_receiver_binary() const {
+ return (*dictionary_)[kTombstoneReceiverBinary].asString();
}
-static constexpr char kSigServerPath[] = "webrtc_sig_server_path";
-void CuttlefishConfig::set_sig_server_path(const std::string& path) {
- // Don't use SetPath here, it's a URL path not a file system path
- (*dictionary_)[kSigServerPath] = path;
+void CuttlefishConfig::set_tombstone_receiver_binary(const std::string& e2e_test_binary) {
+ (*dictionary_)[kTombstoneReceiverBinary] = e2e_test_binary;
}
-std::string CuttlefishConfig::sig_server_path() const {
- return (*dictionary_)[kSigServerPath].asString();
+
+bool CuttlefishConfig::use_bootloader() const {
+ return (*dictionary_)[kUseBootloader].asBool();
}
-static constexpr char kSigServerStrict[] = "webrtc_sig_server_strict";
-void CuttlefishConfig::set_sig_server_strict(bool strict) {
- (*dictionary_)[kSigServerStrict] = strict;
+void CuttlefishConfig::set_use_bootloader(bool use_bootloader) {
+ (*dictionary_)[kUseBootloader] = use_bootloader;
}
-bool CuttlefishConfig::sig_server_strict() const {
- return (*dictionary_)[kSigServerStrict].asBool();
+
+std::string CuttlefishConfig::bootloader() const {
+ return (*dictionary_)[kBootloader].asString();
}
-static constexpr char kSigServerHeadersPath[] =
- "webrtc_sig_server_headers_path";
-void CuttlefishConfig::set_sig_server_headers_path(const std::string& path) {
- SetPath(kSigServerHeadersPath, path);
+void CuttlefishConfig::set_bootloader(const std::string& bootloader) {
+ SetPath(kBootloader, bootloader);
}
-std::string CuttlefishConfig::sig_server_headers_path() const {
- return (*dictionary_)[kSigServerHeadersPath].asString();
+
+void CuttlefishConfig::set_boot_slot(const std::string& boot_slot) {
+ (*dictionary_)[kBootSlot] = boot_slot;
}
-static constexpr char kRunModemSimulator[] = "enable_modem_simulator";
-bool CuttlefishConfig::enable_modem_simulator() const {
- return (*dictionary_)[kRunModemSimulator].asBool();
+std::string CuttlefishConfig::boot_slot() const {
+ return (*dictionary_)[kBootSlot].asString();
}
-void CuttlefishConfig::set_enable_modem_simulator(bool enable_modem_simulator) {
- (*dictionary_)[kRunModemSimulator] = enable_modem_simulator;
+
+void CuttlefishConfig::set_webrtc_certs_dir(const std::string& certs_dir) {
+ (*dictionary_)[kWebRTCCertsDir] = certs_dir;
}
-static constexpr char kModemSimulatorInstanceNumber[] =
- "modem_simulator_instance_number";
-void CuttlefishConfig::set_modem_simulator_instance_number(
- int instance_number) {
- (*dictionary_)[kModemSimulatorInstanceNumber] = instance_number;
+std::string CuttlefishConfig::webrtc_certs_dir() const {
+ return (*dictionary_)[kWebRTCCertsDir].asString();
}
-int CuttlefishConfig::modem_simulator_instance_number() const {
- return (*dictionary_)[kModemSimulatorInstanceNumber].asInt();
+
+std::string CuttlefishConfig::InstanceSpecific::touch_socket_path() const {
+ return PerInstanceInternalPath("touch.sock");
}
-static constexpr char kModemSimulatorSimType[] = "modem_simulator_sim_type";
-void CuttlefishConfig::set_modem_simulator_sim_type(int sim_type) {
- (*dictionary_)[kModemSimulatorSimType] = sim_type;
+std::string CuttlefishConfig::InstanceSpecific::keyboard_socket_path() const {
+ return PerInstanceInternalPath("keyboard.sock");
}
-int CuttlefishConfig::modem_simulator_sim_type() const {
- return (*dictionary_)[kModemSimulatorSimType].asInt();
+
+std::string CuttlefishConfig::InstanceSpecific::frames_socket_path() const {
+ return PerInstanceInternalPath("frames.sock");
}
-static constexpr char kHostToolsVersion[] = "host_tools_version";
-void CuttlefishConfig::set_host_tools_version(
- const std::map<std::string, uint32_t>& versions) {
- Json::Value json(Json::objectValue);
- for (const auto& [key, value] : versions) {
- json[key] = value;
- }
- (*dictionary_)[kHostToolsVersion] = json;
+void CuttlefishConfig::set_loop_max_part(int loop_max_part) {
+ (*dictionary_)[kLoopMaxPart] = loop_max_part;
}
-std::map<std::string, uint32_t> CuttlefishConfig::host_tools_version() const {
- if (!dictionary_->isMember(kHostToolsVersion)) {
- return {};
- }
- std::map<std::string, uint32_t> versions;
- const auto& elem = (*dictionary_)[kHostToolsVersion];
- for (auto it = elem.begin(); it != elem.end(); it++) {
- versions[it.key().asString()] = it->asUInt();
- }
- return versions;
+int CuttlefishConfig::loop_max_part() const {
+ return (*dictionary_)[kLoopMaxPart].asInt();
}
-static constexpr char kGuestEnforceSecurity[] = "guest_enforce_security";
void CuttlefishConfig::set_guest_enforce_security(bool guest_enforce_security) {
(*dictionary_)[kGuestEnforceSecurity] = guest_enforce_security;
}
@@ -575,7 +809,6 @@ bool CuttlefishConfig::guest_enforce_security() const {
return (*dictionary_)[kGuestEnforceSecurity].asBool();
}
-const char* kGuestAuditSecurity = "guest_audit_security";
void CuttlefishConfig::set_guest_audit_security(bool guest_audit_security) {
(*dictionary_)[kGuestAuditSecurity] = guest_audit_security;
}
@@ -583,43 +816,50 @@ bool CuttlefishConfig::guest_audit_security() const {
return (*dictionary_)[kGuestAuditSecurity].asBool();
}
-static constexpr char kenableHostBluetooth[] = "enable_host_bluetooth";
-void CuttlefishConfig::set_enable_host_bluetooth(bool enable_host_bluetooth) {
- (*dictionary_)[kenableHostBluetooth] = enable_host_bluetooth;
+void CuttlefishConfig::set_guest_force_normal_boot(bool guest_force_normal_boot) {
+ (*dictionary_)[kGuestForceNormalBoot] = guest_force_normal_boot;
}
-bool CuttlefishConfig::enable_host_bluetooth() const {
- return (*dictionary_)[kenableHostBluetooth].asBool();
+bool CuttlefishConfig::guest_force_normal_boot() const {
+ return (*dictionary_)[kGuestForceNormalBoot].asBool();
}
-static constexpr char kEnableMetrics[] = "enable_metrics";
-void CuttlefishConfig::set_enable_metrics(std::string enable_metrics) {
- (*dictionary_)[kEnableMetrics] = kUnknown;
- if (!enable_metrics.empty()) {
- switch (enable_metrics.at(0)) {
- case 'y':
- case 'Y':
- (*dictionary_)[kEnableMetrics] = kYes;
- break;
- case 'n':
- case 'N':
- (*dictionary_)[kEnableMetrics] = kNo;
- break;
- }
+void CuttlefishConfig::MutableInstanceSpecific::set_wifi_mac_address(
+ const std::array<unsigned char, 6>& mac_address) {
+ Json::Value mac_address_obj(Json::arrayValue);
+ for (const auto& num : mac_address) {
+ mac_address_obj.append(num);
}
+ (*Dictionary())[kWifiMacAddress] = mac_address_obj;
}
-CuttlefishConfig::Answer CuttlefishConfig::enable_metrics() const {
- return (CuttlefishConfig::Answer)(*dictionary_)[kEnableMetrics].asInt();
+
+std::array<unsigned char, 6> CuttlefishConfig::InstanceSpecific::wifi_mac_address() const {
+ std::array<unsigned char, 6> mac_address{0, 0, 0, 0, 0, 0};
+ auto mac_address_obj = (*Dictionary())[kWifiMacAddress];
+ if (mac_address_obj.size() != 6) {
+ LOG(ERROR) << kWifiMacAddress << " entry had wrong size";
+ return {};
+ }
+ for (int i = 0; i < 6; i++) {
+ mac_address[i] = mac_address_obj[i].asInt();
+ }
+ return mac_address;
}
-static constexpr char kMetricsBinary[] = "metrics_binary";
-void CuttlefishConfig::set_metrics_binary(const std::string& metrics_binary) {
- (*dictionary_)[kMetricsBinary] = metrics_binary;
+void CuttlefishConfig::set_boot_image_kernel_cmdline(std::string boot_image_kernel_cmdline) {
+ Json::Value args_json_obj(Json::arrayValue);
+ for (const auto& arg : android::base::Split(boot_image_kernel_cmdline, " ")) {
+ args_json_obj.append(arg);
+ }
+ (*dictionary_)[kBootImageKernelCmdline] = args_json_obj;
}
-std::string CuttlefishConfig::metrics_binary() const {
- return (*dictionary_)[kMetricsBinary].asString();
+std::vector<std::string> CuttlefishConfig::boot_image_kernel_cmdline() const {
+ std::vector<std::string> cmdline;
+ for (const Json::Value& arg : (*dictionary_)[kBootImageKernelCmdline]) {
+ cmdline.push_back(arg.asString());
+ }
+ return cmdline;
}
-static constexpr char kExtraKernelCmdline[] = "extra_kernel_cmdline";
void CuttlefishConfig::set_extra_kernel_cmdline(std::string extra_cmdline) {
Json::Value args_json_obj(Json::arrayValue);
for (const auto& arg : android::base::Split(extra_cmdline, " ")) {
@@ -635,128 +875,12 @@ std::vector<std::string> CuttlefishConfig::extra_kernel_cmdline() const {
return cmdline;
}
-static constexpr char kRilDns[] = "ril_dns";
-void CuttlefishConfig::set_ril_dns(const std::string& ril_dns) {
- (*dictionary_)[kRilDns] = ril_dns;
-}
-std::string CuttlefishConfig::ril_dns() const {
- return (*dictionary_)[kRilDns].asString();
-}
-
-static constexpr char kKgdb[] = "kgdb";
-void CuttlefishConfig::set_kgdb(bool kgdb) {
- (*dictionary_)[kKgdb] = kgdb;
-}
-bool CuttlefishConfig::kgdb() const {
- return (*dictionary_)[kKgdb].asBool();
-}
-
-static constexpr char kEnableMinimalMode[] = "enable_minimal_mode";
-bool CuttlefishConfig::enable_minimal_mode() const {
- return (*dictionary_)[kEnableMinimalMode].asBool();
-}
-void CuttlefishConfig::set_enable_minimal_mode(bool enable_minimal_mode) {
- (*dictionary_)[kEnableMinimalMode] = enable_minimal_mode;
-}
-
-static constexpr char kConsole[] = "console";
-void CuttlefishConfig::set_console(bool console) {
- (*dictionary_)[kConsole] = console;
-}
-bool CuttlefishConfig::console() const {
- return (*dictionary_)[kConsole].asBool();
-}
-std::string CuttlefishConfig::console_dev() const {
- auto can_use_virtio_console = !kgdb() && !use_bootloader();
- std::string console_dev;
- if (can_use_virtio_console) {
- // If kgdb and the bootloader are disabled, the Android serial console
- // spawns on a virtio-console port. If the bootloader is enabled, virtio
- // console can't be used since uboot doesn't support it.
- console_dev = "hvc1";
- } else {
- // crosvm ARM does not support ttyAMA. ttyAMA is a part of ARM arch.
- Arch target = target_arch();
- if ((target == Arch::Arm64 || target == Arch::Arm) &&
- vm_manager() != vm_manager::CrosvmManager::name()) {
- console_dev = "ttyAMA0";
- } else {
- console_dev = "ttyS0";
- }
- }
- return console_dev;
-}
-
-static constexpr char kVhostNet[] = "vhost_net";
-void CuttlefishConfig::set_vhost_net(bool vhost_net) {
- (*dictionary_)[kVhostNet] = vhost_net;
-}
-bool CuttlefishConfig::vhost_net() const {
- return (*dictionary_)[kVhostNet].asBool();
-}
-
-static constexpr char kEthernet[] = "ethernet";
-void CuttlefishConfig::set_ethernet(bool ethernet) {
- (*dictionary_)[kEthernet] = ethernet;
-}
-bool CuttlefishConfig::ethernet() const {
- return (*dictionary_)[kEthernet].asBool();
-}
-
-static constexpr char kRecordScreen[] = "record_screen";
-void CuttlefishConfig::set_record_screen(bool record_screen) {
- (*dictionary_)[kRecordScreen] = record_screen;
-}
-bool CuttlefishConfig::record_screen() const {
- return (*dictionary_)[kRecordScreen].asBool();
-}
-
-static constexpr char kSmt[] = "smt";
-void CuttlefishConfig::set_smt(bool smt) {
- (*dictionary_)[kSmt] = smt;
-}
-bool CuttlefishConfig::smt() const {
- return (*dictionary_)[kSmt].asBool();
-}
-
-static constexpr char kEnableAudio[] = "enable_audio";
-void CuttlefishConfig::set_enable_audio(bool enable) {
- (*dictionary_)[kEnableAudio] = enable;
-}
-bool CuttlefishConfig::enable_audio() const {
- return (*dictionary_)[kEnableAudio].asBool();
-}
-
-static constexpr char kProtectedVm[] = "protected_vm";
-void CuttlefishConfig::set_protected_vm(bool protected_vm) {
- (*dictionary_)[kProtectedVm] = protected_vm;
-}
-bool CuttlefishConfig::protected_vm() const {
- return (*dictionary_)[kProtectedVm].asBool();
-}
-
-static constexpr char kTargetArch[] = "target_arch";
-void CuttlefishConfig::set_target_arch(Arch target_arch) {
- (*dictionary_)[kTargetArch] = static_cast<int>(target_arch);
-}
-Arch CuttlefishConfig::target_arch() const {
- return static_cast<Arch>((*dictionary_)[kTargetArch].asInt());
-}
-
-static constexpr char kBootconfigSupported[] = "bootconfig_supported";
-bool CuttlefishConfig::bootconfig_supported() const {
- return (*dictionary_)[kBootconfigSupported].asBool();
-}
-void CuttlefishConfig::set_bootconfig_supported(bool bootconfig_supported) {
- (*dictionary_)[kBootconfigSupported] = bootconfig_supported;
-}
-
// Creates the (initially empty) config object and populates it with values from
// the config file if the CUTTLEFISH_CONFIG_FILE env variable is present.
// Returns nullptr if there was an error loading from file
/*static*/ CuttlefishConfig* CuttlefishConfig::BuildConfigImpl() {
- auto config_file_path = StringFromEnv(kCuttlefishConfigEnvVarName,
- GetGlobalConfigFileLink());
+ auto config_file_path = cvd::StringFromEnv(kCuttlefishConfigEnvVarName,
+ vsoc::GetGlobalConfigFileLink());
auto ret = new CuttlefishConfig();
if (ret) {
auto loaded = ret->LoadFromFile(config_file_path.c_str());
@@ -773,13 +897,6 @@ void CuttlefishConfig::set_bootconfig_supported(bool bootconfig_supported) {
return config.get();
}
-/*static*/ bool CuttlefishConfig::ConfigExists() {
- auto config_file_path = StringFromEnv(kCuttlefishConfigEnvVarName,
- GetGlobalConfigFileLink());
- auto real_file_path = AbsolutePath(config_file_path.c_str());
- return FileExists(real_file_path);
-}
-
CuttlefishConfig::CuttlefishConfig() : dictionary_(new Json::Value()) {}
// Can't use '= default' on the header because the compiler complains of
// Json::Value being an incomplete type
@@ -789,16 +906,16 @@ CuttlefishConfig::CuttlefishConfig(CuttlefishConfig&&) = default;
CuttlefishConfig& CuttlefishConfig::operator=(CuttlefishConfig&&) = default;
bool CuttlefishConfig::LoadFromFile(const char* file) {
- auto real_file_path = AbsolutePath(file);
+ auto real_file_path = cvd::AbsolutePath(file);
if (real_file_path.empty()) {
LOG(ERROR) << "Could not get real path for file " << file;
return false;
}
- Json::CharReaderBuilder builder;
+ Json::Reader reader;
std::ifstream ifs(real_file_path);
- std::string errorMessage;
- if (!Json::parseFromStream(builder, ifs, dictionary_.get(), &errorMessage)) {
- LOG(ERROR) << "Could not read config file " << file << ": " << errorMessage;
+ if (!reader.parse(ifs, *dictionary_)) {
+ LOG(ERROR) << "Could not read config file " << file << ": "
+ << reader.getFormattedErrorMessages();
return false;
}
return true;
@@ -815,7 +932,30 @@ bool CuttlefishConfig::SaveToFile(const std::string& file) const {
std::string CuttlefishConfig::AssemblyPath(
const std::string& file_name) const {
- return AbsolutePath(assembly_dir() + "/" + file_name);
+ return cvd::AbsolutePath(assembly_dir() + "/" + file_name);
+}
+
+std::string CuttlefishConfig::composite_disk_path() const {
+ return AssemblyPath("composite.img");
+}
+
+std::string CuttlefishConfig::InstanceSpecific::PerInstancePath(
+ const char* file_name) const {
+ return (instance_dir() + "/") + file_name;
+}
+
+std::string CuttlefishConfig::InstanceSpecific::PerInstanceInternalPath(
+ const char* file_name) const {
+ if (file_name[0] == '\0') {
+ // Don't append a / if file_name is empty.
+ return PerInstancePath(kInternalDirName);
+ }
+ auto relative_path = (std::string(kInternalDirName) + "/") + file_name;
+ return PerInstancePath(relative_path.c_str());
+}
+
+std::string CuttlefishConfig::InstanceSpecific::instance_name() const {
+ return ForCurrentInstance("cvd-");
}
CuttlefishConfig::MutableInstanceSpecific CuttlefishConfig::ForInstance(int num) {
@@ -844,19 +984,8 @@ int GetInstance() {
return instance_id;
}
-int GetDefaultVsockCid() {
- // we assume that this function is used to configure CuttlefishConfig once
- static const int default_vsock_cid = 3 + GetInstance() - 1;
- return default_vsock_cid;
-}
-
-int GetVsockServerPort(const int base,
- const int vsock_guest_cid /**< per instance guest cid */) {
- return base + (vsock_guest_cid - 3);
-}
-
std::string GetGlobalConfigFileLink() {
- return StringFromEnv("HOME", ".") + "/.cuttlefish_config.json";
+ return cvd::StringFromEnv("HOME", ".") + "/.cuttlefish_config.json";
}
std::string ForCurrentInstance(const char* prefix) {
@@ -876,21 +1005,28 @@ std::string RandomSerialNumber(const std::string& prefix) {
return prefix + str;
}
-std::string DefaultHostArtifactsPath(const std::string& file_name) {
- return (StringFromEnv("ANDROID_SOONG_HOST_OUT", StringFromEnv("HOME", ".")) + "/") +
- file_name;
+std::string GetDefaultPerInstanceDir() {
+ std::ostringstream stream;
+ stream << std::getenv("HOME") << "/cuttlefish_runtime";
+ return stream.str();
}
-std::string HostBinaryPath(const std::string& binary_name) {
-#ifdef __ANDROID__
- return binary_name;
-#else
- return DefaultHostArtifactsPath("bin/" + binary_name);
-#endif
+int GetDefaultPerInstanceVsockCid() {
+ constexpr int kFirstGuestCid = 3;
+ return vsoc::HostSupportsVsock() ? ForCurrentInstance(kFirstGuestCid) : 0;
+}
+
+std::string DefaultHostArtifactsPath(const std::string& file_name) {
+ return (cvd::StringFromEnv("ANDROID_HOST_OUT",
+ cvd::StringFromEnv("HOME", ".")) +
+ "/") +
+ file_name;
}
std::string DefaultGuestImagePath(const std::string& file_name) {
- return (StringFromEnv("ANDROID_PRODUCT_OUT", StringFromEnv("HOME", "."))) +
+ return (cvd::StringFromEnv("ANDROID_PRODUCT_OUT",
+ cvd::StringFromEnv("HOME", ".")) +
+ "/") +
file_name;
}
@@ -901,4 +1037,10 @@ bool HostSupportsQemuCli() {
return supported;
}
-} // namespace cuttlefish
+bool HostSupportsVsock() {
+ static bool supported =
+ std::system(
+ "/usr/lib/cuttlefish-common/bin/capability_query.py vsock") == 0;
+ return supported;
+}
+} // namespace vsoc
diff --git a/host/libs/config/cuttlefish_config.h b/host/libs/config/cuttlefish_config.h
index 2b76c75ea..e6a1e79e6 100644
--- a/host/libs/config/cuttlefish_config.h
+++ b/host/libs/config/cuttlefish_config.h
@@ -15,29 +15,17 @@
*/
#pragma once
-#include <sys/types.h>
#include <array>
-#include <cstdint>
-#include <map>
#include <memory>
-#include <optional>
#include <string>
#include <set>
#include <vector>
-#include "common/libs/utils/environment.h"
-#include "host/libs/config/custom_actions.h"
-
namespace Json {
class Value;
}
-namespace cuttlefish {
-constexpr char kLogcatSerialMode[] = "serial";
-constexpr char kLogcatVsockMode[] = "vsock";
-}
-
-namespace cuttlefish {
+namespace vsoc {
constexpr char kDefaultUuidPrefix[] = "699acfc4-c8c4-11e7-882b-5065f31dc1";
constexpr char kCuttlefishConfigEnvVarName[] = "CUTTLEFISH_CONFIG_FILE";
@@ -49,12 +37,8 @@ constexpr char kMobileNetworkConnectedMessage[] =
"VIRTUAL_DEVICE_NETWORK_MOBILE_CONNECTED";
constexpr char kWifiConnectedMessage[] =
"VIRTUAL_DEVICE_NETWORK_WIFI_CONNECTED";
-constexpr char kEthernetConnectedMessage[] =
- "VIRTUAL_DEVICE_NETWORK_ETHERNET_CONNECTED";
-constexpr char kScreenChangedMessage[] = "VIRTUAL_DEVICE_SCREEN_CHANGED";
constexpr char kInternalDirName[] = "internal";
-constexpr char kSharedDirName[] = "shared";
-constexpr char kCrosvmVarEmptyDir[] = "/var/empty";
+
enum class AdbMode {
VsockTunnel,
@@ -63,17 +47,10 @@ enum class AdbMode {
Unknown,
};
-enum class SecureHal {
- Unknown,
- Keymint,
- Gatekeeper,
-};
-
// Holds the configuration of the cuttlefish instances.
class CuttlefishConfig {
public:
static const CuttlefishConfig* Get();
- static bool ConfigExists();
CuttlefishConfig();
CuttlefishConfig(CuttlefishConfig&&);
@@ -89,12 +66,23 @@ class CuttlefishConfig {
std::string AssemblyPath(const std::string&) const;
+ std::string composite_disk_path() const;
+
std::string vm_manager() const;
void set_vm_manager(const std::string& name);
std::string gpu_mode() const;
void set_gpu_mode(const std::string& name);
+ std::string serial_number() const;
+ void set_serial_number(const std::string& serial_number);
+
+ std::string wayland_socket() const;
+ void set_wayland_socket(const std::string& path);
+
+ std::string x_display() const;
+ void set_x_display(const std::string& address);
+
int cpus() const;
void set_cpus(int cpus);
@@ -104,59 +92,104 @@ class CuttlefishConfig {
int dpi() const;
void set_dpi(int dpi);
+ int x_res() const;
+ void set_x_res(int x_res);
+
+ int y_res() const;
+ void set_y_res(int y_res);
+
int refresh_rate_hz() const;
void set_refresh_rate_hz(int refresh_rate_hz);
- struct DisplayConfig {
- int width;
- int height;
- };
+ // Returns kernel image extracted from the boot image or the user-provided one
+ // if given by command line to the launcher. This function should not be used
+ // to get the kernel image the vmm should boot, GetKernelImageToUse() should
+ // be used instead.
+ std::string kernel_image_path() const;
+ void set_kernel_image_path(const std::string& kernel_image_path);
+
+ bool decompress_kernel() const;
+ void set_decompress_kernel(bool decompress_kernel);
+
+ // Returns the path to the kernel image that should be given to the vm manager
+ // to boot, takes into account whether the original image was decompressed or
+ // not.
+ std::string GetKernelImageToUse() const {
+ return decompress_kernel() ? decompressed_kernel_image_path()
+ : kernel_image_path();
+ }
+
+ std::string decompressed_kernel_image_path() const;
+ void set_decompressed_kernel_image_path(const std::string& path);
+
+ bool use_unpacked_kernel() const;
+ void set_use_unpacked_kernel(bool use_unpacked_kernel);
+
+ std::string gdb_flag() const;
+ void set_gdb_flag(const std::string& gdb);
+
+ std::string ramdisk_image_path() const;
+ void set_ramdisk_image_path(const std::string& ramdisk_image_path);
+
+ std::string initramfs_path() const;
+ void set_initramfs_path(const std::string& initramfs_path);
- std::vector<DisplayConfig> display_configs() const;
- void set_display_configs(const std::vector<DisplayConfig>& display_configs);
+ std::string final_ramdisk_path() const;
+ void set_final_ramdisk_path(const std::string& final_ramdisk_path);
- int gdb_port() const;
- void set_gdb_port(int gdb_port);
+ std::string vendor_ramdisk_image_path() const;
+ void set_vendor_ramdisk_image_path(const std::string&
+ vendor_ramdisk_image_path);
bool deprecated_boot_completed() const;
void set_deprecated_boot_completed(bool deprecated_boot_completed);
+ std::string logcat_receiver_binary() const;
+ void set_logcat_receiver_binary(const std::string& binary);
+
+ std::string config_server_binary() const;
+ void set_config_server_binary(const std::string& binary);
+
void set_cuttlefish_env_path(const std::string& path);
std::string cuttlefish_env_path() const;
void set_adb_mode(const std::set<std::string>& modes);
std::set<AdbMode> adb_mode() const;
- void set_secure_hals(const std::set<std::string>& hals);
- std::set<SecureHal> secure_hals() const;
-
void set_setupwizard_mode(const std::string& title);
std::string setupwizard_mode() const;
- void set_qemu_binary_dir(const std::string& qemu_binary_dir);
- std::string qemu_binary_dir() const;
+ void set_qemu_binary(const std::string& qemu_binary);
+ std::string qemu_binary() const;
void set_crosvm_binary(const std::string& crosvm_binary);
std::string crosvm_binary() const;
- void set_tpm_device(const std::string& tpm_device);
- std::string tpm_device() const;
+ void set_console_forwarder_binary(const std::string& crosvm_binary);
+ std::string console_forwarder_binary() const;
+
+ void set_kernel_log_monitor_binary(
+ const std::string& kernel_log_monitor_binary);
+ std::string kernel_log_monitor_binary() const;
void set_enable_vnc_server(bool enable_vnc_server);
bool enable_vnc_server() const;
- void set_enable_sandbox(const bool enable_sandbox);
- bool enable_sandbox() const;
-
- void set_seccomp_policy_dir(const std::string& seccomp_policy_dir);
- std::string seccomp_policy_dir() const;
+ void set_vnc_server_binary(const std::string& vnc_server_binary);
+ std::string vnc_server_binary() const;
void set_enable_webrtc(bool enable_webrtc);
bool enable_webrtc() const;
- void set_webrtc_assets_dir(const std::string& webrtc_assets_dir);
+ void set_webrtc_binary(const std::string& webrtc_binary);
+ std::string webrtc_binary() const;
+
+ void set_webrtc_assets_dir(const std::string& webrtc_binary);
std::string webrtc_assets_dir() const;
+ void set_webrtc_public_ip(const std::string& webrtc_public_ip);
+ std::string webrtc_public_ip() const;
+
void set_webrtc_enable_adb_websocket(bool enable);
bool webrtc_enable_adb_websocket() const;
@@ -166,17 +199,17 @@ class CuttlefishConfig {
void set_vehicle_hal_grpc_server_binary(const std::string& vhal_server_binary);
std::string vehicle_hal_grpc_server_binary() const;
- void set_custom_actions(const std::vector<CustomActionConfig>& actions);
- std::vector<CustomActionConfig> custom_actions() const;
-
void set_restart_subprocesses(bool restart_subprocesses);
bool restart_subprocesses() const;
void set_run_adb_connector(bool run_adb_connector);
bool run_adb_connector() const;
- void set_enable_gnss_grpc_proxy(const bool enable_gnss_grpc_proxy);
- bool enable_gnss_grpc_proxy() const;
+ void set_adb_connector_binary(const std::string& adb_connector_binary);
+ std::string adb_connector_binary() const;
+
+ void set_socket_vsock_proxy_binary(const std::string& binary);
+ std::string socket_vsock_proxy_binary() const;
void set_run_as_daemon(bool run_as_daemon);
bool run_as_daemon() const;
@@ -190,130 +223,47 @@ class CuttlefishConfig {
void set_blank_data_image_fmt(const std::string& blank_data_image_fmt);
std::string blank_data_image_fmt() const;
+ void set_logcat_mode(const std::string& mode);
+ std::string logcat_mode() const;
+
+ void set_enable_tombstone_receiver(bool enable_tombstone_receiver);
+ bool enable_tombstone_receiver() const;
+
+ void set_tombstone_receiver_binary(const std::string& binary);
+ std::string tombstone_receiver_binary() const;
+
+ void set_use_bootloader(bool use_bootloader);
+ bool use_bootloader() const;
+
void set_bootloader(const std::string& bootloader_path);
std::string bootloader() const;
- // TODO (b/163575714) add virtio console support to the bootloader so the
- // virtio console path for the console device can be taken again. When that
- // happens, this function can be deleted along with all the code paths it
- // forces.
- bool use_bootloader() const { return true; };
-
void set_boot_slot(const std::string& boot_slot);
std::string boot_slot() const;
+ void set_loop_max_part(int loop_max_part);
+ int loop_max_part() const;
+
void set_guest_enforce_security(bool guest_enforce_security);
bool guest_enforce_security() const;
void set_guest_audit_security(bool guest_audit_security);
bool guest_audit_security() const;
- void set_enable_host_bluetooth(bool enable_host_bluetooth);
- bool enable_host_bluetooth() const;
+ void set_guest_force_normal_boot(bool guest_force_normal_boot);
+ bool guest_force_normal_boot() const;
- enum Answer {
- kUnknown = 0,
- kYes,
- kNo,
- };
-
- void set_enable_metrics(std::string enable_metrics);
- CuttlefishConfig::Answer enable_metrics() const;
-
- void set_metrics_binary(const std::string& metrics_binary);
- std::string metrics_binary() const;
+ void set_boot_image_kernel_cmdline(std::string boot_image_kernel_cmdline);
+ std::vector<std::string> boot_image_kernel_cmdline() const;
void set_extra_kernel_cmdline(std::string extra_cmdline);
std::vector<std::string> extra_kernel_cmdline() const;
- // A directory containing the SSL certificates for the signaling server
void set_webrtc_certs_dir(const std::string& certs_dir);
std::string webrtc_certs_dir() const;
- // The port for the webrtc signaling server. It's used by the signaling server
- // to bind to it and by the webrtc process to connect to and register itself
- void set_sig_server_port(int port);
- int sig_server_port() const;
-
- // The range of UDP ports available for webrtc sessions.
- void set_webrtc_udp_port_range(std::pair<uint16_t, uint16_t> range);
- std::pair<uint16_t, uint16_t> webrtc_udp_port_range() const;
-
- // The range of TCP ports available for webrtc sessions.
- void set_webrtc_tcp_port_range(std::pair<uint16_t, uint16_t> range);
- std::pair<uint16_t, uint16_t> webrtc_tcp_port_range() const;
-
- // The address of the signaling server
- void set_sig_server_address(const std::string& addr);
- std::string sig_server_address() const;
-
- // The path section of the url where the webrtc process registers itself with
- // the signaling server
- void set_sig_server_path(const std::string& path);
- std::string sig_server_path() const;
-
- // Whether the webrtc process should attempt to verify the authenticity of the
- // signaling server (reject self signed certificates)
- void set_sig_server_strict(bool strict);
- bool sig_server_strict() const;
-
- // A file containing http headers to include in the connection to the
- // signaling server
- void set_sig_server_headers_path(const std::string& path);
- std::string sig_server_headers_path() const;
-
- // The dns address of mobile network (RIL)
- void set_ril_dns(const std::string& ril_dns);
- std::string ril_dns() const;
-
- // KGDB configuration for kernel debugging
- void set_kgdb(bool kgdb);
- bool kgdb() const;
-
- // Serial console
- void set_console(bool console);
- bool console() const;
- std::string console_dev() const;
-
- // Configuration flags for a minimal device
- bool enable_minimal_mode() const;
- void set_enable_minimal_mode(bool enable_minimal_mode);
-
- void set_enable_modem_simulator(bool enable_modem_simulator);
- bool enable_modem_simulator() const;
-
- void set_modem_simulator_instance_number(int instance_numbers);
- int modem_simulator_instance_number() const;
-
- void set_modem_simulator_sim_type(int sim_type);
- int modem_simulator_sim_type() const;
-
- void set_host_tools_version(const std::map<std::string, uint32_t>&);
- std::map<std::string, uint32_t> host_tools_version() const;
-
- void set_vhost_net(bool vhost_net);
- bool vhost_net() const;
-
- void set_ethernet(bool ethernet);
- bool ethernet() const;
-
- void set_record_screen(bool record_screen);
- bool record_screen() const;
-
- void set_smt(bool smt);
- bool smt() const;
-
- void set_enable_audio(bool enable);
- bool enable_audio() const;
-
- void set_protected_vm(bool protected_vm);
- bool protected_vm() const;
-
- void set_target_arch(Arch target_arch);
- Arch target_arch() const;
-
- void set_bootconfig_supported(bool bootconfig_supported);
- bool bootconfig_supported() const;
+ void set_dialog_certs_dir(const std::string& certs_dir);
+ std::string dialog_certs_dir() const;
class InstanceSpecific;
class MutableInstanceSpecific;
@@ -339,56 +289,22 @@ class CuttlefishConfig {
const Json::Value* Dictionary() const;
public:
std::string serial_number() const;
- // If any of the following port numbers is 0, the relevant service is not
- // running on the guest.
-
- // Port number to connect to vnc server on the host
int vnc_server_port() const;
- // Port number to connect to the tombstone receiver on the host
- int tombstone_receiver_port() const;
- // Port number to connect to the config server on the host
- int config_server_port() const;
- // Port number to connect to the keyboard server on the host. (Only
- // operational if QEMU is the vmm.)
- int keyboard_server_port() const;
- // Port number to connect to the touch server on the host. (Only
- // operational if QEMU is the vmm.)
- int touch_server_port() const;
- // Port number to connect to the frame server on the host. (Only
- // operational if using swiftshader as the GPU.)
- int frames_server_port() const;
// Port number to connect to the vehicle HAL server on the host
int vehicle_hal_server_port() const;
- // Port number to connect to the audiocontrol server on the guest
- int audiocontrol_server_port() const;
- // Port number to connect to the adb server on the host
int host_port() const;
- // Port number to connect to the gnss grpc proxy server on the host
- int gnss_grpc_proxy_server_port() const;
std::string adb_ip_and_port() const;
- // Port number to connect to the root-canal on the host
- int rootcanal_hci_port() const;
- int rootcanal_link_port() const;
- int rootcanal_test_port() const;
- std::string rootcanal_config_file() const;
- std::string rootcanal_default_commands_file() const;
-
std::string adb_device_name() const;
std::string device_title() const;
- std::string gnss_file_path() const;
std::string mobile_bridge_name() const;
std::string mobile_tap_name() const;
std::string wifi_tap_name() const;
- std::string ethernet_tap_name() const;
- uint32_t session_id() const;
- bool use_allocd() const;
int vsock_guest_cid() const;
std::string uuid() const;
std::string instance_name() const;
std::vector<std::string> virtual_disk_paths() const;
- // Returns the path to a file with the given name in the instance
- // directory..
+ // Returns the path to a file with the given name in the instance directory..
std::string PerInstancePath(const char* file_name) const;
std::string PerInstanceInternalPath(const char* file_name) const;
@@ -398,31 +314,17 @@ class CuttlefishConfig {
std::string touch_socket_path() const;
std::string keyboard_socket_path() const;
- std::string switches_socket_path() const;
std::string frames_socket_path() const;
- // mock hal guest socket that will be vsock/virtio later on
- std::string confui_hal_guest_socket_path() const;
-
std::string access_kregistry_path() const;
- std::string pstore_path() const;
-
std::string console_path() const;
std::string logcat_path() const;
std::string kernel_log_pipe_name() const;
- std::string console_pipe_prefix() const;
- std::string console_in_pipe_name() const;
- std::string console_out_pipe_name() const;
-
- std::string gnss_pipe_prefix() const;
- std::string gnss_in_pipe_name() const;
- std::string gnss_out_pipe_name() const;
-
- std::string logcat_pipe_name() const;
+ std::string console_pipe_name() const;
std::string launcher_log_path() const;
@@ -430,32 +332,8 @@ class CuttlefishConfig {
std::string sdcard_path() const;
- std::string os_composite_disk_path() const;
-
- std::string persistent_composite_disk_path() const;
-
- std::string uboot_env_image_path() const;
-
- std::string vendor_boot_image_path() const;
-
- std::string audio_server_path() const;
-
- // modem simulator related
- std::string modem_simulator_ports() const;
-
- // The device id the webrtc process should use to register with the
- // signaling server
- std::string webrtc_device_id() const;
-
- // Whether this instance should start the webrtc signaling server
- bool start_webrtc_sig_server() const;
-
// Wifi MAC address inside the guest
std::array<unsigned char, 6> wifi_mac_address() const;
-
- std::string factory_reset_protected_path() const;
-
- std::string persistent_bootconfig_path() const;
};
// A view into an existing CuttlefishConfig object for a particular instance.
@@ -471,44 +349,19 @@ class CuttlefishConfig {
public:
void set_serial_number(const std::string& serial_number);
void set_vnc_server_port(int vnc_server_port);
- void set_tombstone_receiver_port(int tombstone_receiver_port);
- void set_config_server_port(int config_server_port);
- void set_frames_server_port(int config_server_port);
- void set_touch_server_port(int config_server_port);
- void set_keyboard_server_port(int config_server_port);
- void set_gatekeeper_vsock_port(int gatekeeper_vsock_port);
- void set_keymaster_vsock_port(int keymaster_vsock_port);
void set_vehicle_hal_server_port(int vehicle_server_port);
- void set_audiocontrol_server_port(int audiocontrol_server_port);
void set_host_port(int host_port);
void set_adb_ip_and_port(const std::string& ip_port);
- void set_rootcanal_hci_port(int rootcanal_hci_port);
- void set_rootcanal_link_port(int rootcanal_link_port);
- void set_rootcanal_test_port(int rootcanal_test_port);
- void set_rootcanal_config_file(const std::string& rootcanal_config_file);
- void set_rootcanal_default_commands_file(
- const std::string& rootcanal_default_commands_file);
void set_device_title(const std::string& title);
void set_mobile_bridge_name(const std::string& mobile_bridge_name);
void set_mobile_tap_name(const std::string& mobile_tap_name);
void set_wifi_tap_name(const std::string& wifi_tap_name);
- void set_ethernet_tap_name(const std::string& ethernet_tap_name);
- void set_session_id(uint32_t session_id);
- void set_use_allocd(bool use_allocd);
void set_vsock_guest_cid(int vsock_guest_cid);
void set_uuid(const std::string& uuid);
void set_instance_dir(const std::string& instance_dir);
- // modem simulator related
- void set_modem_simulator_ports(const std::string& modem_simulator_ports);
void set_virtual_disk_paths(const std::vector<std::string>& disk_paths);
- void set_webrtc_device_id(const std::string& id);
- void set_start_webrtc_signaling_server(bool start);
// Wifi MAC address inside the guest
void set_wifi_mac_address(const std::array<unsigned char, 6>&);
- // Gnss grpc proxy server port inside the host
- void set_gnss_grpc_proxy_server_port(int gnss_grpc_proxy_server_port);
- // Gnss grpc proxy local file path
- void set_gnss_file_path(const std::string &gnss_file_path);
};
private:
@@ -525,16 +378,6 @@ class CuttlefishConfig {
// Returns the instance number as obtained from the CUTTLEFISH_INSTANCE
// environment variable or the username.
int GetInstance();
-
-// Returns default Vsock CID, which is
-// GetInstance() + 2
-int GetDefaultVsockCid();
-
-// Calculates vsock server port number
-// return base + (vsock_guest_cid - 3)
-int GetVsockServerPort(const int base,
- const int vsock_guest_cid);
-
// Returns a path where the launhcer puts a link to the config file which makes
// it easily discoverable regardless of what vm manager is in use
std::string GetGlobalConfigFileLink();
@@ -545,11 +388,14 @@ std::string GetGlobalConfigFileLink();
std::string ForCurrentInstance(const char* prefix);
int ForCurrentInstance(int base);
-// Returns a random serial number appeneded to a given prefix.
+// Returns a random serial number appended to a given prefix.
std::string RandomSerialNumber(const std::string& prefix);
+std::string GetDefaultPerInstanceDir();
+std::string GetDefaultMempath();
+int GetDefaultPerInstanceVsockCid();
+
std::string DefaultHostArtifactsPath(const std::string& file);
-std::string HostBinaryPath(const std::string& file);
std::string DefaultGuestImagePath(const std::string& file);
std::string DefaultEnvironmentPath(const char* environment_key,
const char* default_value,
@@ -557,10 +403,10 @@ std::string DefaultEnvironmentPath(const char* environment_key,
// Whether the host supports qemu
bool HostSupportsQemuCli();
+bool HostSupportsVsock();
// GPU modes
-extern const char* const kGpuModeAuto;
extern const char* const kGpuModeGuestSwiftshader;
extern const char* const kGpuModeDrmVirgl;
extern const char* const kGpuModeGfxStream;
-} // namespace cuttlefish
+} // namespace vsoc
diff --git a/host/libs/config/cuttlefish_config_instance.cpp b/host/libs/config/cuttlefish_config_instance.cpp
deleted file mode 100644
index 97b350360..000000000
--- a/host/libs/config/cuttlefish_config_instance.cpp
+++ /dev/null
@@ -1,498 +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.
- */
-
-#include "host/libs/config/cuttlefish_config.h"
-
-#include <android-base/logging.h>
-#include <json/json.h>
-
-#include "common/libs/utils/files.h"
-
-namespace cuttlefish {
-namespace {
-
-const char* kInstances = "instances";
-
-} // namespace
-
-Json::Value* CuttlefishConfig::MutableInstanceSpecific::Dictionary() {
- return &(*config_->dictionary_)[kInstances][id_];
-}
-
-const Json::Value* CuttlefishConfig::InstanceSpecific::Dictionary() const {
- return &(*config_->dictionary_)[kInstances][id_];
-}
-
-static constexpr char kInstanceDir[] = "instance_dir";
-std::string CuttlefishConfig::InstanceSpecific::instance_dir() const {
- return (*Dictionary())[kInstanceDir].asString();
-}
-void CuttlefishConfig::MutableInstanceSpecific::set_instance_dir(
- const std::string& instance_dir) {
- (*Dictionary())[kInstanceDir] = instance_dir;
-}
-
-std::string CuttlefishConfig::InstanceSpecific::instance_internal_dir() const {
- return PerInstancePath(kInternalDirName);
-}
-
-static constexpr char kSerialNumber[] = "serial_number";
-std::string CuttlefishConfig::InstanceSpecific::serial_number() const {
- return (*Dictionary())[kSerialNumber].asString();
-}
-void CuttlefishConfig::MutableInstanceSpecific::set_serial_number(
- const std::string& serial_number) {
- (*Dictionary())[kSerialNumber] = serial_number;
-}
-
-static constexpr char kVirtualDiskPaths[] = "virtual_disk_paths";
-std::vector<std::string> CuttlefishConfig::InstanceSpecific::virtual_disk_paths() const {
- std::vector<std::string> virtual_disks;
- auto virtual_disks_json_obj = (*Dictionary())[kVirtualDiskPaths];
- for (const auto& disk : virtual_disks_json_obj) {
- virtual_disks.push_back(disk.asString());
- }
- return virtual_disks;
-}
-void CuttlefishConfig::MutableInstanceSpecific::set_virtual_disk_paths(
- const std::vector<std::string>& virtual_disk_paths) {
- Json::Value virtual_disks_json_obj(Json::arrayValue);
- for (const auto& arg : virtual_disk_paths) {
- virtual_disks_json_obj.append(arg);
- }
- (*Dictionary())[kVirtualDiskPaths] = virtual_disks_json_obj;
-}
-
-std::string CuttlefishConfig::InstanceSpecific::kernel_log_pipe_name() const {
- return AbsolutePath(PerInstanceInternalPath("kernel-log-pipe"));
-}
-
-std::string CuttlefishConfig::InstanceSpecific::console_pipe_prefix() const {
- return AbsolutePath(PerInstanceInternalPath("console"));
-}
-
-std::string CuttlefishConfig::InstanceSpecific::console_in_pipe_name() const {
- return console_pipe_prefix() + ".in";
-}
-
-std::string CuttlefishConfig::InstanceSpecific::console_out_pipe_name() const {
- return console_pipe_prefix() + ".out";
-}
-
-std::string CuttlefishConfig::InstanceSpecific::gnss_pipe_prefix() const {
- return AbsolutePath(PerInstanceInternalPath("gnss"));
-}
-
-std::string CuttlefishConfig::InstanceSpecific::gnss_in_pipe_name() const {
- return gnss_pipe_prefix() + ".in";
-}
-
-std::string CuttlefishConfig::InstanceSpecific::gnss_out_pipe_name() const {
- return gnss_pipe_prefix() + ".out";
-}
-
-static constexpr char kGnssGrpcProxyServerPort[] =
- "gnss_grpc_proxy_server_port";
-int CuttlefishConfig::InstanceSpecific::gnss_grpc_proxy_server_port() const {
- return (*Dictionary())[kGnssGrpcProxyServerPort].asInt();
-}
-void CuttlefishConfig::MutableInstanceSpecific::set_gnss_grpc_proxy_server_port(
- int gnss_grpc_proxy_server_port) {
- (*Dictionary())[kGnssGrpcProxyServerPort] = gnss_grpc_proxy_server_port;
-}
-
-static constexpr char kGnssFilePath[] = "gnss_file_path";
-std::string CuttlefishConfig::InstanceSpecific::gnss_file_path() const {
- return (*Dictionary())[kGnssFilePath].asString();
-}
-void CuttlefishConfig::MutableInstanceSpecific::set_gnss_file_path(
- const std::string& gnss_file_path) {
- (*Dictionary())[kGnssFilePath] = gnss_file_path;
-}
-
-std::string CuttlefishConfig::InstanceSpecific::logcat_pipe_name() const {
- return AbsolutePath(PerInstanceInternalPath("logcat-pipe"));
-}
-
-std::string CuttlefishConfig::InstanceSpecific::access_kregistry_path() const {
- return AbsolutePath(PerInstancePath("access-kregistry"));
-}
-
-std::string CuttlefishConfig::InstanceSpecific::pstore_path() const {
- return AbsolutePath(PerInstancePath("pstore"));
-}
-
-std::string CuttlefishConfig::InstanceSpecific::console_path() const {
- return AbsolutePath(PerInstancePath("console"));
-}
-
-std::string CuttlefishConfig::InstanceSpecific::logcat_path() const {
- return AbsolutePath(PerInstancePath("logcat"));
-}
-
-std::string CuttlefishConfig::InstanceSpecific::launcher_monitor_socket_path()
- const {
- return AbsolutePath(PerInstancePath("launcher_monitor.sock"));
-}
-
-static constexpr char kModemSimulatorPorts[] = "modem_simulator_ports";
-std::string CuttlefishConfig::InstanceSpecific::modem_simulator_ports() const {
- return (*Dictionary())[kModemSimulatorPorts].asString();
-}
-void CuttlefishConfig::MutableInstanceSpecific::set_modem_simulator_ports(
- const std::string& modem_simulator_ports) {
- (*Dictionary())[kModemSimulatorPorts] = modem_simulator_ports;
-}
-
-std::string CuttlefishConfig::InstanceSpecific::launcher_log_path() const {
- return AbsolutePath(PerInstancePath("launcher.log"));
-}
-
-std::string CuttlefishConfig::InstanceSpecific::sdcard_path() const {
- return AbsolutePath(PerInstancePath("sdcard.img"));
-}
-
-std::string CuttlefishConfig::InstanceSpecific::os_composite_disk_path() const {
- return AbsolutePath(PerInstancePath("os_composite.img"));
-}
-
-std::string CuttlefishConfig::InstanceSpecific::persistent_composite_disk_path()
- const {
- return AbsolutePath(PerInstancePath("persistent_composite.img"));
-}
-
-std::string CuttlefishConfig::InstanceSpecific::uboot_env_image_path() const {
- return AbsolutePath(PerInstancePath("uboot_env.img"));
-}
-
-std::string CuttlefishConfig::InstanceSpecific::vendor_boot_image_path() const {
- return AbsolutePath(PerInstancePath("vendor_boot_repacked.img"));
-}
-
-static constexpr char kMobileBridgeName[] = "mobile_bridge_name";
-
-std::string CuttlefishConfig::InstanceSpecific::audio_server_path() const {
- return AbsolutePath(PerInstanceInternalPath("audio_server.sock"));
-}
-
-std::string CuttlefishConfig::InstanceSpecific::mobile_bridge_name() const {
- return (*Dictionary())[kMobileBridgeName].asString();
-}
-void CuttlefishConfig::MutableInstanceSpecific::set_mobile_bridge_name(
- const std::string& mobile_bridge_name) {
- (*Dictionary())[kMobileBridgeName] = mobile_bridge_name;
-}
-
-static constexpr char kMobileTapName[] = "mobile_tap_name";
-std::string CuttlefishConfig::InstanceSpecific::mobile_tap_name() const {
- return (*Dictionary())[kMobileTapName].asString();
-}
-void CuttlefishConfig::MutableInstanceSpecific::set_mobile_tap_name(
- const std::string& mobile_tap_name) {
- (*Dictionary())[kMobileTapName] = mobile_tap_name;
-}
-
-std::string CuttlefishConfig::InstanceSpecific::confui_hal_guest_socket_path()
- const {
- return PerInstanceInternalPath("confui_mock_hal_guest.sock");
-}
-
-static constexpr char kWifiTapName[] = "wifi_tap_name";
-std::string CuttlefishConfig::InstanceSpecific::wifi_tap_name() const {
- return (*Dictionary())[kWifiTapName].asString();
-}
-void CuttlefishConfig::MutableInstanceSpecific::set_wifi_tap_name(
- const std::string& wifi_tap_name) {
- (*Dictionary())[kWifiTapName] = wifi_tap_name;
-}
-
-static constexpr char kEthernetTapName[] = "ethernet_tap_name";
-std::string CuttlefishConfig::InstanceSpecific::ethernet_tap_name() const {
- return (*Dictionary())[kEthernetTapName].asString();
-}
-void CuttlefishConfig::MutableInstanceSpecific::set_ethernet_tap_name(
- const std::string& ethernet_tap_name) {
- (*Dictionary())[kEthernetTapName] = ethernet_tap_name;
-}
-
-static constexpr char kUseAllocd[] = "use_allocd";
-bool CuttlefishConfig::InstanceSpecific::use_allocd() const {
- return (*Dictionary())[kUseAllocd].asBool();
-}
-void CuttlefishConfig::MutableInstanceSpecific::set_use_allocd(
- bool use_allocd) {
- (*Dictionary())[kUseAllocd] = use_allocd;
-}
-
-static constexpr char kSessionId[] = "session_id";
-uint32_t CuttlefishConfig::InstanceSpecific::session_id() const {
- return (*Dictionary())[kSessionId].asUInt();
-}
-void CuttlefishConfig::MutableInstanceSpecific::set_session_id(
- uint32_t session_id) {
- (*Dictionary())[kSessionId] = session_id;
-}
-
-static constexpr char kVsockGuestCid[] = "vsock_guest_cid";
-int CuttlefishConfig::InstanceSpecific::vsock_guest_cid() const {
- return (*Dictionary())[kVsockGuestCid].asInt();
-}
-void CuttlefishConfig::MutableInstanceSpecific::set_vsock_guest_cid(
- int vsock_guest_cid) {
- (*Dictionary())[kVsockGuestCid] = vsock_guest_cid;
-}
-
-static constexpr char kUuid[] = "uuid";
-std::string CuttlefishConfig::InstanceSpecific::uuid() const {
- return (*Dictionary())[kUuid].asString();
-}
-void CuttlefishConfig::MutableInstanceSpecific::set_uuid(const std::string& uuid) {
- (*Dictionary())[kUuid] = uuid;
-}
-
-static constexpr char kHostPort[] = "host_port";
-int CuttlefishConfig::InstanceSpecific::host_port() const {
- return (*Dictionary())[kHostPort].asInt();
-}
-void CuttlefishConfig::MutableInstanceSpecific::set_host_port(int host_port) {
- (*Dictionary())[kHostPort] = host_port;
-}
-
-static constexpr char kAdbIPAndPort[] = "adb_ip_and_port";
-std::string CuttlefishConfig::InstanceSpecific::adb_ip_and_port() const {
- return (*Dictionary())[kAdbIPAndPort].asString();
-}
-void CuttlefishConfig::MutableInstanceSpecific::set_adb_ip_and_port(
- const std::string& ip_port) {
- (*Dictionary())[kAdbIPAndPort] = ip_port;
-}
-
-std::string CuttlefishConfig::InstanceSpecific::adb_device_name() const {
- if (adb_ip_and_port() != "") {
- return adb_ip_and_port();
- }
- LOG(ERROR) << "no adb_mode found, returning bad device name";
- return "NO_ADB_MODE_SET_NO_VALID_DEVICE_NAME";
-}
-
-static constexpr char kDeviceTitle[] = "device_title";
-std::string CuttlefishConfig::InstanceSpecific::device_title() const {
- return (*Dictionary())[kDeviceTitle].asString();
-}
-void CuttlefishConfig::MutableInstanceSpecific::set_device_title(
- const std::string& title) {
- (*Dictionary())[kDeviceTitle] = title;
-}
-
-static constexpr char kVncServerPort[] = "vnc_server_port";
-int CuttlefishConfig::InstanceSpecific::vnc_server_port() const {
- return (*Dictionary())[kVncServerPort].asInt();
-}
-void CuttlefishConfig::MutableInstanceSpecific::set_vnc_server_port(int vnc_server_port) {
- (*Dictionary())[kVncServerPort] = vnc_server_port;
-}
-
-static constexpr char kFramesServerPort[] = "frames_server_port";
-int CuttlefishConfig::InstanceSpecific::frames_server_port() const {
- return (*Dictionary())[kFramesServerPort].asInt();
-}
-void CuttlefishConfig::MutableInstanceSpecific::set_frames_server_port(int frames_server_port) {
- (*Dictionary())[kFramesServerPort] = frames_server_port;
-}
-
-static constexpr char kTouchServerPort[] = "touch_server_port";
-int CuttlefishConfig::InstanceSpecific::touch_server_port() const {
- return (*Dictionary())[kTouchServerPort].asInt();
-}
-
-void CuttlefishConfig::MutableInstanceSpecific::set_touch_server_port(int touch_server_port) {
- (*Dictionary())[kTouchServerPort] = touch_server_port;
-}
-
-static constexpr char kKeyboardServerPort[] = "keyboard_server_port";
-int CuttlefishConfig::InstanceSpecific::keyboard_server_port() const {
- return (*Dictionary())[kKeyboardServerPort].asInt();
-}
-void CuttlefishConfig::MutableInstanceSpecific::set_keyboard_server_port(int keyboard_server_port) {
- (*Dictionary())[kKeyboardServerPort] = keyboard_server_port;
-}
-
-static constexpr char kTombstoneReceiverPort[] = "tombstone_receiver_port";
-int CuttlefishConfig::InstanceSpecific::tombstone_receiver_port() const {
- return (*Dictionary())[kTombstoneReceiverPort].asInt();
-}
-void CuttlefishConfig::MutableInstanceSpecific::set_tombstone_receiver_port(int tombstone_receiver_port) {
- (*Dictionary())[kTombstoneReceiverPort] = tombstone_receiver_port;
-}
-
-static constexpr char kVehicleHalServerPort[] = "vehicle_hal_server_port";
-int CuttlefishConfig::InstanceSpecific::vehicle_hal_server_port() const {
- return (*Dictionary())[kVehicleHalServerPort].asInt();
-}
-void CuttlefishConfig::MutableInstanceSpecific::set_vehicle_hal_server_port(int vehicle_hal_server_port) {
- (*Dictionary())[kVehicleHalServerPort] = vehicle_hal_server_port;
-}
-
-static constexpr char kAudioControlServerPort[] = "audiocontrol_server_port";
-int CuttlefishConfig::InstanceSpecific::audiocontrol_server_port() const {
- return (*Dictionary())[kAudioControlServerPort].asInt();
-}
-void CuttlefishConfig::MutableInstanceSpecific::set_audiocontrol_server_port(int audiocontrol_server_port) {
- (*Dictionary())[kAudioControlServerPort] = audiocontrol_server_port;
-}
-
-static constexpr char kConfigServerPort[] = "config_server_port";
-int CuttlefishConfig::InstanceSpecific::config_server_port() const {
- return (*Dictionary())[kConfigServerPort].asInt();
-}
-void CuttlefishConfig::MutableInstanceSpecific::set_config_server_port(int config_server_port) {
- (*Dictionary())[kConfigServerPort] = config_server_port;
-}
-
-static constexpr char kRootcanalHciPort[] = "rootcanal_hci_port";
-int CuttlefishConfig::InstanceSpecific::rootcanal_hci_port() const {
- return (*Dictionary())[kRootcanalHciPort].asInt();
-}
-void CuttlefishConfig::MutableInstanceSpecific::set_rootcanal_hci_port(
- int rootcanal_hci_port) {
- (*Dictionary())[kRootcanalHciPort] = rootcanal_hci_port;
-}
-
-static constexpr char kRootcanalLinkPort[] = "rootcanal_link_port";
-int CuttlefishConfig::InstanceSpecific::rootcanal_link_port() const {
- return (*Dictionary())[kRootcanalLinkPort].asInt();
-}
-void CuttlefishConfig::MutableInstanceSpecific::set_rootcanal_link_port(
- int rootcanal_link_port) {
- (*Dictionary())[kRootcanalLinkPort] = rootcanal_link_port;
-}
-
-static constexpr char kRootcanalTestPort[] = "rootcanal_test_port";
-int CuttlefishConfig::InstanceSpecific::rootcanal_test_port() const {
- return (*Dictionary())[kRootcanalTestPort].asInt();
-}
-void CuttlefishConfig::MutableInstanceSpecific::set_rootcanal_test_port(
- int rootcanal_test_port) {
- (*Dictionary())[kRootcanalTestPort] = rootcanal_test_port;
-}
-
-static constexpr char kRootcanalConfigFile[] = "rootcanal_config_file";
-std::string CuttlefishConfig::InstanceSpecific::rootcanal_config_file() const {
- return (*Dictionary())[kRootcanalConfigFile].asString();
-}
-void CuttlefishConfig::MutableInstanceSpecific::set_rootcanal_config_file(
- const std::string& rootcanal_config_file) {
- (*Dictionary())[kRootcanalConfigFile] =
- DefaultHostArtifactsPath(rootcanal_config_file);
-}
-
-static constexpr char kRootcanalDefaultCommandsFile[] =
- "rootcanal_default_commands_file";
-std::string
-CuttlefishConfig::InstanceSpecific::rootcanal_default_commands_file() const {
- return (*Dictionary())[kRootcanalDefaultCommandsFile].asString();
-}
-void CuttlefishConfig::MutableInstanceSpecific::
- set_rootcanal_default_commands_file(
- const std::string& rootcanal_default_commands_file) {
- (*Dictionary())[kRootcanalDefaultCommandsFile] =
- DefaultHostArtifactsPath(rootcanal_default_commands_file);
-}
-
-static constexpr char kWebrtcDeviceId[] = "webrtc_device_id";
-void CuttlefishConfig::MutableInstanceSpecific::set_webrtc_device_id(
- const std::string& id) {
- (*Dictionary())[kWebrtcDeviceId] = id;
-}
-std::string CuttlefishConfig::InstanceSpecific::webrtc_device_id() const {
- return (*Dictionary())[kWebrtcDeviceId].asString();
-}
-
-static constexpr char kStartSigServer[] = "webrtc_start_sig_server";
-void CuttlefishConfig::MutableInstanceSpecific::set_start_webrtc_signaling_server(bool start) {
- (*Dictionary())[kStartSigServer] = start;
-}
-bool CuttlefishConfig::InstanceSpecific::start_webrtc_sig_server() const {
- return (*Dictionary())[kStartSigServer].asBool();
-}
-
-std::string CuttlefishConfig::InstanceSpecific::touch_socket_path() const {
- return PerInstanceInternalPath("touch.sock");
-}
-
-std::string CuttlefishConfig::InstanceSpecific::keyboard_socket_path() const {
- return PerInstanceInternalPath("keyboard.sock");
-}
-
-std::string CuttlefishConfig::InstanceSpecific::switches_socket_path() const {
- return PerInstanceInternalPath("switches.sock");
-}
-
-std::string CuttlefishConfig::InstanceSpecific::frames_socket_path() const {
- return PerInstanceInternalPath("frames.sock");
-}
-
-static constexpr char kWifiMacAddress[] = "wifi_mac_address";
-void CuttlefishConfig::MutableInstanceSpecific::set_wifi_mac_address(
- const std::array<unsigned char, 6>& mac_address) {
- Json::Value mac_address_obj(Json::arrayValue);
- for (const auto& num : mac_address) {
- mac_address_obj.append(num);
- }
- (*Dictionary())[kWifiMacAddress] = mac_address_obj;
-}
-std::array<unsigned char, 6> CuttlefishConfig::InstanceSpecific::wifi_mac_address() const {
- std::array<unsigned char, 6> mac_address{0, 0, 0, 0, 0, 0};
- auto mac_address_obj = (*Dictionary())[kWifiMacAddress];
- if (mac_address_obj.size() != 6) {
- LOG(ERROR) << kWifiMacAddress << " entry had wrong size";
- return {};
- }
- for (int i = 0; i < 6; i++) {
- mac_address[i] = mac_address_obj[i].asInt();
- }
- return mac_address;
-}
-
-std::string CuttlefishConfig::InstanceSpecific::factory_reset_protected_path() const {
- return PerInstanceInternalPath("factory_reset_protected.img");
-}
-
-std::string CuttlefishConfig::InstanceSpecific::persistent_bootconfig_path()
- const {
- return PerInstanceInternalPath("bootconfig");
-}
-
-std::string CuttlefishConfig::InstanceSpecific::PerInstancePath(
- const char* file_name) const {
- return (instance_dir() + "/") + file_name;
-}
-
-std::string CuttlefishConfig::InstanceSpecific::PerInstanceInternalPath(
- const char* file_name) const {
- if (file_name[0] == '\0') {
- // Don't append a / if file_name is empty.
- return PerInstancePath(kInternalDirName);
- }
- auto relative_path = (std::string(kInternalDirName) + "/") + file_name;
- return PerInstancePath(relative_path.c_str());
-}
-
-std::string CuttlefishConfig::InstanceSpecific::instance_name() const {
- return "cvd-" + id_;
-}
-
-} // namespace cuttlefish
diff --git a/host/libs/config/data_image.h b/host/libs/config/data_image.h
deleted file mode 100644
index 6a6a81010..000000000
--- a/host/libs/config/data_image.h
+++ /dev/null
@@ -1,21 +0,0 @@
-#pragma once
-
-#include <string>
-
-#include "host/libs/config/cuttlefish_config.h"
-
-namespace cuttlefish {
-
-enum class DataImageResult {
- Error,
- NoChange,
- FileUpdated,
-};
-
-DataImageResult ApplyDataImagePolicy(const CuttlefishConfig& config,
- const std::string& path);
-bool InitializeMiscImage(const std::string& misc_image);
-void CreateBlankImage(
- const std::string& image, int num_mb, const std::string& image_fmt);
-
-} // namespace cuttlefish
diff --git a/host/libs/config/fetcher_config.cpp b/host/libs/config/fetcher_config.cpp
index e58c37843..7e220b5f9 100644
--- a/host/libs/config/fetcher_config.cpp
+++ b/host/libs/config/fetcher_config.cpp
@@ -28,7 +28,7 @@
#include "common/libs/utils/files.h"
-namespace cuttlefish {
+namespace cvd {
namespace {
@@ -111,16 +111,16 @@ bool FetcherConfig::SaveToFile(const std::string& file) const {
}
bool FetcherConfig::LoadFromFile(const std::string& file) {
- auto real_file_path = AbsolutePath(file);
+ auto real_file_path = cvd::AbsolutePath(file);
if (real_file_path.empty()) {
LOG(ERROR) << "Could not get real path for file " << file;
return false;
}
- Json::CharReaderBuilder builder;
+ Json::Reader reader;
std::ifstream ifs(real_file_path);
- std::string errorMessage;
- if (!Json::parseFromStream(builder, ifs, dictionary_.get(), &errorMessage)) {
- LOG(ERROR) << "Could not read config file " << file << ": " << errorMessage;
+ if (!reader.parse(ifs, *dictionary_)) {
+ LOG(ERROR) << "Could not read config file " << file << ": "
+ << reader.getFormattedErrorMessages();
return false;
}
return true;
@@ -209,8 +209,8 @@ std::string FetcherConfig::FindCvdFileWithSuffix(const std::string& suffix) cons
return file;
}
}
- LOG(DEBUG) << "Could not find file ending in " << suffix;
+ LOG(ERROR) << "Could not find file ending in " << suffix;
return "";
}
-} // namespace cuttlefish
+} // namespace cvd
diff --git a/host/libs/config/fetcher_config.h b/host/libs/config/fetcher_config.h
index c15134c25..825fbc608 100644
--- a/host/libs/config/fetcher_config.h
+++ b/host/libs/config/fetcher_config.h
@@ -23,7 +23,7 @@ namespace Json {
class Value;
}
-namespace cuttlefish {
+namespace cvd {
// Order in enum is not guaranteed to be stable, serialized as a string.
enum FileSource {
@@ -33,7 +33,6 @@ enum FileSource {
KERNEL_BUILD,
LOCAL_FILE,
GENERATED,
- BOOTLOADER_BUILD,
};
/*
@@ -83,4 +82,4 @@ public:
std::string FindCvdFileWithSuffix(const std::string& suffix) const;
};
-} // namespace cuttlefish
+} // namespace cvd
diff --git a/host/libs/config/host_tools_version.cpp b/host/libs/config/host_tools_version.cpp
deleted file mode 100644
index 58f0657b3..000000000
--- a/host/libs/config/host_tools_version.cpp
+++ /dev/null
@@ -1,82 +0,0 @@
-//
-// Copyright (C) 2020 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 "host/libs/config/host_tools_version.h"
-
-#include <algorithm>
-#include <fstream>
-#include <future>
-#include <vector>
-
-#include <zlib.h>
-
-#include "common/libs/utils/files.h"
-#include "host/libs/config/cuttlefish_config.h"
-
-using std::uint32_t;
-
-namespace cuttlefish {
-
-static uint32_t FileCrc(const std::string& path) {
- uint32_t crc = crc32(0, (unsigned char*) path.c_str(), path.size());
- std::ifstream file_stream(path, std::ifstream::binary);
- std::vector<char> data(1024, 0);
- while (file_stream) {
- file_stream.read(data.data(), data.size());
- crc = crc32(crc, (unsigned char*) data.data(), file_stream.gcount());
- }
- return crc;
-}
-
-static std::map<std::string, uint32_t> DirectoryCrc(const std::string& path) {
- auto full_path = DefaultHostArtifactsPath(path);
- if (!DirectoryExists(full_path)) {
- return {};
- }
- std::vector<std::string> files = DirectoryContents(full_path);
- for (auto it = files.begin(); it != files.end();) {
- if (*it == "." || *it == "..") {
- it = files.erase(it);
- } else {
- it++;
- }
- }
- std::vector<std::future<uint32_t>> calculations;
- for (auto& file : files) {
- file = path + "/" + file; // mutate in place in files vector
- calculations.emplace_back(
- std::async(FileCrc, DefaultHostArtifactsPath(file)));
- }
- std::map<std::string, uint32_t> crcs;
- for (int i = 0; i < files.size(); i++) {
- crcs[files[i]] = calculations[i].get();
- }
- return crcs;
-}
-
-std::map<std::string, uint32_t> HostToolsCrc() {
- auto bin_future = std::async(DirectoryCrc, "bin");
- auto lib_future = std::async(DirectoryCrc, "lib64");
- std::map<std::string, uint32_t> all_crcs;
- for (auto const& [file, crc] : bin_future.get()) {
- all_crcs[file] = crc;
- }
- for (auto const& [file, crc] : lib_future.get()) {
- all_crcs[file] = crc;
- }
- return all_crcs;
-}
-
-} // namespace cuttlefish
diff --git a/host/libs/config/kernel_args.cpp b/host/libs/config/kernel_args.cpp
deleted file mode 100644
index 421950a00..000000000
--- a/host/libs/config/kernel_args.cpp
+++ /dev/null
@@ -1,120 +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.
- */
-
-#include "host/libs/config/kernel_args.h"
-
-#include <array>
-#include <sstream>
-#include <string>
-#include <vector>
-
-#include "common/libs/utils/environment.h"
-#include "common/libs/utils/files.h"
-#include "host/libs/config/cuttlefish_config.h"
-#include "host/libs/vm_manager/qemu_manager.h"
-#include "host/libs/vm_manager/vm_manager.h"
-
-namespace cuttlefish {
-
-using vm_manager::QemuManager;
-
-namespace {
-
-template<typename T>
-void AppendVector(std::vector<T>* destination, const std::vector<T>& source) {
- destination->insert(destination->end(), source.begin(), source.end());
-}
-
-// TODO(schuffelen): Move more of this into host/libs/vm_manager, as a
-// substitute for the vm_manager comparisons.
-std::vector<std::string> VmManagerKernelCmdline(const CuttlefishConfig& config) {
- std::vector<std::string> vm_manager_cmdline;
- if (config.vm_manager() == QemuManager::name() || config.use_bootloader()) {
- // crosvm sets up the console= earlycon= panic= flags for us if booting straight to
- // the kernel, but QEMU and the bootloader via crosvm does not.
- AppendVector(&vm_manager_cmdline, {"console=hvc0", "panic=-1"});
- Arch target_arch = config.target_arch();
- if (target_arch == Arch::Arm64 || target_arch == Arch::Arm) {
- if (config.vm_manager() == QemuManager::name()) {
- // To update the pl011 address:
- // $ qemu-system-aarch64 -machine virt -cpu cortex-a57 -machine dumpdtb=virt.dtb
- // $ dtc -O dts -o virt.dts -I dtb virt.dtb
- // In the virt.dts file, look for a uart node
- vm_manager_cmdline.push_back(" earlycon=pl011,mmio32,0x9000000");
- } else {
- // Crosvm ARM only supports earlycon uart over mmio.
- vm_manager_cmdline.push_back(" earlycon=uart8250,mmio,0x3f8");
- }
- } else {
- // To update the uart8250 address:
- // $ qemu-system-x86_64 -kernel bzImage -serial stdio | grep ttyS0
- // Only 'io' mode works; mmio and mmio32 do not
- vm_manager_cmdline.push_back("earlycon=uart8250,io,0x3f8");
-
- if (config.vm_manager() == QemuManager::name()) {
- // crosvm doesn't support ACPI PNP, but QEMU does. We need to disable
- // it on QEMU so that the ISA serial ports aren't claimed by ACPI, so
- // we can use serdev with platform devices instead
- vm_manager_cmdline.push_back("pnpacpi=off");
-
- // crosvm sets up the ramoops.xx= flags for us, but QEMU does not.
- // See external/crosvm/x86_64/src/lib.rs
- // this feature is not supported on aarch64
- vm_manager_cmdline.push_back("ramoops.mem_address=0x100000000");
- vm_manager_cmdline.push_back("ramoops.mem_size=0x200000");
- vm_manager_cmdline.push_back("ramoops.console_size=0x80000");
- vm_manager_cmdline.push_back("ramoops.record_size=0x80000");
- vm_manager_cmdline.push_back("ramoops.dump_oops=1");
- } else {
- // crosvm requires these additional parameters on x86_64 in bootloader mode
- AppendVector(&vm_manager_cmdline, {"pci=noacpi", "reboot=k"});
- }
- }
- }
-
- if (config.console() && config.kgdb()) {
- AppendVector(&vm_manager_cmdline, {"kgdboc_earlycon", "kgdbcon",
- "kgdboc=" + config.console_dev()});
- }
- return vm_manager_cmdline;
-}
-
-} // namespace
-
-std::vector<std::string> KernelCommandLineFromConfig(
- const CuttlefishConfig& config) {
- std::vector<std::string> kernel_cmdline;
-
- AppendVector(&kernel_cmdline, VmManagerKernelCmdline(config));
-
- if (config.enable_gnss_grpc_proxy()) {
- kernel_cmdline.push_back("gnss_cmdline.serdev=serial8250/serial0/serial0-0");
- kernel_cmdline.push_back("gnss_cmdline.type=0");
- kernel_cmdline.push_back("serdev_ttyport.pdev_tty_port=ttyS1");
- }
-
- if (config.guest_audit_security()) {
- kernel_cmdline.push_back("audit=1");
- } else {
- kernel_cmdline.push_back("audit=0");
- }
-
- AppendVector(&kernel_cmdline, config.extra_kernel_cmdline());
-
- return kernel_cmdline;
-}
-
-} // namespace cuttlefish
diff --git a/host/libs/config/known_paths.cpp b/host/libs/config/known_paths.cpp
deleted file mode 100644
index 1581a06da..000000000
--- a/host/libs/config/known_paths.cpp
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2020 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 "host/libs/config/known_paths.h"
-
-#include "host/libs/config/cuttlefish_config.h"
-
-namespace cuttlefish {
-
-std::string AdbConnectorBinary() {
- return HostBinaryPath("adb_connector");
-}
-
-std::string ConfigServerBinary() {
- return HostBinaryPath("config_server");
-}
-
-std::string ConsoleForwarderBinary() {
- return HostBinaryPath("console_forwarder");
-}
-
-std::string GnssGrpcProxyBinary() {
- return HostBinaryPath("gnss_grpc_proxy");
-}
-
-std::string KernelLogMonitorBinary() {
- return HostBinaryPath("kernel_log_monitor");
-}
-
-std::string LogcatReceiverBinary() {
- return HostBinaryPath("logcat_receiver");
-}
-
-std::string MetricsBinary() {
- return HostBinaryPath("metrics");
-}
-
-std::string ModemSimulatorBinary() {
- return HostBinaryPath("modem_simulator");
-}
-
-std::string RootCanalBinary() {
- return DefaultHostArtifactsPath("bin/root-canal");
-}
-
-std::string SocketVsockProxyBinary() {
- return HostBinaryPath("socket_vsock_proxy");
-}
-
-std::string TombstoneReceiverBinary() {
- return HostBinaryPath("tombstone_receiver");
-}
-
-std::string WebRtcBinary() {
- return HostBinaryPath("webRTC");
-}
-
-std::string WebRtcSigServerBinary() {
- return HostBinaryPath("webrtc_operator");
-}
-
-std::string VncServerBinary() {
- return HostBinaryPath("vnc_server");
-}
-
-} // namespace cuttlefish
diff --git a/host/libs/config/known_paths.h b/host/libs/config/known_paths.h
deleted file mode 100644
index 71b625392..000000000
--- a/host/libs/config/known_paths.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2020 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>
-
-namespace cuttlefish {
-
-std::string AdbConnectorBinary();
-std::string ConfigServerBinary();
-std::string ConsoleForwarderBinary();
-std::string GnssGrpcProxyBinary();
-std::string KernelLogMonitorBinary();
-std::string LogcatReceiverBinary();
-std::string MetricsBinary();
-std::string ModemSimulatorBinary();
-std::string RootCanalBinary();
-std::string SocketVsockProxyBinary();
-std::string TombstoneReceiverBinary();
-std::string WebRtcBinary();
-std::string WebRtcSigServerBinary();
-std::string VncServerBinary();
-
-} // namespace cuttlefish
diff --git a/host/libs/config/logging.cpp b/host/libs/config/logging.cpp
index 50a14f856..7ff88c7c6 100644
--- a/host/libs/config/logging.cpp
+++ b/host/libs/config/logging.cpp
@@ -22,12 +22,12 @@
using android::base::SetLogger;
-namespace cuttlefish {
+namespace cvd {
void DefaultSubprocessLogging(char* argv[]) {
::android::base::InitLogging(argv, android::base::StderrLogger);
- auto config = CuttlefishConfig::Get();
+ auto config = vsoc::CuttlefishConfig::Get();
CHECK(config) << "Could not open cuttlefish config";
@@ -40,4 +40,4 @@ void DefaultSubprocessLogging(char* argv[]) {
}
}
-} // namespace cuttlefish
+} // namespace cvd
diff --git a/host/libs/config/logging.h b/host/libs/config/logging.h
index 5d57c6f9d..f66ed1e30 100644
--- a/host/libs/config/logging.h
+++ b/host/libs/config/logging.h
@@ -15,8 +15,8 @@
#pragma once
-namespace cuttlefish {
+namespace cvd {
void DefaultSubprocessLogging(char* argv[]);
-} // namespace cuttlefish
+} // namespace cvd
diff --git a/host/libs/confui/Android.bp b/host/libs/confui/Android.bp
deleted file mode 100644
index b74eb2492..000000000
--- a/host/libs/confui/Android.bp
+++ /dev/null
@@ -1,61 +0,0 @@
-//
-// Copyright (C) 2021 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.
-
-// copied from cuttlefish top level Android.bp, cuttlefish_common_headers
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-cc_library_headers {
- name: "libcuttlefish_confui_host_headers",
- vendor_available: true,
- product_available: true,
- host_supported: true,
- apex_available: [
- "//apex_available:platform",
- "com.android.virt",
- ],
-}
-
-cc_library_static {
- name: "libcuttlefish_confui_host",
- srcs: [
- "host_renderer.cc",
- "host_server.cc",
- "host_utils.cc",
- "server_common.cc",
- "session.cc",
- "fonts.S",
- ],
- shared_libs: [
- "libcuttlefish_fs",
- "libbase",
- "libjsoncpp",
- "liblog",
- ],
- header_libs: [
- "libcuttlefish_confui_host_headers",
- ],
- static_libs: [
- "libcuttlefish_host_config",
- "libcuttlefish_utils",
- "libcuttlefish_confui",
- "libcuttlefish_wayland_server",
- "libft2.nodep",
- "libteeui",
- "libteeui_localization",
- ],
- defaults: ["cuttlefish_host"],
-}
diff --git a/host/libs/confui/Roboto-Medium.ttf b/host/libs/confui/Roboto-Medium.ttf
deleted file mode 100644
index 1a7f3b0bb..000000000
--- a/host/libs/confui/Roboto-Medium.ttf
+++ /dev/null
Binary files differ
diff --git a/host/libs/confui/Roboto-Regular.ttf b/host/libs/confui/Roboto-Regular.ttf
deleted file mode 100644
index 2c97eeadf..000000000
--- a/host/libs/confui/Roboto-Regular.ttf
+++ /dev/null
Binary files differ
diff --git a/host/libs/confui/Shield.ttf b/host/libs/confui/Shield.ttf
deleted file mode 100644
index a2f5e33f3..000000000
--- a/host/libs/confui/Shield.ttf
+++ /dev/null
Binary files differ
diff --git a/host/libs/confui/fonts.S b/host/libs/confui/fonts.S
deleted file mode 100644
index 5a134dfce..000000000
--- a/host/libs/confui/fonts.S
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (C) 2020 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 <teeui/incfont.h>
-
-TEEUI_INCFONT(RobotoMedium, "Roboto-Medium.ttf");
-TEEUI_INCFONT(RobotoRegular, "Roboto-Regular.ttf");
-TEEUI_INCFONT(Shield, "Shield.ttf");
diff --git a/host/libs/confui/host_mode_ctrl.h b/host/libs/confui/host_mode_ctrl.h
deleted file mode 100644
index 7cf991ca3..000000000
--- a/host/libs/confui/host_mode_ctrl.h
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (C) 2021 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 <atomic>
-#include <condition_variable>
-#include <cstdint>
-#include <functional>
-#include <mutex>
-
-#include "common/libs/confui/confui.h"
-#include "host/libs/confui/host_utils.h"
-
-namespace cuttlefish {
-/**
- * mechanism to orchestrate concurrent executions of threads
- * that work for screen connector
- *
- * Within VNC or WebRTC service, it tells when it is now in the Android Mode or
- * Confirmation UI mode
- */
-class HostModeCtrl {
- public:
- enum class ModeType : std::uint8_t { kAndroidMode = 55, kConfUI_Mode = 77 };
-
- /**
- * The thread that enqueues Android frames will call this to wait until
- * the mode is kAndroidMode
- *
- * Logically, using atomic_mode_ alone is not sufficient. Using mutex alone
- * is logically complete but slow.
- *
- * Note that most of the time, the mode is kAndroidMode. Also, note that
- * this method is called at every single frame.
- *
- * As an optimization, we check atomic_mode_ first. If failed, we wait for
- * kAndroidMode with mutex-based lock
- *
- * The actual synchronization is not at the and_mode_cv_.wait line but at
- * this line:
- * if (atomic_mode_ == ModeType::kAndroidMode) {
- *
- * This trick reduces the flag checking delays by 70+% on a Gentoo based
- * amd64 desktop, with Linux 5.10
- */
- void WaitAndroidMode() {
- ConfUiLog(DEBUG) << cuttlefish::confui::thread::GetName()
- << "checking atomic Android mode";
- if (atomic_mode_ == ModeType::kAndroidMode) {
- ConfUiLog(DEBUG) << cuttlefish::confui::thread::GetName()
- << "returns as it is already Android mode";
- return;
- }
- auto check = [this]() -> bool {
- return atomic_mode_ == ModeType::kAndroidMode;
- };
- std::unique_lock<std::mutex> lock(mode_mtx_);
- and_mode_cv_.wait(lock, check);
- ConfUiLog(DEBUG) << cuttlefish::confui::thread::GetName()
- << "awakes from cond var waiting for Android mode";
- }
-
- void SetMode(const ModeType mode) {
- ConfUiLog(DEBUG) << cuttlefish::confui::thread::GetName()
- << "tries to acquire the lock in SetMode";
- std::lock_guard<std::mutex> lock(mode_mtx_);
- ConfUiLog(DEBUG) << cuttlefish::confui::thread::GetName()
- << "acquired the lock in SetMode";
- atomic_mode_ = mode;
- if (atomic_mode_ == ModeType::kAndroidMode) {
- ConfUiLog(DEBUG) << cuttlefish::confui::thread::GetName()
- << "signals kAndroidMode in SetMode";
- and_mode_cv_.notify_all();
- return;
- }
- ConfUiLog(DEBUG) << cuttlefish::confui::thread::GetName()
- << "signals kConfUI_Mode in SetMode";
- confui_mode_cv_.notify_all();
- }
-
- auto GetMode() {
- ModeType ret_val = atomic_mode_;
- return ret_val;
- }
-
- auto IsConfirmatioUiMode() {
- return (atomic_mode_ == ModeType::kConfUI_Mode);
- }
-
- auto IsAndroidMode() { return (atomic_mode_ == ModeType::kAndroidMode); }
-
- static HostModeCtrl& Get() {
- static HostModeCtrl host_mode_controller;
- return host_mode_controller;
- }
-
- private:
- HostModeCtrl() : atomic_mode_(ModeType::kAndroidMode) {}
- std::mutex mode_mtx_;
- std::condition_variable and_mode_cv_;
- std::condition_variable confui_mode_cv_;
- std::atomic<ModeType> atomic_mode_;
-};
-} // end of namespace cuttlefish
diff --git a/host/libs/confui/host_renderer.cc b/host/libs/confui/host_renderer.cc
deleted file mode 100644
index f3e0c5272..000000000
--- a/host/libs/confui/host_renderer.cc
+++ /dev/null
@@ -1,245 +0,0 @@
-/*
- * Copyright (C) 2021 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 "host/libs/confui/host_renderer.h"
-
-namespace cuttlefish {
-namespace confui {
-static teeui::Color alfaCombineChannel(std::uint32_t shift, double alfa,
- teeui::Color a, teeui::Color b) {
- a >>= shift;
- a &= 0xff;
- b >>= shift;
- b &= 0xff;
- double acc = alfa * a + (1 - alfa) * b;
- if (acc <= 0) return 0;
- std::uint32_t result = acc;
- if (result > 255) return 255 << shift;
- return result << shift;
-}
-
-ConfUiRenderer::ConfUiRenderer(const std::uint32_t display)
- : display_num_(display),
- lang_id_{"en"},
- prompt_("Am I Yumi Meow?"),
- current_height_(ScreenConnectorInfo::ScreenHeight(display_num_)),
- current_width_(ScreenConnectorInfo::ScreenWidth(display_num_)),
- color_bg_{kColorBackground},
- color_text_{kColorDisabled},
- shield_color_{kColorShield},
- is_inverted_{false},
- ctx_{GetDeviceContext()} {
- auto opted_frame = RepaintRawFrame(prompt_, lang_id_);
- if (opted_frame) {
- raw_frame_ = std::move(opted_frame.value());
- }
-}
-
-void ConfUiRenderer::SetConfUiMessage(const std::string& msg) {
- prompt_ = msg;
- SetText<LabelConfMsg>(msg);
-}
-
-teeui::Error ConfUiRenderer::SetLangId(const std::string& lang_id) {
- using teeui::Error;
- lang_id_ = lang_id;
- teeui::localization::selectLangId(lang_id_.c_str());
- if (auto error = UpdateTranslations()) {
- return error;
- }
- return Error::OK;
-}
-
-teeui::Error ConfUiRenderer::UpdateTranslations() {
- using namespace teeui;
- if (auto error = UpdateString<LabelOK>()) {
- return error;
- }
- if (auto error = UpdateString<LabelOK>()) {
- return error;
- }
- if (auto error = UpdateString<LabelCancel>()) {
- return error;
- }
- if (auto error = UpdateString<LabelTitle>()) {
- return error;
- }
- if (auto error = UpdateString<LabelHint>()) {
- return error;
- }
- return Error::OK;
-}
-
-teeui::context<teeui::ConUIParameters> ConfUiRenderer::GetDeviceContext() {
- using namespace teeui;
- const unsigned long long w = ScreenConnectorInfo::ScreenWidth(display_num_);
- const unsigned long long h = ScreenConnectorInfo::ScreenHeight(display_num_);
- const auto screen_width = operator""_px(w);
- const auto screen_height = operator""_px(h);
- context<teeui::ConUIParameters> ctx(6.45211, 400.0 / 412.0);
- ctx.setParam<RightEdgeOfScreen>(screen_width);
- ctx.setParam<BottomOfScreen>(screen_height);
- ctx.setParam<PowerButtonTop>(20.26_mm);
- ctx.setParam<PowerButtonBottom>(30.26_mm);
- ctx.setParam<VolUpButtonTop>(40.26_mm);
- ctx.setParam<VolUpButtonBottom>(50.26_mm);
- ctx.setParam<DefaultFontSize>(14_dp);
- ctx.setParam<BodyFontSize>(16_dp);
- return ctx;
-}
-
-bool ConfUiRenderer::InitLayout(const std::string& lang_id) {
- layout_ = teeui::instantiateLayout(teeui::ConfUILayout(), ctx_);
- SetLangId(lang_id);
- if (auto error = UpdateTranslations()) {
- ConfUiLog(ERROR) << "Update Translation Error";
- return false;
- }
- UpdateColorScheme(&ctx_);
- return true;
-}
-
-teeui::Error ConfUiRenderer::UpdatePixels(TeeUiFrame& raw_frame,
- std::uint32_t x, std::uint32_t y,
- teeui::Color color) {
- auto buffer = raw_frame.data();
- const auto height = ScreenConnectorInfo::ScreenHeight(display_num_);
- const auto width = ScreenConnectorInfo::ScreenWidth(display_num_);
- auto pos = width * y + x;
- if (pos >= (height * width)) {
- ConfUiLog(ERROR) << "Rendering Out of Bound";
- return teeui::Error::OutOfBoundsDrawing;
- }
- const double alfa = ((color & 0xff000000) >> 24) / 255.0;
- auto& pixel = *reinterpret_cast<teeui::Color*>(buffer + pos);
- pixel = alfaCombineChannel(0, alfa, color, pixel) |
- alfaCombineChannel(8, alfa, color, pixel) |
- alfaCombineChannel(16, alfa, color, pixel);
- return teeui::Error::OK;
-}
-
-std::tuple<TeeUiFrame&, bool> ConfUiRenderer::RenderRawFrame(
- const std::string& confirmation_msg, const std::string& lang_id) {
- /* we repaint only if one or more of the followng meet:
- *
- * 1. raw_frame_ is empty
- * 2. the current_width_ and current_height_ is out of date
- * 3. lang_id is different (e.g. new locale)
- *
- * in the future, maybe you wanna inverted, new background, etc?
- */
- if (lang_id != lang_id_ || !IsFrameReady() ||
- current_height_ != ScreenConnectorInfo::ScreenHeight(display_num_) ||
- current_width_ != ScreenConnectorInfo::ScreenWidth(display_num_)) {
- auto opted_new_frame = RepaintRawFrame(confirmation_msg, lang_id_);
- if (opted_new_frame) {
- // repainting from the scratch successful in a new frame
- raw_frame_ = std::move(opted_new_frame.value());
- return {raw_frame_, true};
- }
- // repaint failed even if it was necessary, so returns invalid values
- raw_frame_.clear();
- return {raw_frame_, false};
- }
- // no need to repaint from the scratch. repaint the confirmation message only
- // the frame is mostly already in raw_frame_
- auto ret_code = RenderConfirmationMsgOnly(confirmation_msg);
- return {raw_frame_, (ret_code == teeui::Error::OK)};
-}
-
-std::optional<TeeUiFrame> ConfUiRenderer::RepaintRawFrame(
- const std::string& confirmation_msg, const std::string& lang_id) {
- /*
- * NOTE: DON'T use current_width_/height_ to create this frame
- * it may fail, and then we must not mess up the current_width_, height_
- *
- */
- if (!InitLayout(lang_id)) {
- return std::nullopt;
- }
- SetConfUiMessage(confirmation_msg);
- auto color = kColorEnabled;
- std::get<teeui::LabelOK>(layout_).setTextColor(color);
- std::get<teeui::LabelCancel>(layout_).setTextColor(color);
-
- /* in the future, if ever we need to register a handler for the
- Label{OK,Cancel}. do this: std::get<teeui::LabelOK>(layout_)
- .setCB(teeui::makeCallback<teeui::Error, teeui::Event>(
- [](teeui::Event e, void* p) -> teeui::Error {
- LOG(DEBUG) << "Calling callback for Confirm?";
- return reinterpret_cast<decltype(owner)*>(p)->TapOk(e); },
- owner));
- */
- // we manually check if click happened, where if yes, and generate the label
- // event manually. So we won't register the handler here.
- /**
- * should be uint32_t for teeui APIs.
- * It assumes that each raw frame buffer element is 4 bytes
- */
- TeeUiFrame new_raw_frame(
- ScreenConnectorInfo::ScreenSizeInBytes(display_num_) / 4,
- kColorBackground);
-
- auto draw_pixel = teeui::makePixelDrawer(
- [this, &new_raw_frame](std::uint32_t x, std::uint32_t y,
- teeui::Color color) -> teeui::Error {
- return this->UpdatePixels(new_raw_frame, x, y, color);
- });
-
- // render all components
- const auto error = drawElements(layout_, draw_pixel);
- if (error) {
- ConfUiLog(ERROR) << "Painting failed: " << error.code();
- return std::nullopt;
- }
-
- // set current frame's dimension as frame generation was successful
- current_height_ = ScreenConnectorInfo::ScreenHeight(display_num_);
- current_width_ = ScreenConnectorInfo::ScreenWidth(display_num_);
-
- return {new_raw_frame};
-}
-
-teeui::Error ConfUiRenderer::RenderConfirmationMsgOnly(
- const std::string& confirmation_msg) {
- // repaint labelbody on the raw_frame__ only
- auto callback_func = [this](std::uint32_t x, std::uint32_t y,
- teeui::Color color) -> teeui::Error {
- return UpdatePixels(raw_frame_, x, y, color);
- };
- auto draw_pixel = teeui::makePixelDrawer(callback_func);
- LabelConfMsg& label = std::get<LabelConfMsg>(layout_);
- auto b = GetBoundary(label);
- for (std::uint32_t i = 0; i != b.w; i++) {
- const auto col_index = i + b.x - 1;
- for (std::uint32_t j = 0; j != b.y; j++) {
- const auto row_index = (j + b.y - 1);
- raw_frame_[current_width_ * row_index + col_index] = color_bg_;
- }
- }
-
- SetConfUiMessage(confirmation_msg);
- ConfUiLog(DEBUG) << "Repaint Confirmation Msg with :" << prompt_;
- if (auto error = std::get<LabelConfMsg>(layout_).draw(draw_pixel)) {
- ConfUiLog(ERROR) << "Repainting Confirmation Message Label failed:"
- << error.code();
- return error;
- }
- return teeui::Error::OK;
-}
-
-} // end of namespace confui
-} // end of namespace cuttlefish
diff --git a/host/libs/confui/host_renderer.h b/host/libs/confui/host_renderer.h
deleted file mode 100644
index c61410948..000000000
--- a/host/libs/confui/host_renderer.h
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * Copyright (C) 2021 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 <cstdint>
-#include <functional>
-#include <memory>
-#include <string>
-#include <tuple>
-#include <vector>
-
-#include <freetype/ftglyph.h> // $(croot)/external/freetype
-#include <teeui/utils.h> // $(croot)/system/teeui/libteeui/.../include
-
-#include "common/libs/confui/confui.h"
-#include "host/libs/confui/layouts/layout.h"
-#include "host/libs/confui/server_common.h"
-#include "host/libs/screen_connector/screen_connector.h"
-
-namespace cuttlefish {
-namespace confui {
-
-/**
- * create a raw frame for confirmation UI dialog
- */
-class ConfUiRenderer {
- public:
- using LabelConfMsg = teeui::LabelBody;
-
- ConfUiRenderer(const std::uint32_t display);
-
- /**
- * this does not repaint from the scratch all the time
- *
- * Unless repainting the whole thing is needed, it remove the message
- * label, and re-draw there. There seems yet no fancy way of doing this.
- * Thus, it repaint the background color on the top of the label, and
- * draw the label on the new background
- *
- * As HostRenderer is intended to be shared across sessions, HostRender
- * owns the buffer, and returns reference to the buffer. Note that no
- * 2 or more sessions are concurrently executed. Only 1 or 0 is active
- * at the given moment.
- */
- std::tuple<TeeUiFrame&, bool> RenderRawFrame(
- const std::string& confirmation_msg, const std::string& lang_id = "en");
-
- bool IsFrameReady() const { return !raw_frame_.empty(); }
-
- private:
- struct Boundary { // inclusive but.. LayoutElement's size is float
- std::uint32_t x, y, w, h; // (x, y) is the top left
- };
-
- template <typename LayoutElement>
- Boundary GetBoundary(LayoutElement&& e) {
- auto box = e.bounds_;
- Boundary b;
- // (x,y) is left top. so floor() makes sense
- // w, h are witdh and height in float. perhaps ceiling makes more
- // sense
- b.x = static_cast<std::uint32_t>(box.x().floor().count());
- b.y = static_cast<std::uint32_t>(box.y().floor().count());
- b.w = static_cast<std::uint32_t>(box.w().ceil().count());
- b.h = static_cast<std::uint32_t>(box.h().ceil().count());
- return b;
- }
-
- // essentially, to repaint from the scratch, so returns new frame
- // when successful. Or, nullopt
- std::optional<TeeUiFrame> RepaintRawFrame(const std::string& confirmation_msg,
- const std::string& lang_id = "en");
-
- bool InitLayout(const std::string& lang_id);
- teeui::Error UpdateTranslations();
- /**
- * could be confusing. update prompt_, and update the text_ in the Label
- * object, the GUI components. This does not render immediately. And..
- * to render it, we must clean up the existing dirty pixels, which
- * this method does not do.
- */
- void SetConfUiMessage(const std::string& s);
- teeui::Error SetLangId(const std::string& lang_id);
- teeui::context<teeui::ConUIParameters> GetDeviceContext();
-
- // effectively, will be send to teeui as a callback function
- teeui::Error UpdatePixels(TeeUiFrame& buffer, std::uint32_t x,
- std::uint32_t y, teeui::Color color);
-
- // from Trusty
- // second param is for type deduction
- template <typename... Elements>
- static teeui::Error drawElements(std::tuple<Elements...>& layout,
- const teeui::PixelDrawer& drawPixel) {
- // Error::operator|| is overloaded, so we don't get short circuit
- // evaluation. But we get the first error that occurs. We will still try and
- // draw the remaining elements in the order they appear in the layout tuple.
- return (std::get<Elements>(layout).draw(drawPixel) || ...);
- }
-
- // repaint the confirmation UI label only
- teeui::Error RenderConfirmationMsgOnly(const std::string& confirmation_msg);
-
- // from Trusty
- template <typename Context>
- void UpdateColorScheme(Context* ctx) {
- using namespace teeui;
- color_text_ = is_inverted_ ? kColorDisabledInv : kColorDisabled;
- shield_color_ = is_inverted_ ? kColorShieldInv : kColorShield;
- color_bg_ = is_inverted_ ? kColorBackgroundInv : kColorBackground;
-
- ctx->template setParam<ShieldColor>(shield_color_);
- ctx->template setParam<ColorText>(color_text_);
- ctx->template setParam<ColorBG>(color_bg_);
- return;
- }
-
- template <typename Label>
- auto SetText(const std::string& text) {
- return std::get<Label>(layout_).setText(
- {text.c_str(), text.c_str() + text.size()});
- }
-
- /**
- * source:
- * https://android.googlesource.com/trusty/app/confirmationui/+/0429cc7/src/trusty_confirmation_ui.cpp#49
- */
- template <typename Label>
- teeui::Error UpdateString() {
- using namespace teeui;
- const char* str;
- auto& label = std::get<Label>(layout_);
- str = localization::lookup(TranslationId(label.textId()));
- if (str == nullptr) {
- ConfUiLog(ERROR) << "Given translation_id" << label.textId()
- << "not found";
- return Error::Localization;
- }
- label.setText({str, str + strlen(str)});
- return Error::OK;
- }
-
- const int display_num_;
- teeui::layout_t<teeui::ConfUILayout> layout_;
- std::string lang_id_;
- std::string prompt_; // confirmation ui message
- TeeUiFrame raw_frame_;
- std::uint32_t current_height_;
- std::uint32_t current_width_;
- teeui::Color color_bg_;
- teeui::Color color_text_;
- teeui::Color shield_color_;
- bool is_inverted_;
- teeui::context<teeui::ConUIParameters> ctx_;
-
- static constexpr const teeui::Color kColorEnabled = 0xff212121;
- static constexpr const teeui::Color kColorDisabled = 0xffbdbdbd;
- static constexpr const teeui::Color kColorEnabledInv = 0xffdedede;
- static constexpr const teeui::Color kColorDisabledInv = 0xff424242;
- static constexpr const teeui::Color kColorBackground = 0xffffffff;
- static constexpr const teeui::Color kColorBackgroundInv = 0xff212121;
- static constexpr const teeui::Color kColorShieldInv = 0xffc4cb80;
- static constexpr const teeui::Color kColorShield = 0xff778500;
-};
-} // end of namespace confui
-} // end of namespace cuttlefish
diff --git a/host/libs/confui/host_server.cc b/host/libs/confui/host_server.cc
deleted file mode 100644
index c14e0ed16..000000000
--- a/host/libs/confui/host_server.cc
+++ /dev/null
@@ -1,259 +0,0 @@
-/*
- * Copyright (C) 2021 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 "host/libs/confui/host_server.h"
-
-#include <chrono>
-#include <functional>
-#include <optional>
-#include <tuple>
-
-#include "common/libs/confui/confui.h"
-#include "host/libs/config/cuttlefish_config.h"
-#include "host/libs/confui/host_utils.h"
-
-namespace cuttlefish {
-namespace confui {
-static auto CuttlefishConfigDefaultInstance() {
- auto config = cuttlefish::CuttlefishConfig::Get();
- CHECK(config) << "Config must not be null";
- return config->ForDefaultInstance();
-}
-
-static std::string HalGuestSocketPath() {
- return CuttlefishConfigDefaultInstance().confui_hal_guest_socket_path();
-}
-
-HostServer& HostServer::Get(
- HostModeCtrl& host_mode_ctrl,
- cuttlefish::ScreenConnectorFrameRenderer& screen_connector) {
- static HostServer host_server{host_mode_ctrl, screen_connector};
- return host_server;
-}
-
-HostServer::HostServer(
- cuttlefish::HostModeCtrl& host_mode_ctrl,
- cuttlefish::ScreenConnectorFrameRenderer& screen_connector)
- : display_num_(0),
- host_mode_ctrl_(host_mode_ctrl),
- screen_connector_{screen_connector},
- renderer_(display_num_),
- hal_socket_path_(HalGuestSocketPath()),
- input_multiplexer_{/* max n_elems */ 20, /* n_Qs */ 2} {
- hal_cmd_q_id_ = input_multiplexer_.GetNewQueueId(); // return 0
- user_input_evt_q_id_ = input_multiplexer_.GetNewQueueId(); // return 1
-}
-
-void HostServer::Start() {
- guest_hal_socket_ = cuttlefish::SharedFD::SocketLocalServer(
- hal_socket_path_, false, SOCK_STREAM, 0666);
- if (!guest_hal_socket_->IsOpen()) {
- ConfUiLog(FATAL) << "Confirmation UI host service mandates a server socket"
- << "to which the guest HAL to connect.";
- return;
- }
- auto hal_cmd_fetching = [this]() { this->HalCmdFetcherLoop(); };
- auto main = [this]() { this->MainLoop(); };
- hal_input_fetcher_thread_ =
- thread::RunThread("HalInputLoop", hal_cmd_fetching);
- main_loop_thread_ = thread::RunThread("MainLoop", main);
- ConfUiLog(DEBUG) << "configured internal socket based input.";
- return;
-}
-
-void HostServer::HalCmdFetcherLoop() {
- hal_cli_socket_ = EstablishHalConnection();
- if (!hal_cli_socket_->IsOpen()) {
- ConfUiLog(FATAL)
- << "Confirmation UI host service mandates connection with HAL.";
- return;
- }
- while (true) {
- auto opted_msg = RecvConfUiMsg(hal_cli_socket_);
- if (!opted_msg) {
- ConfUiLog(ERROR) << "Error in RecvConfUiMsg from HAL";
- continue;
- }
- auto input = std::move(opted_msg.value());
- input_multiplexer_.Push(hal_cmd_q_id_, std::move(input));
- }
-}
-
-bool HostServer::SendUserSelection(UserResponse::type selection) {
- if (!curr_session_) {
- ConfUiLog(FATAL) << "Current session must not be null";
- return false;
- }
- if (curr_session_->GetState() != MainLoopState::kInSession) {
- // ignore
- return true;
- }
-
- std::lock_guard<std::mutex> lock(input_socket_mtx_);
- if (selection != UserResponse::kConfirm &&
- selection != UserResponse::kCancel) {
- ConfUiLog(FATAL) << selection << " must be either" << UserResponse::kConfirm
- << "or" << UserResponse::kCancel;
- return false; // not reaching here
- }
-
- ConfUiMessage input{GetCurrentSessionId(),
- ToString(ConfUiCmd::kUserInputEvent), selection};
-
- input_multiplexer_.Push(user_input_evt_q_id_, std::move(input));
- return true;
-}
-
-void HostServer::PressConfirmButton(const bool is_down) {
- if (!is_down) {
- return;
- }
- // shared by N vnc/webRTC clients
- SendUserSelection(UserResponse::kConfirm);
-}
-
-void HostServer::PressCancelButton(const bool is_down) {
- if (!is_down) {
- return;
- }
- // shared by N vnc/webRTC clients
- SendUserSelection(UserResponse::kCancel);
-}
-
-bool HostServer::IsConfUiActive() {
- if (!curr_session_) {
- return false;
- }
- return curr_session_->IsConfUiActive();
-}
-
-SharedFD HostServer::EstablishHalConnection() {
- ConfUiLog(DEBUG) << "Waiting hal accepting";
- auto new_cli = SharedFD::Accept(*guest_hal_socket_);
- ConfUiLog(DEBUG) << "hal client accepted";
- return new_cli;
-}
-
-std::unique_ptr<Session> HostServer::ComputeCurrentSession(
- const std::string& session_id) {
- if (curr_session_ && (GetCurrentSessionId() != session_id)) {
- ConfUiLog(FATAL) << curr_session_->GetId() << " is active and in the"
- << GetCurrentState() << "but HAL sends command to"
- << session_id;
- }
- if (curr_session_) {
- return std::move(curr_session_);
- }
-
- // pick up a new session, or create one
- auto result = GetSession(session_id);
- if (result) {
- return std::move(result);
- }
-
- auto raw_ptr = new Session(session_id, display_num_, renderer_,
- host_mode_ctrl_, screen_connector_);
- result = std::unique_ptr<Session>(raw_ptr);
- // note that the new session is directly going to curr_session_
- // when it is suspended, it will be moved to session_map_
- return std::move(result);
-}
-
-// read the comments in the header file
-[[noreturn]] void HostServer::MainLoop() {
- while (true) {
- // this gets one input from either queue:
- // from HAL or from all webrtc/vnc clients
- // if no input, sleep until there is
- const auto input = input_multiplexer_.Pop();
- const auto& [session_id, cmd_str, additional_info] = input;
-
- // take input for the Finite States Machine below
- const ConfUiCmd cmd = ToCmd(cmd_str);
- const bool is_user_input = (cmd == ConfUiCmd::kUserInputEvent);
- std::string src = is_user_input ? "input" : "hal";
-
- ConfUiLog(DEBUG) << "In Session" << GetCurrentSessionId() << ","
- << "in state" << GetCurrentState() << ","
- << "received input from" << src << "cmd =" << cmd_str
- << "and additional_info =" << additional_info
- << "going to session" << session_id;
-
- FsmInput fsm_input = ToFsmInput(input);
-
- if (is_user_input && !curr_session_) {
- // discard the input, there's no session to take it yet
- // actually, no confirmation UI screen is available
- ConfUiLog(DEBUG) << "Took user input but no active session is available.";
- continue;
- }
-
- /**
- * if the curr_session_ is null, create one
- * if the curr_session_ is not null but the session id doesn't match,
- * something is wrong. Confirmation UI doesn't allow preemption by
- * another confirmation UI session back to back. When it's preempted,
- * HAL must send "kSuspend"
- *
- */
- curr_session_ = ComputeCurrentSession(session_id);
- ConfUiLog(DEBUG) << "Host service picked up "
- << (curr_session_ ? curr_session_->GetId()
- : "null session");
- ConfUiLog(DEBUG) << "The state of current session is "
- << (curr_session_ ? ToString(curr_session_->GetState())
- : "null session");
-
- if (is_user_input) {
- curr_session_->Transition(is_user_input, hal_cli_socket_, fsm_input,
- additional_info);
- } else {
- ConfUiCmd cmd = ToCmd(cmd_str);
- switch (cmd) {
- case ConfUiCmd::kSuspend:
- curr_session_->Suspend(hal_cli_socket_);
- break;
- case ConfUiCmd::kRestore:
- curr_session_->Restore(hal_cli_socket_);
- break;
- case ConfUiCmd::kAbort:
- curr_session_->Abort(hal_cli_socket_);
- break;
- default:
- curr_session_->Transition(is_user_input, hal_cli_socket_, fsm_input,
- additional_info);
- break;
- }
- }
-
- // check the session if it is inactive (e.g. init, suspended)
- // and if it is done (transitioned to init from any other state)
- if (curr_session_->IsSuspended()) {
- session_map_[GetCurrentSessionId()] = std::move(curr_session_);
- curr_session_ = nullptr;
- continue;
- }
-
- if (curr_session_->GetState() == MainLoopState::kAwaitCleanup) {
- curr_session_->CleanUp();
- curr_session_ = nullptr;
- }
- // otherwise, continue with keeping the curr_session_
- } // end of the infinite while loop
-}
-
-} // end of namespace confui
-} // end of namespace cuttlefish
diff --git a/host/libs/confui/host_server.h b/host/libs/confui/host_server.h
deleted file mode 100644
index be5caeb57..000000000
--- a/host/libs/confui/host_server.h
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * Copyright (C) 2021 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 <atomic>
-#include <cstdint>
-#include <memory>
-#include <mutex>
-#include <string>
-#include <thread>
-#include <unordered_map>
-#include <vector>
-
-#include <android-base/logging.h>
-#include <teeui/utils.h>
-
-#include "common/libs/concurrency/multiplexer.h"
-#include "common/libs/concurrency/semaphore.h"
-#include "common/libs/confui/confui.h"
-#include "common/libs/fs/shared_fd.h"
-#include "host/commands/kernel_log_monitor/utils.h"
-#include "host/libs/config/logging.h"
-#include "host/libs/confui/host_mode_ctrl.h"
-#include "host/libs/confui/host_renderer.h"
-#include "host/libs/confui/host_virtual_input.h"
-#include "host/libs/confui/server_common.h"
-#include "host/libs/confui/session.h"
-#include "host/libs/screen_connector/screen_connector.h"
-
-namespace cuttlefish {
-namespace confui {
-class HostServer : public HostVirtualInput {
- public:
- static HostServer& Get(
- HostModeCtrl& host_mode_ctrl,
- cuttlefish::ScreenConnectorFrameRenderer& screen_connector);
-
- void Start(); // start this server itself
- virtual ~HostServer() = default;
-
- // implement input interfaces. called by webRTC & vnc
- void PressConfirmButton(const bool is_down) override;
- void PressCancelButton(const bool is_down) override;
- bool IsConfUiActive() override;
-
- private:
- explicit HostServer(
- cuttlefish::HostModeCtrl& host_mode_ctrl,
- cuttlefish::ScreenConnectorFrameRenderer& screen_connector);
- HostServer() = delete;
-
- /**
- * basic prompt flow:
- * (1) Without preemption
- * send "kStart" with confirmation message
- * wait kCliAck from the host service with the echoed command
- * wait the confirmation/cancellation (or perhaps reset?)
- * send kStop
- * wait kCliAck from the host service with the echoed command
- *
- * (2) With preemption (e.g.)
- * send "kStart" with confirmation message
- * wait kCliAck from the host service with the echoed command
- * wait the confirmation/cancellation (or perhaps reset?)
- * send kSuspend // when HAL is preempted
- * send kRestore // when HAL resumes
- * send kStop
- *
- * From the host end, it is a close-to-Mealy FSM.
- * There are four states S = {init, session, wait_ack, suspended}
- *
- * 'session' means in a confirmation session. 'wait_ack' means
- * server sends the confirmation and waiting "stop" command from HAL
- * 'suspended' means the HAL service is preemptied. So, the host
- * should render the Android guest frames but keep the confirmation
- * UI session and frame
- *
- * The inputs are I = {u, g}. 'u' is the user input from vnc/webRTC
- * clients. Note that the host service serialized the concurrent user
- * inputs from multiple clients. 'g' is the command from the HAL service
- *
- * The transition rules:
- * (S, I) --> (S, O) where O is the output
- *
- * init, g(start) --> session, set Conf UI mode, render a frame
- * session, u(cancel/confirm) --> waitstop, send the result to HAL
- * session, g(suspend) --> suspend, create a saved session
- * session, g(abort) --> init, clear saved frame
- * waitstop, g(stop) --> init, clear saved frame
- * waitstop, g(suspend) --> suspend, no need to save the session
- * waitstop, g(abort) --> init, clear saved frame
- * suspend, g(restore) --> return to the saved state, restore if there's a
- * saved session
- * suspend, g(abort) --> init, clear saved frame
- *
- * For now, we did not yet implement suspend or abort.
- *
- */
- [[noreturn]] void MainLoop();
- void HalCmdFetcherLoop();
-
- SharedFD EstablishHalConnection();
-
- // failed to start dialog, etc
- // basically, will reset the session, so start from the beginning in the same
- // session
- void ResetOnCommandFailure();
-
- // note: the picked session will be removed from session_map_
- std::unique_ptr<Session> GetSession(const std::string& session_id) {
- if (session_map_.find(session_id) == session_map_.end()) {
- return nullptr;
- }
- std::unique_ptr<Session> temp = std::move(session_map_[session_id]);
- session_map_.erase(session_id);
- return temp;
- }
-
- std::string GetCurrentSessionId() {
- if (curr_session_) {
- return curr_session_->GetId();
- }
- return SESSION_ANY;
- }
-
- std::string GetCurrentState() {
- if (!curr_session_) {
- return {"kInvalid"};
- }
- return ToString(curr_session_->GetState());
- }
- std::unique_ptr<Session> ComputeCurrentSession(const std::string& session_id);
- bool SendUserSelection(UserResponse::type selection);
-
- const std::uint32_t display_num_;
- HostModeCtrl& host_mode_ctrl_;
- ScreenConnectorFrameRenderer& screen_connector_;
-
- // this member creates a raw frame
- ConfUiRenderer renderer_;
-
- std::string input_socket_path_;
- std::string hal_socket_path_;
-
- // session id to Session object map, for those that are suspended
- std::unordered_map<std::string, std::unique_ptr<Session>> session_map_;
- // curr_session_ doesn't belong to session_map_
- std::unique_ptr<Session> curr_session_;
-
- SharedFD guest_hal_socket_;
- // ACCEPTED fd on guest_hal_socket_
- SharedFD hal_cli_socket_;
- std::mutex input_socket_mtx_;
-
- /*
- * Multiplexer has N queues. When pop(), it is going to sleep until
- * there's at least one item in at least one queue. The lower the Q
- * index is, the higher the priority is.
- *
- * For HostServer, we have a queue for the user input events, and
- * another for hal cmd/msg queues
- */
- Multiplexer<ConfUiMessage> input_multiplexer_;
- int hal_cmd_q_id_; // Q id in input_multiplexer_
- int user_input_evt_q_id_; // Q id in input_multiplexer_
-
- std::thread main_loop_thread_;
- std::thread hal_input_fetcher_thread_;
-};
-
-} // end of namespace confui
-} // end of namespace cuttlefish
diff --git a/host/libs/confui/host_utils.cc b/host/libs/confui/host_utils.cc
deleted file mode 100644
index 6ff67b0d7..000000000
--- a/host/libs/confui/host_utils.cc
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2021 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 "host/libs/confui/host_utils.h"
-
-namespace cuttlefish {
-namespace confui {
-namespace thread {
-std::string ThreadTracer::Get(const std::thread::id tid) {
- std::lock_guard<std::mutex> lock(mtx_);
- if (id2name_.find(tid) != id2name_.end()) {
- return id2name_[tid];
- }
- std::stringstream ss;
- ss << "Thread@" << tid;
- return ss.str();
-}
-
-void ThreadTracer::Set(const std::string& name, const std::thread::id tid) {
- std::lock_guard<std::mutex> lock(mtx_);
- if (name2id_.find(name) != name2id_.end()) {
- // has the name already
- if (name2id_[name] != tid) { // used for another thread
- ConfUiLog(FATAL) << "Thread name is duplicated.";
- }
- // name and id are already set correctly
- return;
- }
- if (id2name_.find(tid) != id2name_.end()) {
- // tid exists but has a different name
- name2id_.erase(id2name_[tid]); // delete old_name -> tid map
- }
- id2name_[tid] = name;
- name2id_[name] = tid;
- return;
-}
-
-std::optional<std::thread::id> ThreadTracer::Get(const std::string& name) {
- std::lock_guard<std::mutex> lock(mtx_);
- if (name2id_.find(name) != name2id_.end()) {
- return {name2id_[name]};
- }
- return std::nullopt; // unknown
-}
-
-ThreadTracer& GetThreadTracer() {
- static ThreadTracer thread_tracer;
- return thread_tracer;
-}
-
-std::string GetName(const std::thread::id tid) {
- return GetThreadTracer().Get(tid);
-}
-
-std::optional<std::thread::id> GetId(const std::string& name) {
- return GetThreadTracer().Get(name);
-}
-
-void Set(const std::string& name, const std::thread::id tid) {
- GetThreadTracer().Set(name, tid);
-}
-} // namespace thread
-} // namespace confui
-} // namespace cuttlefish
diff --git a/host/libs/confui/host_utils.h b/host/libs/confui/host_utils.h
deleted file mode 100644
index bd4004b61..000000000
--- a/host/libs/confui/host_utils.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (C) 2021 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 <functional>
-#include <map>
-#include <mutex>
-#include <optional>
-#include <sstream>
-#include <string>
-#include <thread>
-
-#include <android-base/logging.h>
-
-#include "common/libs/confui/confui.h"
-#include "host/commands/kernel_log_monitor/utils.h"
-#include "host/libs/config/logging.h"
-
-namespace cuttlefish {
-namespace confui {
-
-namespace thread {
-/* thread id to name
- * these three functions internally uses the singleton ThreadTracer object.
- *
- * When running a thread, use the global RunThread function
- */
-std::string GetName(const std::thread::id tid = std::this_thread::get_id());
-std::optional<std::thread::id> GetId(const std::string& name);
-void Set(const std::string& name, const std::thread::id tid);
-
-/*
- * This is wrapping std::thread. However, we keep the bidirectional map
- * between the given thread name and the thread id. The main purpose is
- * to help debugging.
- *
- */
-template <typename F, typename... Args>
-std::thread RunThread(const std::string& name, F&& f, Args&&... args);
-
-class ThreadTracer;
-ThreadTracer& GetThreadTracer();
-
-class ThreadTracer {
- friend ThreadTracer& GetThreadTracer();
- friend std::string GetName(const std::thread::id tid);
- friend std::optional<std::thread::id> GetId(const std::string& name);
- friend void Set(const std::string& name, const std::thread::id tid);
-
- template <typename F, typename... Args>
- friend std::thread RunThread(const std::string& name, F&& f, Args&&... args);
-
- private:
- template <typename F, typename... Args>
- std::thread RunThread(const std::string& name, F&& f, Args&&... args) {
- auto th = std::thread(std::forward<F>(f), std::forward<Args>(args)...);
- if (name2id_.find(name) != name2id_.end()) {
- ConfUiLog(FATAL) << "Thread name is duplicated";
- }
- name2id_[name] = th.get_id();
- id2name_[th.get_id()] = name;
- ConfUiLog(DEBUG) << name << "thread started.";
- return th;
- }
- std::string Get(const std::thread::id id = std::this_thread::get_id());
- std::optional<std::thread::id> Get(const std::string& name);
-
- // add later on even though it wasn't started with RunThread
- // if tid is already added, update the name only
- void Set(const std::string& name, const std::thread::id tid);
-
- ThreadTracer() = default;
- std::map<std::thread::id, std::string> id2name_;
- std::map<std::string, std::thread::id> name2id_;
- std::mutex mtx_;
-};
-
-template <typename F, typename... Args>
-std::thread RunThread(const std::string& name, F&& f, Args&&... args) {
- auto& tracer = GetThreadTracer();
- return tracer.RunThread(name, std::forward<F>(f),
- std::forward<Args>(args)...);
-}
-
-} // namespace thread
-} // namespace confui
-} // namespace cuttlefish
diff --git a/host/libs/confui/host_virtual_input.h b/host/libs/confui/host_virtual_input.h
deleted file mode 100644
index ec800cba0..000000000
--- a/host/libs/confui/host_virtual_input.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2021 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.0f
- *
- * 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 <cstdint>
-
-namespace cuttlefish {
-namespace confui {
-enum class ConfUiKeys : std::uint32_t { Confirm = 7, Cancel = 8 };
-
-/**
- * vnc, webrtc will deliver the user inputs from their client
- * to this class object
- */
-class HostVirtualInput {
- public:
- virtual void PressConfirmButton(const bool is_down) = 0;
- virtual void PressCancelButton(const bool is_down) = 0;
- virtual ~HostVirtualInput() = default;
- // guarantees that if this returns true, it is confirmation UI mode
- virtual bool IsConfUiActive() = 0;
-};
-} // namespace confui
-} // namespace cuttlefish
diff --git a/host/libs/confui/layouts/fonts.h b/host/libs/confui/layouts/fonts.h
deleted file mode 100644
index 1abfd259b..000000000
--- a/host/libs/confui/layouts/fonts.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright 2021, 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 <teeui/incfont.h>
-
-/*
- * Each entry TEEUI_INCFONT(<name>) declares:
- * extern unsigned char <name>[];
- * extern unsigned int <name>_length;
- * The first one pointing to a raw ttf font file in the .rodata section, and the
- * second beeing the size of the buffer.
- */
-TEEUI_INCFONT(RobotoMedium);
-TEEUI_INCFONT(RobotoRegular);
-TEEUI_INCFONT(Shield);
diff --git a/host/libs/confui/layouts/layout.h b/host/libs/confui/layouts/layout.h
deleted file mode 100644
index bb40b67d7..000000000
--- a/host/libs/confui/layouts/layout.h
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * Copyright (C) 2021 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 <teeui/button.h>
-#include <teeui/label.h>
-#include <teeui/localization/ConfirmationUITranslations.h>
-#include <teeui/utils.h>
-
-#include "fonts.h"
-
-using teeui::localization::TranslationId;
-
-namespace teeui {
-
-DECLARE_PARAMETER(RightEdgeOfScreen);
-DECLARE_PARAMETER(BottomOfScreen);
-DECLARE_PARAMETER(PowerButtonTop);
-DECLARE_PARAMETER(PowerButtonBottom);
-DECLARE_PARAMETER(VolUpButtonTop);
-DECLARE_PARAMETER(VolUpButtonBottom);
-DECLARE_PARAMETER(DefaultFontSize); // 14_dp regular and 18_dp magnified
-DECLARE_PARAMETER(BodyFontSize); // 16_dp regular and 20_dp magnified
-DECLARE_TYPED_PARAMETER(ShieldColor, ::teeui::Color);
-DECLARE_TYPED_PARAMETER(ColorText, ::teeui::Color);
-DECLARE_TYPED_PARAMETER(ColorBG, ::teeui::Color);
-
-NEW_PARAMETER_SET(ConUIParameters, RightEdgeOfScreen, BottomOfScreen,
- PowerButtonTop, PowerButtonBottom, VolUpButtonTop,
- VolUpButtonBottom, DefaultFontSize, BodyFontSize, ShieldColor,
- ColorText, ColorBG);
-
-CONSTANT(BorderWidth, 24_dp);
-CONSTANT(PowerButtonCenter, (PowerButtonTop() + PowerButtonBottom()) / 2_px);
-CONSTANT(VolUpButtonCenter, (VolUpButtonTop() + VolUpButtonBottom()) / 2.0_px);
-CONSTANT(GrayZone, 12_dp);
-CONSTANT(RightLabelEdge, RightEdgeOfScreen() - BorderWidth - GrayZone);
-CONSTANT(LabelWidth, RightLabelEdge - BorderWidth);
-
-CONSTANT(SQRT2, 1.4142135623_dp);
-CONSTANT(SQRT8, 2.828427125_dp);
-
-CONSTANT(ARROW_SHAPE,
- CONVEX_OBJECTS(
- CONVEX_OBJECT(Vec2d{.0_dp, .0_dp}, Vec2d{6.0_dp, 6.0_dp},
- Vec2d{6.0_dp - SQRT8, 6.0_dp}, Vec2d{-SQRT2, SQRT2}),
- CONVEX_OBJECT(Vec2d{6.0_dp - SQRT8, 6.0_dp}, Vec2d{6.0_dp, 6.0_dp},
- Vec2d{0.0_dp, 12.0_dp},
- Vec2d{-SQRT2, 12.0_dp - SQRT2})));
-
-DECLARE_FONT_BUFFER(RobotoMedium, RobotoMedium, RobotoMedium_length);
-DECLARE_FONT_BUFFER(RobotoRegular, RobotoRegular, RobotoRegular_length);
-DECLARE_FONT_BUFFER(Shield, Shield, Shield_length);
-
-CONSTANT(DefaultFont, FONT(RobotoRegular));
-
-BEGIN_ELEMENT(LabelOK, teeui::Label)
-FontSize(DefaultFontSize());
-LineHeight(20_dp);
-NumberOfLines(2);
-Dimension(LabelWidth, HeightFromLines);
-Position(BorderWidth, PowerButtonCenter - dim_h / 2.0_px);
-DefaultText("Press Power Button Confirm");
-RightJustified;
-VerticallyCentered;
-TextColor(ColorText());
-Font(FONT(RobotoMedium));
-TextID(TEXT_ID(TranslationId::CONFIRM_PWR_BUTTON_DOUBLE_PRESS));
-END_ELEMENT();
-
-BEGIN_ELEMENT(IconPower, teeui::Button, ConvexObjectCount(2))
-Dimension(BorderWidth, PowerButtonBottom() - PowerButtonTop());
-Position(RightEdgeOfScreen() - BorderWidth, PowerButtonTop());
-CornerRadius(3_dp);
-ButtonColor(ColorText());
-RoundTopLeft;
-RoundBottomLeft;
-ConvexObjectColor(ColorBG());
-ConvexObjects(ARROW_SHAPE);
-END_ELEMENT();
-
-BEGIN_ELEMENT(LabelCancel, teeui::Label)
-FontSize(DefaultFontSize());
-LineHeight(20_dp);
-NumberOfLines(2);
-Dimension(LabelWidth, HeightFromLines);
-Position(BorderWidth, VolUpButtonCenter - dim_h / 2.0_px);
-DefaultText("Press Menu Button to Cancel");
-RightJustified;
-VerticallyCentered;
-TextColor(ColorText());
-Font(FONT(RobotoMedium));
-TextID(TEXT_ID(TranslationId::CANCEL));
-END_ELEMENT();
-
-BEGIN_ELEMENT(IconVolUp, teeui::Button, ConvexObjectCount(2))
-Dimension(BorderWidth, VolUpButtonBottom() - VolUpButtonTop());
-Position(RightEdgeOfScreen() - BorderWidth, VolUpButtonTop());
-CornerRadius(5_dp);
-ButtonColor(ColorBG());
-ConvexObjectColor(ColorText());
-ConvexObjects(ARROW_SHAPE);
-END_ELEMENT();
-
-BEGIN_ELEMENT(IconShield, teeui::Label)
-FontSize(24_dp);
-LineHeight(24_dp);
-NumberOfLines(1);
-Dimension(LabelWidth, HeightFromLines);
-Position(BorderWidth, BOTTOM_EDGE_OF(LabelCancel) + 40_dp);
-DefaultText(
- "A"); // ShieldTTF has just one glyph at the code point for capital A
-TextColor(ShieldColor());
-Font(FONT(Shield));
-END_ELEMENT();
-
-BEGIN_ELEMENT(LabelTitle, teeui::Label)
-FontSize(20_dp);
-LineHeight(20_dp);
-NumberOfLines(1);
-Dimension(RightEdgeOfScreen() - BorderWidth, HeightFromLines);
-Position(BorderWidth, BOTTOM_EDGE_OF(IconShield) + 12_dp);
-DefaultText("Android Protected Confirmation");
-Font(FONT(RobotoMedium));
-VerticallyCentered;
-TextColor(ColorText());
-TextID(TEXT_ID(TranslationId::TITLE));
-END_ELEMENT();
-
-BEGIN_ELEMENT(LabelHint, teeui::Label)
-FontSize(DefaultFontSize());
-LineHeight(DefaultFontSize() * 1.5_px);
-NumberOfLines(4);
-Dimension(LabelWidth, HeightFromLines);
-Position(BorderWidth, BottomOfScreen() - BorderWidth - dim_h);
-DefaultText(
- "This confirmation provides an extra layer of security for the action "
- "you're "
- "about to take.");
-VerticalTextAlignment(Alignment::BOTTOM);
-TextColor(ColorText());
-Font(DefaultFont);
-TextID(TEXT_ID(TranslationId::DESCRIPTION));
-END_ELEMENT();
-
-BEGIN_ELEMENT(LabelBody, teeui::Label)
-FontSize(BodyFontSize());
-LineHeight(BodyFontSize() * 1.4_px);
-NumberOfLines(20);
-Position(BorderWidth, BOTTOM_EDGE_OF(LabelTitle) + 18_dp);
-Dimension(LabelWidth, LabelHint::pos_y - pos_y - 24_dp);
-DefaultText(
- "12345678901234567890123456789012345678901234567890123456789012345678901234"
- "567890123456"
- "78901234567890");
-TextColor(ColorText());
-Font(FONT(RobotoRegular));
-END_ELEMENT();
-
-NEW_LAYOUT(ConfUILayout, LabelOK, IconPower, LabelCancel, IconVolUp, IconShield,
- LabelTitle, LabelHint, LabelBody);
-
-} // namespace teeui
diff --git a/host/libs/confui/server_common.cc b/host/libs/confui/server_common.cc
deleted file mode 100644
index cf46fe398..000000000
--- a/host/libs/confui/server_common.cc
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (C) 2021 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 "host/libs/confui/server_common.h"
-namespace cuttlefish {
-namespace confui {
-static FsmInput UserEvtToFsmInput(UserResponse::type user_response) {
- if (user_response == UserResponse::kConfirm) {
- return FsmInput::kUserUnknown;
- }
- if (user_response == UserResponse::kCancel) {
- return FsmInput::kUserCancel;
- }
- return FsmInput::kUserUnknown;
-}
-
-FsmInput ToFsmInput(const ConfUiMessage& confui_msg) {
- ConfUiCmd cmd = ToCmd(confui_msg.type_);
- if (cmd == ConfUiCmd::kUserInputEvent) {
- return UserEvtToFsmInput(confui_msg.msg_);
- }
- const auto hal_cmd = cmd;
- switch (hal_cmd) {
- case ConfUiCmd::kUnknown:
- return FsmInput::kHalUnknown;
- case ConfUiCmd::kStart:
- return FsmInput::kHalStart;
- case ConfUiCmd::kStop:
- return FsmInput::kHalStop;
- case ConfUiCmd::kSuspend:
- return FsmInput::kHalSuspend;
- case ConfUiCmd::kRestore:
- return FsmInput::kHalRestore;
- case ConfUiCmd::kAbort:
- return FsmInput::kHalAbort;
- case ConfUiCmd::kCliAck:
- case ConfUiCmd::kCliRespond:
- default:
- ConfUiLog(FATAL) << "The" << ToString(hal_cmd)
- << "is not handled by Session";
- }
- return FsmInput::kHalUnknown;
-}
-
-std::string ToString(FsmInput input) {
- switch (input) {
- case FsmInput::kUserConfirm:
- return {"kUserConfirm"};
- case FsmInput::kUserCancel:
- return {"kUserCancel"};
- case FsmInput::kUserUnknown:
- return {"kUserUnknown"};
- case FsmInput::kHalStart:
- return {"kHalStart"};
- case FsmInput::kHalStop:
- return {"kHalStop"};
- case FsmInput::kHalSuspend:
- return {"kHalSuspend"};
- case FsmInput::kHalRestore:
- return {"kHalRestore"};
- case FsmInput::kHalAbort:
- return {"kHalAbort"};
- case FsmInput::kHalUnknown:
- default:
- break;
- }
- return {"kHalUnknown"};
-}
-
-std::string ToString(const MainLoopState& state) {
- switch (state) {
- case MainLoopState::kInit:
- return "kInit";
- case MainLoopState::kInSession:
- return "kInSession";
- case MainLoopState::kWaitStop:
- return "kWaitStop";
- case MainLoopState::kSuspended:
- return "kSuspended";
- case MainLoopState::kAwaitCleanup:
- return "kAwaitCleanup";
- default:
- return "kInvalid";
- }
-}
-
-} // end of namespace confui
-} // end of namespace cuttlefish
diff --git a/host/libs/confui/server_common.h b/host/libs/confui/server_common.h
deleted file mode 100644
index 6175d16c9..000000000
--- a/host/libs/confui/server_common.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2021 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 <cstdint>
-#include <vector>
-
-#include "common/libs/confui/confui.h"
-
-namespace cuttlefish {
-namespace confui {
-enum class MainLoopState : std::uint32_t {
- kInit = 1,
- kInSession = 2,
- kWaitStop = 3, // wait ack after sending confirm/cancel
- kSuspended = 4,
- kAwaitCleanup = 5,
- kInvalid = 9
-};
-
-using TeeUiFrame = std::vector<std::uint32_t>;
-
-// FSM input to Session FSM
-enum class FsmInput : std::uint32_t {
- kUserConfirm,
- kUserCancel,
- kUserUnknown,
- kHalStart,
- kHalStop,
- kHalSuspend,
- kHalRestore,
- kHalAbort,
- kHalUnknown
-};
-
-std::string ToString(FsmInput input);
-std::string ToString(const MainLoopState& state);
-
-FsmInput ToFsmInput(const ConfUiMessage& confui_msg);
-
-} // end of namespace confui
-} // end of namespace cuttlefish
diff --git a/host/libs/confui/session.cc b/host/libs/confui/session.cc
deleted file mode 100644
index 3d365c617..000000000
--- a/host/libs/confui/session.cc
+++ /dev/null
@@ -1,269 +0,0 @@
-/*
- * Copyright (C) 2021 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 "host/libs/confui/session.h"
-
-namespace cuttlefish {
-namespace confui {
-
-Session::Session(const std::string& session_id, const std::uint32_t display_num,
- ConfUiRenderer& host_renderer, HostModeCtrl& host_mode_ctrl,
- ScreenConnectorFrameRenderer& screen_connector,
- const std::string& locale)
- : session_id_{session_id},
- display_num_{display_num},
- renderer_{host_renderer},
- host_mode_ctrl_{host_mode_ctrl},
- screen_connector_{screen_connector},
- locale_{locale},
- state_{MainLoopState::kInit},
- saved_state_{MainLoopState::kInit} {}
-
-bool Session::IsConfUiActive() const {
- if (state_ == MainLoopState::kInSession ||
- state_ == MainLoopState::kWaitStop) {
- return true;
- }
- return false;
-}
-
-bool Session::RenderDialog(const std::string& msg, const std::string& locale) {
- auto [teeui_frame, is_success] = renderer_.RenderRawFrame(msg, locale);
- if (!is_success) {
- return false;
- }
- prompt_ = msg;
- locale_ = locale;
-
- ConfUiLog(DEBUG) << "actually trying to render the frame"
- << thread::GetName();
- auto raw_frame = reinterpret_cast<std::uint8_t*>(teeui_frame.data());
- return screen_connector_.RenderConfirmationUi(display_num_, raw_frame);
-}
-
-bool Session::IsSuspended() const {
- return (state_ == MainLoopState::kSuspended);
-}
-
-MainLoopState Session::Transition(const bool is_user_input, SharedFD& hal_cli,
- const FsmInput fsm_input,
- const std::string& additional_info) {
- switch (state_) {
- case MainLoopState::kInit: {
- HandleInit(is_user_input, hal_cli, fsm_input, additional_info);
- } break;
- case MainLoopState::kInSession: {
- HandleInSession(is_user_input, hal_cli, fsm_input);
- } break;
- case MainLoopState::kWaitStop: {
- if (is_user_input) {
- ConfUiLog(DEBUG) << "User input ignored" << ToString(fsm_input) << " : "
- << additional_info << "at state" << ToString(state_);
- }
- HandleWaitStop(is_user_input, hal_cli, fsm_input);
- } break;
- default:
- // host service explicitly calls restore and suspend
- ConfUiLog(FATAL) << "Must not be in the state of" << ToString(state_);
- break;
- }
- return state_;
-};
-
-bool Session::Suspend(SharedFD hal_cli) {
- if (state_ == MainLoopState::kInit) {
- // HAL sent wrong command
- ConfUiLog(FATAL)
- << "HAL sent wrong command, suspend, when the session is in kIinit";
- return false;
- }
- if (state_ == MainLoopState::kSuspended) {
- ConfUiLog(DEBUG) << "Already kSuspended state";
- return false;
- }
- saved_state_ = state_;
- state_ = MainLoopState::kSuspended;
- host_mode_ctrl_.SetMode(HostModeCtrl::ModeType::kAndroidMode);
- if (!packet::SendAck(hal_cli, session_id_, /*is success*/ true,
- "suspended")) {
- ConfUiLog(FATAL) << "I/O error";
- return false;
- }
- return true;
-}
-
-bool Session::Restore(SharedFD hal_cli) {
- if (state_ == MainLoopState::kInit) {
- // HAL sent wrong command
- ConfUiLog(FATAL)
- << "HAL sent wrong command, restore, when the session is in kIinit";
- return false;
- }
-
- if (state_ != MainLoopState::kSuspended) {
- ConfUiLog(DEBUG) << "Already Restored to state " + ToString(state_);
- return false;
- }
- host_mode_ctrl_.SetMode(HostModeCtrl::ModeType::kConfUI_Mode);
- if (!RenderDialog(prompt_, locale_)) {
- // the confirmation UI is driven by a user app, not running from the start
- // automatically so that means webRTC/vnc should have been set up
- ConfUiLog(ERROR) << "Dialog is not rendered. However, it should."
- << "No webRTC can't initiate any confirmation UI.";
- if (!packet::SendAck(hal_cli, session_id_, false,
- "render failed in restore")) {
- ConfUiLog(FATAL) << "Rendering failed in restore, and ack failed in I/O";
- }
- state_ = MainLoopState::kInit;
- return false;
- }
- if (!packet::SendAck(hal_cli, session_id_, true, "restored")) {
- ConfUiLog(FATAL) << "Ack to restore failed in I/O";
- }
- state_ = saved_state_;
- saved_state_ = MainLoopState::kInit;
- return true;
-}
-
-bool Session::Kill(SharedFD hal_cli, const std::string& response_msg) {
- state_ = MainLoopState::kAwaitCleanup;
- saved_state_ = MainLoopState::kInvalid;
- if (!packet::SendAck(hal_cli, session_id_, true, response_msg)) {
- ConfUiLog(FATAL) << "I/O error in ack to Abort";
- return false;
- }
- return true;
-}
-
-void Session::CleanUp() {
- if (state_ != MainLoopState::kAwaitCleanup) {
- ConfUiLog(FATAL) << "Clean up a session only when in kAwaitCleanup";
- }
- // common action done when the state is back to init state
- host_mode_ctrl_.SetMode(HostModeCtrl::ModeType::kAndroidMode);
-}
-
-void Session::ReportErrorToHal(SharedFD hal_cli, const std::string& msg) {
- // reset the session -- destroy it & recreate it with the same
- // session id
- state_ = MainLoopState::kAwaitCleanup;
- if (!packet::SendAck(hal_cli, session_id_, false, msg)) {
- ConfUiLog(FATAL) << "I/O error in sending ack to report rendering failure";
- }
- return;
-}
-
-bool Session::Abort(SharedFD hal_cli) { return Kill(hal_cli, "aborted"); }
-
-void Session::HandleInit(const bool is_user_input, SharedFD hal_cli,
- const FsmInput fsm_input,
- const std::string& additional_info) {
- using namespace cuttlefish::confui::packet;
- if (is_user_input) {
- // ignore user input
- state_ = MainLoopState::kInit;
- return;
- }
-
- ConfUiLog(DEBUG) << ToString(fsm_input) << "is handled in HandleInit";
- if (fsm_input != FsmInput::kHalStart) {
- ConfUiLog(ERROR) << "invalid cmd for Init State:" << ToString(fsm_input);
- // reset the session -- destroy it & recreate it with the same
- // session id
- ReportErrorToHal(hal_cli, "wrong hal command");
- return;
- }
-
- // Start Session
- ConfUiLog(DEBUG) << "Sending ack to hal_cli: "
- << Enum2Base(ConfUiCmd::kCliAck);
- host_mode_ctrl_.SetMode(HostModeCtrl::ModeType::kConfUI_Mode);
- auto confirmation_msg = additional_info;
- if (!RenderDialog(confirmation_msg, locale_)) {
- // the confirmation UI is driven by a user app, not running from the start
- // automatically so that means webRTC/vnc should have been set up
- ConfUiLog(ERROR) << "Dialog is not rendered. However, it should."
- << "No webRTC can't initiate any confirmation UI.";
- ReportErrorToHal(hal_cli, "rendering failed");
- return;
- }
- if (!packet::SendAck(hal_cli, session_id_, true, "started")) {
- ConfUiLog(FATAL) << "Ack to kStart failed in I/O";
- }
- state_ = MainLoopState::kInSession;
- return;
-}
-
-void Session::HandleInSession(const bool is_user_input, SharedFD hal_cli,
- const FsmInput fsm_input) {
- if (!is_user_input) {
- ConfUiLog(FATAL) << "cmd" << ToString(fsm_input)
- << "should not be handled in HandleInSession";
- ReportErrorToHal(hal_cli, "wrong hal command");
- return;
- }
-
- // send to hal_cli either confirm or cancel
- if (fsm_input != FsmInput::kUserConfirm &&
- fsm_input != FsmInput::kUserCancel) {
- /*
- * TODO(kwstephenkim@google.com): change here when other user inputs must
- * be handled
- *
- */
- if (!packet::SendAck(hal_cli, session_id_, true,
- "invalid user input error")) {
- // note that input is what we control in memory
- ConfUiCheck(false) << "Input must be either confirm or cancel for now.";
- }
- return;
- }
-
- ConfUiLog(DEBUG) << "In HandlieInSession, session" << session_id_
- << "is sending the user input" << ToString(fsm_input);
- auto selection = UserResponse::kConfirm;
- if (fsm_input == FsmInput::kUserCancel) {
- selection = UserResponse::kCancel;
- }
- if (!packet::SendResponse(hal_cli, session_id_, selection)) {
- ConfUiLog(FATAL) << "I/O error in sending user response to HAL";
- }
- state_ = MainLoopState::kWaitStop;
- return;
-}
-
-void Session::HandleWaitStop(const bool is_user_input, SharedFD hal_cli,
- const FsmInput fsm_input) {
- using namespace cuttlefish::confui::packet;
-
- if (is_user_input) {
- // ignore user input
- state_ = MainLoopState::kWaitStop;
- return;
- }
- if (fsm_input == FsmInput::kHalStop) {
- ConfUiLog(DEBUG) << "Handling Abort in kWaitStop.";
- Kill(hal_cli, "stopped");
- return;
- }
- ConfUiLog(FATAL) << "In WaitStop, received wrong HAL command "
- << ToString(fsm_input);
- state_ = MainLoopState::kAwaitCleanup;
- return;
-}
-
-} // end of namespace confui
-} // end of namespace cuttlefish
diff --git a/host/libs/confui/session.h b/host/libs/confui/session.h
deleted file mode 100644
index 87e98c9ff..000000000
--- a/host/libs/confui/session.h
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (C) 2021 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 <memory>
-
-#include "common/libs/confui/confui.h"
-#include "host/libs/confui/host_mode_ctrl.h"
-#include "host/libs/confui/host_renderer.h"
-#include "host/libs/confui/server_common.h"
-#include "host/libs/confui/session.h"
-#include "host/libs/screen_connector/screen_connector.h"
-
-namespace cuttlefish {
-namespace confui {
-
-/**
- * Confirmation UI Session
- *
- * E.g. Two guest apps could drive confirmation UI respectively,
- * and both are alive at the moment. Each needs one session
- *
- */
-class Session {
- public:
- Session(const std::string& session_id, const std::uint32_t display_num,
- ConfUiRenderer& host_renderer, HostModeCtrl& host_mode_ctrl,
- ScreenConnectorFrameRenderer& screen_connector,
- const std::string& locale = "en");
-
- bool IsConfUiActive() const;
-
- std::string GetId() { return session_id_; }
-
- MainLoopState GetState() { return state_; }
-
- MainLoopState Transition(const bool is_user_input, SharedFD& hal_cli,
- const FsmInput fsm_input,
- const std::string& additional_info);
-
- /**
- * this make a transition from kWaitStop or kInSession to kSuspend
- */
- bool Suspend(SharedFD hal_cli);
-
- /**
- * this make a transition from kRestore to the saved state
- */
- bool Restore(SharedFD hal_cli);
-
- // abort session
- bool Abort(SharedFD hal_cli);
-
- bool IsSuspended() const;
- void CleanUp();
-
- private:
- /** create a frame, and render it on the vnc/webRTC client
- *
- * note that this does not check host_ctrl_mode_
- */
- bool RenderDialog(const std::string& msg, const std::string& locale);
-
- // transition actions on each state per input
- // the new state will be save to the state_ at the end of each call
- void HandleInit(const bool is_user_input, SharedFD hal_cli,
- const FsmInput fsm_input, const std::string& additional_info);
-
- void HandleWaitStop(const bool is_user_input, SharedFD hal_cli,
- const FsmInput fsm_input);
-
- void HandleInSession(const bool is_user_input, SharedFD hal_cli,
- const FsmInput fsm_input);
-
- bool Kill(SharedFD hal_cli, const std::string& response_msg);
-
- // report with an error ack to HAL, and reset the FSM
- void ReportErrorToHal(SharedFD hal_cli, const std::string& msg);
-
- const std::string session_id_;
- const std::uint32_t display_num_;
- // host renderer is shared across sessions
- ConfUiRenderer& renderer_;
- HostModeCtrl& host_mode_ctrl_;
- ScreenConnectorFrameRenderer& screen_connector_;
-
- // only context to save
- std::string prompt_;
- std::string locale_;
-
- // effectively, this variables are shared with vnc, webRTC thread
- // the input demuxer will check the confirmation UI mode based on this
- std::atomic<MainLoopState> state_;
- MainLoopState saved_state_; // for restore/suspend
-};
-} // end of namespace confui
-} // end of namespace cuttlefish
diff --git a/host/libs/graphics_detector/Android.bp b/host/libs/graphics_detector/Android.bp
deleted file mode 100644
index bd6a55e1b..000000000
--- a/host/libs/graphics_detector/Android.bp
+++ /dev/null
@@ -1,46 +0,0 @@
-//
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package {
- // See: http://go/android-license-faq
- // A large-scale-change added 'default_applicable_licenses' to import
- // all of the 'license_kinds' from "device_google_cuttlefish_license"
- // to get the below license kinds:
- // SPDX-license-identifier-Apache-2.0
- // SPDX-license-identifier-MIT
- default_applicable_licenses: ["device_google_cuttlefish_license"],
-}
-
-cc_library_headers {
- name: "egl_headers",
- export_include_dirs: ["include"],
- defaults: ["cuttlefish_host"],
-}
-
-cc_library_static {
- name: "libcuttlefish_graphics_detector",
- srcs: [
- "graphics_detector.cpp",
- ],
- header_libs: [
- "egl_headers",
- "vulkan_headers",
- ],
- shared_libs: [
- "libbase",
- "liblog",
- ],
- defaults: ["cuttlefish_host"],
-}
diff --git a/host/libs/graphics_detector/graphics_detector.cpp b/host/libs/graphics_detector/graphics_detector.cpp
deleted file mode 100644
index 367e637b4..000000000
--- a/host/libs/graphics_detector/graphics_detector.cpp
+++ /dev/null
@@ -1,604 +0,0 @@
-/*
- * Copyright (C) 2020 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 "host/libs/graphics_detector/graphics_detector.h"
-
-#include <sstream>
-#include <vector>
-
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-#include <android-base/logging.h>
-#include <android-base/strings.h>
-#include <dlfcn.h>
-#include <sys/wait.h>
-#include <vulkan/vulkan.h>
-
-namespace cuttlefish {
-namespace {
-
-constexpr const char kEglLib[] = "libEGL.so.1";
-constexpr const char kGlLib[] = "libOpenGL.so.0";
-constexpr const char kGles1Lib[] = "libGLESv1_CM.so.1";
-constexpr const char kGles2Lib[] = "libGLESv2.so.2";
-constexpr const char kVulkanLib[] = "libvulkan.so.1";
-
-constexpr const char kSurfacelessContextExt[] = "EGL_KHR_surfaceless_context";
-
-class Closer {
-public:
- Closer(std::function<void()> on_close) : on_close_(on_close) {}
- ~Closer() { on_close_(); }
-
-private:
- std::function<void()> on_close_;
-};
-
-struct LibraryCloser {
- public:
- void operator()(void* library) { dlclose(library); }
-};
-
-using ManagedLibrary = std::unique_ptr<void, LibraryCloser>;
-
-void PopulateGlAvailability(GraphicsAvailability* availability) {
- ManagedLibrary gl_lib(dlopen(kGlLib, RTLD_NOW | RTLD_LOCAL));
- if (!gl_lib) {
- LOG(VERBOSE) << "Failed to dlopen " << kGlLib << ".";
- return;
- }
- LOG(VERBOSE) << "Loaded " << kGlLib << ".";
- availability->has_gl = true;
-}
-
-void PopulateGles1Availability(GraphicsAvailability* availability) {
- ManagedLibrary gles1_lib(dlopen(kGles1Lib, RTLD_NOW | RTLD_LOCAL));
- if (!gles1_lib) {
- LOG(VERBOSE) << "Failed to dlopen " << kGles1Lib << ".";
- return;
- }
- LOG(VERBOSE) << "Loaded " << kGles1Lib << ".";
- availability->has_gles1 = true;
-}
-
-void PopulateGles2Availability(GraphicsAvailability* availability) {
- ManagedLibrary gles2_lib(dlopen(kGles2Lib, RTLD_NOW | RTLD_LOCAL));
- if (!gles2_lib) {
- LOG(VERBOSE) << "Failed to dlopen " << kGles2Lib << ".";
- return;
- }
- LOG(VERBOSE) << "Loaded " << kGles2Lib << ".";
- availability->has_gles2 = true;
-}
-
-void PopulateEglAvailability(GraphicsAvailability* availability) {
- ManagedLibrary egllib(dlopen(kEglLib, RTLD_NOW | RTLD_LOCAL));
- if (!egllib) {
- LOG(VERBOSE) << "Failed to dlopen " << kEglLib << ".";
- return;
- }
- LOG(VERBOSE) << "Loaded " << kEglLib << ".";
- availability->has_egl = true;
-
- PFNEGLGETPROCADDRESSPROC eglGetProcAddress =
- reinterpret_cast<PFNEGLGETPROCADDRESSPROC>(
- dlsym(egllib.get(), "eglGetProcAddress"));
- if (eglGetProcAddress == nullptr) {
- LOG(VERBOSE) << "Failed to find function eglGetProcAddress.";
- return;
- }
- LOG(VERBOSE) << "Loaded eglGetProcAddress.";
-
- // Some implementations have it so that eglGetProcAddress is only for
- // loading EXT functions.
- auto EglLoadFunction = [&](const char* name) {
- void* func = dlsym(egllib.get(), name);
- if (func == NULL) {
- func = reinterpret_cast<void*>(eglGetProcAddress(name));
- }
- return func;
- };
-
- PFNEGLGETERRORPROC eglGetError =
- reinterpret_cast<PFNEGLGETERRORPROC>(EglLoadFunction("eglGetError"));
- if (eglGetError == nullptr) {
- LOG(VERBOSE) << "Failed to find function eglGetError.";
- return;
- }
- LOG(VERBOSE) << "Loaded eglGetError.";
-
- PFNEGLGETDISPLAYPROC eglGetDisplay =
- reinterpret_cast<PFNEGLGETDISPLAYPROC>(EglLoadFunction("eglGetDisplay"));
- if (eglGetDisplay == nullptr) {
- LOG(VERBOSE) << "Failed to find function eglGetDisplay.";
- return;
- }
- LOG(VERBOSE) << "Loaded eglGetDisplay.";
-
- EGLDisplay default_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
- if (default_display == EGL_NO_DISPLAY) {
- LOG(VERBOSE) << "Failed to get default display. " << eglGetError();
- return;
- }
- LOG(VERBOSE) << "Found default display.";
- availability->has_egl_default_display = true;
-
- PFNEGLINITIALIZEPROC eglInitialize =
- reinterpret_cast<PFNEGLINITIALIZEPROC>(EglLoadFunction("eglInitialize"));
- if (eglInitialize == nullptr) {
- LOG(VERBOSE) << "Failed to find function eglQueryString";
- return;
- }
-
- EGLint client_version_major = 0;
- EGLint client_version_minor = 0;
- if (eglInitialize(default_display,
- &client_version_major,
- &client_version_minor) != EGL_TRUE) {
- LOG(VERBOSE) << "Failed to initialize default display.";
- return;
- }
- LOG(VERBOSE) << "Initialized default display.";
-
- PFNEGLQUERYSTRINGPROC eglQueryString =
- reinterpret_cast<PFNEGLQUERYSTRINGPROC>(EglLoadFunction("eglQueryString"));
- if (eglQueryString == nullptr) {
- LOG(VERBOSE) << "Failed to find function eglQueryString";
- return;
- }
- LOG(VERBOSE) << "Loaded eglQueryString.";
-
- std::string client_extensions;
- if (client_version_major >= 1 && client_version_minor >= 5) {
- client_extensions = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
- }
- availability->egl_client_extensions = client_extensions;
-
- EGLDisplay display = EGL_NO_DISPLAY;
-
- if (client_extensions.find("EGL_EXT_platform_base") != std::string::npos) {
- LOG(VERBOSE) << "Client extension EGL_EXT_platform_base is supported.";
-
- PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT =
- reinterpret_cast<PFNEGLGETPLATFORMDISPLAYEXTPROC>(
- EglLoadFunction("eglGetPlatformDisplayEXT"));
- if (eglGetPlatformDisplayEXT == nullptr) {
- LOG(VERBOSE) << "Failed to find function eglGetPlatformDisplayEXT";
- return;
- }
-
- display =
- eglGetPlatformDisplayEXT(EGL_PLATFORM_SURFACELESS_MESA,
- EGL_DEFAULT_DISPLAY,
- NULL);
- } else {
- LOG(VERBOSE) << "Failed to find client extension EGL_EXT_platform_base.";
- }
- if (display == EGL_NO_DISPLAY) {
- LOG(VERBOSE) << "Failed to get EGL_PLATFORM_SURFACELESS_MESA display..."
- << "failing back to EGL_DEFAULT_DISPLAY display.";
- display = default_display;
- }
- if (display == EGL_NO_DISPLAY) {
- LOG(VERBOSE) << "Failed to find display.";
- return;
- }
-
- if (eglInitialize(display,
- &client_version_major,
- &client_version_minor) != EGL_TRUE) {
- LOG(VERBOSE) << "Failed to initialize surfaceless display.";
- return;
- }
- LOG(VERBOSE) << "Initialized surfaceless display.";
-
- const std::string version_string = eglQueryString(display, EGL_VERSION);
- if (version_string.empty()) {
- LOG(VERBOSE) << "Failed to query client version.";
- return;
- }
- LOG(VERBOSE) << "Found version: " << version_string;
- availability->egl_version = version_string;
-
- const std::string vendor_string = eglQueryString(display, EGL_VENDOR);
- if (vendor_string.empty()) {
- LOG(VERBOSE) << "Failed to query vendor.";
- return;
- }
- LOG(VERBOSE) << "Found vendor: " << vendor_string;
- availability->egl_vendor = vendor_string;
-
- const std::string extensions_string = eglQueryString(display, EGL_EXTENSIONS);
- if (extensions_string.empty()) {
- LOG(VERBOSE) << "Failed to query extensions.";
- return;
- }
- LOG(VERBOSE) << "Found extensions: " << extensions_string;
- availability->egl_extensions = extensions_string;
-
- if (extensions_string.find(kSurfacelessContextExt) == std::string::npos) {
- LOG(VERBOSE) << "Failed to find extension EGL_KHR_surfaceless_context.";
- return;
- }
-
- const std::string display_apis_string = eglQueryString(display,
- EGL_CLIENT_APIS);
- if (display_apis_string.empty()) {
- LOG(VERBOSE) << "Failed to query display apis.";
- return;
- }
- LOG(VERBOSE) << "Found display apis: " << display_apis_string;
-
- PFNEGLBINDAPIPROC eglBindAPI =
- reinterpret_cast<PFNEGLBINDAPIPROC>(EglLoadFunction("eglBindAPI"));
- if (eglBindAPI == nullptr) {
- LOG(VERBOSE) << "Failed to find function eglBindAPI";
- return;
- }
- LOG(VERBOSE) << "Loaded eglBindAPI.";
-
- if (eglBindAPI(EGL_OPENGL_ES_API) == EGL_FALSE) {
- LOG(VERBOSE) << "Failed to bind GLES API.";
- return;
- }
- LOG(VERBOSE) << "Bound GLES API.";
-
- PFNEGLCHOOSECONFIGPROC eglChooseConfig =
- reinterpret_cast<PFNEGLCHOOSECONFIGPROC>(
- EglLoadFunction("eglChooseConfig"));
- if (eglChooseConfig == nullptr) {
- LOG(VERBOSE) << "Failed to find function eglChooseConfig";
- return;
- }
- LOG(VERBOSE) << "Loaded eglChooseConfig.";
-
- const EGLint framebuffer_config_attributes[] = {
- EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
- EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
- EGL_RED_SIZE, 1,
- EGL_GREEN_SIZE, 1,
- EGL_BLUE_SIZE, 1,
- EGL_ALPHA_SIZE, 0,
- EGL_NONE,
- };
-
- EGLConfig framebuffer_config;
- EGLint num_framebuffer_configs = 0;
- if (eglChooseConfig(display,
- framebuffer_config_attributes,
- &framebuffer_config,
- 1,
- &num_framebuffer_configs) != EGL_TRUE) {
- LOG(VERBOSE) << "Failed to find matching framebuffer config.";
- return;
- }
- LOG(VERBOSE) << "Found matching framebuffer config.";
-
- PFNEGLCREATECONTEXTPROC eglCreateContext =
- reinterpret_cast<PFNEGLCREATECONTEXTPROC>(
- EglLoadFunction("eglCreateContext"));
- if (eglCreateContext == nullptr) {
- LOG(VERBOSE) << "Failed to find function eglCreateContext";
- return;
- }
- LOG(VERBOSE) << "Loaded eglCreateContext.";
-
- PFNEGLDESTROYCONTEXTPROC eglDestroyContext =
- reinterpret_cast<PFNEGLDESTROYCONTEXTPROC>(
- EglLoadFunction("eglDestroyContext"));
- if (eglDestroyContext == nullptr) {
- LOG(VERBOSE) << "Failed to find function eglDestroyContext";
- return;
- }
- LOG(VERBOSE) << "Loaded eglDestroyContext.";
-
- const EGLint context_attributes[] = {
- EGL_CONTEXT_CLIENT_VERSION, 2,
- EGL_NONE
- };
-
- EGLContext context = eglCreateContext(display,
- framebuffer_config,
- EGL_NO_CONTEXT,
- context_attributes);
- if (context == EGL_NO_CONTEXT) {
- LOG(VERBOSE) << "Failed to create EGL context.";
- return;
- }
- LOG(VERBOSE) << "Created EGL context.";
- Closer context_closer([&]() { eglDestroyContext(display, context); });
-
- PFNEGLMAKECURRENTPROC eglMakeCurrent =
- reinterpret_cast<PFNEGLMAKECURRENTPROC>(EglLoadFunction("eglMakeCurrent"));
- if (eglMakeCurrent == nullptr) {
- LOG(VERBOSE) << "Failed to find function eglMakeCurrent";
- return;
- }
- LOG(VERBOSE) << "Loaded eglMakeCurrent.";
-
- if (eglMakeCurrent(display,
- EGL_NO_SURFACE,
- EGL_NO_SURFACE,
- context) != EGL_TRUE) {
- LOG(VERBOSE) << "Failed to make EGL context current.";
- return;
- }
- LOG(VERBOSE) << "Make EGL context current.";
- availability->has_egl_surfaceless_with_gles = true;
-}
-
-void PopulateVulkanAvailability(GraphicsAvailability* availability) {
- ManagedLibrary vklib(dlopen(kVulkanLib, RTLD_NOW | RTLD_LOCAL));
- if (!vklib) {
- LOG(VERBOSE) << "Failed to dlopen " << kVulkanLib << ".";
- return;
- }
- LOG(VERBOSE) << "Loaded " << kVulkanLib << ".";
- availability->has_vulkan = true;
-
- uint32_t instance_version = 0;
-
- PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr =
- reinterpret_cast<PFN_vkGetInstanceProcAddr>(
- dlsym(vklib.get(), "vkGetInstanceProcAddr"));
- if (vkGetInstanceProcAddr == nullptr) {
- LOG(VERBOSE) << "Failed to find symbol vkGetInstanceProcAddr.";
- return;
- }
-
- PFN_vkEnumerateInstanceVersion vkEnumerateInstanceVersion =
- reinterpret_cast<PFN_vkEnumerateInstanceVersion>(
- dlsym(vklib.get(), "vkEnumerateInstanceVersion"));
- if (vkEnumerateInstanceVersion == nullptr ||
- vkEnumerateInstanceVersion(&instance_version) != VK_SUCCESS) {
- instance_version = VK_API_VERSION_1_0;
- }
-
- PFN_vkCreateInstance vkCreateInstance =
- reinterpret_cast<PFN_vkCreateInstance>(
- vkGetInstanceProcAddr(VK_NULL_HANDLE, "vkCreateInstance"));
- if (vkCreateInstance == nullptr) {
- LOG(VERBOSE) << "Failed to get function vkCreateInstance.";
- return;
- }
-
- VkApplicationInfo application_info;
- application_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
- application_info.pNext = nullptr;
- application_info.pApplicationName = "";
- application_info.applicationVersion = 1;
- application_info.pEngineName = "";
- application_info.engineVersion = 1;
- application_info.apiVersion = instance_version;
-
- VkInstanceCreateInfo instance_create_info = {};
- instance_create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
- instance_create_info.pNext = nullptr;
- instance_create_info.flags = 0;
- instance_create_info.pApplicationInfo = &application_info;
- instance_create_info.enabledLayerCount = 0;
- instance_create_info.ppEnabledLayerNames = nullptr;
- instance_create_info.enabledExtensionCount = 0;
- instance_create_info.ppEnabledExtensionNames = nullptr;
-
- VkInstance instance = VK_NULL_HANDLE;
- VkResult result = vkCreateInstance(&instance_create_info, nullptr, &instance);
- if (result != VK_SUCCESS) {
- if (result == VK_ERROR_OUT_OF_HOST_MEMORY) {
- LOG(VERBOSE) << "Failed to create Vulkan instance: "
- << "VK_ERROR_OUT_OF_HOST_MEMORY.";
- } else if (result == VK_ERROR_OUT_OF_DEVICE_MEMORY) {
- LOG(VERBOSE) << "Failed to create Vulkan instance: "
- << "VK_ERROR_OUT_OF_DEVICE_MEMORY.";
- } else if (result == VK_ERROR_INITIALIZATION_FAILED) {
- LOG(VERBOSE) << "Failed to create Vulkan instance: "
- << "VK_ERROR_INITIALIZATION_FAILED.";
- } else if (result == VK_ERROR_LAYER_NOT_PRESENT) {
- LOG(VERBOSE) << "Failed to create Vulkan instance: "
- << "VK_ERROR_LAYER_NOT_PRESENT.";
- } else if (result == VK_ERROR_EXTENSION_NOT_PRESENT) {
- LOG(VERBOSE) << "Failed to create Vulkan instance: "
- << "VK_ERROR_EXTENSION_NOT_PRESENT.";
- } else if (result == VK_ERROR_INCOMPATIBLE_DRIVER) {
- LOG(VERBOSE) << "Failed to create Vulkan instance: "
- << "VK_ERROR_INCOMPATIBLE_DRIVER.";
- } else {
- LOG(VERBOSE) << "Failed to create Vulkan instance.";
- }
- return;
- }
-
- PFN_vkDestroyInstance vkDestroyInstance =
- reinterpret_cast<PFN_vkDestroyInstance>(
- vkGetInstanceProcAddr(instance, "vkDestroyInstance"));
- if (vkDestroyInstance == nullptr) {
- LOG(VERBOSE) << "Failed to get function vkDestroyInstance.";
- return;
- }
-
- Closer instancecloser([&]() {vkDestroyInstance(instance, nullptr); });
-
- PFN_vkEnumeratePhysicalDevices vkEnumeratePhysicalDevices =
- reinterpret_cast<PFN_vkEnumeratePhysicalDevices>(
- vkGetInstanceProcAddr(instance, "vkEnumeratePhysicalDevices"));
- if (vkEnumeratePhysicalDevices == nullptr) {
- LOG(VERBOSE) << "Failed to "
- << "vkGetInstanceProcAddr(vkEnumeratePhysicalDevices).";
- return;
- }
-
- PFN_vkGetPhysicalDeviceProperties vkGetPhysicalDeviceProperties =
- reinterpret_cast<PFN_vkGetPhysicalDeviceProperties>(
- vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceProperties"));
- if (vkGetPhysicalDeviceProperties == nullptr) {
- LOG(VERBOSE) << "Failed to "
- << "vkGetInstanceProcAddr(vkGetPhysicalDeviceProperties).";
- return;
- }
-
- auto vkEnumerateDeviceExtensionProperties =
- reinterpret_cast<PFN_vkEnumerateDeviceExtensionProperties>(
- vkGetInstanceProcAddr(instance, "vkEnumerateDeviceExtensionProperties"));
- if (vkEnumerateDeviceExtensionProperties == nullptr) {
- LOG(VERBOSE) << "Failed to "
- << "vkGetInstanceProcAddr("
- << "vkEnumerateDeviceExtensionProperties"
- << ").";
- return;
- }
-
- uint32_t device_count = 0;
- result = vkEnumeratePhysicalDevices(instance, &device_count, nullptr);
- if (result != VK_SUCCESS) {
- if (result == VK_INCOMPLETE) {
- LOG(VERBOSE) << "Failed to enumerate physical device count: "
- << "VK_INCOMPLETE";
- } else if (result == VK_ERROR_OUT_OF_HOST_MEMORY) {
- LOG(VERBOSE) << "Failed to enumerate physical device count: "
- << "VK_ERROR_OUT_OF_HOST_MEMORY";
- } else if (result == VK_ERROR_OUT_OF_DEVICE_MEMORY) {
- LOG(VERBOSE) << "Failed to enumerate physical device count: "
- << "VK_ERROR_OUT_OF_DEVICE_MEMORY";
- } else if (result == VK_ERROR_INITIALIZATION_FAILED) {
- LOG(VERBOSE) << "Failed to enumerate physical device count: "
- << "VK_ERROR_INITIALIZATION_FAILED";
- } else {
- LOG(VERBOSE) << "Failed to enumerate physical device count.";
- }
- return;
- }
-
- if (device_count == 0) {
- LOG(VERBOSE) << "No physical devices present.";
- return;
- }
-
- std::vector<VkPhysicalDevice> devices(device_count, VK_NULL_HANDLE);
- result = vkEnumeratePhysicalDevices(instance, &device_count, devices.data());
- if (result != VK_SUCCESS) {
- LOG(VERBOSE) << "Failed to enumerate physical devices.";
- return;
- }
-
- for (VkPhysicalDevice device : devices) {
- VkPhysicalDeviceProperties device_properties = {};
- vkGetPhysicalDeviceProperties(device, &device_properties);
-
- uint32_t device_extensions_count = 0;
- vkEnumerateDeviceExtensionProperties(device,
- nullptr,
- &device_extensions_count,
- nullptr);
-
- std::vector<VkExtensionProperties> device_extensions;
- device_extensions.resize(device_extensions_count);
-
- vkEnumerateDeviceExtensionProperties(device,
- nullptr,
- &device_extensions_count,
- device_extensions.data());
-
- std::vector<const char*> device_extensions_strings;
- for (const VkExtensionProperties& device_extension : device_extensions) {
- device_extensions_strings.push_back(device_extension.extensionName);
- }
-
- std::string device_extensions_string =
- android::base::Join(device_extensions_strings, ' ');
-
- if (device_properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) {
- availability->has_discrete_gpu = true;
- availability->discrete_gpu_device_name = device_properties.deviceName;
- availability->discrete_gpu_device_extensions = device_extensions_string;
- break;
- }
- }
-}
-
-GraphicsAvailability GetGraphicsAvailability() {
- GraphicsAvailability availability;
-
- PopulateEglAvailability(&availability);
- PopulateGlAvailability(&availability);
- PopulateGles1Availability(&availability);
- PopulateGles2Availability(&availability);
- PopulateVulkanAvailability(&availability);
-
- return availability;
-}
-
-} // namespace
-
-bool ShouldEnableAcceleratedRendering(
- const GraphicsAvailability& availability) {
- return availability.has_egl && availability.has_egl_surfaceless_with_gles &&
- availability.has_discrete_gpu;
-}
-
-// Runs GetGraphicsAvailability() inside of a subprocess first to ensure that
-// GetGraphicsAvailability() can complete successfully without crashing
-// assemble_cvd. Configurations such as GCE instances without a GPU but with GPU
-// drivers for example have seen crashes.
-GraphicsAvailability GetGraphicsAvailabilityWithSubprocessCheck() {
- pid_t pid = fork();
- if (pid == 0) {
- GetGraphicsAvailability();
- std::exit(0);
- }
- int status;
- if (waitpid(pid, &status, 0) != pid) {
- PLOG(ERROR) << "Failed to wait for graphics check subprocess";
- return GraphicsAvailability{};
- }
- if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
- return GetGraphicsAvailability();
- }
- LOG(VERBOSE) << "Subprocess for detect_graphics failed with " << status;
- return GraphicsAvailability{};
-}
-
-std::ostream& operator<<(std::ostream& stream,
- const GraphicsAvailability& availability) {
- std::ios_base::fmtflags flags_backup(stream.flags());
- stream << std::boolalpha;
- stream << "Graphics Availability:\n";
- stream << "OpenGL available: " << availability.has_gl << "\n";
- stream << "OpenGL ES1 available: " << availability.has_gles1 << "\n";
- stream << "OpenGL ES2 available: " << availability.has_gles2 << "\n";
- stream << "EGL available: " << availability.has_egl << "\n";
- stream << "EGL client extensions: " << availability.egl_client_extensions
- << "\n";
- stream << "EGL default display available: "
- << availability.has_egl_default_display << "\n";
- stream << "EGL display vendor: " << availability.egl_vendor << "\n";
- stream << "EGL display version: " << availability.egl_version << "\n";
- stream << "EGL display extensions: " << availability.egl_extensions << "\n";
- stream << "EGL surfaceless display with GLES: "
- << availability.has_egl_surfaceless_with_gles << "\n";
- stream << "Vulkan available: " << availability.has_vulkan << "\n";
- stream << "Vulkan discrete GPU detected: " << availability.has_discrete_gpu
- << "\n";
- if (availability.has_discrete_gpu) {
- stream << "Vulkan discrete GPU device name: "
- << availability.discrete_gpu_device_name << "\n";
- stream << "Vulkan discrete GPU device extensions: "
- << availability.discrete_gpu_device_extensions << "\n";
- }
- stream.flags(flags_backup);
- return stream;
-}
-
-} // namespace cuttlefish
diff --git a/host/libs/graphics_detector/graphics_detector.h b/host/libs/graphics_detector/graphics_detector.h
deleted file mode 100644
index 83a70685a..000000000
--- a/host/libs/graphics_detector/graphics_detector.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2020 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 <ostream>
-#include <string>
-
-namespace cuttlefish {
-
-struct GraphicsAvailability {
- bool has_gl = false;
- bool has_gles1 = false;
- bool has_gles2 = false;
- bool has_egl = false;
- bool has_egl_default_display = false;
- std::string egl_client_extensions;
- std::string egl_version;
- std::string egl_vendor;
- std::string egl_extensions;
- bool has_egl_surfaceless_with_gles = false;
- bool has_vulkan = false;
- bool has_discrete_gpu = false;
- std::string discrete_gpu_device_name;
- std::string discrete_gpu_device_extensions;
-};
-
-bool ShouldEnableAcceleratedRendering(const GraphicsAvailability& availability);
-GraphicsAvailability GetGraphicsAvailabilityWithSubprocessCheck();
-
-std::ostream& operator<<(std::ostream& out, const GraphicsAvailability& info);
-
-} // namespace cuttlefish
diff --git a/host/libs/graphics_detector/include/EGL/egl.h b/host/libs/graphics_detector/include/EGL/egl.h
deleted file mode 100644
index e5dd15bb7..000000000
--- a/host/libs/graphics_detector/include/EGL/egl.h
+++ /dev/null
@@ -1,361 +0,0 @@
-#ifndef __egl_h_
-#define __egl_h_ 1
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
-** Copyright (c) 2013-2017 The Khronos Group Inc.
-**
-** Permission is hereby granted, free of charge, to any person obtaining a
-** copy of this software and/or associated documentation files (the
-** "Materials"), to deal in the Materials without restriction, including
-** without limitation the rights to use, copy, modify, merge, publish,
-** distribute, sublicense, and/or sell copies of the Materials, and to
-** permit persons to whom the Materials are furnished to do so, subject to
-** the following conditions:
-**
-** The above copyright notice and this permission notice shall be included
-** in all copies or substantial portions of the Materials.
-**
-** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
-*/
-/*
-** This header is generated from the Khronos EGL XML API Registry.
-** The current version of the Registry, generator scripts
-** used to make the header, and the header can be found at
-** http://www.khronos.org/registry/egl
-**
-** Khronos $Git commit SHA1: b5409265f3 $ on $Git commit date: 2020-02-20 08:24:34 -0800 $
-*/
-
-#include <EGL/eglplatform.h>
-
-#ifndef EGL_EGL_PROTOTYPES
-#define EGL_EGL_PROTOTYPES 1
-#endif
-
-/* Generated on date 20200220 */
-
-/* Generated C header for:
- * API: egl
- * Versions considered: .*
- * Versions emitted: .*
- * Default extensions included: None
- * Additional extensions included: _nomatch_^
- * Extensions removed: _nomatch_^
- */
-
-#ifndef EGL_VERSION_1_0
-#define EGL_VERSION_1_0 1
-typedef unsigned int EGLBoolean;
-typedef void *EGLDisplay;
-#include <KHR/khrplatform.h>
-#include <EGL/eglplatform.h>
-typedef void *EGLConfig;
-typedef void *EGLSurface;
-typedef void *EGLContext;
-typedef void (*__eglMustCastToProperFunctionPointerType)(void);
-#define EGL_ALPHA_SIZE 0x3021
-#define EGL_BAD_ACCESS 0x3002
-#define EGL_BAD_ALLOC 0x3003
-#define EGL_BAD_ATTRIBUTE 0x3004
-#define EGL_BAD_CONFIG 0x3005
-#define EGL_BAD_CONTEXT 0x3006
-#define EGL_BAD_CURRENT_SURFACE 0x3007
-#define EGL_BAD_DISPLAY 0x3008
-#define EGL_BAD_MATCH 0x3009
-#define EGL_BAD_NATIVE_PIXMAP 0x300A
-#define EGL_BAD_NATIVE_WINDOW 0x300B
-#define EGL_BAD_PARAMETER 0x300C
-#define EGL_BAD_SURFACE 0x300D
-#define EGL_BLUE_SIZE 0x3022
-#define EGL_BUFFER_SIZE 0x3020
-#define EGL_CONFIG_CAVEAT 0x3027
-#define EGL_CONFIG_ID 0x3028
-#define EGL_CORE_NATIVE_ENGINE 0x305B
-#define EGL_DEPTH_SIZE 0x3025
-#define EGL_DONT_CARE EGL_CAST(EGLint,-1)
-#define EGL_DRAW 0x3059
-#define EGL_EXTENSIONS 0x3055
-#define EGL_FALSE 0
-#define EGL_GREEN_SIZE 0x3023
-#define EGL_HEIGHT 0x3056
-#define EGL_LARGEST_PBUFFER 0x3058
-#define EGL_LEVEL 0x3029
-#define EGL_MAX_PBUFFER_HEIGHT 0x302A
-#define EGL_MAX_PBUFFER_PIXELS 0x302B
-#define EGL_MAX_PBUFFER_WIDTH 0x302C
-#define EGL_NATIVE_RENDERABLE 0x302D
-#define EGL_NATIVE_VISUAL_ID 0x302E
-#define EGL_NATIVE_VISUAL_TYPE 0x302F
-#define EGL_NONE 0x3038
-#define EGL_NON_CONFORMANT_CONFIG 0x3051
-#define EGL_NOT_INITIALIZED 0x3001
-#define EGL_NO_CONTEXT EGL_CAST(EGLContext,0)
-#define EGL_NO_DISPLAY EGL_CAST(EGLDisplay,0)
-#define EGL_NO_SURFACE EGL_CAST(EGLSurface,0)
-#define EGL_PBUFFER_BIT 0x0001
-#define EGL_PIXMAP_BIT 0x0002
-#define EGL_READ 0x305A
-#define EGL_RED_SIZE 0x3024
-#define EGL_SAMPLES 0x3031
-#define EGL_SAMPLE_BUFFERS 0x3032
-#define EGL_SLOW_CONFIG 0x3050
-#define EGL_STENCIL_SIZE 0x3026
-#define EGL_SUCCESS 0x3000
-#define EGL_SURFACE_TYPE 0x3033
-#define EGL_TRANSPARENT_BLUE_VALUE 0x3035
-#define EGL_TRANSPARENT_GREEN_VALUE 0x3036
-#define EGL_TRANSPARENT_RED_VALUE 0x3037
-#define EGL_TRANSPARENT_RGB 0x3052
-#define EGL_TRANSPARENT_TYPE 0x3034
-#define EGL_TRUE 1
-#define EGL_VENDOR 0x3053
-#define EGL_VERSION 0x3054
-#define EGL_WIDTH 0x3057
-#define EGL_WINDOW_BIT 0x0004
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLCHOOSECONFIGPROC) (EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLCOPYBUFFERSPROC) (EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target);
-typedef EGLContext (EGLAPIENTRYP PFNEGLCREATECONTEXTPROC) (EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list);
-typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATEPBUFFERSURFACEPROC) (EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list);
-typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATEPIXMAPSURFACEPROC) (EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list);
-typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATEWINDOWSURFACEPROC) (EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYCONTEXTPROC) (EGLDisplay dpy, EGLContext ctx);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSURFACEPROC) (EGLDisplay dpy, EGLSurface surface);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETCONFIGATTRIBPROC) (EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETCONFIGSPROC) (EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config);
-typedef EGLDisplay (EGLAPIENTRYP PFNEGLGETCURRENTDISPLAYPROC) (void);
-typedef EGLSurface (EGLAPIENTRYP PFNEGLGETCURRENTSURFACEPROC) (EGLint readdraw);
-typedef EGLDisplay (EGLAPIENTRYP PFNEGLGETDISPLAYPROC) (EGLNativeDisplayType display_id);
-typedef EGLint (EGLAPIENTRYP PFNEGLGETERRORPROC) (void);
-typedef __eglMustCastToProperFunctionPointerType (EGLAPIENTRYP PFNEGLGETPROCADDRESSPROC) (const char *procname);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLINITIALIZEPROC) (EGLDisplay dpy, EGLint *major, EGLint *minor);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLMAKECURRENTPROC) (EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYCONTEXTPROC) (EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value);
-typedef const char *(EGLAPIENTRYP PFNEGLQUERYSTRINGPROC) (EGLDisplay dpy, EGLint name);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSURFACEPROC) (EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLSWAPBUFFERSPROC) (EGLDisplay dpy, EGLSurface surface);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLTERMINATEPROC) (EGLDisplay dpy);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLWAITGLPROC) (void);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLWAITNATIVEPROC) (EGLint engine);
-#if EGL_EGL_PROTOTYPES
-EGLAPI EGLBoolean EGLAPIENTRY eglChooseConfig (EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config);
-EGLAPI EGLBoolean EGLAPIENTRY eglCopyBuffers (EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target);
-EGLAPI EGLContext EGLAPIENTRY eglCreateContext (EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list);
-EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferSurface (EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list);
-EGLAPI EGLSurface EGLAPIENTRY eglCreatePixmapSurface (EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list);
-EGLAPI EGLSurface EGLAPIENTRY eglCreateWindowSurface (EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list);
-EGLAPI EGLBoolean EGLAPIENTRY eglDestroyContext (EGLDisplay dpy, EGLContext ctx);
-EGLAPI EGLBoolean EGLAPIENTRY eglDestroySurface (EGLDisplay dpy, EGLSurface surface);
-EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigAttrib (EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value);
-EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigs (EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config);
-EGLAPI EGLDisplay EGLAPIENTRY eglGetCurrentDisplay (void);
-EGLAPI EGLSurface EGLAPIENTRY eglGetCurrentSurface (EGLint readdraw);
-EGLAPI EGLDisplay EGLAPIENTRY eglGetDisplay (EGLNativeDisplayType display_id);
-EGLAPI EGLint EGLAPIENTRY eglGetError (void);
-EGLAPI __eglMustCastToProperFunctionPointerType EGLAPIENTRY eglGetProcAddress (const char *procname);
-EGLAPI EGLBoolean EGLAPIENTRY eglInitialize (EGLDisplay dpy, EGLint *major, EGLint *minor);
-EGLAPI EGLBoolean EGLAPIENTRY eglMakeCurrent (EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx);
-EGLAPI EGLBoolean EGLAPIENTRY eglQueryContext (EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value);
-EGLAPI const char *EGLAPIENTRY eglQueryString (EGLDisplay dpy, EGLint name);
-EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurface (EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value);
-EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffers (EGLDisplay dpy, EGLSurface surface);
-EGLAPI EGLBoolean EGLAPIENTRY eglTerminate (EGLDisplay dpy);
-EGLAPI EGLBoolean EGLAPIENTRY eglWaitGL (void);
-EGLAPI EGLBoolean EGLAPIENTRY eglWaitNative (EGLint engine);
-#endif
-#endif /* EGL_VERSION_1_0 */
-
-#ifndef EGL_VERSION_1_1
-#define EGL_VERSION_1_1 1
-#define EGL_BACK_BUFFER 0x3084
-#define EGL_BIND_TO_TEXTURE_RGB 0x3039
-#define EGL_BIND_TO_TEXTURE_RGBA 0x303A
-#define EGL_CONTEXT_LOST 0x300E
-#define EGL_MIN_SWAP_INTERVAL 0x303B
-#define EGL_MAX_SWAP_INTERVAL 0x303C
-#define EGL_MIPMAP_TEXTURE 0x3082
-#define EGL_MIPMAP_LEVEL 0x3083
-#define EGL_NO_TEXTURE 0x305C
-#define EGL_TEXTURE_2D 0x305F
-#define EGL_TEXTURE_FORMAT 0x3080
-#define EGL_TEXTURE_RGB 0x305D
-#define EGL_TEXTURE_RGBA 0x305E
-#define EGL_TEXTURE_TARGET 0x3081
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLBINDTEXIMAGEPROC) (EGLDisplay dpy, EGLSurface surface, EGLint buffer);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLRELEASETEXIMAGEPROC) (EGLDisplay dpy, EGLSurface surface, EGLint buffer);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLSURFACEATTRIBPROC) (EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLSWAPINTERVALPROC) (EGLDisplay dpy, EGLint interval);
-#if EGL_EGL_PROTOTYPES
-EGLAPI EGLBoolean EGLAPIENTRY eglBindTexImage (EGLDisplay dpy, EGLSurface surface, EGLint buffer);
-EGLAPI EGLBoolean EGLAPIENTRY eglReleaseTexImage (EGLDisplay dpy, EGLSurface surface, EGLint buffer);
-EGLAPI EGLBoolean EGLAPIENTRY eglSurfaceAttrib (EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value);
-EGLAPI EGLBoolean EGLAPIENTRY eglSwapInterval (EGLDisplay dpy, EGLint interval);
-#endif
-#endif /* EGL_VERSION_1_1 */
-
-#ifndef EGL_VERSION_1_2
-#define EGL_VERSION_1_2 1
-typedef unsigned int EGLenum;
-typedef void *EGLClientBuffer;
-#define EGL_ALPHA_FORMAT 0x3088
-#define EGL_ALPHA_FORMAT_NONPRE 0x308B
-#define EGL_ALPHA_FORMAT_PRE 0x308C
-#define EGL_ALPHA_MASK_SIZE 0x303E
-#define EGL_BUFFER_PRESERVED 0x3094
-#define EGL_BUFFER_DESTROYED 0x3095
-#define EGL_CLIENT_APIS 0x308D
-#define EGL_COLORSPACE 0x3087
-#define EGL_COLORSPACE_sRGB 0x3089
-#define EGL_COLORSPACE_LINEAR 0x308A
-#define EGL_COLOR_BUFFER_TYPE 0x303F
-#define EGL_CONTEXT_CLIENT_TYPE 0x3097
-#define EGL_DISPLAY_SCALING 10000
-#define EGL_HORIZONTAL_RESOLUTION 0x3090
-#define EGL_LUMINANCE_BUFFER 0x308F
-#define EGL_LUMINANCE_SIZE 0x303D
-#define EGL_OPENGL_ES_BIT 0x0001
-#define EGL_OPENVG_BIT 0x0002
-#define EGL_OPENGL_ES_API 0x30A0
-#define EGL_OPENVG_API 0x30A1
-#define EGL_OPENVG_IMAGE 0x3096
-#define EGL_PIXEL_ASPECT_RATIO 0x3092
-#define EGL_RENDERABLE_TYPE 0x3040
-#define EGL_RENDER_BUFFER 0x3086
-#define EGL_RGB_BUFFER 0x308E
-#define EGL_SINGLE_BUFFER 0x3085
-#define EGL_SWAP_BEHAVIOR 0x3093
-#define EGL_UNKNOWN EGL_CAST(EGLint,-1)
-#define EGL_VERTICAL_RESOLUTION 0x3091
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLBINDAPIPROC) (EGLenum api);
-typedef EGLenum (EGLAPIENTRYP PFNEGLQUERYAPIPROC) (void);
-typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATEPBUFFERFROMCLIENTBUFFERPROC) (EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLRELEASETHREADPROC) (void);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLWAITCLIENTPROC) (void);
-#if EGL_EGL_PROTOTYPES
-EGLAPI EGLBoolean EGLAPIENTRY eglBindAPI (EGLenum api);
-EGLAPI EGLenum EGLAPIENTRY eglQueryAPI (void);
-EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferFromClientBuffer (EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list);
-EGLAPI EGLBoolean EGLAPIENTRY eglReleaseThread (void);
-EGLAPI EGLBoolean EGLAPIENTRY eglWaitClient (void);
-#endif
-#endif /* EGL_VERSION_1_2 */
-
-#ifndef EGL_VERSION_1_3
-#define EGL_VERSION_1_3 1
-#define EGL_CONFORMANT 0x3042
-#define EGL_CONTEXT_CLIENT_VERSION 0x3098
-#define EGL_MATCH_NATIVE_PIXMAP 0x3041
-#define EGL_OPENGL_ES2_BIT 0x0004
-#define EGL_VG_ALPHA_FORMAT 0x3088
-#define EGL_VG_ALPHA_FORMAT_NONPRE 0x308B
-#define EGL_VG_ALPHA_FORMAT_PRE 0x308C
-#define EGL_VG_ALPHA_FORMAT_PRE_BIT 0x0040
-#define EGL_VG_COLORSPACE 0x3087
-#define EGL_VG_COLORSPACE_sRGB 0x3089
-#define EGL_VG_COLORSPACE_LINEAR 0x308A
-#define EGL_VG_COLORSPACE_LINEAR_BIT 0x0020
-#endif /* EGL_VERSION_1_3 */
-
-#ifndef EGL_VERSION_1_4
-#define EGL_VERSION_1_4 1
-#define EGL_DEFAULT_DISPLAY EGL_CAST(EGLNativeDisplayType,0)
-#define EGL_MULTISAMPLE_RESOLVE_BOX_BIT 0x0200
-#define EGL_MULTISAMPLE_RESOLVE 0x3099
-#define EGL_MULTISAMPLE_RESOLVE_DEFAULT 0x309A
-#define EGL_MULTISAMPLE_RESOLVE_BOX 0x309B
-#define EGL_OPENGL_API 0x30A2
-#define EGL_OPENGL_BIT 0x0008
-#define EGL_SWAP_BEHAVIOR_PRESERVED_BIT 0x0400
-typedef EGLContext (EGLAPIENTRYP PFNEGLGETCURRENTCONTEXTPROC) (void);
-#if EGL_EGL_PROTOTYPES
-EGLAPI EGLContext EGLAPIENTRY eglGetCurrentContext (void);
-#endif
-#endif /* EGL_VERSION_1_4 */
-
-#ifndef EGL_VERSION_1_5
-#define EGL_VERSION_1_5 1
-typedef void *EGLSync;
-typedef intptr_t EGLAttrib;
-typedef khronos_utime_nanoseconds_t EGLTime;
-typedef void *EGLImage;
-#define EGL_CONTEXT_MAJOR_VERSION 0x3098
-#define EGL_CONTEXT_MINOR_VERSION 0x30FB
-#define EGL_CONTEXT_OPENGL_PROFILE_MASK 0x30FD
-#define EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY 0x31BD
-#define EGL_NO_RESET_NOTIFICATION 0x31BE
-#define EGL_LOSE_CONTEXT_ON_RESET 0x31BF
-#define EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT 0x00000001
-#define EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT 0x00000002
-#define EGL_CONTEXT_OPENGL_DEBUG 0x31B0
-#define EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE 0x31B1
-#define EGL_CONTEXT_OPENGL_ROBUST_ACCESS 0x31B2
-#define EGL_OPENGL_ES3_BIT 0x00000040
-#define EGL_CL_EVENT_HANDLE 0x309C
-#define EGL_SYNC_CL_EVENT 0x30FE
-#define EGL_SYNC_CL_EVENT_COMPLETE 0x30FF
-#define EGL_SYNC_PRIOR_COMMANDS_COMPLETE 0x30F0
-#define EGL_SYNC_TYPE 0x30F7
-#define EGL_SYNC_STATUS 0x30F1
-#define EGL_SYNC_CONDITION 0x30F8
-#define EGL_SIGNALED 0x30F2
-#define EGL_UNSIGNALED 0x30F3
-#define EGL_SYNC_FLUSH_COMMANDS_BIT 0x0001
-#define EGL_FOREVER 0xFFFFFFFFFFFFFFFFull
-#define EGL_TIMEOUT_EXPIRED 0x30F5
-#define EGL_CONDITION_SATISFIED 0x30F6
-#define EGL_NO_SYNC EGL_CAST(EGLSync,0)
-#define EGL_SYNC_FENCE 0x30F9
-#define EGL_GL_COLORSPACE 0x309D
-#define EGL_GL_COLORSPACE_SRGB 0x3089
-#define EGL_GL_COLORSPACE_LINEAR 0x308A
-#define EGL_GL_RENDERBUFFER 0x30B9
-#define EGL_GL_TEXTURE_2D 0x30B1
-#define EGL_GL_TEXTURE_LEVEL 0x30BC
-#define EGL_GL_TEXTURE_3D 0x30B2
-#define EGL_GL_TEXTURE_ZOFFSET 0x30BD
-#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x30B3
-#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x30B4
-#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x30B5
-#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x30B6
-#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x30B7
-#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x30B8
-#define EGL_IMAGE_PRESERVED 0x30D2
-#define EGL_NO_IMAGE EGL_CAST(EGLImage,0)
-typedef EGLSync (EGLAPIENTRYP PFNEGLCREATESYNCPROC) (EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSYNCPROC) (EGLDisplay dpy, EGLSync sync);
-typedef EGLint (EGLAPIENTRYP PFNEGLCLIENTWAITSYNCPROC) (EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETSYNCATTRIBPROC) (EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib *value);
-typedef EGLImage (EGLAPIENTRYP PFNEGLCREATEIMAGEPROC) (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLAttrib *attrib_list);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYIMAGEPROC) (EGLDisplay dpy, EGLImage image);
-typedef EGLDisplay (EGLAPIENTRYP PFNEGLGETPLATFORMDISPLAYPROC) (EGLenum platform, void *native_display, const EGLAttrib *attrib_list);
-typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATEPLATFORMWINDOWSURFACEPROC) (EGLDisplay dpy, EGLConfig config, void *native_window, const EGLAttrib *attrib_list);
-typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATEPLATFORMPIXMAPSURFACEPROC) (EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLAttrib *attrib_list);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLWAITSYNCPROC) (EGLDisplay dpy, EGLSync sync, EGLint flags);
-#if EGL_EGL_PROTOTYPES
-EGLAPI EGLSync EGLAPIENTRY eglCreateSync (EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list);
-EGLAPI EGLBoolean EGLAPIENTRY eglDestroySync (EGLDisplay dpy, EGLSync sync);
-EGLAPI EGLint EGLAPIENTRY eglClientWaitSync (EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout);
-EGLAPI EGLBoolean EGLAPIENTRY eglGetSyncAttrib (EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib *value);
-EGLAPI EGLImage EGLAPIENTRY eglCreateImage (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLAttrib *attrib_list);
-EGLAPI EGLBoolean EGLAPIENTRY eglDestroyImage (EGLDisplay dpy, EGLImage image);
-EGLAPI EGLDisplay EGLAPIENTRY eglGetPlatformDisplay (EGLenum platform, void *native_display, const EGLAttrib *attrib_list);
-EGLAPI EGLSurface EGLAPIENTRY eglCreatePlatformWindowSurface (EGLDisplay dpy, EGLConfig config, void *native_window, const EGLAttrib *attrib_list);
-EGLAPI EGLSurface EGLAPIENTRY eglCreatePlatformPixmapSurface (EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLAttrib *attrib_list);
-EGLAPI EGLBoolean EGLAPIENTRY eglWaitSync (EGLDisplay dpy, EGLSync sync, EGLint flags);
-#endif
-#endif /* EGL_VERSION_1_5 */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif \ No newline at end of file
diff --git a/host/libs/graphics_detector/include/EGL/eglext.h b/host/libs/graphics_detector/include/EGL/eglext.h
deleted file mode 100644
index 73c159525..000000000
--- a/host/libs/graphics_detector/include/EGL/eglext.h
+++ /dev/null
@@ -1,1409 +0,0 @@
-#ifndef __eglext_h_
-#define __eglext_h_ 1
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
-** Copyright (c) 2013-2017 The Khronos Group Inc.
-**
-** Permission is hereby granted, free of charge, to any person obtaining a
-** copy of this software and/or associated documentation files (the
-** "Materials"), to deal in the Materials without restriction, including
-** without limitation the rights to use, copy, modify, merge, publish,
-** distribute, sublicense, and/or sell copies of the Materials, and to
-** permit persons to whom the Materials are furnished to do so, subject to
-** the following conditions:
-**
-** The above copyright notice and this permission notice shall be included
-** in all copies or substantial portions of the Materials.
-**
-** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
-*/
-/*
-** This header is generated from the Khronos EGL XML API Registry.
-** The current version of the Registry, generator scripts
-** used to make the header, and the header can be found at
-** http://www.khronos.org/registry/egl
-**
-** Khronos $Git commit SHA1: b5409265f3 $ on $Git commit date: 2020-02-20 08:24:34 -0800 $
-*/
-
-#include <EGL/eglplatform.h>
-
-#define EGL_EGLEXT_VERSION 20200220
-
-/* Generated C header for:
- * API: egl
- * Versions considered: .*
- * Versions emitted: _nomatch_^
- * Default extensions included: egl
- * Additional extensions included: _nomatch_^
- * Extensions removed: _nomatch_^
- */
-
-#ifndef EGL_KHR_cl_event
-#define EGL_KHR_cl_event 1
-#define EGL_CL_EVENT_HANDLE_KHR 0x309C
-#define EGL_SYNC_CL_EVENT_KHR 0x30FE
-#define EGL_SYNC_CL_EVENT_COMPLETE_KHR 0x30FF
-#endif /* EGL_KHR_cl_event */
-
-#ifndef EGL_KHR_cl_event2
-#define EGL_KHR_cl_event2 1
-typedef void *EGLSyncKHR;
-typedef intptr_t EGLAttribKHR;
-typedef EGLSyncKHR (EGLAPIENTRYP PFNEGLCREATESYNC64KHRPROC) (EGLDisplay dpy, EGLenum type, const EGLAttribKHR *attrib_list);
-#ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLSyncKHR EGLAPIENTRY eglCreateSync64KHR (EGLDisplay dpy, EGLenum type, const EGLAttribKHR *attrib_list);
-#endif
-#endif /* EGL_KHR_cl_event2 */
-
-#ifndef EGL_KHR_client_get_all_proc_addresses
-#define EGL_KHR_client_get_all_proc_addresses 1
-#endif /* EGL_KHR_client_get_all_proc_addresses */
-
-#ifndef EGL_KHR_config_attribs
-#define EGL_KHR_config_attribs 1
-#define EGL_CONFORMANT_KHR 0x3042
-#define EGL_VG_COLORSPACE_LINEAR_BIT_KHR 0x0020
-#define EGL_VG_ALPHA_FORMAT_PRE_BIT_KHR 0x0040
-#endif /* EGL_KHR_config_attribs */
-
-#ifndef EGL_KHR_context_flush_control
-#define EGL_KHR_context_flush_control 1
-#define EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR 0
-#define EGL_CONTEXT_RELEASE_BEHAVIOR_KHR 0x2097
-#define EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR 0x2098
-#endif /* EGL_KHR_context_flush_control */
-
-#ifndef EGL_KHR_create_context
-#define EGL_KHR_create_context 1
-#define EGL_CONTEXT_MAJOR_VERSION_KHR 0x3098
-#define EGL_CONTEXT_MINOR_VERSION_KHR 0x30FB
-#define EGL_CONTEXT_FLAGS_KHR 0x30FC
-#define EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR 0x30FD
-#define EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR 0x31BD
-#define EGL_NO_RESET_NOTIFICATION_KHR 0x31BE
-#define EGL_LOSE_CONTEXT_ON_RESET_KHR 0x31BF
-#define EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR 0x00000001
-#define EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR 0x00000002
-#define EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR 0x00000004
-#define EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR 0x00000001
-#define EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR 0x00000002
-#define EGL_OPENGL_ES3_BIT_KHR 0x00000040
-#endif /* EGL_KHR_create_context */
-
-#ifndef EGL_KHR_create_context_no_error
-#define EGL_KHR_create_context_no_error 1
-#define EGL_CONTEXT_OPENGL_NO_ERROR_KHR 0x31B3
-#endif /* EGL_KHR_create_context_no_error */
-
-#ifndef EGL_KHR_debug
-#define EGL_KHR_debug 1
-typedef void *EGLLabelKHR;
-typedef void *EGLObjectKHR;
-typedef void (EGLAPIENTRY *EGLDEBUGPROCKHR)(EGLenum error,const char *command,EGLint messageType,EGLLabelKHR threadLabel,EGLLabelKHR objectLabel,const char* message);
-#define EGL_OBJECT_THREAD_KHR 0x33B0
-#define EGL_OBJECT_DISPLAY_KHR 0x33B1
-#define EGL_OBJECT_CONTEXT_KHR 0x33B2
-#define EGL_OBJECT_SURFACE_KHR 0x33B3
-#define EGL_OBJECT_IMAGE_KHR 0x33B4
-#define EGL_OBJECT_SYNC_KHR 0x33B5
-#define EGL_OBJECT_STREAM_KHR 0x33B6
-#define EGL_DEBUG_MSG_CRITICAL_KHR 0x33B9
-#define EGL_DEBUG_MSG_ERROR_KHR 0x33BA
-#define EGL_DEBUG_MSG_WARN_KHR 0x33BB
-#define EGL_DEBUG_MSG_INFO_KHR 0x33BC
-#define EGL_DEBUG_CALLBACK_KHR 0x33B8
-typedef EGLint (EGLAPIENTRYP PFNEGLDEBUGMESSAGECONTROLKHRPROC) (EGLDEBUGPROCKHR callback, const EGLAttrib *attrib_list);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDEBUGKHRPROC) (EGLint attribute, EGLAttrib *value);
-typedef EGLint (EGLAPIENTRYP PFNEGLLABELOBJECTKHRPROC) (EGLDisplay display, EGLenum objectType, EGLObjectKHR object, EGLLabelKHR label);
-#ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLint EGLAPIENTRY eglDebugMessageControlKHR (EGLDEBUGPROCKHR callback, const EGLAttrib *attrib_list);
-EGLAPI EGLBoolean EGLAPIENTRY eglQueryDebugKHR (EGLint attribute, EGLAttrib *value);
-EGLAPI EGLint EGLAPIENTRY eglLabelObjectKHR (EGLDisplay display, EGLenum objectType, EGLObjectKHR object, EGLLabelKHR label);
-#endif
-#endif /* EGL_KHR_debug */
-
-#ifndef EGL_KHR_display_reference
-#define EGL_KHR_display_reference 1
-#define EGL_TRACK_REFERENCES_KHR 0x3352
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDISPLAYATTRIBKHRPROC) (EGLDisplay dpy, EGLint name, EGLAttrib *value);
-#ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLBoolean EGLAPIENTRY eglQueryDisplayAttribKHR (EGLDisplay dpy, EGLint name, EGLAttrib *value);
-#endif
-#endif /* EGL_KHR_display_reference */
-
-#ifndef EGL_KHR_fence_sync
-#define EGL_KHR_fence_sync 1
-typedef khronos_utime_nanoseconds_t EGLTimeKHR;
-#ifdef KHRONOS_SUPPORT_INT64
-#define EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR 0x30F0
-#define EGL_SYNC_CONDITION_KHR 0x30F8
-#define EGL_SYNC_FENCE_KHR 0x30F9
-typedef EGLSyncKHR (EGLAPIENTRYP PFNEGLCREATESYNCKHRPROC) (EGLDisplay dpy, EGLenum type, const EGLint *attrib_list);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync);
-typedef EGLint (EGLAPIENTRYP PFNEGLCLIENTWAITSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETSYNCATTRIBKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value);
-#ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLSyncKHR EGLAPIENTRY eglCreateSyncKHR (EGLDisplay dpy, EGLenum type, const EGLint *attrib_list);
-EGLAPI EGLBoolean EGLAPIENTRY eglDestroySyncKHR (EGLDisplay dpy, EGLSyncKHR sync);
-EGLAPI EGLint EGLAPIENTRY eglClientWaitSyncKHR (EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout);
-EGLAPI EGLBoolean EGLAPIENTRY eglGetSyncAttribKHR (EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value);
-#endif
-#endif /* KHRONOS_SUPPORT_INT64 */
-#endif /* EGL_KHR_fence_sync */
-
-#ifndef EGL_KHR_get_all_proc_addresses
-#define EGL_KHR_get_all_proc_addresses 1
-#endif /* EGL_KHR_get_all_proc_addresses */
-
-#ifndef EGL_KHR_gl_colorspace
-#define EGL_KHR_gl_colorspace 1
-#define EGL_GL_COLORSPACE_KHR 0x309D
-#define EGL_GL_COLORSPACE_SRGB_KHR 0x3089
-#define EGL_GL_COLORSPACE_LINEAR_KHR 0x308A
-#endif /* EGL_KHR_gl_colorspace */
-
-#ifndef EGL_KHR_gl_renderbuffer_image
-#define EGL_KHR_gl_renderbuffer_image 1
-#define EGL_GL_RENDERBUFFER_KHR 0x30B9
-#endif /* EGL_KHR_gl_renderbuffer_image */
-
-#ifndef EGL_KHR_gl_texture_2D_image
-#define EGL_KHR_gl_texture_2D_image 1
-#define EGL_GL_TEXTURE_2D_KHR 0x30B1
-#define EGL_GL_TEXTURE_LEVEL_KHR 0x30BC
-#endif /* EGL_KHR_gl_texture_2D_image */
-
-#ifndef EGL_KHR_gl_texture_3D_image
-#define EGL_KHR_gl_texture_3D_image 1
-#define EGL_GL_TEXTURE_3D_KHR 0x30B2
-#define EGL_GL_TEXTURE_ZOFFSET_KHR 0x30BD
-#endif /* EGL_KHR_gl_texture_3D_image */
-
-#ifndef EGL_KHR_gl_texture_cubemap_image
-#define EGL_KHR_gl_texture_cubemap_image 1
-#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR 0x30B3
-#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR 0x30B4
-#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR 0x30B5
-#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR 0x30B6
-#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR 0x30B7
-#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR 0x30B8
-#endif /* EGL_KHR_gl_texture_cubemap_image */
-
-#ifndef EGL_KHR_image
-#define EGL_KHR_image 1
-typedef void *EGLImageKHR;
-#define EGL_NATIVE_PIXMAP_KHR 0x30B0
-#define EGL_NO_IMAGE_KHR EGL_CAST(EGLImageKHR,0)
-typedef EGLImageKHR (EGLAPIENTRYP PFNEGLCREATEIMAGEKHRPROC) (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYIMAGEKHRPROC) (EGLDisplay dpy, EGLImageKHR image);
-#ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLImageKHR EGLAPIENTRY eglCreateImageKHR (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list);
-EGLAPI EGLBoolean EGLAPIENTRY eglDestroyImageKHR (EGLDisplay dpy, EGLImageKHR image);
-#endif
-#endif /* EGL_KHR_image */
-
-#ifndef EGL_KHR_image_base
-#define EGL_KHR_image_base 1
-#define EGL_IMAGE_PRESERVED_KHR 0x30D2
-#endif /* EGL_KHR_image_base */
-
-#ifndef EGL_KHR_image_pixmap
-#define EGL_KHR_image_pixmap 1
-#endif /* EGL_KHR_image_pixmap */
-
-#ifndef EGL_KHR_lock_surface
-#define EGL_KHR_lock_surface 1
-#define EGL_READ_SURFACE_BIT_KHR 0x0001
-#define EGL_WRITE_SURFACE_BIT_KHR 0x0002
-#define EGL_LOCK_SURFACE_BIT_KHR 0x0080
-#define EGL_OPTIMAL_FORMAT_BIT_KHR 0x0100
-#define EGL_MATCH_FORMAT_KHR 0x3043
-#define EGL_FORMAT_RGB_565_EXACT_KHR 0x30C0
-#define EGL_FORMAT_RGB_565_KHR 0x30C1
-#define EGL_FORMAT_RGBA_8888_EXACT_KHR 0x30C2
-#define EGL_FORMAT_RGBA_8888_KHR 0x30C3
-#define EGL_MAP_PRESERVE_PIXELS_KHR 0x30C4
-#define EGL_LOCK_USAGE_HINT_KHR 0x30C5
-#define EGL_BITMAP_POINTER_KHR 0x30C6
-#define EGL_BITMAP_PITCH_KHR 0x30C7
-#define EGL_BITMAP_ORIGIN_KHR 0x30C8
-#define EGL_BITMAP_PIXEL_RED_OFFSET_KHR 0x30C9
-#define EGL_BITMAP_PIXEL_GREEN_OFFSET_KHR 0x30CA
-#define EGL_BITMAP_PIXEL_BLUE_OFFSET_KHR 0x30CB
-#define EGL_BITMAP_PIXEL_ALPHA_OFFSET_KHR 0x30CC
-#define EGL_BITMAP_PIXEL_LUMINANCE_OFFSET_KHR 0x30CD
-#define EGL_LOWER_LEFT_KHR 0x30CE
-#define EGL_UPPER_LEFT_KHR 0x30CF
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLLOCKSURFACEKHRPROC) (EGLDisplay dpy, EGLSurface surface, const EGLint *attrib_list);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLUNLOCKSURFACEKHRPROC) (EGLDisplay dpy, EGLSurface surface);
-#ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLBoolean EGLAPIENTRY eglLockSurfaceKHR (EGLDisplay dpy, EGLSurface surface, const EGLint *attrib_list);
-EGLAPI EGLBoolean EGLAPIENTRY eglUnlockSurfaceKHR (EGLDisplay dpy, EGLSurface surface);
-#endif
-#endif /* EGL_KHR_lock_surface */
-
-#ifndef EGL_KHR_lock_surface2
-#define EGL_KHR_lock_surface2 1
-#define EGL_BITMAP_PIXEL_SIZE_KHR 0x3110
-#endif /* EGL_KHR_lock_surface2 */
-
-#ifndef EGL_KHR_lock_surface3
-#define EGL_KHR_lock_surface3 1
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSURFACE64KHRPROC) (EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLAttribKHR *value);
-#ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurface64KHR (EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLAttribKHR *value);
-#endif
-#endif /* EGL_KHR_lock_surface3 */
-
-#ifndef EGL_KHR_mutable_render_buffer
-#define EGL_KHR_mutable_render_buffer 1
-#define EGL_MUTABLE_RENDER_BUFFER_BIT_KHR 0x1000
-#endif /* EGL_KHR_mutable_render_buffer */
-
-#ifndef EGL_KHR_no_config_context
-#define EGL_KHR_no_config_context 1
-#define EGL_NO_CONFIG_KHR EGL_CAST(EGLConfig,0)
-#endif /* EGL_KHR_no_config_context */
-
-#ifndef EGL_KHR_partial_update
-#define EGL_KHR_partial_update 1
-#define EGL_BUFFER_AGE_KHR 0x313D
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLSETDAMAGEREGIONKHRPROC) (EGLDisplay dpy, EGLSurface surface, EGLint *rects, EGLint n_rects);
-#ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLBoolean EGLAPIENTRY eglSetDamageRegionKHR (EGLDisplay dpy, EGLSurface surface, EGLint *rects, EGLint n_rects);
-#endif
-#endif /* EGL_KHR_partial_update */
-
-#ifndef EGL_KHR_platform_android
-#define EGL_KHR_platform_android 1
-#define EGL_PLATFORM_ANDROID_KHR 0x3141
-#endif /* EGL_KHR_platform_android */
-
-#ifndef EGL_KHR_platform_gbm
-#define EGL_KHR_platform_gbm 1
-#define EGL_PLATFORM_GBM_KHR 0x31D7
-#endif /* EGL_KHR_platform_gbm */
-
-#ifndef EGL_KHR_platform_wayland
-#define EGL_KHR_platform_wayland 1
-#define EGL_PLATFORM_WAYLAND_KHR 0x31D8
-#endif /* EGL_KHR_platform_wayland */
-
-#ifndef EGL_KHR_platform_x11
-#define EGL_KHR_platform_x11 1
-#define EGL_PLATFORM_X11_KHR 0x31D5
-#define EGL_PLATFORM_X11_SCREEN_KHR 0x31D6
-#endif /* EGL_KHR_platform_x11 */
-
-#ifndef EGL_KHR_reusable_sync
-#define EGL_KHR_reusable_sync 1
-#ifdef KHRONOS_SUPPORT_INT64
-#define EGL_SYNC_STATUS_KHR 0x30F1
-#define EGL_SIGNALED_KHR 0x30F2
-#define EGL_UNSIGNALED_KHR 0x30F3
-#define EGL_TIMEOUT_EXPIRED_KHR 0x30F5
-#define EGL_CONDITION_SATISFIED_KHR 0x30F6
-#define EGL_SYNC_TYPE_KHR 0x30F7
-#define EGL_SYNC_REUSABLE_KHR 0x30FA
-#define EGL_SYNC_FLUSH_COMMANDS_BIT_KHR 0x0001
-#define EGL_FOREVER_KHR 0xFFFFFFFFFFFFFFFFull
-#define EGL_NO_SYNC_KHR EGL_CAST(EGLSyncKHR,0)
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLSIGNALSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode);
-#ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLBoolean EGLAPIENTRY eglSignalSyncKHR (EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode);
-#endif
-#endif /* KHRONOS_SUPPORT_INT64 */
-#endif /* EGL_KHR_reusable_sync */
-
-#ifndef EGL_KHR_stream
-#define EGL_KHR_stream 1
-typedef void *EGLStreamKHR;
-typedef khronos_uint64_t EGLuint64KHR;
-#ifdef KHRONOS_SUPPORT_INT64
-#define EGL_NO_STREAM_KHR EGL_CAST(EGLStreamKHR,0)
-#define EGL_CONSUMER_LATENCY_USEC_KHR 0x3210
-#define EGL_PRODUCER_FRAME_KHR 0x3212
-#define EGL_CONSUMER_FRAME_KHR 0x3213
-#define EGL_STREAM_STATE_KHR 0x3214
-#define EGL_STREAM_STATE_CREATED_KHR 0x3215
-#define EGL_STREAM_STATE_CONNECTING_KHR 0x3216
-#define EGL_STREAM_STATE_EMPTY_KHR 0x3217
-#define EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR 0x3218
-#define EGL_STREAM_STATE_OLD_FRAME_AVAILABLE_KHR 0x3219
-#define EGL_STREAM_STATE_DISCONNECTED_KHR 0x321A
-#define EGL_BAD_STREAM_KHR 0x321B
-#define EGL_BAD_STATE_KHR 0x321C
-typedef EGLStreamKHR (EGLAPIENTRYP PFNEGLCREATESTREAMKHRPROC) (EGLDisplay dpy, const EGLint *attrib_list);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSTREAMKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMATTRIBKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint value);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSTREAMKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint *value);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSTREAMU64KHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLuint64KHR *value);
-#ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLStreamKHR EGLAPIENTRY eglCreateStreamKHR (EGLDisplay dpy, const EGLint *attrib_list);
-EGLAPI EGLBoolean EGLAPIENTRY eglDestroyStreamKHR (EGLDisplay dpy, EGLStreamKHR stream);
-EGLAPI EGLBoolean EGLAPIENTRY eglStreamAttribKHR (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint value);
-EGLAPI EGLBoolean EGLAPIENTRY eglQueryStreamKHR (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint *value);
-EGLAPI EGLBoolean EGLAPIENTRY eglQueryStreamu64KHR (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLuint64KHR *value);
-#endif
-#endif /* KHRONOS_SUPPORT_INT64 */
-#endif /* EGL_KHR_stream */
-
-#ifndef EGL_KHR_stream_attrib
-#define EGL_KHR_stream_attrib 1
-#ifdef KHRONOS_SUPPORT_INT64
-typedef EGLStreamKHR (EGLAPIENTRYP PFNEGLCREATESTREAMATTRIBKHRPROC) (EGLDisplay dpy, const EGLAttrib *attrib_list);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLSETSTREAMATTRIBKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLAttrib value);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSTREAMATTRIBKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLAttrib *value);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERACQUIREATTRIBKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, const EGLAttrib *attrib_list);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERRELEASEATTRIBKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, const EGLAttrib *attrib_list);
-#ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLStreamKHR EGLAPIENTRY eglCreateStreamAttribKHR (EGLDisplay dpy, const EGLAttrib *attrib_list);
-EGLAPI EGLBoolean EGLAPIENTRY eglSetStreamAttribKHR (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLAttrib value);
-EGLAPI EGLBoolean EGLAPIENTRY eglQueryStreamAttribKHR (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLAttrib *value);
-EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerAcquireAttribKHR (EGLDisplay dpy, EGLStreamKHR stream, const EGLAttrib *attrib_list);
-EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerReleaseAttribKHR (EGLDisplay dpy, EGLStreamKHR stream, const EGLAttrib *attrib_list);
-#endif
-#endif /* KHRONOS_SUPPORT_INT64 */
-#endif /* EGL_KHR_stream_attrib */
-
-#ifndef EGL_KHR_stream_consumer_gltexture
-#define EGL_KHR_stream_consumer_gltexture 1
-#ifdef EGL_KHR_stream
-#define EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR 0x321E
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERGLTEXTUREEXTERNALKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERACQUIREKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERRELEASEKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream);
-#ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerGLTextureExternalKHR (EGLDisplay dpy, EGLStreamKHR stream);
-EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerAcquireKHR (EGLDisplay dpy, EGLStreamKHR stream);
-EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerReleaseKHR (EGLDisplay dpy, EGLStreamKHR stream);
-#endif
-#endif /* EGL_KHR_stream */
-#endif /* EGL_KHR_stream_consumer_gltexture */
-
-#ifndef EGL_KHR_stream_cross_process_fd
-#define EGL_KHR_stream_cross_process_fd 1
-typedef int EGLNativeFileDescriptorKHR;
-#ifdef EGL_KHR_stream
-#define EGL_NO_FILE_DESCRIPTOR_KHR EGL_CAST(EGLNativeFileDescriptorKHR,-1)
-typedef EGLNativeFileDescriptorKHR (EGLAPIENTRYP PFNEGLGETSTREAMFILEDESCRIPTORKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream);
-typedef EGLStreamKHR (EGLAPIENTRYP PFNEGLCREATESTREAMFROMFILEDESCRIPTORKHRPROC) (EGLDisplay dpy, EGLNativeFileDescriptorKHR file_descriptor);
-#ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLNativeFileDescriptorKHR EGLAPIENTRY eglGetStreamFileDescriptorKHR (EGLDisplay dpy, EGLStreamKHR stream);
-EGLAPI EGLStreamKHR EGLAPIENTRY eglCreateStreamFromFileDescriptorKHR (EGLDisplay dpy, EGLNativeFileDescriptorKHR file_descriptor);
-#endif
-#endif /* EGL_KHR_stream */
-#endif /* EGL_KHR_stream_cross_process_fd */
-
-#ifndef EGL_KHR_stream_fifo
-#define EGL_KHR_stream_fifo 1
-#ifdef EGL_KHR_stream
-#define EGL_STREAM_FIFO_LENGTH_KHR 0x31FC
-#define EGL_STREAM_TIME_NOW_KHR 0x31FD
-#define EGL_STREAM_TIME_CONSUMER_KHR 0x31FE
-#define EGL_STREAM_TIME_PRODUCER_KHR 0x31FF
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSTREAMTIMEKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLTimeKHR *value);
-#ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLBoolean EGLAPIENTRY eglQueryStreamTimeKHR (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLTimeKHR *value);
-#endif
-#endif /* EGL_KHR_stream */
-#endif /* EGL_KHR_stream_fifo */
-
-#ifndef EGL_KHR_stream_producer_aldatalocator
-#define EGL_KHR_stream_producer_aldatalocator 1
-#ifdef EGL_KHR_stream
-#endif /* EGL_KHR_stream */
-#endif /* EGL_KHR_stream_producer_aldatalocator */
-
-#ifndef EGL_KHR_stream_producer_eglsurface
-#define EGL_KHR_stream_producer_eglsurface 1
-#ifdef EGL_KHR_stream
-#define EGL_STREAM_BIT_KHR 0x0800
-typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATESTREAMPRODUCERSURFACEKHRPROC) (EGLDisplay dpy, EGLConfig config, EGLStreamKHR stream, const EGLint *attrib_list);
-#ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLSurface EGLAPIENTRY eglCreateStreamProducerSurfaceKHR (EGLDisplay dpy, EGLConfig config, EGLStreamKHR stream, const EGLint *attrib_list);
-#endif
-#endif /* EGL_KHR_stream */
-#endif /* EGL_KHR_stream_producer_eglsurface */
-
-#ifndef EGL_KHR_surfaceless_context
-#define EGL_KHR_surfaceless_context 1
-#endif /* EGL_KHR_surfaceless_context */
-
-#ifndef EGL_KHR_swap_buffers_with_damage
-#define EGL_KHR_swap_buffers_with_damage 1
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLSWAPBUFFERSWITHDAMAGEKHRPROC) (EGLDisplay dpy, EGLSurface surface, const EGLint *rects, EGLint n_rects);
-#ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffersWithDamageKHR (EGLDisplay dpy, EGLSurface surface, const EGLint *rects, EGLint n_rects);
-#endif
-#endif /* EGL_KHR_swap_buffers_with_damage */
-
-#ifndef EGL_KHR_vg_parent_image
-#define EGL_KHR_vg_parent_image 1
-#define EGL_VG_PARENT_IMAGE_KHR 0x30BA
-#endif /* EGL_KHR_vg_parent_image */
-
-#ifndef EGL_KHR_wait_sync
-#define EGL_KHR_wait_sync 1
-typedef EGLint (EGLAPIENTRYP PFNEGLWAITSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLint flags);
-#ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLint EGLAPIENTRY eglWaitSyncKHR (EGLDisplay dpy, EGLSyncKHR sync, EGLint flags);
-#endif
-#endif /* EGL_KHR_wait_sync */
-
-#ifndef EGL_ANDROID_GLES_layers
-#define EGL_ANDROID_GLES_layers 1
-#endif /* EGL_ANDROID_GLES_layers */
-
-#ifndef EGL_ANDROID_blob_cache
-#define EGL_ANDROID_blob_cache 1
-typedef khronos_ssize_t EGLsizeiANDROID;
-typedef void (*EGLSetBlobFuncANDROID) (const void *key, EGLsizeiANDROID keySize, const void *value, EGLsizeiANDROID valueSize);
-typedef EGLsizeiANDROID (*EGLGetBlobFuncANDROID) (const void *key, EGLsizeiANDROID keySize, void *value, EGLsizeiANDROID valueSize);
-typedef void (EGLAPIENTRYP PFNEGLSETBLOBCACHEFUNCSANDROIDPROC) (EGLDisplay dpy, EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get);
-#ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI void EGLAPIENTRY eglSetBlobCacheFuncsANDROID (EGLDisplay dpy, EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get);
-#endif
-#endif /* EGL_ANDROID_blob_cache */
-
-#ifndef EGL_ANDROID_create_native_client_buffer
-#define EGL_ANDROID_create_native_client_buffer 1
-#define EGL_NATIVE_BUFFER_USAGE_ANDROID 0x3143
-#define EGL_NATIVE_BUFFER_USAGE_PROTECTED_BIT_ANDROID 0x00000001
-#define EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_BIT_ANDROID 0x00000002
-#define EGL_NATIVE_BUFFER_USAGE_TEXTURE_BIT_ANDROID 0x00000004
-typedef EGLClientBuffer (EGLAPIENTRYP PFNEGLCREATENATIVECLIENTBUFFERANDROIDPROC) (const EGLint *attrib_list);
-#ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLClientBuffer EGLAPIENTRY eglCreateNativeClientBufferANDROID (const EGLint *attrib_list);
-#endif
-#endif /* EGL_ANDROID_create_native_client_buffer */
-
-#ifndef EGL_ANDROID_framebuffer_target
-#define EGL_ANDROID_framebuffer_target 1
-#define EGL_FRAMEBUFFER_TARGET_ANDROID 0x3147
-#endif /* EGL_ANDROID_framebuffer_target */
-
-#ifndef EGL_ANDROID_front_buffer_auto_refresh
-#define EGL_ANDROID_front_buffer_auto_refresh 1
-#define EGL_FRONT_BUFFER_AUTO_REFRESH_ANDROID 0x314C
-#endif /* EGL_ANDROID_front_buffer_auto_refresh */
-
-#ifndef EGL_ANDROID_get_frame_timestamps
-#define EGL_ANDROID_get_frame_timestamps 1
-typedef khronos_stime_nanoseconds_t EGLnsecsANDROID;
-#define EGL_TIMESTAMP_PENDING_ANDROID EGL_CAST(EGLnsecsANDROID,-2)
-#define EGL_TIMESTAMP_INVALID_ANDROID EGL_CAST(EGLnsecsANDROID,-1)
-#define EGL_TIMESTAMPS_ANDROID 0x3430
-#define EGL_COMPOSITE_DEADLINE_ANDROID 0x3431
-#define EGL_COMPOSITE_INTERVAL_ANDROID 0x3432
-#define EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID 0x3433
-#define EGL_REQUESTED_PRESENT_TIME_ANDROID 0x3434
-#define EGL_RENDERING_COMPLETE_TIME_ANDROID 0x3435
-#define EGL_COMPOSITION_LATCH_TIME_ANDROID 0x3436
-#define EGL_FIRST_COMPOSITION_START_TIME_ANDROID 0x3437
-#define EGL_LAST_COMPOSITION_START_TIME_ANDROID 0x3438
-#define EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID 0x3439
-#define EGL_DISPLAY_PRESENT_TIME_ANDROID 0x343A
-#define EGL_DEQUEUE_READY_TIME_ANDROID 0x343B
-#define EGL_READS_DONE_TIME_ANDROID 0x343C
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETCOMPOSITORTIMINGSUPPORTEDANDROIDPROC) (EGLDisplay dpy, EGLSurface surface, EGLint name);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETCOMPOSITORTIMINGANDROIDPROC) (EGLDisplay dpy, EGLSurface surface, EGLint numTimestamps, const EGLint *names, EGLnsecsANDROID *values);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETNEXTFRAMEIDANDROIDPROC) (EGLDisplay dpy, EGLSurface surface, EGLuint64KHR *frameId);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETFRAMETIMESTAMPSUPPORTEDANDROIDPROC) (EGLDisplay dpy, EGLSurface surface, EGLint timestamp);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETFRAMETIMESTAMPSANDROIDPROC) (EGLDisplay dpy, EGLSurface surface, EGLuint64KHR frameId, EGLint numTimestamps, const EGLint *timestamps, EGLnsecsANDROID *values);
-#ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLBoolean EGLAPIENTRY eglGetCompositorTimingSupportedANDROID (EGLDisplay dpy, EGLSurface surface, EGLint name);
-EGLAPI EGLBoolean EGLAPIENTRY eglGetCompositorTimingANDROID (EGLDisplay dpy, EGLSurface surface, EGLint numTimestamps, const EGLint *names, EGLnsecsANDROID *values);
-EGLAPI EGLBoolean EGLAPIENTRY eglGetNextFrameIdANDROID (EGLDisplay dpy, EGLSurface surface, EGLuint64KHR *frameId);
-EGLAPI EGLBoolean EGLAPIENTRY eglGetFrameTimestampSupportedANDROID (EGLDisplay dpy, EGLSurface surface, EGLint timestamp);
-EGLAPI EGLBoolean EGLAPIENTRY eglGetFrameTimestampsANDROID (EGLDisplay dpy, EGLSurface surface, EGLuint64KHR frameId, EGLint numTimestamps, const EGLint *timestamps, EGLnsecsANDROID *values);
-#endif
-#endif /* EGL_ANDROID_get_frame_timestamps */
-
-#ifndef EGL_ANDROID_get_native_client_buffer
-#define EGL_ANDROID_get_native_client_buffer 1
-struct AHardwareBuffer;
-typedef EGLClientBuffer (EGLAPIENTRYP PFNEGLGETNATIVECLIENTBUFFERANDROIDPROC) (const struct AHardwareBuffer *buffer);
-#ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLClientBuffer EGLAPIENTRY eglGetNativeClientBufferANDROID (const struct AHardwareBuffer *buffer);
-#endif
-#endif /* EGL_ANDROID_get_native_client_buffer */
-
-#ifndef EGL_ANDROID_image_native_buffer
-#define EGL_ANDROID_image_native_buffer 1
-#define EGL_NATIVE_BUFFER_ANDROID 0x3140
-#endif /* EGL_ANDROID_image_native_buffer */
-
-#ifndef EGL_ANDROID_native_fence_sync
-#define EGL_ANDROID_native_fence_sync 1
-#define EGL_SYNC_NATIVE_FENCE_ANDROID 0x3144
-#define EGL_SYNC_NATIVE_FENCE_FD_ANDROID 0x3145
-#define EGL_SYNC_NATIVE_FENCE_SIGNALED_ANDROID 0x3146
-#define EGL_NO_NATIVE_FENCE_FD_ANDROID -1
-typedef EGLint (EGLAPIENTRYP PFNEGLDUPNATIVEFENCEFDANDROIDPROC) (EGLDisplay dpy, EGLSyncKHR sync);
-#ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLint EGLAPIENTRY eglDupNativeFenceFDANDROID (EGLDisplay dpy, EGLSyncKHR sync);
-#endif
-#endif /* EGL_ANDROID_native_fence_sync */
-
-#ifndef EGL_ANDROID_presentation_time
-#define EGL_ANDROID_presentation_time 1
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLPRESENTATIONTIMEANDROIDPROC) (EGLDisplay dpy, EGLSurface surface, EGLnsecsANDROID time);
-#ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLBoolean EGLAPIENTRY eglPresentationTimeANDROID (EGLDisplay dpy, EGLSurface surface, EGLnsecsANDROID time);
-#endif
-#endif /* EGL_ANDROID_presentation_time */
-
-#ifndef EGL_ANDROID_recordable
-#define EGL_ANDROID_recordable 1
-#define EGL_RECORDABLE_ANDROID 0x3142
-#endif /* EGL_ANDROID_recordable */
-
-#ifndef EGL_ANGLE_d3d_share_handle_client_buffer
-#define EGL_ANGLE_d3d_share_handle_client_buffer 1
-#define EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE 0x3200
-#endif /* EGL_ANGLE_d3d_share_handle_client_buffer */
-
-#ifndef EGL_ANGLE_device_d3d
-#define EGL_ANGLE_device_d3d 1
-#define EGL_D3D9_DEVICE_ANGLE 0x33A0
-#define EGL_D3D11_DEVICE_ANGLE 0x33A1
-#endif /* EGL_ANGLE_device_d3d */
-
-#ifndef EGL_ANGLE_query_surface_pointer
-#define EGL_ANGLE_query_surface_pointer 1
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSURFACEPOINTERANGLEPROC) (EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value);
-#ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurfacePointerANGLE (EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value);
-#endif
-#endif /* EGL_ANGLE_query_surface_pointer */
-
-#ifndef EGL_ANGLE_surface_d3d_texture_2d_share_handle
-#define EGL_ANGLE_surface_d3d_texture_2d_share_handle 1
-#endif /* EGL_ANGLE_surface_d3d_texture_2d_share_handle */
-
-#ifndef EGL_ANGLE_window_fixed_size
-#define EGL_ANGLE_window_fixed_size 1
-#define EGL_FIXED_SIZE_ANGLE 0x3201
-#endif /* EGL_ANGLE_window_fixed_size */
-
-#ifndef EGL_ARM_image_format
-#define EGL_ARM_image_format 1
-#define EGL_COLOR_COMPONENT_TYPE_UNSIGNED_INTEGER_ARM 0x3287
-#define EGL_COLOR_COMPONENT_TYPE_INTEGER_ARM 0x3288
-#endif /* EGL_ARM_image_format */
-
-#ifndef EGL_ARM_implicit_external_sync
-#define EGL_ARM_implicit_external_sync 1
-#define EGL_SYNC_PRIOR_COMMANDS_IMPLICIT_EXTERNAL_ARM 0x328A
-#endif /* EGL_ARM_implicit_external_sync */
-
-#ifndef EGL_ARM_pixmap_multisample_discard
-#define EGL_ARM_pixmap_multisample_discard 1
-#define EGL_DISCARD_SAMPLES_ARM 0x3286
-#endif /* EGL_ARM_pixmap_multisample_discard */
-
-#ifndef EGL_EXT_bind_to_front
-#define EGL_EXT_bind_to_front 1
-#define EGL_FRONT_BUFFER_EXT 0x3464
-#endif /* EGL_EXT_bind_to_front */
-
-#ifndef EGL_EXT_buffer_age
-#define EGL_EXT_buffer_age 1
-#define EGL_BUFFER_AGE_EXT 0x313D
-#endif /* EGL_EXT_buffer_age */
-
-#ifndef EGL_EXT_client_extensions
-#define EGL_EXT_client_extensions 1
-#endif /* EGL_EXT_client_extensions */
-
-#ifndef EGL_EXT_client_sync
-#define EGL_EXT_client_sync 1
-#define EGL_SYNC_CLIENT_EXT 0x3364
-#define EGL_SYNC_CLIENT_SIGNAL_EXT 0x3365
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLCLIENTSIGNALSYNCEXTPROC) (EGLDisplay dpy, EGLSync sync, const EGLAttrib *attrib_list);
-#ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLBoolean EGLAPIENTRY eglClientSignalSyncEXT (EGLDisplay dpy, EGLSync sync, const EGLAttrib *attrib_list);
-#endif
-#endif /* EGL_EXT_client_sync */
-
-#ifndef EGL_EXT_compositor
-#define EGL_EXT_compositor 1
-#define EGL_PRIMARY_COMPOSITOR_CONTEXT_EXT 0x3460
-#define EGL_EXTERNAL_REF_ID_EXT 0x3461
-#define EGL_COMPOSITOR_DROP_NEWEST_FRAME_EXT 0x3462
-#define EGL_COMPOSITOR_KEEP_NEWEST_FRAME_EXT 0x3463
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLCOMPOSITORSETCONTEXTLISTEXTPROC) (const EGLint *external_ref_ids, EGLint num_entries);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLCOMPOSITORSETCONTEXTATTRIBUTESEXTPROC) (EGLint external_ref_id, const EGLint *context_attributes, EGLint num_entries);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLCOMPOSITORSETWINDOWLISTEXTPROC) (EGLint external_ref_id, const EGLint *external_win_ids, EGLint num_entries);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLCOMPOSITORSETWINDOWATTRIBUTESEXTPROC) (EGLint external_win_id, const EGLint *window_attributes, EGLint num_entries);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLCOMPOSITORBINDTEXWINDOWEXTPROC) (EGLint external_win_id);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLCOMPOSITORSETSIZEEXTPROC) (EGLint external_win_id, EGLint width, EGLint height);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLCOMPOSITORSWAPPOLICYEXTPROC) (EGLint external_win_id, EGLint policy);
-#ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLBoolean EGLAPIENTRY eglCompositorSetContextListEXT (const EGLint *external_ref_ids, EGLint num_entries);
-EGLAPI EGLBoolean EGLAPIENTRY eglCompositorSetContextAttributesEXT (EGLint external_ref_id, const EGLint *context_attributes, EGLint num_entries);
-EGLAPI EGLBoolean EGLAPIENTRY eglCompositorSetWindowListEXT (EGLint external_ref_id, const EGLint *external_win_ids, EGLint num_entries);
-EGLAPI EGLBoolean EGLAPIENTRY eglCompositorSetWindowAttributesEXT (EGLint external_win_id, const EGLint *window_attributes, EGLint num_entries);
-EGLAPI EGLBoolean EGLAPIENTRY eglCompositorBindTexWindowEXT (EGLint external_win_id);
-EGLAPI EGLBoolean EGLAPIENTRY eglCompositorSetSizeEXT (EGLint external_win_id, EGLint width, EGLint height);
-EGLAPI EGLBoolean EGLAPIENTRY eglCompositorSwapPolicyEXT (EGLint external_win_id, EGLint policy);
-#endif
-#endif /* EGL_EXT_compositor */
-
-#ifndef EGL_EXT_create_context_robustness
-#define EGL_EXT_create_context_robustness 1
-#define EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT 0x30BF
-#define EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT 0x3138
-#define EGL_NO_RESET_NOTIFICATION_EXT 0x31BE
-#define EGL_LOSE_CONTEXT_ON_RESET_EXT 0x31BF
-#endif /* EGL_EXT_create_context_robustness */
-
-#ifndef EGL_EXT_device_base
-#define EGL_EXT_device_base 1
-typedef void *EGLDeviceEXT;
-#define EGL_NO_DEVICE_EXT EGL_CAST(EGLDeviceEXT,0)
-#define EGL_BAD_DEVICE_EXT 0x322B
-#define EGL_DEVICE_EXT 0x322C
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDEVICEATTRIBEXTPROC) (EGLDeviceEXT device, EGLint attribute, EGLAttrib *value);
-typedef const char *(EGLAPIENTRYP PFNEGLQUERYDEVICESTRINGEXTPROC) (EGLDeviceEXT device, EGLint name);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDEVICESEXTPROC) (EGLint max_devices, EGLDeviceEXT *devices, EGLint *num_devices);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDISPLAYATTRIBEXTPROC) (EGLDisplay dpy, EGLint attribute, EGLAttrib *value);
-#ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLBoolean EGLAPIENTRY eglQueryDeviceAttribEXT (EGLDeviceEXT device, EGLint attribute, EGLAttrib *value);
-EGLAPI const char *EGLAPIENTRY eglQueryDeviceStringEXT (EGLDeviceEXT device, EGLint name);
-EGLAPI EGLBoolean EGLAPIENTRY eglQueryDevicesEXT (EGLint max_devices, EGLDeviceEXT *devices, EGLint *num_devices);
-EGLAPI EGLBoolean EGLAPIENTRY eglQueryDisplayAttribEXT (EGLDisplay dpy, EGLint attribute, EGLAttrib *value);
-#endif
-#endif /* EGL_EXT_device_base */
-
-#ifndef EGL_EXT_device_drm
-#define EGL_EXT_device_drm 1
-#define EGL_DRM_DEVICE_FILE_EXT 0x3233
-#define EGL_DRM_MASTER_FD_EXT 0x333C
-#endif /* EGL_EXT_device_drm */
-
-#ifndef EGL_EXT_device_enumeration
-#define EGL_EXT_device_enumeration 1
-#endif /* EGL_EXT_device_enumeration */
-
-#ifndef EGL_EXT_device_openwf
-#define EGL_EXT_device_openwf 1
-#define EGL_OPENWF_DEVICE_ID_EXT 0x3237
-#endif /* EGL_EXT_device_openwf */
-
-#ifndef EGL_EXT_device_query
-#define EGL_EXT_device_query 1
-#endif /* EGL_EXT_device_query */
-
-#ifndef EGL_EXT_gl_colorspace_bt2020_linear
-#define EGL_EXT_gl_colorspace_bt2020_linear 1
-#define EGL_GL_COLORSPACE_BT2020_LINEAR_EXT 0x333F
-#endif /* EGL_EXT_gl_colorspace_bt2020_linear */
-
-#ifndef EGL_EXT_gl_colorspace_bt2020_pq
-#define EGL_EXT_gl_colorspace_bt2020_pq 1
-#define EGL_GL_COLORSPACE_BT2020_PQ_EXT 0x3340
-#endif /* EGL_EXT_gl_colorspace_bt2020_pq */
-
-#ifndef EGL_EXT_gl_colorspace_display_p3
-#define EGL_EXT_gl_colorspace_display_p3 1
-#define EGL_GL_COLORSPACE_DISPLAY_P3_EXT 0x3363
-#endif /* EGL_EXT_gl_colorspace_display_p3 */
-
-#ifndef EGL_EXT_gl_colorspace_display_p3_linear
-#define EGL_EXT_gl_colorspace_display_p3_linear 1
-#define EGL_GL_COLORSPACE_DISPLAY_P3_LINEAR_EXT 0x3362
-#endif /* EGL_EXT_gl_colorspace_display_p3_linear */
-
-#ifndef EGL_EXT_gl_colorspace_display_p3_passthrough
-#define EGL_EXT_gl_colorspace_display_p3_passthrough 1
-#define EGL_GL_COLORSPACE_DISPLAY_P3_PASSTHROUGH_EXT 0x3490
-#endif /* EGL_EXT_gl_colorspace_display_p3_passthrough */
-
-#ifndef EGL_EXT_gl_colorspace_scrgb
-#define EGL_EXT_gl_colorspace_scrgb 1
-#define EGL_GL_COLORSPACE_SCRGB_EXT 0x3351
-#endif /* EGL_EXT_gl_colorspace_scrgb */
-
-#ifndef EGL_EXT_gl_colorspace_scrgb_linear
-#define EGL_EXT_gl_colorspace_scrgb_linear 1
-#define EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT 0x3350
-#endif /* EGL_EXT_gl_colorspace_scrgb_linear */
-
-#ifndef EGL_EXT_image_dma_buf_import
-#define EGL_EXT_image_dma_buf_import 1
-#define EGL_LINUX_DMA_BUF_EXT 0x3270
-#define EGL_LINUX_DRM_FOURCC_EXT 0x3271
-#define EGL_DMA_BUF_PLANE0_FD_EXT 0x3272
-#define EGL_DMA_BUF_PLANE0_OFFSET_EXT 0x3273
-#define EGL_DMA_BUF_PLANE0_PITCH_EXT 0x3274
-#define EGL_DMA_BUF_PLANE1_FD_EXT 0x3275
-#define EGL_DMA_BUF_PLANE1_OFFSET_EXT 0x3276
-#define EGL_DMA_BUF_PLANE1_PITCH_EXT 0x3277
-#define EGL_DMA_BUF_PLANE2_FD_EXT 0x3278
-#define EGL_DMA_BUF_PLANE2_OFFSET_EXT 0x3279
-#define EGL_DMA_BUF_PLANE2_PITCH_EXT 0x327A
-#define EGL_YUV_COLOR_SPACE_HINT_EXT 0x327B
-#define EGL_SAMPLE_RANGE_HINT_EXT 0x327C
-#define EGL_YUV_CHROMA_HORIZONTAL_SITING_HINT_EXT 0x327D
-#define EGL_YUV_CHROMA_VERTICAL_SITING_HINT_EXT 0x327E
-#define EGL_ITU_REC601_EXT 0x327F
-#define EGL_ITU_REC709_EXT 0x3280
-#define EGL_ITU_REC2020_EXT 0x3281
-#define EGL_YUV_FULL_RANGE_EXT 0x3282
-#define EGL_YUV_NARROW_RANGE_EXT 0x3283
-#define EGL_YUV_CHROMA_SITING_0_EXT 0x3284
-#define EGL_YUV_CHROMA_SITING_0_5_EXT 0x3285
-#endif /* EGL_EXT_image_dma_buf_import */
-
-#ifndef EGL_EXT_image_dma_buf_import_modifiers
-#define EGL_EXT_image_dma_buf_import_modifiers 1
-#define EGL_DMA_BUF_PLANE3_FD_EXT 0x3440
-#define EGL_DMA_BUF_PLANE3_OFFSET_EXT 0x3441
-#define EGL_DMA_BUF_PLANE3_PITCH_EXT 0x3442
-#define EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT 0x3443
-#define EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT 0x3444
-#define EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT 0x3445
-#define EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT 0x3446
-#define EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT 0x3447
-#define EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT 0x3448
-#define EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT 0x3449
-#define EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT 0x344A
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDMABUFFORMATSEXTPROC) (EGLDisplay dpy, EGLint max_formats, EGLint *formats, EGLint *num_formats);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDMABUFMODIFIERSEXTPROC) (EGLDisplay dpy, EGLint format, EGLint max_modifiers, EGLuint64KHR *modifiers, EGLBoolean *external_only, EGLint *num_modifiers);
-#ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLBoolean EGLAPIENTRY eglQueryDmaBufFormatsEXT (EGLDisplay dpy, EGLint max_formats, EGLint *formats, EGLint *num_formats);
-EGLAPI EGLBoolean EGLAPIENTRY eglQueryDmaBufModifiersEXT (EGLDisplay dpy, EGLint format, EGLint max_modifiers, EGLuint64KHR *modifiers, EGLBoolean *external_only, EGLint *num_modifiers);
-#endif
-#endif /* EGL_EXT_image_dma_buf_import_modifiers */
-
-#ifndef EGL_EXT_image_gl_colorspace
-#define EGL_EXT_image_gl_colorspace 1
-#define EGL_GL_COLORSPACE_DEFAULT_EXT 0x314D
-#endif /* EGL_EXT_image_gl_colorspace */
-
-#ifndef EGL_EXT_image_implicit_sync_control
-#define EGL_EXT_image_implicit_sync_control 1
-#define EGL_IMPORT_SYNC_TYPE_EXT 0x3470
-#define EGL_IMPORT_IMPLICIT_SYNC_EXT 0x3471
-#define EGL_IMPORT_EXPLICIT_SYNC_EXT 0x3472
-#endif /* EGL_EXT_image_implicit_sync_control */
-
-#ifndef EGL_EXT_multiview_window
-#define EGL_EXT_multiview_window 1
-#define EGL_MULTIVIEW_VIEW_COUNT_EXT 0x3134
-#endif /* EGL_EXT_multiview_window */
-
-#ifndef EGL_EXT_output_base
-#define EGL_EXT_output_base 1
-typedef void *EGLOutputLayerEXT;
-typedef void *EGLOutputPortEXT;
-#define EGL_NO_OUTPUT_LAYER_EXT EGL_CAST(EGLOutputLayerEXT,0)
-#define EGL_NO_OUTPUT_PORT_EXT EGL_CAST(EGLOutputPortEXT,0)
-#define EGL_BAD_OUTPUT_LAYER_EXT 0x322D
-#define EGL_BAD_OUTPUT_PORT_EXT 0x322E
-#define EGL_SWAP_INTERVAL_EXT 0x322F
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETOUTPUTLAYERSEXTPROC) (EGLDisplay dpy, const EGLAttrib *attrib_list, EGLOutputLayerEXT *layers, EGLint max_layers, EGLint *num_layers);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETOUTPUTPORTSEXTPROC) (EGLDisplay dpy, const EGLAttrib *attrib_list, EGLOutputPortEXT *ports, EGLint max_ports, EGLint *num_ports);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLOUTPUTLAYERATTRIBEXTPROC) (EGLDisplay dpy, EGLOutputLayerEXT layer, EGLint attribute, EGLAttrib value);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYOUTPUTLAYERATTRIBEXTPROC) (EGLDisplay dpy, EGLOutputLayerEXT layer, EGLint attribute, EGLAttrib *value);
-typedef const char *(EGLAPIENTRYP PFNEGLQUERYOUTPUTLAYERSTRINGEXTPROC) (EGLDisplay dpy, EGLOutputLayerEXT layer, EGLint name);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLOUTPUTPORTATTRIBEXTPROC) (EGLDisplay dpy, EGLOutputPortEXT port, EGLint attribute, EGLAttrib value);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYOUTPUTPORTATTRIBEXTPROC) (EGLDisplay dpy, EGLOutputPortEXT port, EGLint attribute, EGLAttrib *value);
-typedef const char *(EGLAPIENTRYP PFNEGLQUERYOUTPUTPORTSTRINGEXTPROC) (EGLDisplay dpy, EGLOutputPortEXT port, EGLint name);
-#ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLBoolean EGLAPIENTRY eglGetOutputLayersEXT (EGLDisplay dpy, const EGLAttrib *attrib_list, EGLOutputLayerEXT *layers, EGLint max_layers, EGLint *num_layers);
-EGLAPI EGLBoolean EGLAPIENTRY eglGetOutputPortsEXT (EGLDisplay dpy, const EGLAttrib *attrib_list, EGLOutputPortEXT *ports, EGLint max_ports, EGLint *num_ports);
-EGLAPI EGLBoolean EGLAPIENTRY eglOutputLayerAttribEXT (EGLDisplay dpy, EGLOutputLayerEXT layer, EGLint attribute, EGLAttrib value);
-EGLAPI EGLBoolean EGLAPIENTRY eglQueryOutputLayerAttribEXT (EGLDisplay dpy, EGLOutputLayerEXT layer, EGLint attribute, EGLAttrib *value);
-EGLAPI const char *EGLAPIENTRY eglQueryOutputLayerStringEXT (EGLDisplay dpy, EGLOutputLayerEXT layer, EGLint name);
-EGLAPI EGLBoolean EGLAPIENTRY eglOutputPortAttribEXT (EGLDisplay dpy, EGLOutputPortEXT port, EGLint attribute, EGLAttrib value);
-EGLAPI EGLBoolean EGLAPIENTRY eglQueryOutputPortAttribEXT (EGLDisplay dpy, EGLOutputPortEXT port, EGLint attribute, EGLAttrib *value);
-EGLAPI const char *EGLAPIENTRY eglQueryOutputPortStringEXT (EGLDisplay dpy, EGLOutputPortEXT port, EGLint name);
-#endif
-#endif /* EGL_EXT_output_base */
-
-#ifndef EGL_EXT_output_drm
-#define EGL_EXT_output_drm 1
-#define EGL_DRM_CRTC_EXT 0x3234
-#define EGL_DRM_PLANE_EXT 0x3235
-#define EGL_DRM_CONNECTOR_EXT 0x3236
-#endif /* EGL_EXT_output_drm */
-
-#ifndef EGL_EXT_output_openwf
-#define EGL_EXT_output_openwf 1
-#define EGL_OPENWF_PIPELINE_ID_EXT 0x3238
-#define EGL_OPENWF_PORT_ID_EXT 0x3239
-#endif /* EGL_EXT_output_openwf */
-
-#ifndef EGL_EXT_pixel_format_float
-#define EGL_EXT_pixel_format_float 1
-#define EGL_COLOR_COMPONENT_TYPE_EXT 0x3339
-#define EGL_COLOR_COMPONENT_TYPE_FIXED_EXT 0x333A
-#define EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT 0x333B
-#endif /* EGL_EXT_pixel_format_float */
-
-#ifndef EGL_EXT_platform_base
-#define EGL_EXT_platform_base 1
-typedef EGLDisplay (EGLAPIENTRYP PFNEGLGETPLATFORMDISPLAYEXTPROC) (EGLenum platform, void *native_display, const EGLint *attrib_list);
-typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC) (EGLDisplay dpy, EGLConfig config, void *native_window, const EGLint *attrib_list);
-typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATEPLATFORMPIXMAPSURFACEEXTPROC) (EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLint *attrib_list);
-#ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLDisplay EGLAPIENTRY eglGetPlatformDisplayEXT (EGLenum platform, void *native_display, const EGLint *attrib_list);
-EGLAPI EGLSurface EGLAPIENTRY eglCreatePlatformWindowSurfaceEXT (EGLDisplay dpy, EGLConfig config, void *native_window, const EGLint *attrib_list);
-EGLAPI EGLSurface EGLAPIENTRY eglCreatePlatformPixmapSurfaceEXT (EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLint *attrib_list);
-#endif
-#endif /* EGL_EXT_platform_base */
-
-#ifndef EGL_EXT_platform_device
-#define EGL_EXT_platform_device 1
-#define EGL_PLATFORM_DEVICE_EXT 0x313F
-#endif /* EGL_EXT_platform_device */
-
-#ifndef EGL_EXT_platform_wayland
-#define EGL_EXT_platform_wayland 1
-#define EGL_PLATFORM_WAYLAND_EXT 0x31D8
-#endif /* EGL_EXT_platform_wayland */
-
-#ifndef EGL_EXT_platform_x11
-#define EGL_EXT_platform_x11 1
-#define EGL_PLATFORM_X11_EXT 0x31D5
-#define EGL_PLATFORM_X11_SCREEN_EXT 0x31D6
-#endif /* EGL_EXT_platform_x11 */
-
-#ifndef EGL_EXT_protected_content
-#define EGL_EXT_protected_content 1
-#define EGL_PROTECTED_CONTENT_EXT 0x32C0
-#endif /* EGL_EXT_protected_content */
-
-#ifndef EGL_EXT_protected_surface
-#define EGL_EXT_protected_surface 1
-#endif /* EGL_EXT_protected_surface */
-
-#ifndef EGL_EXT_stream_consumer_egloutput
-#define EGL_EXT_stream_consumer_egloutput 1
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMEROUTPUTEXTPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLOutputLayerEXT layer);
-#ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerOutputEXT (EGLDisplay dpy, EGLStreamKHR stream, EGLOutputLayerEXT layer);
-#endif
-#endif /* EGL_EXT_stream_consumer_egloutput */
-
-#ifndef EGL_EXT_surface_CTA861_3_metadata
-#define EGL_EXT_surface_CTA861_3_metadata 1
-#define EGL_CTA861_3_MAX_CONTENT_LIGHT_LEVEL_EXT 0x3360
-#define EGL_CTA861_3_MAX_FRAME_AVERAGE_LEVEL_EXT 0x3361
-#endif /* EGL_EXT_surface_CTA861_3_metadata */
-
-#ifndef EGL_EXT_surface_SMPTE2086_metadata
-#define EGL_EXT_surface_SMPTE2086_metadata 1
-#define EGL_SMPTE2086_DISPLAY_PRIMARY_RX_EXT 0x3341
-#define EGL_SMPTE2086_DISPLAY_PRIMARY_RY_EXT 0x3342
-#define EGL_SMPTE2086_DISPLAY_PRIMARY_GX_EXT 0x3343
-#define EGL_SMPTE2086_DISPLAY_PRIMARY_GY_EXT 0x3344
-#define EGL_SMPTE2086_DISPLAY_PRIMARY_BX_EXT 0x3345
-#define EGL_SMPTE2086_DISPLAY_PRIMARY_BY_EXT 0x3346
-#define EGL_SMPTE2086_WHITE_POINT_X_EXT 0x3347
-#define EGL_SMPTE2086_WHITE_POINT_Y_EXT 0x3348
-#define EGL_SMPTE2086_MAX_LUMINANCE_EXT 0x3349
-#define EGL_SMPTE2086_MIN_LUMINANCE_EXT 0x334A
-#define EGL_METADATA_SCALING_EXT 50000
-#endif /* EGL_EXT_surface_SMPTE2086_metadata */
-
-#ifndef EGL_EXT_swap_buffers_with_damage
-#define EGL_EXT_swap_buffers_with_damage 1
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLSWAPBUFFERSWITHDAMAGEEXTPROC) (EGLDisplay dpy, EGLSurface surface, const EGLint *rects, EGLint n_rects);
-#ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffersWithDamageEXT (EGLDisplay dpy, EGLSurface surface, const EGLint *rects, EGLint n_rects);
-#endif
-#endif /* EGL_EXT_swap_buffers_with_damage */
-
-#ifndef EGL_EXT_sync_reuse
-#define EGL_EXT_sync_reuse 1
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLUNSIGNALSYNCEXTPROC) (EGLDisplay dpy, EGLSync sync, const EGLAttrib *attrib_list);
-#ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLBoolean EGLAPIENTRY eglUnsignalSyncEXT (EGLDisplay dpy, EGLSync sync, const EGLAttrib *attrib_list);
-#endif
-#endif /* EGL_EXT_sync_reuse */
-
-#ifndef EGL_EXT_yuv_surface
-#define EGL_EXT_yuv_surface 1
-#define EGL_YUV_ORDER_EXT 0x3301
-#define EGL_YUV_NUMBER_OF_PLANES_EXT 0x3311
-#define EGL_YUV_SUBSAMPLE_EXT 0x3312
-#define EGL_YUV_DEPTH_RANGE_EXT 0x3317
-#define EGL_YUV_CSC_STANDARD_EXT 0x330A
-#define EGL_YUV_PLANE_BPP_EXT 0x331A
-#define EGL_YUV_BUFFER_EXT 0x3300
-#define EGL_YUV_ORDER_YUV_EXT 0x3302
-#define EGL_YUV_ORDER_YVU_EXT 0x3303
-#define EGL_YUV_ORDER_YUYV_EXT 0x3304
-#define EGL_YUV_ORDER_UYVY_EXT 0x3305
-#define EGL_YUV_ORDER_YVYU_EXT 0x3306
-#define EGL_YUV_ORDER_VYUY_EXT 0x3307
-#define EGL_YUV_ORDER_AYUV_EXT 0x3308
-#define EGL_YUV_SUBSAMPLE_4_2_0_EXT 0x3313
-#define EGL_YUV_SUBSAMPLE_4_2_2_EXT 0x3314
-#define EGL_YUV_SUBSAMPLE_4_4_4_EXT 0x3315
-#define EGL_YUV_DEPTH_RANGE_LIMITED_EXT 0x3318
-#define EGL_YUV_DEPTH_RANGE_FULL_EXT 0x3319
-#define EGL_YUV_CSC_STANDARD_601_EXT 0x330B
-#define EGL_YUV_CSC_STANDARD_709_EXT 0x330C
-#define EGL_YUV_CSC_STANDARD_2020_EXT 0x330D
-#define EGL_YUV_PLANE_BPP_0_EXT 0x331B
-#define EGL_YUV_PLANE_BPP_8_EXT 0x331C
-#define EGL_YUV_PLANE_BPP_10_EXT 0x331D
-#endif /* EGL_EXT_yuv_surface */
-
-#ifndef EGL_HI_clientpixmap
-#define EGL_HI_clientpixmap 1
-struct EGLClientPixmapHI {
- void *pData;
- EGLint iWidth;
- EGLint iHeight;
- EGLint iStride;
-};
-#define EGL_CLIENT_PIXMAP_POINTER_HI 0x8F74
-typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATEPIXMAPSURFACEHIPROC) (EGLDisplay dpy, EGLConfig config, struct EGLClientPixmapHI *pixmap);
-#ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLSurface EGLAPIENTRY eglCreatePixmapSurfaceHI (EGLDisplay dpy, EGLConfig config, struct EGLClientPixmapHI *pixmap);
-#endif
-#endif /* EGL_HI_clientpixmap */
-
-#ifndef EGL_HI_colorformats
-#define EGL_HI_colorformats 1
-#define EGL_COLOR_FORMAT_HI 0x8F70
-#define EGL_COLOR_RGB_HI 0x8F71
-#define EGL_COLOR_RGBA_HI 0x8F72
-#define EGL_COLOR_ARGB_HI 0x8F73
-#endif /* EGL_HI_colorformats */
-
-#ifndef EGL_IMG_context_priority
-#define EGL_IMG_context_priority 1
-#define EGL_CONTEXT_PRIORITY_LEVEL_IMG 0x3100
-#define EGL_CONTEXT_PRIORITY_HIGH_IMG 0x3101
-#define EGL_CONTEXT_PRIORITY_MEDIUM_IMG 0x3102
-#define EGL_CONTEXT_PRIORITY_LOW_IMG 0x3103
-#endif /* EGL_IMG_context_priority */
-
-#ifndef EGL_IMG_image_plane_attribs
-#define EGL_IMG_image_plane_attribs 1
-#define EGL_NATIVE_BUFFER_MULTIPLANE_SEPARATE_IMG 0x3105
-#define EGL_NATIVE_BUFFER_PLANE_OFFSET_IMG 0x3106
-#endif /* EGL_IMG_image_plane_attribs */
-
-#ifndef EGL_MESA_drm_image
-#define EGL_MESA_drm_image 1
-#define EGL_DRM_BUFFER_FORMAT_MESA 0x31D0
-#define EGL_DRM_BUFFER_USE_MESA 0x31D1
-#define EGL_DRM_BUFFER_FORMAT_ARGB32_MESA 0x31D2
-#define EGL_DRM_BUFFER_MESA 0x31D3
-#define EGL_DRM_BUFFER_STRIDE_MESA 0x31D4
-#define EGL_DRM_BUFFER_USE_SCANOUT_MESA 0x00000001
-#define EGL_DRM_BUFFER_USE_SHARE_MESA 0x00000002
-#define EGL_DRM_BUFFER_USE_CURSOR_MESA 0x00000004
-typedef EGLImageKHR (EGLAPIENTRYP PFNEGLCREATEDRMIMAGEMESAPROC) (EGLDisplay dpy, const EGLint *attrib_list);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLEXPORTDRMIMAGEMESAPROC) (EGLDisplay dpy, EGLImageKHR image, EGLint *name, EGLint *handle, EGLint *stride);
-#ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLImageKHR EGLAPIENTRY eglCreateDRMImageMESA (EGLDisplay dpy, const EGLint *attrib_list);
-EGLAPI EGLBoolean EGLAPIENTRY eglExportDRMImageMESA (EGLDisplay dpy, EGLImageKHR image, EGLint *name, EGLint *handle, EGLint *stride);
-#endif
-#endif /* EGL_MESA_drm_image */
-
-#ifndef EGL_MESA_image_dma_buf_export
-#define EGL_MESA_image_dma_buf_export 1
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLEXPORTDMABUFIMAGEQUERYMESAPROC) (EGLDisplay dpy, EGLImageKHR image, int *fourcc, int *num_planes, EGLuint64KHR *modifiers);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLEXPORTDMABUFIMAGEMESAPROC) (EGLDisplay dpy, EGLImageKHR image, int *fds, EGLint *strides, EGLint *offsets);
-#ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLBoolean EGLAPIENTRY eglExportDMABUFImageQueryMESA (EGLDisplay dpy, EGLImageKHR image, int *fourcc, int *num_planes, EGLuint64KHR *modifiers);
-EGLAPI EGLBoolean EGLAPIENTRY eglExportDMABUFImageMESA (EGLDisplay dpy, EGLImageKHR image, int *fds, EGLint *strides, EGLint *offsets);
-#endif
-#endif /* EGL_MESA_image_dma_buf_export */
-
-#ifndef EGL_MESA_platform_gbm
-#define EGL_MESA_platform_gbm 1
-#define EGL_PLATFORM_GBM_MESA 0x31D7
-#endif /* EGL_MESA_platform_gbm */
-
-#ifndef EGL_MESA_platform_surfaceless
-#define EGL_MESA_platform_surfaceless 1
-#define EGL_PLATFORM_SURFACELESS_MESA 0x31DD
-#endif /* EGL_MESA_platform_surfaceless */
-
-#ifndef EGL_MESA_query_driver
-#define EGL_MESA_query_driver 1
-typedef char *(EGLAPIENTRYP PFNEGLGETDISPLAYDRIVERCONFIGPROC) (EGLDisplay dpy);
-typedef const char *(EGLAPIENTRYP PFNEGLGETDISPLAYDRIVERNAMEPROC) (EGLDisplay dpy);
-#ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI char *EGLAPIENTRY eglGetDisplayDriverConfig (EGLDisplay dpy);
-EGLAPI const char *EGLAPIENTRY eglGetDisplayDriverName (EGLDisplay dpy);
-#endif
-#endif /* EGL_MESA_query_driver */
-
-#ifndef EGL_NOK_swap_region
-#define EGL_NOK_swap_region 1
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLSWAPBUFFERSREGIONNOKPROC) (EGLDisplay dpy, EGLSurface surface, EGLint numRects, const EGLint *rects);
-#ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffersRegionNOK (EGLDisplay dpy, EGLSurface surface, EGLint numRects, const EGLint *rects);
-#endif
-#endif /* EGL_NOK_swap_region */
-
-#ifndef EGL_NOK_swap_region2
-#define EGL_NOK_swap_region2 1
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLSWAPBUFFERSREGION2NOKPROC) (EGLDisplay dpy, EGLSurface surface, EGLint numRects, const EGLint *rects);
-#ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffersRegion2NOK (EGLDisplay dpy, EGLSurface surface, EGLint numRects, const EGLint *rects);
-#endif
-#endif /* EGL_NOK_swap_region2 */
-
-#ifndef EGL_NOK_texture_from_pixmap
-#define EGL_NOK_texture_from_pixmap 1
-#define EGL_Y_INVERTED_NOK 0x307F
-#endif /* EGL_NOK_texture_from_pixmap */
-
-#ifndef EGL_NV_3dvision_surface
-#define EGL_NV_3dvision_surface 1
-#define EGL_AUTO_STEREO_NV 0x3136
-#endif /* EGL_NV_3dvision_surface */
-
-#ifndef EGL_NV_context_priority_realtime
-#define EGL_NV_context_priority_realtime 1
-#define EGL_CONTEXT_PRIORITY_REALTIME_NV 0x3357
-#endif /* EGL_NV_context_priority_realtime */
-
-#ifndef EGL_NV_coverage_sample
-#define EGL_NV_coverage_sample 1
-#define EGL_COVERAGE_BUFFERS_NV 0x30E0
-#define EGL_COVERAGE_SAMPLES_NV 0x30E1
-#endif /* EGL_NV_coverage_sample */
-
-#ifndef EGL_NV_coverage_sample_resolve
-#define EGL_NV_coverage_sample_resolve 1
-#define EGL_COVERAGE_SAMPLE_RESOLVE_NV 0x3131
-#define EGL_COVERAGE_SAMPLE_RESOLVE_DEFAULT_NV 0x3132
-#define EGL_COVERAGE_SAMPLE_RESOLVE_NONE_NV 0x3133
-#endif /* EGL_NV_coverage_sample_resolve */
-
-#ifndef EGL_NV_cuda_event
-#define EGL_NV_cuda_event 1
-#define EGL_CUDA_EVENT_HANDLE_NV 0x323B
-#define EGL_SYNC_CUDA_EVENT_NV 0x323C
-#define EGL_SYNC_CUDA_EVENT_COMPLETE_NV 0x323D
-#endif /* EGL_NV_cuda_event */
-
-#ifndef EGL_NV_depth_nonlinear
-#define EGL_NV_depth_nonlinear 1
-#define EGL_DEPTH_ENCODING_NV 0x30E2
-#define EGL_DEPTH_ENCODING_NONE_NV 0
-#define EGL_DEPTH_ENCODING_NONLINEAR_NV 0x30E3
-#endif /* EGL_NV_depth_nonlinear */
-
-#ifndef EGL_NV_device_cuda
-#define EGL_NV_device_cuda 1
-#define EGL_CUDA_DEVICE_NV 0x323A
-#endif /* EGL_NV_device_cuda */
-
-#ifndef EGL_NV_native_query
-#define EGL_NV_native_query 1
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYNATIVEDISPLAYNVPROC) (EGLDisplay dpy, EGLNativeDisplayType *display_id);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYNATIVEWINDOWNVPROC) (EGLDisplay dpy, EGLSurface surf, EGLNativeWindowType *window);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYNATIVEPIXMAPNVPROC) (EGLDisplay dpy, EGLSurface surf, EGLNativePixmapType *pixmap);
-#ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLBoolean EGLAPIENTRY eglQueryNativeDisplayNV (EGLDisplay dpy, EGLNativeDisplayType *display_id);
-EGLAPI EGLBoolean EGLAPIENTRY eglQueryNativeWindowNV (EGLDisplay dpy, EGLSurface surf, EGLNativeWindowType *window);
-EGLAPI EGLBoolean EGLAPIENTRY eglQueryNativePixmapNV (EGLDisplay dpy, EGLSurface surf, EGLNativePixmapType *pixmap);
-#endif
-#endif /* EGL_NV_native_query */
-
-#ifndef EGL_NV_post_convert_rounding
-#define EGL_NV_post_convert_rounding 1
-#endif /* EGL_NV_post_convert_rounding */
-
-#ifndef EGL_NV_post_sub_buffer
-#define EGL_NV_post_sub_buffer 1
-#define EGL_POST_SUB_BUFFER_SUPPORTED_NV 0x30BE
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLPOSTSUBBUFFERNVPROC) (EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height);
-#ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLBoolean EGLAPIENTRY eglPostSubBufferNV (EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height);
-#endif
-#endif /* EGL_NV_post_sub_buffer */
-
-#ifndef EGL_NV_quadruple_buffer
-#define EGL_NV_quadruple_buffer 1
-#define EGL_QUADRUPLE_BUFFER_NV 0x3231
-#endif /* EGL_NV_quadruple_buffer */
-
-#ifndef EGL_NV_robustness_video_memory_purge
-#define EGL_NV_robustness_video_memory_purge 1
-#define EGL_GENERATE_RESET_ON_VIDEO_MEMORY_PURGE_NV 0x334C
-#endif /* EGL_NV_robustness_video_memory_purge */
-
-#ifndef EGL_NV_stream_consumer_gltexture_yuv
-#define EGL_NV_stream_consumer_gltexture_yuv 1
-#define EGL_YUV_PLANE0_TEXTURE_UNIT_NV 0x332C
-#define EGL_YUV_PLANE1_TEXTURE_UNIT_NV 0x332D
-#define EGL_YUV_PLANE2_TEXTURE_UNIT_NV 0x332E
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERGLTEXTUREEXTERNALATTRIBSNVPROC) (EGLDisplay dpy, EGLStreamKHR stream, const EGLAttrib *attrib_list);
-#ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerGLTextureExternalAttribsNV (EGLDisplay dpy, EGLStreamKHR stream, const EGLAttrib *attrib_list);
-#endif
-#endif /* EGL_NV_stream_consumer_gltexture_yuv */
-
-#ifndef EGL_NV_stream_cross_display
-#define EGL_NV_stream_cross_display 1
-#define EGL_STREAM_CROSS_DISPLAY_NV 0x334E
-#endif /* EGL_NV_stream_cross_display */
-
-#ifndef EGL_NV_stream_cross_object
-#define EGL_NV_stream_cross_object 1
-#define EGL_STREAM_CROSS_OBJECT_NV 0x334D
-#endif /* EGL_NV_stream_cross_object */
-
-#ifndef EGL_NV_stream_cross_partition
-#define EGL_NV_stream_cross_partition 1
-#define EGL_STREAM_CROSS_PARTITION_NV 0x323F
-#endif /* EGL_NV_stream_cross_partition */
-
-#ifndef EGL_NV_stream_cross_process
-#define EGL_NV_stream_cross_process 1
-#define EGL_STREAM_CROSS_PROCESS_NV 0x3245
-#endif /* EGL_NV_stream_cross_process */
-
-#ifndef EGL_NV_stream_cross_system
-#define EGL_NV_stream_cross_system 1
-#define EGL_STREAM_CROSS_SYSTEM_NV 0x334F
-#endif /* EGL_NV_stream_cross_system */
-
-#ifndef EGL_NV_stream_dma
-#define EGL_NV_stream_dma 1
-#define EGL_STREAM_DMA_NV 0x3371
-#define EGL_STREAM_DMA_SERVER_NV 0x3372
-#endif /* EGL_NV_stream_dma */
-
-#ifndef EGL_NV_stream_fifo_next
-#define EGL_NV_stream_fifo_next 1
-#define EGL_PENDING_FRAME_NV 0x3329
-#define EGL_STREAM_TIME_PENDING_NV 0x332A
-#endif /* EGL_NV_stream_fifo_next */
-
-#ifndef EGL_NV_stream_fifo_synchronous
-#define EGL_NV_stream_fifo_synchronous 1
-#define EGL_STREAM_FIFO_SYNCHRONOUS_NV 0x3336
-#endif /* EGL_NV_stream_fifo_synchronous */
-
-#ifndef EGL_NV_stream_flush
-#define EGL_NV_stream_flush 1
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMFLUSHNVPROC) (EGLDisplay dpy, EGLStreamKHR stream);
-#ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLBoolean EGLAPIENTRY eglStreamFlushNV (EGLDisplay dpy, EGLStreamKHR stream);
-#endif
-#endif /* EGL_NV_stream_flush */
-
-#ifndef EGL_NV_stream_frame_limits
-#define EGL_NV_stream_frame_limits 1
-#define EGL_PRODUCER_MAX_FRAME_HINT_NV 0x3337
-#define EGL_CONSUMER_MAX_FRAME_HINT_NV 0x3338
-#endif /* EGL_NV_stream_frame_limits */
-
-#ifndef EGL_NV_stream_metadata
-#define EGL_NV_stream_metadata 1
-#define EGL_MAX_STREAM_METADATA_BLOCKS_NV 0x3250
-#define EGL_MAX_STREAM_METADATA_BLOCK_SIZE_NV 0x3251
-#define EGL_MAX_STREAM_METADATA_TOTAL_SIZE_NV 0x3252
-#define EGL_PRODUCER_METADATA_NV 0x3253
-#define EGL_CONSUMER_METADATA_NV 0x3254
-#define EGL_PENDING_METADATA_NV 0x3328
-#define EGL_METADATA0_SIZE_NV 0x3255
-#define EGL_METADATA1_SIZE_NV 0x3256
-#define EGL_METADATA2_SIZE_NV 0x3257
-#define EGL_METADATA3_SIZE_NV 0x3258
-#define EGL_METADATA0_TYPE_NV 0x3259
-#define EGL_METADATA1_TYPE_NV 0x325A
-#define EGL_METADATA2_TYPE_NV 0x325B
-#define EGL_METADATA3_TYPE_NV 0x325C
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDISPLAYATTRIBNVPROC) (EGLDisplay dpy, EGLint attribute, EGLAttrib *value);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLSETSTREAMMETADATANVPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLint n, EGLint offset, EGLint size, const void *data);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSTREAMMETADATANVPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum name, EGLint n, EGLint offset, EGLint size, void *data);
-#ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLBoolean EGLAPIENTRY eglQueryDisplayAttribNV (EGLDisplay dpy, EGLint attribute, EGLAttrib *value);
-EGLAPI EGLBoolean EGLAPIENTRY eglSetStreamMetadataNV (EGLDisplay dpy, EGLStreamKHR stream, EGLint n, EGLint offset, EGLint size, const void *data);
-EGLAPI EGLBoolean EGLAPIENTRY eglQueryStreamMetadataNV (EGLDisplay dpy, EGLStreamKHR stream, EGLenum name, EGLint n, EGLint offset, EGLint size, void *data);
-#endif
-#endif /* EGL_NV_stream_metadata */
-
-#ifndef EGL_NV_stream_origin
-#define EGL_NV_stream_origin 1
-#define EGL_STREAM_FRAME_ORIGIN_X_NV 0x3366
-#define EGL_STREAM_FRAME_ORIGIN_Y_NV 0x3367
-#define EGL_STREAM_FRAME_MAJOR_AXIS_NV 0x3368
-#define EGL_CONSUMER_AUTO_ORIENTATION_NV 0x3369
-#define EGL_PRODUCER_AUTO_ORIENTATION_NV 0x336A
-#define EGL_LEFT_NV 0x336B
-#define EGL_RIGHT_NV 0x336C
-#define EGL_TOP_NV 0x336D
-#define EGL_BOTTOM_NV 0x336E
-#define EGL_X_AXIS_NV 0x336F
-#define EGL_Y_AXIS_NV 0x3370
-#endif /* EGL_NV_stream_origin */
-
-#ifndef EGL_NV_stream_remote
-#define EGL_NV_stream_remote 1
-#define EGL_STREAM_STATE_INITIALIZING_NV 0x3240
-#define EGL_STREAM_TYPE_NV 0x3241
-#define EGL_STREAM_PROTOCOL_NV 0x3242
-#define EGL_STREAM_ENDPOINT_NV 0x3243
-#define EGL_STREAM_LOCAL_NV 0x3244
-#define EGL_STREAM_PRODUCER_NV 0x3247
-#define EGL_STREAM_CONSUMER_NV 0x3248
-#define EGL_STREAM_PROTOCOL_FD_NV 0x3246
-#endif /* EGL_NV_stream_remote */
-
-#ifndef EGL_NV_stream_reset
-#define EGL_NV_stream_reset 1
-#define EGL_SUPPORT_RESET_NV 0x3334
-#define EGL_SUPPORT_REUSE_NV 0x3335
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLRESETSTREAMNVPROC) (EGLDisplay dpy, EGLStreamKHR stream);
-#ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLBoolean EGLAPIENTRY eglResetStreamNV (EGLDisplay dpy, EGLStreamKHR stream);
-#endif
-#endif /* EGL_NV_stream_reset */
-
-#ifndef EGL_NV_stream_socket
-#define EGL_NV_stream_socket 1
-#define EGL_STREAM_PROTOCOL_SOCKET_NV 0x324B
-#define EGL_SOCKET_HANDLE_NV 0x324C
-#define EGL_SOCKET_TYPE_NV 0x324D
-#endif /* EGL_NV_stream_socket */
-
-#ifndef EGL_NV_stream_socket_inet
-#define EGL_NV_stream_socket_inet 1
-#define EGL_SOCKET_TYPE_INET_NV 0x324F
-#endif /* EGL_NV_stream_socket_inet */
-
-#ifndef EGL_NV_stream_socket_unix
-#define EGL_NV_stream_socket_unix 1
-#define EGL_SOCKET_TYPE_UNIX_NV 0x324E
-#endif /* EGL_NV_stream_socket_unix */
-
-#ifndef EGL_NV_stream_sync
-#define EGL_NV_stream_sync 1
-#define EGL_SYNC_NEW_FRAME_NV 0x321F
-typedef EGLSyncKHR (EGLAPIENTRYP PFNEGLCREATESTREAMSYNCNVPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum type, const EGLint *attrib_list);
-#ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLSyncKHR EGLAPIENTRY eglCreateStreamSyncNV (EGLDisplay dpy, EGLStreamKHR stream, EGLenum type, const EGLint *attrib_list);
-#endif
-#endif /* EGL_NV_stream_sync */
-
-#ifndef EGL_NV_sync
-#define EGL_NV_sync 1
-typedef void *EGLSyncNV;
-typedef khronos_utime_nanoseconds_t EGLTimeNV;
-#ifdef KHRONOS_SUPPORT_INT64
-#define EGL_SYNC_PRIOR_COMMANDS_COMPLETE_NV 0x30E6
-#define EGL_SYNC_STATUS_NV 0x30E7
-#define EGL_SIGNALED_NV 0x30E8
-#define EGL_UNSIGNALED_NV 0x30E9
-#define EGL_SYNC_FLUSH_COMMANDS_BIT_NV 0x0001
-#define EGL_FOREVER_NV 0xFFFFFFFFFFFFFFFFull
-#define EGL_ALREADY_SIGNALED_NV 0x30EA
-#define EGL_TIMEOUT_EXPIRED_NV 0x30EB
-#define EGL_CONDITION_SATISFIED_NV 0x30EC
-#define EGL_SYNC_TYPE_NV 0x30ED
-#define EGL_SYNC_CONDITION_NV 0x30EE
-#define EGL_SYNC_FENCE_NV 0x30EF
-#define EGL_NO_SYNC_NV EGL_CAST(EGLSyncNV,0)
-typedef EGLSyncNV (EGLAPIENTRYP PFNEGLCREATEFENCESYNCNVPROC) (EGLDisplay dpy, EGLenum condition, const EGLint *attrib_list);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSYNCNVPROC) (EGLSyncNV sync);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLFENCENVPROC) (EGLSyncNV sync);
-typedef EGLint (EGLAPIENTRYP PFNEGLCLIENTWAITSYNCNVPROC) (EGLSyncNV sync, EGLint flags, EGLTimeNV timeout);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLSIGNALSYNCNVPROC) (EGLSyncNV sync, EGLenum mode);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETSYNCATTRIBNVPROC) (EGLSyncNV sync, EGLint attribute, EGLint *value);
-#ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLSyncNV EGLAPIENTRY eglCreateFenceSyncNV (EGLDisplay dpy, EGLenum condition, const EGLint *attrib_list);
-EGLAPI EGLBoolean EGLAPIENTRY eglDestroySyncNV (EGLSyncNV sync);
-EGLAPI EGLBoolean EGLAPIENTRY eglFenceNV (EGLSyncNV sync);
-EGLAPI EGLint EGLAPIENTRY eglClientWaitSyncNV (EGLSyncNV sync, EGLint flags, EGLTimeNV timeout);
-EGLAPI EGLBoolean EGLAPIENTRY eglSignalSyncNV (EGLSyncNV sync, EGLenum mode);
-EGLAPI EGLBoolean EGLAPIENTRY eglGetSyncAttribNV (EGLSyncNV sync, EGLint attribute, EGLint *value);
-#endif
-#endif /* KHRONOS_SUPPORT_INT64 */
-#endif /* EGL_NV_sync */
-
-#ifndef EGL_NV_system_time
-#define EGL_NV_system_time 1
-typedef khronos_utime_nanoseconds_t EGLuint64NV;
-#ifdef KHRONOS_SUPPORT_INT64
-typedef EGLuint64NV (EGLAPIENTRYP PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC) (void);
-typedef EGLuint64NV (EGLAPIENTRYP PFNEGLGETSYSTEMTIMENVPROC) (void);
-#ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLuint64NV EGLAPIENTRY eglGetSystemTimeFrequencyNV (void);
-EGLAPI EGLuint64NV EGLAPIENTRY eglGetSystemTimeNV (void);
-#endif
-#endif /* KHRONOS_SUPPORT_INT64 */
-#endif /* EGL_NV_system_time */
-
-#ifndef EGL_NV_triple_buffer
-#define EGL_NV_triple_buffer 1
-#define EGL_TRIPLE_BUFFER_NV 0x3230
-#endif /* EGL_NV_triple_buffer */
-
-#ifndef EGL_TIZEN_image_native_buffer
-#define EGL_TIZEN_image_native_buffer 1
-#define EGL_NATIVE_BUFFER_TIZEN 0x32A0
-#endif /* EGL_TIZEN_image_native_buffer */
-
-#ifndef EGL_TIZEN_image_native_surface
-#define EGL_TIZEN_image_native_surface 1
-#define EGL_NATIVE_SURFACE_TIZEN 0x32A1
-#endif /* EGL_TIZEN_image_native_surface */
-
-#ifndef EGL_WL_bind_wayland_display
-#define EGL_WL_bind_wayland_display 1
-#define PFNEGLBINDWAYLANDDISPLAYWL PFNEGLBINDWAYLANDDISPLAYWLPROC
-#define PFNEGLUNBINDWAYLANDDISPLAYWL PFNEGLUNBINDWAYLANDDISPLAYWLPROC
-#define PFNEGLQUERYWAYLANDBUFFERWL PFNEGLQUERYWAYLANDBUFFERWLPROC
-struct wl_display;
-struct wl_resource;
-#define EGL_WAYLAND_BUFFER_WL 0x31D5
-#define EGL_WAYLAND_PLANE_WL 0x31D6
-#define EGL_TEXTURE_Y_U_V_WL 0x31D7
-#define EGL_TEXTURE_Y_UV_WL 0x31D8
-#define EGL_TEXTURE_Y_XUXV_WL 0x31D9
-#define EGL_TEXTURE_EXTERNAL_WL 0x31DA
-#define EGL_WAYLAND_Y_INVERTED_WL 0x31DB
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLBINDWAYLANDDISPLAYWLPROC) (EGLDisplay dpy, struct wl_display *display);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLUNBINDWAYLANDDISPLAYWLPROC) (EGLDisplay dpy, struct wl_display *display);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYWAYLANDBUFFERWLPROC) (EGLDisplay dpy, struct wl_resource *buffer, EGLint attribute, EGLint *value);
-#ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLBoolean EGLAPIENTRY eglBindWaylandDisplayWL (EGLDisplay dpy, struct wl_display *display);
-EGLAPI EGLBoolean EGLAPIENTRY eglUnbindWaylandDisplayWL (EGLDisplay dpy, struct wl_display *display);
-EGLAPI EGLBoolean EGLAPIENTRY eglQueryWaylandBufferWL (EGLDisplay dpy, struct wl_resource *buffer, EGLint attribute, EGLint *value);
-#endif
-#endif /* EGL_WL_bind_wayland_display */
-
-#ifndef EGL_WL_create_wayland_buffer_from_image
-#define EGL_WL_create_wayland_buffer_from_image 1
-#define PFNEGLCREATEWAYLANDBUFFERFROMIMAGEWL PFNEGLCREATEWAYLANDBUFFERFROMIMAGEWLPROC
-struct wl_buffer;
-typedef struct wl_buffer *(EGLAPIENTRYP PFNEGLCREATEWAYLANDBUFFERFROMIMAGEWLPROC) (EGLDisplay dpy, EGLImageKHR image);
-#ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI struct wl_buffer *EGLAPIENTRY eglCreateWaylandBufferFromImageWL (EGLDisplay dpy, EGLImageKHR image);
-#endif
-#endif /* EGL_WL_create_wayland_buffer_from_image */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif \ No newline at end of file
diff --git a/host/libs/graphics_detector/include/EGL/eglplatform.h b/host/libs/graphics_detector/include/EGL/eglplatform.h
deleted file mode 100644
index a35f91cce..000000000
--- a/host/libs/graphics_detector/include/EGL/eglplatform.h
+++ /dev/null
@@ -1,182 +0,0 @@
-#ifndef __eglplatform_h_
-#define __eglplatform_h_
-
-/*
-** Copyright (c) 2007-2016 The Khronos Group Inc.
-**
-** Permission is hereby granted, free of charge, to any person obtaining a
-** copy of this software and/or associated documentation files (the
-** "Materials"), to deal in the Materials without restriction, including
-** without limitation the rights to use, copy, modify, merge, publish,
-** distribute, sublicense, and/or sell copies of the Materials, and to
-** permit persons to whom the Materials are furnished to do so, subject to
-** the following conditions:
-**
-** The above copyright notice and this permission notice shall be included
-** in all copies or substantial portions of the Materials.
-**
-** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
-*/
-
-/* Platform-specific types and definitions for egl.h
- * $Revision: 30994 $ on $Date: 2015-04-30 13:36:48 -0700 (Thu, 30 Apr 2015) $
- *
- * Adopters may modify khrplatform.h and this file to suit their platform.
- * You are encouraged to submit all modifications to the Khronos group so that
- * they can be included in future versions of this file. Please submit changes
- * by sending them to the public Khronos Bugzilla (http://khronos.org/bugzilla)
- * by filing a bug against product "EGL" component "Registry".
- */
-
-#include <KHR/khrplatform.h>
-
-/* Macros used in EGL function prototype declarations.
- *
- * EGL functions should be prototyped as:
- *
- * EGLAPI return-type EGLAPIENTRY eglFunction(arguments);
- * typedef return-type (EXPAPIENTRYP PFNEGLFUNCTIONPROC) (arguments);
- *
- * KHRONOS_APICALL and KHRONOS_APIENTRY are defined in KHR/khrplatform.h
- */
-
-#ifndef EGLAPI
-#define EGLAPI KHRONOS_APICALL
-#endif
-
-#ifndef EGLAPIENTRY
-#define EGLAPIENTRY KHRONOS_APIENTRY
-#endif
-#define EGLAPIENTRYP EGLAPIENTRY*
-
-/* The types NativeDisplayType, NativeWindowType, and NativePixmapType
- * are aliases of window-system-dependent types, such as X Display * or
- * Windows Device Context. They must be defined in platform-specific
- * code below. The EGL-prefixed versions of Native*Type are the same
- * types, renamed in EGL 1.3 so all types in the API start with "EGL".
- *
- * Khronos STRONGLY RECOMMENDS that you use the default definitions
- * provided below, since these changes affect both binary and source
- * portability of applications using EGL running on different EGL
- * implementations.
- */
-
-#if defined(_WIN32) || defined(__VC32__) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) /* Win32 and WinCE */
-#ifndef WIN32_LEAN_AND_MEAN
-#define WIN32_LEAN_AND_MEAN 1
-#endif
-#include <windows.h>
-
-typedef HDC EGLNativeDisplayType;
-typedef HBITMAP EGLNativePixmapType;
-typedef HWND EGLNativeWindowType;
-
-#elif defined(__EMSCRIPTEN__)
-
-typedef int EGLNativeDisplayType;
-typedef int EGLNativePixmapType;
-typedef int EGLNativeWindowType;
-
-#elif defined(__WINSCW__) || defined(__SYMBIAN32__) /* Symbian */
-
-typedef int EGLNativeDisplayType;
-typedef void *EGLNativePixmapType;
-typedef void *EGLNativeWindowType;
-
-#elif defined(WL_EGL_PLATFORM)
-
-typedef struct wl_display *EGLNativeDisplayType;
-typedef struct wl_egl_pixmap *EGLNativePixmapType;
-typedef struct wl_egl_window *EGLNativeWindowType;
-
-#elif defined(__GBM__)
-
-typedef struct gbm_device *EGLNativeDisplayType;
-typedef struct gbm_bo *EGLNativePixmapType;
-typedef void *EGLNativeWindowType;
-
-#elif defined(__ANDROID__) || defined(ANDROID)
-
-struct ANativeWindow;
-struct egl_native_pixmap_t;
-
-typedef void* EGLNativeDisplayType;
-typedef struct egl_native_pixmap_t* EGLNativePixmapType;
-typedef struct ANativeWindow* EGLNativeWindowType;
-
-#elif defined(USE_OZONE)
-
-typedef intptr_t EGLNativeDisplayType;
-typedef intptr_t EGLNativePixmapType;
-typedef intptr_t EGLNativeWindowType;
-
-#elif defined(__unix__) && defined(EGL_NO_X11)
-
-typedef void *EGLNativeDisplayType;
-typedef khronos_uintptr_t EGLNativePixmapType;
-typedef khronos_uintptr_t EGLNativeWindowType;
-
-#elif defined(__unix__) || defined(USE_X11)
-
-/* X11 (tentative) */
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-
-typedef Display *EGLNativeDisplayType;
-typedef Pixmap EGLNativePixmapType;
-typedef Window EGLNativeWindowType;
-
-#elif defined(__APPLE__)
-
-typedef int EGLNativeDisplayType;
-typedef void *EGLNativePixmapType;
-typedef void *EGLNativeWindowType;
-
-#elif defined(__HAIKU__)
-
-#include <kernel/image.h>
-
-typedef void *EGLNativeDisplayType;
-typedef khronos_uintptr_t EGLNativePixmapType;
-typedef khronos_uintptr_t EGLNativeWindowType;
-
-#elif defined(__Fuchsia__)
-
-typedef void *EGLNativeDisplayType;
-typedef khronos_uintptr_t EGLNativePixmapType;
-typedef khronos_uintptr_t EGLNativeWindowType;
-
-#else
-#error "Platform not recognized"
-#endif
-
-/* EGL 1.2 types, renamed for consistency in EGL 1.3 */
-typedef EGLNativeDisplayType NativeDisplayType;
-typedef EGLNativePixmapType NativePixmapType;
-typedef EGLNativeWindowType NativeWindowType;
-
-
-/* Define EGLint. This must be a signed integral type large enough to contain
- * all legal attribute names and values passed into and out of EGL, whether
- * their type is boolean, bitmask, enumerant (symbolic constant), integer,
- * handle, or other. While in general a 32-bit integer will suffice, if
- * handles are 64 bit types, then EGLint should be defined as a signed 64-bit
- * integer type.
- */
-typedef khronos_int32_t EGLint;
-
-
-/* C++ / C typecast macros for special EGL handle values */
-#if defined(__cplusplus)
-#define EGL_CAST(type, value) (static_cast<type>(value))
-#else
-#define EGL_CAST(type, value) ((type) (value))
-#endif
-
-#endif /* __eglplatform_h */ \ No newline at end of file
diff --git a/host/libs/graphics_detector/include/KHR/khrplatform.h b/host/libs/graphics_detector/include/KHR/khrplatform.h
deleted file mode 100644
index 63e74c78b..000000000
--- a/host/libs/graphics_detector/include/KHR/khrplatform.h
+++ /dev/null
@@ -1,290 +0,0 @@
-#ifndef __khrplatform_h_
-#define __khrplatform_h_
-
-/*
-** Copyright (c) 2008-2018 The Khronos Group Inc.
-**
-** Permission is hereby granted, free of charge, to any person obtaining a
-** copy of this software and/or associated documentation files (the
-** "Materials"), to deal in the Materials without restriction, including
-** without limitation the rights to use, copy, modify, merge, publish,
-** distribute, sublicense, and/or sell copies of the Materials, and to
-** permit persons to whom the Materials are furnished to do so, subject to
-** the following conditions:
-**
-** The above copyright notice and this permission notice shall be included
-** in all copies or substantial portions of the Materials.
-**
-** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
-*/
-
-/* Khronos platform-specific types and definitions.
- *
- * The master copy of khrplatform.h is maintained in the Khronos EGL
- * Registry repository at https://github.com/KhronosGroup/EGL-Registry
- * The last semantic modification to khrplatform.h was at commit ID:
- * 67a3e0864c2d75ea5287b9f3d2eb74a745936692
- *
- * Adopters may modify this file to suit their platform. Adopters are
- * encouraged to submit platform specific modifications to the Khronos
- * group so that they can be included in future versions of this file.
- * Please submit changes by filing pull requests or issues on
- * the EGL Registry repository linked above.
- *
- *
- * See the Implementer's Guidelines for information about where this file
- * should be located on your system and for more details of its use:
- * http://www.khronos.org/registry/implementers_guide.pdf
- *
- * This file should be included as
- * #include <KHR/khrplatform.h>
- * by Khronos client API header files that use its types and defines.
- *
- * The types in khrplatform.h should only be used to define API-specific types.
- *
- * Types defined in khrplatform.h:
- * khronos_int8_t signed 8 bit
- * khronos_uint8_t unsigned 8 bit
- * khronos_int16_t signed 16 bit
- * khronos_uint16_t unsigned 16 bit
- * khronos_int32_t signed 32 bit
- * khronos_uint32_t unsigned 32 bit
- * khronos_int64_t signed 64 bit
- * khronos_uint64_t unsigned 64 bit
- * khronos_intptr_t signed same number of bits as a pointer
- * khronos_uintptr_t unsigned same number of bits as a pointer
- * khronos_ssize_t signed size
- * khronos_usize_t unsigned size
- * khronos_float_t signed 32 bit floating point
- * khronos_time_ns_t unsigned 64 bit time in nanoseconds
- * khronos_utime_nanoseconds_t unsigned time interval or absolute time in
- * nanoseconds
- * khronos_stime_nanoseconds_t signed time interval in nanoseconds
- * khronos_boolean_enum_t enumerated boolean type. This should
- * only be used as a base type when a client API's boolean type is
- * an enum. Client APIs which use an integer or other type for
- * booleans cannot use this as the base type for their boolean.
- *
- * Tokens defined in khrplatform.h:
- *
- * KHRONOS_FALSE, KHRONOS_TRUE Enumerated boolean false/true values.
- *
- * KHRONOS_SUPPORT_INT64 is 1 if 64 bit integers are supported; otherwise 0.
- * KHRONOS_SUPPORT_FLOAT is 1 if floats are supported; otherwise 0.
- *
- * Calling convention macros defined in this file:
- * KHRONOS_APICALL
- * KHRONOS_APIENTRY
- * KHRONOS_APIATTRIBUTES
- *
- * These may be used in function prototypes as:
- *
- * KHRONOS_APICALL void KHRONOS_APIENTRY funcname(
- * int arg1,
- * int arg2) KHRONOS_APIATTRIBUTES;
- */
-
-#if defined(__SCITECH_SNAP__) && !defined(KHRONOS_STATIC)
-# define KHRONOS_STATIC 1
-#endif
-
-/*-------------------------------------------------------------------------
- * Definition of KHRONOS_APICALL
- *-------------------------------------------------------------------------
- * This precedes the return type of the function in the function prototype.
- */
-#if defined(KHRONOS_STATIC)
- /* If the preprocessor constant KHRONOS_STATIC is defined, make the
- * header compatible with static linking. */
-# define KHRONOS_APICALL
-#elif defined(_WIN32)
-# define KHRONOS_APICALL __declspec(dllimport)
-#elif defined (__SYMBIAN32__)
-# define KHRONOS_APICALL IMPORT_C
-#elif defined(__ANDROID__)
-# define KHRONOS_APICALL __attribute__((visibility("default")))
-#else
-# define KHRONOS_APICALL
-#endif
-
-/*-------------------------------------------------------------------------
- * Definition of KHRONOS_APIENTRY
- *-------------------------------------------------------------------------
- * This follows the return type of the function and precedes the function
- * name in the function prototype.
- */
-#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(KHRONOS_STATIC)
- /* Win32 but not WinCE */
-# define KHRONOS_APIENTRY __stdcall
-#else
-# define KHRONOS_APIENTRY
-#endif
-
-/*-------------------------------------------------------------------------
- * Definition of KHRONOS_APIATTRIBUTES
- *-------------------------------------------------------------------------
- * This follows the closing parenthesis of the function prototype arguments.
- */
-#if defined (__ARMCC_2__)
-#define KHRONOS_APIATTRIBUTES __softfp
-#else
-#define KHRONOS_APIATTRIBUTES
-#endif
-
-/*-------------------------------------------------------------------------
- * basic type definitions
- *-----------------------------------------------------------------------*/
-#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__GNUC__) || defined(__SCO__) || defined(__USLC__)
-
-
-/*
- * Using <stdint.h>
- */
-#include <stdint.h>
-typedef int32_t khronos_int32_t;
-typedef uint32_t khronos_uint32_t;
-typedef int64_t khronos_int64_t;
-typedef uint64_t khronos_uint64_t;
-#define KHRONOS_SUPPORT_INT64 1
-#define KHRONOS_SUPPORT_FLOAT 1
-
-#elif defined(__VMS ) || defined(__sgi)
-
-/*
- * Using <inttypes.h>
- */
-#include <inttypes.h>
-typedef int32_t khronos_int32_t;
-typedef uint32_t khronos_uint32_t;
-typedef int64_t khronos_int64_t;
-typedef uint64_t khronos_uint64_t;
-#define KHRONOS_SUPPORT_INT64 1
-#define KHRONOS_SUPPORT_FLOAT 1
-
-#elif defined(_WIN32) && !defined(__SCITECH_SNAP__)
-
-/*
- * Win32
- */
-typedef __int32 khronos_int32_t;
-typedef unsigned __int32 khronos_uint32_t;
-typedef __int64 khronos_int64_t;
-typedef unsigned __int64 khronos_uint64_t;
-#define KHRONOS_SUPPORT_INT64 1
-#define KHRONOS_SUPPORT_FLOAT 1
-
-#elif defined(__sun__) || defined(__digital__)
-
-/*
- * Sun or Digital
- */
-typedef int khronos_int32_t;
-typedef unsigned int khronos_uint32_t;
-#if defined(__arch64__) || defined(_LP64)
-typedef long int khronos_int64_t;
-typedef unsigned long int khronos_uint64_t;
-#else
-typedef long long int khronos_int64_t;
-typedef unsigned long long int khronos_uint64_t;
-#endif /* __arch64__ */
-#define KHRONOS_SUPPORT_INT64 1
-#define KHRONOS_SUPPORT_FLOAT 1
-
-#elif 0
-
-/*
- * Hypothetical platform with no float or int64 support
- */
-typedef int khronos_int32_t;
-typedef unsigned int khronos_uint32_t;
-#define KHRONOS_SUPPORT_INT64 0
-#define KHRONOS_SUPPORT_FLOAT 0
-
-#else
-
-/*
- * Generic fallback
- */
-#include <stdint.h>
-typedef int32_t khronos_int32_t;
-typedef uint32_t khronos_uint32_t;
-typedef int64_t khronos_int64_t;
-typedef uint64_t khronos_uint64_t;
-#define KHRONOS_SUPPORT_INT64 1
-#define KHRONOS_SUPPORT_FLOAT 1
-
-#endif
-
-
-/*
- * Types that are (so far) the same on all platforms
- */
-typedef signed char khronos_int8_t;
-typedef unsigned char khronos_uint8_t;
-typedef signed short int khronos_int16_t;
-typedef unsigned short int khronos_uint16_t;
-
-/*
- * Types that differ between LLP64 and LP64 architectures - in LLP64,
- * pointers are 64 bits, but 'long' is still 32 bits. Win64 appears
- * to be the only LLP64 architecture in current use.
- */
-#ifdef _WIN64
-typedef signed long long int khronos_intptr_t;
-typedef unsigned long long int khronos_uintptr_t;
-typedef signed long long int khronos_ssize_t;
-typedef unsigned long long int khronos_usize_t;
-#else
-typedef signed long int khronos_intptr_t;
-typedef unsigned long int khronos_uintptr_t;
-typedef signed long int khronos_ssize_t;
-typedef unsigned long int khronos_usize_t;
-#endif
-
-#if KHRONOS_SUPPORT_FLOAT
-/*
- * Float type
- */
-typedef float khronos_float_t;
-#endif
-
-#if KHRONOS_SUPPORT_INT64
-/* Time types
- *
- * These types can be used to represent a time interval in nanoseconds or
- * an absolute Unadjusted System Time. Unadjusted System Time is the number
- * of nanoseconds since some arbitrary system event (e.g. since the last
- * time the system booted). The Unadjusted System Time is an unsigned
- * 64 bit value that wraps back to 0 every 584 years. Time intervals
- * may be either signed or unsigned.
- */
-typedef khronos_uint64_t khronos_utime_nanoseconds_t;
-typedef khronos_int64_t khronos_stime_nanoseconds_t;
-#endif
-
-/*
- * Dummy value used to pad enum types to 32 bits.
- */
-#ifndef KHRONOS_MAX_ENUM
-#define KHRONOS_MAX_ENUM 0x7FFFFFFF
-#endif
-
-/*
- * Enumerated boolean type
- *
- * Values other than zero should be considered to be true. Therefore
- * comparisons should not be made against KHRONOS_TRUE.
- */
-typedef enum {
- KHRONOS_FALSE = 0,
- KHRONOS_TRUE = 1,
- KHRONOS_BOOLEAN_ENUM_FORCE_SIZE = KHRONOS_MAX_ENUM
-} khronos_boolean_enum_t;
-
-#endif /* __khrplatform_h_ */ \ No newline at end of file
diff --git a/host/libs/image_aggregator/Android.bp b/host/libs/image_aggregator/Android.bp
deleted file mode 100644
index 23d4874fe..000000000
--- a/host/libs/image_aggregator/Android.bp
+++ /dev/null
@@ -1,54 +0,0 @@
-//
-// Copyright (C) 2021 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-cc_library {
- name: "libcdisk_spec",
- srcs: [
- "cdisk_spec.proto",
- ],
- proto: {
- type: "lite",
- export_proto_headers: true,
- include_dirs: [
- "external/protobuf/src",
- ],
- },
- defaults: ["cuttlefish_host"],
-}
-
-cc_library_static {
- name: "libimage_aggregator",
- srcs: [
- "image_aggregator.cc",
- ],
- export_include_dirs: ["."],
- shared_libs: [
- "libcuttlefish_fs",
- "libcuttlefish_utils",
- "libbase",
- "libprotobuf-cpp-lite",
- "libz",
- ],
- static_libs: [
- "libcdisk_spec",
- "libext2_uuid",
- "libsparse",
- ],
- defaults: ["cuttlefish_host"],
-}
diff --git a/host/libs/image_aggregator/image_aggregator.cc b/host/libs/image_aggregator/image_aggregator.cc
deleted file mode 100644
index b6b412d6c..000000000
--- a/host/libs/image_aggregator/image_aggregator.cc
+++ /dev/null
@@ -1,509 +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.
- */
-
-/*
- * GUID Partition Table and Composite Disk generation code.
- */
-
-#include "host/libs/image_aggregator/image_aggregator.h"
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <stdio.h>
-
-#include <fstream>
-#include <string>
-#include <vector>
-
-#include <android-base/file.h>
-#include <android-base/logging.h>
-#include <cdisk_spec.pb.h>
-#include <google/protobuf/text_format.h>
-#include <sparse/sparse.h>
-#include <uuid.h>
-#include <zlib.h>
-
-#include "common/libs/fs/shared_buf.h"
-#include "common/libs/fs/shared_fd.h"
-#include "common/libs/utils/files.h"
-#include "common/libs/utils/size_utils.h"
-#include "common/libs/utils/subprocess.h"
-#include "host/libs/config/mbr.h"
-
-namespace cuttlefish {
-namespace {
-
-constexpr int GPT_NUM_PARTITIONS = 128;
-
-/**
- * Creates a "Protective" MBR Partition Table header. The GUID
- * Partition Table Specification recommends putting this on the first sector
- * of the disk, to protect against old disk formatting tools from misidentifying
- * the GUID Partition Table later and doing the wrong thing.
- */
-MasterBootRecord ProtectiveMbr(std::uint64_t size) {
- MasterBootRecord mbr = {
- .partitions = {{
- .partition_type = 0xEE,
- .first_lba = 1,
- .num_sectors = (std::uint32_t) size / SECTOR_SIZE,
- }},
- .boot_signature = { 0x55, 0xAA },
- };
- return mbr;
-}
-
-struct __attribute__((packed)) GptHeader {
- std::uint8_t signature[8];
- std::uint8_t revision[4];
- std::uint32_t header_size;
- std::uint32_t header_crc32;
- std::uint32_t reserved;
- std::uint64_t current_lba;
- std::uint64_t backup_lba;
- std::uint64_t first_usable_lba;
- std::uint64_t last_usable_lba;
- std::uint8_t disk_guid[16];
- std::uint64_t partition_entries_lba;
- std::uint32_t num_partition_entries;
- std::uint32_t partition_entry_size;
- std::uint32_t partition_entries_crc32;
-};
-
-static_assert(sizeof(GptHeader) == 92);
-
-struct __attribute__((packed)) GptPartitionEntry {
- std::uint8_t partition_type_guid[16];
- std::uint8_t unique_partition_guid[16];
- std::uint64_t first_lba;
- std::uint64_t last_lba;
- std::uint64_t attributes;
- std::uint16_t partition_name[36]; // UTF-16LE
-};
-
-static_assert(sizeof(GptPartitionEntry) == 128);
-
-struct __attribute__((packed)) GptBeginning {
- MasterBootRecord protective_mbr;
- GptHeader header;
- std::uint8_t header_padding[420];
- GptPartitionEntry entries[GPT_NUM_PARTITIONS];
- std::uint8_t partition_alignment[3072];
-};
-
-static_assert(sizeof(GptBeginning) == SECTOR_SIZE * 40);
-
-struct __attribute__((packed)) GptEnd {
- GptPartitionEntry entries[GPT_NUM_PARTITIONS];
- GptHeader footer;
- std::uint8_t footer_padding[420];
-};
-
-static_assert(sizeof(GptEnd) == SECTOR_SIZE * 33);
-
-struct PartitionInfo {
- MultipleImagePartition source;
- std::uint64_t guest_size;
- std::uint64_t host_size;
- std::uint64_t offset;
-};
-
-/*
- * Returns the file size of `file_path`. If `file_path` is an Android-Sparse
- * file, returns the file size it would have after being converted to a raw
- * file.
- *
- * Android-Sparse is a file format invented by Android that optimizes for
- * chunks of zeroes or repeated data. The Android build system can produce
- * sparse files to save on size of disk files after they are extracted from a
- * disk file, as the imag eflashing process also can handle Android-Sparse
- * images.
- */
-std::uint64_t UnsparsedSize(const std::string& file_path) {
- auto fd = open(file_path.c_str(), O_RDONLY);
- CHECK(fd >= 0) << "Could not open \"" << file_path << "\""
- << strerror(errno);
- auto sparse = sparse_file_import(fd, /* verbose */ false, /* crc */ false);
- auto size =
- sparse ? sparse_file_len(sparse, false, true) : FileSize(file_path);
- close(fd);
- return size;
-}
-
-/*
- * strncpy equivalent for u16 data. GPT disks use UTF16-LE for disk labels.
- */
-void u16cpy(std::uint16_t* dest, std::uint16_t* src, std::size_t size) {
- while (size > 0 && *src) {
- *dest = *src;
- dest++;
- src++;
- size--;
- }
- if (size > 0) {
- *dest = 0;
- }
-}
-
-MultipleImagePartition ToMultipleImagePartition(ImagePartition source) {
- return MultipleImagePartition{
- .label = source.label,
- .image_file_paths = std::vector{source.image_file_path},
- .type = source.type,
- .read_only = source.read_only,
- };
-}
-
-/**
- * Incremental builder class for producing partition tables. Add partitions
- * one-by-one, then produce specification files
- */
-class CompositeDiskBuilder {
-private:
- std::vector<PartitionInfo> partitions_;
- std::uint64_t next_disk_offset_;
-
- static const char* GetPartitionGUID(MultipleImagePartition source) {
- // Due to some endianness mismatch in e2fsprogs GUID vs GPT, the GUIDs are
- // rearranged to make the right GUIDs appear in gdisk
- switch (source.type) {
- case kLinuxFilesystem:
- // Technically 0FC63DAF-8483-4772-8E79-3D69D8477DE4
- return "AF3DC60F-8384-7247-8E79-3D69D8477DE4";
- case kEfiSystemPartition:
- // Technically C12A7328-F81F-11D2-BA4B-00A0C93EC93B
- return "28732AC1-1FF8-D211-BA4B-00A0C93EC93B";
- default:
- LOG(FATAL) << "Unknown partition type: " << (int) source.type;
- }
- }
-
-public:
- CompositeDiskBuilder() : next_disk_offset_(sizeof(GptBeginning)) {}
-
- void AppendPartition(ImagePartition source) {
- AppendPartition(ToMultipleImagePartition(source));
- }
-
- void AppendPartition(MultipleImagePartition source) {
- uint64_t host_size = 0;
- for (const auto& path : source.image_file_paths) {
- host_size += UnsparsedSize(path);
- }
- auto guest_size = AlignToPowerOf2(host_size, PARTITION_SIZE_SHIFT);
- CHECK(host_size == guest_size || source.read_only)
- << "read-write partition " << source.label
- << " is not aligned to the size of " << (1 << PARTITION_SIZE_SHIFT);
- partitions_.push_back(PartitionInfo{
- .source = source,
- .guest_size = guest_size,
- .host_size = host_size,
- .offset = next_disk_offset_,
- });
- next_disk_offset_ =
- AlignToPowerOf2(next_disk_offset_ + guest_size, PARTITION_SIZE_SHIFT);
- }
-
- std::uint64_t DiskSize() const {
- std::uint64_t val = next_disk_offset_ + sizeof(GptEnd);
- return AlignToPowerOf2(val, DISK_SIZE_SHIFT);
- }
-
- /**
- * Generates a composite disk specification file, assuming that `header_file`
- * and `footer_file` will be populated with the contents of `Beginning()` and
- * `End()`.
- */
- CompositeDisk MakeCompositeDiskSpec(const std::string& header_file,
- const std::string& footer_file) const {
- CompositeDisk disk;
- disk.set_version(1);
- disk.set_length(DiskSize());
-
- ComponentDisk* header = disk.add_component_disks();
- header->set_file_path(AbsolutePath(header_file));
- header->set_offset(0);
-
- for (auto& partition : partitions_) {
- uint64_t host_size = 0;
- for (const auto& path : partition.source.image_file_paths) {
- ComponentDisk* component = disk.add_component_disks();
- component->set_file_path(AbsolutePath(path));
- component->set_offset(partition.offset + host_size);
- component->set_read_write_capability(
- partition.source.read_only ? ReadWriteCapability::READ_ONLY
- : ReadWriteCapability::READ_WRITE);
- host_size += UnsparsedSize(path);
- }
- CHECK(partition.host_size == host_size);
- // When partition's size differs from its size on the host
- // reading the disk within the guest os would fail due to the gap.
- // Putting any disk bigger than 4K can fill this gap.
- // Here we reuse the header which is always > 4K.
- // We don't fill the "writable" disk's hole and it should be an error
- // because writes in the guest of can't be reflected to the backing file.
- if (partition.guest_size != partition.host_size) {
- ComponentDisk* component = disk.add_component_disks();
- component->set_file_path(AbsolutePath(header_file));
- component->set_offset(partition.offset + partition.host_size);
- component->set_read_write_capability(ReadWriteCapability::READ_ONLY);
- }
- }
-
- ComponentDisk* footer = disk.add_component_disks();
- footer->set_file_path(AbsolutePath(footer_file));
- footer->set_offset(next_disk_offset_);
-
- return disk;
- }
-
- /*
- * Returns a GUID Partition Table header structure for all the disks that have
- * been added with `AppendDisk`. Includes a protective MBR.
- *
- * This method is not deterministic: some data is generated such as the disk
- * uuids.
- */
- GptBeginning Beginning() const {
- if (partitions_.size() > GPT_NUM_PARTITIONS) {
- LOG(FATAL) << "Too many partitions: " << partitions_.size();
- return {};
- }
- GptBeginning gpt = {
- .protective_mbr = ProtectiveMbr(DiskSize()),
- .header = {
- .signature = {'E', 'F', 'I', ' ', 'P', 'A', 'R', 'T'},
- .revision = {0, 0, 1, 0},
- .header_size = sizeof(GptHeader),
- .current_lba = 1,
- .backup_lba = (next_disk_offset_ + sizeof(GptEnd)) / SECTOR_SIZE - 1,
- .first_usable_lba = sizeof(GptBeginning) / SECTOR_SIZE,
- .last_usable_lba = (next_disk_offset_ - SECTOR_SIZE) / SECTOR_SIZE,
- .partition_entries_lba = 2,
- .num_partition_entries = GPT_NUM_PARTITIONS,
- .partition_entry_size = sizeof(GptPartitionEntry),
- },
- };
- uuid_generate(gpt.header.disk_guid);
- for (std::size_t i = 0; i < partitions_.size(); i++) {
- const auto& partition = partitions_[i];
- gpt.entries[i] = GptPartitionEntry{
- .first_lba = partition.offset / SECTOR_SIZE,
- .last_lba =
- (partition.offset + partition.guest_size) / SECTOR_SIZE - 1,
- };
- uuid_generate(gpt.entries[i].unique_partition_guid);
- if (uuid_parse(GetPartitionGUID(partition.source),
- gpt.entries[i].partition_type_guid)) {
- LOG(FATAL) << "Could not parse partition guid";
- }
- std::u16string wide_name(partitions_[i].source.label.begin(),
- partitions_[i].source.label.end());
- u16cpy((std::uint16_t*) gpt.entries[i].partition_name,
- (std::uint16_t*) wide_name.c_str(), 36);
- }
- // Not sure these are right, but it works for bpttool
- gpt.header.partition_entries_crc32 =
- crc32(0, (std::uint8_t*) gpt.entries,
- GPT_NUM_PARTITIONS * sizeof(GptPartitionEntry));
- gpt.header.header_crc32 =
- crc32(0, (std::uint8_t*) &gpt.header, sizeof(GptHeader));
- return gpt;
- }
-
- /**
- * Generates a GUID Partition Table footer that matches the header in `head`.
- */
- GptEnd End(const GptBeginning& head) const {
- GptEnd gpt;
- std::memcpy((void*) gpt.entries, (void*) head.entries, 128 * 128);
- gpt.footer = head.header;
- gpt.footer.partition_entries_lba = next_disk_offset_ / SECTOR_SIZE;
- std::swap(gpt.footer.current_lba, gpt.footer.backup_lba);
- gpt.footer.header_crc32 = 0;
- gpt.footer.header_crc32 =
- crc32(0, (std::uint8_t*) &gpt.footer, sizeof(GptHeader));
- return gpt;
- }
-};
-
-bool WriteBeginning(SharedFD out, const GptBeginning& beginning) {
- std::string begin_str((const char*) &beginning, sizeof(GptBeginning));
- if (WriteAll(out, begin_str) != begin_str.size()) {
- LOG(ERROR) << "Could not write GPT beginning: " << out->StrError();
- return false;
- }
- return true;
-}
-
-bool WriteEnd(SharedFD out, const GptEnd& end, std::int64_t padding) {
- std::string end_str((const char*) &end, sizeof(GptEnd));
- end_str.resize(end_str.size() + padding, '\0');
- if (WriteAll(out, end_str) != end_str.size()) {
- LOG(ERROR) << "Could not write GPT end: " << out->StrError();
- return false;
- }
- return true;
-}
-
-/**
- * Converts any Android-Sparse image files in `partitions` to raw image files.
- *
- * Android-Sparse is a file format invented by Android that optimizes for
- * chunks of zeroes or repeated data. The Android build system can produce
- * sparse files to save on size of disk files after they are extracted from a
- * disk file, as the imag eflashing process also can handle Android-Sparse
- * images.
- *
- * crosvm has read-only support for Android-Sparse files, but QEMU does not
- * support them.
- */
-void DeAndroidSparse(const std::vector<ImagePartition>& partitions) {
- for (const auto& partition : partitions) {
- auto fd = open(partition.image_file_path.c_str(), O_RDONLY);
- if (fd < 0) {
- PLOG(FATAL) << "Could not open \"" << partition.image_file_path;
- break;
- }
- auto sparse = sparse_file_import(fd, /* verbose */ false, /* crc */ false);
- if (!sparse) {
- close(fd);
- continue;
- }
- LOG(INFO) << "Desparsing " << partition.image_file_path;
- std::string out_file_name = partition.image_file_path + ".desparse";
- auto write_fd = open(out_file_name.c_str(), O_RDWR | O_CREAT | O_TRUNC,
- S_IRUSR | S_IWUSR | S_IRGRP);
- if (write_fd < 0) {
- PLOG(FATAL) << "Could not open " << out_file_name;
- }
- int write_status = sparse_file_write(sparse, write_fd, /* gz */ false,
- /* sparse */ false, /* crc */ false);
- if (write_status < 0) {
- LOG(FATAL) << "Failed to desparse \"" << partition.image_file_path
- << "\": " << write_status;
- }
- close(write_fd);
- if (rename(out_file_name.c_str(), partition.image_file_path.c_str()) < 0) {
- int error_num = errno;
- LOG(FATAL) << "Could not move \"" << out_file_name << "\" to \""
- << partition.image_file_path << "\": " << strerror(error_num);
- }
- sparse_file_destroy(sparse);
- close(fd);
- }
-}
-
-} // namespace
-
-uint64_t AlignToPartitionSize(uint64_t size) {
- return AlignToPowerOf2(size, PARTITION_SIZE_SHIFT);
-}
-
-void AggregateImage(const std::vector<ImagePartition>& partitions,
- const std::string& output_path) {
- DeAndroidSparse(partitions);
- CompositeDiskBuilder builder;
- for (auto& partition : partitions) {
- builder.AppendPartition(partition);
- }
- auto output = SharedFD::Creat(output_path, 0600);
- auto beginning = builder.Beginning();
- if (!WriteBeginning(output, beginning)) {
- LOG(FATAL) << "Could not write GPT beginning to \"" << output_path
- << "\": " << output->StrError();
- }
- for (auto& disk : partitions) {
- auto disk_fd = SharedFD::Open(disk.image_file_path, O_RDONLY);
- auto file_size = FileSize(disk.image_file_path);
- if (!output->CopyFrom(*disk_fd, file_size)) {
- LOG(FATAL) << "Could not copy from \"" << disk.image_file_path
- << "\" to \"" << output_path << "\": " << output->StrError();
- }
- // Handle disk images that are not aligned to PARTITION_SIZE_SHIFT
- std::uint64_t padding =
- AlignToPowerOf2(file_size, PARTITION_SIZE_SHIFT) - file_size;
- std::string padding_str;
- padding_str.resize(padding, '\0');
- if (WriteAll(output, padding_str) != padding_str.size()) {
- LOG(FATAL) << "Could not write partition padding to \"" << output_path
- << "\": " << output->StrError();
- }
- }
- std::uint64_t padding =
- builder.DiskSize() - ((beginning.header.backup_lba + 1) * SECTOR_SIZE);
- if (!WriteEnd(output, builder.End(beginning), padding)) {
- LOG(FATAL) << "Could not write GPT end to \"" << output_path
- << "\": " << output->StrError();
- }
-};
-
-void CreateCompositeDisk(std::vector<ImagePartition> partitions,
- const std::string& header_file,
- const std::string& footer_file,
- const std::string& output_composite_path) {
- std::vector<MultipleImagePartition> multiple_image_partitions;
- for (const auto& partition : partitions) {
- multiple_image_partitions.push_back(ToMultipleImagePartition(partition));
- }
- return CreateCompositeDisk(std::move(multiple_image_partitions), header_file,
- footer_file, output_composite_path);
-}
-
-void CreateCompositeDisk(std::vector<MultipleImagePartition> partitions,
- const std::string& header_file,
- const std::string& footer_file,
- const std::string& output_composite_path) {
- CompositeDiskBuilder builder;
- for (auto& partition : partitions) {
- builder.AppendPartition(partition);
- }
- auto header = SharedFD::Creat(header_file, 0600);
- auto beginning = builder.Beginning();
- if (!WriteBeginning(header, beginning)) {
- LOG(FATAL) << "Could not write GPT beginning to \"" << header_file
- << "\": " << header->StrError();
- }
- auto footer = SharedFD::Creat(footer_file, 0600);
- std::uint64_t padding =
- builder.DiskSize() - ((beginning.header.backup_lba + 1) * SECTOR_SIZE);
- if (!WriteEnd(footer, builder.End(beginning), padding)) {
- LOG(FATAL) << "Could not write GPT end to \"" << footer_file
- << "\": " << footer->StrError();
- }
- auto composite_proto = builder.MakeCompositeDiskSpec(header_file, footer_file);
- std::ofstream composite(output_composite_path.c_str(),
- std::ios::binary | std::ios::trunc);
- composite << "composite_disk\x1d";
- composite_proto.SerializeToOstream(&composite);
- composite.flush();
-}
-
-void CreateQcowOverlay(const std::string& crosvm_path,
- const std::string& backing_file,
- const std::string& output_overlay_path) {
- Command crosvm_qcow2_cmd(crosvm_path);
- crosvm_qcow2_cmd.AddParameter("create_qcow2");
- crosvm_qcow2_cmd.AddParameter("--backing_file=", backing_file);
- crosvm_qcow2_cmd.AddParameter(output_overlay_path);
- int success = crosvm_qcow2_cmd.Start().Wait();
- if (success != 0) {
- LOG(FATAL) << "Unable to run crosvm create_qcow2. Exited with status " << success;
- }
-}
-
-} // namespace cuttlefish
diff --git a/host/libs/image_aggregator/image_aggregator.h b/host/libs/image_aggregator/image_aggregator.h
deleted file mode 100644
index b9a2458a0..000000000
--- a/host/libs/image_aggregator/image_aggregator.h
+++ /dev/null
@@ -1,98 +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.
- */
-#pragma once
-
-/**
- * Functions for manipulating disk files given to crosvm or QEMU.
- */
-
-#include <string>
-#include <vector>
-
-namespace cuttlefish {
-
-enum ImagePartitionType {
- kLinuxFilesystem = 0,
- kEfiSystemPartition,
-};
-
-struct ImagePartition {
- std::string label;
- std::string image_file_path;
- ImagePartitionType type;
- bool read_only;
-};
-
-struct MultipleImagePartition {
- std::string label;
- std::vector<std::string> image_file_paths;
- ImagePartitionType type;
- bool read_only;
-};
-
-uint64_t AlignToPartitionSize(uint64_t size);
-
-/**
- * Combine the files in `partition` into a single raw disk file and write it to
- * `output_path`. The raw disk file will have a GUID Partition Table and copy in
- * the contents of the files mentioned in `partitions`.
- */
-void AggregateImage(const std::vector<ImagePartition>& partitions,
- const std::string& output_path);
-
-/**
- * Generate the files necessary for booting with a Composite Disk.
- *
- * Composite Disk is a crosvm disk format that is a layer of indirection over
- * other disk files. The Composite Disk file lists names and offsets in the
- * virtual disk.
- *
- * For a complete single disk inside the VM, there must also be a GUID Partition
- * Table header and footer. These are saved to `header_file` and `footer_file`,
- * then the specification file containing the file paths and offsets is saved to
- * `output_composite_path`.
- */
-void CreateCompositeDisk(std::vector<ImagePartition> partitions,
- const std::string& header_file,
- const std::string& footer_file,
- const std::string& output_composite_path);
-
-/**
- * Overloaded function to generate a composite disk with multiple images for a
- * single partition.
- */
-void CreateCompositeDisk(std::vector<MultipleImagePartition> partitions,
- const std::string& header_file,
- const std::string& footer_file,
- const std::string& output_composite_path);
-/**
- * Generate a qcow overlay backed by a given implementation file.
- *
- * qcow, or "QEMU Copy-On-Write" is a file format containing a list of disk
- * offsets and file contents. This can be combined with a backing file, to
- * represent an original disk file plus disk updates over that file. The qcow
- * files can be swapped out and replaced without affecting the original. qcow
- * is supported by QEMU and crosvm.
- *
- * The crosvm binary at `crosvm_path` is used to generate an overlay file at
- * `output_overlay_path` that functions as an overlay on the file at
- * `backing_file`.
- */
-void CreateQcowOverlay(const std::string& crosvm_path,
- const std::string& backing_file,
- const std::string& output_overlay_path);
-
-}
diff --git a/host/libs/msg_queue/Android.bp b/host/libs/msg_queue/Android.bp
deleted file mode 100644
index 39d9c967c..000000000
--- a/host/libs/msg_queue/Android.bp
+++ /dev/null
@@ -1,35 +0,0 @@
-//
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-cc_library_host_static {
- name: "libcuttlefish_msg_queue",
- srcs: [
- "msg_queue.cc",
- ],
- shared_libs: [
- "libcuttlefish_fs",
- "libcuttlefish_utils",
- "libbase",
- ],
- static_libs: [
- "libcuttlefish_host_config",
- "libgflags",
- ],
- defaults: ["cuttlefish_host"],
-}
diff --git a/host/libs/msg_queue/README.md b/host/libs/msg_queue/README.md
deleted file mode 100644
index 3cef4114e..000000000
--- a/host/libs/msg_queue/README.md
+++ /dev/null
@@ -1,57 +0,0 @@
-# msg_queue
-
-This is the Cuttlefish message queue wrapper library, as one of the IPC options available. Below are the example usages running in two separate processes.
-
-```
-#define MAX_MSG_SIZE 200
-#define NUM_MESSAGES 100
-
-typedef struct msg_buffer {
- long mesg_type;
- char mesg_text[MAX_MSG_SIZE];
-} msg_buffer;
-
-int example_send()
-{
- // create message queue with the key 'a'
- int queue_id = msg_queue_create('a');
- struct msg_buffer msg;
- for (int i=1; i <= NUM_MESSAGES; i++) {
- // create message types 1-3
- msg.mesg_type = (i % 3) + 1;
- sprintf(msg.mesg_text, "test %d", i);
- int rc = msg_queue_send(queue_id, &msg, strlen(msg.mesg_text)+1, false);
- if (rc == -1) {
- perror("main: msgsnd");
- exit(1);
- }
- }
- printf("generated %d messages, exiting.\n", NUM_MESSAGES);
- return 0;
-}
-```
-
-```
-#define MAX_MSG_SIZE 200
-
-typedef struct msg_buffer {
- long mesg_type;
- char mesg_text[MAX_MSG_SIZE];
-} msg_buffer;
-
-int example_receive()
-{
- // create message queue with the key 'a'
- int queue_id = msg_queue_create('a');
- struct msg_buffer msg;
- while (1) {
- int rc = msg_queue_receive(queue_id, &msg, MAX_MSG_SIZE, 1, false);
- if (rc == -1) {
- perror("main: msgrcv");
- exit(1);
- }
- printf("Reader '%d' read message: '%s'\n", 1, msg.mesg_text);
- }
- return 0;
-}
-```
diff --git a/host/libs/msg_queue/msg_queue.cc b/host/libs/msg_queue/msg_queue.cc
deleted file mode 100644
index 8016a2347..000000000
--- a/host/libs/msg_queue/msg_queue.cc
+++ /dev/null
@@ -1,96 +0,0 @@
-//
-// Copyright (C) 2020 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 "host/libs/msg_queue/msg_queue.h"
-
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/ipc.h>
-#include <sys/msg.h>
-
-#include <fstream>
-#include <iostream>
-#include <memory>
-
-#include <android-base/logging.h>
-
-namespace cuttlefish {
-
-// class holds `msgid` returned from msg_queue_create, and match the lifetime of
-// the message queue to the lifetime of the object.
-
-SysVMessageQueue::SysVMessageQueue(int id) { msgid = id; }
-
-SysVMessageQueue::~SysVMessageQueue(void) {
- if (msgctl(msgid, IPC_RMID, NULL) < 0) {
- int error_num = errno;
- LOG(ERROR) << "Could not remove message queue: " << strerror(error_num);
- }
-}
-
-// SysVMessageQueue::Create would return an empty/null std::unique_ptr if
-// initialization failed.
-std::unique_ptr<SysVMessageQueue> SysVMessageQueue::Create(
- const std::string& path, char proj_id) {
- // key file must exist before calling ftok
- std::fstream fs;
- fs.open(path, std::ios::out);
- fs.close();
-
- // only the owning user has access
- key_t key = ftok(path.c_str(), proj_id);
- if (key < 0) {
- int error_num = errno;
- LOG(ERROR) << "Could not ftok to create IPC key: " << strerror(error_num);
- return NULL;
- }
- int queue_id = msgget(key, 0);
- if (queue_id < 0) {
- queue_id = msgget(key, IPC_CREAT | IPC_EXCL | 0600);
- }
- auto msg = std::unique_ptr<SysVMessageQueue>(new SysVMessageQueue(queue_id));
- return msg;
-}
-
-int SysVMessageQueue::Send(void* data, size_t size, bool block) {
- int msgflg = block ? 0 : IPC_NOWAIT;
- if (msgsnd(msgid, data, size, msgflg) < 0) {
- int error_num = errno;
- if (error_num == EAGAIN) {
- // returns EAGAIN if queue is full and non-blocking
- return EAGAIN;
- }
- LOG(ERROR) << "Could not send message: " << strerror(error_num);
- return error_num;
- }
- return 0;
-}
-
-// If msgtyp is 0, then the first message in the queue is read.
-// If msgtyp is greater than 0, then the first message in the queue of type
-// msgtyp is read.
-// If msgtyp is less than 0, then the first message in the queue with the lowest
-// type less than or equal to the absolute value of msgtyp will be read.
-ssize_t SysVMessageQueue::Receive(void* data, size_t size, long msgtyp,
- bool block) {
- // System call fails with errno set to ENOMSG if queue is empty and
- // non-blocking.
- int msgflg = block ? 0 : IPC_NOWAIT;
- return msgrcv(msgid, data, size, msgtyp, msgflg);
-}
-
-} // namespace cuttlefish
diff --git a/host/libs/msg_queue/msg_queue.h b/host/libs/msg_queue/msg_queue.h
deleted file mode 100644
index 0d43cd1a4..000000000
--- a/host/libs/msg_queue/msg_queue.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2020 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>
-
-namespace cuttlefish {
-class SysVMessageQueue {
- public:
- static std::unique_ptr<SysVMessageQueue> Create(const std::string& path,
- char proj_id);
- ~SysVMessageQueue();
-
- int Send(void* data, size_t size, bool block);
- ssize_t Receive(void* data, size_t size, long msgtyp, bool block);
-
- private:
- SysVMessageQueue(int msgid);
- int msgid;
-};
-} // namespace cuttlefish
diff --git a/host/libs/screen_connector/Android.bp b/host/libs/screen_connector/Android.bp
index d4e40023f..74bc9366e 100644
--- a/host/libs/screen_connector/Android.bp
+++ b/host/libs/screen_connector/Android.bp
@@ -13,33 +13,23 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-cc_library_static {
+cc_library_host_static {
name: "libcuttlefish_screen_connector",
srcs: [
+ "screen_connector.cpp",
+ "socket_based_screen_connector.cpp",
"wayland_screen_connector.cpp",
],
shared_libs: [
"libcuttlefish_fs",
"libbase",
- "libjsoncpp",
"liblog",
],
- header_libs: [
- "libcuttlefish_confui_host_headers",
- ],
static_libs: [
"libcuttlefish_host_config",
"libcuttlefish_utils",
- "libcuttlefish_confui",
"libcuttlefish_wayland_server",
- "libcuttlefish_confui_host",
- "libft2.nodep",
- "libteeui",
- "libteeui_localization",
+ "libjsoncpp",
],
- defaults: ["cuttlefish_host"],
+ defaults: ["cuttlefish_host_only"],
}
diff --git a/host/libs/screen_connector/screen_connector.cpp b/host/libs/screen_connector/screen_connector.cpp
new file mode 100644
index 000000000..132a89406
--- /dev/null
+++ b/host/libs/screen_connector/screen_connector.cpp
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+#include "host/libs/screen_connector/screen_connector.h"
+
+#include <android-base/logging.h>
+
+#include "host/libs/config/cuttlefish_config.h"
+#include "host/libs/screen_connector/socket_based_screen_connector.h"
+#include "host/libs/screen_connector/wayland_screen_connector.h"
+
+namespace cvd {
+
+ScreenConnector* ScreenConnector::Get(int frames_fd) {
+ auto config = vsoc::CuttlefishConfig::Get();
+ if (config->gpu_mode() == vsoc::kGpuModeDrmVirgl ||
+ config->gpu_mode() == vsoc::kGpuModeGfxStream) {
+ return new WaylandScreenConnector(frames_fd);
+ } else if (config->gpu_mode() == vsoc::kGpuModeGuestSwiftshader) {
+ return new SocketBasedScreenConnector(frames_fd);
+ } else {
+ LOG(ERROR) << "Invalid gpu mode: " << config->gpu_mode();
+ return nullptr;
+ }
+}
+
+} // namespace cvd
diff --git a/host/libs/screen_connector/screen_connector.h b/host/libs/screen_connector/screen_connector.h
index de55b0eb4..3a0e0e249 100644
--- a/host/libs/screen_connector/screen_connector.h
+++ b/host/libs/screen_connector/screen_connector.h
@@ -16,242 +16,50 @@
#pragma once
-#include <cassert>
-#include <chrono>
#include <cstdint>
#include <functional>
-#include <memory>
-#include <mutex>
-#include <optional>
-#include <string>
-#include <thread>
-#include <type_traits>
-#include <android-base/logging.h>
-#include "common/libs/concurrency/semaphore.h"
-#include "common/libs/confui/confui.h"
-#include "common/libs/fs/shared_fd.h"
#include "common/libs/utils/size_utils.h"
-
#include "host/libs/config/cuttlefish_config.h"
-#include "host/libs/confui/host_mode_ctrl.h"
-#include "host/libs/confui/host_utils.h"
-#include "host/libs/screen_connector/screen_connector_common.h"
-#include "host/libs/screen_connector/screen_connector_queue.h"
-#include "host/libs/screen_connector/wayland_screen_connector.h"
-
-namespace cuttlefish {
-template <typename ProcessedFrameType>
-class ScreenConnector : public ScreenConnectorInfo,
- public ScreenConnectorFrameRenderer {
- public:
- static_assert(cuttlefish::is_movable<ProcessedFrameType>::value,
- "ProcessedFrameType should be std::move-able.");
- static_assert(std::is_base_of<ScreenConnectorFrameInfo, ProcessedFrameType>::value,
- "ProcessedFrameType should inherit ScreenConnectorFrameInfo");
+namespace cvd {
- /**
- * This is the type of the callback function WebRTC/VNC is supposed to provide
- * ScreenConnector with.
- *
- * The callback function should be defined so that the two parameters are
- * given by the callback function caller (e.g. ScreenConnectorSource) and used
- * to fill out the ProcessedFrameType object, msg.
- *
- * The ProcessedFrameType object is internally created by ScreenConnector,
- * filled out by the ScreenConnectorSource, and returned via OnNextFrame()
- * call.
- */
- using GenerateProcessedFrameCallback = std::function<void(
- std::uint32_t /*display_number*/, std::uint8_t* /*frame_pixels*/,
- /* ScImpl enqueues this type into the Q */
- ProcessedFrameType& msg)>;
+using FrameCallback = std::function<void(std::uint32_t /*frame_number*/,
+ std::uint8_t* /*frame_pixels*/)>;
- static std::unique_ptr<ScreenConnector<ProcessedFrameType>> Get(
- const int frames_fd, HostModeCtrl& host_mode_ctrl) {
- auto config = cuttlefish::CuttlefishConfig::Get();
- ScreenConnector<ProcessedFrameType>* raw_ptr = nullptr;
- if (config->gpu_mode() == cuttlefish::kGpuModeDrmVirgl ||
- config->gpu_mode() == cuttlefish::kGpuModeGfxStream ||
- config->gpu_mode() == cuttlefish::kGpuModeGuestSwiftshader) {
- raw_ptr = new ScreenConnector<ProcessedFrameType>(
- std::make_unique<WaylandScreenConnector>(frames_fd), host_mode_ctrl);
- } else {
- LOG(FATAL) << "Invalid gpu mode: " << config->gpu_mode();
- }
- return std::unique_ptr<ScreenConnector<ProcessedFrameType>>(raw_ptr);
- }
+class ScreenConnector {
+ public:
+ static ScreenConnector* Get(int frames_fd);
virtual ~ScreenConnector() = default;
- /**
- * set the callback function to be eventually used by Wayland/Socket-Based Connectors
- *
- * @param[in] To tell how ScreenConnectorSource caches the frame & meta info
- */
- void SetCallback(GenerateProcessedFrameCallback&& frame_callback) {
- std::lock_guard<std::mutex> lock(streamer_callback_mutex_);
- callback_from_streamer_ = std::move(frame_callback);
- streamer_callback_set_cv_.notify_all();
- /*
- * the first WaitForAtLeastOneClientConnection() call from VNC requires the
- * Android-frame-processing thread starts beforehands (b/178504150)
- */
- if (!sc_android_frame_fetching_thread_.joinable()) {
- sc_android_frame_fetching_thread_ = cuttlefish::confui::thread::RunThread(
- "AndroidFetcher", &ScreenConnector::AndroidFrameFetchingLoop, this);
- }
- }
+ // Runs the given callback on the next available frame after the given
+ // frame number and returns true if successful.
+ virtual bool OnFrameAfter(std::uint32_t frame_number,
+ const FrameCallback& frame_callback) = 0;
- bool IsCallbackSet() const override {
- if (callback_from_streamer_) {
- return true;
- }
- return false;
+ static inline constexpr int BytesPerPixel() {
+ return sizeof(int32_t);
}
- /* returns the processed frame that also includes meta-info such as success/fail
- * and display number from the guest
- *
- * NOTE THAT THIS IS THE ONLY CONSUMER OF THE TWO QUEUES
- */
- ProcessedFrameType OnNextFrame() {
- on_next_frame_cnt_++;
- while (true) {
- ConfUiLog(VERBOSE) << "Streamer waiting Semaphore with host ctrl mode ="
- << static_cast<std::uint32_t>(
- host_mode_ctrl_.GetMode())
- << " and cnd = #" << on_next_frame_cnt_;
- sc_sem_.SemWait();
- ConfUiLog(VERBOSE)
- << "Streamer got Semaphore'ed resources with host ctrl mode ="
- << static_cast<std::uint32_t>(host_mode_ctrl_.GetMode())
- << "and cnd = #" << on_next_frame_cnt_;
- // do something
- if (!sc_android_queue_.Empty()) {
- auto mode = host_mode_ctrl_.GetMode();
- if (mode == HostModeCtrl::ModeType::kAndroidMode) {
- ConfUiLog(VERBOSE)
- << "Streamer gets Android frame with host ctrl mode ="
- << static_cast<std::uint32_t>(mode) << "and cnd = #"
- << on_next_frame_cnt_;
- return sc_android_queue_.PopFront();
- }
- // AndroidFrameFetchingLoop could have added 1 or 2 frames
- // before it becomes Conf UI mode.
- ConfUiLog(VERBOSE)
- << "Streamer ignores Android frame with host ctrl mode ="
- << static_cast<std::uint32_t>(mode) << "and cnd = #"
- << on_next_frame_cnt_;
- sc_android_queue_.PopFront();
- continue;
- }
- ConfUiLog(VERBOSE) << "Streamer gets Conf UI frame with host ctrl mode = "
- << static_cast<std::uint32_t>(
- host_mode_ctrl_.GetMode())
- << " and cnd = #" << on_next_frame_cnt_;
- return sc_confui_queue_.PopFront();
- }
+ static inline int ScreenHeight() {
+ return vsoc::CuttlefishConfig::Get()->y_res();
}
- [[noreturn]] void AndroidFrameFetchingLoop() {
- unsigned long long int loop_cnt = 0;
- cuttlefish::confui::thread::Set("AndroidFrameFetcher",
- std::this_thread::get_id());
- while (true) {
- loop_cnt++;
- ProcessedFrameType processed_frame;
- decltype(callback_from_streamer_) cp_of_streamer_callback;
- {
- std::lock_guard<std::mutex> lock(streamer_callback_mutex_);
- cp_of_streamer_callback = callback_from_streamer_;
- }
- GenerateProcessedFrameCallbackImpl callback_for_sc_impl =
- std::bind(cp_of_streamer_callback, std::placeholders::_1,
- std::placeholders::_2, std::ref(processed_frame));
- ConfUiLog(VERBOSE) << cuttlefish::confui::thread::GetName(
- std::this_thread::get_id())
- << " calling Android OnNextFrame. "
- << " at loop #" << loop_cnt;
- bool flag = sc_android_src_->OnNextFrame(callback_for_sc_impl);
- processed_frame.is_success_ = flag && processed_frame.is_success_;
- const bool is_confui_mode = host_mode_ctrl_.IsConfirmatioUiMode();
- if (!is_confui_mode) {
- ConfUiLog(VERBOSE) << cuttlefish::confui::thread::GetName(
- std::this_thread::get_id())
- << "is sending an Android Frame at loop_cnt #"
- << loop_cnt;
- sc_android_queue_.PushBack(std::move(processed_frame));
- continue;
- }
- ConfUiLog(VERBOSE) << cuttlefish::confui::thread::GetName(
- std::this_thread::get_id())
- << "is skipping an Android Frame at loop_cnt #"
- << loop_cnt;
- }
+ static inline int ScreenWidth() {
+ return vsoc::CuttlefishConfig::Get()->x_res();
}
- /**
- * ConfUi calls this when it has frames to render
- *
- * This won't be called if not by Confirmation UI. This won't affect rendering
- * Android guest frames if Confirmation UI HAL is not active.
- *
- */
- bool RenderConfirmationUi(const std::uint32_t display,
- std::uint8_t* raw_frame) override {
- render_confui_cnt_++;
- // wait callback is not set, the streamer is not ready
- // return with LOG(ERROR)
- if (!IsCallbackSet()) {
- ConfUiLog(ERROR) << "callback function to process frames is not yet set";
- return false;
- }
- ProcessedFrameType processed_frame;
- auto this_thread_name = cuttlefish::confui::thread::GetName();
- ConfUiLog(DEBUG) << this_thread_name
- << "is sending a #" + std::to_string(render_confui_cnt_)
- << "Conf UI frame";
- callback_from_streamer_(display, raw_frame, processed_frame);
- // now add processed_frame to the queue
- sc_confui_queue_.PushBack(std::move(processed_frame));
- return true;
+ static inline int ScreenStride() {
+ return AlignToPowerOf2(ScreenWidth() * BytesPerPixel(), 4);
}
- // Let the screen connector know when there are clients connected
- void ReportClientsConnected(bool have_clients) {
- // screen connector implementation must implement ReportClientsConnected
- sc_android_src_->ReportClientsConnected(have_clients);
- return ;
+ static inline int ScreenSizeInBytes() {
+ return ScreenStride() * ScreenHeight();
}
protected:
- template <typename T,
- typename = std::enable_if_t<
- std::is_base_of<ScreenConnectorSource, T>::value, void>>
- ScreenConnector(std::unique_ptr<T>&& impl, HostModeCtrl& host_mode_ctrl)
- : sc_android_src_{std::move(impl)},
- host_mode_ctrl_{host_mode_ctrl},
- on_next_frame_cnt_{0},
- render_confui_cnt_{0},
- sc_android_queue_{sc_sem_},
- sc_confui_queue_{sc_sem_} {}
- ScreenConnector() = delete;
-
- private:
- // either socket_based or wayland
- std::unique_ptr<ScreenConnectorSource> sc_android_src_;
- HostModeCtrl& host_mode_ctrl_;
- unsigned long long int on_next_frame_cnt_;
- unsigned long long int render_confui_cnt_;
- Semaphore sc_sem_;
- ScreenConnectorQueue<ProcessedFrameType> sc_android_queue_;
- ScreenConnectorQueue<ProcessedFrameType> sc_confui_queue_;
- GenerateProcessedFrameCallback callback_from_streamer_;
- std::thread sc_android_frame_fetching_thread_;
- std::mutex streamer_callback_mutex_; // mutex to set & read callback_from_streamer_
- std::condition_variable streamer_callback_set_cv_;
+ ScreenConnector() = default;
};
-} // namespace cuttlefish
+} // namespace cvd \ No newline at end of file
diff --git a/host/libs/screen_connector/screen_connector_common.h b/host/libs/screen_connector/screen_connector_common.h
deleted file mode 100644
index 48c7c76d1..000000000
--- a/host/libs/screen_connector/screen_connector_common.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (C) 2020 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 <cstdint>
-#include <functional>
-#include <type_traits>
-
-#include <android-base/logging.h>
-#include "common/libs/utils/size_utils.h"
-#include "host/libs/config/cuttlefish_config.h"
-
-namespace cuttlefish {
-
-template<typename T>
-struct is_movable {
- static constexpr const bool value =
- std::is_move_constructible<T>::value &&
- std::is_move_assignable<T>::value;
-};
-
-// this callback type is going directly to socket-based or wayland ScreenConnector
-using GenerateProcessedFrameCallbackImpl = std::function<void(std::uint32_t /*display_number*/,
- std::uint8_t* /*frame_pixels*/)>;
-
-class ScreenConnectorSource {
- public:
- virtual ~ScreenConnectorSource() = default;
- // Runs the given callback on the next available frame after the given
- // frame number and returns true if successful.
- virtual bool OnNextFrame(
- const GenerateProcessedFrameCallbackImpl& frame_callback) = 0;
- virtual void ReportClientsConnected(bool /*have_clients*/) { /* ignore by default */ }
- ScreenConnectorSource() = default;
-};
-
-struct ScreenConnectorInfo {
- // functions are intended to be inlined
- static constexpr std::uint32_t BytesPerPixel() { return 4; }
- static std::uint32_t ScreenCount() {
- auto config = ChkAndGetConfig();
- auto display_configs = config->display_configs();
- return static_cast<std::uint32_t>(display_configs.size());
- }
- static std::uint32_t ScreenHeight(std::uint32_t display_number) {
- auto config = ChkAndGetConfig();
- auto display_configs = config->display_configs();
- CHECK_GT(display_configs.size(), display_number);
- return display_configs[display_number].height;
- }
- static std::uint32_t ScreenWidth(std::uint32_t display_number) {
- auto config = ChkAndGetConfig();
- auto display_configs = config->display_configs();
- CHECK_GE(display_configs.size(), display_number);
- return display_configs[display_number].width;
- }
- static std::uint32_t ScreenStrideBytes(std::uint32_t display_number) {
- return AlignToPowerOf2(ScreenWidth(display_number) * BytesPerPixel(), 4);
- }
- static std::uint32_t ScreenSizeInBytes(std::uint32_t display_number) {
- return ScreenStrideBytes(display_number) * ScreenHeight(display_number);
- }
- private:
- static auto ChkAndGetConfig() -> decltype(cuttlefish::CuttlefishConfig::Get()) {
- auto config = cuttlefish::CuttlefishConfig::Get();
- CHECK(config) << "Config is Missing";
- return config;
- }
-};
-
-struct ScreenConnectorFrameRenderer {
- virtual bool RenderConfirmationUi(const std::uint32_t display,
- std::uint8_t* raw_frame) = 0;
- virtual bool IsCallbackSet() const = 0;
- virtual ~ScreenConnectorFrameRenderer() = default;
-};
-
-// this is inherited by the data type that represents the processed frame
-// being moved around.
-struct ScreenConnectorFrameInfo {
- std::uint32_t display_number_;
- bool is_success_;
-};
-
-} // namespace cuttlefish
diff --git a/host/libs/screen_connector/screen_connector_ctrl.h b/host/libs/screen_connector/screen_connector_ctrl.h
deleted file mode 100644
index 9b9015277..000000000
--- a/host/libs/screen_connector/screen_connector_ctrl.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (C) 2020 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 <atomic>
-#include <condition_variable>
-#include <functional>
-#include <memory>
-#include <mutex>
-#include <thread>
-
-#include "common/libs/concurrency/semaphore.h"
-
-namespace cuttlefish {
-/**
- * mechanism to orchestrate concurrent executions of threads
- * that work for screen connector
- *
- * One thing is when any of wayland/socket-based connector or
- * confirmation UI has a frame, it should wake up the consumer
- * The two queues are separate, so the conditional variables,
- * etc, can't be in the queue
- */
-class ScreenConnectorCtrl {
- public:
- enum class ModeType {
- kAndroidMode,
- kConfUI_Mode
- };
-
- ScreenConnectorCtrl() : atomic_mode_(ModeType::kAndroidMode) {}
-
- /**
- * The thread that enqueues Android frames will call this to wait until
- * the mode is kAndroidMode
- *
- * Logically, using atomic_mode_ alone is not sufficient. Using mutex alone
- * is logically complete but slow.
- *
- * Note that most of the time, the mode is kAndroidMode. Also, note that
- * this method is called at every single frame.
- *
- * As an optimization, we check atomic_mode_ first. If failed, we wait for
- * kAndroidMode with mutex-based lock
- *
- * The actual synchronization is not at the and_mode_cv_.wait line but at
- * this line:
- * if (atomic_mode_ == ModeType::kAndroidMode) {
- *
- * This trick reduces the flag checking delays by 70+% on a Gentoo based
- * amd64 desktop, with Linux 5.10
- */
- void WaitAndroidMode() {
- if (atomic_mode_ == ModeType::kAndroidMode) {
- return ;
- }
- auto check = [this]() -> bool { return atomic_mode_ == ModeType::kAndroidMode; };
- std::unique_lock<std::mutex> lock(mode_mtx_);
- and_mode_cv_.wait(lock, check);
- }
-
- void SetMode(const ModeType mode) {
- std::lock_guard<std::mutex> lock(mode_mtx_);
- atomic_mode_ = mode;
- if (atomic_mode_ == ModeType::kAndroidMode) {
- and_mode_cv_.notify_all();
- }
- }
-
- auto GetMode() {
- std::lock_guard<std::mutex> lock(mode_mtx_);
- ModeType ret_val = atomic_mode_;
- return ret_val;
- }
-
- void SemWait() { sem_.SemWait(); }
-
- // Only called by the producers
- void SemPost() { sem_.SemPost(); }
-
- private:
- std::mutex mode_mtx_;
- std::condition_variable and_mode_cv_;
- std::atomic<ModeType> atomic_mode_;
-
- // track the total number of items in all queues
- Semaphore sem_;
-};
-
-} // namespace cuttlefish
diff --git a/host/libs/screen_connector/screen_connector_queue.h b/host/libs/screen_connector/screen_connector_queue.h
deleted file mode 100644
index 20191681c..000000000
--- a/host/libs/screen_connector/screen_connector_queue.h
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright (C) 2020 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 <deque>
-#include <memory>
-#include <thread>
-#include <mutex>
-#include <condition_variable>
-#include <chrono>
-
-#include "common/libs/concurrency/semaphore.h"
-
-namespace cuttlefish {
-// move-based concurrent queue
-template<typename T>
-class ScreenConnectorQueue {
-
- public:
- static const int kQSize = 2;
-
- static_assert( is_movable<T>::value,
- "Items in ScreenConnectorQueue should be std::mov-able");
-
- ScreenConnectorQueue(Semaphore& sc_sem)
- : q_mutex_(std::make_unique<std::mutex>()), sc_semaphore_(sc_sem) {}
- ScreenConnectorQueue(ScreenConnectorQueue&& cq) = delete;
- ScreenConnectorQueue(const ScreenConnectorQueue& cq) = delete;
- ScreenConnectorQueue& operator=(const ScreenConnectorQueue& cq) = delete;
- ScreenConnectorQueue& operator=(ScreenConnectorQueue&& cq) = delete;
-
- bool Empty() const {
- const std::lock_guard<std::mutex> lock(*q_mutex_);
- return buffer_.empty();
- }
-
- auto Size() const {
- const std::lock_guard<std::mutex> lock(*q_mutex_);
- return buffer_.size();
- }
-
- void WaitEmpty() {
- auto is_empty = [this](void) { return buffer_.empty(); };
- std::unique_lock<std::mutex> lock(*q_mutex_);
- q_empty_.wait(lock, is_empty);
- }
-
- /*
- * PushBack( std::move(src) );
- *
- * Note: this queue is suppoed to be used only by ScreenConnector-
- * related components such as ScreenConnectorSource
- *
- * The traditional assumption was that when webRTC or VNC calls
- * OnFrameAfter, the call should be block until it could return
- * one frame.
- *
- * Thus, the producers of this queue must not produce frames
- * much faster than the consumer, VNC or WebRTC consumes.
- * Therefore, when the small buffer is full -- which means
- * VNC or WebRTC would not call OnFrameAfter --, the producer
- * should stop adding itmes to the queue.
- *
- */
- void PushBack(T&& item) {
- std::unique_lock<std::mutex> lock(*q_mutex_);
- if (Full()) {
- auto is_empty =
- [this](void){ return buffer_.empty(); };
- q_empty_.wait(lock, is_empty);
- }
- buffer_.push_back(std::move(item));
- /* Whether the total number of items in ALL queus is 0 or not
- * is tracked via a semaphore shared by all queues
- *
- * This is NOT intended to block queue from pushing an item
- * This IS intended to awake the screen_connector consumer thread
- * when one or more items are available at least in one queue
- */
- sc_semaphore_.SemPost();
- }
- void PushBack(T& item) = delete;
- void PushBack(const T& item) = delete;
-
- /*
- * PopFront must be preceded by sc_semaphore_.SemWaitItem()
- *
- */
- T PopFront() {
- const std::lock_guard<std::mutex> lock(*q_mutex_);
- auto item = std::move(buffer_.front());
- buffer_.pop_front();
- if (buffer_.empty()) {
- q_empty_.notify_all();
- }
- return item;
- }
-
- private:
- bool Full() const {
- // call this in a critical section
- // after acquiring q_mutex_
- return kQSize == buffer_.size();
- }
- std::deque<T> buffer_;
- std::unique_ptr<std::mutex> q_mutex_;
- std::condition_variable q_empty_;
- Semaphore& sc_semaphore_;
-};
-
-} // namespace cuttlefish
diff --git a/host/libs/screen_connector/socket_based_screen_connector.cpp b/host/libs/screen_connector/socket_based_screen_connector.cpp
new file mode 100644
index 000000000..4630ebba0
--- /dev/null
+++ b/host/libs/screen_connector/socket_based_screen_connector.cpp
@@ -0,0 +1,105 @@
+/*
+ * 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.
+ */
+
+#include "host/libs/screen_connector/socket_based_screen_connector.h"
+
+#include <android-base/logging.h>
+
+#include "common/libs/fs/shared_fd.h"
+
+namespace cvd {
+
+SocketBasedScreenConnector::SocketBasedScreenConnector(int frames_fd) {
+screen_server_thread_ =
+ std::thread([this, frames_fd]() { ServerLoop(frames_fd); });
+}
+
+bool SocketBasedScreenConnector::OnFrameAfter(
+ std::uint32_t frame_number, const FrameCallback& frame_callback) {
+ int buffer_idx = WaitForNewFrameSince(&frame_number);
+ void* buffer = GetBuffer(buffer_idx);
+ frame_callback(frame_number, reinterpret_cast<uint8_t*>(buffer));
+ return true;
+}
+
+int SocketBasedScreenConnector::WaitForNewFrameSince(std::uint32_t* seq_num) {
+ std::unique_lock<std::mutex> lock(new_frame_mtx_);
+ while (seq_num_ == *seq_num) {
+ new_frame_cond_var_.wait(lock);
+ }
+ *seq_num = seq_num_;
+ return newest_buffer_;
+}
+
+void* SocketBasedScreenConnector::GetBuffer(int buffer_idx) {
+ if (buffer_idx < 0) return nullptr;
+ buffer_idx %= NUM_BUFFERS_;
+ return &buffer_[buffer_idx * ScreenSizeInBytes()];
+}
+
+void SocketBasedScreenConnector::ServerLoop(int frames_fd) {
+ if (frames_fd < 0) {
+ LOG(FATAL) << "Invalid file descriptor: " << frames_fd;
+ return;
+ }
+ auto server = SharedFD::Dup(frames_fd);
+ close(frames_fd);
+ if (!server->IsOpen()) {
+ LOG(FATAL) << "Unable to dup screen server: " << server->StrError();
+ return;
+ }
+
+ int current_buffer = 0;
+
+ while (1) {
+ LOG(INFO) << "Screen Connector accepting connections...";
+ auto conn = SharedFD::Accept(*server);
+ if (!conn->IsOpen()) {
+ LOG(ERROR) << "Disconnected fd returned from accept";
+ continue;
+ }
+ while (conn->IsOpen()) {
+ int32_t size = 0;
+ if (conn->Read(&size, sizeof(size)) < 0) {
+ LOG(ERROR) << "Failed to read from hwcomposer: " << conn->StrError();
+ break;
+ }
+ auto buff = reinterpret_cast<uint8_t*>(GetBuffer(current_buffer));
+ while (size > 0) {
+ auto read = conn->Read(buff, size);
+ if (read < 0) {
+ LOG(ERROR) << "Failed to read from hwcomposer: " << conn->StrError();
+ conn->Close();
+ break;
+ }
+ size -= read;
+ buff += read;
+ }
+ BroadcastNewFrame(current_buffer);
+ current_buffer = (current_buffer + 1) % NUM_BUFFERS_;
+ }
+ }
+}
+
+void SocketBasedScreenConnector::BroadcastNewFrame(int buffer_idx) {
+ {
+ std::lock_guard<std::mutex> lock(new_frame_mtx_);
+ seq_num_++;
+ newest_buffer_ = buffer_idx;
+ }
+ new_frame_cond_var_.notify_all();
+}
+} // namespace cvd
diff --git a/host/libs/screen_connector/socket_based_screen_connector.h b/host/libs/screen_connector/socket_based_screen_connector.h
new file mode 100644
index 000000000..0ed8414f4
--- /dev/null
+++ b/host/libs/screen_connector/socket_based_screen_connector.h
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include "host/libs/screen_connector/screen_connector.h"
+
+#include <atomic>
+#include <cinttypes>
+#include <condition_variable>
+#include <mutex>
+#include <thread>
+#include <vector>
+
+namespace cvd {
+
+class SocketBasedScreenConnector : public ScreenConnector {
+ public:
+ explicit SocketBasedScreenConnector(int frames_fd);
+
+ bool OnFrameAfter(std::uint32_t frame_number,
+ const FrameCallback& frame_callback) override;
+
+ private:
+ static constexpr int NUM_BUFFERS_ = 4;
+
+ int WaitForNewFrameSince(std::uint32_t* seq_num);
+ void* GetBuffer(int buffer_idx);
+ void ServerLoop(int frames_fd);
+ void BroadcastNewFrame(int buffer_idx);
+
+ std::vector<std::uint8_t> buffer_ =
+ std::vector<std::uint8_t>(NUM_BUFFERS_ * ScreenSizeInBytes());
+ std::uint32_t seq_num_{0};
+ int newest_buffer_ = 0;
+ std::condition_variable new_frame_cond_var_;
+ std::mutex new_frame_mtx_;
+ std::thread screen_server_thread_;
+};
+
+} // namespace cvd \ No newline at end of file
diff --git a/host/libs/screen_connector/wayland_screen_connector.cpp b/host/libs/screen_connector/wayland_screen_connector.cpp
index 7eb6642f2..4725e85e9 100644
--- a/host/libs/screen_connector/wayland_screen_connector.cpp
+++ b/host/libs/screen_connector/wayland_screen_connector.cpp
@@ -19,11 +19,13 @@
#include <unistd.h>
#include <fcntl.h>
+#include <future>
+
#include <android-base/logging.h>
#include "host/libs/wayland/wayland_server.h"
-namespace cuttlefish {
+namespace cvd {
WaylandScreenConnector::WaylandScreenConnector(int frames_fd) {
int wayland_fd = fcntl(frames_fd, F_DUPFD_CLOEXEC, 3);
@@ -33,10 +35,14 @@ WaylandScreenConnector::WaylandScreenConnector(int frames_fd) {
server_.reset(new wayland::WaylandServer(wayland_fd));
}
-bool WaylandScreenConnector::OnNextFrame(
- const GenerateProcessedFrameCallbackImpl& frame_callback) {
- server_->OnNextFrame(frame_callback);
+bool WaylandScreenConnector::OnFrameAfter(
+ std::uint32_t frame_number, const FrameCallback& frame_callback) {
+ std::future<void> frame_callback_completed_future =
+ server_->OnFrameAfter(frame_number, frame_callback);
+
+ frame_callback_completed_future.get();
+
return true;
}
-} // namespace cuttlefish
+} // namespace cvd \ No newline at end of file
diff --git a/host/libs/screen_connector/wayland_screen_connector.h b/host/libs/screen_connector/wayland_screen_connector.h
index 00e7ca04e..537bb3146 100644
--- a/host/libs/screen_connector/wayland_screen_connector.h
+++ b/host/libs/screen_connector/wayland_screen_connector.h
@@ -16,23 +16,23 @@
#pragma once
-#include "host/libs/screen_connector/screen_connector_common.h"
+#include "host/libs/screen_connector/screen_connector.h"
#include <memory>
#include "host/libs/wayland/wayland_server.h"
-namespace cuttlefish {
+namespace cvd {
-class WaylandScreenConnector : public ScreenConnectorSource {
+class WaylandScreenConnector : public ScreenConnector {
public:
WaylandScreenConnector(int frames_fd);
- bool OnNextFrame(
- const GenerateProcessedFrameCallbackImpl& frame_callback) override;
+ bool OnFrameAfter(std::uint32_t frame_number,
+ const FrameCallback& frame_callback) override;
private:
std::unique_ptr<wayland::WaylandServer> server_;
};
-}
+} \ No newline at end of file
diff --git a/host/libs/vm_manager/Android.bp b/host/libs/vm_manager/Android.bp
index 20c9027df..71ca11cd4 100644
--- a/host/libs/vm_manager/Android.bp
+++ b/host/libs/vm_manager/Android.bp
@@ -13,29 +13,23 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-cc_library_static {
+cc_library_host_static {
name: "libcuttlefish_vm_manager",
srcs: [
"crosvm_manager.cpp",
- "host_configuration.cpp",
"qemu_manager.cpp",
"vm_manager.cpp",
],
- header_libs: [
- "vulkan_headers",
- ],
shared_libs: [
"libcuttlefish_fs",
"libcuttlefish_utils",
"libbase",
- "libjsoncpp",
+ "libicuuc",
],
static_libs: [
+ "libxml2",
"libcuttlefish_host_config",
+ "libjsoncpp",
],
- defaults: ["cuttlefish_host", "cuttlefish_libicuuc"],
+ defaults: ["cuttlefish_host_only"],
}
diff --git a/host/libs/vm_manager/crosvm_manager.cpp b/host/libs/vm_manager/crosvm_manager.cpp
index 82aba2d90..ad78cbf4c 100644
--- a/host/libs/vm_manager/crosvm_manager.cpp
+++ b/host/libs/vm_manager/crosvm_manager.cpp
@@ -19,69 +19,42 @@
#include <sys/stat.h>
#include <sys/types.h>
-#include <cassert>
#include <string>
#include <vector>
#include <android-base/strings.h>
#include <android-base/logging.h>
-#include <vulkan/vulkan.h>
#include "common/libs/utils/environment.h"
#include "common/libs/utils/network.h"
#include "common/libs/utils/subprocess.h"
-#include "common/libs/utils/files.h"
#include "host/libs/config/cuttlefish_config.h"
-#include "host/libs/config/known_paths.h"
#include "host/libs/vm_manager/qemu_manager.h"
-namespace cuttlefish {
namespace vm_manager {
namespace {
-std::string GetControlSocketPath(const CuttlefishConfig& config) {
- return config.ForDefaultInstance()
+std::string GetControlSocketPath(const vsoc::CuttlefishConfig* config) {
+ return config->ForDefaultInstance()
.PerInstanceInternalPath("crosvm_control.sock");
}
-SharedFD AddTapFdParameter(Command* crosvm_cmd,
- const std::string& tap_name) {
- auto tap_fd = OpenTapInterface(tap_name);
+void AddTapFdParameter(cvd::Command* crosvm_cmd, const std::string& tap_name) {
+ auto tap_fd = cvd::OpenTapInterface(tap_name);
if (tap_fd->IsOpen()) {
crosvm_cmd->AddParameter("--tap-fd=", tap_fd);
} else {
LOG(ERROR) << "Unable to connect to " << tap_name << ": "
<< tap_fd->StrError();
}
- return tap_fd;
-}
-
-bool ReleaseDhcpLeases(const std::string& lease_path, SharedFD tap_fd) {
- auto lease_file_fd = SharedFD::Open(lease_path, O_RDONLY);
- if (!lease_file_fd->IsOpen()) {
- LOG(ERROR) << "Could not open leases file \"" << lease_path << '"';
- return false;
- }
- bool success = true;
- auto dhcp_leases = ParseDnsmasqLeases(lease_file_fd);
- for (auto& lease : dhcp_leases) {
- std::uint8_t dhcp_server_ip[] = {192, 168, 96, (std::uint8_t) (ForCurrentInstance(1) * 4 - 3)};
- if (!ReleaseDhcp4(tap_fd, lease.mac_address, lease.ip_address, dhcp_server_ip)) {
- LOG(ERROR) << "Failed to release " << lease;
- success = false;
- } else {
- LOG(INFO) << "Successfully dropped " << lease;
- }
- }
- return success;
}
bool Stop() {
- auto config = CuttlefishConfig::Get();
- Command command(config->crosvm_binary());
+ auto config = vsoc::CuttlefishConfig::Get();
+ cvd::Command command(config->crosvm_binary());
command.AddParameter("stop");
- command.AddParameter(GetControlSocketPath(*config));
+ command.AddParameter(GetControlSocketPath(config));
auto process = command.Start();
@@ -90,67 +63,65 @@ bool Stop() {
} // namespace
-bool CrosvmManager::IsSupported() {
-#ifdef __ANDROID__
- return true;
-#else
- return HostSupportsQemuCli();
-#endif
-}
+const std::string CrosvmManager::name() { return "crosvm"; }
-std::vector<std::string> CrosvmManager::ConfigureGpuMode(
- const std::string& gpu_mode) {
+std::vector<std::string> CrosvmManager::ConfigureGpu(const std::string& gpu_mode) {
// Override the default HAL search paths in all cases. We do this because
// the HAL search path allows for fallbacks, and fallbacks in conjunction
// with properities lead to non-deterministic behavior while loading the
// HALs.
- if (gpu_mode == kGpuModeGuestSwiftshader) {
+ if (gpu_mode == vsoc::kGpuModeGuestSwiftshader) {
return {
- "androidboot.cpuvulkan.version=" + std::to_string(VK_API_VERSION_1_2),
"androidboot.hardware.gralloc=minigbm",
- "androidboot.hardware.hwcomposer=ranchu",
- "androidboot.hardware.egl=angle",
+ "androidboot.hardware.hwcomposer=cutf_hwc2",
+ "androidboot.hardware.egl=swiftshader",
"androidboot.hardware.vulkan=pastel",
};
}
- if (gpu_mode == kGpuModeDrmVirgl) {
+ // Try to load the Nvidia modeset kernel module. Running Crosvm with Nvidia's EGL library on a
+ // fresh machine after a boot will fail because the Nvidia EGL library will fork to run the
+ // nvidia-modprobe command and the main Crosvm process will abort after receiving the exit signal
+ // of the forked child which is interpreted as a failure.
+ cvd::Command modprobe_cmd("/usr/bin/nvidia-modprobe");
+ modprobe_cmd.AddParameter("--modeset");
+ modprobe_cmd.Start().Wait();
+
+ if (gpu_mode == vsoc::kGpuModeDrmVirgl) {
return {
- "androidboot.cpuvulkan.version=0",
"androidboot.hardware.gralloc=minigbm",
"androidboot.hardware.hwcomposer=drm_minigbm",
"androidboot.hardware.egl=mesa",
};
}
- if (gpu_mode == kGpuModeGfxStream) {
+ if (gpu_mode == vsoc::kGpuModeGfxStream) {
return {
- "androidboot.cpuvulkan.version=0",
"androidboot.hardware.gralloc=minigbm",
- "androidboot.hardware.hwcomposer=ranchu",
+ "androidboot.hardware.hwcomposer=drm_minigbm",
"androidboot.hardware.egl=emulation",
"androidboot.hardware.vulkan=ranchu",
- "androidboot.hardware.gltransport=virtio-gpu-asg",
+ "androidboot.hardware.gltransport=virtio-gpu-pipe",
};
}
return {};
}
-std::string CrosvmManager::ConfigureBootDevices(int num_disks) {
+std::vector<std::string> CrosvmManager::ConfigureBootDevices() {
+ // PCI domain 0, bus 0, device 1, function 0
// TODO There is no way to control this assignment with crosvm (yet)
- if (HostArch() == Arch::X86_64) {
- // crosvm has an additional PCI device for an ISA bridge
- return ConfigureMultipleBootDevices("pci0000:00/0000:00:", 1, num_disks);
+ if (cvd::HostArch() == "x86_64") {
+ return { "androidboot.boot_devices=pci0000:00/0000:00:01.0" };
} else {
- // On ARM64 crosvm, block devices are on their own bridge, so we don't
- // need to calculate it, and the path is always the same
- return "androidboot.boot_devices=10000.pci";
+ return { "androidboot.boot_devices=10000.pci" };
}
}
-std::vector<Command> CrosvmManager::StartCommands(
- const CuttlefishConfig& config) {
- auto instance = config.ForDefaultInstance();
- Command crosvm_cmd(config.crosvm_binary(), [](Subprocess* proc) {
+CrosvmManager::CrosvmManager(const vsoc::CuttlefishConfig* config)
+ : VmManager(config) {}
+
+std::vector<cvd::Command> CrosvmManager::StartCommands() {
+ auto instance = config_->ForDefaultInstance();
+ cvd::Command crosvm_cmd(config_->crosvm_binary(), [](cvd::Subprocess* proc) {
auto stopped = Stop();
if (stopped) {
return true;
@@ -158,264 +129,117 @@ std::vector<Command> CrosvmManager::StartCommands(
LOG(WARNING) << "Failed to stop VMM nicely, attempting to KILL";
return KillSubprocess(proc);
});
-
- int hvc_num = 0;
- int serial_num = 0;
- auto add_hvc_sink = [&crosvm_cmd, &hvc_num]() {
- crosvm_cmd.AddParameter("--serial=hardware=virtio-console,num=", ++hvc_num,
- ",type=sink");
- };
- auto add_serial_sink = [&crosvm_cmd, &serial_num]() {
- crosvm_cmd.AddParameter("--serial=hardware=serial,num=", ++serial_num,
- ",type=sink");
- };
- auto add_hvc_console = [&crosvm_cmd, &hvc_num](const std::string& output) {
- crosvm_cmd.AddParameter("--serial=hardware=virtio-console,num=", ++hvc_num,
- ",type=file,path=", output, ",console=true");
- };
- auto add_serial_console_ro = [&crosvm_cmd,
- &serial_num](const std::string& output) {
- crosvm_cmd.AddParameter("--serial=hardware=serial,num=", ++serial_num,
- ",type=file,path=", output, ",earlycon=true");
- };
- auto add_serial_console = [&crosvm_cmd, &serial_num](
- const std::string& output,
- const std::string& input) {
- crosvm_cmd.AddParameter("--serial=hardware=serial,num=", ++serial_num,
- ",type=file,path=", output, ",input=", input,
- ",earlycon=true");
- };
- auto add_hvc_ro = [&crosvm_cmd, &hvc_num](const std::string& output) {
- crosvm_cmd.AddParameter("--serial=hardware=virtio-console,num=", ++hvc_num,
- ",type=file,path=", output);
- };
- auto add_hvc = [&crosvm_cmd, &hvc_num](const std::string& output,
- const std::string& input) {
- crosvm_cmd.AddParameter("--serial=hardware=virtio-console,num=", ++hvc_num,
- ",type=file,path=", output, ",input=", input);
- };
- // Deprecated; do not add any more users
- auto add_serial = [&crosvm_cmd, &serial_num](const std::string& output,
- const std::string& input) {
- crosvm_cmd.AddParameter("--serial=hardware=serial,num=", ++serial_num,
- ",type=file,path=", output, ",input=", input);
- };
-
crosvm_cmd.AddParameter("run");
- if (!config.smt()) {
- crosvm_cmd.AddParameter("--no-smt");
- }
-
- if (config.vhost_net()) {
- crosvm_cmd.AddParameter("--vhost-net");
- }
-
- if (config.protected_vm()) {
- crosvm_cmd.AddParameter("--protected-vm");
- }
-
- if (config.gdb_port() > 0) {
- CHECK(config.cpus() == 1) << "CPUs must be 1 for crosvm gdb mode";
- crosvm_cmd.AddParameter("--gdb=", config.gdb_port());
- }
+ auto gpu_mode = config_->gpu_mode();
- auto display_configs = config.display_configs();
- CHECK_GE(display_configs.size(), 1);
- auto display_config = display_configs[0];
-
- auto gpu_mode = config.gpu_mode();
-
- if (gpu_mode == kGpuModeGuestSwiftshader) {
+ if (gpu_mode == vsoc::kGpuModeGuestSwiftshader) {
crosvm_cmd.AddParameter("--gpu=2D,",
- "width=", display_config.width, ",",
- "height=", display_config.height);
- } else if (gpu_mode == kGpuModeDrmVirgl || gpu_mode == kGpuModeGfxStream) {
- crosvm_cmd.AddParameter(gpu_mode == kGpuModeGfxStream ?
+ "width=", config_->x_res(), ",",
+ "height=", config_->y_res());
+ } else if (gpu_mode == vsoc::kGpuModeDrmVirgl ||
+ gpu_mode == vsoc::kGpuModeGfxStream) {
+ crosvm_cmd.AddParameter(gpu_mode == vsoc::kGpuModeGfxStream ?
"--gpu=gfxstream," : "--gpu=",
- "width=", display_config.width, ",",
- "height=", display_config.height, ",",
+ "width=", config_->x_res(), ",",
+ "height=", config_->y_res(), ",",
"egl=true,surfaceless=true,glx=false,gles=true");
+ crosvm_cmd.AddParameter("--wayland-sock=", instance.frames_socket_path());
}
- crosvm_cmd.AddParameter("--wayland-sock=", instance.frames_socket_path());
-
- // crosvm_cmd.AddParameter("--null-audio");
- crosvm_cmd.AddParameter("--mem=", config.memory_mb());
- crosvm_cmd.AddParameter("--cpus=", config.cpus());
-
- auto disk_num = instance.virtual_disk_paths().size();
- CHECK_GE(VmManager::kMaxDisks, disk_num)
- << "Provided too many disks (" << disk_num << "), maximum "
- << VmManager::kMaxDisks << "supported";
+ if (!config_->final_ramdisk_path().empty()) {
+ crosvm_cmd.AddParameter("--initrd=", config_->final_ramdisk_path());
+ }
+ crosvm_cmd.AddParameter("--mem=", config_->memory_mb());
+ crosvm_cmd.AddParameter("--cpus=", config_->cpus());
+ crosvm_cmd.AddParameter("--params=", kernel_cmdline_);
for (const auto& disk : instance.virtual_disk_paths()) {
- crosvm_cmd.AddParameter(config.protected_vm() ? "--disk=" :
- "--rwdisk=", disk);
+ crosvm_cmd.AddParameter("--rwdisk=", disk);
}
- crosvm_cmd.AddParameter("--socket=", GetControlSocketPath(config));
-
- if (config.enable_vnc_server() || config.enable_webrtc()) {
- auto touch_type_parameter =
- config.enable_webrtc() ? "--multi-touch=" : "--single-touch=";
- crosvm_cmd.AddParameter(touch_type_parameter, instance.touch_socket_path(),
- ":", display_config.width, ":",
- display_config.height);
+ crosvm_cmd.AddParameter("--socket=", GetControlSocketPath(config_));
+
+ if (frontend_enabled_) {
+ crosvm_cmd.AddParameter("--single-touch=", instance.touch_socket_path(),
+ ":", config_->x_res(), ":", config_->y_res());
crosvm_cmd.AddParameter("--keyboard=", instance.keyboard_socket_path());
}
- if (config.enable_webrtc()) {
- crosvm_cmd.AddParameter("--switches=", instance.switches_socket_path());
- }
- auto wifi_tap = AddTapFdParameter(&crosvm_cmd, instance.wifi_tap_name());
+ AddTapFdParameter(&crosvm_cmd, instance.wifi_tap_name());
AddTapFdParameter(&crosvm_cmd, instance.mobile_tap_name());
- if (FileExists(instance.access_kregistry_path())) {
- crosvm_cmd.AddParameter("--rw-pmem-device=",
- instance.access_kregistry_path());
- }
-
- if (FileExists(instance.pstore_path())) {
- crosvm_cmd.AddParameter("--pstore=path=", instance.pstore_path(),
- ",size=", FileSize(instance.pstore_path()));
- }
+ crosvm_cmd.AddParameter("--rw-pmem-device=", instance.access_kregistry_path());
- if (config.enable_sandbox()) {
- const bool seccomp_exists = DirectoryExists(config.seccomp_policy_dir());
- const std::string& var_empty_dir = kCrosvmVarEmptyDir;
- const bool var_empty_available = DirectoryExists(var_empty_dir);
- if (!var_empty_available || !seccomp_exists) {
- LOG(FATAL) << var_empty_dir << " is not an existing, empty directory."
- << "seccomp-policy-dir, " << config.seccomp_policy_dir()
- << " does not exist " << std::endl;
- return {};
- }
- crosvm_cmd.AddParameter("--seccomp-policy-dir=", config.seccomp_policy_dir());
- } else {
- crosvm_cmd.AddParameter("--disable-sandbox");
- }
+ // TODO remove this (use crosvm's seccomp files)
+ crosvm_cmd.AddParameter("--disable-sandbox");
if (instance.vsock_guest_cid() >= 2) {
crosvm_cmd.AddParameter("--cid=", instance.vsock_guest_cid());
}
- // Use a virtio-console instance for the main kernel console. All
- // messages will switch from earlycon to virtio-console after the driver
- // is loaded, and crosvm will append to the kernel log automatically
- add_hvc_console(instance.kernel_log_pipe_name());
-
- if (config.console()) {
- // stdin is the only currently supported way to write data to a serial port in
- // crosvm. A file (named pipe) is used here instead of stdout to ensure only
- // the serial port output is received by the console forwarder as crosvm may
- // print other messages to stdout.
- if (config.kgdb() || config.use_bootloader()) {
- add_serial_console(instance.console_out_pipe_name(),
- instance.console_in_pipe_name());
- // In kgdb mode, we have the interactive console on ttyS0 (both Android's
- // console and kdb), so we can disable the virtio-console port usually
- // allocated to Android's serial console, and redirect it to a sink. This
- // ensures that that the PCI device assignments (and thus sepolicy) don't
- // have to change
- add_hvc_sink();
- } else {
- add_serial_sink();
- add_hvc(instance.console_out_pipe_name(),
- instance.console_in_pipe_name());
- }
- } else {
- // Use an 8250 UART (ISA or platform device) for earlycon, as the
- // virtio-console driver may not be available for early messages
- // In kgdb mode, earlycon is an interactive console, and so early
- // dmesg will go there instead of the kernel.log
- if (config.kgdb() || config.use_bootloader()) {
- add_serial_console_ro(instance.kernel_log_pipe_name());
- }
+ // Redirect the first serial port with the kernel logs to the appropriate file
+ crosvm_cmd.AddParameter("--serial=num=1,type=file,path=",
+ instance.kernel_log_pipe_name(), ",console=true");
- // as above, create a fake virtio-console 'sink' port when the serial
- // console is disabled, so the PCI device ID assignments don't move
- // around
- add_hvc_sink();
+ // Redirect standard input to a pipe for the console forwarder host process
+ // to handle.
+ cvd::SharedFD console_in_rd, console_in_wr;
+ if (!cvd::SharedFD::Pipe(&console_in_rd, &console_in_wr)) {
+ LOG(ERROR) << "Failed to create console pipe for crosvm's stdin: "
+ << console_in_rd->StrError();
+ return {};
}
-
- if (config.enable_gnss_grpc_proxy()) {
- add_serial(instance.gnss_out_pipe_name(), instance.gnss_in_pipe_name());
+ auto console_pipe_name = instance.console_pipe_name();
+ if (mkfifo(console_pipe_name.c_str(), 0660) != 0) {
+ auto error = errno;
+ LOG(ERROR) << "Failed to create console fifo for crosvm: "
+ << strerror(error);
+ return {};
}
- SharedFD log_out_rd, log_out_wr;
- if (!SharedFD::Pipe(&log_out_rd, &log_out_wr)) {
+ // This fd will only be read from, but it's open with write access as well to
+ // keep the pipe open in case the subprocesses exit.
+ cvd::SharedFD console_out_rd =
+ cvd::SharedFD::Open(console_pipe_name.c_str(), O_RDWR);
+ if (!console_out_rd->IsOpen()) {
+ LOG(ERROR) << "Failed to open console fifo for reads: "
+ << console_out_rd->StrError();
+ return {};
+ }
+ // stdin is the only currently supported way to write data to a serial port in
+ // crosvm. A file (named pipe) is used here instead of stdout to ensure only
+ // the serial port output is received by the console forwarder as crosvm may
+ // print other messages to stdout.
+ crosvm_cmd.AddParameter("--serial=num=2,type=file,path=", console_pipe_name,
+ ",stdin=true");
+
+ crosvm_cmd.RedirectStdIO(cvd::Subprocess::StdIOChannel::kStdIn,
+ console_in_rd);
+ cvd::Command console_cmd(config_->console_forwarder_binary());
+ console_cmd.AddParameter("--console_in_fd=", console_in_wr);
+ console_cmd.AddParameter("--console_out_fd=", console_out_rd);
+
+ cvd::SharedFD log_out_rd, log_out_wr;
+ if (!cvd::SharedFD::Pipe(&log_out_rd, &log_out_wr)) {
LOG(ERROR) << "Failed to create log pipe for crosvm's stdout/stderr: "
- << log_out_rd->StrError();
+ << console_in_rd->StrError();
return {};
}
- crosvm_cmd.RedirectStdIO(Subprocess::StdIOChannel::kStdOut, log_out_wr);
- crosvm_cmd.RedirectStdIO(Subprocess::StdIOChannel::kStdErr, log_out_wr);
+ crosvm_cmd.RedirectStdIO(cvd::Subprocess::StdIOChannel::kStdOut,
+ log_out_wr);
+ crosvm_cmd.RedirectStdIO(cvd::Subprocess::StdIOChannel::kStdErr,
+ log_out_wr);
- Command log_tee_cmd(HostBinaryPath("log_tee"));
+ cvd::Command log_tee_cmd(vsoc::DefaultHostArtifactsPath("bin/log_tee"));
log_tee_cmd.AddParameter("--process_name=crosvm");
log_tee_cmd.AddParameter("--log_fd_in=", log_out_rd);
- // Serial port for logcat, redirected to a pipe
- add_hvc_ro(instance.logcat_pipe_name());
-
- add_hvc(instance.PerInstanceInternalPath("keymaster_fifo_vm.out"),
- instance.PerInstanceInternalPath("keymaster_fifo_vm.in"));
- add_hvc(instance.PerInstanceInternalPath("gatekeeper_fifo_vm.out"),
- instance.PerInstanceInternalPath("gatekeeper_fifo_vm.in"));
-
- if (config.enable_host_bluetooth()) {
- add_hvc(instance.PerInstanceInternalPath("bt_fifo_vm.out"),
- instance.PerInstanceInternalPath("bt_fifo_vm.in"));
- } else {
- add_hvc_sink();
- }
- for (auto i = 0; i < VmManager::kMaxDisks - disk_num; i++) {
- add_hvc_sink();
- }
- CHECK(hvc_num + disk_num == VmManager::kMaxDisks + VmManager::kDefaultNumHvcs)
- << "HVC count (" << hvc_num << ") + disk count (" << disk_num << ") "
- << "is not the expected total of "
- << VmManager::kMaxDisks + VmManager::kDefaultNumHvcs << " devices";
-
- if (config.enable_audio()) {
- crosvm_cmd.AddParameter("--ac97=backend=vios,server=" +
- config.ForDefaultInstance().audio_server_path());
- }
-
- // TODO(b/172286896): This is temporarily optional, but should be made
- // unconditional and moved up to the other network devices area
- if (config.ethernet()) {
- AddTapFdParameter(&crosvm_cmd, instance.ethernet_tap_name());
- }
-
- // TODO(b/162071003): virtiofs crashes without sandboxing, this should be fixed
- if (config.enable_sandbox()) {
- // Set up directory shared with virtiofs
- crosvm_cmd.AddParameter("--shared-dir=", instance.PerInstancePath(kSharedDirName),
- ":shared:type=fs");
- }
-
// This needs to be the last parameter
- crosvm_cmd.AddParameter("--bios=", config.bootloader());
-
- // Only run the leases workaround if we are not using the new network
- // bridge architecture - in that case, we have a wider DHCP address
- // space and stale leases should be much less of an issue
- if (!FileExists("/var/run/cuttlefish-dnsmasq-cvd-wbr.leases")) {
- // TODO(schuffelen): QEMU also needs this and this is not the best place for
- // this code. Find a better place to put it.
- auto lease_file =
- ForCurrentInstance("/var/run/cuttlefish-dnsmasq-cvd-wbr-") + ".leases";
- if (!ReleaseDhcpLeases(lease_file, wifi_tap)) {
- LOG(ERROR) << "Failed to release wifi DHCP leases. Connecting to the wifi "
- << "network may not work.";
- }
- }
+ crosvm_cmd.AddParameter(config_->GetKernelImageToUse());
- std::vector<Command> ret;
+ std::vector<cvd::Command> ret;
ret.push_back(std::move(crosvm_cmd));
+ ret.push_back(std::move(console_cmd));
ret.push_back(std::move(log_tee_cmd));
return ret;
}
-} // namespace vm_manager
-} // namespace cuttlefish
-
+} // namespace vm_manager
diff --git a/host/libs/vm_manager/crosvm_manager.h b/host/libs/vm_manager/crosvm_manager.h
index 9d41d6861..848f2ae41 100644
--- a/host/libs/vm_manager/crosvm_manager.h
+++ b/host/libs/vm_manager/crosvm_manager.h
@@ -23,25 +23,21 @@
#include "common/libs/fs/shared_fd.h"
#include "common/libs/utils/subprocess.h"
-namespace cuttlefish {
namespace vm_manager {
// Starts a guest VM with crosvm. It requires the host package to support the
// qemu-cli capability (for network only).
class CrosvmManager : public VmManager {
public:
- static std::string name() { return "crosvm"; }
- CrosvmManager(Arch arch) : VmManager(arch) {}
- virtual ~CrosvmManager() = default;
+ static const std::string name();
+ static bool EnsureInstanceDirExists(const std::string& instance_dir);
+ static std::vector<std::string> ConfigureGpu(const std::string& gpu_mode);
+ static std::vector<std::string> ConfigureBootDevices();
- bool IsSupported() override;
- std::vector<std::string> ConfigureGpuMode(const std::string&) override;
- std::string ConfigureBootDevices(int num_disks) override;
+ CrosvmManager(const vsoc::CuttlefishConfig* config);
+ virtual ~CrosvmManager() = default;
- std::vector<cuttlefish::Command> StartCommands(
- const CuttlefishConfig& config) override;
+ std::vector<cvd::Command> StartCommands() override;
};
-} // namespace vm_manager
-} // namespace cuttlefish
-
+} // namespace vm_manager
diff --git a/host/libs/vm_manager/host_configuration.cpp b/host/libs/vm_manager/host_configuration.cpp
deleted file mode 100644
index f49f74dbb..000000000
--- a/host/libs/vm_manager/host_configuration.cpp
+++ /dev/null
@@ -1,107 +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.
- */
-
-#include "host/libs/vm_manager/host_configuration.h"
-
-#include <string>
-#include <utility>
-#include <vector>
-
-#include <android-base/logging.h>
-#include <sys/utsname.h>
-
-#include "common/libs/utils/users.h"
-
-namespace cuttlefish {
-namespace vm_manager {
-namespace {
-
-bool UserInGroup(const std::string& group,
- std::vector<std::string>* config_commands) {
- if (!InGroup(group)) {
- LOG(ERROR) << "User must be a member of " << group;
- config_commands->push_back("# Add your user to the " + group + " group:");
- config_commands->push_back("sudo usermod -aG " + group + " $USER");
- return false;
- }
- return true;
-}
-
-constexpr std::pair<int,int> invalid_linux_version = std::pair<int,int>();
-
-std::pair<int,int> GetLinuxVersion() {
- struct utsname info;
- if (!uname(&info)) {
- char* digit = strtok(info.release, "+.-");
- int major = atoi(digit);
- if (digit) {
- digit = strtok(NULL, "+.-");
- int minor = atoi(digit);
- return std::pair<int,int>{major, minor};
- }
- }
- LOG(ERROR) << "Failed to detect Linux kernel version";
- return invalid_linux_version;
-}
-
-bool LinuxVersionAtLeast(std::vector<std::string>* config_commands,
- const std::pair<int,int>& version,
- int major, int minor) {
- if (version.first > major ||
- (version.first == major && version.second >= minor)) {
- return true;
- }
-
- LOG(ERROR) << "Kernel version must be >=" << major << "." << minor
- << ", have " << version.first << "." << version.second;
- config_commands->push_back("# Please upgrade your kernel to >=" +
- std::to_string(major) + "." +
- std::to_string(minor));
- return false;
-}
-
-} // namespace
-
-bool ValidateHostConfiguration(std::vector<std::string>* config_commands) {
- // if we can't detect the kernel version, just fail
- auto version = GetLinuxVersion();
- if (version == invalid_linux_version) {
- return false;
- }
-
- // the check for cvdnetwork needs to happen even if the user is not in kvm, so
- // we can't just say UserInGroup("kvm") && UserInGroup("cvdnetwork")
- auto in_cvdnetwork = UserInGroup("cvdnetwork", config_commands);
-
- // if we're in the virtaccess group this is likely to be a CrOS environment.
- auto is_cros = InGroup("virtaccess");
- if (is_cros) {
- // relax the minimum kernel requirement slightly, as chromeos-4.4 has the
- // needed backports to enable vhost_vsock
- auto linux_ver_4_4 = LinuxVersionAtLeast(config_commands, version, 4, 4);
- return in_cvdnetwork && linux_ver_4_4;
- } else {
- // this is regular Linux, so use the Debian group name and be more
- // conservative with the kernel version check.
- auto in_kvm = UserInGroup("kvm", config_commands);
- auto linux_ver_4_8 = LinuxVersionAtLeast(config_commands, version, 4, 8);
- return in_cvdnetwork && in_kvm && linux_ver_4_8;
- }
-}
-
-} // namespace vm_manager
-} // namespace cuttlefish
-
diff --git a/host/libs/vm_manager/host_configuration.h b/host/libs/vm_manager/host_configuration.h
deleted file mode 100644
index 0705522fc..000000000
--- a/host/libs/vm_manager/host_configuration.h
+++ /dev/null
@@ -1,28 +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.
- */
-#pragma once
-
-#include <string>
-#include <vector>
-
-namespace cuttlefish {
-namespace vm_manager {
-
-bool ValidateHostConfiguration(std::vector<std::string>* config_commands);
-
-} // namespace vm_manager
-} // namespace cuttlefish
-
diff --git a/host/libs/vm_manager/qemu_manager.cpp b/host/libs/vm_manager/qemu_manager.cpp
index f26818a86..f08d66cc2 100644
--- a/host/libs/vm_manager/qemu_manager.cpp
+++ b/host/libs/vm_manager/qemu_manager.cpp
@@ -32,21 +32,19 @@
#include <android-base/strings.h>
#include <android-base/logging.h>
-#include <vulkan/vulkan.h>
#include "common/libs/fs/shared_select.h"
#include "common/libs/utils/files.h"
#include "common/libs/utils/subprocess.h"
#include "common/libs/utils/users.h"
#include "host/libs/config/cuttlefish_config.h"
-#include "host/libs/config/known_paths.h"
-namespace cuttlefish {
namespace vm_manager {
+
namespace {
-std::string GetMonitorPath(const CuttlefishConfig& config) {
- return config.ForDefaultInstance()
+std::string GetMonitorPath(const vsoc::CuttlefishConfig* config) {
+ return config->ForDefaultInstance()
.PerInstanceInternalPath("qemu_monitor.sock");
}
@@ -56,9 +54,9 @@ void LogAndSetEnv(const char* key, const std::string& value) {
}
bool Stop() {
- auto config = CuttlefishConfig::Get();
- auto monitor_path = GetMonitorPath(*config);
- auto monitor_sock = SharedFD::SocketLocalClient(
+ auto config = vsoc::CuttlefishConfig::Get();
+ auto monitor_path = GetMonitorPath(config);
+ auto monitor_sock = cvd::SharedFD::SocketLocalClient(
monitor_path.c_str(), false, SOCK_STREAM);
if (!monitor_sock->IsOpen()) {
@@ -87,57 +85,37 @@ bool Stop() {
} // namespace
-bool QemuManager::IsSupported() {
- return HostSupportsQemuCli();
-}
+const std::string QemuManager::name() { return "qemu_cli"; }
-std::vector<std::string> QemuManager::ConfigureGpuMode(
- const std::string& gpu_mode) {
- if (gpu_mode == kGpuModeGuestSwiftshader) {
- // Override the default HAL search paths in all cases. We do this because
- // the HAL search path allows for fallbacks, and fallbacks in conjunction
- // with properities lead to non-deterministic behavior while loading the
- // HALs.
- return {
- "androidboot.cpuvulkan.version=" + std::to_string(VK_API_VERSION_1_1),
- "androidboot.hardware.gralloc=minigbm",
- "androidboot.hardware.hwcomposer=ranchu",
- "androidboot.hardware.egl=swiftshader",
- "androidboot.hardware.vulkan=pastel",
- };
+std::vector<std::string> QemuManager::ConfigureGpu(const std::string& gpu_mode) {
+ if (gpu_mode != vsoc::kGpuModeGuestSwiftshader) {
+ return {};
}
-
- if (gpu_mode == kGpuModeDrmVirgl) {
- return {
- "androidboot.cpuvulkan.version=0",
+ // Override the default HAL search paths in all cases. We do this because
+ // the HAL search path allows for fallbacks, and fallbacks in conjunction
+ // with properities lead to non-deterministic behavior while loading the
+ // HALs.
+ return {
"androidboot.hardware.gralloc=minigbm",
- "androidboot.hardware.hwcomposer=drm_minigbm",
- "androidboot.hardware.egl=mesa",
- };
- }
-
- return {};
+ "androidboot.hardware.hwcomposer=cutf_cvm_ashmem",
+ "androidboot.hardware.egl=swiftshader",
+ "androidboot.hardware.vulkan=pastel",
+ };
}
-std::string QemuManager::ConfigureBootDevices(int num_disks) {
- switch (arch_) {
- case Arch::X86:
- case Arch::X86_64: {
- // QEMU has additional PCI devices for an ISA bridge and PIIX4
- return ConfigureMultipleBootDevices("pci0000:00/0000:00:", 2, num_disks);
- }
- case Arch::Arm:
- return "androidboot.boot_devices=3f000000.pcie";
- case Arch::Arm64:
- return "androidboot.boot_devices=4010000000.pcie";
- }
+std::vector<std::string> QemuManager::ConfigureBootDevices() {
+ // PCI domain 0, bus 0, device 3, function 0
+ // This is controlled with 'addr=0x3' in cf_qemu.sh
+ return { "androidboot.boot_devices=pci0000:00/0000:00:03.0" };
}
-std::vector<Command> QemuManager::StartCommands(
- const CuttlefishConfig& config) {
- auto instance = config.ForDefaultInstance();
+QemuManager::QemuManager(const vsoc::CuttlefishConfig* config)
+ : VmManager(config) {}
+
+std::vector<cvd::Command> QemuManager::StartCommands() {
+ auto instance = config_->ForDefaultInstance();
- auto stop = [](Subprocess* proc) {
+ auto stop = [](cvd::Subprocess* proc) {
auto stopped = Stop();
if (stopped) {
return true;
@@ -146,140 +124,33 @@ std::vector<Command> QemuManager::StartCommands(
<< "attempting to KILL";
return KillSubprocess(proc);
};
- std::string qemu_binary = config.qemu_binary_dir();
- switch (arch_) {
- case Arch::Arm:
- qemu_binary += "/qemu-system-arm";
- break;
- case Arch::Arm64:
- qemu_binary += "/qemu-system-aarch64";
- break;
- case Arch::X86:
- qemu_binary += "/qemu-system-i386";
- break;
- case Arch::X86_64:
- qemu_binary += "/qemu-system-x86_64";
- break;
- }
- Command qemu_cmd(qemu_binary, stop);
-
- int hvc_num = 0;
- int serial_num = 0;
- auto add_hvc_sink = [&qemu_cmd, &hvc_num]() {
- qemu_cmd.AddParameter("-chardev");
- qemu_cmd.AddParameter("null,id=hvc", hvc_num);
- qemu_cmd.AddParameter("-device");
- qemu_cmd.AddParameter(
- "virtio-serial-pci-non-transitional,max_ports=1,id=virtio-serial",
- hvc_num);
- qemu_cmd.AddParameter("-device");
- qemu_cmd.AddParameter("virtconsole,bus=virtio-serial", hvc_num,
- ".0,chardev=hvc", hvc_num);
- hvc_num++;
- };
- auto add_serial_sink = [&qemu_cmd, &serial_num]() {
- qemu_cmd.AddParameter("-chardev");
- qemu_cmd.AddParameter("null,id=serial", serial_num);
- qemu_cmd.AddParameter("-serial");
- qemu_cmd.AddParameter("chardev:serial", serial_num);
- serial_num++;
- };
- auto add_serial_console_ro = [&qemu_cmd,
- &serial_num](const std::string& output) {
- qemu_cmd.AddParameter("-chardev");
- qemu_cmd.AddParameter("file,id=serial", serial_num, ",path=", output,
- ",append=on");
- qemu_cmd.AddParameter("-serial");
- qemu_cmd.AddParameter("chardev:serial", serial_num);
- serial_num++;
- };
- auto add_serial_console = [&qemu_cmd,
- &serial_num](const std::string& prefix) {
- qemu_cmd.AddParameter("-chardev");
- qemu_cmd.AddParameter("pipe,id=serial", serial_num, ",path=", prefix);
- qemu_cmd.AddParameter("-serial");
- qemu_cmd.AddParameter("chardev:serial", serial_num);
- serial_num++;
- };
- auto add_hvc_ro = [&qemu_cmd, &hvc_num](const std::string& output) {
- qemu_cmd.AddParameter("-chardev");
- qemu_cmd.AddParameter("file,id=hvc", hvc_num, ",path=", output,
- ",append=on");
- qemu_cmd.AddParameter("-device");
- qemu_cmd.AddParameter(
- "virtio-serial-pci-non-transitional,max_ports=1,id=virtio-serial",
- hvc_num);
- qemu_cmd.AddParameter("-device");
- qemu_cmd.AddParameter("virtconsole,bus=virtio-serial", hvc_num,
- ".0,chardev=hvc", hvc_num);
- hvc_num++;
- };
- auto add_hvc = [&qemu_cmd, &hvc_num](const std::string& prefix) {
- qemu_cmd.AddParameter("-chardev");
- qemu_cmd.AddParameter("pipe,id=hvc", hvc_num, ",path=", prefix);
- qemu_cmd.AddParameter("-device");
- qemu_cmd.AddParameter(
- "virtio-serial-pci-non-transitional,max_ports=1,id=virtio-serial",
- hvc_num);
- qemu_cmd.AddParameter("-device");
- qemu_cmd.AddParameter("virtconsole,bus=virtio-serial", hvc_num,
- ".0,chardev=hvc", hvc_num);
- hvc_num++;
- };
-
- bool is_arm = arch_ == Arch::Arm || arch_ == Arch::Arm64;
- auto access_kregistry_size_bytes = 0;
- if (FileExists(instance.access_kregistry_path())) {
- access_kregistry_size_bytes = FileSize(instance.access_kregistry_path());
- CHECK((access_kregistry_size_bytes & (1024 * 1024 - 1)) == 0)
- << instance.access_kregistry_path() << " file size ("
- << access_kregistry_size_bytes << ") not a multiple of 1MB";
- }
-
- auto pstore_size_bytes = 0;
- if (FileExists(instance.pstore_path())) {
- pstore_size_bytes = FileSize(instance.pstore_path());
- CHECK((pstore_size_bytes & (1024 * 1024 - 1)) == 0)
- << instance.pstore_path() << " file size ("
- << pstore_size_bytes << ") not a multiple of 1MB";
- }
+ bool is_arm = android::base::EndsWith(config_->qemu_binary(), "system-aarch64");
+ cvd::Command qemu_cmd(config_->qemu_binary(), stop);
qemu_cmd.AddParameter("-name");
qemu_cmd.AddParameter("guest=", instance.instance_name(), ",debug-threads=on");
qemu_cmd.AddParameter("-machine");
- auto machine = is_arm ? "virt,gic-version=2,mte=on"
- : "pc-i440fx-2.8,accel=kvm,nvdimm=on";
+ auto machine = is_arm ? "virt,gic_version=2" : "pc-i440fx-2.8,accel=kvm";
qemu_cmd.AddParameter(machine, ",usb=off,dump-guest-core=off");
qemu_cmd.AddParameter("-m");
- auto maxmem = config.memory_mb() +
- access_kregistry_size_bytes / 1024 / 1024 +
- (is_arm ? 0 : pstore_size_bytes / 1024 / 1024);
- auto slots = is_arm ? "" : ",slots=2";
- qemu_cmd.AddParameter("size=", config.memory_mb(), "M",
- ",maxmem=", maxmem, "M", slots);
-
- qemu_cmd.AddParameter("-overcommit");
- qemu_cmd.AddParameter("mem-lock=off");
-
- // Assume SMT is always 2 threads per core, which is how most hardware
- // today is configured, and the way crosvm does it
+ qemu_cmd.AddParameter(config_->memory_mb());
+
+ qemu_cmd.AddParameter("-realtime");
+ qemu_cmd.AddParameter("mlock=off");
+
qemu_cmd.AddParameter("-smp");
- if (config.smt()) {
- CHECK(config.cpus() % 2 == 0)
- << "CPUs must be a multiple of 2 in SMT mode";
- qemu_cmd.AddParameter(config.cpus(), ",cores=",
- config.cpus() / 2, ",threads=2");
- } else {
- qemu_cmd.AddParameter(config.cpus(), ",cores=",
- config.cpus(), ",threads=1");
- }
+ qemu_cmd.AddParameter(config_->cpus(), ",sockets=", config_->cpus(),
+ ",cores=1,threads=1");
qemu_cmd.AddParameter("-uuid");
qemu_cmd.AddParameter(instance.uuid());
+ qemu_cmd.AddParameter("-display");
+ qemu_cmd.AddParameter("none");
+
qemu_cmd.AddParameter("-no-user-config");
qemu_cmd.AddParameter("-nodefaults");
qemu_cmd.AddParameter("-no-shutdown");
@@ -290,207 +161,119 @@ std::vector<Command> QemuManager::StartCommands(
qemu_cmd.AddParameter("-boot");
qemu_cmd.AddParameter("strict=on");
- qemu_cmd.AddParameter("-chardev");
- qemu_cmd.AddParameter("socket,id=charmonitor,path=", GetMonitorPath(config),
- ",server,nowait");
-
- qemu_cmd.AddParameter("-mon");
- qemu_cmd.AddParameter("chardev=charmonitor,id=monitor,mode=control");
-
- // In kgdb mode, earlycon is an interactive console, and so early
- // dmesg will go there instead of the kernel.log. On QEMU, we do this
- // bit of logic up before the hvc console is set up, so the command line
- // flags appear in the right order and "append=on" does the right thing
- if (!(config.console() && (config.kgdb() || config.use_bootloader()))) {
- add_serial_console_ro(instance.kernel_log_pipe_name());
- }
-
- // Use a virtio-console instance for the main kernel console. All
- // messages will switch from earlycon to virtio-console after the driver
- // is loaded, and QEMU will append to the kernel log automatically
- add_hvc_ro(instance.kernel_log_pipe_name());
-
- if (config.console()) {
- if (config.kgdb() || config.use_bootloader()) {
- add_serial_console(instance.console_pipe_prefix());
-
- // In kgdb mode, we have the interactive console on ttyS0 (both Android's
- // console and kdb), so we can disable the virtio-console port usually
- // allocated to Android's serial console, and redirect it to a sink. This
- // ensures that that the PCI device assignments (and thus sepolicy) don't
- // have to change
- add_hvc_sink();
- } else {
- add_serial_sink();
- add_hvc(instance.console_pipe_prefix());
- }
- } else {
- if (config.kgdb() || config.use_bootloader()) {
- // The add_serial_console_ro() call above was applied by the time we reach
- // this code, so we don't need another add_serial_*() call
- }
-
- // as above, create a fake virtio-console 'sink' port when the serial
- // console is disabled, so the PCI device ID assignments don't move
- // around
- add_hvc_sink();
- }
-
- if (config.enable_gnss_grpc_proxy()) {
- add_serial_console(instance.gnss_pipe_prefix());
- }
-
- // Serial port for logcat, redirected to a pipe
- add_hvc_ro(instance.logcat_pipe_name());
-
- add_hvc(instance.PerInstanceInternalPath("keymaster_fifo_vm"));
- add_hvc(instance.PerInstanceInternalPath("gatekeeper_fifo_vm"));
- if (config.enable_host_bluetooth()) {
- add_hvc(instance.PerInstanceInternalPath("bt_fifo_vm"));
- } else {
- add_hvc_sink();
- }
+ qemu_cmd.AddParameter("-kernel");
+ qemu_cmd.AddParameter(config_->GetKernelImageToUse());
- auto disk_num = instance.virtual_disk_paths().size();
+ qemu_cmd.AddParameter("-append");
+ qemu_cmd.AddParameter(kernel_cmdline_);
- for (auto i = 0; i < VmManager::kMaxDisks - disk_num; i++) {
- add_hvc_sink();
- }
-
- CHECK(hvc_num + disk_num == VmManager::kMaxDisks + VmManager::kDefaultNumHvcs)
- << "HVC count (" << hvc_num << ") + disk count (" << disk_num << ") "
- << "is not the expected total of "
- << VmManager::kMaxDisks + VmManager::kDefaultNumHvcs << " devices";
+ qemu_cmd.AddParameter("-device");
+ qemu_cmd.AddParameter("virtio-serial-pci,id=virtio-serial0");
- CHECK_GE(VmManager::kMaxDisks, disk_num)
- << "Provided too many disks (" << disk_num << "), maximum "
- << VmManager::kMaxDisks << "supported";
- auto readonly = config.protected_vm() ? ",readonly" : "";
- for (size_t i = 0; i < disk_num; i++) {
+ for (size_t i = 0; i < instance.virtual_disk_paths().size(); i++) {
auto bootindex = i == 0 ? ",bootindex=1" : "";
- auto format = i == 0 ? "" : ",format=raw";
auto disk = instance.virtual_disk_paths()[i];
qemu_cmd.AddParameter("-drive");
qemu_cmd.AddParameter("file=", disk, ",if=none,id=drive-virtio-disk", i,
- ",aio=threads", format, readonly);
+ ",aio=threads");
qemu_cmd.AddParameter("-device");
- qemu_cmd.AddParameter("virtio-blk-pci-non-transitional,scsi=off,drive=drive-virtio-disk", i,
+ qemu_cmd.AddParameter("virtio-blk-pci,scsi=off,drive=drive-virtio-disk", i,
",id=virtio-disk", i, bootindex);
}
- if (config.gpu_mode() == kGpuModeDrmVirgl) {
- qemu_cmd.AddParameter("-display");
- qemu_cmd.AddParameter("egl-headless");
+ qemu_cmd.AddParameter("-netdev");
+ qemu_cmd.AddParameter("tap,id=hostnet0,ifname=", instance.wifi_tap_name(),
+ ",script=no,downscript=no");
- qemu_cmd.AddParameter("-vnc");
- qemu_cmd.AddParameter(":", instance.vnc_server_port() - 5900);
- } else {
- qemu_cmd.AddParameter("-display");
- qemu_cmd.AddParameter("none");
- }
+ auto romfile = is_arm ? ",romfile" : "";
+ qemu_cmd.AddParameter("-device");
+ qemu_cmd.AddParameter("virtio-net-pci,netdev=hostnet0,id=net0", romfile);
- if (!is_arm && FileExists(instance.pstore_path())) {
- // QEMU will assign the NVDIMM (ramoops pstore region) 100000000-1001fffff
- // As we will pass this to ramoops, define this region first so it is always
- // located at this address. This is currently x86 only.
- qemu_cmd.AddParameter("-object");
- qemu_cmd.AddParameter("memory-backend-file,id=objpmem0,share,mem-path=",
- instance.pstore_path(), ",size=", pstore_size_bytes);
+ qemu_cmd.AddParameter("-netdev");
+ qemu_cmd.AddParameter("tap,id=hostnet1,ifname=", instance.mobile_tap_name(),
+ ",script=no,downscript=no");
- qemu_cmd.AddParameter("-device");
- qemu_cmd.AddParameter("nvdimm,memdev=objpmem0,id=ramoops");
- }
+ qemu_cmd.AddParameter("-device");
+ qemu_cmd.AddParameter("virtio-net-pci,netdev=hostnet1,id=net1", romfile);
- // QEMU does not implement virtio-pmem-pci for ARM64 yet; restore this
- // when the device has been added
- if (!is_arm && FileExists(instance.access_kregistry_path())) {
- qemu_cmd.AddParameter("-object");
- qemu_cmd.AddParameter("memory-backend-file,id=objpmem1,share,mem-path=",
- instance.access_kregistry_path(), ",size=",
- access_kregistry_size_bytes);
+ qemu_cmd.AddParameter("-device");
+ qemu_cmd.AddParameter("virtio-balloon-pci,id=balloon0");
- qemu_cmd.AddParameter("-device");
- qemu_cmd.AddParameter("virtio-pmem-pci,disable-legacy=on,memdev=objpmem1,id=pmem0");
- }
+ qemu_cmd.AddParameter("-device");
+ qemu_cmd.AddParameter("virtio-gpu-pci,id=gpu0");
qemu_cmd.AddParameter("-object");
qemu_cmd.AddParameter("rng-random,id=objrng0,filename=/dev/urandom");
qemu_cmd.AddParameter("-device");
- qemu_cmd.AddParameter("virtio-rng-pci-non-transitional,rng=objrng0,id=rng0,",
+ qemu_cmd.AddParameter("virtio-rng-pci,rng=objrng0,id=rng0,",
"max-bytes=1024,period=2000");
- qemu_cmd.AddParameter("-device");
- qemu_cmd.AddParameter("virtio-mouse-pci");
-
- qemu_cmd.AddParameter("-device");
- qemu_cmd.AddParameter("virtio-keyboard-pci");
+ qemu_cmd.AddParameter("-cpu");
+ qemu_cmd.AddParameter(is_arm ? "cortex-a53" : "host");
- auto vhost_net = config.vhost_net() ? ",vhost=on" : "";
+ qemu_cmd.AddParameter("-msg");
+ qemu_cmd.AddParameter("timestamp=on");
qemu_cmd.AddParameter("-device");
- qemu_cmd.AddParameter("virtio-balloon-pci-non-transitional,id=balloon0");
+ qemu_cmd.AddParameter("AC97");
- qemu_cmd.AddParameter("-netdev");
- qemu_cmd.AddParameter("tap,id=hostnet0,ifname=", instance.wifi_tap_name(),
- ",script=no,downscript=no", vhost_net);
+ if (config_->use_bootloader()) {
+ qemu_cmd.AddParameter("-bios");
+ qemu_cmd.AddParameter(config_->bootloader());
+ }
- qemu_cmd.AddParameter("-device");
- qemu_cmd.AddParameter("virtio-net-pci-non-transitional,netdev=hostnet0,id=net0");
+ qemu_cmd.AddParameter("-chardev");
+ qemu_cmd.AddParameter("socket,id=charmonitor,path=", GetMonitorPath(config_),
+ ",server,nowait");
- qemu_cmd.AddParameter("-netdev");
- qemu_cmd.AddParameter("tap,id=hostnet1,ifname=", instance.mobile_tap_name(),
- ",script=no,downscript=no", vhost_net);
+ qemu_cmd.AddParameter("-mon");
+ qemu_cmd.AddParameter("chardev=charmonitor,id=monitor,mode=control");
- qemu_cmd.AddParameter("-device");
- qemu_cmd.AddParameter("virtio-net-pci-non-transitional,netdev=hostnet1,id=net1");
+ qemu_cmd.AddParameter("-chardev");
+ qemu_cmd.AddParameter("file,id=charserial0,path=",
+ instance.kernel_log_pipe_name(), ",append=on");
qemu_cmd.AddParameter("-device");
- qemu_cmd.AddParameter("virtio-gpu-pci,id=gpu0");
-
- qemu_cmd.AddParameter("-cpu");
- qemu_cmd.AddParameter(IsHostCompatible(arch_) ? "host" : "max");
-
- qemu_cmd.AddParameter("-msg");
- qemu_cmd.AddParameter("timestamp=on");
+ // On ARM, the early console can be PCI, and ISA is not supported
+ // On x86, the early console must be ISA, not PCI, so we start to get kernel
+ // messages as soon as possible. ISA devices do not have 'addr' assignments.
+ auto kernel_console_serial = is_arm ? "pci-serial" : "isa-serial";
+ qemu_cmd.AddParameter(kernel_console_serial, ",chardev=charserial0,id=serial0");
- qemu_cmd.AddParameter("-device");
- qemu_cmd.AddParameter("vhost-vsock-pci-non-transitional,guest-cid=",
- instance.vsock_guest_cid());
+ qemu_cmd.AddParameter("-chardev");
+ qemu_cmd.AddParameter("socket,id=charserial1,path=", instance.console_path(),
+ ",server,nowait");
qemu_cmd.AddParameter("-device");
- qemu_cmd.AddParameter("AC97");
+ qemu_cmd.AddParameter(kernel_console_serial, ",chardev=charserial1,id=serial1");
- // TODO(b/172286896): This is temporarily optional, but should be made
- // unconditional and moved up to the other network devices area
- if (config.ethernet()) {
- qemu_cmd.AddParameter("-netdev");
- qemu_cmd.AddParameter("tap,id=hostnet2,ifname=", instance.ethernet_tap_name(),
- ",script=no,downscript=no", vhost_net);
+ if (config_->logcat_mode() == "serial") {
+ qemu_cmd.AddParameter("-chardev");
+ qemu_cmd.AddParameter("file,id=charchannel0,path=", instance.logcat_path(),
+ ",append=on");
qemu_cmd.AddParameter("-device");
- qemu_cmd.AddParameter("virtio-net-pci-non-transitional,netdev=hostnet2,id=net2");
+ qemu_cmd.AddParameter("virtserialport,bus=virtio-serial0.0,nr=1,",
+ "chardev=charchannel0,id=channel0,name=cf-logcat");
}
- qemu_cmd.AddParameter("-device");
- qemu_cmd.AddParameter("qemu-xhci,id=xhci");
-
- qemu_cmd.AddParameter("-bios");
- qemu_cmd.AddParameter(config.bootloader());
-
- if (config.gdb_port() > 0) {
- qemu_cmd.AddParameter("-S");
+ if (config_->gdb_flag().size() > 0) {
qemu_cmd.AddParameter("-gdb");
- qemu_cmd.AddParameter("tcp::", config.gdb_port());
+ qemu_cmd.AddParameter(config_->gdb_flag());
}
+ qemu_cmd.AddParameter("-initrd");
+ qemu_cmd.AddParameter(config_->final_ramdisk_path());
+
+ qemu_cmd.AddParameter("-device");
+ qemu_cmd.AddParameter("vhost-vsock-pci,guest-cid=", instance.vsock_guest_cid());
+
LogAndSetEnv("QEMU_AUDIO_DRV", "none");
- std::vector<Command> ret;
+ std::vector<cvd::Command> ret;
ret.push_back(std::move(qemu_cmd));
return ret;
}
-} // namespace vm_manager
-} // namespace cuttlefish
-
+} // namespace vm_manager
diff --git a/host/libs/vm_manager/qemu_manager.h b/host/libs/vm_manager/qemu_manager.h
index 934a97692..4b048762c 100644
--- a/host/libs/vm_manager/qemu_manager.h
+++ b/host/libs/vm_manager/qemu_manager.h
@@ -22,26 +22,20 @@
#include "common/libs/fs/shared_fd.h"
-namespace cuttlefish {
namespace vm_manager {
// Starts a guest VM using the qemu command directly. It requires the host
// package to support the qemu-cli capability.
class QemuManager : public VmManager {
public:
- static std::string name() { return "qemu_cli"; }
+ static const std::string name();
+ static std::vector<std::string> ConfigureGpu(const std::string& gpu_mode);
+ static std::vector<std::string> ConfigureBootDevices();
- QemuManager(Arch arch) : VmManager(arch) {}
+ QemuManager(const vsoc::CuttlefishConfig* config);
virtual ~QemuManager() = default;
- bool IsSupported() override;
- std::vector<std::string> ConfigureGpuMode(const std::string&) override;
- std::string ConfigureBootDevices(int num_disks) override;
-
- std::vector<cuttlefish::Command> StartCommands(
- const CuttlefishConfig& config) override;
+ std::vector<cvd::Command> StartCommands() override;
};
-} // namespace vm_manager
-} // namespace cuttlefish
-
+} // namespace vm_manager
diff --git a/host/libs/vm_manager/vm_manager.cpp b/host/libs/vm_manager/vm_manager.cpp
index 8c2ef5745..ceea86524 100644
--- a/host/libs/vm_manager/vm_manager.cpp
+++ b/host/libs/vm_manager/vm_manager.cpp
@@ -16,51 +16,174 @@
#include "host/libs/vm_manager/vm_manager.h"
-#include <android-base/logging.h>
-
-#include <iomanip>
#include <memory>
+#include <android-base/logging.h>
+#include <sys/utsname.h>
+
+#include "common/libs/utils/users.h"
#include "host/libs/config/cuttlefish_config.h"
-#include "host/libs/vm_manager/crosvm_manager.h"
#include "host/libs/vm_manager/qemu_manager.h"
+#include "host/libs/vm_manager/crosvm_manager.h"
-namespace cuttlefish {
namespace vm_manager {
-std::unique_ptr<VmManager> GetVmManager(const std::string& name, Arch arch) {
- std::unique_ptr<VmManager> vmm;
- if (name == QemuManager::name()) {
- vmm.reset(new QemuManager(arch));
- } else if (name == CrosvmManager::name()) {
- vmm.reset(new CrosvmManager(arch));
+VmManager::VmManager(const vsoc::CuttlefishConfig* config)
+ : config_(config) {}
+
+namespace{
+template <typename T>
+VmManager* GetManagerSingleton(const vsoc::CuttlefishConfig* config) {
+ static std::shared_ptr<VmManager> vm_manager(new T(config));
+ return vm_manager.get();
+}
+}
+
+std::map<std::string, VmManager::VmManagerHelper>
+ VmManager::vm_manager_helpers_ = {
+ {
+ QemuManager::name(),
+ {
+ GetManagerSingleton<QemuManager>,
+ vsoc::HostSupportsQemuCli,
+ QemuManager::ConfigureGpu,
+ QemuManager::ConfigureBootDevices,
+ },
+ },
+ {
+ CrosvmManager::name(),
+ {
+ GetManagerSingleton<CrosvmManager>,
+ // Same as Qemu for the time being
+ vsoc::HostSupportsQemuCli,
+ CrosvmManager::ConfigureGpu,
+ CrosvmManager::ConfigureBootDevices,
+ }
+ }
+ };
+
+VmManager* VmManager::Get(const std::string& vm_manager_name,
+ const vsoc::CuttlefishConfig* config) {
+ if (VmManager::IsValidName(vm_manager_name)) {
+ return vm_manager_helpers_[vm_manager_name].builder(config);
}
- if (!vmm) {
- LOG(ERROR) << "Invalid VM manager: " << name;
+ LOG(ERROR) << "Requested invalid VmManager: " << vm_manager_name;
+ return nullptr;
+}
+
+bool VmManager::IsValidName(const std::string& name) {
+ return vm_manager_helpers_.count(name) > 0;
+}
+
+bool VmManager::IsVmManagerSupported(const std::string& name) {
+ return VmManager::IsValidName(name) &&
+ vm_manager_helpers_[name].support_checker();
+}
+
+std::vector<std::string> VmManager::ConfigureGpuMode(
+ const std::string& vmm_name, const std::string& gpu_mode) {
+ auto it = vm_manager_helpers_.find(vmm_name);
+ if (it == vm_manager_helpers_.end()) {
return {};
}
- if (!vmm->IsSupported()) {
- LOG(ERROR) << "VM manager " << name << " is not supported on this machine.";
+ return it->second.configure_gpu_mode(gpu_mode);
+}
+
+std::vector<std::string> VmManager::ConfigureBootDevices(
+ const std::string& vmm_name) {
+ auto it = vm_manager_helpers_.find(vmm_name);
+ if (it == vm_manager_helpers_.end()) {
return {};
}
- return vmm;
+ return it->second.configure_boot_devices();
}
-std::string ConfigureMultipleBootDevices(const std::string& pci_path,
- int pci_offset, int num_disks) {
- int num_boot_devices =
- (num_disks < VmManager::kDefaultNumBootDevices) ? num_disks : VmManager::kDefaultNumBootDevices;
- std::string boot_devices_prop = "androidboot.boot_devices=";
- for (int i = 0; i < num_boot_devices; i++) {
- std::stringstream stream;
- stream << std::setfill('0') << std::setw(2) << std::hex
- << pci_offset + i + VmManager::kDefaultNumHvcs + VmManager::kMaxDisks - num_disks;
- boot_devices_prop += pci_path + stream.str() + ".0,";
+std::vector<std::string> VmManager::GetValidNames() {
+ std::vector<std::string> ret = {};
+ for (const auto& key_val: vm_manager_helpers_) {
+ ret.push_back(key_val.first);
}
- boot_devices_prop.pop_back();
- return {boot_devices_prop};
+ return ret;
}
-} // namespace vm_manager
-} // namespace cuttlefish
+bool VmManager::UserInGroup(const std::string& group,
+ std::vector<std::string>* config_commands) {
+ if (!cvd::InGroup(group)) {
+ LOG(ERROR) << "User must be a member of " << group;
+ config_commands->push_back("# Add your user to the " + group + " group:");
+ config_commands->push_back("sudo usermod -aG " + group + " $USER");
+ return false;
+ }
+ return true;
+}
+
+std::pair<int,int> VmManager::GetLinuxVersion() {
+ struct utsname info;
+ if (!uname(&info)) {
+ char* digit = strtok(info.release, "+.-");
+ int major = atoi(digit);
+ if (digit) {
+ digit = strtok(NULL, "+.-");
+ int minor = atoi(digit);
+ return std::pair<int,int>{major, minor};
+ }
+ }
+ LOG(ERROR) << "Failed to detect Linux kernel version";
+ return invalid_linux_version;
+}
+
+bool VmManager::LinuxVersionAtLeast(std::vector<std::string>* config_commands,
+ const std::pair<int,int>& version,
+ int major, int minor) {
+ if (version.first > major ||
+ (version.first == major && version.second >= minor)) {
+ return true;
+ }
+
+ LOG(ERROR) << "Kernel version must be >=" << major << "." << minor
+ << ", have " << version.first << "." << version.second;
+ config_commands->push_back("# Please upgrade your kernel to >=" +
+ std::to_string(major) + "." +
+ std::to_string(minor));
+ return false;
+}
+
+bool VmManager::ValidateHostConfiguration(
+ std::vector<std::string>* config_commands) const {
+ // if we can't detect the kernel version, just fail
+ auto version = VmManager::GetLinuxVersion();
+ if (version == invalid_linux_version) {
+ return false;
+ }
+
+ // the check for cvdnetwork needs to happen even if the user is not in kvm, so
+ // we can't just say UserInGroup("kvm") && UserInGroup("cvdnetwork")
+ auto in_cvdnetwork = VmManager::UserInGroup("cvdnetwork", config_commands);
+
+ // if we're in the virtaccess group this is likely to be a CrOS environment.
+ auto is_cros = cvd::InGroup("virtaccess");
+ if (is_cros) {
+ // relax the minimum kernel requirement slightly, as chromeos-4.4 has the
+ // needed backports to enable vhost_vsock
+ auto linux_ver_4_4 =
+ VmManager::LinuxVersionAtLeast(config_commands, version, 4, 4);
+ return in_cvdnetwork && linux_ver_4_4;
+ } else {
+ // this is regular Linux, so use the Debian group name and be more
+ // conservative with the kernel version check.
+ auto in_kvm = VmManager::UserInGroup("kvm", config_commands);
+ auto linux_ver_4_8 =
+ VmManager::LinuxVersionAtLeast(config_commands, version, 4, 8);
+ return in_cvdnetwork && in_kvm && linux_ver_4_8;
+ }
+}
+
+void VmManager::WithFrontend(bool enabled) {
+ frontend_enabled_ = enabled;
+}
+
+void VmManager::WithKernelCommandLine(const std::string& kernel_cmdline) {
+ kernel_cmdline_ = kernel_cmdline;
+}
+} // namespace vm_manager
diff --git a/host/libs/vm_manager/vm_manager.h b/host/libs/vm_manager/vm_manager.h
index b538e8f29..a86218ccc 100644
--- a/host/libs/vm_manager/vm_manager.h
+++ b/host/libs/vm_manager/vm_manager.h
@@ -15,69 +15,75 @@
*/
#pragma once
+#include <map>
+#include <set>
#include <string>
+#include <utility>
#include <vector>
#include <common/libs/utils/subprocess.h>
#include <host/libs/config/cuttlefish_config.h>
-namespace cuttlefish {
namespace vm_manager {
-// Superclass of every guest VM manager.
+// Superclass of every guest VM manager. It provides a static getter that
+// returns the requested vm manager as a singleton.
class VmManager {
- protected:
- const Arch arch_;
-
public:
- // This is the number of HVC virtual console ports that should be configured
- // by the VmManager. Because crosvm currently allocates these ports as the
- // first PCI devices, and it does not control the allocation of PCI ID
- // assignments, the number of these ports affects the PCI paths for
- // subsequent PCI devices, and these paths are hard-coded in SEPolicy.
- // Fortunately, HVC virtual console ports can be set up to be "sink" devices,
- // so even if they are disabled and the guest isn't using them, they don't
- // need to consume host resources, except for the PCI ID. Use this trick to
- // keep the number of PCI IDs assigned constant for all flags/vm manager
- // combinations
- static const int kDefaultNumHvcs = 6;
-
- // This is the number of virtual disks (block devices) that should be
- // configured by the VmManager. Related to the description above regarding
- // HVC ports, this problem can also affect block devices (which are
- // enumerated second) if not all of the block devices are available. Unlike
- // HVC virtual console ports, block devices cannot be configured to be sinks,
- // so we once again leverage HVC virtual console ports to "bump up" the last
- // assigned virtual disk PCI ID (i.e. 2 disks = 7 hvcs, 1 disks = 8 hvcs)
- static const int kMaxDisks = 3;
+ // Returns the most suitable vm manager as a singleton. It may return nullptr
+ // if the requested vm manager is not supported by the current version of the
+ // host packages
+ static VmManager* Get(const std::string& vm_manager_name,
+ const vsoc::CuttlefishConfig* config);
+ static bool IsValidName(const std::string& name);
+ static std::vector<std::string> ConfigureGpuMode(
+ const std::string& vmm_name, const std::string& gpu_mode);
+ static std::vector<std::string> ConfigureBootDevices(
+ const std::string& vmm_name);
+ static bool IsVmManagerSupported(const std::string& name);
+ static std::vector<std::string> GetValidNames();
- // This is the number of virtual disks that contribute to the named partition
- // list (/dev/block/by-name/*) under Android. The partitions names from
- // multiple disks *must not* collide. Normally we have one set of partitions
- // from the powerwashed disk (operating system disk) and another set from
- // the persistent disk
- static const int kDefaultNumBootDevices = 2;
-
- VmManager(Arch arch) : arch_(arch) {}
virtual ~VmManager() = default;
- virtual bool IsSupported() = 0;
- virtual std::vector<std::string> ConfigureGpuMode(const std::string&) = 0;
- virtual std::string ConfigureBootDevices(int num_disks) = 0;
+ virtual void WithFrontend(bool);
+ virtual void WithKernelCommandLine(const std::string&);
// Starts the VMM. It will usually build a command and pass it to the
// command_starter function, although it may start more than one. The
// command_starter function allows to customize the way vmm commands are
// started/tracked/etc.
- virtual std::vector<cuttlefish::Command> StartCommands(
- const CuttlefishConfig& config) = 0;
-};
+ virtual std::vector<cvd::Command> StartCommands() = 0;
-std::unique_ptr<VmManager> GetVmManager(const std::string&, Arch arch);
+ virtual bool ValidateHostConfiguration(
+ std::vector<std::string>* config_commands) const;
-std::string ConfigureMultipleBootDevices(const std::string& pci_path, int pci_offset,
- int num_disks);
+ protected:
+ static bool UserInGroup(const std::string& group,
+ std::vector<std::string>* config_commands);
+ static constexpr std::pair<int,int> invalid_linux_version =
+ std::pair<int,int>();
+ static std::pair<int,int> GetLinuxVersion();
+ static bool LinuxVersionAtLeast(std::vector<std::string>* config_commands,
+ const std::pair<int,int>& version,
+ int major, int minor);
+
+ const vsoc::CuttlefishConfig* config_;
+ VmManager(const vsoc::CuttlefishConfig* config);
-} // namespace vm_manager
-} // namespace cuttlefish
+ bool frontend_enabled_;
+ std::string kernel_cmdline_;
+
+ private:
+ struct VmManagerHelper {
+ // The singleton implementation
+ std::function<VmManager*(const vsoc::CuttlefishConfig*)> builder;
+ // Whether the host packages support this vm manager
+ std::function<bool()> support_checker;
+ std::function<std::vector<std::string>(const std::string&)> configure_gpu_mode;
+ std::function<std::vector<std::string>()> configure_boot_devices;
+ };
+ // Asociates a vm manager helper to every valid vm manager name
+ static std::map<std::string, VmManagerHelper> vm_manager_helpers_;
+};
+} // namespace vm_manager
diff --git a/host/libs/wayland/Android.bp b/host/libs/wayland/Android.bp
index 4be6528ce..6123d6770 100644
--- a/host/libs/wayland/Android.bp
+++ b/host/libs/wayland/Android.bp
@@ -13,11 +13,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-cc_library_static {
+cc_library_host_static {
name: "libcuttlefish_wayland_server",
srcs: [
"wayland_compositor.cpp",
@@ -27,7 +23,6 @@ cc_library_static {
"wayland_server.cpp",
"wayland_subcompositor.cpp",
"wayland_surface.cpp",
- "wayland_surfaces.cpp",
],
shared_libs: [
"libbase",
@@ -40,5 +35,6 @@ cc_library_static {
"libwayland_server",
"libwayland_extension_server_protocols",
],
- defaults: ["cuttlefish_host"],
+ defaults: ["cuttlefish_host_only"],
}
+
diff --git a/host/libs/wayland/wayland_compositor.cpp b/host/libs/wayland/wayland_compositor.cpp
index 61790926c..96fdd6def 100644
--- a/host/libs/wayland/wayland_compositor.cpp
+++ b/host/libs/wayland/wayland_compositor.cpp
@@ -21,7 +21,6 @@
#include <wayland-server-core.h>
#include <wayland-server-protocol.h>
-#include "host/libs/wayland/wayland_surface.h"
#include "host/libs/wayland/wayland_utils.h"
namespace wayland {
@@ -191,12 +190,7 @@ void compositor_create_surface(wl_client* client,
<< " compositor=" << compositor
<< " id=" << id;
- // Wayland seems to use a single global id space for all objects.
- static std::atomic<std::uint32_t> sNextDisplayId{0};
- uint32_t display_id = sNextDisplayId++;
-
- Surfaces* surfaces = GetUserData<Surfaces>(compositor);
- Surface* surface = surfaces->GetOrCreateSurface(display_id);
+ Surface* surface = GetUserData<Surface>(compositor);
wl_resource* surface_resource = wl_resource_create(
client, &wl_surface_interface, wl_resource_get_version(compositor), id);
@@ -245,9 +239,9 @@ void bind_compositor(wl_client* client,
} // namespace
-void BindCompositorInterface(wl_display* display, Surfaces* surfaces) {
+void BindCompositorInterface(wl_display* display, Surface* surface) {
wl_global_create(display, &wl_compositor_interface, kCompositorVersion,
- surfaces, bind_compositor);
+ surface, bind_compositor);
}
} // namespace wayland
diff --git a/host/libs/wayland/wayland_compositor.h b/host/libs/wayland/wayland_compositor.h
index 18f0d7e05..5054c40df 100644
--- a/host/libs/wayland/wayland_compositor.h
+++ b/host/libs/wayland/wayland_compositor.h
@@ -21,11 +21,11 @@
#include <wayland-server-core.h>
-#include "host/libs/wayland/wayland_surfaces.h"
+#include "host/libs/wayland/wayland_surface.h"
namespace wayland {
// Binds the compositor interface to the given wayland server.
-void BindCompositorInterface(wl_display* display, Surfaces* surfaces);
+void BindCompositorInterface(wl_display* display, Surface* surface);
} // namespace wayland \ No newline at end of file
diff --git a/host/libs/wayland/wayland_server.cpp b/host/libs/wayland/wayland_server.cpp
index 4dc4b8819..699fda24c 100644
--- a/host/libs/wayland/wayland_server.cpp
+++ b/host/libs/wayland/wayland_server.cpp
@@ -35,7 +35,7 @@ namespace internal {
struct WaylandServerState {
struct wl_display* display_ = nullptr;
- Surfaces surfaces_;
+ Surface surface_;
};
} // namespace internal
@@ -78,7 +78,7 @@ void WaylandServer::ServerLoop(int fd) {
wl_display_init_shm(server_state_->display_);
- BindCompositorInterface(server_state_->display_, &server_state_->surfaces_);
+ BindCompositorInterface(server_state_->display_, &server_state_->surface_);
BindDmabufInterface(server_state_->display_);
BindSubcompositorInterface(server_state_->display_);
BindSeatInterface(server_state_->display_);
@@ -94,8 +94,20 @@ void WaylandServer::ServerLoop(int fd) {
wl_display_destroy(server_state_->display_);
}
-void WaylandServer::OnNextFrame(const Surfaces::FrameCallback& callback) {
- server_state_->surfaces_.OnNextFrame(callback);
+std::future<void> WaylandServer::OnFrameAfter(
+ uint32_t frame_number,
+ const FrameCallback& frame_callback) {
+ // Wraps the given callback in a callback that can be waited on using
+ // std::future.
+ Surface::FrameCallbackPackaged packaged([&frame_callback](std::uint32_t frame_number,
+ std::uint8_t* frame_pixels){
+ frame_callback(frame_number, frame_pixels);
+ });
+
+ std::future<void> frame_callback_complete = packaged.get_future();
+
+ server_state_->surface_.OnFrameAfter(frame_number, std::move(packaged));
+ return frame_callback_complete;
}
-} // namespace wayland
+} // namespace wayland \ No newline at end of file
diff --git a/host/libs/wayland/wayland_server.h b/host/libs/wayland/wayland_server.h
index 3149481d7..e73d74a20 100644
--- a/host/libs/wayland/wayland_server.h
+++ b/host/libs/wayland/wayland_server.h
@@ -24,14 +24,15 @@
#include <string>
#include <thread>
-#include "host/libs/wayland/wayland_surfaces.h"
-
namespace wayland {
namespace internal {
struct WaylandServerState;
} // namespace internal
+using FrameCallback = std::function<void(std::uint32_t /*frame_number*/,
+ std::uint8_t* /*frame_pixels*/)>;
+
// A Wayland compositing server that provides an interface for receiving frame
// updates from a connected client.
class WaylandServer {
@@ -48,10 +49,12 @@ class WaylandServer {
WaylandServer(WaylandServer&& rhs) = delete;
WaylandServer& operator=(WaylandServer&& rhs) = delete;
- // Blocks until the given callback is run on the next frame available.
- void OnNextFrame(const Surfaces::FrameCallback& callback);
+ // Registers a callback to run on the next frame available after the given
+ // frame number.
+ std::future<void> OnFrameAfter(std::uint32_t frame_number,
+ const FrameCallback& frame_callback);
- private:
+ private:
void ServerLoop(int wayland_socket_fd);
bool server_ready_ = false;
diff --git a/host/libs/wayland/wayland_surface.cpp b/host/libs/wayland/wayland_surface.cpp
index e9abece9a..eb4b4010c 100644
--- a/host/libs/wayland/wayland_surface.cpp
+++ b/host/libs/wayland/wayland_surface.cpp
@@ -19,13 +19,8 @@
#include <android-base/logging.h>
#include <wayland-server-protocol.h>
-#include "host/libs/wayland/wayland_surfaces.h"
-
namespace wayland {
-Surface::Surface(std::uint32_t display_number, Surfaces& surfaces)
- : display_number_(display_number), surfaces_(surfaces) {}
-
void Surface::SetRegion(const Region& region) {
std::unique_lock<std::mutex> lock(state_mutex_);
state_.region = region;
@@ -41,26 +36,29 @@ void Surface::Commit() {
state_.current_buffer = state_.pending_buffer;
state_.pending_buffer = nullptr;
- if (state_.current_buffer == nullptr) {
- return;
- }
-
- struct wl_shm_buffer* shm_buffer = wl_shm_buffer_get(state_.current_buffer);
- CHECK(shm_buffer != nullptr);
+ {
+ std::unique_lock<std::mutex> lock(callback_mutex_);
+ if (callback_ && callback_->frame_number < state_.current_frame_number) {
+ struct wl_shm_buffer* shm_buffer =
+ wl_shm_buffer_get(state_.current_buffer);
+ CHECK(shm_buffer != nullptr);
- wl_shm_buffer_begin_access(shm_buffer);
+ wl_shm_buffer_begin_access(shm_buffer);
- const int32_t buffer_w = wl_shm_buffer_get_width(shm_buffer);
- CHECK(buffer_w == state_.region.w);
- const int32_t buffer_h = wl_shm_buffer_get_height(shm_buffer);
- CHECK(buffer_h == state_.region.h);
+ const int32_t buffer_w = wl_shm_buffer_get_width(shm_buffer);
+ CHECK(buffer_w == state_.region.w);
+ const int32_t buffer_h = wl_shm_buffer_get_height(shm_buffer);
+ CHECK(buffer_h == state_.region.h);
- uint8_t* buffer_pixels =
- reinterpret_cast<uint8_t*>(wl_shm_buffer_get_data(shm_buffer));
+ uint8_t* buffer_pixels =
+ reinterpret_cast<uint8_t*>(wl_shm_buffer_get_data(shm_buffer));
- surfaces_.HandleSurfaceFrame(display_number_, buffer_pixels);
+ callback_->frame_callback(state_.current_frame_number, buffer_pixels);
+ callback_.reset();
- wl_shm_buffer_end_access(shm_buffer);
+ wl_shm_buffer_end_access(shm_buffer);
+ }
+ }
wl_buffer_send_release(state_.current_buffer);
wl_client_flush(wl_resource_get_client(state_.current_buffer));
@@ -69,4 +67,11 @@ void Surface::Commit() {
state_.current_frame_number++;
}
+void Surface::OnFrameAfter(uint32_t frame_number,
+ FrameCallbackPackaged frame_callback) {
+ std::unique_lock<std::mutex> lock(callback_mutex_);
+ callback_.emplace(PendingFrameCallback{frame_number,
+ std::move(frame_callback)});
+}
+
} // namespace wayland \ No newline at end of file
diff --git a/host/libs/wayland/wayland_surface.h b/host/libs/wayland/wayland_surface.h
index fcf2345d0..e0d0a12b9 100644
--- a/host/libs/wayland/wayland_surface.h
+++ b/host/libs/wayland/wayland_surface.h
@@ -17,19 +17,19 @@
#pragma once
+#include <optional>
#include <stdint.h>
-#include <mutex>
+#include <thread>
+#include <future>
#include <wayland-server-core.h>
namespace wayland {
-class Surfaces;
-
// Tracks the buffer associated with a Wayland surface.
class Surface {
public:
- Surface(std::uint32_t display_number, Surfaces& surfaces);
+ Surface() = default;
virtual ~Surface() = default;
Surface(const Surface& rhs) = delete;
@@ -53,10 +53,16 @@ class Surface {
// Commits the pending frame state.
void Commit();
- private:
- std::uint32_t display_number_;
- Surfaces& surfaces_;
+ using FrameCallbackPackaged =
+ std::packaged_task<void(std::uint32_t /*frame_number*/,
+ std::uint8_t* /*frame_pixels*/)>;
+ // Registers a callback that should be invoked on the first frame after
+ // the given frame number.
+ void OnFrameAfter(uint32_t frame_number,
+ FrameCallbackPackaged frame_callback);
+
+ private:
struct State {
uint32_t current_frame_number = 0;
@@ -72,6 +78,15 @@ class Surface {
std::mutex state_mutex_;
State state_;
+
+ struct PendingFrameCallback {
+ uint32_t frame_number;
+
+ FrameCallbackPackaged frame_callback;
+ };
+
+ std::mutex callback_mutex_;
+ std::optional<PendingFrameCallback> callback_;
};
-} // namespace wayland
+} // namespace wayland \ No newline at end of file
diff --git a/host/libs/wayland/wayland_surfaces.cpp b/host/libs/wayland/wayland_surfaces.cpp
deleted file mode 100644
index 7096574e2..000000000
--- a/host/libs/wayland/wayland_surfaces.cpp
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2020 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 "host/libs/wayland/wayland_surfaces.h"
-
-#include <android-base/logging.h>
-#include <wayland-server-protocol.h>
-
-#include "host/libs/wayland/wayland_surface.h"
-
-namespace wayland {
-
-Surface* Surfaces::GetOrCreateSurface(std::uint32_t id) {
- std::unique_lock<std::mutex> lock(surfaces_mutex_);
-
- auto [it, inserted] = surfaces_.try_emplace(id, nullptr);
-
- std::unique_ptr<Surface>& surface_ptr = it->second;
- if (inserted) {
- surface_ptr.reset(new Surface(id, *this));
- }
- return surface_ptr.get();
-}
-
-void Surfaces::OnNextFrame(const FrameCallback& frame_callback) {
- // Wraps the given callback in a std::package_task that can be waited upon
- // for completion.
- Surfaces::FrameCallbackPackaged frame_callback_packaged(
- [&frame_callback](std::uint32_t display_number,
- std::uint8_t* frame_pixels) {
- frame_callback(display_number, frame_pixels);
- });
-
- {
- std::unique_lock<std::mutex> lock(callback_mutex_);
- callback_.emplace(&frame_callback_packaged);
- }
-
- // Blocks until the frame_callback_packaged was called.
- frame_callback_packaged.get_future().get();
-}
-
-void Surfaces::HandleSurfaceFrame(std::uint32_t display_number,
- std::uint8_t* frame_bytes) {
- std::unique_lock<std::mutex> lock(callback_mutex_);
- if (callback_) {
- (*callback_.value())(display_number, frame_bytes);
- callback_.reset();
- }
-}
-
-} // namespace wayland \ No newline at end of file
diff --git a/host/libs/wayland/wayland_surfaces.h b/host/libs/wayland/wayland_surfaces.h
deleted file mode 100644
index ec67ca448..000000000
--- a/host/libs/wayland/wayland_surfaces.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2020 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 <future>
-#include <memory>
-#include <mutex>
-#include <optional>
-#include <thread>
-#include <unordered_map>
-
-namespace wayland {
-
-class Surface;
-
-class Surfaces {
- public:
- Surfaces() = default;
- virtual ~Surfaces() = default;
-
- Surfaces(const Surfaces& rhs) = delete;
- Surfaces& operator=(const Surfaces& rhs) = delete;
-
- Surfaces(Surfaces&& rhs) = delete;
- Surfaces& operator=(Surfaces&& rhs) = delete;
-
- Surface* GetOrCreateSurface(std::uint32_t id);
-
- using FrameCallback = std::function<void(std::uint32_t /*display_number*/,
- std::uint8_t* /*frame_pixels*/)>;
-
- // Blocking
- void OnNextFrame(const FrameCallback& callback);
-
- private:
- friend class Surface;
- void HandleSurfaceFrame(std::uint32_t display_number,
- std::uint8_t* frame_bytes);
-
- std::mutex surfaces_mutex_;
- std::unordered_map<std::uint32_t, std::unique_ptr<Surface>> surfaces_;
-
- using FrameCallbackPackaged = std::packaged_task<void(
- std::uint32_t /*display_number*/, std::uint8_t* /*frame_bytes*/)>;
-
- std::mutex callback_mutex_;
- std::optional<FrameCallbackPackaged*> callback_;
-};
-
-} // namespace wayland
diff --git a/host/libs/websocket/websocket_handler.cpp b/host/libs/websocket/websocket_handler.cpp
deleted file mode 100644
index 9d6f6361b..000000000
--- a/host/libs/websocket/websocket_handler.cpp
+++ /dev/null
@@ -1,70 +0,0 @@
-//
-// Copyright (C) 2020 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 "host/libs/websocket/websocket_handler.h"
-
-#include <android-base/logging.h>
-#include <libwebsockets.h>
-
-namespace cuttlefish {
-
-WebSocketHandler::WebSocketHandler(struct lws* wsi) : wsi_(wsi) {}
-
-void WebSocketHandler::EnqueueMessage(const uint8_t* data, size_t len,
- bool binary) {
- std::vector<uint8_t> buffer(LWS_PRE + len, 0);
- std::copy(data, data + len, buffer.begin() + LWS_PRE);
- buffer_queue_.emplace_front(std::move(buffer), binary);
- lws_callback_on_writable(wsi_);
-}
-
-// Attempts to write what's left on a websocket buffer to the websocket,
-// updating the buffer.
-void WebSocketHandler::WriteWsBuffer(WebSocketHandler::WsBuffer& ws_buffer) {
- auto len = ws_buffer.data.size() - LWS_PRE;
- auto flags = lws_write_ws_flags(
- ws_buffer.binary ? LWS_WRITE_BINARY : LWS_WRITE_TEXT, true, true);
- auto res = lws_write(wsi_, &ws_buffer.data[LWS_PRE], len,
- static_cast<enum lws_write_protocol>(flags));
- // lws_write will write all bytes of the provided buffer or enqueue the ones
- // it couldn't write for later, but it guarantees it will consume the entire
- // buffer, so we only need to check for error.
- if (res < 0) {
- // This shouldn't happen since this function is called in response to a
- // LWS_CALLBACK_SERVER_WRITEABLE call.
- LOG(FATAL) << "Failed to write data on the websocket";
- }
-}
-
-bool WebSocketHandler::OnWritable() {
- if (buffer_queue_.empty()) {
- return close_;
- }
- WriteWsBuffer(buffer_queue_.back());
- buffer_queue_.pop_back();
-
- if (!buffer_queue_.empty()) {
- lws_callback_on_writable(wsi_);
- }
- // Only close if there are no more queued writes
- return buffer_queue_.empty() && close_;
-}
-
-void WebSocketHandler::Close() {
- close_ = true;
- lws_callback_on_writable(wsi_);
-}
-
-} // namespace cuttlefish
diff --git a/host/libs/websocket/websocket_handler.h b/host/libs/websocket/websocket_handler.h
deleted file mode 100644
index 45b51faf4..000000000
--- a/host/libs/websocket/websocket_handler.h
+++ /dev/null
@@ -1,66 +0,0 @@
-//
-// Copyright (C) 2020 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 <deque>
-#include <vector>
-
-struct lws;
-
-namespace cuttlefish {
-
-class WebSocketHandler {
- public:
- WebSocketHandler(struct lws* wsi);
- virtual ~WebSocketHandler() = default;
-
- virtual void OnReceive(const uint8_t* msg, size_t len, bool binary) = 0;
- virtual void OnReceive(const uint8_t* msg, size_t len, bool binary,
- [[maybe_unused]] bool is_final) {
- OnReceive(msg, len, binary);
- }
- virtual void OnConnected() = 0;
- virtual void OnClosed() = 0;
-
- void EnqueueMessage(const uint8_t* data, size_t len, bool binary = false);
- void EnqueueMessage(const char* data, size_t len, bool binary = false) {
- EnqueueMessage(reinterpret_cast<const uint8_t*>(data), len, binary);
- }
- void Close();
- bool OnWritable();
-
- private:
- struct WsBuffer {
- WsBuffer(std::vector<uint8_t> data, bool binary)
- : data(std::move(data)), binary(binary) {}
- std::vector<uint8_t> data;
- bool binary;
- };
-
- void WriteWsBuffer(WsBuffer& ws_buffer);
-
- struct lws* wsi_;
- bool close_ = false;
- std::deque<WsBuffer> buffer_queue_;
-};
-
-class WebSocketHandlerFactory {
- public:
- virtual ~WebSocketHandlerFactory() = default;
- virtual std::shared_ptr<WebSocketHandler> Build(struct lws* wsi) = 0;
-};
-
-} // namespace cuttlefish
diff --git a/host/libs/websocket/websocket_server.cpp b/host/libs/websocket/websocket_server.cpp
deleted file mode 100644
index cdfcba23e..000000000
--- a/host/libs/websocket/websocket_server.cpp
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * Copyright (C) 2020 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 <host/libs/websocket/websocket_server.h>
-
-#include <string>
-#include <unordered_map>
-
-#include <android-base/logging.h>
-#include <libwebsockets.h>
-
-#include <host/libs/websocket/websocket_handler.h>
-
-namespace cuttlefish {
-WebSocketServer::WebSocketServer(
- const char* protocol_name,
- const std::string &certs_dir,
- const std::string &assets_dir,
- int server_port) {
- std::string cert_file = certs_dir + "/server.crt";
- std::string key_file = certs_dir + "/server.key";
-
- retry_ = {
- .secs_since_valid_ping = 3,
- .secs_since_valid_hangup = 10,
- };
-
- struct lws_protocols protocols[] = {
- {protocol_name, ServerCallback, 4096, 0, 0, nullptr, 0},
- {nullptr, nullptr, 0, 0, 0, nullptr, 0}};
-
- mount_ = {
- .mount_next = nullptr,
- .mountpoint = "/",
- .mountpoint_len = 1,
- .origin = assets_dir.c_str(),
- .def = "index.html",
- .protocol = nullptr,
- .cgienv = nullptr,
- .extra_mimetypes = nullptr,
- .interpret = nullptr,
- .cgi_timeout = 0,
- .cache_max_age = 0,
- .auth_mask = 0,
- .cache_reusable = 0,
- .cache_revalidate = 0,
- .cache_intermediaries = 0,
- .origin_protocol = LWSMPRO_FILE, // files in a dir
- .basic_auth_login_file = nullptr,
- };
-
- struct lws_context_creation_info info;
- headers_ = {NULL, NULL,
- "content-security-policy:",
- "default-src 'self'; "
- "style-src 'self' https://fonts.googleapis.com/; "
- "font-src https://fonts.gstatic.com/; "};
-
- memset(&info, 0, sizeof info);
- info.port = server_port;
- info.mounts = &mount_;
- info.protocols = protocols;
- info.vhost_name = "localhost";
- info.ws_ping_pong_interval = 10;
- info.headers = &headers_;
- info.options |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
- info.ssl_cert_filepath = cert_file.c_str();
- info.ssl_private_key_filepath = key_file.c_str();
- info.retry_and_idle_policy = &retry_;
-
- context_ = lws_create_context(&info);
- if (!context_) {
- LOG(FATAL) << "Failed to create websocket context";
- }
-}
-
-void WebSocketServer::RegisterHandlerFactory(
- const std::string &path,
- std::unique_ptr<WebSocketHandlerFactory> handler_factory_p) {
- handler_factories_[path] = std::move(handler_factory_p);
-}
-
-void WebSocketServer::Serve() {
- int n = 0;
- while (n >= 0) {
- n = lws_service(context_, 0);
- }
- lws_context_destroy(context_);
-}
-
-std::unordered_map<struct lws*, std::shared_ptr<WebSocketHandler>> WebSocketServer::handlers_ = {};
-std::unordered_map<std::string, std::unique_ptr<WebSocketHandlerFactory>>
- WebSocketServer::handler_factories_ = {};
-
-std::string WebSocketServer::GetPath(struct lws* wsi) {
- auto len = lws_hdr_total_length(wsi, WSI_TOKEN_GET_URI);
- std::string path(len + 1, '\0');
- auto ret = lws_hdr_copy(wsi, path.data(), path.size(), WSI_TOKEN_GET_URI);
- if (ret <= 0) {
- len = lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_COLON_PATH);
- path.resize(len + 1, '\0');
- ret = lws_hdr_copy(wsi, path.data(), path.size(), WSI_TOKEN_HTTP_COLON_PATH);
- }
- if (ret < 0) {
- LOG(FATAL) << "Something went wrong getting the path";
- }
- path.resize(len);
- return path;
-}
-
-int WebSocketServer::ServerCallback(struct lws* wsi, enum lws_callback_reasons reason,
- void* user, void* in, size_t len) {
- switch (reason) {
- case LWS_CALLBACK_ESTABLISHED: {
- auto path = GetPath(wsi);
- auto handler = InstantiateHandler(path, wsi);
- if (!handler) {
- // This message came on an unexpected uri, close the connection.
- lws_close_reason(wsi, LWS_CLOSE_STATUS_NOSTATUS, (uint8_t*)"404", 3);
- return -1;
- }
- handlers_[wsi] = handler;
- handler->OnConnected();
- break;
- }
- case LWS_CALLBACK_CLOSED: {
- auto handler = handlers_[wsi];
- if (handler) {
- handler->OnClosed();
- handlers_.erase(wsi);
- }
- break;
- }
- case LWS_CALLBACK_SERVER_WRITEABLE: {
- auto handler = handlers_[wsi];
- if (handler) {
- auto should_close = handler->OnWritable();
- if (should_close) {
- lws_close_reason(wsi, LWS_CLOSE_STATUS_NORMAL, nullptr, 0);
- return 1;
- }
- } else {
- LOG(WARNING) << "Unknown wsi became writable";
- return -1;
- }
- break;
- }
- case LWS_CALLBACK_RECEIVE: {
- auto handler = handlers_[wsi];
- if (handler) {
- bool is_final = (lws_remaining_packet_payload(wsi) == 0) &&
- lws_is_final_fragment(wsi);
- handler->OnReceive(reinterpret_cast<const uint8_t*>(in), len,
- lws_frame_is_binary(wsi), is_final);
- } else {
- LOG(WARNING) << "Unkwnown wsi sent data";
- }
- break;
- }
- default:
- return lws_callback_http_dummy(wsi, reason, user, in, len);
- }
- return 0;
-}
-
-std::shared_ptr<WebSocketHandler> WebSocketServer::InstantiateHandler(
- const std::string& uri_path, struct lws* wsi) {
- auto it = handler_factories_.find(uri_path);
- if (it == handler_factories_.end()) {
- LOG(ERROR) << "Wrong path provided in URI: " << uri_path;
- return nullptr;
- } else {
- LOG(INFO) << "Creating handler for " << uri_path;
- return it->second->Build(wsi);
- }
-}
-
-} // namespace cuttlefish
diff --git a/host/libs/websocket/websocket_server.h b/host/libs/websocket/websocket_server.h
deleted file mode 100644
index 0695b3be1..000000000
--- a/host/libs/websocket/websocket_server.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2020 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 <unordered_map>
-
-#include <android-base/logging.h>
-#include <libwebsockets.h>
-
-#include <host/libs/websocket/websocket_handler.h>
-
-namespace cuttlefish {
-class WebSocketServer {
- public:
- WebSocketServer(
- const char* protocol_name,
- const std::string &certs_dir,
- const std::string &assets_dir,
- int port);
- ~WebSocketServer() = default;
-
- void RegisterHandlerFactory(
- const std::string &path,
- std::unique_ptr<WebSocketHandlerFactory> handler_factory_p);
- void Serve();
-
-
- private:
- static std::unordered_map<struct lws*, std::shared_ptr<WebSocketHandler>> handlers_;
- static std::unordered_map<std::string, std::unique_ptr<WebSocketHandlerFactory>>
- handler_factories_;
-
- static std::string GetPath(struct lws* wsi);
- static int ServerCallback(struct lws* wsi, enum lws_callback_reasons reason,
- void* user, void* in, size_t len);
- static std::shared_ptr<WebSocketHandler> InstantiateHandler(
- const std::string& uri_path, struct lws* wsi);
-
- struct lws_context* context_;
- struct lws_http_mount mount_;
- struct lws_protocol_vhost_options headers_;
- lws_retry_bo_t retry_;
-};
-
-} // namespace cuttlefish
diff --git a/host_package.mk b/host_package.mk
index bd6b51f42..7d8c41bc9 100644
--- a/host_package.mk
+++ b/host_package.mk
@@ -1,17 +1,131 @@
-cvd_host_packages := $(SOONG_HOST_OUT)/cvd-host_package.tar.gz
-ifeq ($(HOST_CROSS_OS)_$(HOST_CROSS_ARCH),linux_bionic_arm64)
- cvd_host_packages += $(SOONG_OUT_DIR)/host/$(HOST_CROSS_OS)-$(HOST_CROSS_ARCH)/cvd-host_package.tar.gz
-endif
+LOCAL_PATH := $(call my-dir)
+
+cvd_host_package_tar := $(HOST_OUT)/cvd-host_package.tar.gz
.PHONY: hosttar
-hosttar: $(cvd_host_packages)
+hosttar: $(cvd_host_package_tar)
# Build this by default when a developer types make
-droidcore: $(cvd_host_packages)
+droidcore: $(cvd_host_package_tar)
+
+# Build and store them on the build server.
+$(call dist-for-goals, dist_files, $(cvd_host_package_tar))
+
+bin_path := $(notdir $(HOST_OUT_EXECUTABLES))
+lib_path := $(notdir $(HOST_OUT_SHARED_LIBRARIES))
+tests_path := $(notdir $(HOST_OUT_NATIVE_TESTS))
+webrtc_files_path := usr/share/webrtc
+
+cvd_host_executables := \
+ adb \
+ adbshell \
+ launch_cvd \
+ lpmake \
+ lpunpack \
+ socket_vsock_proxy \
+ adb_connector \
+ stop_cvd \
+ vnc_server \
+ cf_bpttool \
+ kernel_log_monitor \
+ extract-vmlinux \
+ crosvm \
+ aarch64-linux-gnu/crosvm \
+ aarch64-linux-gnu/libepoxy.so.0 \
+ aarch64-linux-gnu/libgbm.so.1 \
+ aarch64-linux-gnu/libminijail.so \
+ aarch64-linux-gnu/libvirglrenderer.so.1 \
+ x86_64-linux-gnu/crosvm \
+ x86_64-linux-gnu/libepoxy.so.0 \
+ x86_64-linux-gnu/libgbm.so.1 \
+ x86_64-linux-gnu/libminijail.so \
+ x86_64-linux-gnu/libvirglrenderer.so.1 \
+ x86_64-linux-gnu/libc++.so.1 \
+ x86_64-linux-gnu/libandroid-emu-shared.so \
+ x86_64-linux-gnu/libemugl_common.so \
+ x86_64-linux-gnu/libOpenglRender.so \
+ x86_64-linux-gnu/libgfxstream_backend.so \
+ logcat_receiver \
+ config_server \
+ tombstone_receiver \
+ console_forwarder \
+ assemble_cvd \
+ run_cvd \
+ cvd_status \
+ webRTC \
+ fsck.f2fs \
+ resize.f2fs \
+ make_f2fs \
+ tapsetiff \
+ newfs_msdos \
+ log_tee \
+
+ifneq ($(wildcard device/google/trout),)
+ cvd_host_executables += android.hardware.automotive.vehicle@2.0-virtualization-grpc-server
+endif
+
+cvd_host_tests := \
+ monotonic_time_test \
+ cuttlefish_net_tests \
+
+cvd_host_shared_libraries := \
+ libbase.so \
+ libcutils.so \
+ libcuttlefish_fs.so \
+ libcuttlefish_utils.so \
+ cuttlefish_tcp_socket.so \
+ cuttlefish_net.so \
+ liblog.so \
+ libnl.so \
+ libc++.so \
+ liblp.so \
+ libsparse-host.so \
+ libcrypto-host.so \
+ libcrypto_utils.so \
+ libext4_utils.so \
+ libz-host.so \
+ libicuuc-host.so \
+ libicui18n-host.so \
+ libandroidicu-host.so \
+ libcuttlefish_device_config.so \
+ cdisk_spec.so \
+ libprotobuf-cpp-full.so \
+ libziparchive.so \
+ libvpx.so \
+ libssl-host.so \
+ libopus.so \
+ libyuv.so \
+ libjpeg.so \
+ libhidlbase.so \
+ libutils.so \
+ libjsoncpp.so \
+ libgrpc++.so \
+ android.hardware.automotive.vehicle@2.0.so \
+
+webrtc_assets := \
+ index.html \
+ style.css \
+ js/logcat.js \
+ js/receive.js \
+ js/viewpane.js \
+
+webrtc_certs := \
+ server.crt \
+ server.key \
+ server.p12 \
+ trusted.pem \
+
+cvd_host_webrtc_files := \
+ $(addprefix assets/,$(webrtc_assets)) \
+ $(addprefix certs/,$(webrtc_certs)) \
-# Dist
-# Note that only the last package is dist'ed. It would be from x86 in case of cf_x86_phone,
-# and from arm64 in case of cf_arm64_phone.
-$(call dist-for-goals, dist_files,$(word $(words $(cvd_host_packages)), $(cvd_host_packages)))
+cvd_host_package_files := \
+ $(addprefix $(bin_path)/,$(cvd_host_executables)) \
+ $(addprefix $(lib_path)/,$(cvd_host_shared_libraries)) \
+ $(foreach test,$(cvd_host_tests), ${tests_path}/$(test)/$(test)) \
+ $(addprefix $(webrtc_files_path)/,$(cvd_host_webrtc_files)) \
-cvd_host_packages :=
+$(cvd_host_package_tar): PRIVATE_FILES := $(cvd_host_package_files)
+$(cvd_host_package_tar): $(addprefix $(HOST_OUT)/,$(cvd_host_package_files))
+ $(hide) rm -rf $@ && tar Scfz $@.tmp -C $(HOST_OUT) $(PRIVATE_FILES)
+ $(hide) mv $@.tmp $@
diff --git a/recovery/recovery_ui.cpp b/recovery/recovery_ui.cpp
deleted file mode 100644
index 217542ebf..000000000
--- a/recovery/recovery_ui.cpp
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2020 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 <recovery_ui/ethernet_device.h>
-#include <recovery_ui/ethernet_ui.h>
-
-class CuttlefishRecoveryUI : public EthernetRecoveryUI {
- public:
- bool IsUsbConnected() override {
- return true;
- }
-};
-
-Device* make_device() {
- return new EthernetDevice(new CuttlefishRecoveryUI);
-}
diff --git a/required_images b/required_images
deleted file mode 100644
index 6f5c1800b..000000000
--- a/required_images
+++ /dev/null
@@ -1,7 +0,0 @@
-boot.img
-bootloader
-super.img
-userdata.img
-vbmeta.img
-vbmeta_system.img
-vendor_boot.img
diff --git a/rustfmt.toml b/rustfmt.toml
deleted file mode 120000
index 475ba8fde..000000000
--- a/rustfmt.toml
+++ /dev/null
@@ -1 +0,0 @@
-../../../build/soong/scripts/rustfmt.toml \ No newline at end of file
diff --git a/guest/Android.mk b/shared/Android.mk
index 428f4b5e5..c605e76de 100644
--- a/guest/Android.mk
+++ b/shared/Android.mk
@@ -1,4 +1,5 @@
-# Copyright (C) 2021 The Android Open Source Project
+#
+# 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.
@@ -11,8 +12,7 @@
# 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)
include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/shared/BoardConfig.mk b/shared/BoardConfig.mk
index 5f118b093..7c5f6ed65 100644
--- a/shared/BoardConfig.mk
+++ b/shared/BoardConfig.mk
@@ -18,54 +18,37 @@
# Common BoardConfig for all supported architectures.
#
-# TODO(b/170639028): Back up TARGET_NO_BOOTLOADER
-__TARGET_NO_BOOTLOADER := $(TARGET_NO_BOOTLOADER)
include build/make/target/board/BoardConfigMainlineCommon.mk
-TARGET_NO_BOOTLOADER := $(__TARGET_NO_BOOTLOADER)
TARGET_BOOTLOADER_BOARD_NAME := cutf
-BOARD_SYSTEMIMAGE_FILE_SYSTEM_TYPE := $(TARGET_RO_FILE_SYSTEM_TYPE)
-
# Boot partition size: 32M
# This is only used for OTA update packages. The image size on disk
# will not change (as is it not a filesystem.)
BOARD_BOOTIMAGE_PARTITION_SIZE := 67108864
-ifdef TARGET_DEDICATED_RECOVERY
BOARD_RECOVERYIMAGE_PARTITION_SIZE := 67108864
-endif
BOARD_VENDOR_BOOTIMAGE_PARTITION_SIZE := 67108864
# Build a separate vendor.img partition
BOARD_USES_VENDORIMAGE := true
-BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE := $(TARGET_RO_FILE_SYSTEM_TYPE)
+BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE := ext4
BOARD_USES_METADATA_PARTITION := true
# Build a separate product.img partition
BOARD_USES_PRODUCTIMAGE := true
-BOARD_PRODUCTIMAGE_FILE_SYSTEM_TYPE := $(TARGET_RO_FILE_SYSTEM_TYPE)
+BOARD_PRODUCTIMAGE_FILE_SYSTEM_TYPE := ext4
# Build a separate system_ext.img partition
BOARD_USES_SYSTEM_EXTIMAGE := true
-BOARD_SYSTEM_EXTIMAGE_FILE_SYSTEM_TYPE := $(TARGET_RO_FILE_SYSTEM_TYPE)
+BOARD_SYSTEM_EXTIMAGE_FILE_SYSTEM_TYPE := ext4
TARGET_COPY_OUT_SYSTEM_EXT := system_ext
# Build a separate odm.img partition
BOARD_USES_ODMIMAGE := true
-BOARD_ODMIMAGE_FILE_SYSTEM_TYPE := $(TARGET_RO_FILE_SYSTEM_TYPE)
+BOARD_ODMIMAGE_FILE_SYSTEM_TYPE := ext4
TARGET_COPY_OUT_ODM := odm
-# Build a separate vendor_dlkm partition
-BOARD_USES_VENDOR_DLKMIMAGE := true
-BOARD_VENDOR_DLKMIMAGE_FILE_SYSTEM_TYPE := ext4
-TARGET_COPY_OUT_VENDOR_DLKM := vendor_dlkm
-
-# Build a separate odm_dlkm partition
-BOARD_USES_ODM_DLKMIMAGE := true
-BOARD_ODM_DLKMIMAGE_FILE_SYSTEM_TYPE := ext4
-TARGET_COPY_OUT_ODM_DLKM := odm_dlkm
-
# FIXME: Remove this once we generate the vbmeta digest correctly
BOARD_AVB_MAKE_VBMETA_IMAGE_ARGS += --flag 2
@@ -76,36 +59,9 @@ BOARD_AVB_VBMETA_SYSTEM_ALGORITHM := SHA256_RSA2048
BOARD_AVB_VBMETA_SYSTEM_ROLLBACK_INDEX := $(PLATFORM_SECURITY_PATCH_TIMESTAMP)
BOARD_AVB_VBMETA_SYSTEM_ROLLBACK_INDEX_LOCATION := 1
-# Enable chained vbmeta for boot images
-BOARD_AVB_BOOT_KEY_PATH := external/avb/test/data/testkey_rsa2048.pem
-BOARD_AVB_BOOT_ALGORITHM := SHA256_RSA2048
-BOARD_AVB_BOOT_ROLLBACK_INDEX := $(PLATFORM_SECURITY_PATCH_TIMESTAMP)
-BOARD_AVB_BOOT_ROLLBACK_INDEX_LOCATION := 2
-
-# Using sha256 for dm-verity partitions. b/178983355
-# system, system_other, product.
-TARGET_AVB_SYSTEM_HASHTREE_ALGORITHM ?= sha256
-TARGET_AVB_SYSTEM_OTHER_HASHTREE_ALGORITHM ?= sha256
-TARGET_AVB_PRODUCT_HASHTREE_ALGORITHM ?= sha256
-# Using blake2b-256 for system_ext. This give us move coverage of the
-# algorithms as we otherwise don't have a device using blake2b-256.
-TARGET_AVB_SYSTEM_EXT_HASHTREE_ALGORITHM ?= blake2b-256
-
-BOARD_AVB_SYSTEM_ADD_HASHTREE_FOOTER_ARGS += --hash_algorithm $(TARGET_AVB_SYSTEM_HASHTREE_ALGORITHM)
-BOARD_AVB_SYSTEM_OTHER_ADD_HASHTREE_FOOTER_ARGS += --hash_algorithm $(TARGET_AVB_SYSTEM_OTHER_HASHTREE_ALGORITHM)
-BOARD_AVB_SYSTEM_EXT_ADD_HASHTREE_FOOTER_ARGS += --hash_algorithm $(TARGET_AVB_SYSTEM_EXT_HASHTREE_ALGORITHM)
-BOARD_AVB_PRODUCT_ADD_HASHTREE_FOOTER_ARGS += --hash_algorithm $(TARGET_AVB_PRODUCT_HASHTREE_ALGORITHM)
-
-# vendor and odm.
-BOARD_AVB_VENDOR_ADD_HASHTREE_FOOTER_ARGS += --hash_algorithm sha256
-BOARD_AVB_ODM_ADD_HASHTREE_FOOTER_ARGS += --hash_algorithm sha256
-
-# vendor_dlkm and odm_dlkm.
-BOARD_AVB_VENDOR_DLKM_ADD_HASHTREE_FOOTER_ARGS += --hash_algorithm sha256
-BOARD_AVB_ODM_DLKM_ADD_HASHTREE_FOOTER_ARGS += --hash_algorithm sha256
-
BOARD_USES_GENERIC_AUDIO := false
USE_CAMERA_STUB := true
+TARGET_USERIMAGES_SPARSE_EXT_DISABLED := true
# Hardware composer configuration
TARGET_USES_HWC2 := true
@@ -113,16 +69,16 @@ TARGET_USES_HWC2 := true
# The compiler will occasionally generate movaps, etc.
BOARD_MALLOC_ALIGNMENT := 16
-# Disable sparse on all filesystem images
-TARGET_USERIMAGES_SPARSE_EROFS_DISABLED := true
-TARGET_USERIMAGES_SPARSE_EXT_DISABLED := true
+# Make the userdata partition 4.25G to accomodate ASAN and CTS
+BOARD_USERDATAIMAGE_PARTITION_SIZE := 4563402752
TARGET_USERIMAGES_SPARSE_F2FS_DISABLED := true
-
-# Make the userdata partition 6G to accommodate ASAN and CTS
-BOARD_USERDATAIMAGE_PARTITION_SIZE := $(TARGET_USERDATAIMAGE_PARTITION_SIZE)
BOARD_USERDATAIMAGE_FILE_SYSTEM_TYPE := $(TARGET_USERDATAIMAGE_FILE_SYSTEM_TYPE)
TARGET_USERIMAGES_USE_F2FS := true
+# Cache partition size: 64M
+BOARD_CACHEIMAGE_PARTITION_SIZE := 67108864
+BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE := ext4
+
BOARD_GPU_DRIVERS := virgl
# Enable goldfish's encoder.
@@ -147,7 +103,6 @@ USE_OPENGL_RENDERER := true
BOARD_WLAN_DEVICE := wlan0
BOARD_HOSTAPD_DRIVER := NL80211
BOARD_WPA_SUPPLICANT_DRIVER := NL80211
-BOARD_WPA_SUPPLICANT_PRIVATE_LIB := lib_driver_cmd_simulated_cf
WPA_SUPPLICANT_VERSION := VER_0_8_X
WIFI_DRIVER_FW_PATH_PARAM := "/dev/null"
WIFI_DRIVER_FW_PATH_STA := "/dev/null"
@@ -156,22 +111,34 @@ WIFI_DRIVER_FW_PATH_AP := "/dev/null"
# vendor sepolicy
BOARD_VENDOR_SEPOLICY_DIRS += device/google/cuttlefish/shared/sepolicy/vendor
BOARD_VENDOR_SEPOLICY_DIRS += device/google/cuttlefish/shared/sepolicy/vendor/google
-
-BOARD_SEPOLICY_DIRS += system/bt/vendor_libs/linux/sepolicy
-
-# Avoid multiple includes of sepolicy already included by Pixel experience.
-ifneq ($(filter aosp_% %_auto %_go_phone trout_% %_tv,$(PRODUCT_NAME)),)
-
-SYSTEM_EXT_PRIVATE_SEPOLICY_DIRS += hardware/google/pixel-sepolicy/flipendo
-
-endif
-
# product sepolicy, allow other layers to append
PRODUCT_PRIVATE_SEPOLICY_DIRS += device/google/cuttlefish/shared/sepolicy/product/private
# PRODUCT_PUBLIC_SEPOLICY_DIRS += device/google/cuttlefish/shared/sepolicy/product/public
# system_ext sepolicy
-SYSTEM_EXT_PRIVATE_SEPOLICY_DIRS += device/google/cuttlefish/shared/sepolicy/system_ext/private
-# SYSTEM_EXT_PUBLIC_SEPOLICY_DIRS += device/google/cuttlefish/shared/sepolicy/system_ext/public
+BOARD_PLAT_PRIVATE_SEPOLICY_DIR += device/google/cuttlefish/shared/sepolicy/system_ext/private
+# BOARD_PLAT_PUBLIC_SEPOLICY_DIR += device/google/cuttlefish/shared/sepolicy/system_ext/public
+
+VSOC_STLPORT_INCLUDES :=
+VSOC_STLPORT_LIBS :=
+VSOC_STLPORT_STATIC_LIBS :=
+VSOC_TEST_INCLUDES := external/googletest/googlemock/include external/googletest/googletest/include
+VSOC_TEST_LIBRARIES := libgmock_main_host libgtest_host libgmock_host
+VSOC_LIBCXX_STATIC := libc++_static
+VSOC_PROTOBUF_SHARED_LIB := libprotobuf-cpp-full
+
+CUTTLEFISH_LIBRIL_NAME := libril-cuttlefish-fork
+ENABLE_CUTTLEFISH_RILD := true
+
+# TODO(ender): Remove all these once we stop depending on GCE code.
+GCE_VERSION_CFLAGS := -DGCE_PLATFORM_SDK_VERSION=${PLATFORM_SDK_VERSION}
+GCE_STLPORT_INCLUDES := $(VSOC_STLPORT_INCLUDES)
+GCE_STLPORT_LIBS := $(VSOC_STLPORT_LIBS)
+GCE_STLPORT_STATIC_LIBS := $(VSOC_STLPORT_STATIC_LIBS)
+GCE_TEST_INCLUDES := $(VSOC_TEST_INCLUDES)
+GCE_TEST_LIBRARIES := $(VSOC_TEST_LIBRARIES)
+GCE_LIBCXX_STATIC := $(VSOC_LIBCXX_STATIC)
+GCE_PROTOBUF_SHARED_LIB := $(VSOC_PROTOBUF_SHARED_LIB)
+# TODO(ender): up till here.
STAGEFRIGHT_AVCENC_CFLAGS := -DANDROID_GCE
@@ -184,24 +151,17 @@ DHCPCD_USE_SCRIPT := yes
TARGET_RECOVERY_PIXEL_FORMAT := ABGR_8888
-TARGET_RECOVERY_UI_LIB := librecovery_ui_cuttlefish
+
TARGET_RECOVERY_FSTAB ?= device/google/cuttlefish/shared/config/fstab.f2fs
-BOARD_SUPER_PARTITION_SIZE := 7516192768 # 7GiB
-BOARD_SUPER_PARTITION_GROUPS := google_system_dynamic_partitions google_vendor_dynamic_partitions
-BOARD_GOOGLE_SYSTEM_DYNAMIC_PARTITIONS_PARTITION_LIST := product system system_ext
-BOARD_GOOGLE_SYSTEM_DYNAMIC_PARTITIONS_SIZE := 5771362304 # 5.375GiB
-BOARD_GOOGLE_VENDOR_DYNAMIC_PARTITIONS_PARTITION_LIST := odm vendor vendor_dlkm odm_dlkm
-# 1404MiB, reserve 4MiB for dynamic partition metadata
-BOARD_GOOGLE_VENDOR_DYNAMIC_PARTITIONS_SIZE := 1472200704
+BOARD_SUPER_PARTITION_SIZE := 6442450944
+BOARD_SUPER_PARTITION_GROUPS := google_dynamic_partitions
+BOARD_GOOGLE_DYNAMIC_PARTITIONS_PARTITION_LIST := odm product system system_ext vendor
+BOARD_GOOGLE_DYNAMIC_PARTITIONS_SIZE := 6442450944
BOARD_BUILD_SUPER_IMAGE_BY_DEFAULT := true
BOARD_SUPER_IMAGE_IN_UPDATE_PACKAGE := true
TARGET_RELEASETOOLS_EXTENSIONS := device/google/cuttlefish/shared
-# Generate a partial ota update package for partitions in vbmeta_system
-BOARD_PARTIAL_OTA_UPDATE_PARTITIONS_LIST := product system system_ext vbmeta_system
-
-BOARD_BOOTLOADER_IN_UPDATE_PACKAGE := true
BOARD_RAMDISK_USE_LZ4 := true
# To see full logs from init, disable ratelimiting.
@@ -210,61 +170,21 @@ BOARD_KERNEL_CMDLINE += printk.devkmsg=on
BOARD_KERNEL_CMDLINE += firmware_class.path=/vendor/etc/
BOARD_KERNEL_CMDLINE += init=/init
-BOARD_BOOTCONFIG += androidboot.hardware=cutf_cvm
-
-# TODO(b/179489292): Remove once kfence is enabled everywhere
-BOARD_KERNEL_CMDLINE += kfence.sample_interval=500
-
-BOARD_KERNEL_CMDLINE += loop.max_part=7
-
-# TODO(b/182417593): Move all of these module options to modules.options
-# TODO(b/176860479): Remove once goldfish and cuttlefish share a wifi implementation
-BOARD_BOOTCONFIG += kernel.mac80211_hwsim.radios=0
-# TODO(b/175151042): Remove once we are using virtio-snd on cuttlefish
-BOARD_BOOTCONFIG += kernel.snd-hda-intel.enable=0
-# Reduce slab size usage from virtio vsock to reduce slab fragmentation
-BOARD_BOOTCONFIG += \
- kernel.vmw_vsock_virtio_transport_common.virtio_transport_max_vsock_pkt_buf_size=16384
+BOARD_KERNEL_CMDLINE += androidboot.hardware=cutf_cvm
+BOARD_KERNEL_CMDLINE += security=selinux
+BOARD_KERNEL_CMDLINE += androidboot.console=ttyS1
ifeq ($(TARGET_USERDATAIMAGE_FILE_SYSTEM_TYPE),f2fs)
-BOARD_BOOTCONFIG += androidboot.fstab_suffix=f2fs
+BOARD_KERNEL_CMDLINE += androidboot.fstab_suffix=f2fs
endif
ifeq ($(TARGET_USERDATAIMAGE_FILE_SYSTEM_TYPE),ext4)
-BOARD_BOOTCONFIG += androidboot.fstab_suffix=ext4
+BOARD_KERNEL_CMDLINE += androidboot.fstab_suffix=ext4
endif
BOARD_INCLUDE_DTB_IN_BOOTIMG := true
-BOARD_BOOT_HEADER_VERSION := 4
+BOARD_BOOT_HEADER_VERSION := 3
+BOARD_USES_RECOVERY_AS_BOOT := true
BOARD_MKBOOTIMG_ARGS += --header_version $(BOARD_BOOT_HEADER_VERSION)
-PRODUCT_COPY_FILES += \
- device/google/cuttlefish/dtb.img:dtb.img \
- device/google/cuttlefish/required_images:required_images \
-
+PRODUCT_COPY_FILES += device/google/cuttlefish/dtb.img:dtb.img
BOARD_BUILD_SYSTEM_ROOT_IMAGE := false
-
-# Cuttlefish doesn't support ramdump feature yet, exclude the ramdump debug tool.
-EXCLUDE_BUILD_RAMDUMP_UPLOADER_DEBUG_TOOL := true
-
-# GKI-related variables.
-BOARD_USES_GENERIC_KERNEL_IMAGE := true
-ifdef TARGET_DEDICATED_RECOVERY
- BOARD_EXCLUDE_KERNEL_FROM_RECOVERY_IMAGE := true
-else
- BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT := true
-endif
-BOARD_MOVE_GSI_AVB_KEYS_TO_VENDOR_BOOT := true
-
-# TARGET_KERNEL_USE is defined in kernel.mk, if not defined in the environment variable.
-# Keep in sync with GKI APEX in device.mk
-ifneq (,$(TARGET_KERNEL_USE))
- ifneq (,$(filter 5.4, $(TARGET_KERNEL_USE)))
- BOARD_KERNEL_MODULE_INTERFACE_VERSIONS := 5.4-android12-0
- else
- BOARD_KERNEL_MODULE_INTERFACE_VERSIONS := $(TARGET_KERNEL_USE)-android12-unstable
- endif
-endif
-
-BOARD_GENERIC_RAMDISK_KERNEL_MODULES_LOAD := dm-user.ko
-
-BOARD_HAVE_BLUETOOTH := true
diff --git a/shared/auto/android-info.txt b/shared/auto/android-info.txt
deleted file mode 100644
index cc15c01a7..000000000
--- a/shared/auto/android-info.txt
+++ /dev/null
@@ -1 +0,0 @@
-config=auto
diff --git a/shared/auto/device.mk b/shared/auto/device.mk
index fb1ccdf0a..1c036cc4c 100644
--- a/shared/auto/device.mk
+++ b/shared/auto/device.mk
@@ -17,6 +17,7 @@
################################################
# Begin GCE specific configurations
+DEVICE_MANIFEST_FILE += device/google/cuttlefish/shared/config/manifest.xml
DEVICE_MANIFEST_FILE += device/google/cuttlefish/shared/auto/manifest.xml
$(call inherit-product, device/google/cuttlefish/shared/device.mk)
@@ -31,25 +32,20 @@ PRODUCT_COPY_FILES += \
packages/services/Car/car_product/init/init.bootstat.rc:$(TARGET_COPY_OUT_VENDOR)/etc/init/hw//init.bootstat.rc \
packages/services/Car/car_product/init/init.car.rc:$(TARGET_COPY_OUT_VENDOR)/etc/init/hw//init.car.rc
-ifneq ($(LOCAL_SENSOR_FILE_OVERRIDES),true)
- PRODUCT_COPY_FILES += \
- frameworks/native/data/etc/android.hardware.sensor.accelerometer.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.sensor.accelerometer.xml \
- frameworks/native/data/etc/android.hardware.sensor.compass.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.sensor.compass.xml
-endif
-
PRODUCT_COPY_FILES += \
- frameworks/native/data/etc/android.hardware.bluetooth.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.bluetooth.xml \
frameworks/native/data/etc/android.hardware.broadcastradio.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.broadcastradio.xml \
- frameworks/native/data/etc/android.hardware.faketouch.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.faketouch.xml \
frameworks/native/data/etc/android.hardware.screen.landscape.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.screen.landscape.xml \
+ frameworks/native/data/etc/android.hardware.sensor.accelerometer.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.sensor.accelerometer.xml \
+ frameworks/native/data/etc/android.hardware.sensor.compass.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.sensor.compass.xml \
frameworks/native/data/etc/android.software.activities_on_secondary_displays.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.software.activities_on_secondary_displays.xml \
frameworks/native/data/etc/car_core_hardware.xml:system/etc/permissions/car_core_hardware.xml \
-PRODUCT_VENDOR_PROPERTIES += \
+PRODUCT_PROPERTY_OVERRIDES += \
keyguard.no_require_sim=true \
ro.cdma.home.operator.alpha=Android \
ro.cdma.home.operator.numeric=302780 \
ro.com.android.dataroaming=true \
+ vendor.rild.libpath=libcuttlefish-ril.so \
# vehicle HAL
ifeq ($(LOCAL_VHAL_PRODUCT_PACKAGE),)
@@ -63,7 +59,7 @@ PRODUCT_PACKAGES += android.hardware.broadcastradio@2.0-service
# AudioControl HAL
ifeq ($(LOCAL_AUDIOCONTROL_HAL_PRODUCT_PACKAGE),)
- LOCAL_AUDIOCONTROL_HAL_PRODUCT_PACKAGE := android.hardware.automotive.audiocontrol-service.example
+ LOCAL_AUDIOCONTROL_HAL_PRODUCT_PACKAGE := android.hardware.automotive.audiocontrol@2.0-service
endif
PRODUCT_PACKAGES += $(LOCAL_AUDIOCONTROL_HAL_PRODUCT_PACKAGE)
@@ -74,7 +70,7 @@ PRODUCT_PACKAGES_DEBUG += canhalctrl \
canhalsend
PRODUCT_PACKAGES += \
- libcuttlefish-ril-2 \
+ libcuttlefish-ril \
libcuttlefish-rild
# system_other support
@@ -90,10 +86,6 @@ $(call inherit-product, packages/services/Car/car_product/build/car.mk)
# Placed here due to b/110784510
PRODUCT_BRAND := generic
-DEVICE_PACKAGE_OVERLAYS += device/google/cuttlefish/shared/auto/overlay
-
-TARGET_BOARD_INFO_FILE ?= device/google/cuttlefish/shared/auto/android-info.txt
-
PRODUCT_ENFORCE_RRO_TARGETS := framework-res
TARGET_NO_TELEPHONY := true
diff --git a/shared/auto/manifest.xml b/shared/auto/manifest.xml
index 7bf5d3c26..d115dbd10 100644
--- a/shared/auto/manifest.xml
+++ b/shared/auto/manifest.xml
@@ -9,7 +9,7 @@
*/
-->
<!-- Android Auto Embedded specific HALs-->
-<manifest version="1.0" type="device">
+<manifest version="1.0" type="device" target-level="5">
<!-- FIXME: Implement automotive.evs HAL
<hal format="hidl">
<name>android.hardware.automotive.evs</name>
diff --git a/shared/config/Android.bp b/shared/config/Android.bp
deleted file mode 100644
index 03bbc084f..000000000
--- a/shared/config/Android.bp
+++ /dev/null
@@ -1,33 +0,0 @@
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-prebuilt_etc_host {
- name: "cvd_config_auto.json",
- src: "config_auto.json",
- sub_dir: "cvd_config",
-}
-
-prebuilt_etc_host {
- name: "cvd_config_foldable.json",
- src: "config_foldable.json",
- sub_dir: "cvd_config",
-}
-
-prebuilt_etc_host {
- name: "cvd_config_phone.json",
- src: "config_phone.json",
- sub_dir: "cvd_config",
-}
-
-prebuilt_etc_host {
- name: "cvd_config_tablet.json",
- src: "config_tablet.json",
- sub_dir: "cvd_config",
-}
-
-prebuilt_etc_host {
- name: "cvd_config_tv.json",
- src: "config_tv.json",
- sub_dir: "cvd_config",
-}
diff --git a/shared/config/Android.mk b/shared/config/Android.mk
new file mode 100644
index 000000000..1397bcc3f
--- /dev/null
+++ b/shared/config/Android.mk
@@ -0,0 +1,37 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+# This section generates wpa_supplicant.conf using the target product name and
+# model as that file requires such build target specific fields.
+
+LOCAL_MODULE := wpa_supplicant.vsoc.conf
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR)/etc/wifi
+LOCAL_MODULE_STEM := wpa_supplicant.conf
+LOCAL_MULTILIB := first
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/gen_wpa_supplicant_conf.sh
+ $(hide) echo "Generating $@"
+ $(hide) mkdir -p $(dir $@)
+ $(hide) $< "${TARGET_PRODUCT}" "${PRODUCT_MODEL}" \
+ "${PLATFORM_SDK_VERSION}" > $@
diff --git a/shared/config/CleanSpec.mk b/shared/config/CleanSpec.mk
index 9556fc568..a74a710d2 100644
--- a/shared/config/CleanSpec.mk
+++ b/shared/config/CleanSpec.mk
@@ -50,4 +50,3 @@ $(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/bin/hw/android.hardware.gnss
$(call add-clean-step, find $(PRODUCT_OUT)/vendor/bin/hw/ -type f -name "android.hardware.drm@*" -print0 | xargs -0 rm -f)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/etc/init/android.hardware.graphics.allocator@4.0-service.minigbm.rc)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/bin/hw/android.hardware.graphics.allocator@4.0-service.minigbm)
-$(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/bin/hw/android.hardware.gnss@2.1-service)
diff --git a/shared/config/android.hardware.media.omx@1.0.xml b/shared/config/android.hardware.media.omx@1.0.xml
deleted file mode 100644
index a04bcd052..000000000
--- a/shared/config/android.hardware.media.omx@1.0.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<manifest version="1.0" type="device">
- <hal format="hidl">
- <name>android.hardware.media.omx</name>
- <transport>hwbinder</transport>
- <fqname>@1.0::IOmx/default</fqname>
- <fqname>@1.0::IOmxStore/default</fqname>
- </hal>
-</manifest>
diff --git a/shared/config/camera_v1.json b/shared/config/camera_v1.json
new file mode 100644
index 000000000..8a2ae5bf2
--- /dev/null
+++ b/shared/config/camera_v1.json
@@ -0,0 +1,52 @@
+{
+ "__readme": [
+ "Basic Camera HAL v1 configuration."
+ ],
+
+ "camera_definitions": [
+ {
+ "orientation": "back",
+ "hal_version": "1",
+ "resolutions": [
+ {
+ "width": "1600",
+ "height": "1200"
+ },
+ {
+ "width": "1280",
+ "height": "720"
+ },
+ {
+ "width": "640",
+ "height": "480"
+ },
+ {
+ "width": "320",
+ "height": "240"
+ }
+ ]
+ },
+ {
+ "orientation": "front",
+ "hal_version": "1",
+ "resolutions": [
+ {
+ "width": "1024",
+ "height": "768"
+ },
+ {
+ "width": "800",
+ "height": "600"
+ },
+ {
+ "width": "640",
+ "height": "480"
+ },
+ {
+ "width": "320",
+ "height": "240"
+ }
+ ]
+ }
+ ]
+}
diff --git a/shared/config/camera_v3.json b/shared/config/camera_v3.json
new file mode 100644
index 000000000..347900430
--- /dev/null
+++ b/shared/config/camera_v3.json
@@ -0,0 +1,52 @@
+{
+ "__readme": [
+ "Basic Camera HAL v3 configuration."
+ ],
+
+ "camera_definitions": [
+ {
+ "orientation": "back",
+ "hal_version": "3",
+ "resolutions": [
+ {
+ "width": "1600",
+ "height": "1200"
+ },
+ {
+ "width": "1280",
+ "height": "720"
+ },
+ {
+ "width": "640",
+ "height": "480"
+ },
+ {
+ "width": "320",
+ "height": "240"
+ }
+ ]
+ },
+ {
+ "orientation": "front",
+ "hal_version": "3",
+ "resolutions": [
+ {
+ "width": "1024",
+ "height": "768"
+ },
+ {
+ "width": "800",
+ "height": "600"
+ },
+ {
+ "width": "640",
+ "height": "480"
+ },
+ {
+ "width": "320",
+ "height": "240"
+ }
+ ]
+ }
+ ]
+}
diff --git a/shared/config/config_auto.json b/shared/config/config_auto.json
deleted file mode 100644
index b8f2bfe84..000000000
--- a/shared/config/config_auto.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "x_res" : 1280,
- "y_res" : 800,
- "dpi" : 160,
- "memory_mb" : 4096
-}
diff --git a/shared/config/config_foldable.json b/shared/config/config_foldable.json
deleted file mode 100644
index dd64d1707..000000000
--- a/shared/config/config_foldable.json
+++ /dev/null
@@ -1,34 +0,0 @@
-{
- "x_res" : 1768,
- "y_res" : 2208,
- "dpi" : 386,
- "memory_mb" : 4096,
- "custom_actions" : [
- {
- "device_states": [
- {
- "lid_switch_open": false,
- "hinge_angle_value": 0
- }
- ],
- "button":{
- "command":"device_state_closed",
- "title":"Device State Closed",
- "icon_name":"smartphone"
- }
- },
- {
- "device_states": [
- {
- "lid_switch_open": true,
- "hinge_angle_value": 180
- }
- ],
- "button":{
- "command":"device_state_opened",
- "title":"Device State Opened",
- "icon_name":"tablet"
- }
- }
- ]
-}
diff --git a/shared/config/config_phone.json b/shared/config/config_phone.json
deleted file mode 100644
index 69ad97733..000000000
--- a/shared/config/config_phone.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "x_res" : 720,
- "y_res" : 1280,
- "dpi" : 320,
- "memory_mb" : 2048
-}
diff --git a/shared/config/config_tablet.json b/shared/config/config_tablet.json
deleted file mode 100644
index 832d637a0..000000000
--- a/shared/config/config_tablet.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "x_res" : 2560,
- "y_res" : 1800,
- "dpi" : 320,
- "memory_mb" : 4096
-}
diff --git a/shared/config/config_tv.json b/shared/config/config_tv.json
deleted file mode 100644
index 9698d017c..000000000
--- a/shared/config/config_tv.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "x_res" : 1920,
- "y_res" : 1080,
- "dpi" : 213,
- "memory_mb" : 2048
-}
diff --git a/shared/config/fstab-erofs.ext4 b/shared/config/fstab-erofs.ext4
deleted file mode 100644
index ec7b3feaf..000000000
--- a/shared/config/fstab-erofs.ext4
+++ /dev/null
@@ -1,18 +0,0 @@
-/dev/block/by-name/boot /boot emmc defaults recoveryonly,slotselect
-/dev/block/by-name/vendor_boot /vendor_boot emmc defaults recoveryonly,slotselect
-system /system erofs ro wait,logical,first_stage_mount,slotselect,avb=vbmeta_system
-# Add all non-dynamic partitions except system, after this comment
-/dev/block/by-name/userdata /data ext4 nodev,noatime,nosuid,errors=panic latemount,wait,check,quota,formattable,fileencryption=aes-256-xts:aes-256-cts,keydirectory=/metadata/vold/metadata_encryption,checkpoint=block
-/dev/block/by-name/metadata /metadata ext4 nodev,noatime,nosuid,errors=panic wait,formattable,first_stage_mount,check
-/dev/block/by-name/misc /misc emmc defaults defaults
-# Add all dynamic partitions except system, after this comment
-odm /odm erofs ro wait,logical,first_stage_mount,slotselect,avb
-product /product erofs ro wait,logical,first_stage_mount,slotselect,avb
-system_ext /system_ext erofs ro wait,logical,first_stage_mount,slotselect,avb=vbmeta_system
-vendor /vendor erofs ro wait,logical,first_stage_mount,slotselect,avb=vbmeta
-vendor_dlkm /vendor_dlkm ext4 noatime,ro,errors=panic wait,logical,first_stage_mount,slotselect,avb
-odm_dlkm /odm_dlkm ext4 noatime,ro,errors=panic wait,logical,first_stage_mount,slotselect,avb
-/dev/block/zram0 none swap defaults zramsize=75%
-/dev/block/vdc1 /sdcard vfat defaults recoveryonly
-/devices/*/block/vdc auto auto defaults voldmanaged=sdcard1:auto,encryptable=userdata
-shared /mnt/vendor/shared virtiofs nosuid,nodev,noatime nofail
diff --git a/shared/config/fstab-erofs.f2fs b/shared/config/fstab-erofs.f2fs
deleted file mode 100644
index 1b5486eec..000000000
--- a/shared/config/fstab-erofs.f2fs
+++ /dev/null
@@ -1,18 +0,0 @@
-/dev/block/by-name/boot /boot emmc defaults recoveryonly,slotselect
-/dev/block/by-name/vendor_boot /vendor_boot emmc defaults recoveryonly,slotselect
-system /system erofs ro wait,logical,first_stage_mount,slotselect,avb=vbmeta_system
-# Add all non-dynamic partitions except system, after this comment
-/dev/block/by-name/userdata /data f2fs nodev,noatime,nosuid,inlinecrypt,reserve_root=32768 latemount,wait,check,quota,formattable,fileencryption=aes-256-xts:aes-256-cts:v2+inlinecrypt_optimized,fscompress,keydirectory=/metadata/vold/metadata_encryption,checkpoint=fs
-/dev/block/by-name/metadata /metadata ext4 nodev,noatime,nosuid,errors=panic wait,formattable,first_stage_mount,check
-/dev/block/by-name/misc /misc emmc defaults defaults
-# Add all dynamic partitions except system, after this comment
-odm /odm erofs ro wait,logical,first_stage_mount,slotselect,avb
-product /product erofs ro wait,logical,first_stage_mount,slotselect,avb
-system_ext /system_ext erofs ro wait,logical,first_stage_mount,slotselect,avb=vbmeta_system
-vendor /vendor erofs ro wait,logical,first_stage_mount,slotselect,avb=vbmeta
-vendor_dlkm /vendor_dlkm ext4 noatime,ro,errors=panic wait,logical,first_stage_mount,slotselect,avb
-odm_dlkm /odm_dlkm ext4 noatime,ro,errors=panic wait,logical,first_stage_mount,slotselect,avb
-/dev/block/zram0 none swap defaults zramsize=75%
-/dev/block/vdc1 /sdcard vfat defaults recoveryonly
-/devices/*/block/vdc auto auto defaults voldmanaged=sdcard1:auto,encryptable=userdata
-shared /mnt/vendor/shared virtiofs nosuid,nodev,noatime nofail
diff --git a/shared/config/fstab.ext4 b/shared/config/fstab.ext4
index 167794143..9b6eab5df 100644
--- a/shared/config/fstab.ext4
+++ b/shared/config/fstab.ext4
@@ -2,7 +2,8 @@
/dev/block/by-name/vendor_boot /vendor_boot emmc defaults recoveryonly,slotselect
system /system ext4 noatime,ro,errors=panic wait,logical,first_stage_mount,slotselect,avb=vbmeta_system
# Add all non-dynamic partitions except system, after this comment
-/dev/block/by-name/userdata /data ext4 nodev,noatime,nosuid,errors=panic latemount,wait,check,quota,formattable,fileencryption=aes-256-xts:aes-256-cts,keydirectory=/metadata/vold/metadata_encryption,checkpoint=block
+/dev/block/by-name/userdata /data ext4 nodev,noatime,nosuid,errors=panic wait,fileencryption=aes-256-xts:aes-256-cts,fsverity
+/dev/block/by-name/cache /cache ext4 nodev,noatime,nosuid,errors=panic wait
/dev/block/by-name/metadata /metadata ext4 nodev,noatime,nosuid,errors=panic wait,formattable,first_stage_mount,check
/dev/block/by-name/misc /misc emmc defaults defaults
# Add all dynamic partitions except system, after this comment
@@ -10,9 +11,6 @@ odm /odm ext4 noatime,ro,errors=panic wait,logical,first_stage_mount,slotselect,
product /product ext4 noatime,ro,errors=panic wait,logical,first_stage_mount,slotselect,avb
system_ext /system_ext ext4 noatime,ro,errors=panic wait,logical,first_stage_mount,slotselect,avb=vbmeta_system
vendor /vendor ext4 noatime,ro,errors=panic wait,logical,first_stage_mount,slotselect,avb=vbmeta
-vendor_dlkm /vendor_dlkm ext4 noatime,ro,errors=panic wait,logical,first_stage_mount,slotselect,avb
-odm_dlkm /odm_dlkm ext4 noatime,ro,errors=panic wait,logical,first_stage_mount,slotselect,avb
/dev/block/zram0 none swap defaults zramsize=75%
-/dev/block/vdc1 /sdcard vfat defaults recoveryonly
-/devices/*/block/vdc auto auto defaults voldmanaged=sdcard1:auto,encryptable=userdata
-shared /mnt/vendor/shared virtiofs nosuid,nodev,noatime nofail
+/tmp /sdcard none defaults,bind recoveryonly
+/devices/*/block/vdb auto auto defaults voldmanaged=sdcard1:auto,encryptable=userdata
diff --git a/shared/config/fstab.f2fs b/shared/config/fstab.f2fs
index 597e3f0b2..2e9f31f2d 100644
--- a/shared/config/fstab.f2fs
+++ b/shared/config/fstab.f2fs
@@ -2,7 +2,8 @@
/dev/block/by-name/vendor_boot /vendor_boot emmc defaults recoveryonly,slotselect
system /system ext4 noatime,ro,errors=panic wait,logical,first_stage_mount,slotselect,avb=vbmeta_system
# Add all non-dynamic partitions except system, after this comment
-/dev/block/by-name/userdata /data f2fs nodev,noatime,nosuid,inlinecrypt,reserve_root=32768 latemount,wait,check,quota,formattable,fileencryption=aes-256-xts:aes-256-cts:v2+inlinecrypt_optimized,fscompress,keydirectory=/metadata/vold/metadata_encryption,checkpoint=fs
+/dev/block/by-name/userdata /data f2fs nodev,noatime,nosuid,inlinecrypt,reserve_root=32768 latemount,wait,fileencryption=aes-256-xts:aes-256-cts:v2+inlinecrypt_optimized,fsverity,keydirectory=/metadata/vold/metadata_encryption
+/dev/block/by-name/cache /cache ext4 nodev,noatime,nosuid,errors=panic wait
/dev/block/by-name/metadata /metadata ext4 nodev,noatime,nosuid,errors=panic wait,formattable,first_stage_mount,check
/dev/block/by-name/misc /misc emmc defaults defaults
# Add all dynamic partitions except system, after this comment
@@ -10,9 +11,6 @@ odm /odm ext4 noatime,ro,errors=panic wait,logical,first_stage_mount,slotselect,
product /product ext4 noatime,ro,errors=panic wait,logical,first_stage_mount,slotselect,avb
system_ext /system_ext ext4 noatime,ro,errors=panic wait,logical,first_stage_mount,slotselect,avb=vbmeta_system
vendor /vendor ext4 noatime,ro,errors=panic wait,logical,first_stage_mount,slotselect,avb=vbmeta
-vendor_dlkm /vendor_dlkm ext4 noatime,ro,errors=panic wait,logical,first_stage_mount,slotselect,avb
-odm_dlkm /odm_dlkm ext4 noatime,ro,errors=panic wait,logical,first_stage_mount,slotselect,avb
/dev/block/zram0 none swap defaults zramsize=75%
-/dev/block/vdc1 /sdcard vfat defaults recoveryonly
-/devices/*/block/vdc auto auto defaults voldmanaged=sdcard1:auto,encryptable=userdata
-shared /mnt/vendor/shared virtiofs nosuid,nodev,noatime nofail
+/tmp /sdcard none defaults,bind recoveryonly
+/devices/*/block/vdb auto auto defaults voldmanaged=sdcard1:auto,encryptable=userdata
diff --git a/shared/config/gen_wpa_supplicant_conf.sh b/shared/config/gen_wpa_supplicant_conf.sh
new file mode 100755
index 000000000..72ecb2199
--- /dev/null
+++ b/shared/config/gen_wpa_supplicant_conf.sh
@@ -0,0 +1,20 @@
+#!/bin/bash
+#
+# Generates wpa_supplicant.conf file for wifi
+# Usage: generate_wpa_supplicant_conf.sh <device name> <model name> <SDK API level>
+
+if [ -n "$3" -a "$3" -lt "21" ]
+then
+ # before mnc.
+ cat <<eof
+ctrl_interface=wlan0
+eof
+fi
+
+cat <<eof
+update_config=1
+device_name=$1
+model_name=$2
+serial_number=
+device_type=10-0050F204-5
+eof
diff --git a/shared/config/init.product.rc b/shared/config/init.product.rc
index 22371a325..fe7130c6f 100644
--- a/shared/config/init.product.rc
+++ b/shared/config/init.product.rc
@@ -1,8 +1,19 @@
on early-init
setprop ro.setupwizard.mode ${ro.boot.setupwizard_mode}
+on property:ro.boot.tombstone_transmit=1
+ enable tombstone_transmit
+
+
service tombstone_transmit /product/bin/tombstone_transmit
# Start tombstone_transmit after /data is mounted.
class late_start
group system
user root
+ disabled
+
+# TODO: disable this service once cuttlefish implements system suspend
+service suspend_blocker /product/bin/suspend_blocker
+ class main
+ group system
+ user root
diff --git a/shared/config/init.recovery.rc b/shared/config/init.recovery.rc
index 3fdd4b013..6f9ca1410 100644
--- a/shared/config/init.recovery.rc
+++ b/shared/config/init.recovery.rc
@@ -3,8 +3,8 @@ service console /system/bin/sh
console
disabled
user root
- group root shell log readproc
- seclabel u:r:su:s0
+ group shell log readproc
+ seclabel u:r:shell:s0
setenv HOSTNAME console
on property:ro.debuggable=1
diff --git a/shared/config/init.vendor.rc b/shared/config/init.vendor.rc
index 77b79dc97..94da76815 100644
--- a/shared/config/init.vendor.rc
+++ b/shared/config/init.vendor.rc
@@ -1,16 +1,20 @@
on early-init
# loglevel 8
+ mkdir /var/run 0755 root root
+ mkdir /var/run/media 0755 media root
+ mkdir /var/run/system 0755 system root
+ mkdir /dev/gce 0750
+ chown system system /dev/gce
- mount securityfs securityfs /sys/kernel/security
+ # For KCOV
+ mount debugfs debugfs /sys/kernel/debug
+ chmod 0755 /sys/kernel/debug
setprop ro.sf.lcd_density ${ro.boot.lcd_density}
setprop ro.hardware.egl ${ro.boot.hardware.egl}
- setprop debug.sf.vsync_reactor_ignore_present_fences true
setprop ro.hardware.gralloc ${ro.boot.hardware.gralloc}
setprop ro.hardware.hwcomposer ${ro.boot.hardware.hwcomposer}
setprop ro.hardware.vulkan ${ro.boot.hardware.vulkan}
- setprop ro.cpuvulkan.version ${ro.boot.cpuvulkan.version}
- setprop ro.hw_timeout_multiplier ${ro.boot.hw_timeout_multiplier}
# start module load in the background
start vendor.insmod_sh
@@ -18,8 +22,9 @@ on early-init
on init
# ZRAM setup
write /sys/block/zram0/comp_algorithm lz4
-
+ #
# EAS uclamp interfaces
+ #
mkdir /dev/cpuctl/foreground
mkdir /dev/cpuctl/background
mkdir /dev/cpuctl/top-app
@@ -40,9 +45,8 @@ on init
chmod 0664 /dev/cpuctl/top-app/tasks
chmod 0664 /dev/cpuctl/rt/tasks
-on fs
- mkdir /mnt/vendor/shared 0770 system system
+on fs
# Mount everything that does not require fsck
mount_all --early
restorecon_recursive /vendor
@@ -51,19 +55,32 @@ on fs
# works around framework netiface enumeration issue
start rename_eth1
- start bt_vhci_forwarder
-
- # So GceBootReporter can print to kmsg
+ # TODO(ender): Find better way to talk to serial port.
chmod 622 /dev/kmsg
+ # for GCE camera HAL
+ mkdir /var/media 0770 audio media
+
+ chmod 0664 /sys/kernel/debug/ieee80211/phy1/hwsim/group
+ chmod 0664 /sys/kernel/debug/ieee80211/phy1/hwsim/ps
+ chmod 0664 /sys/kernel/debug/ieee80211/phy0/rc/fixed_rate_idx
+ chmod 0664 /sys/kernel/debug/ieee80211/phy0/hwsim/group
+ chmod 0664 /sys/kernel/debug/ieee80211/phy0/hwsim/ps
+ chmod 0664 /sys/kernel/debug/ieee80211/phy1/rc/fixed_rate_idx
+
+
on post-fs
# set RLIMIT_MEMLOCK to 64MB
setrlimit 8 67108864 67108864
+
on post-fs-data
+ start vport_trigger
+
mkdir /data/vendor/modem_dump 0777 system system
mkdir /data/vendor/radio 0777 system system
+
on late-fs
# Wait for keymaster
exec_start wait_for_keymaster
@@ -73,6 +90,7 @@ on late-fs
write /dev/kmsg "GUEST_BUILD_FINGERPRINT: ${ro.build.fingerprint}"
+
on boot
chmod 0660 /dev/cpuctl
mkdir /data/vendor/wifi 0770 wifi wifi
@@ -80,19 +98,19 @@ on boot
mkdir /data/vendor/wifi/wpa/sockets 0770 wifi wifi
start socket_vsock_proxy
-service bt_vhci_forwarder /vendor/bin/bt_vhci_forwarder -virtio_console_dev=/dev/hvc5
- user bluetooth
- group bluetooth
service setup_wifi /vendor/bin/setup_wifi
oneshot
+
service rename_eth1 /vendor/bin/rename_netiface eth1 rmnet0
oneshot
+
on property:sys.boot_completed=1
trigger sys-boot-completed-set
+
# We want one opportunity per boot to enable zram, so we
# use a trigger we fire from the above stanza. If
# persist.sys.zram_enabled becomes true after boot,
@@ -109,10 +127,30 @@ service vendor.insmod_sh /vendor/bin/init.insmod.sh
service socket_vsock_proxy /vendor/bin/socket_vsock_proxy -server=vsock -tcp_port=5555 -vsock_port=6520
-service seriallogging /system/bin/logcat -b all -v threadtime -f /dev/hvc2 *:V
+
+service vport_trigger /vendor/bin/vport_trigger
+ oneshot
+
+
+on property:vendor.ser.cf-logcat=*
+ symlink ${vendor.ser.cf-logcat} /dev/cf-logcat
+ enable seriallogging
+
+
+service seriallogging /system/bin/logcat -b all -v threadtime -f /dev/cf-logcat *:V
+ class main
+ user root
+ disabled
+
+
+on property:ro.boot.vsock_logcat_port=*
+ enable vsock_logcat
+
+
+service vsock_logcat /vendor/bin/vsock_logcat
class main
- user logd
- group root logd
+ user root
+ disabled
service vsoc_input_service /vendor/bin/vsoc_input_service -touch_port=${ro.boot.vsock_touch_port} -keyboard_port=${ro.boot.vsock_keyboard_port}
group root uhid
@@ -131,20 +169,14 @@ service wpa_supplicant /vendor/bin/hw/wpa_supplicant -g@android:wpa_wlan0
interface android.hardware.wifi.supplicant@1.1::ISupplicant default
interface android.hardware.wifi.supplicant@1.2::ISupplicant default
interface android.hardware.wifi.supplicant@1.3::ISupplicant default
- interface android.hardware.wifi.supplicant@1.4::ISupplicant default
socket wpa_wlan0 dgram 660 wifi wifi
group system wifi inet
disabled
oneshot
+
service bugreport /system/bin/dumpstate -d -p -z
class main
disabled
oneshot
keycodes 30 48
-
-# TODO: disable this service once cuttlefish implements system suspend
-service suspend_blocker /vendor/bin/suspend_blocker
- class early_hal # Start together with system_suspend HAL
- group system
- user root
diff --git a/shared/config/input/Crosvm_Virtio_Multitouch_Touchscreen.idc b/shared/config/input/Crosvm_Virtio_Multitouch_Touchscreen.idc
deleted file mode 100644
index 662f46751..000000000
--- a/shared/config/input/Crosvm_Virtio_Multitouch_Touchscreen.idc
+++ /dev/null
@@ -1,6 +0,0 @@
-device.internal = 1
-
-touch.deviceType = touchScreen
-touch.orientationAware = 1
-
-# touch.displayId = local:0
diff --git a/shared/config/manifest.xml b/shared/config/manifest.xml
index baca8dfb8..484952b27 100644
--- a/shared/config/manifest.xml
+++ b/shared/config/manifest.xml
@@ -16,7 +16,8 @@
** limitations under the License.
*/
-->
-<manifest version="1.0" type="device" target-level="6">
+<manifest version="1.0" type="device" target-level="5">
+ <kernel target-level="5" />
<hal format="hidl">
<name>android.hardware.audio</name>
<transport>hwbinder</transport>
@@ -67,9 +68,18 @@
</hal>
-->
<hal format="hidl">
+ <name>android.hardware.bluetooth</name>
+ <transport>hwbinder</transport>
+ <version>1.1</version>
+ <interface>
+ <name>IBluetoothHci</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl">
<name>android.hardware.bluetooth.audio</name>
<transport>hwbinder</transport>
- <version>2.1</version>
+ <version>2.0</version>
<interface>
<name>IBluetoothAudioProvidersFactory</name>
<instance>default</instance>
@@ -98,14 +108,33 @@
</hal>
-->
<hal format="hidl">
+ <name>android.hardware.graphics.allocator</name>
+ <transport>hwbinder</transport>
+ <version>4.0</version>
+ <interface>
+ <name>IAllocator</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <!-- TODO (b/130079341): -->
+ <hal format="hidl">
<name>android.hardware.graphics.composer</name>
<transport>hwbinder</transport>
- <version>2.3</version>
+ <version>2.2</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>4.0</version>
+ <interface>
+ <name>IMapper</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
<!-- TODO (b/130075874):
<hal format="hidl">
<name>android.hardware.ir</name>
@@ -117,6 +146,19 @@
</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>
<!-- TODO (b/130079342):
<hal format="hidl">
<name>android.hardware.memtrack</name>
@@ -153,7 +195,7 @@
<hal format="hidl">
<name>android.hardware.radio</name>
<transport>hwbinder</transport>
- <version>1.6</version>
+ <version>1.5</version>
<interface>
<name>IRadio</name>
<instance>slot1</instance>
@@ -166,15 +208,17 @@
</interface>
-->
</hal>
+ <!-- TODO (b/130076972):
<hal format="hidl">
<name>android.hardware.radio.config</name>
<transport>hwbinder</transport>
- <version>1.3</version>
+ <version>1.2</version>
<interface>
<name>IRadioConfig</name>
<instance>default</instance>
</interface>
</hal>
+ -->
<!-- TODO (b/130079239):
<hal format="hidl">
<name>android.hardware.secure_element</name>
@@ -186,7 +230,6 @@
</interface>
</hal>
-->
- <!--
<hal format="hidl">
<name>android.hardware.soundtrigger</name>
<transport>hwbinder</transport>
@@ -196,7 +239,6 @@
<instance>default</instance>
</interface>
</hal>
- -->
<!-- TODO (b/130079321):
<hal format="hidl">
<name>android.hardware.tetheroffload.config</name>
diff --git a/shared/config/manifest_android.hardware.bluetooth@1.1-service.xml b/shared/config/manifest_android.hardware.bluetooth@1.1-service.xml
deleted file mode 100644
index 4d70779e0..000000000
--- a/shared/config/manifest_android.hardware.bluetooth@1.1-service.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2021, 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.
-*/
--->
-<manifest version="1.0" type="device">
- <hal format="hidl">
- <name>android.hardware.bluetooth</name>
- <transport>hwbinder</transport>
- <version>1.1</version>
- <interface>
- <name>IBluetoothHci</name>
- <instance>default</instance>
- </interface>
- </hal>
-</manifest>
diff --git a/shared/config/media_codecs_performance.xml b/shared/config/media_codecs_performance.xml
index a85067f5d..4c44a23cc 100644
--- a/shared/config/media_codecs_performance.xml
+++ b/shared/config/media_codecs_performance.xml
@@ -45,24 +45,10 @@
<MediaCodecs>
<Encoders>
- <MediaCodec name="c2.android.h263.encoder" type="video/3gpp" update="true">
- <!-- 3 runs, min 849 max 1008 gmean 943 -->
- <Limit name="measured-frame-rate-176x144" range="849-1008" />
- </MediaCodec>
<MediaCodec name="OMX.google.h263.encoder" type="video/3gpp" update="true">
<!-- 3 runs, min 849 max 1008 gmean 943 -->
<Limit name="measured-frame-rate-176x144" range="849-1008" />
</MediaCodec>
- <MediaCodec name="c2.android.avc.encoder" type="video/avc" update="true">
- <!-- 3 runs, min 496 max 629 gmean 565 -->
- <Limit name="measured-frame-rate-320x240" range="496-629" />
- <!-- 2 runs, min 197 max 203 gmean 201 -->
- <Limit name="measured-frame-rate-720x480" range="197-203" />
- <!-- 2 runs, min 93 max 97 gmean 95 -->
- <Limit name="measured-frame-rate-1280x720" range="93-97" />
- <!-- 2 runs, min 45 max 47 gmean 46 -->
- <Limit name="measured-frame-rate-1920x1080" range="45-47" />
- </MediaCodec>
<MediaCodec name="OMX.google.h264.encoder" type="video/avc" update="true">
<!-- 3 runs, min 496 max 629 gmean 565 -->
<Limit name="measured-frame-rate-320x240" range="496-629" />
@@ -73,28 +59,10 @@
<!-- 2 runs, min 45 max 47 gmean 46 -->
<Limit name="measured-frame-rate-1920x1080" range="45-47" />
</MediaCodec>
- <MediaCodec name="c2.android.hevc.encoder" type="video/hevc" update="true">
- <!-- MANUALLY ADJUSTED -->
- <Limit name="measured-frame-rate-320x240" range="27-40" />
- </MediaCodec>
- <MediaCodec name="c2.android.mpeg4.encoder" type="video/mp4v-es" update="true">
- <!-- 3 runs, min 881 max 1142 gmean 994 -->
- <Limit name="measured-frame-rate-176x144" range="881-1142" />
- </MediaCodec>
<MediaCodec name="OMX.google.mpeg4.encoder" type="video/mp4v-es" update="true">
<!-- 3 runs, min 881 max 1142 gmean 994 -->
<Limit name="measured-frame-rate-176x144" range="881-1142" />
</MediaCodec>
- <MediaCodec name="c2.android.vp8.encoder" type="video/x-vnd.on2.vp8" update="true">
- <!-- 3 runs, min 249 max 285 gmean 264 -->
- <Limit name="measured-frame-rate-320x180" range="249-285" />
- <!-- 3 runs, min 104 max 115 gmean 109 -->
- <Limit name="measured-frame-rate-640x360" range="104-115" />
- <!-- 3 runs, min 34 max 35 gmean 34 -->
- <Limit name="measured-frame-rate-1280x720" range="34-35" />
- <!-- 3 runs, min 26 max 29 gmean 27 -->
- <Limit name="measured-frame-rate-1920x1080" range="26-29" />
- </MediaCodec>
<MediaCodec name="OMX.google.vp8.encoder" type="video/x-vnd.on2.vp8" update="true">
<!-- 3 runs, min 249 max 285 gmean 264 -->
<Limit name="measured-frame-rate-320x180" range="249-285" />
@@ -105,14 +73,6 @@
<!-- 3 runs, min 26 max 29 gmean 27 -->
<Limit name="measured-frame-rate-1920x1080" range="26-29" />
</MediaCodec>
- <MediaCodec name="c2.android.vp9.encoder" type="video/x-vnd.on2.vp9" update="true">
- <!-- MANUALLY ADJUSTED -->
- <Limit name="measured-frame-rate-320x180" range="158-281" />
- <!-- MANUALLY ADJUSTED -->
- <Limit name="measured-frame-rate-640x360" range="56-66" />
- <!-- MANUALLY ADJUSTED -->
- <Limit name="measured-frame-rate-1280x720" range="23-23" />
- </MediaCodec>
</Encoders>
<Decoders>
<MediaCodec name="c2.android.avc.decoder" type="video/avc" update="true">
diff --git a/shared/config/product_manifest.xml b/shared/config/product_manifest.xml
deleted file mode 100644
index 5a8c4ba1c..000000000
--- a/shared/config/product_manifest.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2020, 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.
-*/
--->
-<manifest version="1.0" type="framework" />
diff --git a/shared/config/system_ext_manifest.xml b/shared/config/spn-conf.xml
index 5a8c4ba1c..f1639df6d 100644
--- a/shared/config/system_ext_manifest.xml
+++ b/shared/config/spn-conf.xml
@@ -1,7 +1,7 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="UTF-8"?>
<!--
/*
-** Copyright 2020, The Android Open Source Project.
+** 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.
@@ -16,4 +16,6 @@
** limitations under the License.
*/
-->
-<manifest version="1.0" type="framework" />
+<spnOverrides>
+ <spnOverride numeric="311740" spn="Android"/>
+</spnOverrides>
diff --git a/shared/config/task_profiles.json b/shared/config/task_profiles.json
index 42366fc17..b883c46ee 100644
--- a/shared/config/task_profiles.json
+++ b/shared/config/task_profiles.json
@@ -1,4 +1,47 @@
{
+ "Attributes": [
+ {
+ "Name": "LowCapacityCPUs",
+ "Controller": "cpuset",
+ "File": "background/cpus"
+ },
+ {
+ "Name": "HighCapacityCPUs",
+ "Controller": "cpuset",
+ "File": "foreground/cpus"
+ },
+ {
+ "Name": "MaxCapacityCPUs",
+ "Controller": "cpuset",
+ "File": "top-app/cpus"
+ },
+ {
+ "Name": "MemLimit",
+ "Controller": "memory",
+ "File": "memory.limit_in_bytes"
+ },
+ {
+ "Name": "MemSoftLimit",
+ "Controller": "memory",
+ "File": "memory.soft_limit_in_bytes"
+ },
+ {
+ "Name": "MemSwappiness",
+ "Controller": "memory",
+ "File": "memory.swappiness"
+ },
+ {
+ "Name": "UClampMin",
+ "Controller": "cpu",
+ "File": "cpu.uclamp.min"
+ },
+ {
+ "Name": "UClampMax",
+ "Controller": "cpu",
+ "File": "cpu.uclamp.max"
+ }
+ ],
+
"Profiles": [
{
"Name": "HighEnergySaving",
@@ -14,6 +57,32 @@
]
},
{
+ "Name": "Frozen",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "freezer",
+ "Path": "frozen"
+ }
+ }
+ ]
+ },
+ {
+ "Name": "Unfrozen",
+ "Actions": [
+ {
+ "Name": "JoinCgroup",
+ "Params":
+ {
+ "Controller": "freezer",
+ "Path": ""
+ }
+ }
+ ]
+ },
+ {
"Name": "NormalPerformance",
"Actions": [
{
diff --git a/shared/config/ueventd.rc b/shared/config/ueventd.rc
index 8f2420113..ba62a8720 100644
--- a/shared/config/ueventd.rc
+++ b/shared/config/ueventd.rc
@@ -1,3 +1,6 @@
+# android.permission.cts.FileSystemPermissionTest#testDevHwRandomLockedDown
+/dev/hw_random 0600 root root
+
# virtio-gpu
/dev/dri/card0 0660 system graphics
/dev/dri/controlD64 0660 system graphics
@@ -8,25 +11,3 @@
# resume-on-reboot
/dev/block/pmem0 0770 system system
-
-# vtpm
-/dev/tpm0 0000 root root
-/dev/tpmrm0 000 system system
-
-# seriallogging
-/dev/hvc2 0660 system logd
-
-# keymaster
-/dev/hvc3 0666 system system
-
-# gatekeeper
-/dev/hvc4 0660 system system
-
-# bluetooth
-/dev/hvc5 0660 bluetooth bluetooth
-/dev/vhci 0660 bluetooth bluetooth
-
-/dev/gnss0 0666 system system
-
-# Factory Reset Protection
-/dev/block/by-name/frp 0660 system system
diff --git a/shared/device.mk b/shared/device.mk
index 8647d0175..377db3b18 100644
--- a/shared/device.mk
+++ b/shared/device.mk
@@ -23,44 +23,29 @@ $(call inherit-product, $(SRC_TARGET_DIR)/product/updatable_apex.mk)
# Enable userspace reboot
$(call inherit-product, $(SRC_TARGET_DIR)/product/userspace_reboot.mk)
-# Enforce generic ramdisk allow list
-$(call inherit-product, $(SRC_TARGET_DIR)/product/generic_ramdisk.mk)
-
-PRODUCT_SOONG_NAMESPACES += device/generic/goldfish-opengl # for vulkan
-
-PRODUCT_SHIPPING_API_LEVEL := 31
+PRODUCT_SHIPPING_API_LEVEL := 30
+PRODUCT_BUILD_BOOT_IMAGE := true
PRODUCT_USE_DYNAMIC_PARTITIONS := true
DISABLE_RILD_OEM_HOOK := true
-PRODUCT_SET_DEBUGFS_RESTRICTIONS := true
-
PRODUCT_SOONG_NAMESPACES += device/generic/goldfish-opengl # for vulkan
-PRODUCT_FS_COMPRESSION := 1
-TARGET_RO_FILE_SYSTEM_TYPE ?= ext4
TARGET_USERDATAIMAGE_FILE_SYSTEM_TYPE ?= f2fs
-TARGET_USERDATAIMAGE_PARTITION_SIZE ?= 6442450944
TARGET_VULKAN_SUPPORT ?= true
-TARGET_ENABLE_HOST_BLUETOOTH_EMULATION ?= true
-TARGET_USE_BTLINUX_HAL_IMPL ?= true
AB_OTA_UPDATER := true
AB_OTA_PARTITIONS += \
- boot \
odm \
- odm_dlkm \
product \
system \
system_ext \
vbmeta \
vbmeta_system \
- vendor \
- vendor_boot \
- vendor_dlkm \
+ vendor
# Enable Virtual A/B
-$(call inherit-product, $(SRC_TARGET_DIR)/product/virtual_ab_ota/compression.mk)
+$(call inherit-product, $(SRC_TARGET_DIR)/product/virtual_ab_ota.mk)
# Enable Scoped Storage related
$(call inherit-product, $(SRC_TARGET_DIR)/product/emulated_storage.mk)
@@ -71,79 +56,43 @@ $(call inherit-product, $(SRC_TARGET_DIR)/product/emulated_storage.mk)
PRODUCT_PRODUCT_PROPERTIES += \
persist.adb.tcp.port=5555 \
ro.com.google.locationfeatures=1 \
- persist.sys.fuse.passthrough.enable=true \
-
-# Storage: for factory reset protection feature
-PRODUCT_VENDOR_PROPERTIES += \
- ro.frp.pst=/dev/block/by-name/frp
# Explanation of specific properties:
# debug.hwui.swap_with_damage avoids boot failure on M http://b/25152138
# ro.opengles.version OpenGLES 3.0
-# ro.hardware.keystore_desede=true needed for CtsKeystoreTestCases
-PRODUCT_VENDOR_PROPERTIES += \
+PRODUCT_PROPERTY_OVERRIDES += \
tombstoned.max_tombstone_count=500 \
- vendor.bt.rootcanal_test_console=off \
+ bt.rootcanal_test_console=off \
debug.hwui.swap_with_damage=0 \
ro.carrier=unknown \
- ro.com.android.dataroaming?=false \
+ ro.com.android.dataroaming=false \
ro.hardware.virtual_device=1 \
ro.logd.size=1M \
ro.opengles.version=196608 \
wifi.interface=wlan0 \
persist.sys.zram_enabled=1 \
- ro.hardware.keystore_desede=true \
ro.rebootescrow.device=/dev/block/pmem0 \
ro.incremental.enable=1 \
- debug.c2.use_dmabufheaps=1 \
- ro.camerax.extensions.enabled=true \
# Below is a list of properties we probably should get rid of.
-PRODUCT_VENDOR_PROPERTIES += \
+PRODUCT_PROPERTY_OVERRIDES += \
wlan.driver.status=ok
-ifneq ($(LOCAL_DISABLE_OMX),true)
-# Codec 1.0 requires the OMX services
-DEVICE_MANIFEST_FILE += \
- device/google/cuttlefish/shared/config/android.hardware.media.omx@1.0.xml
-endif
-
-PRODUCT_VENDOR_PROPERTIES += \
- debug.stagefright.c2inputsurface=-1
+# Codec 2.0 is unstable on x86
+PRODUCT_PROPERTY_OVERRIDES += \
+ debug.stagefright.ccodec=0
-# Enforce privapp permissions control.
-PRODUCT_VENDOR_PROPERTIES += ro.control_privapp_permissions?=enforce
+# Enforce privapp-permissions whitelist.
+PRODUCT_PROPERTY_OVERRIDES += ro.control_privapp_permissions=enforce
# aes-256-heh default is not supported in standard kernels.
-PRODUCT_VENDOR_PROPERTIES += ro.crypto.volume.filenames_mode=aes-256-cts
+PRODUCT_PROPERTY_OVERRIDES += ro.crypto.volume.filenames_mode=aes-256-cts
# Copy preopted files from system_b on first boot
-PRODUCT_VENDOR_PROPERTIES += ro.cp_system_other_odex=1
-
-AB_OTA_POSTINSTALL_CONFIG += \
- RUN_POSTINSTALL_system=true \
- POSTINSTALL_PATH_system=system/bin/otapreopt_script \
- FILESYSTEM_TYPE_system=ext4 \
- POSTINSTALL_OPTIONAL_system=true
-
-AB_OTA_POSTINSTALL_CONFIG += \
- RUN_POSTINSTALL_vendor=true \
- POSTINSTALL_PATH_vendor=bin/checkpoint_gc \
- FILESYSTEM_TYPE_vendor=ext4 \
- POSTINSTALL_OPTIONAL_vendor=true
-
-# Userdata Checkpointing OTA GC
-PRODUCT_PACKAGES += \
- checkpoint_gc
-
-# Enable CameraX extension sample
-PRODUCT_PACKAGES += androidx.camera.extensions.impl sample_camera_extensions.xml
+PRODUCT_PROPERTY_OVERRIDES += ro.cp_system_other_odex=1
# DRM service opt-in
-PRODUCT_VENDOR_PROPERTIES += drm.service.enabled=true
-
-# Call deleteAllKeys if vold detects a factory reset
-PRODUCT_VENDOR_PROPERTIES += ro.crypto.metadata_init_delete_all_keys.enabled=true
+PRODUCT_PROPERTY_OVERRIDES += drm.service.enabled=true
PRODUCT_SOONG_NAMESPACES += hardware/google/camera
PRODUCT_SOONG_NAMESPACES += hardware/google/camera/devices/EmulatedCamera
@@ -152,25 +101,18 @@ PRODUCT_SOONG_NAMESPACES += hardware/google/camera/devices/EmulatedCamera
# Packages for various GCE-specific utilities
#
PRODUCT_PACKAGES += \
+ socket_vsock_proxy \
CuttlefishService \
- cuttlefish_sensor_injection \
+ wpa_supplicant.vsoc.conf \
+ vsoc_input_service \
+ vport_trigger \
rename_netiface \
+ ip_link_add \
setup_wifi \
- bt_vhci_forwarder \
- socket_vsock_proxy \
tombstone_transmit \
+ vsock_logcat \
tombstone_producer \
suspend_blocker \
- vsoc_input_service \
- vtpm_manager \
-
-SOONG_CONFIG_NAMESPACES += cvd
-SOONG_CONFIG_cvd += launch_configs
-SOONG_CONFIG_cvd_launch_configs += \
- cvd_config_auto.json \
- cvd_config_phone.json \
- cvd_config_tablet.json \
- cvd_config_tv.json \
#
# Packages for AOSP-available stuff we use from the framework
@@ -187,13 +129,6 @@ PRODUCT_PACKAGES += \
# Packages for the OpenGL implementation
#
-# ANGLE provides an OpenGL implementation built on top of Vulkan.
-PRODUCT_PACKAGES += \
- libEGL_angle \
- libGLESv1_CM_angle \
- libGLESv2_angle \
- libfeature_support_angle.so
-
# SwiftShader provides a software-only implementation that is not thread-safe
PRODUCT_PACKAGES += \
libEGL_swiftshader \
@@ -216,7 +151,6 @@ endif
# GL/Vk implementation for gfxstream
PRODUCT_PACKAGES += \
- hwcomposer.ranchu \
libandroidemu \
libOpenglCodecCommon \
libOpenglSystemCommon \
@@ -225,8 +159,7 @@ PRODUCT_PACKAGES += \
libEGL_emulation \
libGLESv2_enc \
libGLESv2_emulation \
- libGLESv1_enc \
- libGoldfishProfiler \
+ libGLESv1_enc
#
# Packages for testing
@@ -240,27 +173,10 @@ DEVICE_PACKAGE_OVERLAYS := device/google/cuttlefish/shared/overlay
# pick up every density resources.
#
-# Common manifest for all targets
-#
-DEVICE_MANIFEST_FILE += device/google/cuttlefish/shared/config/manifest.xml
-
-#
# General files
#
-
-
-ifneq ($(LOCAL_SENSOR_FILE_OVERRIDES),true)
- PRODUCT_COPY_FILES += \
- frameworks/native/data/etc/android.hardware.sensor.ambient_temperature.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.sensor.ambient_temperature.xml \
- frameworks/native/data/etc/android.hardware.sensor.barometer.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.sensor.barometer.xml \
- frameworks/native/data/etc/android.hardware.sensor.gyroscope.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.sensor.gyroscope.xml \
- frameworks/native/data/etc/android.hardware.sensor.hinge_angle.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.sensor.hinge_angle.xml \
- frameworks/native/data/etc/android.hardware.sensor.light.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.sensor.light.xml \
- frameworks/native/data/etc/android.hardware.sensor.proximity.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.sensor.proximity.xml \
- frameworks/native/data/etc/android.hardware.sensor.relative_humidity.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.sensor.relative_humidity.xml
-endif
-
PRODUCT_COPY_FILES += \
+ device/google/cuttlefish/shared/config/audio_policy.conf:$(TARGET_COPY_OUT_VENDOR)/etc/audio_policy.conf \
hardware/google/camera/devices/EmulatedCamera/hwl/configs/emu_camera_back.json:$(TARGET_COPY_OUT_VENDOR)/etc/config/emu_camera_back.json \
hardware/google/camera/devices/EmulatedCamera/hwl/configs/emu_camera_front.json:$(TARGET_COPY_OUT_VENDOR)/etc/config/emu_camera_front.json \
hardware/google/camera/devices/EmulatedCamera/hwl/configs/emu_camera_depth.json:$(TARGET_COPY_OUT_VENDOR)/etc/config/emu_camera_depth.json \
@@ -276,12 +192,13 @@ PRODUCT_COPY_FILES += \
frameworks/av/media/libeffects/data/audio_effects.xml:$(TARGET_COPY_OUT_VENDOR)/etc/audio_effects.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 \
+ 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 \
frameworks/native/data/etc/android.hardware.audio.low_latency.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.audio.low_latency.xml \
- frameworks/native/data/etc/android.hardware.bluetooth.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.bluetooth.xml \
frameworks/native/data/etc/android.hardware.bluetooth_le.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.bluetooth_le.xml \
frameworks/native/data/etc/android.hardware.camera.concurrent.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.camera.concurrent.xml \
frameworks/native/data/etc/android.hardware.camera.flash-autofocus.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.camera.flash-autofocus.xml \
@@ -289,47 +206,35 @@ PRODUCT_COPY_FILES += \
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.camera.raw.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.camera.raw.xml \
frameworks/native/data/etc/android.hardware.ethernet.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.ethernet.xml \
+ frameworks/native/data/etc/android.hardware.faketouch.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.faketouch.xml \
frameworks/native/data/etc/android.hardware.location.gps.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.location.gps.xml \
frameworks/native/data/etc/android.hardware.reboot_escrow.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.reboot_escrow.xml \
+ frameworks/native/data/etc/android.hardware.sensor.ambient_temperature.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.sensor.ambient_temperature.xml \
+ frameworks/native/data/etc/android.hardware.sensor.barometer.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.sensor.barometer.xml \
+ frameworks/native/data/etc/android.hardware.sensor.gyroscope.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.sensor.gyroscope.xml \
+ frameworks/native/data/etc/android.hardware.sensor.hinge_angle.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.sensor.hinge_angle.xml \
+ frameworks/native/data/etc/android.hardware.sensor.light.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.sensor.light.xml \
+ frameworks/native/data/etc/android.hardware.sensor.proximity.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.sensor.proximity.xml \
+ frameworks/native/data/etc/android.hardware.sensor.relative_humidity.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.sensor.relative_humidity.xml \
frameworks/native/data/etc/android.hardware.usb.accessory.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.usb.accessory.xml \
- frameworks/native/data/etc/android.hardware.usb.host.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.usb.host.xml \
frameworks/native/data/etc/android.hardware.wifi.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.wifi.xml \
- frameworks/native/data/etc/android.hardware.wifi.passpoint.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.wifi.passpoint.xml \
frameworks/native/data/etc/android.software.ipsec_tunnels.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.software.ipsec_tunnels.xml \
frameworks/native/data/etc/android.software.sip.voip.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.software.sip.voip.xml \
frameworks/native/data/etc/android.software.verified_boot.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.software.verified_boot.xml \
system/bt/vendor_libs/test_vendor_lib/data/controller_properties.json:vendor/etc/bluetooth/controller_properties.json \
device/google/cuttlefish/shared/config/task_profiles.json:$(TARGET_COPY_OUT_VENDOR)/etc/task_profiles.json \
- device/google/cuttlefish/shared/config/input/Crosvm_Virtio_Multitouch_Touchscreen.idc:$(TARGET_COPY_OUT_VENDOR)/usr/idc/Crosvm_Virtio_Multitouch_Touchscreen.idc
-
-ifeq ($(TARGET_RO_FILE_SYSTEM_TYPE),ext4)
-PRODUCT_COPY_FILES += \
- device/google/cuttlefish/shared/config/fstab.f2fs:$(TARGET_COPY_OUT_VENDOR_RAMDISK)/first_stage_ramdisk/fstab.f2fs \
- device/google/cuttlefish/shared/config/fstab.f2fs:$(TARGET_COPY_OUT_VENDOR_RAMDISK)/fstab.f2fs \
+ device/google/cuttlefish/shared/config/fstab.f2fs:$(TARGET_COPY_OUT_RAMDISK)/fstab.f2fs \
device/google/cuttlefish/shared/config/fstab.f2fs:$(TARGET_COPY_OUT_VENDOR)/etc/fstab.f2fs \
device/google/cuttlefish/shared/config/fstab.f2fs:$(TARGET_COPY_OUT_RECOVERY)/root/first_stage_ramdisk/fstab.f2fs \
- device/google/cuttlefish/shared/config/fstab.ext4:$(TARGET_COPY_OUT_VENDOR_RAMDISK)/first_stage_ramdisk/fstab.ext4 \
- device/google/cuttlefish/shared/config/fstab.ext4:$(TARGET_COPY_OUT_VENDOR_RAMDISK)/fstab.ext4 \
+ device/google/cuttlefish/shared/config/fstab.ext4:$(TARGET_COPY_OUT_RAMDISK)/fstab.ext4 \
device/google/cuttlefish/shared/config/fstab.ext4:$(TARGET_COPY_OUT_VENDOR)/etc/fstab.ext4 \
device/google/cuttlefish/shared/config/fstab.ext4:$(TARGET_COPY_OUT_RECOVERY)/root/first_stage_ramdisk/fstab.ext4
-else
-PRODUCT_COPY_FILES += \
- device/google/cuttlefish/shared/config/fstab-$(TARGET_RO_FILE_SYSTEM_TYPE).f2fs:$(TARGET_COPY_OUT_VENDOR_RAMDISK)/first_stage_ramdisk/fstab.f2fs \
- device/google/cuttlefish/shared/config/fstab-$(TARGET_RO_FILE_SYSTEM_TYPE).f2fs:$(TARGET_COPY_OUT_VENDOR_RAMDISK)/fstab.f2fs \
- device/google/cuttlefish/shared/config/fstab-$(TARGET_RO_FILE_SYSTEM_TYPE).f2fs:$(TARGET_COPY_OUT_VENDOR)/etc/fstab.f2fs \
- device/google/cuttlefish/shared/config/fstab-$(TARGET_RO_FILE_SYSTEM_TYPE).f2fs:$(TARGET_COPY_OUT_RECOVERY)/root/first_stage_ramdisk/fstab.f2fs \
- device/google/cuttlefish/shared/config/fstab-$(TARGET_RO_FILE_SYSTEM_TYPE).ext4:$(TARGET_COPY_OUT_VENDOR_RAMDISK)/first_stage_ramdisk/fstab.ext4 \
- device/google/cuttlefish/shared/config/fstab-$(TARGET_RO_FILE_SYSTEM_TYPE).ext4:$(TARGET_COPY_OUT_VENDOR_RAMDISK)/fstab.ext4 \
- device/google/cuttlefish/shared/config/fstab-$(TARGET_RO_FILE_SYSTEM_TYPE).ext4:$(TARGET_COPY_OUT_VENDOR)/etc/fstab.ext4 \
- device/google/cuttlefish/shared/config/fstab-$(TARGET_RO_FILE_SYSTEM_TYPE).ext4:$(TARGET_COPY_OUT_RECOVERY)/root/first_stage_ramdisk/fstab.ext4
-endif
ifeq ($(TARGET_VULKAN_SUPPORT),true)
PRODUCT_COPY_FILES += \
frameworks/native/data/etc/android.hardware.vulkan.level-0.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.vulkan.level.xml \
frameworks/native/data/etc/android.hardware.vulkan.version-1_0_3.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.vulkan.version.xml \
- frameworks/native/data/etc/android.software.vulkan.deqp.level-2021-03-01.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.software.vulkan.deqp.level.xml \
- frameworks/native/data/etc/android.software.opengles.deqp.level-2021-03-01.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.software.opengles.deqp.level.xml
+ frameworks/native/data/etc/android.software.vulkan.deqp.level-2020-03-01.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.software.vulkan.deqp.level.xml
endif
# Packages for HAL implementations
@@ -341,37 +246,21 @@ PRODUCT_PACKAGES += \
android.hardware.atrace@1.0-service
#
-# Weaver aidl HAL
-#
-PRODUCT_PACKAGES += \
- android.hardware.weaver-service.example
-
-#
-# OemLock aidl HAL
-#
-PRODUCT_PACKAGES += \
- android.hardware.oemlock-service.example
-
-#
# Authsecret HAL
#
PRODUCT_PACKAGES += \
android.hardware.authsecret@1.0-service
#
-# Authsecret AIDL HAL
-#
-PRODUCT_PACKAGES += \
- android.hardware.authsecret-service.example
-#
# Hardware Composer HAL
#
PRODUCT_PACKAGES += \
hwcomposer.drm_minigbm \
- hwcomposer.cutf \
+ hwcomposer.cutf_cvm_ashmem \
+ hwcomposer.cutf_hwc2 \
hwcomposer-stats \
- android.hardware.graphics.composer@2.3-impl \
- android.hardware.graphics.composer@2.3-service
+ android.hardware.graphics.composer@2.2-impl \
+ android.hardware.graphics.composer@2.2-service
#
# Gralloc HAL
@@ -383,80 +272,39 @@ PRODUCT_PACKAGES += \
#
# Bluetooth HAL and Compatibility Bluetooth library (for older revs).
#
-ifeq ($(LOCAL_BLUETOOTH_PRODUCT_PACKAGE),)
-ifeq ($(TARGET_ENABLE_HOST_BLUETOOTH_EMULATION),true)
-ifeq ($(TARGET_USE_BTLINUX_HAL_IMPL),true)
- LOCAL_BLUETOOTH_PRODUCT_PACKAGE := android.hardware.bluetooth@1.1-service.btlinux
-else
- LOCAL_BLUETOOTH_PRODUCT_PACKAGE := android.hardware.bluetooth@1.1-service.remote
-endif
-else
- LOCAL_BLUETOOTH_PRODUCT_PACKAGE := android.hardware.bluetooth@1.1-service.sim
-endif
- DEVICE_MANIFEST_FILE += device/google/cuttlefish/shared/config/manifest_android.hardware.bluetooth@1.1-service.xml
-endif
-
-PRODUCT_PACKAGES += $(LOCAL_BLUETOOTH_PRODUCT_PACKAGE)
-
-PRODUCT_PACKAGES += android.hardware.bluetooth.audio@2.1-impl
+PRODUCT_PACKAGES += \
+ android.hardware.bluetooth@1.1-service.sim \
+ android.hardware.bluetooth.audio@2.0-impl
#
# Audio HAL
#
-LOCAL_AUDIO_PRODUCT_PACKAGE ?= \
+PRODUCT_PACKAGES += \
audio.primary.cutf \
audio.r_submix.default \
- android.hardware.audio@6.0-impl \
- android.hardware.audio.effect@6.0-impl \
- android.hardware.audio@2.0-service
-
-LOCAL_AUDIO_PRODUCT_COPY_FILES ?= \
- device/google/cuttlefish/shared/config/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 \
- frameworks/av/services/audiopolicy/config/primary_audio_policy_configuration.xml:$(TARGET_COPY_OUT_VENDOR)/etc/primary_audio_policy_configuration.xml
-
-LOCAL_AUDIO_DEVICE_PACKAGE_OVERLAYS ?=
-
-PRODUCT_PACKAGES += $(LOCAL_AUDIO_PRODUCT_PACKAGE)
-PRODUCT_COPY_FILES += $(LOCAL_AUDIO_PRODUCT_COPY_FILES)
-DEVICE_PACKAGE_OVERLAYS += $(LOCAL_AUDIO_DEVICE_PACKAGE_OVERLAYS)
+ android.hardware.audio@6.0-impl:32 \
+ android.hardware.audio.effect@6.0-impl:32 \
+ android.hardware.audio@2.0-service \
+ android.hardware.soundtrigger@2.3-impl \
#
-# BiometricsFace HAL (HIDL)
+# BiometricsFace HAL
#
PRODUCT_PACKAGES += \
android.hardware.biometrics.face@1.0-service.example
#
-# BiometricsFingerprint HAL (HIDL)
-#
-PRODUCT_PACKAGES += \
- android.hardware.biometrics.fingerprint@2.2-service.example
-
-#
-# BiometricsFace HAL (AIDL)
-#
-PRODUCT_PACKAGES += \
- android.hardware.biometrics.face-service.example
-
-#
-# BiometricsFingerprint HAL (AIDL)
-#
-PRODUCT_PACKAGES += \
- android.hardware.biometrics.fingerprint-service.example
-
-#
# Contexthub HAL
#
PRODUCT_PACKAGES += \
- android.hardware.contexthub@1.2-service.mock
+ android.hardware.contexthub@1.1-service.mock
#
# Drm HAL
#
PRODUCT_PACKAGES += \
- android.hardware.drm@1.4-service.clearkey \
- android.hardware.drm@1.4-service.widevine
+ android.hardware.drm@1.3-service.clearkey \
+ android.hardware.drm@1.3-service.widevine
#
# Dumpstate HAL
@@ -470,24 +318,21 @@ PRODUCT_PACKAGES += $(LOCAL_DUMPSTATE_PRODUCT_PACKAGE)
# Camera
#
PRODUCT_PACKAGES += \
- android.hardware.camera.provider@2.7-service-google \
+ android.hardware.camera.provider@2.6-service-google \
libgooglecamerahwl_impl \
- android.hardware.camera.provider@2.7-impl-google \
+ android.hardware.camera.provider@2.6-impl-google \
#
# Gatekeeper
#
-ifeq ($(LOCAL_GATEKEEPER_PRODUCT_PACKAGE),)
- LOCAL_GATEKEEPER_PRODUCT_PACKAGE := android.hardware.gatekeeper@1.0-service.software
-endif
PRODUCT_PACKAGES += \
- $(LOCAL_GATEKEEPER_PRODUCT_PACKAGE)
+ android.hardware.gatekeeper@1.0-service.software
#
# GPS
#
PRODUCT_PACKAGES += \
- android.hardware.gnss-service.example
+ android.hardware.gnss@2.1-service
# Health
ifeq ($(LOCAL_HEALTH_PRODUCT_PACKAGE),)
@@ -499,7 +344,7 @@ PRODUCT_PACKAGES += $(LOCAL_HEALTH_PRODUCT_PACKAGE)
# Health Storage
PRODUCT_PACKAGES += \
- android.hardware.health.storage-service.cuttlefish
+ android.hardware.health.storage@1.0-service.cuttlefish
# Identity Credential
PRODUCT_PACKAGES += \
@@ -530,17 +375,10 @@ PRODUCT_PACKAGES += \
android.hardware.lights-service.example \
#
-# KeyMint HAL
+# Keymaster HAL
#
-ifeq ($(LOCAL_KEYMINT_PRODUCT_PACKAGE),)
- LOCAL_KEYMINT_PRODUCT_PACKAGE := android.hardware.security.keymint-service
-endif
- PRODUCT_PACKAGES += \
- $(LOCAL_KEYMINT_PRODUCT_PACKAGE)
-
-# Keymint configuration
-PRODUCT_COPY_FILES += \
- frameworks/native/data/etc/android.software.device_id_attestation.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.software.device_id_attestation.xml
+PRODUCT_PACKAGES += \
+ android.hardware.keymaster@4.1-service
#
# Power HAL
@@ -552,7 +390,7 @@ PRODUCT_PACKAGES += \
# PowerStats HAL
#
PRODUCT_PACKAGES += \
- android.hardware.power.stats-service.example
+ android.hardware.power.stats@1.0-service.mock
#
# NeuralNetworks HAL
@@ -562,13 +400,7 @@ PRODUCT_PACKAGES += \
android.hardware.neuralnetworks@1.3-service-sample-float-fast \
android.hardware.neuralnetworks@1.3-service-sample-float-slow \
android.hardware.neuralnetworks@1.3-service-sample-minimal \
- android.hardware.neuralnetworks@1.3-service-sample-quant \
- android.hardware.neuralnetworks-service-sample-all \
- android.hardware.neuralnetworks-service-sample-float-fast \
- android.hardware.neuralnetworks-service-sample-float-slow \
- android.hardware.neuralnetworks-service-sample-minimal \
- android.hardware.neuralnetworks-service-sample-quant \
- android.hardware.neuralnetworks-shim-service-sample
+ android.hardware.neuralnetworks@1.3-service-sample-quant
#
# USB
@@ -581,42 +413,17 @@ PRODUCT_PACKAGES += \
# BootControl HAL
PRODUCT_PACKAGES += \
- android.hardware.boot@1.2-impl \
- android.hardware.boot@1.2-impl.recovery \
- android.hardware.boot@1.2-service
+ android.hardware.boot@1.1-impl \
+ android.hardware.boot@1.1-impl.recovery \
+ android.hardware.boot@1.1-service
# RebootEscrow HAL
PRODUCT_PACKAGES += \
android.hardware.rebootescrow-service.default
-# Memtrack HAL
-PRODUCT_PACKAGES += \
- android.hardware.memtrack-service.example
-
-# GKI APEX
-# Keep in sync with BOARD_KERNEL_MODULE_INTERFACE_VERSIONS
-ifneq (,$(TARGET_KERNEL_USE))
- ifneq (,$(filter 5.4, $(TARGET_KERNEL_USE)))
- PRODUCT_PACKAGES += com.android.gki.kmi_5_4_android12_unstable
- else
- PRODUCT_PACKAGES += com.android.gki.kmi_$(subst .,_,$(TARGET_KERNEL_USE))_android12_unstable
- endif
-endif
-
-# Prevent GKI and boot image downgrades
-PRODUCT_PRODUCT_PROPERTIES += \
- ro.build.ab_update.gki.prevent_downgrade_version=true \
- ro.build.ab_update.gki.prevent_downgrade_spl=true \
-
# WLAN driver configuration files
PRODUCT_COPY_FILES += \
- external/wpa_supplicant_8/wpa_supplicant/wpa_supplicant_template.conf:$(TARGET_COPY_OUT_VENDOR)/etc/wifi/wpa_supplicant.conf \
- $(LOCAL_PATH)/config/wpa_supplicant_overlay.conf:$(TARGET_COPY_OUT_VENDOR)/etc/wifi/wpa_supplicant_overlay.conf
-
-# Fastboot HAL & fastbootd
-PRODUCT_PACKAGES += \
- android.hardware.fastboot@1.1-impl-mock \
- fastbootd
+ $(LOCAL_PATH)/wpa_supplicant_overlay.conf:$(TARGET_COPY_OUT_VENDOR)/etc/wifi/wpa_supplicant_overlay.conf
# Recovery mode
ifneq ($(TARGET_NO_RECOVERY),true)
@@ -626,16 +433,6 @@ PRODUCT_COPY_FILES += \
device/google/cuttlefish/shared/config/cgroups.json:$(TARGET_COPY_OUT_RECOVERY)/root/vendor/etc/cgroups.json \
device/google/cuttlefish/shared/config/ueventd.rc:$(TARGET_COPY_OUT_RECOVERY)/root/ueventd.cutf_cvm.rc \
-PRODUCT_PACKAGES += \
- update_engine_sideload
-
-endif
-
-ifdef TARGET_DEDICATED_RECOVERY
-PRODUCT_BUILD_RECOVERY_IMAGE := true
-PRODUCT_PACKAGES += linker.vendor_ramdisk shell_and_utilities_vendor_ramdisk
-else
-PRODUCT_PACKAGES += linker.recovery shell_and_utilities_recovery
endif
#
@@ -647,26 +444,10 @@ PRODUCT_COPY_FILES += \
# Host packages to install
PRODUCT_HOST_PACKAGES += socket_vsock_proxy
-PRODUCT_EXTRA_VNDK_VERSIONS := 28 29 30
+PRODUCT_EXTRA_VNDK_VERSIONS := 28 29
PRODUCT_SOONG_NAMESPACES += external/mesa3d
-#for Confirmation UI
-PRODUCT_SOONG_NAMESPACES += vendor/google_devices/common/proprietary/confirmatioui_hal
-
# Need this so that the application's loop on reading input can be synchronized
# with HW VSYNC
-PRODUCT_VENDOR_PROPERTIES += \
- ro.surface_flinger.running_without_sync_framework=true
-
-# Set support one-handed mode
-PRODUCT_PRODUCT_PROPERTIES += \
- ro.support_one_handed_mode=true
-
-# Set one_handed_mode screen translate offset percentage
-PRODUCT_PRODUCT_PROPERTIES += \
- persist.debug.one_handed_offset_percentage=50
-
-# Set one_handed_mode translate animation duration milliseconds
-PRODUCT_PRODUCT_PROPERTIES += \
- persist.debug.one_handed_translate_animation_duration=300
+PRODUCT_DEFAULT_PROPERTY_OVERRIDES += ro.surface_flinger.running_without_sync_framework=true
diff --git a/shared/foldable/android-info.txt b/shared/foldable/android-info.txt
deleted file mode 100644
index 855268558..000000000
--- a/shared/foldable/android-info.txt
+++ /dev/null
@@ -1 +0,0 @@
-config=foldable
diff --git a/shared/foldable/device_state_configuration.xml b/shared/foldable/device_state_configuration.xml
deleted file mode 100644
index 9618b117f..000000000
--- a/shared/foldable/device_state_configuration.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-<device-state-config>
- <device-state>
- <identifier>0</identifier>
- <name>CLOSED</name>
- <conditions>
- <lid-switch>
- <open>false</open>
- </lid-switch>
- </conditions>
- </device-state>
- <device-state>
- <identifier>1</identifier>
- <name>HALF_OPENED</name>
- <conditions>
- <lid-switch>
- <open>true</open>
- </lid-switch>
- <sensor>
- <type>android.sensor.hinge_angle</type>
- <name>Hinge Angle Sensor</name>
- <value>
- <min>0</min>
- <max>180</max>
- </value>
- </sensor>
- </conditions>
- </device-state>
- <device-state>
- <identifier>2</identifier>
- <name>OPENED</name>
- <conditions>
- <lid-switch>
- <open>true</open>
- </lid-switch>
- </conditions>
- </device-state>
-</device-state-config>
diff --git a/shared/foldable/overlay/frameworks/base/core/res/res/values/config.xml b/shared/foldable/overlay/frameworks/base/core/res/res/values/config.xml
deleted file mode 100644
index 2c540e1ef..000000000
--- a/shared/foldable/overlay/frameworks/base/core/res/res/values/config.xml
+++ /dev/null
@@ -1,42 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2021, 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.
-*/
--->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- Indicate the display area rect for foldable devices in folded state. -->
- <!-- left and right bounds come from: (open_width/2) +/- (folded_width)/2 -->
- <string name="config_foldedArea">476 0 1292 2208</string>
- <!-- WindowsManager JetPack display features -->
- <string name="config_display_features" translatable="false">fold-[884,0,884,2208]</string>
- <!-- Map of System DeviceState supplied by DeviceStateManager to WM Jetpack posture. -->
- <string-array name="config_device_state_postures" translatable="false">
- <item>0:1</item> <!-- CLOSED : STATE_FLAT -->
- <item>3:2</item> <!-- HALF_OPENED : STATE_HALF_OPENED -->
- <item>2:3</item> <!-- OPENED : STATE_FLIPPED -->
- </string-array>
- <!-- The device states (supplied by DeviceStateManager) that should be treated as folded by the
- display fold controller. -->
- <integer-array name="config_foldedDeviceStates" translatable="false">
- <item>0</item> <!-- CLOSED -->
- </integer-array>
- <!-- Controls whether the device support multi window modes like split-screen. -->
- <bool name="config_supportsMultiWindow">true</bool>
- <!-- Controls whether device supports split-screen mode. -->
- <bool name="config_supportsSplitScreenMultiWindow">true</bool>
- <!-- Radius of the software rounded corners. -->
- <dimen name="rounded_corner_radius">34px</dimen>
-</resources>
diff --git a/shared/go/device.mk b/shared/go/device.mk
index e16592348..7c7f719b6 100644
--- a/shared/go/device.mk
+++ b/shared/go/device.mk
@@ -15,11 +15,11 @@
#
$(call inherit-product, build/target/product/go_defaults.mk)
-$(call inherit-product, device/google/cuttlefish/shared/phone/device.mk)
# By default, enable zram; experiment can toggle the flag,
# which takes effect on boot
-PRODUCT_VENDOR_PROPERTIES += \
+PRODUCT_PROPERTY_OVERRIDES += \
+ ro.statsd.enable=true \
pm.dexopt.downgrade_after_inactive_days=10 \
pm.dexopt.shared=quicken \
dalvik.vm.heapgrowthlimit=128m \
diff --git a/shared/go_512/device.mk b/shared/go_512/device.mk
index 0ab601b56..4a95a7383 100644
--- a/shared/go_512/device.mk
+++ b/shared/go_512/device.mk
@@ -15,11 +15,11 @@
#
$(call inherit-product, build/target/product/go_defaults_512.mk)
-$(call inherit-product, device/google/cuttlefish/shared/phone/device.mk)
# By default, enable zram; experiment can toggle the flag,
# which takes effect on boot
-PRODUCT_VENDOR_PROPERTIES += \
+PRODUCT_PROPERTY_OVERRIDES += \
+ ro.statsd.enable=true \
pm.dexopt.downgrade_after_inactive_days=10 \
pm.dexopt.shared=quicken \
dalvik.vm.heapgrowthlimit=128m \
diff --git a/shared/overlay/frameworks/base/core/res/res/xml/power_profile.xml b/shared/overlay/frameworks/base/core/res/res/xml/power_profile.xml
index 48c44486b..bdcb48d14 100644
--- a/shared/overlay/frameworks/base/core/res/res/xml/power_profile.xml
+++ b/shared/overlay/frameworks/base/core/res/res/xml/power_profile.xml
@@ -20,7 +20,7 @@
<device name="Android">
<!-- Most values are the incremental current used by a feature,
in mA (measured at nominal voltage).
- The default values are deliberately incorrect unused values.
+ The default values are deliberately incorrect dummy values.
OEM's must measure and provide actual values before
shipping a device.
Example real-world values are given in comments, but they
diff --git a/shared/overlay/frameworks/base/packages/SettingsProvider/res/values/defaults.xml b/shared/overlay/frameworks/base/packages/SettingsProvider/res/values/defaults.xml
index baef765ee..3213eab5c 100644
--- a/shared/overlay/frameworks/base/packages/SettingsProvider/res/values/defaults.xml
+++ b/shared/overlay/frameworks/base/packages/SettingsProvider/res/values/defaults.xml
@@ -20,5 +20,4 @@
<bool name="def_stay_on_while_plugged_in">true</bool>
<bool name="def_install_non_market_apps">true</bool>
<bool name="def_package_verifier_enable">false</bool>
- <bool name="def_accelerometer_rotation">true</bool>
</resources>
diff --git a/shared/pc/OWNERS b/shared/pc/OWNERS
deleted file mode 100644
index 47eb80ec1..000000000
--- a/shared/pc/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-# pc cuttlefish leads
-armenk@google.com
-xutan@google.com \ No newline at end of file
diff --git a/shared/pc/device_vendor.mk b/shared/pc/device_vendor.mk
deleted file mode 100644
index ad597c516..000000000
--- a/shared/pc/device_vendor.mk
+++ /dev/null
@@ -1,28 +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.
-#
-
-PRODUCT_MANIFEST_FILES += device/google/cuttlefish/shared/config/product_manifest.xml
-SYSTEM_EXT_MANIFEST_FILES += device/google/cuttlefish/shared/config/system_ext_manifest.xml
-
-$(call inherit-product, $(SRC_TARGET_DIR)/product/handheld_vendor.mk)
-
-PRODUCT_COPY_FILES += \
- frameworks/native/data/etc/pc_core_hardware.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/pc_core_hardware.xml
-
-$(call inherit-product, frameworks/native/build/tablet-7in-xhdpi-2048-dalvik-heap.mk)
-$(call inherit-product, device/google/cuttlefish/shared/device.mk)
-
-DEVICE_PACKAGE_OVERLAYS += device/google/cuttlefish/shared/pc/overlay \ No newline at end of file
diff --git a/shared/permissions/cuttlefish_excluded_hardware.xml b/shared/permissions/cuttlefish_excluded_hardware.xml
index c3d03d597..366028986 100644
--- a/shared/permissions/cuttlefish_excluded_hardware.xml
+++ b/shared/permissions/cuttlefish_excluded_hardware.xml
@@ -14,6 +14,7 @@
limitations under the License.
-->
<permissions>
+ <unavailable-feature name="android.hardware.microphone" />
<unavailable-feature name="android.software.print" />
<unavailable-feature name="android.software.voice_recognizers" />
</permissions>
diff --git a/shared/phone/android-info.txt b/shared/phone/android-info.txt
deleted file mode 100644
index 2286c3d30..000000000
--- a/shared/phone/android-info.txt
+++ /dev/null
@@ -1 +0,0 @@
-config=phone
diff --git a/shared/phone/device.mk b/shared/phone/device.mk
index 4b5f041ae..56bed4edf 100644
--- a/shared/phone/device.mk
+++ b/shared/phone/device.mk
@@ -14,18 +14,17 @@
# limitations under the License.
#
-PRODUCT_MANIFEST_FILES += device/google/cuttlefish/shared/config/product_manifest.xml
-SYSTEM_EXT_MANIFEST_FILES += device/google/cuttlefish/shared/config/system_ext_manifest.xml
+DEVICE_MANIFEST_FILE += device/google/cuttlefish/shared/config/manifest.xml
$(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_base_telephony.mk)
$(call inherit-product, frameworks/native/build/phone-xhdpi-2048-dalvik-heap.mk)
$(call inherit-product, device/google/cuttlefish/shared/device.mk)
-PRODUCT_VENDOR_PROPERTIES += \
+PRODUCT_PROPERTY_OVERRIDES += \
keyguard.no_require_sim=true \
ro.cdma.home.operator.alpha=Android \
ro.cdma.home.operator.numeric=302780 \
- ro.telephony.default_network=9 \
+ vendor.rild.libpath=libcuttlefish-ril.so \
PRODUCT_PACKAGES += \
MmsService \
@@ -33,15 +32,12 @@ PRODUCT_PACKAGES += \
PhoneService \
Telecom \
TeleService \
- libcuttlefish-ril-2 \
+ libcuttlefish-ril \
libcuttlefish-rild
PRODUCT_COPY_FILES += \
- frameworks/native/data/etc/android.hardware.faketouch.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.faketouch.xml \
frameworks/native/data/etc/android.hardware.telephony.gsm.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.telephony.gsm.xml
-DEVICE_PACKAGE_OVERLAYS += device/google/cuttlefish/shared/phone/overlay
-
# These flags are important for the GSI, but break auto
# These are used by aosp_cf_x86_go_phone targets
PRODUCT_ENFORCE_RRO_TARGETS := framework-res
diff --git a/shared/phone/device_vendor.mk b/shared/phone/device_vendor.mk
index 61f72c1b5..1c4d2d430 100644
--- a/shared/phone/device_vendor.mk
+++ b/shared/phone/device_vendor.mk
@@ -14,8 +14,7 @@
# limitations under the License.
#
-PRODUCT_MANIFEST_FILES += device/google/cuttlefish/shared/config/product_manifest.xml
-SYSTEM_EXT_MANIFEST_FILES += device/google/cuttlefish/shared/config/system_ext_manifest.xml
+DEVICE_MANIFEST_FILE += device/google/cuttlefish/shared/config/manifest.xml
$(call inherit-product, $(SRC_TARGET_DIR)/product/handheld_vendor.mk)
$(call inherit-product, $(SRC_TARGET_DIR)/product/telephony_vendor.mk)
@@ -26,12 +25,12 @@ PRODUCT_COPY_FILES += \
$(call inherit-product, frameworks/native/build/phone-xhdpi-2048-dalvik-heap.mk)
$(call inherit-product, device/google/cuttlefish/shared/device.mk)
-PRODUCT_VENDOR_PROPERTIES += \
+PRODUCT_PROPERTY_OVERRIDES += \
keyguard.no_require_sim=true \
ro.cdma.home.operator.alpha=Android \
ro.cdma.home.operator.numeric=302780 \
ro.com.android.dataroaming=true \
- ro.telephony.default_network=9 \
+ vendor.rild.libpath=libcuttlefish-ril.so \
# TODO: not existing anymore?
PRODUCT_PACKAGES += \
@@ -39,16 +38,8 @@ PRODUCT_PACKAGES += \
PhoneService \
PRODUCT_PACKAGES += \
- libcuttlefish-ril-2 \
+ libcuttlefish-ril \
libcuttlefish-rild
PRODUCT_COPY_FILES += \
- frameworks/native/data/etc/android.hardware.biometrics.face.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.biometrics.face.xml \
- frameworks/native/data/etc/android.hardware.faketouch.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.faketouch.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.telephony.gsm.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.telephony.gsm.xml \
- frameworks/native/data/etc/android.hardware.telephony.ims.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.telephony.ims.xml
-
-DEVICE_PACKAGE_OVERLAYS += device/google/cuttlefish/shared/phone/overlay
-
-TARGET_BOARD_INFO_FILE ?= device/google/cuttlefish/shared/phone/android-info.txt
+ frameworks/native/data/etc/android.hardware.telephony.gsm.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.telephony.gsm.xml
diff --git a/shared/sepolicy/OWNERS b/shared/sepolicy/OWNERS
index 2975ddf68..854d2e97d 100644
--- a/shared/sepolicy/OWNERS
+++ b/shared/sepolicy/OWNERS
@@ -9,4 +9,5 @@ jiyong@google.com
nnk@google.com
smoreland@google.com
sspatil@google.com
+tomcherry@google.com
trong@google.com
diff --git a/shared/sepolicy/product/private/file_contexts b/shared/sepolicy/product/private/file_contexts
index 0b9214402..f0255a0a2 100644
--- a/shared/sepolicy/product/private/file_contexts
+++ b/shared/sepolicy/product/private/file_contexts
@@ -1,4 +1,5 @@
#############################
# Product files
#
+/product/bin/suspend_blocker u:object_r:suspend_blocker_exec:s0
/product/bin/tombstone_transmit u:object_r:tombstone_transmit_exec:s0
diff --git a/shared/sepolicy/product/private/suspend_blocker.te b/shared/sepolicy/product/private/suspend_blocker.te
new file mode 100644
index 000000000..41c72b95d
--- /dev/null
+++ b/shared/sepolicy/product/private/suspend_blocker.te
@@ -0,0 +1,6 @@
+type suspend_blocker, domain, coredomain;
+type suspend_blocker_exec, exec_type, file_type;
+
+init_daemon_domain(suspend_blocker);
+
+wakelock_use(suspend_blocker);
diff --git a/shared/sepolicy/product/private/tombstone_transmit.te b/shared/sepolicy/product/private/tombstone_transmit.te
index 289be52da..a17ed104a 100644
--- a/shared/sepolicy/product/private/tombstone_transmit.te
+++ b/shared/sepolicy/product/private/tombstone_transmit.te
@@ -1,9 +1,9 @@
type tombstone_transmit, domain, coredomain;
-type tombstone_transmit_exec, exec_type, system_file_type, file_type;
+type tombstone_transmit_exec, exec_type, file_type;
init_daemon_domain(tombstone_transmit);
-product_internal_prop(vsock_tombstone_port_prop)
+type vsock_tombstone_port_prop, property_type;
get_prop(tombstone_transmit, vsock_tombstone_port_prop)
allow tombstone_transmit self:capability net_admin;
diff --git a/shared/sepolicy/system_ext/private/con_monitor.te b/shared/sepolicy/system_ext/private/con_monitor.te
index c708b7a77..d638ac160 100644
--- a/shared/sepolicy/system_ext/private/con_monitor.te
+++ b/shared/sepolicy/system_ext/private/con_monitor.te
@@ -1,9 +1,10 @@
# ConnectivityMonitor app
-type con_monitor_app, domain, coredomain;
+type con_monitor_app, domain;
app_domain(con_monitor_app)
set_prop(con_monitor_app, radio_prop)
+set_prop(con_monitor_app, vendor_radio_prop)
userdebug_or_eng(`set_prop(con_monitor_app, dumpstate_options_prop)')
allow con_monitor_app app_api_service:service_manager find;
allow con_monitor_app radio_vendor_data_file:dir rw_dir_perms;
diff --git a/shared/sepolicy/system_ext/private/flipendo.te b/shared/sepolicy/system_ext/private/flipendo.te
deleted file mode 100644
index bdf57dcdd..000000000
--- a/shared/sepolicy/system_ext/private/flipendo.te
+++ /dev/null
@@ -1 +0,0 @@
-gpu_access(flipendo)
diff --git a/shared/sepolicy/system_ext/private/mediatranscoding.te b/shared/sepolicy/system_ext/private/mediatranscoding.te
deleted file mode 100644
index 47f6d8e76..000000000
--- a/shared/sepolicy/system_ext/private/mediatranscoding.te
+++ /dev/null
@@ -1,2 +0,0 @@
-# Allow mediatranscoding service to access the GPU
-gpu_access(mediatranscoding)
diff --git a/shared/sepolicy/system_ext/private/property.te b/shared/sepolicy/system_ext/private/property.te
index c7cab203b..ffe5680db 100644
--- a/shared/sepolicy/system_ext/private/property.te
+++ b/shared/sepolicy/system_ext/private/property.te
@@ -1,4 +1,4 @@
# Vendor aware available type
-vendor_restricted_prop(vendor_aware_available_prop)
+type vendor_aware_available_prop, property_type;
-vendor_restricted_prop(vendor_radio_prop)
+type vendor_radio_prop, property_type;
diff --git a/shared/sepolicy/system_ext/private/property_contexts b/shared/sepolicy/system_ext/private/property_contexts
index 13c17c3fd..ba4a683f1 100644
--- a/shared/sepolicy/system_ext/private/property_contexts
+++ b/shared/sepolicy/system_ext/private/property_contexts
@@ -5,5 +5,7 @@ persist.vendor.radio.VT_ENABLE u:object_r:vendor_radio_prop:s0
persist.vendor.radio.VT_HYBRID_ENABLE u:object_r:vendor_radio_prop:s0
persist.vendor.radio.videopause.mode u:object_r:vendor_radio_prop:s0
persist.vendor.radio.smlog_switch u:object_r:vendor_radio_prop:s0
+persist.radio.poweranomaly.start u:object_r:vendor_radio_prop:s0
+persist.radio.lowpowermonitor.start u:object_r:vendor_radio_prop:s0
ro.vendor.radio.log_loc u:object_r:vendor_radio_prop:s0
ro.vendor.radio.log_prefix u:object_r:vendor_radio_prop:s0
diff --git a/shared/sepolicy/system_ext/private/sample_tuner_tis_app.te b/shared/sepolicy/system_ext/private/sample_tuner_tis_app.te
deleted file mode 100644
index 60f5e6987..000000000
--- a/shared/sepolicy/system_ext/private/sample_tuner_tis_app.te
+++ /dev/null
@@ -1,7 +0,0 @@
-# Sample Tuner TIS app
-type sample_tuner_tis_app, domain;
-
-app_domain(sample_tuner_tis_app)
-
-allow sample_tuner_tis_app app_api_service:service_manager find;
-hal_client_domain(sample_tuner_tis_app, hal_tv_tuner);
diff --git a/shared/sepolicy/system_ext/private/seapp_contexts b/shared/sepolicy/system_ext/private/seapp_contexts
index 1cd866568..23c3681fa 100644
--- a/shared/sepolicy/system_ext/private/seapp_contexts
+++ b/shared/sepolicy/system_ext/private/seapp_contexts
@@ -4,6 +4,3 @@ user=_app seinfo=platform name=com.android.pixellogger domain=logger_app type=ap
# Connectivity monitor
user=_app isPrivApp=true seinfo=platform name=com.google.android.connectivitymonitor domain=con_monitor_app type=app_data_file levelFrom=all
-
-# Sample Tuner TIS
-user=system isPrivApp=true seinfo=platform name=com.android.tv.samples.sampletunertvinput domain=sample_tuner_tis_app type=app_data_file levelFrom=all
diff --git a/shared/sepolicy/vendor/adbd.te b/shared/sepolicy/vendor/adbd.te
index 4ed653afc..48c3e0cd5 100644
--- a/shared/sepolicy/vendor/adbd.te
+++ b/shared/sepolicy/vendor/adbd.te
@@ -4,6 +4,8 @@ allow adbd unlabeled:{socket vsock_socket} rw_socket_perms_no_ioctl;
allow adbd kernel:system module_request;
recovery_only(`
+allow adbd tmpfs:dir w_dir_perms;
+allow adbd tmpfs:file create_file_perms;
# TODO(b/130668487): Label the vsock sockets.
allow su unlabeled:{ socket vsock_socket } rw_socket_perms_no_ioctl;
')
diff --git a/shared/sepolicy/vendor/bt_device.te b/shared/sepolicy/vendor/bt_device.te
deleted file mode 100644
index 5c88bfb3f..000000000
--- a/shared/sepolicy/vendor/bt_device.te
+++ /dev/null
@@ -1 +0,0 @@
-type bt_device, dev_type; \ No newline at end of file
diff --git a/shared/sepolicy/vendor/bt_vhci_forwarder.te b/shared/sepolicy/vendor/bt_vhci_forwarder.te
deleted file mode 100644
index 21726968c..000000000
--- a/shared/sepolicy/vendor/bt_vhci_forwarder.te
+++ /dev/null
@@ -1,6 +0,0 @@
-type bt_vhci_forwarder, domain;
-type bt_vhci_forwarder_exec, exec_type, vendor_file_type, file_type;
-
-init_daemon_domain(bt_vhci_forwarder)
-
-allow bt_vhci_forwarder bt_device:chr_file { open read write ioctl};
diff --git a/shared/sepolicy/vendor/bug_map b/shared/sepolicy/vendor/bug_map
index 57cbf3cc7..e8f546e5f 100644
--- a/shared/sepolicy/vendor/bug_map
+++ b/shared/sepolicy/vendor/bug_map
@@ -1,6 +1,7 @@
init system_lib_file dir b/133444385
init system_lib_file file b/133444385
+logpersist logpersist capability b/132911257
+logpersist device file b/143108875
migrate_legacy_obb_data dalvikcache_data_file file b/152338071
+shell adbd vsock_socket b/131904985
system_server system_server process b/65201432
-gmscore_app hal_camera_prop file b/156287758
-priv_app radio_vendor_data_file dir b/188833462
diff --git a/shared/sepolicy/vendor/cameraserver.te b/shared/sepolicy/vendor/cameraserver.te
index 7bc3fbfa0..94146e11a 100644
--- a/shared/sepolicy/vendor/cameraserver.te
+++ b/shared/sepolicy/vendor/cameraserver.te
@@ -1 +1,4 @@
+# Read GCE initial metadata file
+allow cameraserver initial_metadata_file:file r_file_perms;
+
gpu_access(cameraserver)
diff --git a/shared/sepolicy/vendor/crash_dump.te b/shared/sepolicy/vendor/crash_dump.te
deleted file mode 100644
index 9242e771b..000000000
--- a/shared/sepolicy/vendor/crash_dump.te
+++ /dev/null
@@ -1 +0,0 @@
-dontaudit crash_dump gpu_device:dir *;
diff --git a/shared/sepolicy/vendor/cuttlefish_sensor_injection.te b/shared/sepolicy/vendor/cuttlefish_sensor_injection.te
deleted file mode 100644
index 9e7aca519..000000000
--- a/shared/sepolicy/vendor/cuttlefish_sensor_injection.te
+++ /dev/null
@@ -1,15 +0,0 @@
-type cuttlefish_sensor_injection, domain;
-type cuttlefish_sensor_injection_exec, exec_type, vendor_file_type, file_type;
-
-# Switch to cuttlefish_sensor_injection domain when executing from shell.
-domain_auto_trans(shell, cuttlefish_sensor_injection_exec, cuttlefish_sensor_injection)
-allow cuttlefish_sensor_injection shell:fd use;
-
-# Allow cuttlefish_sensor_injection to communicate over adb connection.
-allow cuttlefish_sensor_injection adbd:fd use;
-allow cuttlefish_sensor_injection adbd:unix_stream_socket { read write };
-# Needed to run the binary directly via adb socket.
-allow cuttlefish_sensor_injection devpts:chr_file { read write };
-
-# Grant cuttlefish_sensor_injection access to the ISensors HAL.
-hal_client_domain(cuttlefish_sensor_injection, hal_sensors)
diff --git a/shared/sepolicy/vendor/device.te b/shared/sepolicy/vendor/device.te
index b698e355c..e63eddf76 100644
--- a/shared/sepolicy/vendor/device.te
+++ b/shared/sepolicy/vendor/device.te
@@ -1,2 +1,3 @@
# Device types
type ab_block_device, dev_type;
+type virtual_serial_device, dev_type;
diff --git a/shared/sepolicy/vendor/dumpstate.te b/shared/sepolicy/vendor/dumpstate.te
index 6233ca154..34caf72fb 100644
--- a/shared/sepolicy/vendor/dumpstate.te
+++ b/shared/sepolicy/vendor/dumpstate.te
@@ -1,5 +1 @@
allow dumpstate hal_neuralnetworks_sample:process signal;
-
-allow dumpstate system_data_file:dir w_dir_perms;
-
-allow dumpstate gpu_device:dir search; \ No newline at end of file
diff --git a/shared/sepolicy/vendor/file.te b/shared/sepolicy/vendor/file.te
index 53c46283d..131c27562 100644
--- a/shared/sepolicy/vendor/file.te
+++ b/shared/sepolicy/vendor/file.te
@@ -1,4 +1,5 @@
# File types
+type initial_metadata_file, file_type;
type sensors_hal_socket, file_type;
type tombstone_snapshot_file, file_type;
type var_run_system_file, file_type;
diff --git a/shared/sepolicy/vendor/file_contexts b/shared/sepolicy/vendor/file_contexts
index 20538a50f..13ab51787 100644
--- a/shared/sepolicy/vendor/file_contexts
+++ b/shared/sepolicy/vendor/file_contexts
@@ -2,36 +2,47 @@
# Devices
#
-/dev/block/by-name/misc u:object_r:misc_block_device:s0
-/dev/block/by-name/boot_[ab] u:object_r:boot_block_device:s0
-/dev/block/by-name/vendor_boot_[ab] u:object_r:boot_block_device:s0
-/dev/block/by-name/vbmeta_[ab] u:object_r:ab_block_device:s0
-/dev/block/by-name/vbmeta_system_[ab] u:object_r:ab_block_device:s0
-/dev/block/by-name/super u:object_r:super_block_device:s0
-/dev/block/by-name/userdata u:object_r:userdata_block_device:s0
-/dev/block/by-name/metadata u:object_r:metadata_block_device:s0
-
-/dev/block/by-name/frp u:object_r:frp_block_device:s0
+# crosvm (x86) block devices
+/dev/block/pci/pci0000:00/0000:00:01\.0/by-name/misc u:object_r:misc_block_device:s0
+/dev/block/pci/pci0000:00/0000:00:01\.0/by-name/boot_[ab] u:object_r:boot_block_device:s0
+/dev/block/pci/pci0000:00/0000:00:01\.0/by-name/vendor_boot_[ab] u:object_r:boot_block_device:s0
+/dev/block/pci/pci0000:00/0000:00:01\.0/by-name/verity_[ab] u:object_r:ab_block_device:s0
+/dev/block/pci/pci0000:00/0000:00:01\.0/by-name/verity_system_[ab] u:object_r:ab_block_device:s0
+/dev/block/pci/pci0000:00/0000:00:01\.0/by-name/super u:object_r:super_block_device:s0
+/dev/block/pci/pci0000:00/0000:00:01\.0/by-name/userdata u:object_r:userdata_block_device:s0
+/dev/block/pci/pci0000:00/0000:00:01\.0/by-name/cache u:object_r:cache_block_device:s0
+/dev/block/pci/pci0000:00/0000:00:01\.0/by-name/metadata u:object_r:metadata_block_device:s0
+# crosvm (arm64) block devices
+/dev/block/platform/10000.pci/by-name/misc u:object_r:misc_block_device:s0
+/dev/block/platform/10000.pci/by-name/boot_[ab] u:object_r:boot_block_device:s0
+/dev/block/platform/10000.pci/by-name/vendor_boot_[ab] u:object_r:boot_block_device:s0
+/dev/block/platform/10000.pci/by-name/verity_[ab] u:object_r:ab_block_device:s0
+/dev/block/platform/10000.pci/by-name/verity_system_[ab] u:object_r:ab_block_device:s0
+/dev/block/platform/10000.pci/by-name/super u:object_r:super_block_device:s0
+/dev/block/platform/10000.pci/by-name/userdata u:object_r:userdata_block_device:s0
+/dev/block/platform/10000.pci/by-name/cache u:object_r:cache_block_device:s0
+/dev/block/platform/10000.pci/by-name/metadata u:object_r:metadata_block_device:s0
+# qemu block devices
+/dev/block/pci/pci0000:00/0000:00:03\.0/by-name/misc u:object_r:misc_block_device:s0
+/dev/block/pci/pci0000:00/0000:00:03\.0/by-name/boot_[ab] u:object_r:boot_block_device:s0
+/dev/block/pci/pci0000:00/0000:00:03\.0/by-name/vendor_boot_[ab] u:object_r:boot_block_device:s0
+/dev/block/pci/pci0000:00/0000:00:03\.0/by-name/verity_[ab] u:object_r:ab_block_device:s0
+/dev/block/pci/pci0000:00/0000:00:03\.0/by-name/verity_system_[ab] u:object_r:ab_block_device:s0
+/dev/block/pci/pci0000:00/0000:00:03\.0/by-name/super u:object_r:super_block_device:s0
+/dev/block/pci/pci0000:00/0000:00:03\.0/by-name/userdata u:object_r:userdata_block_device:s0
+/dev/block/pci/pci0000:00/0000:00:03\.0/by-name/cache u:object_r:cache_block_device:s0
+/dev/block/pci/pci0000:00/0000:00:03\.0/by-name/metadata u:object_r:metadata_block_device:s0
/dev/block/pmem0 u:object_r:rebootescrow_device:s0
/dev/block/zram0 u:object_r:swap_block_device:s0
/dev/dri u:object_r:gpu_device:s0
/dev/dri/card0 u:object_r:graphics_device:s0
/dev/dri/renderD128 u:object_r:gpu_device:s0
-/dev/hvc0 u:object_r:serial_device:s0
-/dev/hvc1 u:object_r:serial_device:s0
-/dev/hvc2 u:object_r:serial_device:s0
-/dev/hvc3 u:object_r:keymaster_device:s0
-/dev/hvc4 u:object_r:gatekeeper_device:s0
-/dev/hvc5 u:object_r:bt_device:s0
-
-/dev/vhci u:object_r:bt_device:s0
-
-# ARM serial console device
-/dev/ttyAMA[0-9]* u:object_r:serial_device:s0
+/dev/vport[0-9]p[0-9]* u:object_r:virtual_serial_device:s0
#############################
# Root files
+/initial\.metadata u:object_r:initial_metadata_file:s0
/ts_snap\.txt u:object_r:tombstone_snapshot_file:s0
#############################
@@ -43,56 +54,35 @@
/var/run/system(/.*)? u:object_r:var_run_system_file:s0
#############################
-# sys files
-# x86
-/sys/devices/pci0000:00/0000:00:[0-9a-fA-F]{2}\.0/virtio[0-9]+/net(/.*)? u:object_r:sysfs_net:s0
-# qemu (x86)
-/sys/devices/platform/10000.pci/pci0000:00/0000:00:[0-9a-fA-F]{2}\.0/virtio[0-9]+/net(/.*)? u:object_r:sysfs_net:s0
-# qemu (aarch64)
-/sys/devices/platform/4010000000.pcie/pci0000:00/0000:00:[0-9a-fA-F]{2}.0/virtio[0-9]+/net u:object_r:sysfs_net:s0
-# qemu (arm)
-/sys/devices/platform/3f000000.pcie/pci0000:00/0000:00:[0-9a-fA-F]{2}.0/virtio[0-9]+/net u:object_r:sysfs_net:s0
-
-#############################
# Vendor files
#
-/vendor/bin/cuttlefish_sensor_injection u:object_r:cuttlefish_sensor_injection_exec:s0
/vendor/bin/socket_vsock_proxy u:object_r:socket_vsock_proxy_exec:s0
+/vendor/bin/vsock_logcat u:object_r:vsock_logcat_exec:s0
/vendor/bin/vsoc_input_service u:object_r:vsoc_input_service_exec:s0
+/vendor/bin/vport_trigger u:object_r:vport_trigger_exec:s0
/vendor/bin/rename_netiface u:object_r:rename_netiface_exec:s0
-/vendor/bin/suspend_blocker u:object_r:suspend_blocker_exec:s0
/vendor/bin/hw/libcuttlefish-rild u:object_r:libcuttlefish_rild_exec:s0
-/vendor/bin/hw/android\.hardware\.camera\.provider@2\.7-service-google u:object_r:hal_camera_default_exec:s0
-/vendor/bin/hw/android\.hardware\.camera\.provider@2\.7-service-google-lazy u:object_r:hal_camera_default_exec:s0
+/vendor/bin/hw/android\.hardware\.camera\.provider@2\.6-service-google u:object_r:hal_camera_default_exec:s0
+/vendor/bin/hw/android\.hardware\.camera\.provider@2\.6-service-google-lazy u:object_r:hal_camera_default_exec:s0
/vendor/bin/hw/android\.hardware\.power\.stats@1\.0-service\.mock u:object_r:hal_power_stats_default_exec:s0
-/vendor/bin/hw/android\.hardware\.bluetooth@1\.1-service\.remote u:object_r:hal_bluetooth_remote_exec:s0
/vendor/bin/hw/android\.hardware\.bluetooth@1\.1-service\.sim u:object_r:hal_bluetooth_sim_exec:s0
-/vendor/bin/hw/android\.hardware\.contexthub@1\.2-service\.mock u:object_r:hal_contexthub_default_exec:s0
+/vendor/bin/hw/android\.hardware\.contexthub@1\.1-service\.mock u:object_r:hal_contexthub_default_exec:s0
/vendor/bin/hw/android\.hardware\.drm@[0-9]+\.[0-9]+-service\.clearkey u:object_r:hal_drm_clearkey_exec:s0
/vendor/bin/hw/android\.hardware\.drm@[0-9]+\.[0-9]+-service-lazy\.clearkey u:object_r:hal_drm_clearkey_exec:s0
/vendor/bin/hw/android\.hardware\.drm@[0-9]+\.[0-9]+-service\.widevine u:object_r:hal_drm_widevine_exec:s0
/vendor/bin/hw/android\.hardware\.drm@[0-9]+\.[0-9]+-service-lazy\.widevine u:object_r:hal_drm_widevine_exec:s0
/vendor/bin/hw/android\.hardware\.graphics\.allocator@4\.0-service\.minigbm u:object_r:hal_graphics_allocator_default_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\.health\.storage-service\.cuttlefish u:object_r:hal_health_storage_default_exec:s0
+/vendor/bin/hw/android\.hardware\.health\.storage@1\.0-service\.cuttlefish u:object_r:hal_health_storage_default_exec:s0
/vendor/bin/hw/android\.hardware\.lights-service\.example u:object_r:hal_light_default_exec:s0
/vendor/bin/hw/android\.hardware\.neuralnetworks@1\.3-service-sample-.* u:object_r:hal_neuralnetworks_sample_exec:s0
-/vendor/bin/hw/android\.hardware\.neuralnetworks-shim-service-sample u:object_r:hal_neuralnetworks_sample_exec:s0
-/vendor/bin/hw/android\.hardware\.neuralnetworks-service-sample-.* u:object_r:hal_neuralnetworks_sample_exec:s0
/vendor/bin/hw/android\.hardware\.vibrator@1\.x-service\.example u:object_r:hal_vibrator_default_exec:s0
+/vendor/bin/ip_link_add u:object_r:ip_link_add_exec:s0
/vendor/bin/setup_wifi u:object_r:setup_wifi_exec:s0
-/vendor/bin/bt_vhci_forwarder u:object_r:bt_vhci_forwarder_exec:s0
-
/vendor/bin/hw/android\.hardware\.sensors@2\.1-service\.mock u:object_r:hal_sensors_default_exec:s0
/vendor/bin/hw/android\.hardware\.input\.classifier@1\.0-service.default u:object_r:hal_input_classifier_default_exec:s0
/vendor/bin/hw/android\.hardware\.thermal@2\.0-service\.mock u:object_r:hal_thermal_default_exec:s0
-/vendor/bin/hw/android\.hardware\.security\.keymint-service\.remote u:object_r:hal_keymint_remote_exec:s0
-/vendor/bin/hw/android\.hardware\.keymaster@4\.1-service.remote u:object_r:hal_keymaster_remote_exec:s0
-/vendor/bin/hw/android\.hardware\.gatekeeper@1\.0-service.remote u:object_r:hal_gatekeeper_remote_exec:s0
-/vendor/bin/hw/android\.hardware\.oemlock-service.example u:object_r:hal_oemlock_default_exec:s0
-/vendor/bin/hw/android\.hardware\.weaver-service.example u:object_r:hal_weaver_default_exec:s0
/vendor/bin/hw/android\.hardware\.authsecret@1\.0-service u:object_r:hal_authsecret_default_exec:s0
-/vendor/bin/hw/android\.hardware\.authsecret-service.example u:object_r:hal_authsecret_default_exec:s0
/vendor/bin/hw/android\.hardware\.rebootescrow-service\.default u:object_r:hal_rebootescrow_default_exec:s0
/vendor/bin/init\.insmod\.sh u:object_r:init_insmod_sh_exec:s0
@@ -117,8 +107,3 @@
/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)?/libEGL_angle\.so u:object_r:same_process_hal_file:s0
-/vendor/lib(64)?/libGLESv1_CM_angle\.so u:object_r:same_process_hal_file:s0
-/vendor/lib(64)?/libGLESv2_angle\.so u:object_r:same_process_hal_file:s0
-/vendor/lib(64)?/libfeature_support_angle\.so u:object_r:same_process_hal_file:s0
-/vendor/lib(64)?/libGoldfishProfiler\.so u:object_r:same_process_hal_file:s0
diff --git a/shared/sepolicy/vendor/genfs_contexts b/shared/sepolicy/vendor/genfs_contexts
index 22cb59fce..14b81312e 100644
--- a/shared/sepolicy/vendor/genfs_contexts
+++ b/shared/sepolicy/vendor/genfs_contexts
@@ -1,80 +1,54 @@
-dnl Run "m4 genfs_contexts" to test
-dnl # $1 = pci prefix
-dnl # $2 = pci ID start (hex)
-dnl # $3 = virtio ID start (decimal)
-pushdef(`cf_pci_block_device', `dnl
-genfscon sysfs $1/0000:00:eval($2 + 0, 16, 2).0/virtio`'eval($3 + 0)`'/block u:object_r:sysfs_devices_block:s0 # vda
-genfscon sysfs $1/0000:00:eval($2 + 1, 16, 2).0/virtio`'eval($3 + 1)`'/block u:object_r:sysfs_devices_block:s0 # vdb
-genfscon sysfs $1/0000:00:eval($2 + 2, 16, 2).0/virtio`'eval($3 + 2)`'/block u:object_r:sysfs_devices_block:s0 # vdc
-genfscon sysfs $1/0000:00:eval($2 + 3, 16, 2).0/virtio`'eval($3 + 3)`'/ndbus0 u:object_r:sysfs_devices_block:s0 # pmem0
-dnl')dnl
-dnl
-dnl # $1 = pci prefix
-dnl # $2 = pci ID start (hex)
-pushdef(`cf_pci_gpu_device', `dnl
-genfscon sysfs $1/0000:00:eval($2, 16, 2).0/device u:object_r:sysfs_gpu:s0
-genfscon sysfs $1/0000:00:eval($2, 16, 2).0/subsystem_device u:object_r:sysfs_gpu:s0
-genfscon sysfs $1/0000:00:eval($2, 16, 2).0/subsystem_vendor u:object_r:sysfs_gpu:s0
-genfscon sysfs $1/0000:00:eval($2, 16, 2).0/uevent u:object_r:sysfs_gpu:s0
-genfscon sysfs $1/0000:00:eval($2, 16, 2).0/vendor u:object_r:sysfs_gpu:s0
-dnl')dnl
-dnl
-dnl # $1 = rtc prefix
-dnl # $2 = rtc number (decimal)
-dnl # $3 = rtc wakeup offset (decimal)
-pushdef(`cf_rtc_wakeup_alarmtimer', `dnl
-genfscon sysfs $1/wakeup/wakeup$3 u:object_r:sysfs_wakeup:s0
-genfscon sysfs $1/rtc/rtc$2/wakeup`'eval($3 + 1)`' u:object_r:sysfs_wakeup:s0 # <= 5.5
-genfscon sysfs $1/rtc/rtc$2/alarmtimer.0.auto/wakeup/wakeup`'eval($3 + 1)`' u:object_r:sysfs_wakeup:s0 # >5.5
-dnl')dnl
-dnl
# crosvm (x86)
-cf_pci_block_device(/devices/pci0000:00, 0x6, 5)
-cf_pci_gpu_device(/devices/pci0000:00, 0x11)
+genfscon sysfs /devices/pci0000:00/0000:00:08.0/virtio7/net u:object_r:sysfs_net:s0 # buried_eth0 & wlan0
+genfscon sysfs /devices/pci0000:00/0000:00:09.0/virtio8/net u:object_r:sysfs_net:s0 # rmnet0
+genfscon sysfs /devices/pci0000:00/0000:00:0b.0/device u:object_r:sysfs_gpu:s0
+genfscon sysfs /devices/pci0000:00/0000:00:0b.0/subsystem_device u:object_r:sysfs_gpu:s0
+genfscon sysfs /devices/pci0000:00/0000:00:0b.0/subsystem_vendor u:object_r:sysfs_gpu:s0
+genfscon sysfs /devices/pci0000:00/0000:00:0b.0/uevent u:object_r:sysfs_gpu:s0
+genfscon sysfs /devices/pci0000:00/0000:00:0b.0/vendor u:object_r:sysfs_gpu:s0
## find /sys/devices/platform/* -type d -name 'rtc[0-9]' | sed 's,/rtc[0-9],,'
-genfscon sysfs /devices/platform/rtc_cmos/rtc u:object_r:sysfs_rtc:s0
+## x86 rtc_cmos on crosvm does not currently expose rtcN/hctosys
## find /sys/devices/platform/* -type d -name 'wakeup[0-9]'
-cf_rtc_wakeup_alarmtimer(/devices/platform/rtc_cmos, 0, 0)
-genfscon sysfs /devices/platform/rtc-test.1/wakeup/wakeup2 u:object_r:sysfs_wakeup:s0
+genfscon sysfs /devices/platform/rtc_cmos/wakeup/wakeup0 u:object_r:sysfs_wakeup:s0
+genfscon sysfs /devices/platform/rtc-test.1/wakeup/wakeup1 u:object_r:sysfs_wakeup:s0
+genfscon sysfs /devices/platform/rtc-test.1/rtc/rtc1/wakeup2 u:object_r:sysfs_wakeup:s0 # <= 5.5
+genfscon sysfs /devices/platform/rtc-test.1/rtc/rtc1/alarmtimer.0.auto/wakeup/wakeup2 u:object_r:sysfs_wakeup:s0 # >5.5
genfscon sysfs /devices/platform/rtc-test.2/wakeup/wakeup3 u:object_r:sysfs_wakeup:s0
# crosvm (arm64)
-cf_pci_block_device(/devices/platform/10000.pci, 0x6, 4)
-cf_pci_gpu_device(/devices/platform/10000.pci/pci0000:00, 0x11)
+genfscon sysfs /devices/platform/10000.pci/pci0000:00/0000:00:08.0/virtio7/net u:object_r:sysfs_net:s0 # buried_eth0 & wlan0
+genfscon sysfs /devices/platform/10000.pci/pci0000:00/0000:00:09.0/virtio8/net u:object_r:sysfs_net:s0 # rmnet0
+genfscon sysfs /devices/platform/10000.pci/pci0000:00/0000:00:0b.0/device u:object_r:sysfs_gpu:s0
+genfscon sysfs /devices/platform/10000.pci/pci0000:00/0000:00:0b.0/subsystem_device u:object_r:sysfs_gpu:s0
+genfscon sysfs /devices/platform/10000.pci/pci0000:00/0000:00:0b.0/subsystem_vendor u:object_r:sysfs_gpu:s0
+genfscon sysfs /devices/platform/10000.pci/pci0000:00/0000:00:0b.0/uevent u:object_r:sysfs_gpu:s0
+genfscon sysfs /devices/platform/10000.pci/pci0000:00/0000:00:0b.0/vendor u:object_r:sysfs_gpu:s0
## find /sys/devices/platform/* -type d -name 'rtc[0-9]' | sed 's,/rtc[0-9],,'
genfscon sysfs /devices/platform/2000.rtc/rtc u:object_r:sysfs_rtc:s0
## find /sys/devices/platform/* -type d -name 'wakeup[0-9]'
## arm64 2000.rtc on crosvm does not currently expose a wakeup node
-cf_rtc_wakeup_alarmtimer(/devices/platform/rtc-test.1, 2, 0)
-genfscon sysfs /devices/platform/rtc-test.2/wakeup/wakeup2 u:object_r:sysfs_wakeup:s0
+genfscon sysfs /devices/platform/rtc-test.1/rtc/rtc2/wakeup1 u:object_r:sysfs_wakeup:s0 # <= 5.5
+genfscon sysfs /devices/platform/rtc-test.1/rtc/rtc2/alarmtimer.0.auto/wakeup/wakeup1 u:object_r:sysfs_wakeup:s0 # >5.5
# qemu (x86)
-cf_pci_block_device(/devices/pci0000:00, 0x7, 5)
+genfscon sysfs /devices/pci0000:00/0000:00:05.0/virtio3/net u:object_r:sysfs_net:s0 # buried_eth0 & wlan0
+genfscon sysfs /devices/pci0000:00/0000:00:06.0/virtio4/net u:object_r:sysfs_net:s0 # rmnet0
+# FIXME: Add sysfs_gpu labels for qemu
## find /sys/devices/platform/* -type d -name 'rtc[0-9]' | sed 's,/rtc[0-9],,'
-genfscon sysfs /devices/pnp0/00:04/rtc u:object_r:sysfs_rtc:s0
+genfscon sysfs /devices/pnp0/00:00/rtc u:object_r:sysfs_rtc:s0
## find /sys/devices/platform/* -type d -name 'wakeup[0-9][0-9]'
-cf_rtc_wakeup_alarmtimer(/devices/pnp0/00:04, 0, 19)
-genfscon sysfs /devices/platform/rtc-test.1/wakeup/wakeup21 u:object_r:sysfs_wakeup:s0
-genfscon sysfs /devices/platform/rtc-test.2/wakeup/wakeup22 u:object_r:sysfs_wakeup:s0
+genfscon sysfs /devices/pnp0/00:00/wakeup/wakeup13 u:object_r:sysfs_wakeup:s0
+genfscon sysfs /devices/pnp0/00:00/rtc/rtc0/wakeup14 u:object_r:sysfs_wakeup:s0 # <= 5.5
+genfscon sysfs /devices/pnp0/00:00/rtc/rtc0/alarmtimer.0.auto/wakeup/wakeup14 u:object_r:sysfs_wakeup:s0 # >5.5
+genfscon sysfs /devices/platform/rtc-test.1/wakeup/wakeup15 u:object_r:sysfs_wakeup:s0
+genfscon sysfs /devices/platform/rtc-test.2/wakeup/wakeup16 u:object_r:sysfs_wakeup:s0
-# qemu (arm64)
-cf_pci_block_device(/devices/platform/4010000000.pcie/pci0000:00, 0x6, 4)
-cf_pci_gpu_device(/devices/platform/4010000000.pcie/pci0000:00, 0x10)
-## find /sys/devices/platform/* -type d -name 'rtc[0-9]' | sed 's,/rtc[0-9],,'
-genfscon sysfs /devices/platform/9010000.pl031/rtc u:object_r:sysfs_rtc:s0
-## find /sys/devices/platform/* -type d -name 'wakeup[0-9]'
-cf_rtc_wakeup_alarmtimer(/devices/platform/9010000.pl031, 0, 0)
-
-# qemu (arm)
-cf_pci_block_device(/devices/platform/3f000000.pcie/pci0000:00, 0x6, 4)
-cf_pci_gpu_device(/devices/platform/3f000000.pcie/pci0000:00, 0xf)
+# common to qemu (x86) and crosvm (arm64)
+genfscon sysfs /devices/platform/rtc-test.1/wakeup/wakeup0 u:object_r:sysfs_wakeup:s0
+genfscon sysfs /devices/platform/rtc-test.2/wakeup/wakeup2 u:object_r:sysfs_wakeup:s0
# common on all platforms / vm managers
genfscon sysfs /devices/platform/rtc-test.0/rtc u:object_r:sysfs_rtc:s0
genfscon sysfs /devices/platform/rtc-test.1/rtc u:object_r:sysfs_rtc:s0
genfscon sysfs /devices/platform/rtc-test.2/rtc u:object_r:sysfs_rtc:s0
genfscon sysfs /bus/iio/devices u:object_r:sysfs_iio_devices:s0
-dnl
-popdef(`cf_pci_block_device')dnl
-popdef(`cf_pci_gpu_device')dnl
-popdef(`cf_rtc_wakeup_alarmtimer')dnl
diff --git a/shared/sepolicy/vendor/google/bug_map b/shared/sepolicy/vendor/google/bug_map
index 0521b52be..26c5581cf 100644
--- a/shared/sepolicy/vendor/google/bug_map
+++ b/shared/sepolicy/vendor/google/bug_map
@@ -1,2 +1 @@
-untrusted_app selinuxfs file b/175910397
zygote ramdump_app process b/139558100
diff --git a/shared/sepolicy/vendor/google/gmscore_app.te b/shared/sepolicy/vendor/google/gmscore_app.te
index 44cd1a7be..a29e3c438 100644
--- a/shared/sepolicy/vendor/google/gmscore_app.te
+++ b/shared/sepolicy/vendor/google/gmscore_app.te
@@ -1 +1,3 @@
+get_prop(gmscore_app, hal_camera_prop)
+
gpu_access(gmscore_app)
diff --git a/shared/sepolicy/vendor/google/hwservice.te b/shared/sepolicy/vendor/google/hwservice.te
index 1c32f8ff1..ca4766a2c 100644
--- a/shared/sepolicy/vendor/google/hwservice.te
+++ b/shared/sepolicy/vendor/google/hwservice.te
@@ -1 +1 @@
-type hal_wlc_hwservice, hwservice_manager_type, vendor_hwservice_type;
+type hal_wlc_hwservice, hwservice_manager_type;
diff --git a/shared/sepolicy/vendor/google/mediaprovider.te b/shared/sepolicy/vendor/google/mediaprovider.te
deleted file mode 100644
index 515ef26c2..000000000
--- a/shared/sepolicy/vendor/google/mediaprovider.te
+++ /dev/null
@@ -1 +0,0 @@
-gpu_access(mediaprovider)
diff --git a/shared/sepolicy/vendor/google/traceur_app.te b/shared/sepolicy/vendor/google/traceur_app.te
deleted file mode 100644
index ed1bead4e..000000000
--- a/shared/sepolicy/vendor/google/traceur_app.te
+++ /dev/null
@@ -1 +0,0 @@
-gpu_access(traceur_app)
diff --git a/shared/sepolicy/vendor/gpuservice.te b/shared/sepolicy/vendor/gpuservice.te
deleted file mode 100644
index 4deb99fad..000000000
--- a/shared/sepolicy/vendor/gpuservice.te
+++ /dev/null
@@ -1 +0,0 @@
-allow gpuservice gpu_device:dir { search ioctl };
diff --git a/shared/sepolicy/vendor/hal_bluetooth_remote.te b/shared/sepolicy/vendor/hal_bluetooth_remote.te
deleted file mode 100644
index 459f89175..000000000
--- a/shared/sepolicy/vendor/hal_bluetooth_remote.te
+++ /dev/null
@@ -1,8 +0,0 @@
-type hal_bluetooth_remote, domain;
-type hal_bluetooth_remote_exec, exec_type, vendor_file_type, file_type;
-
-hal_server_domain(hal_bluetooth_remote, hal_bluetooth)
-
-init_daemon_domain(hal_bluetooth_remote)
-
-allow hal_bluetooth_remote bt_device:chr_file { open read write ioctl}; \ No newline at end of file
diff --git a/shared/sepolicy/vendor/hal_bluetooth_sim.te b/shared/sepolicy/vendor/hal_bluetooth_sim.te
index d29b1a9d6..82bab59a7 100644
--- a/shared/sepolicy/vendor/hal_bluetooth_sim.te
+++ b/shared/sepolicy/vendor/hal_bluetooth_sim.te
@@ -1,9 +1,9 @@
type hal_bluetooth_sim, domain;
type hal_bluetooth_sim_exec, exec_type, vendor_file_type, file_type;
-vendor_internal_prop(vendor_bt_rootcanal_prop)
+type hal_bluetooth_sim_prop, property_type;
hal_server_domain(hal_bluetooth_sim, hal_bluetooth)
init_daemon_domain(hal_bluetooth_sim)
-get_prop(hal_bluetooth_sim, vendor_bt_rootcanal_prop)
+get_prop(hal_bluetooth_sim, hal_bluetooth_sim_prop)
diff --git a/shared/sepolicy/vendor/hal_camera_default.te b/shared/sepolicy/vendor/hal_camera_default.te
index 6bf571ced..2442d83bc 100644
--- a/shared/sepolicy/vendor/hal_camera_default.te
+++ b/shared/sepolicy/vendor/hal_camera_default.te
@@ -1,12 +1,13 @@
+type hal_camera_prop, property_type;
+
vndbinder_use(hal_camera_default)
hal_client_domain(hal_camera_default, hal_graphics_allocator)
+get_prop(hal_camera_default, hal_camera_prop)
+
# For camera hal to talk with sensor service
binder_call(hal_camera_default, sensor_service_server)
binder_call(sensor_service_server, hal_camera_default)
-# Allow the Camera HAL to communicate with the thermal HAL.
-hal_client_domain(hal_camera_default, hal_thermal)
-
gpu_access(hal_camera_default)
diff --git a/shared/sepolicy/vendor/hal_gatekeeper_remote.te b/shared/sepolicy/vendor/hal_gatekeeper_remote.te
deleted file mode 100644
index db895dddb..000000000
--- a/shared/sepolicy/vendor/hal_gatekeeper_remote.te
+++ /dev/null
@@ -1,14 +0,0 @@
-type hal_gatekeeper_remote, domain;
-hal_server_domain(hal_gatekeeper_remote, hal_gatekeeper)
-
-type hal_gatekeeper_remote_exec, exec_type, vendor_file_type, file_type;
-init_daemon_domain(hal_gatekeeper_remote)
-
-type gatekeeper_device, file_type;
-
-allow hal_gatekeeper_remote device:dir r_dir_perms;
-allow hal_gatekeeper_remote gatekeeper_device:chr_file rw_file_perms;
-
-# Write to kernel log (/dev/kmsg)
-allow hal_gatekeeper_remote kmsg_device:chr_file w_file_perms;
-allow hal_gatekeeper_remote kmsg_device:chr_file getattr;
diff --git a/shared/sepolicy/vendor/hal_graphics_allocator.te b/shared/sepolicy/vendor/hal_graphics_allocator.te
new file mode 100644
index 000000000..5975599a4
--- /dev/null
+++ b/shared/sepolicy/vendor/hal_graphics_allocator.te
@@ -0,0 +1,5 @@
+# TODO(b/64158954): Remove/update these rules once gralloc impl changes
+allow hal_graphics_allocator_client hal_graphics_allocator_default_tmpfs:file read;
+
+# Read GCE initial metadata file
+allow hal_graphics_allocator_server initial_metadata_file:file r_file_perms;
diff --git a/shared/sepolicy/vendor/hal_graphics_composer.te b/shared/sepolicy/vendor/hal_graphics_composer.te
index 492903876..6bba59d57 100644
--- a/shared/sepolicy/vendor/hal_graphics_composer.te
+++ b/shared/sepolicy/vendor/hal_graphics_composer.te
@@ -1,8 +1,8 @@
-vendor_restricted_prop(vendor_vsock_frames_port_prop)
+type vsock_frames_port_prop, property_type;
allow hal_graphics_composer_server hal_graphics_allocator_default_tmpfs:file read;
allow hal_graphics_composer_server self:{ socket vsock_socket } create_socket_perms_no_ioctl;
gpu_access(hal_graphics_composer_server)
-get_prop(hal_graphics_composer_server, vendor_vsock_frames_port_prop)
-get_prop(hal_graphics_composer_server, vendor_cuttlefish_config_server_port_prop)
+get_prop(hal_graphics_composer_server, vsock_frames_port_prop)
+get_prop(hal_graphics_composer_server, cuttlefish_config_server_port_prop)
diff --git a/shared/sepolicy/vendor/hal_graphics_composer_default.te b/shared/sepolicy/vendor/hal_graphics_composer_default.te
index 807ec7366..c3a7cab31 100644
--- a/shared/sepolicy/vendor/hal_graphics_composer_default.te
+++ b/shared/sepolicy/vendor/hal_graphics_composer_default.te
@@ -2,7 +2,4 @@ hal_client_domain(hal_graphics_composer_default, hal_graphics_allocator);
vndbinder_use(hal_graphics_composer_default)
allow hal_graphics_composer_default self:netlink_kobject_uevent_socket { bind create read };
-
-# Supress warnings for drm_hwcomposer trying to read some vendor.hwc.*
-# properties as Cuttlefish never configures these properties.
-dontaudit hal_graphics_composer_default default_prop:file read; \ No newline at end of file
+get_prop(hal_graphics_composer_default, cf_graphics_config_prop)
diff --git a/shared/sepolicy/vendor/hal_keymaster_remote.te b/shared/sepolicy/vendor/hal_keymaster_remote.te
deleted file mode 100644
index f85da041a..000000000
--- a/shared/sepolicy/vendor/hal_keymaster_remote.te
+++ /dev/null
@@ -1,14 +0,0 @@
-type hal_keymaster_remote, domain;
-hal_server_domain(hal_keymaster_remote, hal_keymaster)
-
-type hal_keymaster_remote_exec, exec_type, vendor_file_type, file_type;
-init_daemon_domain(hal_keymaster_remote)
-
-type keymaster_device, file_type;
-
-allow hal_keymaster_remote device:dir r_dir_perms;
-allow hal_keymaster_remote keymaster_device:chr_file rw_file_perms;
-
-# Write to kernel log (/dev/kmsg)
-allow hal_keymaster_remote kmsg_device:chr_file w_file_perms;
-allow hal_keymaster_remote kmsg_device:chr_file getattr;
diff --git a/shared/sepolicy/vendor/hal_keymint_remote.te b/shared/sepolicy/vendor/hal_keymint_remote.te
deleted file mode 100644
index 27f82915b..000000000
--- a/shared/sepolicy/vendor/hal_keymint_remote.te
+++ /dev/null
@@ -1,12 +0,0 @@
-type hal_keymint_remote, domain;
-hal_server_domain(hal_keymint_remote, hal_keymint)
-
-type hal_keymint_remote_exec, exec_type, vendor_file_type, file_type;
-init_daemon_domain(hal_keymint_remote)
-
-allow hal_keymint_remote device:dir r_dir_perms;
-allow hal_keymint_remote keymaster_device:chr_file rw_file_perms;
-
-# Write to kernel log (/dev/kmsg)
-allow hal_keymint_remote kmsg_device:chr_file w_file_perms;
-allow hal_keymint_remote kmsg_device:chr_file getattr;
diff --git a/shared/sepolicy/vendor/init.te b/shared/sepolicy/vendor/init.te
index 7f362ef8a..26f71100e 100644
--- a/shared/sepolicy/vendor/init.te
+++ b/shared/sepolicy/vendor/init.te
@@ -12,18 +12,6 @@ allow init kernel:system module_request;
allow init binfmt_miscfs:file w_file_perms;
allow init proc:dir mounton;
-# init relabel vbmeta* symlinks
-allow init ab_block_device:lnk_file relabelto;
-
# /mnt/sdcard -> /storage/self/primary symlink is deprecated. Ignore attempts to
# create it. This denial is fixed in core policy in Android R aosp/943799.
dontaudit init tmpfs:lnk_file create;
-
-# permit mount of virtiofs on /mnt/vendor/shared
-allow init mnt_vendor_file:dir mounton;
-
-allow init keymaster_device:chr_file rw_file_perms;
-allow init gatekeeper_device:chr_file rw_file_perms;
-allow init bt_device:chr_file rw_file_perms;
-
-allow init frp_block_device:blk_file setattr;
diff --git a/shared/sepolicy/vendor/ip_link_add.te b/shared/sepolicy/vendor/ip_link_add.te
new file mode 100644
index 000000000..a1c13e20f
--- /dev/null
+++ b/shared/sepolicy/vendor/ip_link_add.te
@@ -0,0 +1,10 @@
+type ip_link_add, domain;
+type ip_link_add_exec, exec_type, vendor_file_type, file_type;
+
+init_daemon_domain(ip_link_add)
+
+allow ip_link_add self:capability { net_admin net_raw sys_module };
+allow ip_link_add self:udp_socket { create ioctl };
+allow ip_link_add self:netlink_route_socket { bind create nlmsg_write read write };
+
+allow ip_link_add kernel:system module_request;
diff --git a/shared/sepolicy/vendor/kernel.te b/shared/sepolicy/vendor/kernel.te
new file mode 100644
index 000000000..b4eec4b99
--- /dev/null
+++ b/shared/sepolicy/vendor/kernel.te
@@ -0,0 +1,19 @@
+# kernel domain is used for all processes started before Android init installs SELinux policy.
+# Normally, no processes should be in this domain because clumping multiple processes into a single
+# SELinux domain overprivileges each of those processes.
+
+# TODO(b/65049764): Get rid of the hostapd instance started before Android init
+net_domain(kernel)
+allow kernel self:capability net_admin;
+allow kernel self:netlink_socket create_socket_perms_no_ioctl;
+allow kernel tmpfs:dir search;
+
+# TODO(b/65049764): Get rid of GCE proxy and similar daemons started before Android init
+# gce.meta.proxy and gce.ex.outer write to /dev/console which for some reason does not appear
+# labelled as console_device although it is labeled as such on the filesystem.
+allow kernel rootfs:chr_file write;
+
+# kdevtmpfs accesses devices before ueventd runs restorecon and relabels devices
+allow kernel device:chr_file { create setattr getattr unlink };
+allow kernel device:dir create_dir_perms;
+allow kernel self:capability mknod;
diff --git a/shared/sepolicy/vendor/libcuttlefish_rild.te b/shared/sepolicy/vendor/libcuttlefish_rild.te
index 8f3bbe707..49b7d500e 100644
--- a/shared/sepolicy/vendor/libcuttlefish_rild.te
+++ b/shared/sepolicy/vendor/libcuttlefish_rild.te
@@ -8,7 +8,6 @@ hal_server_domain(libcuttlefish_rild, hal_telephony)
# Failing to create these sockets appears to be non-fatal
net_domain(libcuttlefish_rild)
-get_prop(libcuttlefish_rild, vendor_cuttlefish_config_server_port_prop)
-get_prop(libcuttlefish_rild, vendor_modem_simulator_ports_prop)
+get_prop(libcuttlefish_rild, cuttlefish_config_server_port_prop)
allow libcuttlefish_rild self:{ socket vsock_socket } create_socket_perms_no_ioctl;
diff --git a/shared/sepolicy/vendor/logpersist.te b/shared/sepolicy/vendor/logpersist.te
index 226cb00bb..715240978 100644
--- a/shared/sepolicy/vendor/logpersist.te
+++ b/shared/sepolicy/vendor/logpersist.te
@@ -1,4 +1,8 @@
# Output to virtual serial console. Needed because seriallogging daemon
-# runs logcat and directs its output to hvcX the /dev filesystem.
+# runs logcat and directs its output to vportXpY or cf_logcat_pipe under
+# the /dev filesystem.
allow logpersist device:dir r_dir_perms;
-allow logpersist serial_device:chr_file ra_file_perms;
+allow logpersist device:fifo_file ra_file_perms;
+allow logpersist virtual_serial_device:chr_file ra_file_perms;
+
+allowxperm logpersist device:fifo_file ioctl F2FS_IOC_SET_PIN_FILE;
diff --git a/shared/sepolicy/vendor/property.te b/shared/sepolicy/vendor/property.te
index a727365b2..19e38969b 100644
--- a/shared/sepolicy/vendor/property.te
+++ b/shared/sepolicy/vendor/property.te
@@ -1,2 +1 @@
-vendor_restricted_prop(vendor_cuttlefish_config_server_port_prop)
-vendor_internal_prop(vendor_modem_simulator_ports_prop)
+type cuttlefish_config_server_port_prop, property_type;
diff --git a/shared/sepolicy/vendor/property_contexts b/shared/sepolicy/vendor/property_contexts
index ebbe2711b..ab2952705 100644
--- a/shared/sepolicy/vendor/property_contexts
+++ b/shared/sepolicy/vendor/property_contexts
@@ -1,14 +1,27 @@
-ro.boot.cpuvulkan.version u:object_r:vendor_graphics_config_prop:s0 exact int
-ro.boot.cuttlefish_config_server_port u:object_r:vendor_cuttlefish_config_server_port_prop:s0
-ro.boot.hardware.egl u:object_r:vendor_graphics_config_prop:s0 exact string
-ro.boot.hardware.gralloc u:object_r:vendor_graphics_config_prop:s0 exact string
-ro.boot.hardware.hwcomposer u:object_r:vendor_graphics_config_prop:s0 exact string
-ro.boot.hardware.vulkan u:object_r:vendor_graphics_config_prop:s0 exact string
-ro.boot.lcd_density u:object_r:vendor_graphics_config_prop:s0 exact int
-ro.boot.vsock_frames_port u:object_r:vendor_vsock_frames_port_prop:s0
-ro.boot.vsock_keyboard_port u:object_r:vendor_vsock_keyboard_port:s0
-ro.boot.modem_simulator_ports u:object_r:vendor_modem_simulator_ports_prop:s0
-ro.boot.vsock_touch_port u:object_r:vendor_vsock_touch_port:s0
-ro.boot.wifi_mac_address u:object_r:vendor_wifi_mac_address:s0
-vendor.bt.rootcanal_mac_address u:object_r:vendor_bt_rootcanal_prop:s0
-vendor.bt.rootcanal_test_console u:object_r:vendor_bt_rootcanal_prop:s0
+bt.rootcanal_mac_address u:object_r:hal_bluetooth_sim_prop:s0
+bt.rootcanal_test_console u:object_r:hal_bluetooth_sim_prop:s0
+qemu.sf.back_camera_caps u:object_r:hal_camera_prop:s0
+qemu.sf.front_camera_caps u:object_r:hal_camera_prop:s0
+qemu.sf.fake_camera u:object_r:hal_camera_prop:s0
+ro.boot.cuttlefish_config_server_port u:object_r:cuttlefish_config_server_port_prop:s0
+ro.boot.fstab_name u:object_r:cf_fstab_name_prop:s0 exact string
+ro.boot.hardware.egl u:object_r:cf_graphics_config_prop:s0 exact string
+ro.boot.hardware.gralloc u:object_r:cf_graphics_config_prop:s0 exact string
+ro.boot.hardware.hwcomposer u:object_r:cf_graphics_config_prop:s0 exact string
+ro.boot.hardware.vulkan u:object_r:cf_graphics_config_prop:s0 exact string
+ro.boot.lcd_density u:object_r:cf_graphics_config_prop:s0 exact int
+ro.boot.vsock_frames_port u:object_r:vsock_frames_port_prop:s0
+ro.boot.vsock_keyboard_port u:object_r:cuttlefish_vsock_keyboard_port:s0
+ro.boot.vsock_logcat_port u:object_r:vsock_logcat_port_prop:s0
+ro.boot.vsock_touch_port u:object_r:cuttlefish_vsock_touch_port:s0
+ro.boot.wifi_mac_address u:object_r:cuttlefish_wifi_mac_address:s0
+ro.cdma.home.operator.alpha u:object_r:vendor_init_radio_prop:s0
+ro.cdma.home.operator.numeric u:object_r:vendor_init_radio_prop:s0
+sys.cf.ser. u:object_r:sys_cf_ser_prop:s0
+vendor.ser. u:object_r:vendor_ser_prop:s0
+vendor.vsock_logcat_status u:object_r:vsock_logcat_status_prop:s0
+hwc.drm.device u:object_r:cf_graphics_config_prop:s0 exact string
+hwc.drm.exclude_non_hwfb_imports u:object_r:cf_graphics_config_prop:s0 exact int
+hwc.drm.primary_display_order u:object_r:cf_graphics_config_prop:s0 exact string
+hwc.drm.scale_with_gpu u:object_r:cf_graphics_config_prop:s0 exact int
+hwc.drm.use_overlay_planes u:object_r:cf_graphics_config_prop:s0 exact int
diff --git a/shared/sepolicy/vendor/radio.te b/shared/sepolicy/vendor/radio.te
deleted file mode 100644
index 62b7582f7..000000000
--- a/shared/sepolicy/vendor/radio.te
+++ /dev/null
@@ -1 +0,0 @@
-gpu_access(radio)
diff --git a/shared/sepolicy/vendor/recovery.te b/shared/sepolicy/vendor/recovery.te
index dcb710052..b0e515714 100644
--- a/shared/sepolicy/vendor/recovery.te
+++ b/shared/sepolicy/vendor/recovery.te
@@ -3,10 +3,10 @@ allow recovery gpu_device:dir search;
allow recovery graphics_device:chr_file rw_file_perms;
# Allow sideload from file pushed to fake /sdcard
-allow recovery vfat:dir r_dir_perms;
-allow recovery vfat:file r_file_perms;
+allow recovery appdomain_tmpfs:file r_file_perms;
# Seen during 'Wipe data/factory reset'
+allow recovery cache_block_device:blk_file rw_file_perms;
allow recovery devpts:chr_file rw_file_perms;
allow recovery kmsg_device:chr_file { getattr w_file_perms };
# Note: fsetid checks are triggered when creating a file in a directory with
diff --git a/shared/sepolicy/vendor/seapp_contexts b/shared/sepolicy/vendor/seapp_contexts
index f2a116f0d..820c41638 100644
--- a/shared/sepolicy/vendor/seapp_contexts
+++ b/shared/sepolicy/vendor/seapp_contexts
@@ -1,2 +1,2 @@
# GceService app
-user=_app isPrivApp=true seinfo=default name=com.android.google.gce.gceservice domain=gceservice type=app_data_file levelFrom=all
+user=_app isPrivApp=true seinfo=default name=com.android.google.gce.gceservice domain=gceservice type=app_data_file
diff --git a/shared/sepolicy/vendor/service_contexts b/shared/sepolicy/vendor/service_contexts
index d20d026cf..5a5ed0045 100644
--- a/shared/sepolicy/vendor/service_contexts
+++ b/shared/sepolicy/vendor/service_contexts
@@ -1,9 +1,2 @@
-android.hardware.neuralnetworks.IDevice/nnapi-sample_all u:object_r:hal_neuralnetworks_service:s0
-android.hardware.neuralnetworks.IDevice/nnapi-sample_float_fast u:object_r:hal_neuralnetworks_service:s0
-android.hardware.neuralnetworks.IDevice/nnapi-sample_float_slow u:object_r:hal_neuralnetworks_service:s0
-android.hardware.neuralnetworks.IDevice/nnapi-sample_minimal u:object_r:hal_neuralnetworks_service:s0
-android.hardware.neuralnetworks.IDevice/nnapi-sample_quant u:object_r:hal_neuralnetworks_service:s0
-android.hardware.neuralnetworks.IDevice/nnapi-sample_sl_shim u:object_r:hal_neuralnetworks_service:s0
-
# Binder service mappings
gce u:object_r:gce_service:s0
diff --git a/shared/sepolicy/vendor/setup_wifi.te b/shared/sepolicy/vendor/setup_wifi.te
index 23a34ebc0..a6bd363eb 100644
--- a/shared/sepolicy/vendor/setup_wifi.te
+++ b/shared/sepolicy/vendor/setup_wifi.te
@@ -9,6 +9,6 @@ allow setup_wifi self:netlink_route_socket { bind create nlmsg_write read write
allow setup_wifi kernel:system module_request;
-vendor_internal_prop(vendor_wifi_mac_address)
+type cuttlefish_wifi_mac_address, property_type;
-get_prop(setup_wifi, vendor_wifi_mac_address)
+get_prop(setup_wifi, cuttlefish_wifi_mac_address)
diff --git a/shared/sepolicy/vendor/shell.te b/shared/sepolicy/vendor/shell.te
index cc26032cf..ea0ee611b 100644
--- a/shared/sepolicy/vendor/shell.te
+++ b/shared/sepolicy/vendor/shell.te
@@ -1,5 +1 @@
allow shell serial_device:chr_file { getattr ioctl read write };
-allow shell cuttlefish_sensor_injection_exec:file rx_file_perms;
-
-# TODO(b/130668487): Label the vsock sockets.
-allow shell adbd:{ socket vsock_socket } rw_socket_perms_no_ioctl;
diff --git a/shared/sepolicy/vendor/socket_vsock_proxy.te b/shared/sepolicy/vendor/socket_vsock_proxy.te
index d4e2b1aba..eaca90943 100644
--- a/shared/sepolicy/vendor/socket_vsock_proxy.te
+++ b/shared/sepolicy/vendor/socket_vsock_proxy.te
@@ -4,7 +4,7 @@ type socket_vsock_proxy_exec, exec_type, vendor_file_type, file_type;
init_daemon_domain(socket_vsock_proxy)
allow socket_vsock_proxy self:global_capability_class_set { net_admin net_raw };
-allow socket_vsock_proxy self:{ socket vsock_socket } { create getopt read write listen accept bind shutdown };
+allow socket_vsock_proxy self:{ socket vsock_socket } { create read write listen accept bind };
# TODO: socket returned by accept() has unlabeled context on it. Give it a
# specific label.
diff --git a/shared/sepolicy/vendor/surfaceflinger.te b/shared/sepolicy/vendor/surfaceflinger.te
index 9b3e2c74a..05774e762 100644
--- a/shared/sepolicy/vendor/surfaceflinger.te
+++ b/shared/sepolicy/vendor/surfaceflinger.te
@@ -1,6 +1,5 @@
allow surfaceflinger self:process execmem;
-allow surfaceflinger hal_graphics_composer_default:dir search;
-allow surfaceflinger hal_graphics_composer_default:file r_file_perms;
-
+# Read GCE initial metadata file
+allow surfaceflinger initial_metadata_file:file r_file_perms;
gpu_access(surfaceflinger)
diff --git a/shared/sepolicy/vendor/suspend_blocker.te b/shared/sepolicy/vendor/suspend_blocker.te
deleted file mode 100644
index fa6e02a85..000000000
--- a/shared/sepolicy/vendor/suspend_blocker.te
+++ /dev/null
@@ -1,6 +0,0 @@
-type suspend_blocker, domain;
-type suspend_blocker_exec, exec_type, vendor_file_type, file_type;
-
-init_daemon_domain(suspend_blocker);
-
-wakelock_use(suspend_blocker);
diff --git a/shared/sepolicy/vendor/system_server.te b/shared/sepolicy/vendor/system_server.te
index 372ca5077..23497fca5 100644
--- a/shared/sepolicy/vendor/system_server.te
+++ b/shared/sepolicy/vendor/system_server.te
@@ -6,6 +6,3 @@
# allow execmem rule were added here.
permissive system_server;
gpu_access(system_server)
-
-# Cuttlefish is still using the legacy wifi HAL (pre-HIDL)
-get_prop(system_server, wifi_hal_prop)
diff --git a/shared/sepolicy/vendor/ueventd.te b/shared/sepolicy/vendor/ueventd.te
index 9cb896f90..985c8ec4d 100644
--- a/shared/sepolicy/vendor/ueventd.te
+++ b/shared/sepolicy/vendor/ueventd.te
@@ -1,4 +1 @@
allow ueventd metadata_file:dir search;
-
-allow ueventd keymaster_device:chr_file { rw_file_perms create setattr };
-allow ueventd gatekeeper_device:chr_file { rw_file_perms create setattr };
diff --git a/shared/sepolicy/vendor/update_engine_common.te b/shared/sepolicy/vendor/update_engine_common.te
deleted file mode 100644
index a79ce414e..000000000
--- a/shared/sepolicy/vendor/update_engine_common.te
+++ /dev/null
@@ -1 +0,0 @@
-allow update_engine_common ab_block_device:blk_file rw_file_perms;
diff --git a/shared/sepolicy/vendor/usbforward.te b/shared/sepolicy/vendor/usbforward.te
new file mode 100644
index 000000000..6d0833e0c
--- /dev/null
+++ b/shared/sepolicy/vendor/usbforward.te
@@ -0,0 +1,22 @@
+type usbforward, domain;
+type usbforward_exec, exec_type, vendor_file_type, file_type;
+
+init_daemon_domain(usbforward)
+
+# Virtual serial device I/O
+allow usbforward virtual_serial_device:chr_file rw_file_perms;
+
+# USB I/O
+allow usbforward usb_device:dir r_dir_perms;
+allow usbforward usb_device:chr_file rw_file_perms;
+
+# Read /sys/devices/platform/dummy_hcd.0/usb1/1-1/speed. Although this file is labelled
+# It is acceptable to give usbforward this wide access because usbforward is not a stock Android
+# domain and it does not run Android apps. Thus, the laxer access restrictions of this domain
+# do not impact how compatible the resulting Android emulator appears to system services and apps.
+allow usbforward sysfs:file r_file_perms;
+
+# Do not audit attempts to read /dev directory. This access does not appear to be necessary.
+dontaudit usbforward device:dir r_dir_perms;
+
+allow usbforward self:netlink_kobject_uevent_socket create_socket_perms_no_ioctl;
diff --git a/shared/sepolicy/vendor/vendor_init.te b/shared/sepolicy/vendor/vendor_init.te
index 37e76e1fd..f4fffe6d7 100644
--- a/shared/sepolicy/vendor/vendor_init.te
+++ b/shared/sepolicy/vendor/vendor_init.te
@@ -1,9 +1,17 @@
-vendor_internal_prop(vendor_graphics_config_prop)
+type vendor_init_radio_prop, property_type;
+type cf_graphics_config_prop, property_type;
+type cf_fstab_name_prop, property_type;
allow vendor_init {
audio_device
}:chr_file { getattr };
-set_prop(vendor_init, vendor_bt_rootcanal_prop)
+set_prop(vendor_init, hal_bluetooth_sim_prop)
-get_prop(vendor_init, vendor_graphics_config_prop)
+set_prop(vendor_init, vendor_init_radio_prop)
+
+get_prop(vendor_init, vendor_ser_prop)
+
+get_prop(vendor_init, cf_graphics_config_prop)
+
+get_prop(vendor_init, cf_fstab_name_prop)
diff --git a/shared/sepolicy/vendor/vold.te b/shared/sepolicy/vendor/vold.te
index fdb36e82f..1dc963d42 100644
--- a/shared/sepolicy/vendor/vold.te
+++ b/shared/sepolicy/vendor/vold.te
@@ -1,4 +1 @@
allow vold kernel:system module_request;
-
-# vold will access /mnt/vendor/shared for unknown reasons
-allow vold mnt_vendor_file:dir r_dir_perms;
diff --git a/shared/sepolicy/vendor/vport_trigger.te b/shared/sepolicy/vendor/vport_trigger.te
new file mode 100644
index 000000000..a21e29547
--- /dev/null
+++ b/shared/sepolicy/vendor/vport_trigger.te
@@ -0,0 +1,12 @@
+type vport_trigger, domain;
+type vport_trigger_exec, exec_type, vendor_file_type, file_type;
+
+type sys_cf_ser_prop, property_type;
+type vendor_ser_prop, property_type;
+
+init_daemon_domain(vport_trigger)
+
+r_dir_file(vport_trigger, sysfs_type)
+
+set_prop(vport_trigger, sys_cf_ser_prop)
+set_prop(vport_trigger, vendor_ser_prop)
diff --git a/shared/sepolicy/vendor/vsoc_input_service.te b/shared/sepolicy/vendor/vsoc_input_service.te
index b934e1258..ec2098535 100644
--- a/shared/sepolicy/vendor/vsoc_input_service.te
+++ b/shared/sepolicy/vendor/vsoc_input_service.te
@@ -1,7 +1,7 @@
type vsoc_input_service, domain;
type vsoc_input_service_exec, exec_type, vendor_file_type, file_type;
-vendor_internal_prop(vendor_vsock_keyboard_port)
-vendor_internal_prop(vendor_vsock_touch_port)
+type cuttlefish_vsock_keyboard_port, property_type;
+type cuttlefish_vsock_touch_port, property_type;
init_daemon_domain(vsoc_input_service)
@@ -10,7 +10,7 @@ allow vsoc_input_service uhid_device:chr_file rw_file_perms;
net_domain(vsoc_input_service)
-get_prop(vsoc_input_service, vendor_cuttlefish_config_server_port_prop)
+get_prop(vsoc_input_service, cuttlefish_config_server_port_prop)
allow vsoc_input_service self:{ socket vsock_socket } create_socket_perms_no_ioctl;
diff --git a/shared/sepolicy/vendor/vsock_logcat.te b/shared/sepolicy/vendor/vsock_logcat.te
new file mode 100644
index 000000000..7b7e8ff22
--- /dev/null
+++ b/shared/sepolicy/vendor/vsock_logcat.te
@@ -0,0 +1,17 @@
+type vsock_logcat, domain;
+type vsock_logcat_exec, exec_type, vendor_file_type, file_type;
+type vsock_logcat_port_prop, property_type;
+type vsock_logcat_status_prop, property_type;
+
+init_daemon_domain(vsock_logcat)
+
+get_prop(vsock_logcat, vsock_logcat_port_prop)
+
+set_prop(vsock_logcat, vendor_ser_prop)
+set_prop(vsock_logcat, vsock_logcat_status_prop)
+
+allow vsock_logcat device:dir w_dir_perms;
+allow vsock_logcat device:fifo_file create_file_perms;
+allow vsock_logcat kmsg_device:chr_file rw_file_perms;
+allow vsock_logcat self:capability net_admin;
+allow vsock_logcat self:{ socket vsock_socket } create_socket_perms_no_ioctl;
diff --git a/shared/tv/android-info.txt b/shared/tv/android-info.txt
deleted file mode 100644
index 8eae9029d..000000000
--- a/shared/tv/android-info.txt
+++ /dev/null
@@ -1 +0,0 @@
-config=tv
diff --git a/shared/tv/device.mk b/shared/tv/device.mk
index 9b78ee197..a56b42bff 100644
--- a/shared/tv/device.mk
+++ b/shared/tv/device.mk
@@ -14,6 +14,7 @@
# limitations under the License.
#
+DEVICE_MANIFEST_FILE += device/google/cuttlefish/shared/config/manifest.xml
DEVICE_MANIFEST_FILE += device/google/cuttlefish/shared/tv/manifest.xml
$(call inherit-product, $(SRC_TARGET_DIR)/product/core_minimal.mk)
@@ -28,19 +29,13 @@ PRODUCT_COPY_FILES += \
frameworks/native/data/etc/android.hardware.hdmi.cec.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.hdmi.cec.xml \
frameworks/native/data/etc/android.hardware.sensor.accelerometer.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.sensor.accelerometer.xml \
frameworks/native/data/etc/android.hardware.sensor.compass.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.sensor.compass.xml \
- hardware/interfaces/tv/tuner/config/sample_tuner_vts_config_1_0.xml:$(TARGET_COPY_OUT_VENDOR)/etc/tuner_vts_config_1_0.xml \
- hardware/interfaces/tv/tuner/config/sample_tuner_vts_config_1_1.xml:$(TARGET_COPY_OUT_VENDOR)/etc/tuner_vts_config_1_1.xml \
+ frameworks/native/data/etc/android.hardware.touchscreen.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.touchscreen.xml \
# HDMI CEC HAL
-PRODUCT_PACKAGES += android.hardware.tv.cec@1.1-service
-
-# Setup HDMI CEC as Playback Device
-PRODUCT_PROPERTY_OVERRIDES += ro.hdmi.device_type=4
+PRODUCT_PACKAGES += android.hardware.tv.cec@1.0-service.mock
# Tuner HAL
-PRODUCT_PACKAGES += android.hardware.tv.tuner@1.1-service
+PRODUCT_PACKAGES += android.hardware.tv.tuner@1.0-service
# Enabling managed profiles
DEVICE_PACKAGE_OVERLAYS += device/google/cuttlefish/shared/tv/overlay
-
-TARGET_BOARD_INFO_FILE ?= device/google/cuttlefish/shared/tv/android-info.txt
diff --git a/shared/tv/manifest.xml b/shared/tv/manifest.xml
index 8aab6eea7..0dc4a4563 100644
--- a/shared/tv/manifest.xml
+++ b/shared/tv/manifest.xml
@@ -16,7 +16,7 @@
** limitations under the License.
*/
-->
-<manifest version="1.0" type="device">
+<manifest version="1.0" type="device" target-level="5">
<!-- FIXME: Implement tv.cec HAL
<hal format="hidl">
<name>android.hardware.tv.cec</name>
diff --git a/shared/tv/overlay/frameworks/base/core/res/res/values/config.xml b/shared/tv/overlay/frameworks/base/core/res/res/values/config.xml
index 5ec4e7872..195a8a796 100644
--- a/shared/tv/overlay/frameworks/base/core/res/res/values/config.xml
+++ b/shared/tv/overlay/frameworks/base/core/res/res/values/config.xml
@@ -17,8 +17,4 @@
<resources>
<!-- Maximum number of supported users -->
<integer name="config_multiuserMaximumUsers">4</integer>
- <!-- Restricting eth2 -->
- <string-array translatable="false" name="config_ethernet_interfaces">
- <item>eth2;11,12,14;;</item>
- </string-array>
</resources>
diff --git a/shared/tv/sepolicy/vendor/file_contexts b/shared/tv/sepolicy/vendor/file_contexts
index 88b1cf5a2..267f8311a 100644
--- a/shared/tv/sepolicy/vendor/file_contexts
+++ b/shared/tv/sepolicy/vendor/file_contexts
@@ -1 +1,2 @@
/vendor/bin/hw/android\.hardware\.tv\.cec@1\.0-service\.mock u:object_r:hal_tv_cec_mock_exec:s0
+/vendor/bin/hw/android\.hardware\.tv\.tuner@1\.0-service u:object_r:hal_tv_tuner_default_exec:s0
diff --git a/shared/config/wpa_supplicant_overlay.conf b/shared/wpa_supplicant_overlay.conf
index e1f530dbd..e1f530dbd 100644
--- a/shared/config/wpa_supplicant_overlay.conf
+++ b/shared/wpa_supplicant_overlay.conf
diff --git a/guest/libs/Android.mk b/tests/Android.mk
index 428f4b5e5..337f5b902 100644
--- a/guest/libs/Android.mk
+++ b/tests/Android.mk
@@ -1,4 +1,4 @@
-# Copyright (C) 2021 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,6 +13,4 @@
# limitations under the License.
LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/graphics/Android.bp b/tests/graphics/Android.bp
deleted file mode 100644
index 676781741..000000000
--- a/tests/graphics/Android.bp
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright (C) 2021 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-java_test_host {
- name: "GfxstreamEnabledTest",
- srcs: [
- "src/**/*.java",
- ],
- test_options: {
- unit_test: false,
- },
- test_suites: [
- "device-tests",
- ],
- libs: [
- "tradefed",
- ],
-}
diff --git a/tests/graphics/src/com/android/cuttlefish/tests/GfxstreamEnabledTest.java b/tests/graphics/src/com/android/cuttlefish/tests/GfxstreamEnabledTest.java
deleted file mode 100644
index c3400a05a..000000000
--- a/tests/graphics/src/com/android/cuttlefish/tests/GfxstreamEnabledTest.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.cuttlefish.tests;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import com.android.tradefed.device.cloud.RemoteAndroidVirtualDevice;
-import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
-
-import org.junit.Assert;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/**
- * Tests that Gfxstream was enabled as the virtual device's OpenGL and Vulkan driver.
- */
-@RunWith(DeviceJUnit4ClassRunner.class)
-public class GfxstreamEnabledTest extends BaseHostJUnit4Test {
-
- @Test
- public void testGfxstreamEnabled() throws Exception {
- if (!(getDevice() instanceof RemoteAndroidVirtualDevice)) {
- return;
- }
-
- assertThat(getDevice().getProperty("ro.hardware.egl")).isEqualTo("emulation");
- assertThat(getDevice().getProperty("ro.hardware.vulkan")).isEqualTo("ranchu");
- }
-} \ No newline at end of file
diff --git a/tests/hal/Android.bp b/tests/hal/Android.bp
index 5aa14ce2c..41cb2c09f 100644
--- a/tests/hal/Android.bp
+++ b/tests/hal/Android.bp
@@ -1,7 +1,3 @@
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
cc_test {
name: "hal_implementation_test",
srcs: ["hal_implementation_test.cpp"],
diff --git a/tests/hal/hal_implementation_test.cpp b/tests/hal/hal_implementation_test.cpp
index e7bdc7256..8c2ae503f 100644
--- a/tests/hal/hal_implementation_test.cpp
+++ b/tests/hal/hal_implementation_test.cpp
@@ -25,47 +25,45 @@ using namespace android;
static const std::set<std::string> kKnownMissingHidl = {
"android.frameworks.bufferhub@1.0",
- "android.frameworks.cameraservice.device@2.1",
- "android.frameworks.schedulerservice@1.0", // deprecated, see b/37226359
+ "android.frameworks.cameraservice.device@2.0",
"android.frameworks.vr.composer@1.0",
"android.frameworks.vr.composer@2.0",
"android.frameworks.automotive.display@1.0",
- "android.frameworks.stats@1.0", // converted to AIDL, see b/177667419
"android.hardware.audio@2.0",
"android.hardware.audio@4.0",
"android.hardware.audio@5.0",
- "android.hardware.audio@7.0",
"android.hardware.audio.effect@2.0",
"android.hardware.audio.effect@4.0",
"android.hardware.audio.effect@5.0",
- "android.hardware.audio.effect@7.0",
"android.hardware.automotive.audiocontrol@1.0",
"android.hardware.automotive.audiocontrol@2.0",
"android.hardware.automotive.can@1.0",
+ "android.hardware.automotive.evs@1.0",
"android.hardware.automotive.evs@1.1",
"android.hardware.automotive.sv@1.0",
"android.hardware.automotive.vehicle@2.0",
- "android.hardware.biometrics.fingerprint@2.3",
+ "android.hardware.biometrics.fingerprint@2.1",
+ "android.hardware.biometrics.fingerprint@2.2",
"android.hardware.bluetooth.a2dp@1.0",
"android.hardware.broadcastradio@1.1",
"android.hardware.broadcastradio@2.0",
"android.hardware.cas.native@1.0",
"android.hardware.confirmationui@1.0",
"android.hardware.configstore@1.1", // deprecated, see b/149050985, b/149050733
- "android.hardware.fastboot@1.1",
+ "android.hardware.fastboot@1.0",
"android.hardware.gnss.measurement_corrections@1.1", // is sub-interface of gnss
"android.hardware.gnss.visibility_control@1.0",
"android.hardware.graphics.allocator@2.0",
"android.hardware.graphics.allocator@3.0",
"android.hardware.graphics.bufferqueue@1.0",
"android.hardware.graphics.bufferqueue@2.0",
+ "android.hardware.graphics.composer@2.3",
"android.hardware.graphics.composer@2.4",
"android.hardware.graphics.mapper@2.1",
"android.hardware.graphics.mapper@3.0",
- "android.hardware.health.storage@1.0", // converted to AIDL, see b/177470478
+ "android.hardware.health@1.0",
"android.hardware.ir@1.0",
"android.hardware.keymaster@3.0",
- "android.hardware.keymaster@4.1", // Replaced by KeyMint
"android.hardware.light@2.0",
"android.hardware.media.bufferpool@1.0",
"android.hardware.media.bufferpool@2.0",
@@ -73,25 +71,26 @@ static const std::set<std::string> kKnownMissingHidl = {
"android.hardware.nfc@1.2",
"android.hardware.oemlock@1.0",
"android.hardware.power@1.3",
- "android.hardware.power.stats@1.0",
+ "android.hardware.radio.config@1.2",
"android.hardware.radio.deprecated@1.0",
"android.hardware.renderscript@1.0",
- "android.hardware.soundtrigger@2.3",
"android.hardware.secure_element@1.2",
"android.hardware.sensors@1.0",
"android.hardware.tetheroffload.config@1.0",
- "android.hardware.tetheroffload.control@1.1", // see b/170699770
+ "android.hardware.tetheroffload.control@1.0",
"android.hardware.thermal@1.1",
- "android.hardware.tv.cec@1.1",
+ "android.hardware.tv.cec@1.0",
+ "android.hardware.tv.cec@2.0",
"android.hardware.tv.input@1.0",
- "android.hardware.tv.tuner@1.1",
- "android.hardware.usb@1.3",
- "android.hardware.usb.gadget@1.2",
+ "android.hardware.tv.tuner@1.0",
+ "android.hardware.usb@1.2",
+ "android.hardware.usb.gadget@1.1",
"android.hardware.vibrator@1.3",
"android.hardware.vr@1.0",
"android.hardware.weaver@1.0",
- "android.hardware.wifi@1.5",
- "android.hardware.wifi.hostapd@1.3",
+ "android.hardware.wifi@1.3",
+ "android.hardware.wifi@1.4",
+ "android.hardware.wifi.hostapd@1.2",
"android.hardware.wifi.offload@1.0",
"android.hidl.base@1.0",
"android.hidl.memory.token@1.0",
@@ -99,28 +98,19 @@ static const std::set<std::string> kKnownMissingHidl = {
static const std::set<std::string> kKnownMissingAidl = {
// types-only packages, which never expect a default implementation
- "android.hardware.biometrics.common.",
- "android.hardware.common.",
- "android.hardware.common.fmq.",
- "android.hardware.graphics.common.",
+ "android.hardware.common.NativeHandle",
+ "android.hardware.graphics.common.ExtendableType",
// These KeyMaster types are in an AIDL types-only HAL because they're used
// by the Identity Credential AIDL HAL. Remove this when fully porting
// KeyMaster to AIDL.
- "android.hardware.keymaster.",
-
- // These types are only used in Automotive.
- "android.automotive.computepipe.registry.",
- "android.automotive.computepipe.runner.",
- "android.automotive.watchdog.",
- "android.frameworks.automotive.powerpolicy.",
- "android.frameworks.automotive.telemetry.",
- "android.hardware.automotive.audiocontrol.",
- "android.hardware.automotive.occupant_awareness.",
+ "android.hardware.keymaster.HardwareAuthToken",
+ "android.hardware.keymaster.HardwareAuthenticatorType",
+ "android.hardware.keymaster.Timestamp",
};
// AOSP packages which are never considered
-static bool isHidlPackageConsidered(const FQName& name) {
+static bool isHidlPackageWhitelist(const FQName& name) {
static std::vector<std::string> gAospExclude = {
// packages not implemented now that we never expect to be implemented
"android.hardware.tests",
@@ -129,10 +119,10 @@ static bool isHidlPackageConsidered(const FQName& name) {
};
for (const std::string& package : gAospExclude) {
if (name.inPackage(package)) {
- return false;
+ return true;
}
}
- return true;
+ return false;
}
static bool isAospHidlInterface(const FQName& name) {
@@ -176,8 +166,9 @@ static std::set<FQName> allHidlManifestInterfaces() {
static bool isAospAidlInterface(const std::string& name) {
return base::StartsWith(name, "android.") &&
- !base::StartsWith(name, "android.hardware.tests.") &&
- !base::StartsWith(name, "android.aidl.tests");
+ !base::StartsWith(name, "android.automotive.") &&
+ !base::StartsWith(name, "android.hardware.automotive.") &&
+ !base::StartsWith(name, "android.hardware.tests.");
}
static std::set<std::string> allAidlManifestInterfaces() {
@@ -196,9 +187,7 @@ static std::set<std::string> allAidlManifestInterfaces() {
TEST(Hal, AllHidlInterfacesAreInAosp) {
for (const FQName& name : allHidlManifestInterfaces()) {
- EXPECT_TRUE(isAospHidlInterface(name))
- << "This device should only have AOSP interfaces, not: "
- << name.string();
+ EXPECT_TRUE(isAospHidlInterface(name)) << name.string();
}
}
@@ -208,7 +197,7 @@ TEST(Hal, HidlInterfacesImplemented) {
for (const FQName& f : allTreeHidlInterfaces()) {
if (!isAospHidlInterface(f)) continue;
- if (!isHidlPackageConsidered(f)) continue;
+ if (isHidlPackageWhitelist(f)) continue;
unimplemented[f.package()][f.getPackageMajorVersion()].insert(f.getPackageMinorVersion());
}
@@ -220,7 +209,8 @@ TEST(Hal, HidlInterfacesImplemented) {
for (const FQName& f : allHidlManifestInterfaces()) {
if (thoughtMissing.erase(f.getPackageAndVersion().string()) > 0) {
- ADD_FAILURE() << "Instance in missing list, but available: " << f.string();
+ std::cout << "[ WARNING ] Instance in missing list, but available: "
+ << f.string() << std::endl;
}
std::set<size_t>& minors = unimplemented[f.package()][f.getPackageMajorVersion()];
@@ -249,25 +239,17 @@ TEST(Hal, HidlInterfacesImplemented) {
}
for (const std::string& missing : thoughtMissing) {
- ADD_FAILURE() << "Instance in missing list and cannot find it anywhere: " << missing
- << " (multiple versions in missing list?)";
+ std::cout << "[ WARNING ] Instance in missing list and cannot find it anywhere: "
+ << missing << std::endl;
}
}
TEST(Hal, AllAidlInterfacesAreInAosp) {
for (const std::string& name : allAidlManifestInterfaces()) {
- EXPECT_TRUE(isAospAidlInterface(name))
- << "This device should only have AOSP interfaces, not: " << name;
+ EXPECT_TRUE(isAospAidlInterface(name)) << name;
}
}
-// android.hardware.foo.IFoo -> android.hardware.foo.
-std::string getAidlPackage(const std::string& aidlType) {
- size_t lastDot = aidlType.rfind('.');
- CHECK(lastDot != std::string::npos);
- return aidlType.substr(0, lastDot + 1);
-}
-
TEST(Hal, AidlInterfacesImplemented) {
std::set<std::string> manifest = allAidlManifestInterfaces();
std::set<std::string> thoughtMissing = kKnownMissingAidl;
@@ -281,28 +263,29 @@ TEST(Hal, AidlInterfacesImplemented) {
bool knownMissing = false;
for (const std::string& type : iface.types) {
if (manifest.erase(type) > 0) hasRegistration = true;
- if (thoughtMissing.erase(getAidlPackage(type)) > 0) knownMissing = true;
+ if (thoughtMissing.erase(type) > 0) knownMissing = true;
}
if (knownMissing) {
if (hasRegistration) {
- ADD_FAILURE() << "Interface in missing list, but available: " << iface.name
+ std::cout << "[ WARNING ] Interface in missing list, but available: " << iface.name
<< " which declares the following types:\n "
- << base::Join(iface.types, "\n ");
+ << base::Join(iface.types, "\n ") << std::endl;
}
continue;
}
EXPECT_TRUE(hasRegistration) << iface.name << " which declares the following types:\n "
- << base::Join(iface.types, "\n ");
+ << base::Join(iface.types, "\n ") << std::endl;
}
for (const std::string& iface : thoughtMissing) {
- ADD_FAILURE() << "Interface in manifest list and cannot find it anywhere: " << iface;
+ std::cout << "[ WARNING ] Interface in manifest list and cannot find it anywhere: "
+ << iface << std::endl;
}
for (const std::string& iface : manifest) {
- ADD_FAILURE() << "Can't find manifest entry in tree: " << iface;
+ std::cout << "[ WARNING ] Can't find manifest entry in tree: " << iface << std::endl;
}
}
diff --git a/tests/powerwash/src/com/android/cuttlefish/tests/PowerwashTest.java b/tests/powerwash/src/com/android/cuttlefish/tests/PowerwashTest.java
deleted file mode 100644
index 84fa85219..000000000
--- a/tests/powerwash/src/com/android/cuttlefish/tests/PowerwashTest.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.cuttlefish.tests;
-
-import com.android.tradefed.device.cloud.RemoteAndroidVirtualDevice;
-import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
-
-import java.io.File;
-import org.junit.Assert;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/**
- * Test powerwash function.
- *
- * <p>* This test resets the device thus it should not run with other tests in the same test suite
- * to avoid unexpected behavior.
- *
- * <p>* The test logic relies on powerwash_cvd tool, so it can only run in a test lab setup.
- */
-@RunWith(DeviceJUnit4ClassRunner.class)
-public class PowerwashTest extends BaseHostJUnit4Test {
-
- @Test
- public void testPowerwash() throws Exception {
- // Create a file in tmp directory
- final String tmpFile = "/data/local/tmp/powerwash_tmp";
- getDevice().executeShellCommand("touch " + tmpFile);
-
- // Reboot the device to make sure the file persits.
- getDevice().reboot();
- getDevice().waitForDeviceAvailable();
- File file = getDevice().pullFile(tmpFile);
- if (file == null) {
- Assert.fail("Setup failed: tmp file failed to persist after device reboot.");
- }
-
- if (getDevice() instanceof RemoteAndroidVirtualDevice) {
- ((RemoteAndroidVirtualDevice) getDevice()).powerwashGce();
- } else {
- Assert.fail("This test only supports running in test lab setup.");
- }
-
- // Verify that the device is back online and pre-xisting file is gone.
- file = getDevice().pullFile(tmpFile);
- if (file != null) {
- Assert.fail("Powerwash failed: pre-existing file still exists.");
- }
- }
-}
diff --git a/tests/recovery/AndroidTest.xml b/tests/recovery/AndroidTest.xml
deleted file mode 100644
index f21b65996..000000000
--- a/tests/recovery/AndroidTest.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2020 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.
--->
-
-<configuration description="GKI Install test">
- <test class="com.android.tradefed.testtype.HostTest" >
- <option name="jar" value="RebootRecoveryTest.jar" />
- </test>
-</configuration>
diff --git a/tests/recovery/src/com/android/cuttlefish/tests/RebootRecoveryTest.java b/tests/recovery/src/com/android/cuttlefish/tests/RebootRecoveryTest.java
deleted file mode 100644
index f4d77573f..000000000
--- a/tests/recovery/src/com/android/cuttlefish/tests/RebootRecoveryTest.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.cuttlefish.tests;
-
-import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
-
-import org.junit.After;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/**
- * Test rebooting into recovery.
- */
-@RunWith(DeviceJUnit4ClassRunner.class)
-public class RebootRecoveryTest extends BaseHostJUnit4Test {
- @Test
- public void testRebootRecovery() throws Exception {
- getDevice().rebootIntoRecovery();
- }
-
- @After
- public void tearDown() throws Exception {
- getDevice().reboot();
- }
-}
diff --git a/tests/ril/Android.bp b/tests/ril/Android.bp
deleted file mode 100644
index ed1d30d3e..000000000
--- a/tests/ril/Android.bp
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2020 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-android_test {
- name: "CuttlefishRilTests",
- srcs: ["src/**/*.java"],
- libs: ["android.test.runner.stubs"],
- static_libs: [
- "androidx.test.rules",
- "compatibility-device-util-axt",
- "hamcrest-library",
- "platform-test-annotations",
- ],
- sdk_version: "current",
- certificate: "platform",
-}
diff --git a/tests/ril/Android.mk b/tests/ril/Android.mk
new file mode 100644
index 000000000..178e916d9
--- /dev/null
+++ b/tests/ril/Android.mk
@@ -0,0 +1,39 @@
+# Copyright 2017 Google Inc. All Rights Reserved.
+#
+# 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.
+
+ifeq (0, $(shell test $(PLATFORM_SDK_VERSION) -ge 24; echo $$?))
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+# Only compile source java files in this apk.
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := CuttlefishRilTests
+LOCAL_SDK_VERSION := current
+LOCAL_CERTIFICATE := platform
+ifeq (0, $(shell test $(PLATFORM_SDK_VERSION) -ge 28; echo $$?))
+LOCAL_JAVA_LIBRARIES := android.test.runner.stubs
+else
+LOCAL_JAVA_LIBRARIES := android.test.runner
+endif
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test espresso-core
+
+LOCAL_STATIC_JAVA_LIBRARIES+=platform-test-annotations
+
+include $(BUILD_PACKAGE)
+
+endif
diff --git a/tests/ril/AndroidManifest.xml b/tests/ril/AndroidManifest.xml
index 487210931..462daa67d 100644
--- a/tests/ril/AndroidManifest.xml
+++ b/tests/ril/AndroidManifest.xml
@@ -29,7 +29,7 @@
android:targetSdkVersion="25" />
<instrumentation
- android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:name="android.support.test.runner.AndroidJUnitRunner"
android:targetPackage="com.android.cuttlefish.ril.tests" />
<application>
diff --git a/tests/ril/runtests.sh b/tests/ril/runtests.sh
index 2bb4bac8e..d27145578 100755
--- a/tests/ril/runtests.sh
+++ b/tests/ril/runtests.sh
@@ -27,4 +27,4 @@ adb wait-for-device
adb uninstall com.android.cuttlefish.ril.tests || true
adb install -r -g "$OUT/data/app/CuttlefishRilTests/CuttlefishRilTests.apk"
# optionally: -e class com.android.cuttlefish.ril.RilE2eTests#testName
-adb shell am instrument -w "$@" 'com.android.cuttlefish.ril.tests/androidx.test.runner.AndroidJUnitRunner'
+adb shell am instrument -w "$@" 'com.android.cuttlefish.ril.tests/android.support.test.runner.AndroidJUnitRunner'
diff --git a/tests/ril/src/com/android/cuttlefish/ril/tests/RilE2eTests.java b/tests/ril/src/com/android/cuttlefish/ril/tests/RilE2eTests.java
index 3c5db3f33..e09895f2d 100644
--- a/tests/ril/src/com/android/cuttlefish/ril/tests/RilE2eTests.java
+++ b/tests/ril/src/com/android/cuttlefish/ril/tests/RilE2eTests.java
@@ -15,25 +15,22 @@
*/
package com.android.cuttlefish.ril.tests;
-import static org.hamcrest.Matchers.greaterThan;
-
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkInfo;
+import android.net.wifi.SupplicantState;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
-import android.os.Build;
+import android.support.test.InstrumentationRegistry;
import android.telephony.CellInfoGsm;
import android.telephony.CellSignalStrengthGsm;
import android.telephony.TelephonyManager;
import android.util.Log;
-import androidx.test.InstrumentationRegistry;
-
-import com.android.compatibility.common.util.PropertyUtil;
-
+import static org.hamcrest.Matchers.greaterThan;
import org.junit.Assert;
-import org.junit.Assume;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
@@ -41,6 +38,7 @@ import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import java.net.Socket;
+import java.util.List;
/**
* Tests used to validate E2E RIL functionality.
@@ -56,13 +54,6 @@ public class RilE2eTests {
@Before
public void setUp() throws Exception {
- // Ideally this should be done in the @BeforeClass hook, but that would
- // make tradefed unhappy with a bunch "test did not run due to
- // instrumentation issue. See run level error for reason." errors.
- Assume.assumeFalse(
- "Skip testing deprecated radio HAL from Q or earlier vendor",
- PropertyUtil.getFirstApiLevel() <= Build.VERSION_CODES.Q);
-
mContext = InstrumentationRegistry.getInstrumentation().getContext();
mWifiManager = (WifiManager)mContext.getSystemService(Context.WIFI_SERVICE);
mConnManager = (ConnectivityManager)mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
diff --git a/tests/wifi/Android.bp b/tests/wifi/Android.bp
deleted file mode 100644
index 838e861a1..000000000
--- a/tests/wifi/Android.bp
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2020 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-android_test {
- name: "CuttlefishWifiTests",
- srcs: ["src/**/*.java"],
- libs: ["android.test.runner.stubs"],
- static_libs: [
- "androidx.test.rules",
- "platform-test-annotations",
- ],
- sdk_version: "current",
- certificate: "platform",
-}
diff --git a/tests/wifi/Android.mk b/tests/wifi/Android.mk
new file mode 100644
index 000000000..50ba90937
--- /dev/null
+++ b/tests/wifi/Android.mk
@@ -0,0 +1,35 @@
+# Copyright 2017 Google Inc. All Rights Reserved.
+#
+# 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.
+
+ifeq (0, $(shell test $(PLATFORM_SDK_VERSION) -ge 24; echo $$?))
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+# Only compile source java files in this apk.
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := CuttlefishWifiTests
+LOCAL_SDK_VERSION := current
+LOCAL_CERTIFICATE := platform
+ifeq (0, $(shell test $(PLATFORM_SDK_VERSION) -ge 28; echo $$?))
+LOCAL_JAVA_LIBRARIES := android.test.runner.stubs
+else
+LOCAL_JAVA_LIBRARIES := android.test.runner
+endif
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test platform-test-annotations
+
+include $(BUILD_PACKAGE)
+endif
diff --git a/tests/wifi/AndroidManifest.xml b/tests/wifi/AndroidManifest.xml
index 9394ad059..0ff13884a 100644
--- a/tests/wifi/AndroidManifest.xml
+++ b/tests/wifi/AndroidManifest.xml
@@ -28,7 +28,7 @@
android:targetSdkVersion="25" />
<instrumentation
- android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:name="android.support.test.runner.AndroidJUnitRunner"
android:targetPackage="com.android.cuttlefish.wifi.tests" />
<application>
diff --git a/tests/wifi/runtests.sh b/tests/wifi/runtests.sh
index c6642d306..c86790145 100755
--- a/tests/wifi/runtests.sh
+++ b/tests/wifi/runtests.sh
@@ -27,4 +27,4 @@ adb wait-for-device
adb uninstall com.android.cuttlefish.wifi.tests || true
adb install -r -g "$OUT/data/app/CuttlefishWifiTests/CuttlefishWifiTests.apk"
# optionally: -e class com.android.cuttlefish.wifi.WifiE2eTests#testName
-adb shell am instrument -w "$@" 'com.android.cuttlefish.wifi.tests/androidx.test.runner.AndroidJUnitRunner'
+adb shell am instrument -w "$@" 'com.android.cuttlefish.wifi.tests/android.support.test.runner.AndroidJUnitRunner'
diff --git a/tests/wifi/src/com/android/cuttlefish/wifi/tests/WifiE2eTests.java b/tests/wifi/src/com/android/cuttlefish/wifi/tests/WifiE2eTests.java
index 1ea4a1d21..e3d9e7086 100644
--- a/tests/wifi/src/com/android/cuttlefish/wifi/tests/WifiE2eTests.java
+++ b/tests/wifi/src/com/android/cuttlefish/wifi/tests/WifiE2eTests.java
@@ -19,14 +19,14 @@ import android.content.Context;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkInfo;
+import android.net.ConnectivityManager;
import android.net.wifi.SupplicantState;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
+import android.support.test.InstrumentationRegistry;
import android.util.Log;
-import androidx.test.InstrumentationRegistry;
-
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
@@ -121,11 +121,9 @@ public class WifiE2eTests {
Assert.assertNotNull(configs);
for (WifiConfiguration config : configs) {
Log.i(TAG, "Removing network " + config.networkId + ": " + config.SSID);
- mWifiManager.disableNetwork(config.networkId);
- mWifiManager.removeNetwork(config.networkId);
+ Assert.assertTrue(mWifiManager.disableNetwork(config.networkId));
+ Assert.assertTrue(mWifiManager.removeNetwork(config.networkId));
}
- configs = mWifiManager.getConfiguredNetworks();
- Assert.assertEquals(0, configs.size());
waitForSupplicantState(
SupplicantState.INACTIVE,
diff --git a/tools/create_base_image_arm.sh b/tools/create_base_image_arm.sh
index 644d909db..262d427b0 100755
--- a/tools/create_base_image_arm.sh
+++ b/tools/create_base_image_arm.sh
@@ -16,7 +16,7 @@
script_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
-source "${ANDROID_BUILD_TOP}/external/shflags/shflags"
+source "${ANDROID_BUILD_TOP}/external/shflags/src/shflags"
DEFINE_boolean p1 \
false "Only generate/write the 1st partition (loader1)" "1"
@@ -281,7 +281,7 @@ load mmc ${devnum}:${distro_bootpart} 0x04000000 /boot/uInitrd
load mmc ${devnum}:${distro_bootpart} 0x01f00000 /boot/dtb/rockchip/rk3399-rock-pi-4.dtb
setenv finduuid "part uuid mmc ${devnum}:${distro_bootpart} uuid"
run finduuid
-setenv bootargs "earlycon=uart8250,mmio32,0xff1a0000 console=ttyS2,1500000n8 loglevel=7 root=PARTUUID=${uuid} rootwait rootfstype=ext4 sdhci.debug_quirks=0x20000000 of_devlink=0"
+setenv bootargs "earlycon=uart8250,mmio32,0xff1a0000 console=ttyS2,1500000n8 loglevel=7 root=PARTUUID=${uuid} rootwait rootfstype=ext4 sdhci.debug_quirks=0x20000000"
booti 0x02080000 0x04000000 0x01f00000
EOF
${ANDROID_HOST_OUT}/bin/mkimage \
@@ -307,7 +307,7 @@ EOF
echo "Installing required packages..."
chroot ${mntdir} /bin/bash <<EOF
apt-get update
-apt-get install -y -f initramfs-tools u-boot-tools network-manager openssh-server sudo man-db vim git dpkg-dev cdbs debhelper config-package-dev gdisk eject lzop binfmt-support ntpdate lsof
+apt-get install -y -f initramfs-tools u-boot-tools network-manager openssh-server sudo man-db vim git dpkg-dev cdbs debhelper config-package-dev gdisk eject lzop binfmt-support ntpdate
EOF
echo "Turning on DHCP client..."
@@ -456,7 +456,7 @@ src_dev=mmcblk0
dest_dev=mmcblk1
part_num=p5
-if [ -e /dev/mmcblk0p5 ] && [ -e /dev/mmcblk1p5 ]; then
+if [ -e /dev/mmcblk0p5 ]; then
led 1
sgdisk -Z -a1 /dev/${dest_dev}
diff --git a/tools/create_base_image_gce.sh b/tools/create_base_image_gce.sh
index 02797dbf9..7c693c574 100755
--- a/tools/create_base_image_gce.sh
+++ b/tools/create_base_image_gce.sh
@@ -44,7 +44,6 @@ sudo mount /dev/sdb1 /mnt/image
cp "${debs[@]}" /mnt/image/tmp
sudo mount -t sysfs none /mnt/image/sys
sudo mount -t proc none /mnt/image/proc
-sudo mount --bind /boot/efi /mnt/image/boot/efi
sudo mount --bind /dev/ /mnt/image/dev
sudo mount --bind /dev/pts /mnt/image/dev/pts
sudo mount --bind /run /mnt/image/run
@@ -100,23 +99,10 @@ if [[ $(query_nvidia "driver_version") == "" ]]; then
exit 1
fi
-# Vulkan loader
-sudo chroot /mnt/image /usr/bin/apt install -y libvulkan1
-
-# Wayland-server needed to have Nvidia driver fail gracefully when attemping to
-# use the EGL API on GCE instances without a GPU.
-sudo chroot /mnt/image /usr/bin/apt install -y libwayland-server0
# Clean up the builder's version of resolv.conf
sudo rm /mnt/image/etc/resolv.conf
-# Make sure the image has /var/empty, and allow unprivileged_userns_clone for
-# minijail process sandboxing
-sudo chroot /mnt/image /usr/bin/mkdir -p /var/empty
-sudo tee /mnt/image/etc/sysctl.d/80-nsjail.conf >/dev/null <<EOF
-kernel.unprivileged_userns_clone=1
-EOF
-
# Skip unmounting:
# Sometimes systemd starts, making it hard to unmount
# In any case we'll unmount cleanly when the instance shuts down
diff --git a/tools/create_base_image_hostlib.sh b/tools/create_base_image_hostlib.sh
index dafefbd8f..f9982a5e2 100755
--- a/tools/create_base_image_hostlib.sh
+++ b/tools/create_base_image_hostlib.sh
@@ -8,7 +8,7 @@
# INTERNAL_IP can be set to --internal-ip run on a GCE instance
# The instance will need --scope compute-rw
-source "${ANDROID_BUILD_TOP}/external/shflags/shflags"
+source "${ANDROID_BUILD_TOP}/external/shflags/src/shflags"
DEFINE_string build_instance \
"${USER}-build" "Instance name to create for the build" "i"
@@ -29,8 +29,10 @@ DEFINE_string source_image_project debian-cloud \
DEFINE_string repository_url \
"https://github.com/google/android-cuttlefish.git" \
"URL to the repository with host changes" "u"
-DEFINE_string repository_branch main \
+DEFINE_string repository_branch master \
"Branch to check out" "b"
+DEFINE_string variant master \
+ "Variant to build: generally master or stable"
SSH_FLAGS=(${INTERNAL_IP})
diff --git a/tools/play_audio/.gitignore b/tools/play_audio/.gitignore
new file mode 100644
index 000000000..a6795baa7
--- /dev/null
+++ b/tools/play_audio/.gitignore
@@ -0,0 +1,3 @@
+*.o
+play_audio
+opuscpp
diff --git a/tools/play_audio/Makefile b/tools/play_audio/Makefile
new file mode 100644
index 000000000..30730ef43
--- /dev/null
+++ b/tools/play_audio/Makefile
@@ -0,0 +1,12 @@
+CXXFLAGS := -Wextra -Wall -pedantic-errors -std=c++17
+LDLIBS := -lopus -lgflags -lglog -lSDL2
+LINK.o := $(LINK.cc)
+
+PROG := play_audio
+OBJS := $(PROG).o client_socket.o sdl_wrapper.o opuscpp/opus_wrapper.o
+
+$(PROG): $(OBJS)
+
+clean:
+ rm -f $(OBJS) $(PROG)
+
diff --git a/tools/play_audio/README.md b/tools/play_audio/README.md
new file mode 100644
index 000000000..28c227fee
--- /dev/null
+++ b/tools/play_audio/README.md
@@ -0,0 +1,30 @@
+# Play Audio
+
+Audio receiver for a cuttlefish instance. A binary to play audio from a remote
+Android virtual device.
+
+## Install Dependencies
+
+```
+git clone https://github.com/google/opuscpp
+sudo apt install libsdl2-2.0-0 libsdl2-dev libopus-dev libopus0 libgflags-dev libgoogle-glog-dev
+```
+
+## Build
+
+```
+make
+```
+
+## Run
+Use ssh port forwarding to forward `7444` from a running instance. Then run the
+`play_audio` binary.
+
+```
+./play_audio
+```
+
+If you are running multiple virtual devices on a host, you must pass the
+`device_num` flag to specify the device corresponding to the `vsoc-##` username,
+and you will have to add `1 - device_num` to the port that you forward (vsoc-02
+= port 7445).
diff --git a/tools/play_audio/client_socket.cpp b/tools/play_audio/client_socket.cpp
new file mode 100644
index 000000000..dbc3db749
--- /dev/null
+++ b/tools/play_audio/client_socket.cpp
@@ -0,0 +1,113 @@
+/*
+ *
+ * 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.
+ */
+#include "client_socket.h"
+
+#include "android-base/logging.h"
+
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <unistd.h>
+
+#include <cstdint>
+#include <cstring>
+#include <vector>
+
+namespace {
+std::uint16_t HostOrderUInt16(const void* src) {
+ std::uint16_t result{};
+ std::memcpy(&result, src, sizeof result);
+ return htons(result);
+}
+
+std::uint32_t HostOrderUInt32(const void* src) {
+ std::uint32_t result{};
+ std::memcpy(&result, src, sizeof result);
+ return htonl(result);
+}
+} // namespace
+
+using cfp::ClientSocket;
+
+ClientSocket::ClientSocket(std::uint16_t port)
+ : socket_fd_{socket(AF_INET, SOCK_STREAM, 0)} {
+ sockaddr_in server_addr{};
+
+ if (socket_fd_ < 0) {
+ LOG(ERROR) << "couldn't create socket\n";
+ return;
+ }
+ server_addr.sin_family = AF_INET;
+ server_addr.sin_port = htons(port);
+
+ if (inet_pton(AF_INET, "127.0.0.1", &server_addr.sin_addr) <= 0) {
+ LOG(ERROR) << "couldn't convert localhost address\n";
+ close();
+ return;
+ }
+
+ if (connect(socket_fd_, reinterpret_cast<sockaddr*>(&server_addr),
+ sizeof server_addr) < 0) {
+ LOG(ERROR) << "connection failed\n";
+ close();
+ return;
+ }
+}
+
+ClientSocket::~ClientSocket() { close(); }
+
+ClientSocket::ClientSocket(ClientSocket&& other)
+ : socket_fd_{other.socket_fd_} {
+ other.socket_fd_ = -1;
+}
+
+ClientSocket& ClientSocket::operator=(ClientSocket&& other) {
+ close();
+ socket_fd_ = other.socket_fd_;
+ other.socket_fd_ = -1;
+ return *this;
+}
+
+std::vector<unsigned char> ClientSocket::RecvAll(ssize_t count) {
+ std::vector<unsigned char> buf(count);
+ size_t total_read = 0;
+ while (total_read < buf.size()) {
+ auto just_read =
+ read(socket_fd_, buf.data() + total_read, buf.size() - total_read);
+ if (just_read <= 0) {
+ LOG(ERROR) << "read failed";
+ return {};
+ }
+ total_read += static_cast<size_t>(just_read);
+ }
+ return buf;
+}
+
+std::uint16_t ClientSocket::RecvUInt16() {
+ return HostOrderUInt16(RecvAll(sizeof(std::uint16_t)).data());
+}
+
+std::uint32_t ClientSocket::RecvUInt32() {
+ return HostOrderUInt32(RecvAll(sizeof(std::uint32_t)).data());
+}
+
+void ClientSocket::close() {
+ if (socket_fd_ >= 0) {
+ ::close(socket_fd_);
+ socket_fd_ = -1;
+ }
+}
diff --git a/tools/play_audio/client_socket.h b/tools/play_audio/client_socket.h
new file mode 100644
index 000000000..f51cb6ad5
--- /dev/null
+++ b/tools/play_audio/client_socket.h
@@ -0,0 +1,57 @@
+/*
+ *
+ * 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.
+ */
+#ifndef CFP_CLIENT_SOCKET_
+#define CFP_CLIENT_SOCKET_
+
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <unistd.h>
+
+#include <cstdint>
+#include <cstring>
+#include <iostream>
+#include <vector>
+
+namespace cfp {
+
+class ClientSocket {
+ public:
+ ClientSocket(std::uint16_t port);
+ ~ClientSocket();
+
+ ClientSocket(ClientSocket&& other);
+ ClientSocket& operator=(ClientSocket&& other);
+
+ ClientSocket(const ClientSocket&) = delete;
+ ClientSocket& operator=(const ClientSocket&) = delete;
+
+ bool valid() const { return socket_fd_ >= 0; }
+
+ std::vector<unsigned char> RecvAll(ssize_t count);
+
+ std::uint16_t RecvUInt16();
+ std::uint32_t RecvUInt32();
+
+ private:
+ void close();
+ int socket_fd_ = -1;
+};
+
+} // namespace cfp
+
+#endif
diff --git a/tools/play_audio/play_audio.cpp b/tools/play_audio/play_audio.cpp
new file mode 100644
index 000000000..64c2a10fc
--- /dev/null
+++ b/tools/play_audio/play_audio.cpp
@@ -0,0 +1,109 @@
+/*
+ *
+ * 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.
+ */
+#include "client_socket.h"
+#include "sdl_wrapper.h"
+
+#include "android-base/logging.h"
+#include "gflags/gflags.h"
+#include "opuscpp/opus_wrapper.h"
+#include <SDL2/SDL.h>
+
+#include <cstdint>
+#include <tuple>
+#include <vector>
+
+DEFINE_int32(
+ device_num, 1,
+ "Cuttlefish device number, corresponding to username vsoc-## number");
+
+namespace {
+std::uint16_t AudioPort() {
+ constexpr std::uint16_t kAudioStreamBasePort = 7444;
+ std::uint16_t audio_port = kAudioStreamBasePort + (FLAGS_device_num - 1);
+ return audio_port;
+}
+
+cfp::ClientSocket Connect() {
+ const auto port = AudioPort();
+ auto conn = cfp::ClientSocket{port};
+ if (!conn.valid()) {
+ LOG(FATAL) << "couldn't connect on port " << port;
+ }
+ return conn;
+}
+
+std::tuple<std::uint16_t, std::uint16_t> RecvHeader(cfp::ClientSocket* conn) {
+ // creating variables because these must be received in order
+ auto num_channels = conn->RecvUInt16();
+ auto frame_rate = conn->RecvUInt16();
+ LOG(INFO) << "\nnum_channels: " << num_channels
+ << "\nframe_rate: " << frame_rate << '\n';
+ return {num_channels, frame_rate};
+}
+
+// Returns frame_size and encoded audio
+std::tuple<std::uint32_t, std::vector<unsigned char>> RecvEncodedAudio(
+ cfp::ClientSocket* conn) {
+ auto length = conn->RecvUInt32();
+ auto frame_size = conn->RecvUInt32();
+ auto encoded = conn->RecvAll(length);
+
+ if (encoded.size() < length) {
+ encoded.clear();
+ }
+ return {frame_size, std::move(encoded)};
+}
+
+void PlayDecodedAudio(cfp::SDLAudioDevice* audio_device,
+ const std::vector<opus_int16>& audio) {
+ auto sz = audio.size() * sizeof audio[0];
+ auto ret = audio_device->QueueAudio(audio.data(), sz);
+ if (ret < 0) {
+ LOG(ERROR) << "failed to queue audio: " << SDL_GetError() << '\n';
+ }
+}
+
+} // namespace
+
+int main(int argc, char* argv[]) {
+ ::google::InitGoogleLogging(argv[0]);
+ ::gflags::ParseCommandLineFlags(&argc, &argv, true);
+ cfp::SDLLib sdl{};
+
+ auto conn = Connect();
+ const auto& [num_channels, frame_rate] = RecvHeader(&conn);
+
+ auto audio_device = sdl.OpenAudioDevice(frame_rate, num_channels);
+ auto dec =
+ opus::Decoder{static_cast<std::uint32_t>(frame_rate), num_channels};
+ CHECK(dec.valid()) << "Could not construct Decoder. Maybe bad frame_rate ("
+ << frame_rate <<") or num_channels (" << num_channels
+ << ")?";
+
+ while (true) {
+ CHECK(dec.valid()) << "decoder in invalid state";
+ const auto& [frame_size, encoded] = RecvEncodedAudio(&conn);
+ if (encoded.empty()) {
+ break;
+ }
+ auto decoded = dec.Decode(encoded, frame_size, false);
+ if (decoded.empty()) {
+ break;
+ }
+ PlayDecodedAudio(&audio_device, decoded);
+ }
+}
diff --git a/tools/play_audio/sdl_wrapper.cpp b/tools/play_audio/sdl_wrapper.cpp
new file mode 100644
index 000000000..69892932d
--- /dev/null
+++ b/tools/play_audio/sdl_wrapper.cpp
@@ -0,0 +1,75 @@
+/*
+ *
+ * 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.
+ */
+
+#include "sdl_wrapper.h"
+
+#include "android-base/logging.h"
+#include <SDL2/SDL.h>
+
+#include <cstdint>
+
+using cfp::SDLAudioDevice;
+using cfp::SDLLib;
+
+SDLAudioDevice::SDLAudioDevice(SDLAudioDevice&& other)
+ : device_id_{other.device_id_} {
+ other.device_id_ = 0;
+}
+SDLAudioDevice& SDLAudioDevice::operator=(SDLAudioDevice&& other) {
+ close();
+ device_id_ = other.device_id_;
+ other.device_id_ = 0;
+ return *this;
+}
+
+SDLAudioDevice::~SDLAudioDevice() { close(); }
+
+int SDLAudioDevice::QueueAudio(const void* data, std::uint32_t len) {
+ return SDL_QueueAudio(device_id_, data, len);
+}
+
+SDLAudioDevice::SDLAudioDevice(SDL_AudioDeviceID device_id)
+ : device_id_{device_id} {}
+
+void SDLAudioDevice::close() {
+ if (device_id_ != 0) {
+ SDL_CloseAudioDevice(device_id_);
+ }
+}
+
+SDLLib::SDLLib() { SDL_Init(SDL_INIT_AUDIO); }
+SDLLib::~SDLLib() { SDL_Quit(); }
+
+SDLAudioDevice SDLLib::OpenAudioDevice(int freq, std::uint8_t num_channels) {
+ SDL_AudioSpec wav_spec{};
+ wav_spec.freq = freq;
+ wav_spec.format = AUDIO_S16LSB;
+ wav_spec.channels = num_channels;
+ wav_spec.silence = 0;
+ // .samples seems to work as low as 256,
+ // docs say this is 4096 when used with SDL_LoadWAV so I'm sticking with
+ // that
+ wav_spec.samples = 4096;
+ wav_spec.size = 0;
+
+ auto audio_device_id = SDL_OpenAudioDevice(nullptr, 0, &wav_spec, nullptr, 0);
+ if (audio_device_id == 0) {
+ LOG(FATAL) << "failed to open audio device: " << SDL_GetError() << '\n';
+ }
+ SDL_PauseAudioDevice(audio_device_id, false);
+ return SDLAudioDevice{audio_device_id};
+}
diff --git a/tools/play_audio/sdl_wrapper.h b/tools/play_audio/sdl_wrapper.h
new file mode 100644
index 000000000..9be1df5cb
--- /dev/null
+++ b/tools/play_audio/sdl_wrapper.h
@@ -0,0 +1,55 @@
+/*
+ *
+ * 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.
+ */
+#include <SDL2/SDL.h>
+#include <cstdint>
+
+namespace cfp {
+
+class SDLLib;
+
+class SDLAudioDevice {
+ public:
+ SDLAudioDevice(SDLAudioDevice&& other);
+ SDLAudioDevice& operator=(SDLAudioDevice&& other);
+
+ SDLAudioDevice(const SDLAudioDevice&) = delete;
+ SDLAudioDevice& operator=(const SDLAudioDevice&) = delete;
+
+ ~SDLAudioDevice();
+
+ int QueueAudio(const void* data, std::uint32_t len);
+
+ private:
+ friend SDLLib;
+ explicit SDLAudioDevice(SDL_AudioDeviceID device_id);
+ void close();
+
+ SDL_AudioDeviceID device_id_{};
+};
+
+class SDLLib {
+ public:
+ SDLLib();
+ ~SDLLib();
+
+ SDLLib(const SDLLib&) = delete;
+ SDLLib& operator=(const SDLLib&) = delete;
+
+ SDLAudioDevice OpenAudioDevice(int freq, std::uint8_t num_channels);
+};
+
+} // namespace cfp
diff --git a/tools/upload_to_gce_and_run.py b/tools/upload_to_gce_and_run.py
index f4dc4b801..f9e796c6f 100755
--- a/tools/upload_to_gce_and_run.py
+++ b/tools/upload_to_gce_and_run.py
@@ -19,14 +19,11 @@ def upload_artifacts(args):
dir = os.getcwd()
try:
os.chdir(args.image_dir)
- artifacts = []
- artifact_patterns = ['*.img', 'bootloader']
- for artifact_pattern in artifact_patterns:
- artifacts.extend(glob.glob(artifact_pattern))
- if len(artifacts) == 0:
+ images = glob.glob('*.img')
+ if len(images) == 0:
raise OSError('No images found in: %s' + args.image_dir)
subprocess.check_call(
- 'tar -c -f - --lzop -S ' + ' '.join(artifacts) +
+ 'tar -c -f - --lzop -S ' + ' '.join(images) +
' | ' +
gcloud_ssh(args) + '-- tar -x -f - --lzop -S',
shell=True)
@@ -58,20 +55,13 @@ def stop_cvd(args):
shell=True)
-def __get_default_hostdir():
- soong_host_dir = os.environ.get('ANDROID_SOONG_HOST_OUT')
- if soong_host_dir:
- return soong_host_dir
- return os.environ.get('ANDROID_HOST_OUT', '.')
-
-
def main():
parser = argparse.ArgumentParser(
description='Upload a local build to Google Compute Engine and run it')
parser.add_argument(
'-host_dir',
type=str,
- default=__get_default_hostdir(),
+ default=os.environ.get('ANDROID_HOST_OUT', '.'),
help='path to the dist directory')
parser.add_argument(
'-image_dir',
@@ -85,7 +75,7 @@ def main():
'-zone', type=str, default=None,
help='zone containing the instance')
parser.add_argument(
- '-user', type=str, default=os.environ.get('USER', 'vsoc-01'),
+ '-user', type=str, default='vsoc-01',
help='user to update on the instance')
parser.add_argument(
'-data-image', type=str, default=None,
diff --git a/tools/upload_via_ssh.py b/tools/upload_via_ssh.py
index 53594730b..c20a57fa1 100755
--- a/tools/upload_via_ssh.py
+++ b/tools/upload_via_ssh.py
@@ -12,7 +12,7 @@ def upload_artifacts(args):
dir = os.getcwd()
try:
os.chdir(args.image_dir)
- images = glob.glob('*.img') + ["bootloader"]
+ images = glob.glob('*.img')
if len(images) == 0:
raise OSError('File not found: ' + args.image_dir + '/*.img')
subprocess.check_call(
@@ -58,8 +58,8 @@ def main():
parser.add_argument(
'-host_dir',
type=str,
- default=os.environ.get('ANDROID_SOONG_HOST_OUT', '.'),
- help='path to soong host out directory')
+ default=os.environ.get('ANDROID_HOST_OUT', '.'),
+ help='path to the dist directory')
parser.add_argument(
'-image_dir',
type=str,
diff --git a/vsoc_arm64/BoardConfig.mk b/vsoc_arm64/BoardConfig.mk
index bc016a8e8..32090f524 100644
--- a/vsoc_arm64/BoardConfig.mk
+++ b/vsoc_arm64/BoardConfig.mk
@@ -15,7 +15,7 @@
#
#
-# arm64 target for Cuttlefish
+# x86 target for Cuttlefish
#
-include device/google/cuttlefish/shared/BoardConfig.mk
@@ -32,10 +32,7 @@ TARGET_2ND_CPU_ABI2 := armeabi
TARGET_2ND_CPU_VARIANT := cortex-a53
TARGET_TRANSLATE_2ND_ARCH := false
-ifeq ($(BOARD_VENDOR_RAMDISK_KERNEL_MODULES),)
- BOARD_VENDOR_RAMDISK_KERNEL_MODULES += $(wildcard kernel/prebuilts/common-modules/virtual-device/$(TARGET_KERNEL_USE)/arm64/*.ko)
-endif
+BOARD_VENDOR_RAMDISK_KERNEL_MODULES += $(wildcard device/google/cuttlefish_kernel/5.4-arm64/*.ko)
-HOST_CROSS_OS := linux_bionic
-HOST_CROSS_ARCH := arm64
-HOST_CROSS_2ND_ARCH :=
+# TODO(b/149410031): temporarily exclude sdcardfs
+BOARD_VENDOR_RAMDISK_KERNEL_MODULES := $(filter-out %/sdcardfs.ko,$(BOARD_VENDOR_RAMDISK_KERNEL_MODULES))
diff --git a/vsoc_arm64/auto/aosp_cf.mk b/vsoc_arm64/auto/aosp_cf.mk
index 51ae7a3a4..2d311dbd4 100644
--- a/vsoc_arm64/auto/aosp_cf.mk
+++ b/vsoc_arm64/auto/aosp_cf.mk
@@ -14,15 +14,11 @@
# limitations under the License.
#
-$(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit_only.mk)
+$(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit.mk)
$(call inherit-product, device/google/cuttlefish/shared/auto/device.mk)
-$(call inherit-product, device/google/cuttlefish/vsoc_arm64/kernel.mk)
+$(call inherit-product, device/google/cuttlefish/vsoc_arm64/device.mk)
PRODUCT_NAME := aosp_cf_arm64_auto
PRODUCT_DEVICE := vsoc_arm64
-PRODUCT_MANUFACTURER := Google
PRODUCT_MODEL := Cuttlefish arm64 auto
-
-PRODUCT_VENDOR_PROPERTIES += \
- ro.soc.manufacturer=$(PRODUCT_MANUFACTURER) \
- ro.soc.model=$(PRODUCT_DEVICE)
+DEVICE_PACKAGE_OVERLAYS += device/google/cuttlefish/vsoc_arm64/auto/overlay
diff --git a/shared/auto/overlay/frameworks/base/core/res/res/values/config.xml b/vsoc_arm64/auto/overlay/frameworks/base/core/res/res/values/config.xml
index 60c7ae90b..b3a4b68c2 100644
--- a/shared/auto/overlay/frameworks/base/core/res/res/values/config.xml
+++ b/vsoc_arm64/auto/overlay/frameworks/base/core/res/res/values/config.xml
@@ -23,8 +23,4 @@
<bool name="config_guestUserEphemeral" translatable="false">true</bool>
<!-- Maximum number of users allowed on the device. -->
<integer name="config_multiuserMaximumUsers" translatable="false">4</integer>
- <!-- Restricting eth2 -->
- <string-array translatable="false" name="config_ethernet_interfaces">
- <item>eth2;11,12,14;;</item>
- </string-array>
</resources>
diff --git a/vsoc_arm64/bootloader.mk b/vsoc_arm64/bootloader.mk
deleted file mode 100644
index a5aea9449..000000000
--- a/vsoc_arm64/bootloader.mk
+++ /dev/null
@@ -1,22 +0,0 @@
-#
-# Copyright (C) 2020 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_NO_BOOTLOADER := false
-# FIXME: Copying the QEMU bootloader for now, but this should be updated..
-BOARD_PREBUILT_BOOTLOADER := \
- device/google/cuttlefish_prebuilts/bootloader/crosvm_aarch64/u-boot.bin
-PRODUCT_COPY_FILES += \
- device/google/cuttlefish_prebuilts/bootloader/qemu_aarch64/u-boot.bin:bootloader.qemu
diff --git a/vsoc_arm64/kernel.mk b/vsoc_arm64/device.mk
index c27f7cbd5..1ff841639 100644
--- a/vsoc_arm64/kernel.mk
+++ b/vsoc_arm64/device.mk
@@ -13,6 +13,4 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-TARGET_KERNEL_USE ?= 5.10
-
-PRODUCT_COPY_FILES += kernel/prebuilts/$(TARGET_KERNEL_USE)/arm64/kernel-$(TARGET_KERNEL_USE):kernel
+PRODUCT_COPY_FILES += device/google/cuttlefish_kernel/5.4-arm64/kernel-5.4:kernel
diff --git a/vsoc_arm64/phone/aosp_cf.mk b/vsoc_arm64/phone/aosp_cf.mk
index b33e52372..ce1947f5f 100644
--- a/vsoc_arm64/phone/aosp_cf.mk
+++ b/vsoc_arm64/phone/aosp_cf.mk
@@ -18,7 +18,7 @@
# All components inherited here go to system image (same as GSI system)
#
$(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit.mk)
-$(call inherit-product, $(SRC_TARGET_DIR)/product/generic_system.mk)
+$(call inherit-product, $(SRC_TARGET_DIR)/product/mainline_system.mk)
PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS := relaxed
@@ -38,20 +38,14 @@ $(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_product.mk)
#
$(call inherit-product, device/google/cuttlefish/shared/phone/device_vendor.mk)
-# Nested virtualization support
-$(call inherit-product, packages/modules/Virtualization/apex/product_packages.mk)
-
#
# Special settings for the target
#
-$(call inherit-product, device/google/cuttlefish/vsoc_arm64/kernel.mk)
-$(call inherit-product, device/google/cuttlefish/vsoc_arm64/bootloader.mk)
+DEVICE_PACKAGE_OVERLAYS += device/google/cuttlefish/vsoc_arm64/phone/overlay
+
+$(call inherit-product, device/google/cuttlefish/vsoc_arm64/device.mk)
+
PRODUCT_NAME := aosp_cf_arm64_phone
PRODUCT_DEVICE := vsoc_arm64
-PRODUCT_MANUFACTURER := Google
PRODUCT_MODEL := Cuttlefish arm64 phone
-
-PRODUCT_VENDOR_PROPERTIES += \
- ro.soc.manufacturer=$(PRODUCT_MANUFACTURER) \
- ro.soc.model=$(PRODUCT_DEVICE)
diff --git a/shared/phone/overlay/frameworks/base/core/res/res/values/config.xml b/vsoc_arm64/phone/overlay/frameworks/base/core/res/res/values/config.xml
index c1b0d3e4c..5455fd4af 100644
--- a/shared/phone/overlay/frameworks/base/core/res/res/values/config.xml
+++ b/vsoc_arm64/phone/overlay/frameworks/base/core/res/res/values/config.xml
@@ -43,29 +43,6 @@
<bool name="config_showNavigationBar" translatable="false">true</bool>
<dimen name="config_viewConfigurationTouchSlop" translatable="false">12dp</dimen>
<integer name="config_mobile_mtu" translatable="false">1460</integer>
- <!-- Whether Multiuser UI should be shown -->
- <bool name="config_enableMultiUserUI" translatable="false">true</bool>
<!-- Maximum number of supported users -->
<integer name="config_multiuserMaximumUsers" translatable="false">4</integer>
- <!-- Support mic and camera muting -->
- <bool name="config_supportsMicToggle">true</bool>
- <bool name="config_supportsCamToggle">true</bool>
-
- <string name="config_mms_user_agent" translatable="false">CuttlefishNexus</string>
- <string name="config_mms_user_agent_profile_url" translatable="false">http://gsm.lge.com/html/gsm/Nexus5-M3.xml</string>
- <string name="config_wlan_data_service_package" translatable="false">com.android.ims</string>
- <string name="config_wlan_network_service_package" translatable="false">com.android.ims</string>
- <!-- Restricting eth2 -->
- <string-array translatable="false" name="config_ethernet_interfaces">
- <item>eth2;11,12,14;;</item>
- </string-array>
-
- <!-- List of biometric sensors on the device, in decreasing strength. Consumed by AuthService
- when registering authenticators with BiometricService. Format must be ID:Modality:Strength,
- where: IDs are unique per device, Modality as defined in BiometricAuthenticator.java,
- and Strength as defined in Authenticators.java -->
- <string-array name="config_biometric_sensors" translatable="false" >
- <item>2:2:255</item> <!-- ID2:Fingerprint(HIDL):Weak -->
- <item>3:8:255</item> <!-- ID3:Face(HIDL):Weak -->
- </string-array>
</resources>
diff --git a/vsoc_arm64_only/BoardConfig.mk b/vsoc_arm64_only/BoardConfig.mk
deleted file mode 100644
index b5a13406d..000000000
--- a/vsoc_arm64_only/BoardConfig.mk
+++ /dev/null
@@ -1,34 +0,0 @@
-#
-# 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.
-#
-
-#
-# arm64 (64-bit only) target for Cuttlefish
-#
-
--include device/google/cuttlefish/shared/BoardConfig.mk
-
-TARGET_BOARD_PLATFORM := vsoc_arm64
-TARGET_ARCH := arm64
-TARGET_ARCH_VARIANT := armv8-a
-TARGET_CPU_ABI := arm64-v8a
-TARGET_CPU_VARIANT := cortex-a53
-
-AUDIOSERVER_MULTILIB := first
-BOARD_VENDOR_RAMDISK_KERNEL_MODULES += $(wildcard kernel/prebuilts/common-modules/virtual-device/5.10/arm64/*.ko)
-
-HOST_CROSS_OS := linux_bionic
-HOST_CROSS_ARCH := arm64
-HOST_CROSS_2ND_ARCH :=
diff --git a/vsoc_arm64_only/phone/aosp_cf.mk b/vsoc_arm64_only/phone/aosp_cf.mk
deleted file mode 100644
index 5bcfc7b19..000000000
--- a/vsoc_arm64_only/phone/aosp_cf.mk
+++ /dev/null
@@ -1,62 +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.
-#
-
-#
-# All components inherited here go to system image (same as GSI system)
-#
-$(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit_only.mk)
-$(call inherit-product, $(SRC_TARGET_DIR)/product/generic_system.mk)
-
-PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS := relaxed
-
-#
-# All components inherited here go to system_ext image (same as GSI system_ext)
-#
-$(call inherit-product, $(SRC_TARGET_DIR)/product/handheld_system_ext.mk)
-$(call inherit-product, $(SRC_TARGET_DIR)/product/telephony_system_ext.mk)
-
-#
-# All components inherited here go to product image (same as GSI product)
-#
-$(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_product.mk)
-
-#
-# All components inherited here go to vendor image
-#
-LOCAL_DISABLE_OMX := true
-$(call inherit-product, device/google/cuttlefish/shared/phone/device_vendor.mk)
-
-# Nested virtualization support
-$(call inherit-product, packages/modules/Virtualization/apex/product_packages.mk)
-
-#
-# Special settings for the target
-#
-$(call inherit-product, device/google/cuttlefish/vsoc_arm64/kernel.mk)
-$(call inherit-product, device/google/cuttlefish/vsoc_arm64/bootloader.mk)
-
-# Exclude features that are not available on AOSP devices.
-PRODUCT_COPY_FILES += \
- frameworks/native/data/etc/aosp_excluded_hardware.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/aosp_excluded_hardware.xml
-
-PRODUCT_NAME := aosp_cf_arm64_only_phone
-PRODUCT_DEVICE := vsoc_arm64_only
-PRODUCT_MANUFACTURER := Google
-PRODUCT_MODEL := Cuttlefish arm64 phone 64-bit only
-
-PRODUCT_VENDOR_PROPERTIES += \
- ro.soc.manufacturer=$(PRODUCT_MANUFACTURER) \
- ro.soc.model=$(PRODUCT_DEVICE)
diff --git a/vsoc_arm_only/BoardConfig.mk b/vsoc_arm_only/BoardConfig.mk
deleted file mode 100644
index e0cb5ce95..000000000
--- a/vsoc_arm_only/BoardConfig.mk
+++ /dev/null
@@ -1,34 +0,0 @@
-#
-# Copyright 2020 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.
-#
-
-#
-# arm (32-bit only) target for Cuttlefish
-#
-
--include device/google/cuttlefish/shared/BoardConfig.mk
-
-TARGET_BOARD_PLATFORM := vsoc_arm
-TARGET_ARCH := arm
-TARGET_ARCH_VARIANT := armv7-a-neon
-TARGET_CPU_ABI := armeabi-v7a
-TARGET_CPU_ABI2 := armeabi
-TARGET_CPU_VARIANT := cortex-a15
-
-BOARD_VENDOR_RAMDISK_KERNEL_MODULES += $(wildcard device/google/cuttlefish_prebuilts/kernel/5.4-arm/*.ko)
-
-HOST_CROSS_OS := linux_bionic
-HOST_CROSS_ARCH := arm64
-HOST_CROSS_2ND_ARCH :=
diff --git a/vsoc_arm_only/bootloader.mk b/vsoc_arm_only/bootloader.mk
deleted file mode 100644
index 93de14e85..000000000
--- a/vsoc_arm_only/bootloader.mk
+++ /dev/null
@@ -1,22 +0,0 @@
-#
-# Copyright (C) 2020 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_NO_BOOTLOADER := false
-# FIXME: Copying the QEMU bootloader for now, but this should be updated..
-BOARD_PREBUILT_BOOTLOADER := \
- device/google/cuttlefish_prebuilts/bootloader/qemu_arm/u-boot.bin
-PRODUCT_COPY_FILES += \
- device/google/cuttlefish_prebuilts/bootloader/qemu_arm/u-boot.bin:bootloader.qemu
diff --git a/vsoc_arm_only/phone/aosp_cf.mk b/vsoc_arm_only/phone/aosp_cf.mk
deleted file mode 100644
index 2643c9047..000000000
--- a/vsoc_arm_only/phone/aosp_cf.mk
+++ /dev/null
@@ -1,71 +0,0 @@
-#
-# Copyright (C) 2020 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.
-#
-
-#
-# All components inherited here go to system image (same as GSI system)
-#
-$(call inherit-product, $(SRC_TARGET_DIR)/product/generic_system.mk)
-
-PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS := relaxed
-
-#
-# All components inherited here go to system_ext image (same as GSI system_ext)
-#
-$(call inherit-product, $(SRC_TARGET_DIR)/product/handheld_system_ext.mk)
-$(call inherit-product, $(SRC_TARGET_DIR)/product/telephony_system_ext.mk)
-
-#
-# All components inherited here go to product image (same as GSI product)
-#
-$(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_product.mk)
-PRODUCT_OTA_ENFORCE_VINTF_KERNEL_REQUIREMENTS := false
-
-#
-# FIXME: Set up Go defaults because we are currently limited (by a U-Boot bug)
-# to 512MB of RAM
-#
-$(call inherit-product, $(SRC_TARGET_DIR)/product/go_defaults_512.mk)
-PRODUCT_ARTIFACT_PATH_REQUIREMENT_ALLOWED_LIST += \
- system/apex/com.android.tethering.inprocess.apex \
- system/apex/com.android.tethering.inprocess.capex \
- system/app/PlatformCaptivePortalLogin/PlatformCaptivePortalLogin.apk \
- system/priv-app/CellBroadcastServiceModulePlatform/CellBroadcastServiceModulePlatform.apk \
- system/priv-app/InProcessNetworkStack/InProcessNetworkStack.apk \
- system/priv-app/PlatformNetworkPermissionConfig/PlatformNetworkPermissionConfig.apk \
-
-#
-# All components inherited here go to vendor image
-#
-$(call inherit-product, device/google/cuttlefish/shared/phone/device_vendor.mk)
-
-#
-# Special settings for the target
-#
-$(call inherit-product, device/google/cuttlefish/vsoc_arm_only/kernel.mk)
-$(call inherit-product, device/google/cuttlefish/vsoc_arm_only/bootloader.mk)
-
-# Exclude features that are not available on AOSP devices.
-PRODUCT_COPY_FILES += \
- frameworks/native/data/etc/aosp_excluded_hardware.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/aosp_excluded_hardware.xml
-
-PRODUCT_NAME := aosp_cf_arm_only_phone
-PRODUCT_DEVICE := vsoc_arm_only
-PRODUCT_MANUFACTURER := Google
-PRODUCT_MODEL := Cuttlefish arm phone 32-bit only
-
-PRODUCT_VENDOR_PROPERTIES += \
- ro.soc.manufacturer=$(PRODUCT_MANUFACTURER) \
- ro.soc.model=$(PRODUCT_DEVICE)
diff --git a/vsoc_x86/BoardConfig.mk b/vsoc_x86/BoardConfig.mk
index 70db8c2bf..f12dc7015 100644
--- a/vsoc_x86/BoardConfig.mk
+++ b/vsoc_x86/BoardConfig.mk
@@ -31,12 +31,7 @@ TARGET_NATIVE_BRIDGE_CPU_VARIANT := generic
TARGET_NATIVE_BRIDGE_ABI := armeabi-v7a armeabi
BUILD_BROKEN_DUP_RULES := true
+BOARD_VENDOR_RAMDISK_KERNEL_MODULES += $(wildcard device/google/cuttlefish_kernel/5.4-x86_64/*.ko)
-ifeq ($(BOARD_VENDOR_RAMDISK_KERNEL_MODULES),)
- BOARD_VENDOR_RAMDISK_KERNEL_MODULES += $(wildcard kernel/prebuilts/common-modules/virtual-device/5.10/x86-64/*.ko)
-endif
-
-# TODO(b/156534160): Temporarily allow for the old style PRODUCT_COPY_FILES for ndk_translation_prebuilt
-ifeq ($(USE_NDK_TRANSLATION_BINARY),true)
-BUILD_BROKEN_ELF_PREBUILT_PRODUCT_COPY_FILES := true
-endif
+# TODO(b/149410031): temporarily exclude sdcardfs
+BOARD_VENDOR_RAMDISK_KERNEL_MODULES := $(filter-out %/sdcardfs.ko,$(BOARD_VENDOR_RAMDISK_KERNEL_MODULES))
diff --git a/vsoc_x86/auto/device.mk b/vsoc_x86/auto/device.mk
index c3ccba340..88399b879 100644
--- a/vsoc_x86/auto/device.mk
+++ b/vsoc_x86/auto/device.mk
@@ -15,18 +15,14 @@
#
$(call inherit-product, device/google/cuttlefish/shared/auto/device.mk)
-$(call inherit-product, device/google/cuttlefish/vsoc_x86_64/kernel.mk)
-$(call inherit-product, device/google/cuttlefish/vsoc_x86_64/bootloader.mk)
+$(call inherit-product, device/google/cuttlefish/vsoc_x86/device.mk)
PRODUCT_NAME := aosp_cf_x86_auto
PRODUCT_DEVICE := vsoc_x86
-PRODUCT_MANUFACTURER := Google
PRODUCT_MODEL := Cuttlefish x86 auto
+PRODUCT_PACKAGE_OVERLAYS += device/google/cuttlefish/vsoc_x86/auto/overlay
+
# Whitelisted packages per user type
PRODUCT_COPY_FILES += \
device/google/cuttlefish/vsoc_x86/auto/preinstalled-packages-product-car-cuttlefish.xml:$(TARGET_COPY_OUT_PRODUCT)/etc/sysconfig/preinstalled-packages-product-car-cuttlefish.xml
-
-PRODUCT_VENDOR_PROPERTIES += \
- ro.soc.manufacturer=$(PRODUCT_MANUFACTURER) \
- ro.soc.model=$(PRODUCT_DEVICE)
diff --git a/shared/pc/overlay/frameworks/base/core/res/res/values/config.xml b/vsoc_x86/auto/overlay/frameworks/base/core/res/res/values/config.xml
index 86896be01..b3a4b68c2 100644
--- a/shared/pc/overlay/frameworks/base/core/res/res/values/config.xml
+++ b/vsoc_x86/auto/overlay/frameworks/base/core/res/res/values/config.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
-** Copyright 2017, 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.
@@ -17,11 +17,10 @@
*/
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <bool name="config_showNavigationBar" translatable="false">true</bool>
- <!-- Maximum number of supported users -->
+ <!-- Enable multi-user. -->
+ <bool name="config_enableMultiUserUI" translatable="false">true</bool>
+ <!-- If true, all guest users created on the device will be ephemeral. -->
+ <bool name="config_guestUserEphemeral" translatable="false">true</bool>
+ <!-- Maximum number of users allowed on the device. -->
<integer name="config_multiuserMaximumUsers" translatable="false">4</integer>
- <!-- Restricting eth2 -->
- <string-array translatable="false" name="config_ethernet_interfaces">
- <item>eth2;11,12,14;;</item>
- </string-array>
-</resources> \ No newline at end of file
+</resources>
diff --git a/vsoc_x86/auto/preinstalled-packages-product-car-cuttlefish.xml b/vsoc_x86/auto/preinstalled-packages-product-car-cuttlefish.xml
index 49aef5d1f..1536291a4 100644
--- a/vsoc_x86/auto/preinstalled-packages-product-car-cuttlefish.xml
+++ b/vsoc_x86/auto/preinstalled-packages-product-car-cuttlefish.xml
@@ -71,30 +71,11 @@
<install-in user-type="FULL" />
<install-in user-type="SYSTEM" />
</install-in-user-type>
- <!-- Required for Tethering -->
- <install-in-user-type package="com.android.networkstack.tethering">
- <install-in user-type="FULL" />
- <install-in user-type="SYSTEM" />
- </install-in-user-type>
- <install-in-user-type package="com.android.connectivity.resources">
- <install-in user-type="FULL" />
- <install-in user-type="SYSTEM" />
- </install-in-user-type>
- <!-- Required for Wifi -->
- <install-in-user-type package="com.android.networkstack.inprocess">
- <install-in user-type="FULL" />
- <install-in user-type="SYSTEM" />
- </install-in-user-type>
<!-- Required when sysui queries for system user apps to handle the home intent -->
<install-in-user-type package="com.android.car.carlauncher">
<install-in user-type="FULL" />
<install-in user-type="SYSTEM" />
</install-in-user-type>
- <!-- Required when using Camera2 extensions -->
- <install-in-user-type package="com.android.cameraextensions">
- <install-in user-type="SYSTEM" />
- <install-in user-type="FULL" />
- </install-in-user-type>
<!--
Apps that do need to run on SYSTEM and evaluated by package owner.
@@ -148,21 +129,108 @@
<install-in-user-type package="com.android.car.themeplayground">
<install-in user-type="FULL" />
</install-in-user-type>
- <install-in-user-type package="com.android.car.linkviewer">
+ <install-in-user-type package="com.android.theme.color.amethyst">
+ <install-in user-type="FULL" />
+ </install-in-user-type>
+ <install-in-user-type package="com.android.theme.color.aquamarine">
+ <install-in user-type="FULL" />
+ </install-in-user-type>
+ <install-in-user-type package="com.android.theme.color.black">
+ <install-in user-type="FULL" />
+ </install-in-user-type>
+ <install-in-user-type package="com.android.theme.color.tangerine">
+ <install-in user-type="FULL" />
+ </install-in-user-type>
+ <install-in-user-type package="com.android.theme.color.cinnamon">
+ <install-in user-type="FULL" />
+ </install-in-user-type>
+ <install-in-user-type package="com.android.theme.color.green">
+ <install-in user-type="FULL" />
+ </install-in-user-type>
+ <install-in-user-type package="com.android.theme.color.ocean">
+ <install-in user-type="FULL" />
+ </install-in-user-type>
+ <install-in-user-type package="com.android.theme.color.space">
+ <install-in user-type="FULL" />
+ </install-in-user-type>
+ <install-in-user-type package="com.android.theme.color.orchid">
+ <install-in user-type="FULL" />
+ </install-in-user-type>
+ <install-in-user-type package="com.android.theme.color.purple">
+ <install-in user-type="FULL" />
+ </install-in-user-type>
+ <install-in-user-type package="com.android.theme.font.notoserifsource">
+ <install-in user-type="FULL" />
+ </install-in-user-type>
+ <install-in-user-type package="com.android.theme.icon.pebble">
+ <install-in user-type="FULL" />
+ </install-in-user-type>
+ <install-in-user-type package="com.android.theme.icon.roundedrect">
+ <install-in user-type="FULL" />
+ </install-in-user-type>
+ <install-in-user-type package="com.android.theme.icon.squircle">
+ <install-in user-type="FULL" />
+ </install-in-user-type>
+ <install-in-user-type package="com.android.theme.icon.taperedrect">
+ <install-in user-type="FULL" />
+ </install-in-user-type>
+ <install-in-user-type package="com.android.theme.icon.teardrop">
+ <install-in user-type="FULL" />
+ </install-in-user-type>
+ <install-in-user-type package="com.android.theme.icon.vessel">
+ <install-in user-type="FULL" />
+ </install-in-user-type>
+ <install-in-user-type package="com.android.theme.icon_pack.circular.android">
+ <install-in user-type="FULL" />
+ </install-in-user-type>
+ <install-in-user-type package="com.android.theme.icon_pack.circular.launcher">
+ <install-in user-type="FULL" />
+ </install-in-user-type>
+ <install-in-user-type package="com.android.theme.icon_pack.circular.settings">
+ <install-in user-type="FULL" />
+ </install-in-user-type>
+ <install-in-user-type package="com.android.theme.icon_pack.circular.systemui">
+ <install-in user-type="FULL" />
+ </install-in-user-type>
+ <install-in-user-type package="com.android.theme.icon_pack.circular.themepicker">
+ <install-in user-type="FULL" />
+ </install-in-user-type>
+ <install-in-user-type package="com.android.theme.icon_pack.filled.android">
+ <install-in user-type="FULL" />
+ </install-in-user-type>
+ <install-in-user-type package="com.android.theme.icon_pack.filled.launcher">
+ <install-in user-type="FULL" />
+ </install-in-user-type>
+ <install-in-user-type package="com.android.theme.icon_pack.filled.settings">
+ <install-in user-type="FULL" />
+ </install-in-user-type>
+ <install-in-user-type package="com.android.theme.icon_pack.filled.systemui">
+ <install-in user-type="FULL" />
+ </install-in-user-type>
+ <install-in-user-type package="com.android.theme.icon_pack.filled.themepicker">
+ <install-in user-type="FULL" />
+ </install-in-user-type>
+ <install-in-user-type package="com.android.theme.icon_pack.rounded.android">
+ <install-in user-type="FULL" />
+ </install-in-user-type>
+ <install-in-user-type package="com.android.theme.icon_pack.rounded.launcher">
<install-in user-type="FULL" />
</install-in-user-type>
- <install-in-user-type package="com.android.car.multidisplay">
+ <install-in-user-type package="com.android.theme.icon_pack.rounded.settings">
<install-in user-type="FULL" />
</install-in-user-type>
- <install-in-user-type package="com.android.car.voicecontrol">
+ <install-in-user-type package="com.android.theme.icon_pack.rounded.systemui">
<install-in user-type="FULL" />
</install-in-user-type>
- <install-in-user-type package="com.google.android.car.multidisplaytest">
+ <install-in-user-type package="com.android.car.linkviewer">
<install-in user-type="FULL" />
</install-in-user-type>
<install-in-user-type package="com.android.car.retaildemo">
<install-in user-type="FULL" />
</install-in-user-type>
+ <install-in-user-type package="com.android.car.voicecontrol">
+ <install-in user-type="FULL" />
+ </install-in-user-type>
<install-in-user-type package="com.android.documentsui">
<install-in user-type="FULL" />
</install-in-user-type>
@@ -178,10 +246,17 @@
<install-in-user-type package="com.google.android.apps.geo.autograph.vms.client.systemstate">
<install-in user-type="FULL" />
</install-in-user-type>
+ <install-in-user-type package="com.android.theme.icon_pack.rounded.themepicker">
+ <install-in user-type="FULL" />
+ </install-in-user-type>
+ <install-in-user-type package="com.android.networkstack.tethering">
+ <install-in user-type="FULL" />
+ </install-in-user-type>
<install-in-user-type package="com.android.smspush">
<install-in user-type="FULL" />
</install-in-user-type>
<install-in-user-type package="com.android.angle">
<install-in user-type="FULL" />
</install-in-user-type>
+
</config>
diff --git a/vsoc_x86_64/kernel.mk b/vsoc_x86/device.mk
index 5dded660c..de288f470 100644
--- a/vsoc_x86_64/kernel.mk
+++ b/vsoc_x86/device.mk
@@ -13,6 +13,4 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-TARGET_KERNEL_USE ?= 5.10
-
-PRODUCT_COPY_FILES += kernel/prebuilts/$(TARGET_KERNEL_USE)/x86_64/kernel-$(TARGET_KERNEL_USE):kernel
+PRODUCT_COPY_FILES += device/google/cuttlefish_kernel/5.4-x86_64/kernel-5.4:kernel
diff --git a/vsoc_x86/go_512_phone/device.mk b/vsoc_x86/go_512_phone/device.mk
index 2df9023ae..b33d06e1d 100644
--- a/vsoc_x86/go_512_phone/device.mk
+++ b/vsoc_x86/go_512_phone/device.mk
@@ -15,14 +15,9 @@
#
$(call inherit-product, device/google/cuttlefish/shared/go_512/device.mk)
-$(call inherit-product, device/google/cuttlefish/vsoc_x86_64/kernel.mk)
+$(call inherit-product, device/google/cuttlefish/vsoc_x86/phone/device.mk)
PRODUCT_NAME := aosp_cf_x86_go_512_phone
PRODUCT_DEVICE := vsoc_x86
-PRODUCT_MANUFACTURER := Google
PRODUCT_MODEL := Cuttlefish x86 Go 512 phone
PRODUCT_PACKAGE_OVERLAYS := device/google/cuttlefish/vsoc_x86/phone/overlay
-
-PRODUCT_VENDOR_PROPERTIES += \
- ro.soc.manufacturer=$(PRODUCT_MANUFACTURER) \
- ro.soc.model=$(PRODUCT_DEVICE)
diff --git a/vsoc_x86/go_phone/device.mk b/vsoc_x86/go_phone/device.mk
index 8b2a8f3ad..b61edc5be 100644
--- a/vsoc_x86/go_phone/device.mk
+++ b/vsoc_x86/go_phone/device.mk
@@ -15,14 +15,10 @@
#
$(call inherit-product, device/google/cuttlefish/shared/go/device.mk)
-$(call inherit-product, device/google/cuttlefish/vsoc_x86_64/kernel.mk)
+$(call inherit-product, device/google/cuttlefish/vsoc_x86/phone/device.mk)
+$(call inherit-product, device/google/cuttlefish/vsoc_x86/device.mk)
PRODUCT_NAME := aosp_cf_x86_go_phone
PRODUCT_DEVICE := vsoc_x86
-PRODUCT_MANUFACTURER := Google
PRODUCT_MODEL := Cuttlefish x86 Go phone
PRODUCT_PACKAGE_OVERLAYS := device/google/cuttlefish/vsoc_x86/phone/overlay
-
-PRODUCT_VENDOR_PROPERTIES += \
- ro.soc.manufacturer=$(PRODUCT_MANUFACTURER) \
- ro.soc.model=$(PRODUCT_DEVICE)
diff --git a/vsoc_x86/pasan/aosp_cf.mk b/vsoc_x86/pasan/aosp_cf.mk
index d4c8d5755..e6b2adc69 100644
--- a/vsoc_x86/pasan/aosp_cf.mk
+++ b/vsoc_x86/pasan/aosp_cf.mk
@@ -17,7 +17,7 @@
#
# All components inherited here go to system image (same as GSI system)
#
-$(call inherit-product, $(SRC_TARGET_DIR)/product/generic_system.mk)
+$(call inherit-product, $(SRC_TARGET_DIR)/product/mainline_system.mk)
PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS := relaxed
@@ -40,18 +40,11 @@ $(call inherit-product, device/google/cuttlefish/shared/phone/device_vendor.mk)
#
# Special settings for the target
#
-$(call inherit-product, device/google/cuttlefish/vsoc_x86_64/kernel.mk)
-$(call inherit-product, device/google/cuttlefish/vsoc_x86_64/bootloader.mk)
+DEVICE_PACKAGE_OVERLAYS += device/google/cuttlefish/vsoc_x86/phone/overlay
+
+$(call inherit-product, device/google/cuttlefish/vsoc_x86/device.mk)
-# Exclude features that are not available on AOSP devices.
-PRODUCT_COPY_FILES += \
- frameworks/native/data/etc/aosp_excluded_hardware.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/aosp_excluded_hardware.xml
PRODUCT_NAME := aosp_cf_x86_pasan
PRODUCT_DEVICE := vsoc_x86
-PRODUCT_MANUFACTURER := Google
PRODUCT_MODEL := Cuttlefish x86 phone
-
-PRODUCT_VENDOR_PROPERTIES += \
- ro.soc.manufacturer=$(PRODUCT_MANUFACTURER) \
- ro.soc.model=$(PRODUCT_DEVICE)
diff --git a/vsoc_x86/phone/aosp_cf.mk b/vsoc_x86/phone/aosp_cf.mk
index 3e6ec6b4c..2d75b0895 100644
--- a/vsoc_x86/phone/aosp_cf.mk
+++ b/vsoc_x86/phone/aosp_cf.mk
@@ -17,7 +17,7 @@
#
# All components inherited here go to system image (same as GSI system)
#
-$(call inherit-product, $(SRC_TARGET_DIR)/product/generic_system.mk)
+$(call inherit-product, $(SRC_TARGET_DIR)/product/mainline_system.mk)
PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS := relaxed
@@ -40,8 +40,9 @@ $(call inherit-product, device/google/cuttlefish/shared/phone/device_vendor.mk)
#
# Special settings for the target
#
-$(call inherit-product, device/google/cuttlefish/vsoc_x86_64/kernel.mk)
-$(call inherit-product, device/google/cuttlefish/vsoc_x86_64/bootloader.mk)
+DEVICE_PACKAGE_OVERLAYS += device/google/cuttlefish/vsoc_x86/phone/overlay
+
+$(call inherit-product, device/google/cuttlefish/vsoc_x86/device.mk)
# Exclude features that are not available on AOSP devices.
PRODUCT_COPY_FILES += \
@@ -49,9 +50,4 @@ PRODUCT_COPY_FILES += \
PRODUCT_NAME := aosp_cf_x86_phone
PRODUCT_DEVICE := vsoc_x86
-PRODUCT_MANUFACTURER := Google
PRODUCT_MODEL := Cuttlefish x86 phone
-
-PRODUCT_VENDOR_PROPERTIES += \
- ro.soc.manufacturer=$(PRODUCT_MANUFACTURER) \
- ro.soc.model=$(PRODUCT_DEVICE)
diff --git a/.clang-format b/vsoc_x86/phone/device.mk
index 9f9ffe36d..a3caa19ab 100644
--- a/.clang-format
+++ b/vsoc_x86/phone/device.mk
@@ -1,5 +1,5 @@
#
-# Copyright (C) 2020 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.
@@ -14,8 +14,10 @@
# limitations under the License.
#
-# See https://clang.llvm.org/docs/ClangFormatStyleOptions.html for the
-# various options that can be configured and for the definitions of each
-# of the below options.
+$(call inherit-product, device/google/cuttlefish/shared/phone/device.mk)
+$(call inherit-product, device/google/cuttlefish/vsoc_x86/device.mk)
-BasedOnStyle: Google
+PRODUCT_NAME := aosp_cf_x86_phone
+PRODUCT_DEVICE := vsoc_x86
+PRODUCT_MODEL := Cuttlefish x86 phone
+PRODUCT_PACKAGE_OVERLAYS := device/google/cuttlefish/vsoc_x86/phone/overlay
diff --git a/vsoc_x86/phone/overlay/frameworks/base/core/res/res/values/config.xml b/vsoc_x86/phone/overlay/frameworks/base/core/res/res/values/config.xml
new file mode 100644
index 000000000..5455fd4af
--- /dev/null
+++ b/vsoc_x86/phone/overlay/frameworks/base/core/res/res/values/config.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** 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.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="networkAttributes" translatable="false">
+ <item>"mobile,0,0,0,-1,true"</item>
+ <item>"wifi,1,1,1,-1,true"</item>
+ <item>"mobile_mms,2,0,2,60000,true"</item>
+ <item>"mobile_hipri,5,0,3,60000,true"</item>
+ <item>"bluetooth,7,7,2,-1,true"</item>
+ </string-array>
+ <string-array name="radioAttributes" translatable="false">
+ <item>"0,1"</item>
+ <item>"1,1"</item>
+ <item>"4,1"</item>
+ <item>"7,1"</item>
+ <item>"11,1"</item>
+ </string-array>
+ <string-array name="config_tether_wifi_regexs" translatable="false">
+ <item>"wlan0"</item>
+ </string-array>
+ <string-array name="config_tether_apndata" translatable="false">
+ <item>Android,android,,,,,,,,311,740,,default,dun,ims</item>
+ </string-array>
+ <bool name="config_bluetooth_address_validation" translatable="false">true</bool>
+ <bool name="config_sms_capable" translatable="false">true</bool>
+ <string name="default_sms_application" translatable="false">com.android.mms</string>
+ <bool name="config_showNavigationBar" translatable="false">true</bool>
+ <dimen name="config_viewConfigurationTouchSlop" translatable="false">12dp</dimen>
+ <integer name="config_mobile_mtu" translatable="false">1460</integer>
+ <!-- Maximum number of supported users -->
+ <integer name="config_multiuserMaximumUsers" translatable="false">4</integer>
+</resources>
diff --git a/vsoc_x86/tv/device.mk b/vsoc_x86/tv/device.mk
index b65f50c50..7689ee336 100644
--- a/vsoc_x86/tv/device.mk
+++ b/vsoc_x86/tv/device.mk
@@ -15,14 +15,9 @@
#
$(call inherit-product, device/google/cuttlefish/shared/tv/device.mk)
-$(call inherit-product, device/google/cuttlefish/vsoc_x86_64/kernel.mk)
-$(call inherit-product, device/google/cuttlefish/vsoc_x86_64/bootloader.mk)
+$(call inherit-product, device/google/cuttlefish/vsoc_x86/device.mk)
PRODUCT_NAME := aosp_cf_x86_tv
PRODUCT_DEVICE := vsoc_x86
-PRODUCT_MANUFACTURER := Google
PRODUCT_MODEL := Cuttlefish x86 tv
-
-PRODUCT_VENDOR_PROPERTIES += \
- ro.soc.manufacturer=$(PRODUCT_MANUFACTURER) \
- ro.soc.model=$(PRODUCT_DEVICE)
+# PRODUCT_PACKAGE_OVERLAYS := device/google/cuttlefish/vsoc_x86/tv/overlay
diff --git a/vsoc_x86_64/BoardConfig.mk b/vsoc_x86_64/BoardConfig.mk
index 52dde5c14..9c2cbfe79 100644
--- a/vsoc_x86_64/BoardConfig.mk
+++ b/vsoc_x86_64/BoardConfig.mk
@@ -41,7 +41,7 @@ TARGET_NATIVE_BRIDGE_2ND_CPU_VARIANT := generic
TARGET_NATIVE_BRIDGE_2ND_ABI := armeabi-v7a armeabi
BUILD_BROKEN_DUP_RULES := true
+BOARD_VENDOR_RAMDISK_KERNEL_MODULES += $(wildcard device/google/cuttlefish_kernel/5.4-x86_64/*.ko)
-ifeq ($(BOARD_VENDOR_RAMDISK_KERNEL_MODULES),)
- BOARD_VENDOR_RAMDISK_KERNEL_MODULES += $(wildcard kernel/prebuilts/common-modules/virtual-device/$(TARGET_KERNEL_USE)/x86-64/*.ko)
-endif
+# TODO(b/149410031): temporarily exclude sdcardfs
+BOARD_VENDOR_RAMDISK_KERNEL_MODULES := $(filter-out %/sdcardfs.ko,$(BOARD_VENDOR_RAMDISK_KERNEL_MODULES))
diff --git a/vsoc_x86_64/auto/OWNERS b/vsoc_x86_64/auto/OWNERS
deleted file mode 100644
index 1b990efbe..000000000
--- a/vsoc_x86_64/auto/OWNERS
+++ /dev/null
@@ -1,5 +0,0 @@
-# Android Auto leads
-ankitarora@google.com
-egranata@google.com
-gurunagarajan@google.com
-keunyoung@google.com
diff --git a/vsoc_x86_64/auto/device.mk b/vsoc_x86_64/auto/device.mk
deleted file mode 100644
index b21f694a2..000000000
--- a/vsoc_x86_64/auto/device.mk
+++ /dev/null
@@ -1,29 +0,0 @@
-#
-# Copyright (C) 2020 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.
-#
-
-$(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit_only.mk)
-$(call inherit-product, device/google/cuttlefish/shared/auto/device.mk)
-$(call inherit-product, device/google/cuttlefish/vsoc_x86_64/kernel.mk)
-$(call inherit-product, device/google/cuttlefish/vsoc_x86_64/bootloader.mk)
-
-PRODUCT_NAME := aosp_cf_x86_64_auto
-PRODUCT_DEVICE := vsoc_x86_64
-PRODUCT_MANUFACTURER := Google
-PRODUCT_MODEL := Cuttlefish x86_64 auto
-
-PRODUCT_VENDOR_PROPERTIES += \
- ro.soc.manufacturer=$(PRODUCT_MANUFACTURER) \
- ro.soc.model=$(PRODUCT_DEVICE)
diff --git a/vsoc_x86_64/bootloader.mk b/vsoc_x86_64/bootloader.mk
deleted file mode 100644
index b0d8c5d89..000000000
--- a/vsoc_x86_64/bootloader.mk
+++ /dev/null
@@ -1,21 +0,0 @@
-#
-# Copyright (C) 2020 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_NO_BOOTLOADER := false
-BOARD_PREBUILT_BOOTLOADER := \
- device/google/cuttlefish_prebuilts/bootloader/crosvm_x86_64/u-boot.rom
-PRODUCT_COPY_FILES += \
- device/google/cuttlefish_prebuilts/bootloader/qemu_x86_64/u-boot.rom:bootloader.qemu
diff --git a/vsoc_arm_only/kernel.mk b/vsoc_x86_64/device.mk
index 50b4e0b5b..de288f470 100644
--- a/vsoc_arm_only/kernel.mk
+++ b/vsoc_x86_64/device.mk
@@ -1,5 +1,5 @@
#
-# Copyright (C) 2020 The Android Open Source Project
+# 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.
@@ -13,4 +13,4 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-PRODUCT_COPY_FILES += device/google/cuttlefish_prebuilts/kernel/5.4-arm/kernel-5.4:kernel
+PRODUCT_COPY_FILES += device/google/cuttlefish_kernel/5.4-x86_64/kernel-5.4:kernel
diff --git a/vsoc_x86_64/pc/OWNERS b/vsoc_x86_64/pc/OWNERS
deleted file mode 100644
index 47eb80ec1..000000000
--- a/vsoc_x86_64/pc/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-# pc cuttlefish leads
-armenk@google.com
-xutan@google.com \ No newline at end of file
diff --git a/vsoc_x86_64/pc/aosp_cf.mk b/vsoc_x86_64/pc/aosp_cf.mk
deleted file mode 100644
index 1853785e6..000000000
--- a/vsoc_x86_64/pc/aosp_cf.mk
+++ /dev/null
@@ -1,52 +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.
-#
-
-#
-# All components inherited here go to system image (same as GSI system)
-#
-$(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit.mk)
-$(call inherit-product, $(SRC_TARGET_DIR)/product/generic_system.mk)
-
-#
-# All components inherited here go to system_ext image (same as GSI system_ext)a
-#
-$(call inherit-product, $(SRC_TARGET_DIR)/product/handheld_system_ext.mk)
-# $(call inherit-product, $(SRC_TARGET_DIR)/product/telephony_system_ext.mk)
-
-#
-# All components inherited here go to product image (same as GSI product)
-#
-$(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_product.mk)
-
-#
-# All components inherited here go to vendor image
-#
-$(call inherit-product, device/google/cuttlefish/shared/pc/device_vendor.mk)
-
-#
-# Special settings for the target
-#
-$(call inherit-product, device/google/cuttlefish/vsoc_x86_64/kernel.mk)
-$(call inherit-product, device/google/cuttlefish/vsoc_x86_64/bootloader.mk)
-
-PRODUCT_NAME := aosp_cf_x86_64_pc
-PRODUCT_DEVICE := vsoc_x86_64
-PRODUCT_MANUFACTURER := Google
-PRODUCT_MODEL := Cuttlefish x86_64 pc
-
-PRODUCT_VENDOR_PROPERTIES += \
- ro.soc.manufacturer=$(PRODUCT_MANUFACTURER) \
- ro.soc.model=$(PRODUCT_DEVICE)
diff --git a/vsoc_x86_64/phone/aosp_cf.mk b/vsoc_x86_64/phone/aosp_cf.mk
index 478452f25..791a7207a 100644
--- a/vsoc_x86_64/phone/aosp_cf.mk
+++ b/vsoc_x86_64/phone/aosp_cf.mk
@@ -18,7 +18,7 @@
# All components inherited here go to system image (same as GSI system)
#
$(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit.mk)
-$(call inherit-product, $(SRC_TARGET_DIR)/product/generic_system.mk)
+$(call inherit-product, $(SRC_TARGET_DIR)/product/mainline_system.mk)
PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS := relaxed
@@ -38,24 +38,14 @@ $(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_product.mk)
#
$(call inherit-product, device/google/cuttlefish/shared/phone/device_vendor.mk)
-# Nested virtualization support
-$(call inherit-product, packages/modules/Virtualization/apex/product_packages.mk)
-
#
# Special settings for the target
#
-$(call inherit-product, device/google/cuttlefish/vsoc_x86_64/kernel.mk)
-$(call inherit-product, device/google/cuttlefish/vsoc_x86_64/bootloader.mk)
+DEVICE_PACKAGE_OVERLAYS += device/google/cuttlefish/vsoc_x86_64/phone/overlay
+
+$(call inherit-product, device/google/cuttlefish/vsoc_x86_64/device.mk)
-# Exclude features that are not available on AOSP devices.
-PRODUCT_COPY_FILES += \
- frameworks/native/data/etc/aosp_excluded_hardware.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/aosp_excluded_hardware.xml
PRODUCT_NAME := aosp_cf_x86_64_phone
PRODUCT_DEVICE := vsoc_x86_64
-PRODUCT_MANUFACTURER := Google
PRODUCT_MODEL := Cuttlefish x86_64 phone
-
-PRODUCT_VENDOR_PROPERTIES += \
- ro.soc.manufacturer=$(PRODUCT_MANUFACTURER) \
- ro.soc.model=$(PRODUCT_DEVICE)
diff --git a/vsoc_x86_64/phone/aosp_cf_foldable.mk b/vsoc_x86_64/phone/aosp_cf_foldable.mk
deleted file mode 100644
index 89b0ea3d2..000000000
--- a/vsoc_x86_64/phone/aosp_cf_foldable.mk
+++ /dev/null
@@ -1,30 +0,0 @@
-#
-# Copyright (C) 2021 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.
-#
-
-# Inherit mostly from aosp_cf_x86_64_phone
-$(call inherit-product, device/google/cuttlefish/vsoc_x86_64/phone/aosp_cf.mk)
-PRODUCT_NAME := aosp_cf_x86_64_foldable
-PRODUCT_MODEL := Cuttlefish x86_64 foldable
-
-# Include the device state configuration for a foldable device.
-PRODUCT_COPY_FILES += \
- device/google/cuttlefish/shared/foldable/device_state_configuration.xml:$(TARGET_COPY_OUT_VENDOR)/etc/devicestate/device_state_configuration.xml
-# Include RRO settings that specify the fold states and screen information.
-DEVICE_PACKAGE_OVERLAYS += device/google/cuttlefish/shared/foldable/overlay
-# Include the foldable `launch_cvd --config foldable` option.
-SOONG_CONFIG_cvd_launch_configs += cvd_config_foldable.json
-# Include the android-info.txt that specifies the foldable --config by default.
-TARGET_BOARD_INFO_FILE := device/google/cuttlefish/shared/foldable/android-info.txt
diff --git a/vsoc_x86_64/phone/overlay/frameworks/base/core/res/res/values/config.xml b/vsoc_x86_64/phone/overlay/frameworks/base/core/res/res/values/config.xml
new file mode 100644
index 000000000..36184c845
--- /dev/null
+++ b/vsoc_x86_64/phone/overlay/frameworks/base/core/res/res/values/config.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2011, 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.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="networkAttributes" translatable="false">
+ <item>"mobile,0,0,0,-1,true"</item>
+ <item>"wifi,1,1,1,-1,true"</item>
+ <item>"mobile_mms,2,0,2,60000,true"</item>
+ <item>"mobile_hipri,5,0,3,60000,true"</item>
+ <item>"bluetooth,7,7,2,-1,true"</item>
+ </string-array>
+ <string-array name="radioAttributes" translatable="false">
+ <item>"0,1"</item>
+ <item>"1,1"</item>
+ <item>"4,1"</item>
+ <item>"7,1"</item>
+ <item>"11,1"</item>
+ </string-array>
+ <string-array name="config_tether_wifi_regexs" translatable="false">
+ <item>"wlan0"</item>
+ </string-array>
+ <string-array name="config_tether_apndata" translatable="false">
+ <item>Android,android,,,,,,,,302,780,,default,dun,ims</item>
+ </string-array>
+ <bool name="config_bluetooth_address_validation" translatable="false">true</bool>
+ <bool name="config_sms_capable" translatable="false">true</bool>
+ <string name="default_sms_application" translatable="false">com.android.mms</string>
+ <bool name="config_showNavigationBar" translatable="false">true</bool>
+ <dimen name="config_viewConfigurationTouchSlop" translatable="false">12dp</dimen>
+ <integer name="config_mobile_mtu" translatable="false">1460</integer>
+ <!-- Maximum number of supported users -->
+ <integer name="config_multiuserMaximumUsers" translatable="false">4</integer>
+</resources>
diff --git a/vsoc_x86_64/tv/device.mk b/vsoc_x86_64/tv/device.mk
deleted file mode 100644
index d25210dd7..000000000
--- a/vsoc_x86_64/tv/device.mk
+++ /dev/null
@@ -1,29 +0,0 @@
-#
-# Copyright (C) 2021 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.
-#
-
-$(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit.mk)
-$(call inherit-product, device/google/cuttlefish/shared/tv/device.mk)
-$(call inherit-product, device/google/cuttlefish/vsoc_x86_64/kernel.mk)
-$(call inherit-product, device/google/cuttlefish/vsoc_x86_64/bootloader.mk)
-
-PRODUCT_NAME := aosp_cf_x86_64_tv
-PRODUCT_DEVICE := vsoc_x86_64
-PRODUCT_MANUFACTURER := Google
-PRODUCT_MODEL := Cuttlefish x86_64 tv
-
-PRODUCT_VENDOR_PROPERTIES += \
- ro.soc.manufacturer=$(PRODUCT_MANUFACTURER) \
- ro.soc.model=$(PRODUCT_DEVICE)
diff --git a/vsoc_x86_64_only/BoardConfig.mk b/vsoc_x86_64_only/BoardConfig.mk
deleted file mode 100644
index d7025335d..000000000
--- a/vsoc_x86_64_only/BoardConfig.mk
+++ /dev/null
@@ -1,35 +0,0 @@
-#
-# 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.
-#
-
-#
-# x86_64 (64-bit only) target for Cuttlefish
-#
-
--include device/google/cuttlefish/shared/BoardConfig.mk
-
-TARGET_BOARD_PLATFORM := vsoc_x86_64
-TARGET_ARCH := x86_64
-TARGET_ARCH_VARIANT := silvermont
-TARGET_CPU_ABI := x86_64
-
-TARGET_NATIVE_BRIDGE_ARCH := arm64
-TARGET_NATIVE_BRIDGE_ARCH_VARIANT := armv8-a
-TARGET_NATIVE_BRIDGE_CPU_VARIANT := generic
-TARGET_NATIVE_BRIDGE_ABI := arm64-v8a
-
-AUDIOSERVER_MULTILIB := first
-BUILD_BROKEN_DUP_RULES := true
-BOARD_VENDOR_RAMDISK_KERNEL_MODULES += $(wildcard kernel/prebuilts/common-modules/virtual-device/5.10/x86-64/*.ko)
diff --git a/vsoc_x86_64_only/phone/aosp_cf.mk b/vsoc_x86_64_only/phone/aosp_cf.mk
deleted file mode 100644
index 0e8757d5f..000000000
--- a/vsoc_x86_64_only/phone/aosp_cf.mk
+++ /dev/null
@@ -1,62 +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.
-#
-
-#
-# All components inherited here go to system image (same as GSI system)
-#
-$(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit_only.mk)
-$(call inherit-product, $(SRC_TARGET_DIR)/product/generic_system.mk)
-
-PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS := relaxed
-
-#
-# All components inherited here go to system_ext image (same as GSI system_ext)
-#
-$(call inherit-product, $(SRC_TARGET_DIR)/product/handheld_system_ext.mk)
-$(call inherit-product, $(SRC_TARGET_DIR)/product/telephony_system_ext.mk)
-
-#
-# All components inherited here go to product image (same as GSI product)
-#
-$(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_product.mk)
-
-#
-# All components inherited here go to vendor image
-#
-LOCAL_DISABLE_OMX := true
-$(call inherit-product, device/google/cuttlefish/shared/phone/device_vendor.mk)
-
-# Nested virtualization support
-$(call inherit-product, packages/modules/Virtualization/apex/product_packages.mk)
-
-#
-# Special settings for the target
-#
-$(call inherit-product, device/google/cuttlefish/vsoc_x86_64/kernel.mk)
-$(call inherit-product, device/google/cuttlefish/vsoc_x86_64/bootloader.mk)
-
-# Exclude features that are not available on AOSP devices.
-PRODUCT_COPY_FILES += \
- frameworks/native/data/etc/aosp_excluded_hardware.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/aosp_excluded_hardware.xml
-
-PRODUCT_NAME := aosp_cf_x86_64_only_phone
-PRODUCT_DEVICE := vsoc_x86_64_only
-PRODUCT_MANUFACTURER := Google
-PRODUCT_MODEL := Cuttlefish x86_64 phone 64-bit only
-
-PRODUCT_VENDOR_PROPERTIES += \
- ro.soc.manufacturer=$(PRODUCT_MANUFACTURER) \
- ro.soc.model=$(PRODUCT_DEVICE)
diff --git a/vsoc_x86_noapex/aosp_cf_noapex.mk b/vsoc_x86_noapex/aosp_cf_noapex.mk
index aa5d3b217..fcf7607e9 100644
--- a/vsoc_x86_noapex/aosp_cf_noapex.mk
+++ b/vsoc_x86_noapex/aosp_cf_noapex.mk
@@ -17,15 +17,10 @@
# Order of this and the following statements is important.
# Putting this first in the list takes precedence over the one inherited from
# aosp_cf.
-OVERRIDE_TARGET_FLATTEN_APEX := true
+PRODUCT_PROPERTY_OVERRIDES += ro.apex.updatable=false
$(call inherit-product, device/google/cuttlefish/vsoc_x86/phone/aosp_cf.mk)
PRODUCT_NAME := aosp_cf_x86_phone_noapex
PRODUCT_DEVICE := vsoc_x86_noapex
-PRODUCT_MANUFACTURER := Google
PRODUCT_MODEL := Cuttlefish x86 phone without APEX support
-
-PRODUCT_VENDOR_PROPERTIES += \
- ro.soc.manufacturer=$(PRODUCT_MANUFACTURER) \
- ro.soc.model=$(PRODUCT_DEVICE)
diff --git a/vsoc_x86_only/kernel.mk b/vsoc_x86_only/kernel.mk
deleted file mode 100644
index 23cf08621..000000000
--- a/vsoc_x86_only/kernel.mk
+++ /dev/null
@@ -1,18 +0,0 @@
-#
-# Copyright (C) 2020 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_KERNEL_USE ?= 5.10
-
-PRODUCT_COPY_FILES += device/google/cuttlefish_prebuilts/kernel/$(TARGET_KERNEL_USE)-i686/kernel-$(TARGET_KERNEL_USE):kernel
diff --git a/vsoc_x86_only/phone/aosp_cf.mk b/vsoc_x86_only/phone/aosp_cf.mk
deleted file mode 100644
index 1aacd16d3..000000000
--- a/vsoc_x86_only/phone/aosp_cf.mk
+++ /dev/null
@@ -1,60 +0,0 @@
-#
-# Copyright (C) 2020 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.
-#
-
-#
-# All components inherited here go to system image (same as GSI system)
-#
-$(call inherit-product, $(SRC_TARGET_DIR)/product/generic_system.mk)
-
-PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS := relaxed
-
-#
-# All components inherited here go to system_ext image (same as GSI system_ext)
-#
-$(call inherit-product, $(SRC_TARGET_DIR)/product/handheld_system_ext.mk)
-$(call inherit-product, $(SRC_TARGET_DIR)/product/telephony_system_ext.mk)
-
-#
-# All components inherited here go to product image (same as GSI product)
-#
-$(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_product.mk)
-PRODUCT_OTA_ENFORCE_VINTF_KERNEL_REQUIREMENTS := false
-
-#
-# All components inherited here go to vendor image
-#
-$(call inherit-product, device/google/cuttlefish/shared/phone/device_vendor.mk)
-
-#
-# Special settings for the target
-#
-$(call inherit-product, device/google/cuttlefish/vsoc_x86_only/kernel.mk)
-# FIXME: For now, this uses the "64-bit" bootloader (for why, take a look at
-# http://u-boot.10912.n7.nabble.com/64-bit-x86-U-Boot-td244620.html)
-$(call inherit-product, device/google/cuttlefish/vsoc_x86_64/bootloader.mk)
-
-# Exclude features that are not available on AOSP devices.
-PRODUCT_COPY_FILES += \
- frameworks/native/data/etc/aosp_excluded_hardware.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/aosp_excluded_hardware.xml
-
-PRODUCT_NAME := aosp_cf_x86_only_phone
-PRODUCT_DEVICE := vsoc_x86_only
-PRODUCT_MANUFACTURER := Google
-PRODUCT_MODEL := Cuttlefish x86 phone 32-bit kernel
-
-PRODUCT_VENDOR_PROPERTIES += \
- ro.soc.manufacturer=$(PRODUCT_MANUFACTURER) \
- ro.soc.model=$(PRODUCT_DEVICE)